1 /*
2 * This file is part of the Colobot: Gold Edition source code
3 * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
4 * http://epsitec.ch; http://colobot.info; http://github.com/colobot
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see http://gnu.org/licenses
18 */
19
20 #include "CBot/CBotInstr/CBotDefString.h"
21
22 #include "CBot/CBotInstr/CBotLeftExprVar.h"
23 #include "CBot/CBotInstr/CBotDefArray.h"
24 #include "CBot/CBotInstr/CBotTwoOpExpr.h"
25
26 #include "CBot/CBotStack.h"
27 #include "CBot/CBotCStack.h"
28
29 #include "CBot/CBotVar/CBotVar.h"
30
31 namespace CBot
32 {
33
34 ////////////////////////////////////////////////////////////////////////////////
CBotDefString()35 CBotDefString::CBotDefString()
36 {
37 m_var = nullptr;
38 m_expr = nullptr;
39 }
40
41 ////////////////////////////////////////////////////////////////////////////////
~CBotDefString()42 CBotDefString::~CBotDefString()
43 {
44 delete m_var;
45 delete m_expr;
46 }
47
48 ////////////////////////////////////////////////////////////////////////////////
Compile(CBotToken * & p,CBotCStack * pStack,bool cont,bool noskip)49 CBotInstr* CBotDefString::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, bool noskip)
50 {
51 CBotToken* pp = cont ? nullptr : p;
52
53 if (!cont && !IsOfType(p, ID_STRING)) return nullptr;
54
55 CBotDefString* inst = static_cast<CBotDefString*>(CompileArray(p, pStack, CBotTypString));
56 if (inst != nullptr || !pStack->IsOk()) return inst;
57
58 CBotCStack* pStk = pStack->TokenStack(pp);
59
60 inst = new CBotDefString();
61
62 inst->m_expr = nullptr;
63
64 CBotToken* vartoken = p;
65 CBotVar* var = nullptr;
66 inst->SetToken(vartoken);
67
68 if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )))
69 {
70 (static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = CBotTypString;
71 if (pStk->CheckVarLocal(vartoken))
72 {
73 pStk->SetStartError(vartoken->GetStart());
74 pStk->SetError(CBotErrRedefVar, vartoken->GetEnd());
75 goto error;
76 }
77
78 if (IsOfType(p, ID_OPBRK))
79 {
80 delete inst; // type is not CBotDefString
81 p = vartoken; // returns the variable name
82
83 // compiles an array declaration
84
85 CBotInstr* inst2 = CBotDefArray::Compile(p, pStk, CBotTypString);
86
87 inst = static_cast<CBotDefString*>(inst2);
88 goto suite; // no assignment, variable already created
89 }
90
91 if (IsOfType(p, ID_ASS))
92 {
93 pStk->SetStartError(p->GetStart());
94 if ( IsOfType(p, ID_SEP) )
95 {
96 pStk->SetError(CBotErrNoExpression, p->GetStart());
97 goto error;
98 }
99 if (nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )))
100 {
101 goto error;
102 }
103 /* if (!pStk->GetTypResult().Eq(CBotTypString)) // type compatible ?
104 {
105 pStk->SetError(CBotErrBadType1, p->GetStart());
106 goto error;
107 }*/
108 }
109
110 var = CBotVar::Create(*vartoken, CBotTypString);
111 var->SetInit(inst->m_expr != nullptr ? CBotVar::InitType::DEF : CBotVar::InitType::UNDEF);
112 var->SetUniqNum(
113 (static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
114 pStack->AddVar(var);
115 suite:
116 if (pStk->IsOk() && IsOfType(p, ID_COMMA))
117 {
118 if (nullptr != ( inst->m_next2b = CBotDefString::Compile(p, pStk, true, noskip)))
119 {
120 return pStack->Return(inst, pStk);
121 }
122 }
123
124 if (noskip || IsOfType(p, ID_SEP))
125 {
126 return pStack->Return(inst, pStk);
127 }
128
129 pStk->SetError(CBotErrNoTerminator, p->GetStart());
130 }
131
132 error:
133 delete inst;
134 return pStack->Return(nullptr, pStk);
135 }
136
137 ////////////////////////////////////////////////////////////////////////////////
Execute(CBotStack * & pj)138 bool CBotDefString::Execute(CBotStack* &pj)
139 {
140 CBotStack* pile = pj->AddStack(this);
141
142 if ( pile->GetState()==0)
143 {
144 if (m_expr && !m_expr->Execute(pile)) return false;
145 m_var->Execute(pile);
146
147 if (!pile->SetState(1)) return false;
148 }
149
150 if (pile->IfStep()) return false;
151
152 if ( m_next2b &&
153 !m_next2b->Execute(pile)) return false;
154
155 return pj->Return(pile);
156 }
157
158 ////////////////////////////////////////////////////////////////////////////////
RestoreState(CBotStack * & pj,bool bMain)159 void CBotDefString::RestoreState(CBotStack* &pj, bool bMain)
160 {
161 CBotStack* pile = pj;
162
163 if (bMain)
164 {
165 pile = pj->RestoreStack(this);
166 if (pile == nullptr) return;
167
168 if ( pile->GetState()==0)
169 {
170 if (m_expr) m_expr->RestoreState(pile, bMain);
171 return;
172 }
173 }
174
175 m_var->RestoreState(pile, bMain);
176
177 if (m_next2b)
178 m_next2b->RestoreState(pile, bMain);
179 }
180
GetDebugLinks()181 std::map<std::string, CBotInstr*> CBotDefString::GetDebugLinks()
182 {
183 auto links = CBotInstr::GetDebugLinks();
184 links["m_var"] = m_var;
185 links["m_expr"] = m_expr;
186 return links;
187 }
188
189 } // namespace CBot
190