Fix execution of default arguments
parent
588bf30b94
commit
b032dad578
|
@ -136,30 +136,38 @@ bool CBotDefParam::Execute(CBotVar** ppVars, CBotStack* &pj)
|
||||||
CBotDefParam* p = this;
|
CBotDefParam* p = this;
|
||||||
|
|
||||||
bool useDefault = false;
|
bool useDefault = false;
|
||||||
|
CBotStack* pile = pj->AddStack();
|
||||||
|
|
||||||
while ( p != nullptr )
|
while ( p != nullptr )
|
||||||
{
|
{
|
||||||
// creates a local variable on the stack
|
pile = pile->AddStack();
|
||||||
CBotVar* newvar = CBotVar::Create(p->m_token.GetString(), p->m_type);
|
if (pile->GetState() == 1) // already done?
|
||||||
|
{
|
||||||
|
if (ppVars != nullptr && ppVars[i] != nullptr) ++i;
|
||||||
|
p = p->m_next;
|
||||||
|
continue; // next param
|
||||||
|
}
|
||||||
|
|
||||||
CBotVar* pVar = nullptr;
|
CBotVar* pVar = nullptr;
|
||||||
CBotStack* pile = nullptr; // stack for default expression
|
|
||||||
|
|
||||||
if (useDefault || (ppVars == nullptr || ppVars[i] == nullptr))
|
if (useDefault || (ppVars == nullptr || ppVars[i] == nullptr))
|
||||||
{
|
{
|
||||||
assert(p->m_expr != nullptr);
|
assert(p->m_expr != nullptr);
|
||||||
|
|
||||||
pile = pj->AddStack();
|
|
||||||
useDefault = true;
|
useDefault = true;
|
||||||
|
|
||||||
while (pile->IsOk() && !p->m_expr->Execute(pile));
|
if (!p->m_expr->Execute(pile)) return false; // interupt here
|
||||||
if (!pile->IsOk()) return pj->Return(pile); // return the error
|
|
||||||
|
|
||||||
pVar = pile->GetVar();
|
pVar = pile->GetVar();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pVar = ppVars[i];
|
pVar = ppVars[i];
|
||||||
|
|
||||||
|
pile->SetState(1); // mark this param done
|
||||||
|
|
||||||
|
// creates a local variable on the stack
|
||||||
|
CBotVar* newvar = CBotVar::Create(p->m_token.GetString(), p->m_type);
|
||||||
|
|
||||||
// serves to make the transformation of types:
|
// serves to make the transformation of types:
|
||||||
if ((useDefault && pVar != nullptr) ||
|
if ((useDefault && pVar != nullptr) ||
|
||||||
(ppVars != nullptr && pVar != nullptr))
|
(ppVars != nullptr && pVar != nullptr))
|
||||||
|
@ -202,7 +210,6 @@ bool CBotDefParam::Execute(CBotVar** ppVars, CBotStack* &pj)
|
||||||
pj->AddVar(newvar); // add a variable
|
pj->AddVar(newvar); // add a variable
|
||||||
p = p->m_next;
|
p = p->m_next;
|
||||||
if (!useDefault) i++;
|
if (!useDefault) i++;
|
||||||
if (pile != nullptr) pile->Delete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -217,14 +224,27 @@ bool CBotDefParam::HasDefault()
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotDefParam::RestoreState(CBotStack* &pj, bool bMain)
|
void CBotDefParam::RestoreState(CBotStack* &pj, bool bMain)
|
||||||
{
|
{
|
||||||
// int i = 0;
|
assert(this != nullptr);
|
||||||
CBotDefParam* p = this;
|
CBotDefParam* p = this;
|
||||||
|
|
||||||
|
CBotStack* pile = nullptr;
|
||||||
|
if (bMain) pile = pj->RestoreStack();
|
||||||
|
|
||||||
while ( p != nullptr )
|
while ( p != nullptr )
|
||||||
{
|
{
|
||||||
|
if (bMain && pile != nullptr)
|
||||||
|
{
|
||||||
|
pile = pile->RestoreStack();
|
||||||
|
if (pile != nullptr && pile->GetState() == 0)
|
||||||
|
{
|
||||||
|
assert(p->m_expr != nullptr);
|
||||||
|
p->m_expr->RestoreState(pile, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
// creates a local variable on the stack
|
// creates a local variable on the stack
|
||||||
CBotVar* var = pj->FindVar(p->m_token.GetString());
|
CBotVar* var = pj->FindVar(p->m_token.GetString());
|
||||||
var->SetUniqNum(p->m_nIdent);
|
if (var != nullptr) var->SetUniqNum(p->m_nIdent);
|
||||||
p = p->m_next;
|
p = p->m_next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -370,11 +370,18 @@ bool CBotFunction::Execute(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInstance)
|
||||||
|
|
||||||
pile->SetProgram(m_pProg); // bases for routines
|
pile->SetProgram(m_pProg); // bases for routines
|
||||||
|
|
||||||
|
if ( pile->IfStep() ) return false;
|
||||||
|
|
||||||
if ( pile->GetState() == 0 )
|
if ( pile->GetState() == 0 )
|
||||||
{
|
{
|
||||||
if (m_param != nullptr)
|
if (m_param != nullptr)
|
||||||
{
|
{
|
||||||
|
// stack for parameters and default args
|
||||||
|
CBotStack* pile3b = pile->AddStack();
|
||||||
|
pile3b->SetState(1);
|
||||||
|
|
||||||
if ( !m_param->Execute(ppVars, pile) ) return false; // define parameters
|
if ( !m_param->Execute(ppVars, pile) ) return false; // define parameters
|
||||||
|
pile3b->Delete(); // done with param stack
|
||||||
}
|
}
|
||||||
pile->IncState();
|
pile->IncState();
|
||||||
}
|
}
|
||||||
|
@ -408,8 +415,6 @@ bool CBotFunction::Execute(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInstance)
|
||||||
pile->IncState();
|
pile->IncState();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( pile->IfStep() ) return false;
|
|
||||||
|
|
||||||
if ( !m_block->Execute(pile) )
|
if ( !m_block->Execute(pile) )
|
||||||
{
|
{
|
||||||
if ( pile->GetError() < 0 )
|
if ( pile->GetError() < 0 )
|
||||||
|
@ -438,7 +443,22 @@ void CBotFunction::RestoreState(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInst
|
||||||
pile2->Delete();
|
pile2->Delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_param->RestoreState(pile2, true); // parameters
|
if ( pile->GetState() == 0 )
|
||||||
|
{
|
||||||
|
if (m_param != nullptr)
|
||||||
|
{
|
||||||
|
CBotStack* pile3b = pile2->RestoreStack();
|
||||||
|
|
||||||
|
if (pile3b != nullptr && pile3b->GetState() == 1)
|
||||||
|
m_param->RestoreState(pile2, true); // restore executing default arguments
|
||||||
|
else
|
||||||
|
m_param->RestoreState(pile2, false); // restore parameter IDs
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_param != nullptr)
|
||||||
|
m_param->RestoreState(pile2, false); // restore parameter IDs
|
||||||
|
|
||||||
if ( !m_MasterClass.empty() )
|
if ( !m_MasterClass.empty() )
|
||||||
{
|
{
|
||||||
|
@ -670,7 +690,10 @@ int CBotFunction::DoCall(CBotProgram* program, const std::list<CBotFunction*>& l
|
||||||
|
|
||||||
if ( pStk1->GetState() == 0 )
|
if ( pStk1->GetState() == 0 )
|
||||||
{
|
{
|
||||||
if ( !pt->m_MasterClass.empty() )
|
// stack for parameters and default args
|
||||||
|
CBotStack* pStk3b = pStk3->AddStack();
|
||||||
|
|
||||||
|
if (pStk3b->GetState() == 0 && !pt->m_MasterClass.empty())
|
||||||
{
|
{
|
||||||
CBotVar* pInstance = program->m_thisVar;
|
CBotVar* pInstance = program->m_thisVar;
|
||||||
// make "this" known
|
// make "this" known
|
||||||
|
@ -696,20 +719,21 @@ int CBotFunction::DoCall(CBotProgram* program, const std::list<CBotFunction*>& l
|
||||||
pThis->SetUniqNum(-2);
|
pThis->SetUniqNum(-2);
|
||||||
pStk1->AddVar(pThis);
|
pStk1->AddVar(pThis);
|
||||||
}
|
}
|
||||||
|
pStk3b->SetState(1); // set 'this' was created
|
||||||
|
|
||||||
// initializes the variables as parameters
|
// initializes the variables as parameters
|
||||||
if (pt->m_param != nullptr)
|
if (pt->m_param != nullptr)
|
||||||
{
|
{
|
||||||
if (!pt->m_param->Execute(ppVars, pStk3)) // interupts only if error on a default value
|
if (!pt->m_param->Execute(ppVars, pStk3)) // interupt here
|
||||||
{
|
{
|
||||||
if ( pt->m_pProg != program )
|
if (!pStk3->IsOk() && pt->m_pProg != program)
|
||||||
{
|
{
|
||||||
pStk3->SetPosError(pToken); // indicates the error on the procedure call
|
pStk3->SetPosError(pToken); // indicates the error on the procedure call
|
||||||
}
|
}
|
||||||
return pStack->Return(pStk3);
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pStk3b->Delete(); // done with param stack
|
||||||
pStk1->IncState();
|
pStk1->IncState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,12 +802,21 @@ void CBotFunction::RestoreCall(const std::list<CBotFunction*>& localFunctionList
|
||||||
|
|
||||||
if ( pStk1->GetState() == 0 )
|
if ( pStk1->GetState() == 0 )
|
||||||
{
|
{
|
||||||
pt->m_param->RestoreState(pStk3, true);
|
if (pt->m_param != nullptr)
|
||||||
|
{
|
||||||
|
CBotStack* pStk3b = pStk3->RestoreStack();
|
||||||
|
|
||||||
|
if (pStk3b != nullptr && pStk3b->GetState() == 1)
|
||||||
|
pt->m_param->RestoreState(pStk3, true); // restore executing default arguments
|
||||||
|
else
|
||||||
|
pt->m_param->RestoreState(pStk3, false); // restore parameter IDs
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// initializes the variables as parameters
|
// initializes the variables as parameters
|
||||||
pt->m_param->RestoreState(pStk3, false);
|
if (pt->m_param != nullptr)
|
||||||
|
pt->m_param->RestoreState(pStk3, false); // restore parameter IDs
|
||||||
pt->m_block->RestoreState(pStk3, true);
|
pt->m_block->RestoreState(pStk3, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -810,6 +843,11 @@ int CBotFunction::DoCall(const std::list<CBotFunction*>& localFunctionList, long
|
||||||
// preparing parameters on the stack
|
// preparing parameters on the stack
|
||||||
|
|
||||||
if ( pStk->GetState() == 0 )
|
if ( pStk->GetState() == 0 )
|
||||||
|
{
|
||||||
|
// stack for parameters and default args
|
||||||
|
CBotStack* pStk3b = pStk3->AddStack();
|
||||||
|
|
||||||
|
if (pStk3b->GetState() == 0)
|
||||||
{
|
{
|
||||||
// sets the variable "this" on the stack
|
// sets the variable "this" on the stack
|
||||||
CBotVar* pthis = CBotVar::Create("this", CBotTypNullPointer);
|
CBotVar* pthis = CBotVar::Create("this", CBotTypNullPointer);
|
||||||
|
@ -826,18 +864,22 @@ int CBotFunction::DoCall(const std::list<CBotFunction*>& localFunctionList, long
|
||||||
psuper->SetUniqNum(-3); // special value
|
psuper->SetUniqNum(-3); // special value
|
||||||
pStk->AddVar(psuper);
|
pStk->AddVar(psuper);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
pStk3b->SetState(1); // set 'this' was created
|
||||||
|
|
||||||
// initializes the variables as parameters
|
// initializes the variables as parameters
|
||||||
if (pt->m_param != nullptr)
|
if (pt->m_param != nullptr)
|
||||||
{
|
{
|
||||||
if (!pt->m_param->Execute(ppVars, pStk3)) // interupts only if error on a default value
|
if (!pt->m_param->Execute(ppVars, pStk3)) // interupt here
|
||||||
{
|
{
|
||||||
if ( pt->m_pProg != pProgCurrent )
|
if (!pStk3->IsOk() && pt->m_pProg != pProgCurrent)
|
||||||
{
|
{
|
||||||
pStk3->SetPosError(pToken); // indicates the error on the procedure call
|
pStk3->SetPosError(pToken); // indicates the error on the procedure call
|
||||||
}
|
}
|
||||||
return pStack->Return(pStk3);
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pStk3b->Delete(); // done with param stack
|
||||||
pStk->IncState();
|
pStk->IncState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -905,7 +947,21 @@ bool CBotFunction::RestoreCall(const std::list<CBotFunction*>& localFunctionList
|
||||||
CBotStack* pStk3 = pStk->RestoreStack(nullptr); // to set parameters passed
|
CBotStack* pStk3 = pStk->RestoreStack(nullptr); // to set parameters passed
|
||||||
if ( pStk3 == nullptr ) return true;
|
if ( pStk3 == nullptr ) return true;
|
||||||
|
|
||||||
pt->m_param->RestoreState(pStk3, true); // parameters
|
if ( pStk->GetState() == 0 )
|
||||||
|
{
|
||||||
|
if (pt->m_param != nullptr)
|
||||||
|
{
|
||||||
|
CBotStack* pStk3b = pStk3->RestoreStack();
|
||||||
|
if (pStk3b != nullptr && pStk3b->GetState() == 1)
|
||||||
|
pt->m_param->RestoreState(pStk3, true); // restore executing default arguments
|
||||||
|
else
|
||||||
|
pt->m_param->RestoreState(pStk3, false); // restore parameter IDs
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pt->m_param != nullptr)
|
||||||
|
pt->m_param->RestoreState(pStk3, false); // restore parameter IDs
|
||||||
|
|
||||||
if ( pStk->GetState() > 1 && // latching is effective?
|
if ( pStk->GetState() > 1 && // latching is effective?
|
||||||
pt->m_bSynchro )
|
pt->m_bSynchro )
|
||||||
|
|
Loading…
Reference in New Issue