Fix constructor/destructor and field syntax
parent
8fc0151444
commit
64bc1f1afb
|
@ -1736,6 +1736,9 @@ msgstr ""
|
|||
msgid "Ambiguous call to overloaded function"
|
||||
msgstr ""
|
||||
|
||||
msgid "Function needs return type \"void\""
|
||||
msgstr ""
|
||||
|
||||
msgid "Dividing by zero"
|
||||
msgstr ""
|
||||
|
||||
|
|
3
po/de.po
3
po/de.po
|
@ -616,6 +616,9 @@ msgstr "Diese Funktion gibt es schon"
|
|||
msgid "Function name missing"
|
||||
msgstr "Hier muss der Name der Funktion stehen"
|
||||
|
||||
msgid "Function needs return type \"void\""
|
||||
msgstr ""
|
||||
|
||||
msgid "Game speed"
|
||||
msgstr "Spielgeschwindigkeit"
|
||||
|
||||
|
|
3
po/fr.po
3
po/fr.po
|
@ -603,6 +603,9 @@ msgstr "Cette fonction existe déjà"
|
|||
msgid "Function name missing"
|
||||
msgstr "Nom de la fonction attendu"
|
||||
|
||||
msgid "Function needs return type \"void\""
|
||||
msgstr ""
|
||||
|
||||
msgid "Game speed"
|
||||
msgstr "Vitesse du jeu"
|
||||
|
||||
|
|
3
po/pl.po
3
po/pl.po
|
@ -605,6 +605,9 @@ msgstr "Funkcja już istnieje"
|
|||
msgid "Function name missing"
|
||||
msgstr "Brakująca nazwa funkcji"
|
||||
|
||||
msgid "Function needs return type \"void\""
|
||||
msgstr ""
|
||||
|
||||
msgid "Game speed"
|
||||
msgstr "Prędkość gry"
|
||||
|
||||
|
|
3
po/ru.po
3
po/ru.po
|
@ -612,6 +612,9 @@ msgstr "Функция уже существует"
|
|||
msgid "Function name missing"
|
||||
msgstr "Имя функции отсутствует"
|
||||
|
||||
msgid "Function needs return type \"void\""
|
||||
msgstr ""
|
||||
|
||||
msgid "Game speed"
|
||||
msgstr "Скорость игры"
|
||||
|
||||
|
|
|
@ -248,6 +248,19 @@ CBotVar* CBotClass::GetItemRef(int nIdent)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool CBotClass::CheckVar(const std::string &name)
|
||||
{
|
||||
CBotVar* p = m_pVar;
|
||||
|
||||
while ( p != nullptr )
|
||||
{
|
||||
if ( p->GetName() == name ) return true;
|
||||
p = p->GetNext();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool CBotClass::IsIntrinsic()
|
||||
{
|
||||
|
@ -556,6 +569,8 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
|||
while (pStack->IsOk())
|
||||
{
|
||||
CBotTypResult type2 = CBotTypResult(type); // reset type after comma
|
||||
CBotToken* varToken = p;
|
||||
|
||||
std::string pp = p->GetString();
|
||||
if ( IsOfType(p, ID_NOT) )
|
||||
{
|
||||
|
@ -564,33 +579,6 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
|||
|
||||
if (IsOfType(p, TokenTypVar))
|
||||
{
|
||||
CBotInstr* limites = nullptr;
|
||||
while ( IsOfType( p, ID_OPBRK ) ) // a table?
|
||||
{
|
||||
CBotInstr* i = nullptr;
|
||||
pStack->SetStartError( p->GetStart() );
|
||||
if ( p->GetType() != ID_CLBRK )
|
||||
{
|
||||
i = CBotExpression::Compile( p, pStack ); // expression for the value
|
||||
if (i == nullptr || pStack->GetType() != CBotTypInt) // must be a number
|
||||
{
|
||||
pStack->SetError(CBotErrBadIndex, p->GetStart());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
i = new CBotEmpty(); // special if not a formula
|
||||
|
||||
type2 = CBotTypResult(CBotTypArrayPointer, type2);
|
||||
|
||||
if (limites == nullptr) limites = i;
|
||||
else limites->AddNext3(i);
|
||||
|
||||
if (IsOfType(p, ID_CLBRK)) continue;
|
||||
pStack->SetError(CBotErrCloseIndex, p->GetStart());
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( p->GetType() == ID_OPENPAR )
|
||||
{
|
||||
if ( !bSecond )
|
||||
|
@ -673,12 +661,51 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
|||
}
|
||||
|
||||
// definition of an element
|
||||
if (type2.Eq(0))
|
||||
if (type.Eq(0))
|
||||
{
|
||||
pStack->SetError(CBotErrNoTerminator, p);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pp[0] == '~' || pp == GetName()) // bad variable name
|
||||
{
|
||||
pStack->SetError(CBotErrNoVar, varToken);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!bSecond && CheckVar(pp)) // variable already exists
|
||||
{
|
||||
pStack->SetError(CBotErrRedefVar, varToken);
|
||||
return false;
|
||||
}
|
||||
|
||||
CBotInstr* limites = nullptr;
|
||||
while ( IsOfType( p, ID_OPBRK ) ) // an array
|
||||
{
|
||||
CBotInstr* i = nullptr;
|
||||
pStack->SetStartError( p->GetStart() );
|
||||
if ( p->GetType() != ID_CLBRK )
|
||||
{
|
||||
i = CBotExpression::Compile( p, pStack ); // expression for the value
|
||||
if (i == nullptr || pStack->GetType() != CBotTypInt) // must be a number
|
||||
{
|
||||
pStack->SetError(CBotErrBadIndex, p->GetStart());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
i = new CBotEmpty(); // special if not a formula
|
||||
|
||||
type2 = CBotTypResult(CBotTypArrayPointer, type2);
|
||||
|
||||
if (limites == nullptr) limites = i;
|
||||
else limites->AddNext3(i);
|
||||
|
||||
if (IsOfType(p, ID_CLBRK)) continue;
|
||||
pStack->SetError(CBotErrCloseIndex, p->GetStart());
|
||||
return false;
|
||||
}
|
||||
|
||||
CBotInstr* i = nullptr;
|
||||
if ( IsOfType(p, ID_ASS ) )
|
||||
{
|
||||
|
|
|
@ -221,6 +221,13 @@ public:
|
|||
*/
|
||||
CBotVar* GetItemRef(int nIdent);
|
||||
|
||||
/*!
|
||||
* \brief Check whether a variable is already defined in a class
|
||||
* \param name Name of the variable
|
||||
* \return True if a variable is defined in the class
|
||||
*/
|
||||
bool CheckVar(const std::string &name);
|
||||
|
||||
/*!
|
||||
* \brief CompileMethode Compiles a method associated with an instance of
|
||||
* class the method can be declared by the user or AddFunction.
|
||||
|
|
|
@ -237,6 +237,7 @@ enum CBotError : int
|
|||
CBotErrNoPublic = 5042, //!< missing word "public"
|
||||
CBotErrNoExpression = 5043, //!< expression expected after =
|
||||
CBotErrAmbiguousCall = 5044, //!< ambiguous call to overloaded function
|
||||
CBotErrFuncNotVoid = 5045, //!< function needs return type "void"
|
||||
|
||||
// Runtime errors
|
||||
CBotErrZeroDiv = 6000, //!< division by zero
|
||||
|
|
|
@ -165,6 +165,7 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
|
|||
if ( IsOfType(p, ID_NOT) )
|
||||
{
|
||||
CBotToken d(std::string("~") + p->GetString());
|
||||
d.SetPos(pp->GetStart(), p->GetEnd());
|
||||
func->m_token = d;
|
||||
}
|
||||
|
||||
|
@ -268,6 +269,7 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
|
|||
if ( IsOfType(p, ID_NOT) )
|
||||
{
|
||||
CBotToken d(std::string("~") + p->GetString());
|
||||
d.SetPos(pp->GetStart(), p->GetEnd());
|
||||
func->m_token = d;
|
||||
}
|
||||
|
||||
|
@ -289,10 +291,40 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
|
|||
if (!IsOfType(p, TokenTypVar)) goto bad;
|
||||
|
||||
}
|
||||
func->m_param = CBotDefParam::Compile(p, pStk );
|
||||
|
||||
CBotToken* openPar = p;
|
||||
func->m_param = CBotDefParam::Compile(p, pStk); // compile parameters
|
||||
|
||||
if (pStk->IsOk() && pClass != nullptr) // method in a class
|
||||
{
|
||||
// check if a constructor has return type void
|
||||
if (func->GetName() == pClass->GetName() && !func->m_retTyp.Eq(CBotTypVoid))
|
||||
{
|
||||
pp = &(func->m_retToken);
|
||||
pStk->SetError(CBotErrFuncNotVoid, pp);
|
||||
}
|
||||
|
||||
if (pStk->IsOk() && pp->GetString() == "~") // destructor
|
||||
{
|
||||
// check destructor name
|
||||
if (func->GetName() != ("~" + pClass->GetName()))
|
||||
pStk->SetError(CBotErrNoFunc, pp);
|
||||
// confirm no parameters
|
||||
if (pStk->IsOk() && func->m_param != nullptr)
|
||||
pStk->SetError(CBotErrClosePar, openPar->GetNext());
|
||||
// must return void
|
||||
if (pStk->IsOk() && !func->m_retTyp.Eq(CBotTypVoid))
|
||||
{
|
||||
pp = &(func->m_retToken);
|
||||
pStk->SetError(CBotErrFuncNotVoid, pp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pStk->IsOk())
|
||||
{
|
||||
// looks if the function exists elsewhere
|
||||
pp = &(func->m_token);
|
||||
if (( pClass != nullptr || !pStack->CheckCall(pp, func->m_param)) &&
|
||||
( pClass == nullptr || !pClass->CheckCall(pStack->GetProgram(), func->m_param, pp)) )
|
||||
{
|
||||
|
|
|
@ -719,6 +719,7 @@ void InitializeRestext()
|
|||
stringsCbot[CBot::CBotErrNoPublic] = TR("Public required");
|
||||
stringsCbot[CBot::CBotErrNoExpression] = TR("Expression expected after =");
|
||||
stringsCbot[CBot::CBotErrAmbiguousCall] = TR("Ambiguous call to overloaded function");
|
||||
stringsCbot[CBot::CBotErrFuncNotVoid] = TR("Function needs return type \"void\"");
|
||||
|
||||
stringsCbot[CBot::CBotErrZeroDiv] = TR("Dividing by zero");
|
||||
stringsCbot[CBot::CBotErrNotInit] = TR("Variable not initialized");
|
||||
|
|
|
@ -867,14 +867,13 @@ TEST_F(CBotUT, ClassNullPointer)
|
|||
);
|
||||
}
|
||||
|
||||
// TODO: This doesn't work
|
||||
TEST_F(CBotUT, DISABLED_ClassDestructorNaming)
|
||||
TEST_F(CBotUT, ClassDestructorNaming)
|
||||
{
|
||||
ExecuteTest(
|
||||
"public class TestClass {\n"
|
||||
" public void ~SomethingElse() {}\n"
|
||||
"}\n",
|
||||
static_cast<CBotError>(-1) // TODO: no error for that
|
||||
CBotErrNoFunc
|
||||
);
|
||||
ExecuteTest(
|
||||
"public class SomethingElse {\n"
|
||||
|
@ -882,7 +881,26 @@ TEST_F(CBotUT, DISABLED_ClassDestructorNaming)
|
|||
"public class TestClass2 {\n"
|
||||
" public void ~SomethingElse() {}\n"
|
||||
"}\n",
|
||||
static_cast<CBotError>(-1) // TODO: no error for that
|
||||
CBotErrNoFunc
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(CBotUT, ClassDestructorSyntax)
|
||||
{
|
||||
ExecuteTest(
|
||||
"public class TestClass {\n"
|
||||
" void ~TestClass(int i) {}\n"
|
||||
"}\n"
|
||||
"extern void DestructorNoParams() {}\n",
|
||||
CBotErrClosePar
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"public class TestClass {\n"
|
||||
" int ~TestClass() {}\n"
|
||||
"}\n"
|
||||
"extern void DestructorReturnTypeVoid() {}\n",
|
||||
CBotErrFuncNotVoid
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -930,6 +948,39 @@ TEST_F(CBotUT, ClassMethodRedefined)
|
|||
"}\n",
|
||||
CBotErrRedefFunc
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"public class TestClass {\n"
|
||||
" void ~TestClass() {}\n"
|
||||
" void ~TestClass() {}\n"
|
||||
"}\n",
|
||||
CBotErrRedefFunc
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(CBotUT, ClassFieldNaming)
|
||||
{
|
||||
ExecuteTest(
|
||||
"public class TestClass {\n"
|
||||
" int ~i = 1;\n"
|
||||
"}\n",
|
||||
CBotErrNoVar
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"public class TestClass {\n"
|
||||
" int TestClass = 1;\n"
|
||||
"}\n",
|
||||
CBotErrNoVar
|
||||
);
|
||||
|
||||
ExecuteTest(
|
||||
"public class TestClass {\n"
|
||||
" int i = 1;\n"
|
||||
" int i = 2;\n"
|
||||
"}\n",
|
||||
CBotErrRedefVar
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(CBotUT, ClassRedefinedInDifferentPrograms)
|
||||
|
|
Loading…
Reference in New Issue