2014-10-14 13:11:37 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the Colobot: Gold Edition source code
|
2016-02-13 13:11:30 +00:00
|
|
|
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
2015-08-22 14:40:02 +00:00
|
|
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
2014-10-14 13:11:37 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2015-11-23 20:59:56 +00:00
|
|
|
#include "CBot/CBotClass.h"
|
|
|
|
|
|
|
|
#include "CBot/CBotInstr/CBotNew.h"
|
|
|
|
#include "CBot/CBotInstr/CBotLeftExprVar.h"
|
|
|
|
#include "CBot/CBotInstr/CBotTwoOpExpr.h"
|
|
|
|
#include "CBot/CBotInstr/CBotFunction.h"
|
|
|
|
#include "CBot/CBotInstr/CBotExpression.h"
|
|
|
|
#include "CBot/CBotInstr/CBotListArray.h"
|
|
|
|
#include "CBot/CBotInstr/CBotEmpty.h"
|
|
|
|
|
2015-12-31 15:11:19 +00:00
|
|
|
#include "CBot/CBotVar/CBotVar.h"
|
|
|
|
|
2015-12-31 13:44:19 +00:00
|
|
|
#include "CBot/CBotExternalCall.h"
|
2015-11-23 20:59:56 +00:00
|
|
|
#include "CBot/CBotStack.h"
|
|
|
|
#include "CBot/CBotCStack.h"
|
|
|
|
#include "CBot/CBotUtils.h"
|
|
|
|
#include "CBot/CBotFileUtils.h"
|
|
|
|
#include "CBot/CBotCallMethode.h"
|
|
|
|
|
2015-12-31 15:11:19 +00:00
|
|
|
#include <algorithm>
|
2015-11-15 22:18:47 +00:00
|
|
|
|
2015-12-26 13:19:24 +00:00
|
|
|
namespace CBot
|
|
|
|
{
|
2015-11-15 16:37:53 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-31 15:30:54 +00:00
|
|
|
std::set<CBotClass*> CBotClass::m_publicClasses{};
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-20 15:19:10 +00:00
|
|
|
CBotClass::CBotClass(const std::string& name,
|
2015-12-31 15:30:54 +00:00
|
|
|
CBotClass* parent,
|
2015-11-15 16:37:53 +00:00
|
|
|
bool bIntrinsic)
|
2012-08-07 13:46:04 +00:00
|
|
|
{
|
2015-12-31 15:54:13 +00:00
|
|
|
m_parent = parent;
|
2012-08-08 20:35:17 +00:00
|
|
|
m_name = name;
|
2015-08-16 10:43:42 +00:00
|
|
|
m_pVar = nullptr;
|
|
|
|
m_pCalls = nullptr;
|
|
|
|
m_pMethod = nullptr;
|
2015-12-31 15:54:13 +00:00
|
|
|
m_rUpdate = nullptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
m_IsDef = true;
|
|
|
|
m_bIntrinsic= bIntrinsic;
|
2015-12-31 15:54:13 +00:00
|
|
|
m_nbVar = m_parent == nullptr ? 0 : m_parent->m_nbVar;
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2015-12-31 15:30:54 +00:00
|
|
|
m_publicClasses.insert(this);
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-07 13:46:04 +00:00
|
|
|
CBotClass::~CBotClass()
|
|
|
|
{
|
2015-12-31 15:30:54 +00:00
|
|
|
m_publicClasses.erase(this);
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
delete m_pVar;
|
|
|
|
delete m_pCalls;
|
|
|
|
delete m_pMethod;
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-20 15:19:10 +00:00
|
|
|
CBotClass* CBotClass::Create(const std::string& name,
|
2015-11-15 16:37:53 +00:00
|
|
|
CBotClass* parent,
|
|
|
|
bool intrinsic)
|
2015-10-03 20:05:14 +00:00
|
|
|
{
|
|
|
|
return new CBotClass(name, parent, intrinsic);
|
|
|
|
}
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-31 15:30:54 +00:00
|
|
|
void CBotClass::ClearPublic()
|
2012-08-07 13:46:04 +00:00
|
|
|
{
|
2015-12-31 15:30:54 +00:00
|
|
|
m_publicClasses.clear();
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-07 13:46:04 +00:00
|
|
|
void CBotClass::Purge()
|
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( this == nullptr ) return;
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
delete m_pVar;
|
2015-08-16 10:43:42 +00:00
|
|
|
m_pVar = nullptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
delete m_pCalls;
|
2015-08-16 10:43:42 +00:00
|
|
|
m_pCalls = nullptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
delete m_pMethod;
|
2015-08-16 10:43:42 +00:00
|
|
|
m_pMethod = nullptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
m_IsDef = false;
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2015-12-31 15:54:13 +00:00
|
|
|
m_nbVar = m_parent == nullptr ? 0 : m_parent->m_nbVar;
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
m_next->Purge();
|
2015-08-16 10:43:42 +00:00
|
|
|
m_next = nullptr; // no longer belongs to this chain
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-31 15:11:19 +00:00
|
|
|
bool CBotClass::Lock(CBotProgram* prog)
|
2012-08-07 13:46:04 +00:00
|
|
|
{
|
2015-12-31 15:11:19 +00:00
|
|
|
if (m_lockProg.size() == 0)
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
2015-12-31 15:11:19 +00:00
|
|
|
m_lockCurrentCount = 1;
|
|
|
|
m_lockProg.push_back(prog);
|
2012-08-08 20:35:17 +00:00
|
|
|
return true;
|
|
|
|
}
|
2015-12-31 15:11:19 +00:00
|
|
|
if (prog == m_lockProg[0])
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
2015-12-31 15:11:19 +00:00
|
|
|
m_lockCurrentCount++;
|
2012-08-08 20:35:17 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-12-31 15:11:19 +00:00
|
|
|
if (std::find(m_lockProg.begin(), m_lockProg.end(), prog) != m_lockProg.end())
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
2015-12-31 15:11:19 +00:00
|
|
|
return false; // already pending
|
2012-08-08 20:35:17 +00:00
|
|
|
}
|
|
|
|
|
2015-12-31 15:11:19 +00:00
|
|
|
m_lockProg.push_back(prog);
|
2012-08-08 20:35:17 +00:00
|
|
|
|
|
|
|
return false;
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-07 13:46:04 +00:00
|
|
|
void CBotClass::Unlock()
|
|
|
|
{
|
2015-12-31 15:11:19 +00:00
|
|
|
if (--m_lockCurrentCount > 0) return; // if called Lock() multiple times, wait for all to unlock
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2015-12-31 15:11:19 +00:00
|
|
|
m_lockProg.pop_front();
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-31 15:11:19 +00:00
|
|
|
void CBotClass::FreeLock(CBotProgram* prog)
|
2012-08-07 13:46:04 +00:00
|
|
|
{
|
2015-12-31 15:30:54 +00:00
|
|
|
for (CBotClass* pClass : m_publicClasses)
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
2015-12-31 15:11:19 +00:00
|
|
|
if (pClass->m_lockProg.size() > 0 && prog == pClass->m_lockProg[0])
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
2015-12-31 15:11:19 +00:00
|
|
|
pClass->m_lockCurrentCount = 0;
|
2012-08-08 20:35:17 +00:00
|
|
|
}
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2016-01-23 20:33:58 +00:00
|
|
|
// Note: erasing an end iterator is undefined behaviour
|
|
|
|
auto it = std::remove(pClass->m_lockProg.begin(), pClass->m_lockProg.end(), prog);
|
|
|
|
if (it != pClass->m_lockProg.end())
|
|
|
|
{
|
|
|
|
pClass->m_lockProg.erase(it);
|
|
|
|
}
|
2012-08-08 20:35:17 +00:00
|
|
|
}
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-20 15:19:10 +00:00
|
|
|
bool CBotClass::AddItem(std::string name,
|
2015-11-15 16:37:53 +00:00
|
|
|
CBotTypResult type,
|
2015-12-21 22:07:40 +00:00
|
|
|
CBotVar::ProtectionLevel mPrivate)
|
2012-08-07 13:46:04 +00:00
|
|
|
{
|
2012-08-11 18:59:35 +00:00
|
|
|
CBotClass* pClass = type.GetClass();
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
CBotVar* pVar = CBotVar::Create( name, type );
|
|
|
|
/// pVar->SetUniqNum(CBotVar::NextUniqNum());
|
|
|
|
pVar->SetPrivate( mPrivate );
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( pClass != nullptr )
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
|
|
|
// pVar->SetClass(pClass);
|
|
|
|
if ( type.Eq(CBotTypClass) )
|
|
|
|
{
|
|
|
|
// adds a new statement for the object initialization
|
|
|
|
pVar->m_InitExpr = new CBotNew() ;
|
2012-08-11 18:59:35 +00:00
|
|
|
CBotToken nom( pClass->GetName() );
|
2012-08-08 20:35:17 +00:00
|
|
|
pVar->m_InitExpr->SetToken(&nom);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return AddItem( pVar );
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-07 13:46:04 +00:00
|
|
|
bool CBotClass::AddItem(CBotVar* pVar)
|
|
|
|
{
|
2012-08-08 20:35:17 +00:00
|
|
|
pVar->SetUniqNum(++m_nbVar);
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( m_pVar == nullptr ) m_pVar = pVar;
|
2012-08-08 20:35:17 +00:00
|
|
|
else m_pVar->AddNext(pVar);
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
return true;
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-20 15:19:10 +00:00
|
|
|
std::string CBotClass::GetName()
|
2012-08-07 13:46:04 +00:00
|
|
|
{
|
2012-08-08 20:35:17 +00:00
|
|
|
return m_name;
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-11 18:59:35 +00:00
|
|
|
CBotClass* CBotClass::GetParent()
|
2012-08-07 13:46:04 +00:00
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( this == nullptr ) return nullptr;
|
2015-12-31 15:54:13 +00:00
|
|
|
return m_parent;
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-07 13:46:04 +00:00
|
|
|
bool CBotClass::IsChildOf(CBotClass* pClass)
|
|
|
|
{
|
2012-08-08 20:35:17 +00:00
|
|
|
CBotClass* p = this;
|
2015-08-16 10:43:42 +00:00
|
|
|
while ( p != nullptr )
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
|
|
|
if ( p == pClass ) return true;
|
2015-12-31 15:54:13 +00:00
|
|
|
p = p->m_parent;
|
2012-08-08 20:35:17 +00:00
|
|
|
}
|
|
|
|
return false;
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-11 18:59:35 +00:00
|
|
|
CBotVar* CBotClass::GetVar()
|
2012-08-07 13:46:04 +00:00
|
|
|
{
|
2012-08-08 20:35:17 +00:00
|
|
|
return m_pVar;
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-20 15:19:10 +00:00
|
|
|
CBotVar* CBotClass::GetItem(const std::string& name)
|
2012-08-07 13:46:04 +00:00
|
|
|
{
|
2012-08-08 20:35:17 +00:00
|
|
|
CBotVar* p = m_pVar;
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
while ( p != nullptr )
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
2012-08-11 18:59:35 +00:00
|
|
|
if ( p->GetName() == name ) return p;
|
|
|
|
p = p->GetNext();
|
2012-08-08 20:35:17 +00:00
|
|
|
}
|
2015-12-31 15:54:13 +00:00
|
|
|
if (m_parent != nullptr ) return m_parent->GetItem(name);
|
2015-08-16 10:43:42 +00:00
|
|
|
return nullptr;
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-11 18:59:35 +00:00
|
|
|
CBotVar* CBotClass::GetItemRef(int nIdent)
|
2012-08-07 13:46:04 +00:00
|
|
|
{
|
2012-08-08 20:35:17 +00:00
|
|
|
CBotVar* p = m_pVar;
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
while ( p != nullptr )
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
2012-08-11 18:59:35 +00:00
|
|
|
if ( p->GetUniqNum() == nIdent ) return p;
|
|
|
|
p = p->GetNext();
|
2012-08-08 20:35:17 +00:00
|
|
|
}
|
2015-12-31 15:54:13 +00:00
|
|
|
if (m_parent != nullptr ) return m_parent->GetItemRef(nIdent);
|
2015-08-16 10:43:42 +00:00
|
|
|
return nullptr;
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-07 13:46:04 +00:00
|
|
|
bool CBotClass::IsIntrinsic()
|
|
|
|
{
|
2012-08-08 20:35:17 +00:00
|
|
|
return m_bIntrinsic;
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-07 13:46:04 +00:00
|
|
|
CBotClass* CBotClass::Find(CBotToken* &pToken)
|
|
|
|
{
|
2012-08-11 18:59:35 +00:00
|
|
|
return Find(pToken->GetString());
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-20 15:19:10 +00:00
|
|
|
CBotClass* CBotClass::Find(const std::string& name)
|
2012-08-07 13:46:04 +00:00
|
|
|
{
|
2015-12-31 15:30:54 +00:00
|
|
|
for (CBotClass* p : m_publicClasses)
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
2012-08-11 18:59:35 +00:00
|
|
|
if ( p->GetName() == name ) return p;
|
2012-08-08 20:35:17 +00:00
|
|
|
}
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
return nullptr;
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-20 15:19:10 +00:00
|
|
|
bool CBotClass::AddFunction(const std::string& name,
|
|
|
|
bool rExec(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user),
|
|
|
|
CBotTypResult rCompile(CBotVar* pThis, CBotVar*& pVar))
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
|
|
|
// stores pointers to the two functions
|
|
|
|
CBotCallMethode* p = m_pCalls;
|
2015-08-16 10:43:42 +00:00
|
|
|
CBotCallMethode* pp = nullptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
while ( p != nullptr )
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
2015-12-24 10:57:34 +00:00
|
|
|
if ( name == p->m_name )
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( pp == nullptr ) m_pCalls = p->m_next;
|
2012-08-08 20:35:17 +00:00
|
|
|
else pp->m_next = p->m_next;
|
|
|
|
delete p;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
pp = p;
|
|
|
|
p = p->m_next;
|
|
|
|
}
|
|
|
|
|
|
|
|
p = new CBotCallMethode(name, rExec, rCompile);
|
2013-05-26 15:47:54 +00:00
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
if (m_pCalls == nullptr) m_pCalls = p;
|
2012-08-08 20:35:17 +00:00
|
|
|
else m_pCalls->AddNext(p); // added to the list
|
|
|
|
|
|
|
|
return true;
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-31 15:54:13 +00:00
|
|
|
bool CBotClass::SetUpdateFunc(void rUpdate(CBotVar* thisVar, void* user))
|
2012-08-07 13:46:04 +00:00
|
|
|
{
|
2015-12-31 15:54:13 +00:00
|
|
|
m_rUpdate = rUpdate;
|
2012-08-08 20:35:17 +00:00
|
|
|
return true;
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-20 15:19:10 +00:00
|
|
|
CBotTypResult CBotClass::CompileMethode(const std::string& name,
|
2015-11-15 16:37:53 +00:00
|
|
|
CBotVar* pThis,
|
|
|
|
CBotVar** ppParams,
|
|
|
|
CBotCStack* pStack,
|
|
|
|
long& nIdent)
|
2012-08-07 13:46:04 +00:00
|
|
|
{
|
2012-08-08 20:35:17 +00:00
|
|
|
nIdent = 0; // forget the previous one if necessary
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
// find the methods declared by AddFunction
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2015-12-24 10:57:34 +00:00
|
|
|
CBotTypResult r = m_pCalls->CompileCall(name, pThis, ppParams, pStack);
|
2012-08-11 18:59:35 +00:00
|
|
|
if ( r.GetType() >= 0) return r;
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
// find the methods declared by user
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
r = m_pMethod->CompileCall(name, ppParams, nIdent);
|
2015-12-31 15:54:13 +00:00
|
|
|
if ( r.Eq(CBotErrUndefCall) && m_parent != nullptr )
|
|
|
|
return m_parent->m_pMethod->CompileCall(name, ppParams, nIdent);
|
2012-08-08 20:35:17 +00:00
|
|
|
return r;
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool CBotClass::ExecuteMethode(long& nIdent,
|
2015-12-20 15:19:10 +00:00
|
|
|
const std::string& name,
|
2015-11-15 16:37:53 +00:00
|
|
|
CBotVar* pThis,
|
|
|
|
CBotVar** ppParams,
|
2015-12-20 15:19:10 +00:00
|
|
|
CBotVar*& pResult,
|
|
|
|
CBotStack*& pStack,
|
2012-08-08 20:35:17 +00:00
|
|
|
CBotToken* pToken)
|
2012-08-07 13:46:04 +00:00
|
|
|
{
|
2015-12-24 10:57:34 +00:00
|
|
|
int ret = m_pCalls->DoCall(name, pThis, ppParams, pResult, pStack, pToken);
|
2012-08-08 20:35:17 +00:00
|
|
|
if (ret>=0) return ret;
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
ret = m_pMethod->DoCall(nIdent, name, pThis, ppParams, pStack, pToken, this);
|
2015-11-21 12:27:40 +00:00
|
|
|
if (ret >= 0) return ret;
|
|
|
|
|
2015-12-31 15:54:13 +00:00
|
|
|
if (m_parent != nullptr)
|
2015-11-21 12:27:40 +00:00
|
|
|
{
|
2015-12-31 15:54:13 +00:00
|
|
|
ret = m_parent->m_pCalls->DoCall(name, pThis, ppParams, pResult, pStack, pToken);
|
2015-11-21 12:27:40 +00:00
|
|
|
if (ret >= 0) return ret;
|
2015-12-31 15:54:13 +00:00
|
|
|
ret = m_parent->m_pMethod->DoCall(nIdent, name, pThis, ppParams, pStack, pToken, m_parent);
|
2015-11-21 12:27:40 +00:00
|
|
|
}
|
2012-08-08 20:35:17 +00:00
|
|
|
return ret;
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CBotClass::RestoreMethode(long& nIdent,
|
2015-12-20 15:19:10 +00:00
|
|
|
const std::string& name,
|
2015-11-15 16:37:53 +00:00
|
|
|
CBotVar* pThis,
|
|
|
|
CBotVar** ppParams,
|
2015-12-20 15:19:10 +00:00
|
|
|
CBotStack*& pStack)
|
2012-08-07 13:46:04 +00:00
|
|
|
{
|
2012-08-08 20:35:17 +00:00
|
|
|
m_pMethod->RestoreCall(nIdent, name, pThis, ppParams, pStack, this);
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-07 13:46:04 +00:00
|
|
|
bool CBotClass::SaveStaticState(FILE* pf)
|
|
|
|
{
|
2012-08-08 20:35:17 +00:00
|
|
|
if (!WriteWord( pf, CBOTVERSION*2)) return false;
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
// saves the state of static variables in classes
|
2015-12-31 15:30:54 +00:00
|
|
|
for (CBotClass* p : m_publicClasses)
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
2015-12-31 15:30:54 +00:00
|
|
|
if (!WriteWord( pf, 1 )) return false;
|
2012-08-08 20:35:17 +00:00
|
|
|
// save the name of the class
|
2012-08-11 18:59:35 +00:00
|
|
|
if (!WriteString( pf, p->GetName() )) return false;
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2012-08-11 18:59:35 +00:00
|
|
|
CBotVar* pv = p->GetVar();
|
2015-08-16 10:43:42 +00:00
|
|
|
while( pv != nullptr )
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
|
|
|
if ( pv->IsStatic() )
|
|
|
|
{
|
2015-12-31 15:30:54 +00:00
|
|
|
if (!WriteWord( pf, 1 )) return false;
|
2012-08-11 18:59:35 +00:00
|
|
|
if (!WriteString( pf, pv->GetName() )) return false;
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2015-12-31 15:30:54 +00:00
|
|
|
if ( !pv->Save0State(pf) ) return false; // common header
|
2012-08-08 20:35:17 +00:00
|
|
|
if ( !pv->Save1State(pf) ) return false; // saves as the child class
|
2015-12-31 15:30:54 +00:00
|
|
|
if ( !WriteWord( pf, 0 ) ) return false;
|
2012-08-08 20:35:17 +00:00
|
|
|
}
|
2012-08-11 18:59:35 +00:00
|
|
|
pv = pv->GetNext();
|
2012-08-08 20:35:17 +00:00
|
|
|
}
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2015-12-31 15:30:54 +00:00
|
|
|
if (!WriteWord( pf, 0 )) return false;
|
2012-08-08 20:35:17 +00:00
|
|
|
}
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2015-12-31 15:30:54 +00:00
|
|
|
if (!WriteWord( pf, 0 )) return false;
|
2012-08-08 20:35:17 +00:00
|
|
|
return true;
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2012-08-07 13:46:04 +00:00
|
|
|
bool CBotClass::RestoreStaticState(FILE* pf)
|
|
|
|
{
|
2015-12-20 15:19:10 +00:00
|
|
|
std::string ClassName, VarName;
|
2012-08-08 20:35:17 +00:00
|
|
|
CBotClass* pClass;
|
|
|
|
unsigned short w;
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
if (!ReadWord( pf, w )) return false;
|
|
|
|
if ( w != CBOTVERSION*2 ) return false;
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (!ReadWord( pf, w )) return false;
|
|
|
|
if ( w == 0 ) return true;
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
if (!ReadString( pf, ClassName )) return false;
|
|
|
|
pClass = Find(ClassName);
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
if (!ReadWord( pf, w )) return false;
|
|
|
|
if ( w == 0 ) break;
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
CBotVar* pVar = nullptr;
|
|
|
|
CBotVar* pv = nullptr;
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
if (!ReadString( pf, VarName )) return false;
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( pClass != nullptr ) pVar = pClass->GetItem(VarName);
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2013-05-26 15:47:54 +00:00
|
|
|
if (!CBotVar::RestoreState(pf, pv)) return false; // the temp variable
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
if ( pVar != nullptr ) pVar->Copy(pv);
|
2012-08-08 20:35:17 +00:00
|
|
|
delete pv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
|
|
|
|
2015-11-15 16:37:53 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2015-12-24 11:36:09 +00:00
|
|
|
bool CBotClass::CheckCall(CBotProgram* program, CBotDefParam* pParam, CBotToken*& pToken)
|
2012-08-07 13:46:04 +00:00
|
|
|
{
|
2015-12-20 15:19:10 +00:00
|
|
|
std::string name = pToken->GetString();
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2015-12-24 11:36:09 +00:00
|
|
|
if ( program->GetExternalCalls()->CheckCall(name) ) return true;
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
CBotFunction* pp = m_pMethod;
|
2015-08-16 10:43:42 +00:00
|
|
|
while ( pp != nullptr )
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
2012-08-11 18:59:35 +00:00
|
|
|
if ( pToken->GetString() == pp->GetName() )
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
|
|
|
// are their parameters exactly the same?
|
|
|
|
if ( pp->CheckParam( pParam ) )
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
pp = pp->Next();
|
|
|
|
}
|
2012-08-07 13:46:04 +00:00
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
return false;
|
2012-08-07 13:46:04 +00:00
|
|
|
}
|
2015-11-15 17:40:16 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CBotClass* CBotClass::Compile1(CBotToken* &p, CBotCStack* pStack)
|
|
|
|
{
|
|
|
|
if ( !IsOfType(p, ID_PUBLIC) )
|
|
|
|
{
|
2015-12-20 18:01:03 +00:00
|
|
|
pStack->SetError(CBotErrNoPublic, p);
|
2015-11-15 17:40:16 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !IsOfType(p, ID_CLASS) ) return nullptr;
|
|
|
|
|
2015-12-20 15:19:10 +00:00
|
|
|
std::string name = p->GetString();
|
2015-11-15 17:40:16 +00:00
|
|
|
|
|
|
|
CBotClass* pOld = CBotClass::Find(name);
|
|
|
|
if ( pOld != nullptr && pOld->m_IsDef )
|
|
|
|
{
|
2015-12-20 18:01:03 +00:00
|
|
|
pStack->SetError( CBotErrRedefClass, p );
|
2015-11-15 17:40:16 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// a name of the class is there?
|
|
|
|
if (IsOfType(p, TokenTypVar))
|
|
|
|
{
|
|
|
|
CBotClass* pPapa = nullptr;
|
|
|
|
if ( IsOfType( p, ID_EXTENDS ) )
|
|
|
|
{
|
2015-12-20 15:19:10 +00:00
|
|
|
std::string name = p->GetString();
|
2015-11-15 17:40:16 +00:00
|
|
|
pPapa = CBotClass::Find(name);
|
|
|
|
|
|
|
|
if (!IsOfType(p, TokenTypVar) || pPapa == nullptr )
|
|
|
|
{
|
2015-12-20 18:01:03 +00:00
|
|
|
pStack->SetError( CBotErrNotClass, p );
|
2015-11-15 17:40:16 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
CBotClass* classe = (pOld == nullptr) ? new CBotClass(name, pPapa) : pOld;
|
2015-12-31 15:54:13 +00:00
|
|
|
classe->Purge(); // empty the old definitions // TODO: Doesn't this remove all classes of the current program?
|
2015-11-15 17:40:16 +00:00
|
|
|
classe->m_IsDef = false; // current definition
|
|
|
|
|
|
|
|
if ( !IsOfType( p, ID_OPBLK) )
|
|
|
|
{
|
2015-12-20 18:01:03 +00:00
|
|
|
pStack->SetError(CBotErrOpenBlock, p);
|
2015-11-15 17:40:16 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
while ( pStack->IsOk() && !IsOfType( p, ID_CLBLK ) )
|
|
|
|
{
|
|
|
|
classe->CompileDefItem(p, pStack, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pStack->IsOk()) return classe;
|
|
|
|
}
|
2015-12-20 18:01:03 +00:00
|
|
|
pStack->SetError(CBotErrNoTerminator, p);
|
2015-11-15 17:40:16 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
|
|
|
{
|
|
|
|
bool bStatic = false;
|
2015-12-21 22:07:40 +00:00
|
|
|
CBotVar::ProtectionLevel mProtect = CBotVar::ProtectionLevel::Public;
|
2015-11-15 17:40:16 +00:00
|
|
|
bool bSynchro = false;
|
|
|
|
|
|
|
|
while (IsOfType(p, ID_SEP)) ;
|
|
|
|
|
|
|
|
CBotTypResult type( -1 );
|
|
|
|
|
|
|
|
if ( IsOfType(p, ID_SYNCHO) ) bSynchro = true;
|
|
|
|
CBotToken* pBase = p;
|
|
|
|
|
|
|
|
if ( IsOfType(p, ID_STATIC) ) bStatic = true;
|
2015-12-21 22:07:40 +00:00
|
|
|
if ( IsOfType(p, ID_PUBLIC) ) mProtect = CBotVar::ProtectionLevel::Public;
|
|
|
|
if ( IsOfType(p, ID_PRIVATE) ) mProtect = CBotVar::ProtectionLevel::Private;
|
|
|
|
if ( IsOfType(p, ID_PROTECTED) ) mProtect = CBotVar::ProtectionLevel::Protected;
|
2015-11-15 17:40:16 +00:00
|
|
|
if ( IsOfType(p, ID_STATIC) ) bStatic = true;
|
|
|
|
|
|
|
|
// CBotClass* pClass = nullptr;
|
|
|
|
type = TypeParam(p, pStack); // type of the result
|
|
|
|
|
|
|
|
if ( type.Eq(-1) )
|
|
|
|
{
|
2015-12-20 18:01:03 +00:00
|
|
|
pStack->SetError(CBotErrNoType, p);
|
2015-11-15 17:40:16 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (pStack->IsOk())
|
|
|
|
{
|
2015-12-23 11:47:37 +00:00
|
|
|
std::string pp = p->GetString();
|
|
|
|
if ( IsOfType(p, ID_NOT) )
|
|
|
|
{
|
|
|
|
pp = std::string("~") + p->GetString();
|
|
|
|
}
|
2015-11-15 17:40:16 +00:00
|
|
|
|
|
|
|
if (IsOfType(p, TokenTypVar))
|
|
|
|
{
|
|
|
|
CBotInstr* limites = nullptr;
|
|
|
|
while ( IsOfType( p, ID_OPBRK ) ) // a table?
|
|
|
|
{
|
|
|
|
CBotInstr* i = nullptr;
|
|
|
|
|
|
|
|
if ( p->GetType() != ID_CLBRK )
|
|
|
|
i = CBotExpression::Compile( p, pStack ); // expression for the value
|
|
|
|
else
|
|
|
|
i = new CBotEmpty(); // special if not a formula
|
|
|
|
|
|
|
|
type = CBotTypResult(CBotTypArrayPointer, type);
|
|
|
|
|
|
|
|
if (!pStack->IsOk() || !IsOfType( p, ID_CLBRK ) )
|
|
|
|
{
|
2015-12-20 18:01:03 +00:00
|
|
|
pStack->SetError(CBotErrCloseIndex, p->GetStart());
|
2015-11-15 17:40:16 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* CBotVar* pv = pStack->GetVar();
|
|
|
|
if ( pv->GetType()>= CBotTypBoolean )
|
|
|
|
{
|
2015-12-20 18:01:03 +00:00
|
|
|
pStack->SetError(CBotErrBadType1, p->GetStart());
|
2015-11-15 17:40:16 +00:00
|
|
|
return false;
|
|
|
|
}*/
|
|
|
|
|
|
|
|
if (limites == nullptr) limites = i;
|
|
|
|
else limites->AddNext3(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( p->GetType() == ID_OPENPAR )
|
|
|
|
{
|
|
|
|
if ( !bSecond )
|
|
|
|
{
|
|
|
|
p = pBase;
|
|
|
|
CBotFunction* f =
|
|
|
|
CBotFunction::Compile1(p, pStack, this);
|
|
|
|
|
|
|
|
if ( f == nullptr ) return false;
|
|
|
|
|
|
|
|
if (m_pMethod == nullptr) m_pMethod = f;
|
|
|
|
else m_pMethod->AddNext(f);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// return a method precompiled in pass 1
|
|
|
|
CBotFunction* pf = m_pMethod;
|
|
|
|
CBotFunction* prev = nullptr;
|
|
|
|
while ( pf != nullptr )
|
|
|
|
{
|
2015-12-23 11:47:37 +00:00
|
|
|
if (pf->GetName() == pp) break;
|
2015-11-15 17:40:16 +00:00
|
|
|
prev = pf;
|
|
|
|
pf = pf->Next();
|
|
|
|
}
|
|
|
|
|
2015-12-23 11:47:37 +00:00
|
|
|
bool bConstructor = (pp == GetName());
|
2015-11-15 17:40:16 +00:00
|
|
|
CBotCStack* pile = pStack->TokenStack(nullptr, true);
|
|
|
|
|
|
|
|
// make "this" known
|
2015-12-20 15:19:10 +00:00
|
|
|
CBotToken TokenThis(std::string("this"), std::string());
|
2015-12-23 16:50:10 +00:00
|
|
|
CBotVar* pThis = CBotVar::Create(TokenThis, CBotTypResult( CBotTypClass, this ) );
|
2015-11-15 17:40:16 +00:00
|
|
|
pThis->SetUniqNum(-2);
|
|
|
|
pile->AddVar(pThis);
|
|
|
|
|
2015-12-31 15:54:13 +00:00
|
|
|
if (m_parent)
|
2015-11-15 17:40:16 +00:00
|
|
|
{
|
|
|
|
// makes "super" known
|
2015-12-20 15:19:10 +00:00
|
|
|
CBotToken TokenSuper(std::string("super"), std::string());
|
2015-12-31 15:54:13 +00:00
|
|
|
CBotVar* pThis = CBotVar::Create(TokenSuper, CBotTypResult(CBotTypClass, m_parent) );
|
2015-11-15 17:40:16 +00:00
|
|
|
pThis->SetUniqNum(-3);
|
|
|
|
pile->AddVar(pThis);
|
|
|
|
}
|
|
|
|
|
|
|
|
// int num = 1;
|
|
|
|
CBotClass* my = this;
|
|
|
|
while (my != nullptr)
|
|
|
|
{
|
|
|
|
// places a copy of variables of a class (this) on a stack
|
|
|
|
CBotVar* pv = my->m_pVar;
|
|
|
|
while (pv != nullptr)
|
|
|
|
{
|
|
|
|
CBotVar* pcopy = CBotVar::Create(pv);
|
|
|
|
CBotVar::InitType initType = CBotVar::InitType::UNDEF;
|
|
|
|
if (!bConstructor || pv->IsStatic())
|
|
|
|
initType = CBotVar::InitType::DEF;
|
|
|
|
pcopy->SetInit(initType);
|
|
|
|
pcopy->SetUniqNum(pv->GetUniqNum());
|
|
|
|
pile->AddVar(pcopy);
|
|
|
|
pv = pv->GetNext();
|
|
|
|
}
|
2015-12-31 15:54:13 +00:00
|
|
|
my = my->m_parent;
|
2015-11-15 17:40:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// compiles a method
|
|
|
|
p = pBase;
|
|
|
|
CBotFunction* f =
|
|
|
|
CBotFunction::Compile(p, pile, nullptr/*, false*/);
|
|
|
|
|
|
|
|
if ( f != nullptr )
|
|
|
|
{
|
2015-12-23 15:46:41 +00:00
|
|
|
f->m_pProg = pStack->GetProgram();
|
2015-11-15 17:40:16 +00:00
|
|
|
f->m_bSynchro = bSynchro;
|
|
|
|
// replaces the element in the chain
|
|
|
|
f->m_next = pf->m_next;
|
|
|
|
pf->m_next = nullptr;
|
|
|
|
delete pf;
|
|
|
|
if (prev == nullptr) m_pMethod = f;
|
|
|
|
else prev->m_next = f;
|
|
|
|
}
|
|
|
|
pStack->Return(nullptr, pile);
|
|
|
|
}
|
|
|
|
|
|
|
|
return pStack->IsOk();
|
|
|
|
}
|
|
|
|
|
|
|
|
// definition of an element
|
|
|
|
if (type.Eq(0))
|
|
|
|
{
|
2015-12-20 18:01:03 +00:00
|
|
|
pStack->SetError(CBotErrNoTerminator, p);
|
2015-11-15 17:40:16 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
CBotInstr* i = nullptr;
|
|
|
|
if ( IsOfType(p, ID_ASS ) )
|
|
|
|
{
|
|
|
|
if ( type.Eq(CBotTypArrayPointer) )
|
|
|
|
{
|
|
|
|
i = CBotListArray::Compile(p, pStack, type.GetTypElem());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// it has an assignmet to calculate
|
|
|
|
i = CBotTwoOpExpr::Compile(p, pStack);
|
|
|
|
}
|
|
|
|
if ( !pStack->IsOk() ) return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( !bSecond )
|
|
|
|
{
|
2015-12-23 11:47:37 +00:00
|
|
|
CBotVar* pv = CBotVar::Create(pp, type);
|
2015-11-15 17:40:16 +00:00
|
|
|
pv -> SetStatic( bStatic );
|
|
|
|
pv -> SetPrivate( mProtect );
|
|
|
|
|
|
|
|
AddItem( pv );
|
|
|
|
|
|
|
|
pv->m_InitExpr = i;
|
|
|
|
pv->m_LimExpr = limites;
|
|
|
|
|
|
|
|
|
|
|
|
if ( pv->IsStatic() && pv->m_InitExpr != nullptr )
|
|
|
|
{
|
2015-12-24 13:39:38 +00:00
|
|
|
CBotStack* pile = CBotStack::AllocateStack(); // independent stack
|
2015-11-15 17:40:16 +00:00
|
|
|
while(pile->IsOk() && !pv->m_InitExpr->Execute(pile)); // evaluates the expression without timer
|
|
|
|
pv->SetVal( pile->GetVar() ) ;
|
|
|
|
pile->Delete();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
delete i;
|
|
|
|
|
|
|
|
if ( IsOfType(p, ID_COMMA) ) continue;
|
|
|
|
if ( IsOfType(p, ID_SEP) ) break;
|
|
|
|
}
|
2015-12-20 18:01:03 +00:00
|
|
|
pStack->SetError(CBotErrNoTerminator, p);
|
2015-11-15 17:40:16 +00:00
|
|
|
}
|
|
|
|
return pStack->IsOk();
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CBotClass* CBotClass::Compile(CBotToken* &p, CBotCStack* pStack)
|
|
|
|
{
|
|
|
|
if ( !IsOfType(p, ID_PUBLIC) ) return nullptr;
|
|
|
|
if ( !IsOfType(p, ID_CLASS) ) return nullptr;
|
|
|
|
|
2015-12-20 15:19:10 +00:00
|
|
|
std::string name = p->GetString();
|
2015-11-15 17:40:16 +00:00
|
|
|
|
|
|
|
// a name for the class is there?
|
|
|
|
if (IsOfType(p, TokenTypVar))
|
|
|
|
{
|
|
|
|
// the class was created by Compile1
|
|
|
|
CBotClass* pOld = CBotClass::Find(name);
|
|
|
|
|
|
|
|
if ( IsOfType( p, ID_EXTENDS ) )
|
|
|
|
{
|
|
|
|
// TODO: Not sure how correct is that - I have no idea how the precompilation (Compile1 method) works ~krzys_h
|
2015-12-20 15:19:10 +00:00
|
|
|
std::string name = p->GetString();
|
2015-11-15 17:40:16 +00:00
|
|
|
CBotClass* pPapa = CBotClass::Find(name);
|
|
|
|
|
|
|
|
if (!IsOfType(p, TokenTypVar) || pPapa == nullptr)
|
|
|
|
{
|
2015-12-20 18:01:03 +00:00
|
|
|
pStack->SetError( CBotErrNotClass, p );
|
2015-11-15 17:40:16 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
2015-12-31 15:54:13 +00:00
|
|
|
pOld->m_parent = pPapa;
|
2015-11-15 17:40:16 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (pOld != nullptr)
|
|
|
|
{
|
2015-12-31 15:54:13 +00:00
|
|
|
pOld->m_parent = nullptr;
|
2015-11-15 17:40:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
IsOfType( p, ID_OPBLK); // necessarily
|
|
|
|
|
|
|
|
while ( pStack->IsOk() && !IsOfType( p, ID_CLBLK ) )
|
|
|
|
{
|
|
|
|
pOld->CompileDefItem(p, pStack, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
pOld->m_IsDef = true; // complete definition
|
|
|
|
if (pStack->IsOk()) return pOld;
|
|
|
|
}
|
2015-12-20 18:01:03 +00:00
|
|
|
pStack->SetError(CBotErrNoTerminator, p);
|
2015-11-15 17:40:16 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
2015-12-26 13:19:24 +00:00
|
|
|
|
2015-12-31 15:54:13 +00:00
|
|
|
void CBotClass::Update(CBotVar* var, void* user)
|
|
|
|
{
|
|
|
|
m_rUpdate(var, user);
|
|
|
|
}
|
|
|
|
|
2015-12-26 13:19:24 +00:00
|
|
|
} // namespace CBot
|