2015-11-15 22:41:24 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the Colobot: Gold Edition source code
|
2021-09-11 13:52:34 +00:00
|
|
|
* Copyright (C) 2001-2021, Daniel Roux, EPSITEC SA & TerranovaTeam
|
2015-11-15 22:41:24 +00:00
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2015-11-23 20:59:56 +00:00
|
|
|
#include "CBot/CBotCStack.h"
|
2015-11-15 22:41:24 +00:00
|
|
|
|
2017-11-15 21:21:01 +00:00
|
|
|
#include "CBot/CBotClass.h"
|
2015-11-23 20:59:56 +00:00
|
|
|
#include "CBot/CBotToken.h"
|
2015-12-26 13:19:24 +00:00
|
|
|
#include "CBot/CBotExternalCall.h"
|
2015-11-15 22:41:24 +00:00
|
|
|
|
2015-11-23 20:59:56 +00:00
|
|
|
#include "CBot/CBotVar/CBotVar.h"
|
2015-11-15 22:41:24 +00:00
|
|
|
|
2015-11-23 20:59:56 +00:00
|
|
|
#include "CBot/CBotInstr/CBotFunction.h"
|
2015-11-15 22:41:24 +00:00
|
|
|
|
2015-12-26 13:19:24 +00:00
|
|
|
namespace CBot
|
|
|
|
{
|
2015-11-15 22:41:24 +00:00
|
|
|
|
2021-06-12 02:47:33 +00:00
|
|
|
struct CBotCStack::Data
|
|
|
|
{
|
|
|
|
//! The program currently being compiled
|
|
|
|
CBotProgram* prog = nullptr;
|
|
|
|
//! The current error state of the compile stack
|
|
|
|
CBotError error = CBotNoErr;
|
|
|
|
int errEnd = 0;
|
|
|
|
//! The return type of the function currently being compiled
|
|
|
|
CBotTypResult retTyp = CBotTypResult(CBotTypVoid);
|
|
|
|
};
|
2015-11-15 22:41:24 +00:00
|
|
|
|
|
|
|
CBotCStack::CBotCStack(CBotCStack* ppapa)
|
|
|
|
{
|
|
|
|
m_prev = ppapa;
|
|
|
|
|
|
|
|
if (ppapa == nullptr)
|
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
m_data = new CBotCStack::Data;
|
|
|
|
m_errStart = 0;
|
2015-11-15 22:41:24 +00:00
|
|
|
m_bBlock = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
m_data = ppapa->m_data;
|
|
|
|
m_errStart = ppapa->m_errStart;
|
2015-11-15 22:41:24 +00:00
|
|
|
m_bBlock = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CBotCStack::~CBotCStack()
|
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
if (m_prev == nullptr) delete m_data;
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CBotCStack* CBotCStack::TokenStack(CBotToken* pToken, bool bBlock)
|
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
if (m_next) return m_next.get(); // include on an existing stack
|
2015-11-15 22:41:24 +00:00
|
|
|
|
2021-06-12 02:47:33 +00:00
|
|
|
m_next.reset(new CBotCStack(this));
|
|
|
|
m_next->m_bBlock = bBlock;
|
2015-11-15 22:41:24 +00:00
|
|
|
|
2021-06-12 02:47:33 +00:00
|
|
|
if (pToken != nullptr) m_next->SetStartError(pToken->GetStart());
|
2015-11-15 22:41:24 +00:00
|
|
|
|
2021-06-12 02:47:33 +00:00
|
|
|
return m_next.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CBotCStack::DeleteNext()
|
|
|
|
{
|
|
|
|
m_next.reset();
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CBotInstr* CBotCStack::Return(CBotInstr* inst, CBotCStack* pfils)
|
|
|
|
{
|
|
|
|
if ( pfils == this ) return inst;
|
|
|
|
|
2021-06-12 02:47:33 +00:00
|
|
|
m_var = std::move(pfils->m_var); // result transmitted
|
2015-11-15 22:41:24 +00:00
|
|
|
|
2021-06-12 02:47:33 +00:00
|
|
|
if (m_data->error != CBotNoErr)
|
2015-11-15 22:41:24 +00:00
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
m_errStart = pfils->m_errStart; // retrieves the position of the error
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
|
2021-06-12 02:47:33 +00:00
|
|
|
m_next.reset();
|
2015-11-15 22:41:24 +00:00
|
|
|
return inst;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CBotFunction* CBotCStack::ReturnFunc(CBotFunction* inst, CBotCStack* pfils)
|
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
m_var = std::move(pfils->m_var); // result transmitted
|
2015-11-15 22:41:24 +00:00
|
|
|
|
2021-06-12 02:47:33 +00:00
|
|
|
if (m_data->error != CBotNoErr)
|
2015-11-15 22:41:24 +00:00
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
m_errStart = pfils->m_errStart; // retrieves the position of the error
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
|
2021-06-12 02:47:33 +00:00
|
|
|
m_next.reset();
|
2015-11-15 22:41:24 +00:00
|
|
|
return inst;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-20 18:16:01 +00:00
|
|
|
CBotError CBotCStack::GetError(int& start, int& end)
|
2015-11-15 22:41:24 +00:00
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
start = m_errStart;
|
|
|
|
end = m_data->errEnd;
|
|
|
|
return m_data->error;
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-20 18:16:01 +00:00
|
|
|
CBotError CBotCStack::GetError()
|
2015-11-15 22:41:24 +00:00
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
return m_data->error;
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-25 18:16:54 +00:00
|
|
|
CBotTypResult CBotCStack::GetTypResult(CBotVar::GetTypeMode mode)
|
2015-11-15 22:41:24 +00:00
|
|
|
{
|
|
|
|
if (m_var == nullptr)
|
|
|
|
return CBotTypResult(99);
|
|
|
|
return m_var->GetTypResult(mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-25 18:16:54 +00:00
|
|
|
int CBotCStack::GetType(CBotVar::GetTypeMode mode)
|
2015-11-15 22:41:24 +00:00
|
|
|
{
|
|
|
|
if (m_var == nullptr)
|
|
|
|
return 99;
|
|
|
|
return m_var->GetType(mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CBotClass* CBotCStack::GetClass()
|
|
|
|
{
|
|
|
|
if ( m_var == nullptr )
|
|
|
|
return nullptr;
|
2015-12-25 18:16:54 +00:00
|
|
|
if ( m_var->GetType(CBotVar::GetTypeMode::CLASS_AS_POINTER) != CBotTypPointer ) return nullptr;
|
2015-11-15 22:41:24 +00:00
|
|
|
|
|
|
|
return m_var->GetClass();
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CBotCStack::SetType(CBotTypResult& type)
|
|
|
|
{
|
|
|
|
if (m_var == nullptr) return;
|
|
|
|
m_var->SetType( type );
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CBotVar* CBotCStack::FindVar(CBotToken* &pToken)
|
|
|
|
{
|
|
|
|
CBotCStack* p = this;
|
2021-06-12 02:47:33 +00:00
|
|
|
const auto& name = pToken->GetString();
|
2015-11-15 22:41:24 +00:00
|
|
|
|
|
|
|
while (p != nullptr)
|
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
if (p->m_bBlock) for (auto& var : p->m_listVar)
|
2015-11-15 22:41:24 +00:00
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
if (name == var->GetName()) return var.get();
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
p = p->m_prev;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CBotVar* CBotCStack::FindVar(CBotToken& Token)
|
|
|
|
{
|
|
|
|
CBotToken* pt = &Token;
|
|
|
|
return FindVar(pt);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CBotVar* CBotCStack::CopyVar(CBotToken& Token)
|
|
|
|
{
|
|
|
|
CBotVar* pVar = FindVar( Token );
|
|
|
|
|
|
|
|
if ( pVar == nullptr) return nullptr;
|
|
|
|
|
|
|
|
CBotVar* pCopy = CBotVar::Create( "", pVar->GetType() );
|
|
|
|
pCopy->Copy(pVar);
|
|
|
|
return pCopy;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool CBotCStack::IsOk()
|
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
return (m_data->error == CBotNoErr);
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CBotCStack::SetStartError( int pos )
|
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
if (m_data->error != CBotNoErr) return; // does not change existing error
|
|
|
|
m_errStart = pos;
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-20 18:16:01 +00:00
|
|
|
void CBotCStack::SetError(CBotError n, int pos)
|
2015-11-15 22:41:24 +00:00
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
if (n != CBotNoErr && m_data->error != CBotNoErr) return; // does not change existing error
|
|
|
|
m_data->error = n;
|
|
|
|
m_data->errEnd = pos;
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-20 18:16:01 +00:00
|
|
|
void CBotCStack::SetError(CBotError n, CBotToken* p)
|
2015-11-15 22:41:24 +00:00
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
if (m_data->error != CBotNoErr) return; // does not change existing error
|
|
|
|
m_data->error = n;
|
|
|
|
m_errStart = p->GetStart();
|
|
|
|
m_data->errEnd = p->GetEnd();
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-20 18:16:01 +00:00
|
|
|
void CBotCStack::ResetError(CBotError n, int start, int end)
|
2015-11-15 22:41:24 +00:00
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
m_data->error = n;
|
|
|
|
m_errStart = start;
|
|
|
|
m_data->errEnd = end;
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool CBotCStack::NextToken(CBotToken* &p)
|
|
|
|
{
|
|
|
|
CBotToken* pp = p;
|
|
|
|
|
|
|
|
p = p->GetNext();
|
|
|
|
if (p!=nullptr) return true;
|
|
|
|
|
2015-12-20 18:01:03 +00:00
|
|
|
SetError(CBotErrNoTerminator, pp->GetEnd());
|
2015-11-15 22:41:24 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-23 15:46:41 +00:00
|
|
|
void CBotCStack::SetProgram(CBotProgram* p)
|
2015-11-15 22:41:24 +00:00
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
m_data->prog = p;
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-23 15:46:41 +00:00
|
|
|
CBotProgram* CBotCStack::GetProgram()
|
2015-11-15 22:41:24 +00:00
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
return m_data->prog;
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CBotCStack::SetRetType(CBotTypResult& type)
|
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
m_data->retTyp = type;
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CBotTypResult CBotCStack::GetRetType()
|
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
return m_data->retTyp;
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CBotCStack::SetVar( CBotVar* var )
|
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
m_var.reset(var);
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CBotCStack::SetCopyVar( CBotVar* var )
|
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
m_var.reset();
|
2015-11-15 22:41:24 +00:00
|
|
|
|
|
|
|
if ( var == nullptr ) return;
|
2021-06-12 02:47:33 +00:00
|
|
|
m_var.reset(CBotVar::Create("", var->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC)));
|
2015-11-15 22:41:24 +00:00
|
|
|
m_var->Copy( var );
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CBotVar* CBotCStack::GetVar()
|
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
return m_var.get();
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CBotCStack::AddVar(CBotVar* pVar)
|
|
|
|
{
|
|
|
|
CBotCStack* p = this;
|
|
|
|
|
2021-06-12 02:47:33 +00:00
|
|
|
// find the level of the current block
|
2015-11-15 22:41:24 +00:00
|
|
|
while (p != nullptr && p->m_bBlock == 0) p = p->m_prev;
|
|
|
|
|
2021-06-12 02:47:33 +00:00
|
|
|
if (p == nullptr || pVar == nullptr) return;
|
2015-11-15 22:41:24 +00:00
|
|
|
|
2021-06-12 02:47:33 +00:00
|
|
|
p->m_listVar.emplace_back(pVar);
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
|
2017-11-15 21:21:01 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CBotCStack::CreateVarThis(CBotClass* pClass)
|
|
|
|
{
|
|
|
|
if ( pClass == nullptr ) return;
|
|
|
|
|
|
|
|
CBotVar* pThis = CBotVar::Create("this", CBotTypResult(CBotTypClass, pClass));
|
|
|
|
|
|
|
|
pThis->SetUniqNum(-2); // special ID for "this"
|
|
|
|
AddVar(pThis);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CBotCStack::CreateVarSuper(CBotClass* pClass)
|
|
|
|
{
|
|
|
|
if ( pClass == nullptr ) return;
|
|
|
|
|
|
|
|
CBotVar* pSuper = CBotVar::Create("super", CBotTypResult(CBotTypClass, pClass));
|
|
|
|
|
|
|
|
pSuper->SetUniqNum(-3); // special ID for "super"
|
|
|
|
AddVar(pSuper);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CBotCStack::CreateMemberVars(CBotClass* pClass, bool setDefined)
|
|
|
|
{
|
|
|
|
while (pClass != nullptr)
|
|
|
|
{
|
|
|
|
CBotVar* pv = pClass->GetVar();
|
|
|
|
while (pv != nullptr)
|
|
|
|
{
|
|
|
|
CBotVar* pcopy = CBotVar::Create(pv);
|
|
|
|
CBotVar::InitType initType = CBotVar::InitType::UNDEF;
|
|
|
|
if (setDefined || pv->IsStatic())
|
|
|
|
initType = CBotVar::InitType::DEF;
|
|
|
|
pcopy->SetInit(initType);
|
|
|
|
pcopy->SetUniqNum(pv->GetUniqNum());
|
|
|
|
pcopy->SetPrivate(pv->GetPrivate());
|
|
|
|
AddVar(pcopy);
|
|
|
|
pv = pv->GetNext();
|
|
|
|
}
|
|
|
|
pClass = pClass->GetParent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-15 22:41:24 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool CBotCStack::CheckVarLocal(CBotToken* &pToken)
|
|
|
|
{
|
|
|
|
CBotCStack* p = this;
|
2021-06-12 02:47:33 +00:00
|
|
|
const auto& name = pToken->GetString();
|
2015-11-15 22:41:24 +00:00
|
|
|
|
2021-06-12 02:47:33 +00:00
|
|
|
// find the level of the current block
|
|
|
|
while (p != nullptr && p->m_bBlock == 0) p = p->m_prev;
|
|
|
|
|
|
|
|
if (p != nullptr) for (auto& var : p->m_listVar)
|
2015-11-15 22:41:24 +00:00
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
if (name == var->GetName()) return true;
|
2015-11-15 22:41:24 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CBotTypResult CBotCStack::CompileCall(CBotToken* &p, CBotVar** ppVars, long& nIdent)
|
|
|
|
{
|
|
|
|
nIdent = 0;
|
|
|
|
CBotTypResult val(-1);
|
|
|
|
|
2021-06-12 02:47:33 +00:00
|
|
|
val = GetProgram()->GetExternalCalls()->CompileCall(p, nullptr, ppVars, this);
|
2015-11-15 22:41:24 +00:00
|
|
|
if (val.GetType() < 0)
|
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
val = CBotFunction::CompileCall(p->GetString(), ppVars, nIdent, GetProgram());
|
2015-11-15 22:41:24 +00:00
|
|
|
if ( val.GetType() < 0 )
|
|
|
|
{
|
|
|
|
// pVar = nullptr; // the error is not on a particular parameter
|
2015-12-20 18:16:01 +00:00
|
|
|
SetError( static_cast<CBotError>(-val.GetType()), p );
|
2015-11-15 22:41:24 +00:00
|
|
|
val.SetType(-val.GetType());
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2017-11-15 21:21:01 +00:00
|
|
|
bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam, const std::string& className)
|
2015-11-15 22:41:24 +00:00
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
const auto& name = pToken->GetString();
|
2015-11-15 22:41:24 +00:00
|
|
|
|
2021-06-12 02:47:33 +00:00
|
|
|
if ( GetProgram()->GetExternalCalls()->CheckCall(name) ) return true;
|
2015-11-15 22:41:24 +00:00
|
|
|
|
2021-06-12 02:47:33 +00:00
|
|
|
for (CBotFunction* pp : GetProgram()->GetFunctions())
|
2015-11-15 22:41:24 +00:00
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
if ( name == pp->GetName() )
|
2015-11-15 22:41:24 +00:00
|
|
|
{
|
2017-11-15 21:21:01 +00:00
|
|
|
// ignore methods for a different class
|
|
|
|
if ( className != pp->GetClassName() )
|
|
|
|
continue;
|
2015-11-15 22:41:24 +00:00
|
|
|
// are parameters exactly the same?
|
|
|
|
if ( pp->CheckParam( pParam ) )
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-24 14:07:40 +00:00
|
|
|
for (CBotFunction* pp : CBotFunction::m_publicFunctions)
|
2015-11-15 22:41:24 +00:00
|
|
|
{
|
2021-06-12 02:47:33 +00:00
|
|
|
if ( name == pp->GetName() )
|
2015-11-15 22:41:24 +00:00
|
|
|
{
|
2017-11-15 21:21:01 +00:00
|
|
|
// ignore methods for a different class
|
|
|
|
if ( className != pp->GetClassName() )
|
|
|
|
continue;
|
2015-11-15 22:41:24 +00:00
|
|
|
// are parameters exactly the same?
|
|
|
|
if ( pp->CheckParam( pParam ) )
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
2015-12-26 13:19:24 +00:00
|
|
|
|
2021-06-12 02:47:33 +00:00
|
|
|
} // namespace CBot
|