colobot/src/CBot/CBotClass.cpp

885 lines
24 KiB
C++
Raw Normal View History

/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsiteс.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
*/
2012-08-07 13:46:04 +00:00
/////////////////////////////////////////////////////////////////////
// Management of variables of class type
//
#include "CBot.h"
CBotClass* CBotClass::m_ExClass = NULL;
CBotClass::CBotClass(const char* name, CBotClass* pPapa, bool bIntrinsic)
{
2012-08-08 20:35:17 +00:00
m_pParent = pPapa;
m_name = name;
m_pVar = NULL;
m_next = NULL;
m_pCalls = NULL;
m_pMethod = NULL;
m_rMaj = NULL;
m_IsDef = true;
m_bIntrinsic= bIntrinsic;
m_cptLock = 0;
m_cptOne = 0;
m_nbVar = m_pParent == NULL ? 0 : m_pParent->m_nbVar;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
for ( int j= 0; j< 5 ; j++ )
{
m_ProgInLock[j] = NULL;
}
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
// is located alone in the list
if (m_ExClass) m_ExClass->m_ExPrev = this;
m_ExNext = m_ExClass;
m_ExPrev = NULL;
m_ExClass = this;
2012-08-07 13:46:04 +00:00
}
CBotClass::~CBotClass()
{
// removes the list of class
2012-08-08 20:35:17 +00:00
if ( m_ExPrev ) m_ExPrev->m_ExNext = m_ExNext;
else m_ExClass = m_ExNext;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
if ( m_ExNext ) m_ExNext->m_ExPrev = m_ExPrev;
m_ExPrev = NULL;
m_ExNext = NULL;
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
2012-08-08 20:35:17 +00:00
delete m_next; // releases all of them on this level
2012-08-07 13:46:04 +00:00
}
void CBotClass::Free()
{
2012-08-08 20:35:17 +00:00
while ( m_ExClass != NULL )
{
delete m_ExClass;
}
2012-08-07 13:46:04 +00:00
}
void CBotClass::Purge()
{
2012-08-08 20:35:17 +00:00
if ( this == NULL ) return;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
delete m_pVar;
m_pVar = NULL;
delete m_pCalls;
m_pCalls = NULL;
delete m_pMethod;
m_pMethod = NULL;
m_IsDef = false;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
m_nbVar = m_pParent == NULL ? 0 : m_pParent->m_nbVar;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
m_next->Purge();
m_next = NULL; // no longer belongs to this chain
2012-08-07 13:46:04 +00:00
}
bool CBotClass::Lock(CBotProgram* p)
{
2012-08-08 20:35:17 +00:00
int i = m_cptLock++;
if ( i == 0 )
{
m_cptOne = 1;
m_ProgInLock[0] = p;
return true;
}
if ( p == m_ProgInLock[0] )
2012-08-08 20:35:17 +00:00
{
m_cptOne++;
m_cptLock--; // has already been counted
return true;
}
for ( int j = 1 ; j <= i ; j++)
{
if ( p == m_ProgInLock[j] )
{
m_cptLock--;
return false; // already pending
}
}
if ( i < 5 ) // max 5 in query
{
m_ProgInLock[i] = p; // located in a queue
}
else
m_cptLock--;
return false;
2012-08-07 13:46:04 +00:00
}
void CBotClass::Unlock()
{
2012-08-08 20:35:17 +00:00
if ( --m_cptOne > 0 ) return ;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
int i = --m_cptLock;
if ( i<0 )
{
m_cptLock = 0;
return;
}
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
for ( int j= 0; j< i ; j++ )
{
m_ProgInLock[j] = m_ProgInLock[j+1];
}
m_ProgInLock[i] = 0;
2012-08-07 13:46:04 +00:00
}
void CBotClass::FreeLock(CBotProgram* p)
{
2012-08-08 20:35:17 +00:00
CBotClass* pClass = m_ExClass;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
while ( pClass != NULL )
{
if ( p == pClass->m_ProgInLock[0] )
2012-08-08 20:35:17 +00:00
{
pClass->m_cptLock -= pClass->m_cptOne;
pClass->m_cptOne = 0;
}
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
for ( int j = 1; j < 5 ; j++ )
if ( p == pClass->m_ProgInLock[j] )
2012-08-08 20:35:17 +00:00
pClass->m_cptLock--;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
pClass = pClass->m_ExNext;
}
2012-08-07 13:46:04 +00:00
}
bool CBotClass::AddItem(CBotString name, CBotTypResult type, int mPrivate)
{
2012-08-08 20:35:17 +00:00
CBotToken token(name, CBotString());
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
2012-08-08 20:35:17 +00:00
if ( pClass != NULL )
{
// 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
}
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
2012-08-08 20:35:17 +00:00
if ( m_pVar == NULL ) m_pVar = pVar;
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
}
void CBotClass::AddNext(CBotClass* pClass)
{
2012-08-08 20:35:17 +00:00
CBotClass* p = this;
while (p->m_next != NULL) p = p->m_next;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
p->m_next = pClass;
2012-08-07 13:46:04 +00:00
}
2012-08-11 18:59:35 +00:00
CBotString 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
}
2012-08-11 18:59:35 +00:00
CBotClass* CBotClass::GetParent()
2012-08-07 13:46:04 +00:00
{
2012-08-08 20:35:17 +00:00
if ( this == NULL ) return NULL;
return m_pParent;
2012-08-07 13:46:04 +00:00
}
bool CBotClass::IsChildOf(CBotClass* pClass)
{
2012-08-08 20:35:17 +00:00
CBotClass* p = this;
while ( p != NULL )
{
if ( p == pClass ) return true;
p = p->m_pParent;
}
return false;
2012-08-07 13:46:04 +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
}
2012-08-11 18:59:35 +00:00
CBotVar* CBotClass::GetItem(const char* 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
2012-08-08 20:35:17 +00:00
while ( p != NULL )
{
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
}
2012-08-11 18:59:35 +00:00
if ( m_pParent != NULL ) return m_pParent->GetItem(name);
2012-08-08 20:35:17 +00:00
return NULL;
2012-08-07 13:46:04 +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
2012-08-08 20:35:17 +00:00
while ( p != NULL )
{
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
}
2012-08-11 18:59:35 +00:00
if ( m_pParent != NULL ) return m_pParent->GetItemRef(nIdent);
2012-08-08 20:35:17 +00:00
return NULL;
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
}
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
}
CBotClass* CBotClass::Find(const char* name)
{
2012-08-08 20:35:17 +00:00
CBotClass* p = m_ExClass;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
while ( p != NULL )
{
2012-08-11 18:59:35 +00:00
if ( p->GetName() == name ) return p;
2012-08-08 20:35:17 +00:00
p = p->m_ExNext;
}
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
return NULL;
2012-08-07 13:46:04 +00:00
}
bool CBotClass::AddFunction(const char* name,
bool rExec (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user),
2012-08-08 20:35:17 +00:00
CBotTypResult rCompile (CBotVar* pThis, CBotVar* &pVar))
{
// stores pointers to the two functions
CBotCallMethode* p = m_pCalls;
CBotCallMethode* pp = NULL;
while ( p != NULL )
{
2012-08-11 18:59:35 +00:00
if ( name == p->GetName() )
2012-08-08 20:35:17 +00:00
{
if ( pp == NULL ) m_pCalls = p->m_next;
else pp->m_next = p->m_next;
delete p;
break;
}
pp = p;
p = p->m_next;
}
p = new CBotCallMethode(name, rExec, rCompile);
2012-08-08 20:35:17 +00:00
if (m_pCalls == NULL) m_pCalls = p;
else m_pCalls->AddNext(p); // added to the list
return true;
2012-08-07 13:46:04 +00:00
}
bool CBotClass::AddUpdateFunc( void rMaj ( CBotVar* pThis, void* pUser ) )
{
2012-08-08 20:35:17 +00:00
m_rMaj = rMaj;
return true;
2012-08-07 13:46:04 +00:00
}
// compiles a method associated with an instance of class
// the method can be declared by the user or AddFunction
CBotTypResult CBotClass::CompileMethode(const char* name,
CBotVar* pThis, CBotVar** ppParams,
2012-08-08 20:35:17 +00:00
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
2012-08-08 20:35:17 +00:00
CBotTypResult r = m_pCalls->CompileCall(name, pThis, ppParams, pStack, nIdent);
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);
if ( r.Eq(TX_UNDEFCALL) && m_pParent != NULL )
return m_pParent->m_pMethod->CompileCall(name, ppParams, nIdent);
return r;
2012-08-07 13:46:04 +00:00
}
// executes a method
bool CBotClass::ExecuteMethode(long& nIdent, const char* name,
CBotVar* pThis, CBotVar** ppParams,
2012-08-08 20:35:17 +00:00
CBotVar* &pResult, CBotStack* &pStack,
CBotToken* pToken)
2012-08-07 13:46:04 +00:00
{
2012-08-08 20:35:17 +00:00
int ret = m_pCalls->DoCall(nIdent, name, pThis, ppParams, pResult, pStack, pToken);
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);
return ret;
2012-08-07 13:46:04 +00:00
}
// restored the execution stack
void CBotClass::RestoreMethode(long& nIdent, const char* name, CBotVar* pThis,
2012-08-08 20:35:17 +00:00
CBotVar** ppParams, 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
}
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
CBotClass* p = m_ExClass;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
while ( p != NULL )
{
if (!WriteWord( pf, 1)) return false;
// 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();
2012-08-08 20:35:17 +00:00
while( pv != NULL )
{
if ( pv->IsStatic() )
{
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
2012-08-08 20:35:17 +00:00
if ( !pv->Save0State(pf)) return false; // common header
if ( !pv->Save1State(pf) ) return false; // saves as the child class
if ( !WriteWord( pf, 0)) return false;
}
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
2012-08-08 20:35:17 +00:00
if (!WriteWord( pf, 0)) return false;
p = p->m_ExNext;
}
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
if (!WriteWord( pf, 0)) return false;
return true;
2012-08-07 13:46:04 +00:00
}
bool CBotClass::RestoreStaticState(FILE* pf)
{
2012-08-08 20:35:17 +00:00
CBotString ClassName, VarName;
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
2012-08-08 20:35:17 +00:00
CBotVar* pVar = NULL;
CBotVar* pv = NULL;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
if (!ReadString( pf, VarName )) return false;
2012-08-11 18:59:35 +00:00
if ( pClass != NULL ) pVar = pClass->GetItem(VarName);
2012-08-07 13:46:04 +00:00
if (!CBotVar::RestoreState(pf, pv)) return false; // the temp variable
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
if ( pVar != NULL ) pVar->Copy(pv);
delete pv;
}
}
return true;
2012-08-07 13:46:04 +00:00
}
/////////////////////////////////////////////////////////////////////
CBotClassInst::CBotClassInst()
{
2012-08-08 20:35:17 +00:00
m_next = NULL;
m_var = NULL;
m_Parameters = NULL;
m_expr = NULL;
m_hasParams = false;
m_nMethodeIdent = 0;
name = "CBotClassInst";
2012-08-07 13:46:04 +00:00
}
CBotClassInst::~CBotClassInst()
{
2012-08-08 20:35:17 +00:00
delete m_var;
// delete m_next; // done by the destructor of the base class ~CBotInstr()
2012-08-07 13:46:04 +00:00
}
// definition of pointer (s) to an object
// style
// CPoint A, B ;
CBotInstr* CBotClassInst::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* pClass)
{
2012-08-08 20:35:17 +00:00
// seeks the corresponding classes
if ( pClass == NULL )
{
2012-08-11 18:59:35 +00:00
pStack->SetStartError(p->GetStart());
2012-08-08 20:35:17 +00:00
pClass = CBotClass::Find(p);
if ( pClass == NULL )
{
// not found? is bizare
pStack->SetError(TX_NOCLASS, p);
return NULL;
}
2012-08-11 18:59:35 +00:00
p = p->GetNext();
2012-08-08 20:35:17 +00:00
}
bool bIntrinsic = pClass->IsIntrinsic();
CBotTypResult type = CBotTypResult( bIntrinsic ? CBotTypIntrinsic : CBotTypPointer, pClass );
CBotClassInst* inst = static_cast<CBotClassInst*>(CompileArray(p, pStack, type));
2012-08-08 20:35:17 +00:00
if ( inst != NULL || !pStack->IsOk() ) return inst;
CBotCStack* pStk = pStack->TokenStack();
inst = new CBotClassInst();
2012-08-07 13:46:04 +00:00
/// \TODO Need to be revised and fixed after adding unit tests
2012-08-11 18:59:35 +00:00
CBotToken token(pClass->GetName(), CBotString(), p->GetStart(), p->GetEnd());
2012-08-08 20:35:17 +00:00
inst->SetToken(&token);
CBotToken* vartoken = p;
if ( NULL != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )) )
{
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = type;
2012-08-08 20:35:17 +00:00
if (pStk->CheckVarLocal(vartoken)) // redefinition of the variable
{
2012-08-11 18:59:35 +00:00
pStk->SetStartError(vartoken->GetStart());
pStk->SetError(TX_REDEFVAR, vartoken->GetEnd());
2012-08-08 20:35:17 +00:00
goto error;
}
if (IsOfType(p, ID_OPBRK)) // with any clues?
{
delete inst; // is not type CBotInt
p = vartoken; // returns to the variable name
// compiles declaration an array
2012-08-08 20:35:17 +00:00
inst = static_cast<CBotClassInst*>(CBotInstArray::Compile( p, pStk, type ));
2012-08-08 20:35:17 +00:00
if (!pStk->IsOk() )
{
2012-08-11 18:59:35 +00:00
pStk->SetError(TX_CLBRK, p->GetStart());
2012-08-08 20:35:17 +00:00
goto error;
}
goto suite; // no assignment, variable already created
}
CBotVar* var;
2012-08-11 18:59:35 +00:00
var = CBotVar::Create(vartoken->GetString(), type); // creates the instance
2012-08-08 20:35:17 +00:00
// var->SetClass(pClass);
var->SetUniqNum(
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
2012-08-08 20:35:17 +00:00
// its attribute a unique number
pStack->AddVar(var); // placed on the stack
// look if there are parameters
2012-08-11 18:59:35 +00:00
inst->m_hasParams = (p->GetType() == ID_OPENPAR);
2012-08-08 20:35:17 +00:00
CBotVar* ppVars[1000];
inst->m_Parameters = CompileParams(p, pStk, ppVars);
if ( !pStk->IsOk() ) goto error;
// if there are parameters, is the equivalent to the stament "new"
// CPoint A ( 0, 0 ) is equivalent to
// CPoint A = new CPoint( 0, 0 )
// if ( NULL != inst->m_Parameters )
if ( inst->m_hasParams )
{
// the constructor is there?
// CBotString noname;
2012-08-11 18:59:35 +00:00
CBotTypResult r = pClass->CompileMethode(pClass->GetName(), var, ppVars, pStk, inst->m_nMethodeIdent);
2012-08-08 20:35:17 +00:00
delete pStk->TokenStack(); // releases the supplement stack
2012-08-11 18:59:35 +00:00
int typ = r.GetType();
2012-08-08 20:35:17 +00:00
if (typ == TX_UNDEFCALL)
{
// si le constructeur n'existe pas
if (inst->m_Parameters != NULL) // with parameters
{
pStk->SetError(TX_NOCONST, vartoken);
goto error;
}
typ = 0;
}
if (typ>20)
{
2012-08-11 18:59:35 +00:00
pStk->SetError(typ, vartoken->GetEnd());
2012-08-08 20:35:17 +00:00
goto error;
}
}
if (IsOfType(p, ID_ASS)) // with a assignment?
{
if (inst->m_hasParams)
{
2012-08-11 18:59:35 +00:00
pStk->SetError(TX_ENDOF, p->GetStart());
2012-08-08 20:35:17 +00:00
goto error;
}
if ( NULL == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )) )
{
goto error;
}
2012-08-11 18:59:35 +00:00
CBotClass* result = pStk->GetClass();
if ( !pStk->GetTypResult(1).Eq(CBotTypNullPointer) &&
( !pStk->GetTypResult(1).Eq(CBotTypPointer) ||
2012-08-08 20:35:17 +00:00
( result != NULL && !pClass->IsChildOf(result) ))) // type compatible ?
{
2012-08-11 18:59:35 +00:00
pStk->SetError(TX_BADTYPE, p->GetStart());
2012-08-08 20:35:17 +00:00
goto error;
}
2012-08-11 18:59:35 +00:00
// if ( !bIntrinsic ) var->SetPointer(pStk->GetVar()->GetPointer());
if ( !bIntrinsic )
2012-08-08 20:35:17 +00:00
{
// does not use the result on the stack, to impose the class
CBotVar* pvar = CBotVar::Create("", pClass);
var->SetPointer( pvar ); // variable already declared instance pointer
delete pvar; // removes the second pointer
}
var->SetInit(CBotVar::InitType::DEF); // marks the pointer as init
2012-08-08 20:35:17 +00:00
}
else if (inst->m_hasParams)
{
// creates the object on the "job" (\TODO "tas")
// with a pointer to the object
if ( !bIntrinsic )
2012-08-08 20:35:17 +00:00
{
CBotVar* pvar = CBotVar::Create("", pClass);
var->SetPointer( pvar ); // variable already declared instance pointer
delete pvar; // removes the second pointer
}
var->SetInit(CBotVar::InitType::IS_POINTER); // marks the pointer as init
2012-08-08 20:35:17 +00:00
}
2012-08-07 13:46:04 +00:00
suite:
if (IsOfType(p, ID_COMMA)) // several chained definitions
2012-08-08 20:35:17 +00:00
{
if ( NULL != ( inst->m_next = CBotClassInst::Compile(p, pStk, pClass) )) // compiles the following
{
return pStack->Return(inst, pStk);
}
}
2012-08-08 20:35:17 +00:00
if (IsOfType(p, ID_SEP)) // complete instruction
{
return pStack->Return(inst, pStk);
}
2012-08-11 18:59:35 +00:00
pStk->SetError(TX_ENDOF, p->GetStart());
2012-08-08 20:35:17 +00:00
}
2012-08-07 13:46:04 +00:00
error:
2012-08-08 20:35:17 +00:00
delete inst;
return pStack->Return(NULL, pStk);
2012-08-07 13:46:04 +00:00
}
// declaration of the instance of a class, for example:
2012-08-08 20:35:17 +00:00
// CPoint A, B;
2012-08-07 13:46:04 +00:00
bool CBotClassInst::Execute(CBotStack* &pj)
{
2012-08-08 20:35:17 +00:00
CBotVar* pThis = NULL;
CBotStack* pile = pj->AddStack(this);//essential for SetState()
// if ( pile == EOX ) return true;
CBotToken* pt = &m_token;
CBotClass* pClass = CBotClass::Find(pt);
bool bIntrincic = pClass->IsIntrinsic();
// creates the variable of type pointer to the object
2012-08-11 18:59:35 +00:00
if ( pile->GetState()==0)
2012-08-08 20:35:17 +00:00
{
2012-08-11 18:59:35 +00:00
CBotString name = m_var->m_token.GetString();
2012-08-08 20:35:17 +00:00
if ( bIntrincic )
{
pThis = CBotVar::Create(name, CBotTypResult( CBotTypIntrinsic, pClass ));
}
else
{
pThis = CBotVar::Create(name, CBotTypResult( CBotTypPointer, pClass ));
}
pThis->SetUniqNum((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent); // its attribute as unique number
2012-08-08 20:35:17 +00:00
pile->AddVar(pThis); // place on the stack
pile->IncState();
}
if ( pThis == NULL ) pThis = pile->FindVar((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent);
2012-08-08 20:35:17 +00:00
2012-08-11 18:59:35 +00:00
if ( pile->GetState()<3)
2012-08-08 20:35:17 +00:00
{
// ss there an assignment or parameters (contructor)
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
// CBotVarClass* pInstance = NULL;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
if ( m_expr != NULL )
{
// evaluates the expression for the assignment
if (!m_expr->Execute(pile)) return false;
2012-08-08 20:35:17 +00:00
if ( bIntrincic )
{
2012-08-11 18:59:35 +00:00
CBotVar* pv = pile->GetVar();
if ( pv == NULL || pv->GetPointer() == NULL )
2012-08-08 20:35:17 +00:00
{
pile->SetError(TX_NULLPT, &m_token);
return pj->Return(pile);
}
2012-08-11 18:59:35 +00:00
pThis->Copy(pile->GetVar(), false);
2012-08-08 20:35:17 +00:00
}
else
{
CBotVarClass* pInstance;
pInstance = (static_cast<CBotVarPointer*>(pile->GetVar()))->GetPointer(); // value for the assignment
2012-08-08 20:35:17 +00:00
pThis->SetPointer(pInstance);
}
pThis->SetInit(CBotVar::InitType::DEF);
2012-08-08 20:35:17 +00:00
}
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
else if ( m_hasParams )
{
// evaluates the constructor of an instance
2012-08-07 13:46:04 +00:00
2012-08-11 18:59:35 +00:00
if ( !bIntrincic && pile->GetState() == 1)
2012-08-08 20:35:17 +00:00
{
CBotToken* pt = &m_token;
CBotClass* pClass = CBotClass::Find(pt);
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
// creates an instance of the requested class
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
CBotVarClass* pInstance;
pInstance = static_cast<CBotVarClass*>(CBotVar::Create("", pClass));
2012-08-08 20:35:17 +00:00
pThis->SetPointer(pInstance);
delete pInstance;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
pile->IncState();
}
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
CBotVar* ppVars[1000];
CBotStack* pile2 = pile;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
int i = 0;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
CBotInstr* p = m_Parameters;
// evaluates the parameters
// and places the values on the stack
// to (can) be interrupted (broken) at any time
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
if ( p != NULL) while ( true )
{
pile2 = pile2->AddStack(); // place on the stack for the results
2012-08-11 18:59:35 +00:00
if ( pile2->GetState() == 0 )
2012-08-08 20:35:17 +00:00
{
if (!p->Execute(pile2)) return false; // interrupted here?
pile2->SetState(1);
}
2012-08-11 18:59:35 +00:00
ppVars[i++] = pile2->GetVar();
p = p->GetNext();
2012-08-08 20:35:17 +00:00
if ( p == NULL) break;
}
ppVars[i] = NULL;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
// creates a variable for the result
CBotVar* pResult = NULL; // constructor still void
if ( !pClass->ExecuteMethode(m_nMethodeIdent, pClass->GetName(),
pThis, ppVars,
2012-08-11 18:59:35 +00:00
pResult, pile2, GetToken())) return false; // interrupt
2012-08-08 20:35:17 +00:00
pThis->SetInit(CBotVar::InitType::DEF);
2012-08-08 20:35:17 +00:00
pThis->ConstructorSet(); // indicates that the constructor has been called
pile->Return(pile2); // releases a piece of stack
2012-08-11 18:59:35 +00:00
// pInstance = pThis->GetPointer();
2012-08-08 20:35:17 +00:00
}
// if ( !bIntrincic ) pThis->SetPointer(pInstance); // a pointer to the instance
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
pile->SetState(3); // finished this part
}
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
if ( pile->IfStep() ) return false;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
if ( m_next2b != NULL &&
!m_next2b->Execute(pile)) return false; // other (s) definition (s)
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
return pj->Return( pile ); // transmits below (further)
2012-08-07 13:46:04 +00:00
}
void CBotClassInst::RestoreState(CBotStack* &pj, bool bMain)
{
2012-08-08 20:35:17 +00:00
CBotVar* pThis = NULL;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
CBotStack* pile = pj;
if ( bMain ) pile = pj->RestoreStack(this);
if ( pile == NULL ) return;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
// creates the variable of type pointer to the object
{
2012-08-11 18:59:35 +00:00
CBotString name = m_var->m_token.GetString();
2012-08-08 20:35:17 +00:00
pThis = pile->FindVar(name);
pThis->SetUniqNum((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent); // its attribute a unique number
2012-08-08 20:35:17 +00:00
}
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
CBotToken* pt = &m_token;
CBotClass* pClass = CBotClass::Find(pt);
bool bIntrincic = pClass->IsIntrinsic();
2012-08-07 13:46:04 +00:00
2012-08-11 18:59:35 +00:00
if ( bMain && pile->GetState()<3)
2012-08-08 20:35:17 +00:00
{
// is there an assignment or parameters (constructor)
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
// CBotVarClass* pInstance = NULL;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
if ( m_expr != NULL )
{
// evaluates the expression for the assignment
m_expr->RestoreState(pile, bMain);
return;
}
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
else if ( m_hasParams )
{
// evaluates the constructor of an instance
2012-08-07 13:46:04 +00:00
2012-08-11 18:59:35 +00:00
if ( !bIntrincic && pile->GetState() == 1)
2012-08-08 20:35:17 +00:00
{
return;
}
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
CBotVar* ppVars[1000];
CBotStack* pile2 = pile;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
int i = 0;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
CBotInstr* p = m_Parameters;
// evaluates the parameters
// and the values an the stack
// for the ability to be interrupted at any time (\TODO pour pouvoir être interrompu n'importe quand)
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
if ( p != NULL) while ( true )
{
pile2 = pile2->RestoreStack(); // place on the stack for the results
if ( pile2 == NULL ) return;
2012-08-07 13:46:04 +00:00
2012-08-11 18:59:35 +00:00
if ( pile2->GetState() == 0 )
2012-08-08 20:35:17 +00:00
{
p->RestoreState(pile2, bMain); // interrupted here?
return;
}
2012-08-11 18:59:35 +00:00
ppVars[i++] = pile2->GetVar();
p = p->GetNext();
2012-08-08 20:35:17 +00:00
if ( p == NULL) break;
}
ppVars[i] = NULL;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
// creates a variable for the result
// CBotVar* pResult = NULL; // constructor still void
2012-08-07 13:46:04 +00:00
2012-08-11 18:59:35 +00:00
pClass->RestoreMethode(m_nMethodeIdent, pClass->GetName(), pThis, ppVars, pile2);
2012-08-08 20:35:17 +00:00
return;
}
}
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
if ( m_next2b != NULL )
m_next2b->RestoreState(pile, bMain); // other(s) definition(s)
2012-08-07 13:46:04 +00:00
}
// test if a procedure name is already defined somewhere
bool CBotClass::CheckCall(CBotToken* &pToken, CBotDefParam* pParam)
{
2012-08-11 18:59:35 +00:00
CBotString name = pToken->GetString();
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
if ( CBotCall::CheckCall(name) ) return true;
2012-08-07 13:46:04 +00:00
2012-08-08 20:35:17 +00:00
CBotFunction* pp = m_pMethod;
while ( pp != NULL )
{
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
}