diff --git a/src/CBot/CBotClass.cpp b/src/CBot/CBotClass.cpp index 70c72ef5..45510763 100644 --- a/src/CBot/CBotClass.cpp +++ b/src/CBot/CBotClass.cpp @@ -504,16 +504,25 @@ CBotClass* CBotClass::Compile1(CBotToken* &p, CBotCStack* pStack) classe->Purge(); // empty the old definitions // TODO: Doesn't this remove all classes of the current program? classe->m_IsDef = false; // current definition + classe->m_pOpenblk = p; + if ( !IsOfType( p, ID_OPBLK) ) { pStack->SetError(CBotErrOpenBlock, p); return nullptr; } - while ( pStack->IsOk() && !IsOfType( p, ID_CLBLK ) ) + int level = 1; + do // skip over the definition { - classe->CompileDefItem(p, pStack, false); + int type = p->GetType(); + p = p->GetNext(); + if (type == ID_OPBLK) level++; + if (type == ID_CLBLK) level--; } + while (level > 0 && p != nullptr); + + if (level > 0) pStack->SetError(CBotErrCloseBlock, classe->m_pOpenblk); if (pStack->IsOk()) return classe; } @@ -521,6 +530,26 @@ CBotClass* CBotClass::Compile1(CBotToken* &p, CBotCStack* pStack) return nullptr; } +//////////////////////////////////////////////////////////////////////////////// +void CBotClass::DefineClasses(CBotClass* pClass, CBotCStack* pStack) +{ + while (pClass != nullptr) + { + CBotClass* pParent = pClass->m_parent; + pClass->m_nbVar = (pParent == nullptr) ? 0 : pParent->m_nbVar; + CBotToken* p = pClass->m_pOpenblk->GetNext(); + + while (pStack->IsOk() && !IsOfType(p, ID_CLBLK)) + { + pClass->CompileDefItem(p, pStack, false); + } + + if (!pStack->IsOk()) return; + + pClass = pClass->GetNext(); + } +} + //////////////////////////////////////////////////////////////////////////////// bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond) { diff --git a/src/CBot/CBotClass.h b/src/CBot/CBotClass.h index 234f5786..2fc494dc 100644 --- a/src/CBot/CBotClass.h +++ b/src/CBot/CBotClass.h @@ -291,6 +291,14 @@ public: static CBotClass* Compile1(CBotToken* &p, CBotCStack* pStack); + /*! + * \brief DefineClasses Calls CompileDefItem for each class in a list + * of classes, defining fields and pre-compiling methods. + * \param pClass List of classes + * \param pStack + */ + static void DefineClasses(CBotClass* pClass, CBotCStack* pStack); + /*! * \brief CompileDefItem * \param p @@ -385,6 +393,8 @@ private: CBotFunction* m_pMethod; void (*m_rUpdate)(CBotVar* thisVar, void* user); + CBotToken* m_pOpenblk; + //! How many times the program currently holding the lock called Lock() int m_lockCurrentCount = 0; //! Programs waiting for lock. m_lockProg[0] is the program currently holding the lock, if any diff --git a/src/CBot/CBotProgram.cpp b/src/CBot/CBotProgram.cpp index d0284ea2..77dac399 100644 --- a/src/CBot/CBotProgram.cpp +++ b/src/CBot/CBotProgram.cpp @@ -99,6 +99,10 @@ bool CBotProgram::Compile(const std::string& program, std::vector<std::string>& else m_functions->AddNext(next); } } + + // Define fields and pre-compile methods for each class in this program + if (pStack->IsOk()) CBotClass::DefineClasses(m_classes, pStack.get()); + if ( !pStack->IsOk() ) { m_error = pStack->GetError(m_errorStart, m_errorEnd);