[colobot] 17/74: Add accessing members to function calls
Didier Raboud
odyx at moszumanska.debian.org
Mon Nov 7 07:50:00 UTC 2016
This is an automated email from the git hooks/post-receive script.
odyx pushed a commit to branch debian/master
in repository colobot.
commit fad38cd0e9313c6058f5ec7f7027f4904fdccbcc
Author: melex750 <melex750 at users.noreply.github.com>
Date: Thu Aug 4 03:16:59 2016 -0400
Add accessing members to function calls
---
src/CBot/CBotInstr/CBotExprRetVar.cpp | 183 ++++++++++++++++++++++++++++++++
src/CBot/CBotInstr/CBotExprRetVar.h | 45 ++++++++
src/CBot/CBotInstr/CBotIndexExpr.h | 1 +
src/CBot/CBotInstr/CBotInstrCall.cpp | 93 ++++++++--------
src/CBot/CBotInstr/CBotInstrCall.h | 4 +
src/CBot/CBotInstr/CBotInstrMethode.cpp | 43 +++++++-
src/CBot/CBotInstr/CBotInstrMethode.h | 4 +
src/CBot/CMakeLists.txt | 2 +
8 files changed, 330 insertions(+), 45 deletions(-)
diff --git a/src/CBot/CBotInstr/CBotExprRetVar.cpp b/src/CBot/CBotInstr/CBotExprRetVar.cpp
new file mode 100644
index 0000000..28b0fa8
--- /dev/null
+++ b/src/CBot/CBotInstr/CBotExprRetVar.cpp
@@ -0,0 +1,183 @@
+
+#include <sstream>
+#include "CBot/CBotInstr/CBotExprRetVar.h"
+
+#include "CBot/CBotInstr/CBotExpression.h"
+#include "CBot/CBotInstr/CBotInstrMethode.h"
+#include "CBot/CBotInstr/CBotIndexExpr.h"
+#include "CBot/CBotInstr/CBotFieldExpr.h"
+
+#include "CBot/CBotStack.h"
+
+namespace CBot
+{
+
+////////////////////////////////////////////////////////////////////////////////
+CBotExprRetVar::CBotExprRetVar()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+CBotExprRetVar::~CBotExprRetVar()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+CBotInstr* CBotExprRetVar::Compile(CBotToken*& p, CBotCStack* pStack)
+{
+ if (p->GetType() == ID_DOT)
+ {
+ CBotVar* var = pStack->GetVar();
+
+ if (var == nullptr)
+ {
+ pStack->SetError(CBotErrNoTerminator, p->GetStart());
+ return nullptr;
+ }
+
+ CBotCStack* pStk = pStack->TokenStack();
+ CBotInstr* inst = new CBotExprRetVar();
+
+ while (true)
+ {
+ pStk->SetStartError(p->GetStart());
+ if (var->GetType() == CBotTypArrayPointer)
+ {
+ if (IsOfType( p, ID_OPBRK ))
+ {
+ CBotIndexExpr* i = new CBotIndexExpr();
+ i->m_expr = CBotExpression::Compile(p, pStk);
+ inst->AddNext3(i);
+
+ var = var->GetItem(0,true);
+
+ if (i->m_expr == nullptr || pStk->GetType() != CBotTypInt)
+ {
+ pStk->SetError(CBotErrBadIndex, p->GetStart());
+ goto err;
+ }
+ if (!pStk->IsOk() || !IsOfType( p, ID_CLBRK ))
+ {
+ pStk->SetError(CBotErrCloseIndex, p->GetStart());
+ goto err;
+ }
+ continue;
+ }
+ }
+ if (var->GetType(CBotVar::GetTypeMode::CLASS_AS_POINTER) == CBotTypPointer)
+ {
+ if (IsOfType(p, ID_DOT))
+ {
+ CBotToken* pp = p;
+
+ if (p->GetType() == TokenTypVar)
+ {
+ if (p->GetNext()->GetType() == ID_OPENPAR)
+ {
+ CBotInstr* i = CBotInstrMethode::Compile(p, pStk, var);
+ if (!pStk->IsOk()) goto err;
+ inst->AddNext3(i);
+ return pStack->Return(inst, pStk);
+ }
+ else
+ {
+ CBotFieldExpr* i = new CBotFieldExpr();
+ i->SetToken(pp);
+ inst->AddNext3(i);
+ var = var->GetItem(p->GetString());
+ if (var != nullptr)
+ {
+ i->SetUniqNum(var->GetUniqNum());
+ if ( var->IsPrivate() &&
+ !pStk->GetProgram()->m_bCompileClass)
+ {
+ pStk->SetError(CBotErrPrivate, pp);
+ goto err;
+ }
+ }
+ }
+
+ if (var != nullptr)
+ {
+ p = p->GetNext();
+ continue;
+ }
+ pStk->SetError(CBotErrUndefItem, p);
+ goto err;
+ }
+ pStk->SetError(CBotErrUndefClass, p);
+ goto err;
+ }
+ }
+ break;
+ }
+
+ pStk->SetCopyVar(var);
+ if (pStk->IsOk()) return pStack->Return(inst, pStk);
+
+ pStk->SetError(CBotErrUndefVar, p);
+err:
+ delete inst;
+ return pStack->Return(nullptr, pStk);
+ }
+ return nullptr;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool CBotExprRetVar::Execute(CBotStack* &pj)
+{
+
+ CBotStack* pile = pj->AddStack();
+ CBotStack* pile1 = pile;
+ CBotVar* pVar;
+
+ if (pile1->GetState() == 0)
+ {
+ pVar = pj->GetVar();
+ pVar->Update(pj->GetUserPtr());
+
+ if ( !m_next3->ExecuteVar(pVar, pile, &m_token, true, false) )
+ return false;
+
+ if (pVar)
+ pile1->SetCopyVar(pVar);
+ else
+ return pj->Return(pile1);
+
+ pile1->IncState();
+ }
+ pVar = pile1->GetVar();
+
+ if (pVar == nullptr)
+ {
+ return pj->Return(pile1);
+ }
+
+ if (pVar->IsUndefined())
+ {
+ pile1->SetError(CBotErrNotInit, &m_token);
+ return pj->Return(pile1);
+ }
+ return pj->Return(pile1);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void CBotExprRetVar::RestoreState(CBotStack* &pj, bool bMain)
+{
+ if (!bMain) return;
+
+ CBotStack* pile = pj->RestoreStack();
+ if ( pile == nullptr ) return;
+
+ if (pile->GetState() == 0)
+ m_next3->RestoreStateVar(pile, bMain);
+}
+
+std::string CBotExprRetVar::GetDebugData()
+{
+ std::stringstream ss;
+ ss << m_token.GetString() << "func(...).something" << std::endl;
+ return ss.str();
+}
+
+} // namespace CBot
diff --git a/src/CBot/CBotInstr/CBotExprRetVar.h b/src/CBot/CBotInstr/CBotExprRetVar.h
new file mode 100644
index 0000000..79c72ac
--- /dev/null
+++ b/src/CBot/CBotInstr/CBotExprRetVar.h
@@ -0,0 +1,45 @@
+
+#pragma once
+
+#include "CBot/CBotInstr/CBotInstr.h"
+
+namespace CBot
+{
+
+/**
+ * \brief Access a member/element of the variable on the stack
+ *
+ *
+ *
+ */
+class CBotExprRetVar : public CBotInstr
+{
+public:
+ CBotExprRetVar();
+ ~CBotExprRetVar();
+
+ static CBotInstr* Compile(CBotToken*& p, CBotCStack* pStack);
+
+ /*!
+ * \brief Execute
+ * \param pj
+ * \return
+ */
+ bool Execute(CBotStack* &pj) override;
+
+ /*!
+ * \brief RestoreState
+ * \param pj
+ * \param bMain
+ */
+ void RestoreState(CBotStack* &pj, bool bMain) override;
+
+protected:
+ virtual const std::string GetDebugName() override { return "CBotExprRetVar"; }
+ virtual std::string GetDebugData() override;
+
+private:
+
+};
+
+} // namespace CBot
diff --git a/src/CBot/CBotInstr/CBotIndexExpr.h b/src/CBot/CBotInstr/CBotIndexExpr.h
index 15fe2d4..8ac6ed5 100644
--- a/src/CBot/CBotInstr/CBotIndexExpr.h
+++ b/src/CBot/CBotInstr/CBotIndexExpr.h
@@ -69,6 +69,7 @@ private:
CBotInstr* m_expr;
friend class CBotLeftExpr;
friend class CBotExprVar;
+ friend class CBotExprRetVar;
};
} // namespace CBot
diff --git a/src/CBot/CBotInstr/CBotInstrCall.cpp b/src/CBot/CBotInstr/CBotInstrCall.cpp
index 111ec81..6b45bb5 100644
--- a/src/CBot/CBotInstr/CBotInstrCall.cpp
+++ b/src/CBot/CBotInstr/CBotInstrCall.cpp
@@ -18,7 +18,8 @@
*/
#include "CBot/CBotInstr/CBotInstrCall.h"
-#include "CBot/CBotInstr/CBotExpression.h"
+#include "CBot/CBotInstr/CBotExprRetVar.h"
+#include "CBot/CBotInstr/CBotInstrUtils.h"
#include "CBot/CBotStack.h"
@@ -47,62 +48,26 @@ CBotInstrCall::~CBotInstrCall()
////////////////////////////////////////////////////////////////////////////////
CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack)
{
- CBotVar* ppVars[1000];
-
- int i = 0;
CBotToken* pp = p;
p = p->GetNext();
- pStack->SetStartError(p->GetStart());
- CBotCStack* pile = pStack;
-
- if ( IsOfType(p, ID_OPENPAR) )
+ if (p->GetType() == ID_OPENPAR)
{
- int start, end;
+
+ CBotVar* ppVars[1000];
+
CBotInstrCall* inst = new CBotInstrCall();
inst->SetToken(pp);
// compile la list of parameters
- if (!IsOfType(p, ID_CLOSEPAR)) while (true)
+ inst->m_parameters = CompileParams(p, pStack, ppVars);
+
+ if ( !pStack->IsOk() )
{
- start = p->GetStart();
- pile = pile->TokenStack(); // keeps the results on the stack
-
- CBotInstr* param = CBotExpression::Compile(p, pile);
- end = p->GetStart();
- if (inst->m_parameters == nullptr ) inst->m_parameters = param;
- else inst->m_parameters->AddNext(param); // constructs the list
-
- if ( !pile->IsOk() )
- {
- delete inst;
- return pStack->Return(nullptr, pile);
- }
-
- if ( param != nullptr )
- {
- if ( pile->GetTypResult().Eq(99) )
- {
- delete pStack->TokenStack();
- pStack->SetError(CBotErrVoid, p->GetStart());
- delete inst;
- return nullptr;
- }
- ppVars[i] = pile->GetVar();
- ppVars[i]->GetToken()->SetPos(start, end);
- i++;
-
- if (IsOfType(p, ID_COMMA)) continue; // skips the comma
- if (IsOfType(p, ID_CLOSEPAR)) break;
- }
-
- pStack->SetError(CBotErrClosePar, p->GetStart());
- delete pStack->TokenStack();
delete inst;
return nullptr;
}
- ppVars[i] = nullptr;
// the routine is known?
// CBotClass* pClass = nullptr;
@@ -124,6 +89,17 @@ CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack)
}
else pStack->SetVar(nullptr); // routine returns void
+ if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStack)))
+ {
+ inst->m_exprRetVar->SetToken(&inst->m_token);
+ delete pStack->TokenStack();
+ }
+ if ( !pStack->IsOk() )
+ {
+ delete inst;
+ return nullptr;
+ }
+
return inst;
}
p = pp;
@@ -138,6 +114,17 @@ bool CBotInstrCall::Execute(CBotStack* &pj)
CBotStack* pile = pj->AddStack(this);
if ( pile->StackOver() ) return pj->Return( pile );
+ CBotStack* pile3 = nullptr;
+ if (m_exprRetVar != nullptr) // func().member
+ {
+ pile3 = pile->AddStack2();
+ if (pile3->GetState() == 1) // function call is done?
+ {
+ if (!m_exprRetVar->Execute(pile3)) return false;
+ return pj->Return(pile3);
+ }
+ }
+
// CBotStack* pile1 = pile;
int i = 0;
@@ -165,6 +152,14 @@ bool CBotInstrCall::Execute(CBotStack* &pj)
if ( !pile2->ExecuteCall(m_nFuncIdent, GetToken(), ppVars, m_typRes)) return false; // interrupt
+ if (m_exprRetVar != nullptr) // func().member
+ {
+ pile3->SetCopyVar( pile2->GetVar() ); // copy the result
+ pile2->SetVar(nullptr);
+ pile3->SetState(1); // set call is done
+ return false; // go back to the top ^^^
+ }
+
return pj->Return(pile2); // release the entire stack
}
@@ -176,6 +171,16 @@ void CBotInstrCall::RestoreState(CBotStack* &pj, bool bMain)
CBotStack* pile = pj->RestoreStack(this);
if ( pile == nullptr ) return;
+ if (m_exprRetVar != nullptr) // func().member
+ {
+ CBotStack* pile3 = pile->AddStack2();
+ if (pile3->GetState() == 1) // function call is done?
+ {
+ m_exprRetVar->RestoreState(pile3, bMain);
+ return;
+ }
+ }
+
// CBotStack* pile1 = pile;
int i = 0;
diff --git a/src/CBot/CBotInstr/CBotInstrCall.h b/src/CBot/CBotInstr/CBotInstrCall.h
index 7e8aba0..e39534f 100644
--- a/src/CBot/CBotInstr/CBotInstrCall.h
+++ b/src/CBot/CBotInstr/CBotInstrCall.h
@@ -69,6 +69,10 @@ private:
CBotTypResult m_typRes;
//! Id of a function.
long m_nFuncIdent;
+
+ //! Instruction to return a member of the returned object.
+ CBotInstr* m_exprRetVar;
+
friend class CBotDebug;
};
diff --git a/src/CBot/CBotInstr/CBotInstrMethode.cpp b/src/CBot/CBotInstr/CBotInstrMethode.cpp
index 3bdf849..78ed6b4 100644
--- a/src/CBot/CBotInstr/CBotInstrMethode.cpp
+++ b/src/CBot/CBotInstr/CBotInstrMethode.cpp
@@ -20,6 +20,7 @@
#include <sstream>
#include "CBot/CBotInstr/CBotInstrMethode.h"
+#include "CBot/CBotInstr/CBotExprRetVar.h"
#include "CBot/CBotInstr/CBotInstrUtils.h"
#include "CBot/CBotStack.h"
@@ -86,7 +87,16 @@ CBotInstr* CBotInstrMethode::Compile(CBotToken* &p, CBotCStack* pStack, CBotVar*
}
pStack->SetVar(pResult);
}
- return inst;
+ else pStack->SetVar(nullptr);
+
+ if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStack)))
+ {
+ inst->m_exprRetVar->SetToken(&inst->m_token);
+ delete pStack->TokenStack();
+ }
+
+ if ( pStack->IsOk() )
+ return inst;
}
delete inst;
return nullptr;
@@ -106,6 +116,18 @@ bool CBotInstrMethode::ExecuteVar(CBotVar* &pVar, CBotStack* &pj, CBotToken* pre
return pj->Return(pile1);
}
+ CBotStack* pile3 = nullptr;
+ if (m_exprRetVar != nullptr) // .func().member
+ {
+ pile3 = pile1->AddStack2();
+ if (pile3->GetState() == 1)
+ {
+ if (!m_exprRetVar->Execute(pile3)) return false;
+ pVar = nullptr;
+ return pj->Return(pile3);
+ }
+ }
+
if (pile1->IfStep()) return false;
CBotStack* pile2 = pile1->AddStack(); // for the next parameters
@@ -159,6 +181,15 @@ bool CBotInstrMethode::ExecuteVar(CBotVar* &pVar, CBotStack* &pj, CBotToken* pre
pResult, pile2, GetToken())) return false;
if (pRes != pResult) delete pRes;
+ if (m_exprRetVar != nullptr) // .func().member
+ {
+ pile3->SetCopyVar( pile2->GetVar() );
+ pile2->SetVar(nullptr);
+ pile3->SetState(1); // set call is done
+ pVar = nullptr;
+ return false; // go back to the top ^^^
+ }
+
pVar = nullptr; // does not return value for this
return pj->Return(pile2); // release the entire stack
}
@@ -172,6 +203,16 @@ void CBotInstrMethode::RestoreStateVar(CBotStack* &pile, bool bMain)
CBotStack* pile1 = pile->RestoreStack(this); // place for the copy of This
if (pile1 == nullptr) return;
+ if (m_exprRetVar != nullptr) // .func().member
+ {
+ CBotStack* pile3 = pile1->AddStack2();
+ if (pile3->GetState() == 1) // function call is done?
+ {
+ m_exprRetVar->RestoreState(pile3, bMain);
+ return;
+ }
+ }
+
CBotStack* pile2 = pile1->RestoreStack(); // and for the parameters coming
if (pile2 == nullptr) return;
diff --git a/src/CBot/CBotInstr/CBotInstrMethode.h b/src/CBot/CBotInstr/CBotInstrMethode.h
index 6c8d173..fb2b205 100644
--- a/src/CBot/CBotInstr/CBotInstrMethode.h
+++ b/src/CBot/CBotInstr/CBotInstrMethode.h
@@ -83,6 +83,10 @@ private:
long m_MethodeIdent;
//! Name of the class.
std::string m_className;
+
+ //! Instruction to return a member of the returned object.
+ CBotInstr* m_exprRetVar;
+
};
} // namespace CBot
diff --git a/src/CBot/CMakeLists.txt b/src/CBot/CMakeLists.txt
index b77d0bb..6ac4d13 100644
--- a/src/CBot/CMakeLists.txt
+++ b/src/CBot/CMakeLists.txt
@@ -54,6 +54,8 @@ set(SOURCES
CBotInstr/CBotExprLitNum.h
CBotInstr/CBotExprLitString.cpp
CBotInstr/CBotExprLitString.h
+ CBotInstr/CBotExprRetVar.cpp
+ CBotInstr/CBotExprRetVar.h
CBotInstr/CBotExprUnaire.cpp
CBotInstr/CBotExprUnaire.h
CBotInstr/CBotExprVar.cpp
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/colobot.git
More information about the Pkg-games-commits
mailing list