1 /* "CodeWorker":	a scripting language for parsing and generating text.
2 
3 Copyright (C) 1996-1997, 1999-2002 C�dric Lemaire
4 
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9 
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Lesser General Public License for more details.
14 
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 
19 To contact the author: codeworker@free.fr
20 */
21 
22 #ifdef WIN32
23 #pragma warning (disable : 4786)
24 #endif
25 
26 #include "UtlException.h"
27 #include "ScpStream.h"
28 
29 #include "DtaProject.h"
30 #include "GrfFunction.h"
31 #include "DtaClass.h"
32 #include "CppCompilerEnvironment.h"
33 #include "DtaScript.h" // declaration of 'GrfScriptBlock'
34 #include "GrfBlock.h"
35 
36 namespace CodeWorker {
~GrfBlock()37 	GrfBlock::~GrfBlock() {
38 		clear();
39 	}
40 
getScript() const41 	DtaScript* GrfBlock::getScript() const {
42 		const GrfBlock* pBlock = this;
43 		while (pBlock->_pScript == NULL) {
44 			pBlock = pBlock->getParent();
45 			if (pBlock == NULL) return NULL;
46 		}
47 		return pBlock->_pScript;
48 	}
49 
clear()50 	void GrfBlock::clear() {
51 		for (std::vector<GrfCommand*>::iterator i = _commands.begin(); i != _commands.end(); i++) {
52 			delete (*i);
53 		}
54 		if (_functions != NULL) {
55 			for (std::list<GrfCommand*>::iterator j = _functions->begin(); j != _functions->end(); j++) {
56 				GrfCommand* pFunction = *j;
57 				*j = NULL;
58 				delete pFunction;
59 			}
60 			delete _functions;
61 		}
62 		if (_classes != NULL) {
63 			for (std::list<DtaClass*>::iterator j = _classes->begin(); j != _classes->end(); j++) {
64 				DtaClass* pClass = *j;
65 				*j = NULL;
66 				delete pClass;
67 			}
68 			delete _classes;
69 		}
70 		delete _variables;
71 		_commands = std::vector<GrfCommand*>();
72 		_functions = NULL;
73 		_classes = NULL;
74 		_variables = NULL;
75 	}
76 
applyRecursively(APPLY_ON_COMMAND_FUNCTION apply)77 	void GrfBlock::applyRecursively(APPLY_ON_COMMAND_FUNCTION apply) {
78 		GrfCommand::applyRecursively(apply);
79 		for (std::vector<GrfCommand*>::iterator i = _commands.begin(); i != _commands.end(); i++) (*i)->applyRecursively(apply);
80 		if (_functions != NULL) {
81 			for (std::list<GrfCommand*>::iterator i = _functions->begin(); i != _functions->end(); i++) (*i)->applyRecursively(apply);
82 		}
83 	}
84 
add(GrfCommand * pCommand)85 	void GrfBlock::add(GrfCommand* pCommand) {
86 		pCommand->setParent(this);
87 		_commands.push_back(pCommand);
88 	}
89 
setCommand(int i,GrfCommand * pCommand)90 	void GrfBlock::setCommand(int i, GrfCommand* pCommand) {
91 		_commands[i] = pCommand;
92 		pCommand->setParent(this);
93 	}
94 
moveCommands(GrfBlock & destinationBlock)95 	void GrfBlock::moveCommands(GrfBlock& destinationBlock) {
96 		while (!_commands.empty()) {
97 			GrfCommand* pCommand =  _commands.back();
98 			pCommand->setParent(&destinationBlock);
99 			destinationBlock._commands.push_back(pCommand);
100 			_commands.pop_back();
101 		}
102 	}
103 
removeCommand(GrfCommand * pCommand)104 	bool GrfBlock::removeCommand(GrfCommand* pCommand) {
105 		for (std::vector<GrfCommand*>::iterator i = _commands.begin(); i != _commands.end(); i++) {
106 			if (*i == pCommand) {
107 				delete *i;
108 				_commands.erase(i);
109 				return true;
110 			}
111 		}
112 		return false;
113 	}
114 
addFunction(const std::string & sFunctionName,const std::string & sTemplate,bool bGenericKey)115 	GrfFunction* GrfBlock::addFunction(const std::string& sFunctionName, const std::string& sTemplate, bool bGenericKey) {
116 		GrfFunction* pFunction = getFunction(sFunctionName, sTemplate, bGenericKey);
117 		if (pFunction != NULL) return NULL;
118 		pFunction = new GrfFunction(this, sFunctionName, sTemplate, bGenericKey);
119 		if (_functions == NULL) _functions = new std::list<GrfCommand*>;
120 		_functions->push_back(pFunction);
121 		return pFunction;
122 	}
123 
addFunction(GrfFunction * pFunction)124 	GrfFunction* GrfBlock::addFunction(GrfFunction* pFunction) {
125 		if (getFunction(pFunction->getFunctionName(), pFunction->getTemplateInstantiation(), pFunction->isGenericKey()) != NULL) return NULL;
126 		if (_functions == NULL) _functions = new std::list<GrfCommand*>;
127 		_functions->push_back(pFunction);
128 		return pFunction;
129 	}
130 
getFunction(const std::string & sFunctionName,const std::string & sTemplate,bool bGenericKey) const131 	GrfFunction* GrfBlock::getFunction(const std::string& sFunctionName, const std::string& sTemplate, bool bGenericKey) const {
132 		if (_functions != NULL) {
133 			for (std::list<GrfCommand*>::const_iterator i = _functions->begin(); i != _functions->end(); ++i) {
134 				GrfFunction* pFunction = (GrfFunction*) (*i);
135 				if (pFunction->getName() == sFunctionName) {
136 					if (pFunction->isGenericKey()) {
137 						if (bGenericKey) {
138 							return pFunction;
139 						}
140 					} else if (pFunction->getTemplateInstantiation() == sTemplate) {
141 						return pFunction;
142 					}
143 				}
144 			}
145 		}
146 		if (getParent() != NULL) {
147 			return getParent()->getFunction(sFunctionName, sTemplate, bGenericKey);
148 		}
149 		return NULL;
150 	}
151 
removeFunction(const std::string & sFunctionName,const std::string & sTemplateInstantiation)152 	bool GrfBlock::removeFunction(const std::string& sFunctionName, const std::string& sTemplateInstantiation) {
153 		if (_functions != NULL) {
154 			for (std::list<GrfCommand*>::iterator i = _functions->begin(); i != _functions->end(); i++) {
155 				GrfFunction* pFunction = (GrfFunction*) (*i);
156 				if ((pFunction != NULL) && (pFunction->getName() == sFunctionName) && (pFunction->getTemplateInstantiation() == sTemplateInstantiation)) {
157 					delete *i;
158 					_functions->erase(i);
159 					return true;
160 				}
161 			}
162 		}
163 		return false;
164 	}
165 
removeGenericTemplateFunction(const std::string & sFunctionName)166 	bool GrfBlock::removeGenericTemplateFunction(const std::string& sFunctionName) {
167 		if (_functions != NULL) {
168 			for (std::list<GrfCommand*>::iterator i = _functions->begin(); i != _functions->end(); ++i) {
169 				GrfFunction* pFunction = (GrfFunction*) (*i);
170 				if ((pFunction != NULL) && (pFunction->getName() == sFunctionName) && pFunction->isGenericKey()) {
171 					delete *i;
172 					_functions->erase(i);
173 					return true;
174 				}
175 			}
176 		}
177 		return false;
178 	}
179 
moveFunctions(GrfBlock & destinationBlock)180 	void GrfBlock::moveFunctions(GrfBlock& destinationBlock) {
181 		if ((_functions != NULL) && !_functions->empty()) {
182 			if (destinationBlock._functions == NULL) destinationBlock._functions = new std::list<GrfCommand*>;
183 			do {
184 				GrfFunction* pFunction = (GrfFunction*) _functions->front();
185 				destinationBlock.removeFunction(pFunction->getName(), pFunction->getTemplateInstantiation());
186 				pFunction->setParent(&destinationBlock);
187 				destinationBlock._functions->push_back(pFunction);
188 				_functions->pop_front();
189 			} while (!_functions->empty());
190 			delete _functions;
191 			_functions = NULL;
192 		}
193 	}
194 
195 
addLocalVariable(const std::string & sVarName,EXPRESSION_TYPE varType)196 	bool GrfBlock::addLocalVariable(const std::string& sVarName, EXPRESSION_TYPE varType) {
197 		if (_variables == NULL) {
198 			_variables = new std::map<std::string, EXPRESSION_TYPE>;
199 		} else {
200 			std::map<std::string, EXPRESSION_TYPE>::const_iterator cursor = _variables->find(sVarName);
201 			if (cursor != _variables->end()) return false;
202 		}
203 		(*_variables)[sVarName] = varType;
204 		return true;
205 	}
206 
addBNFLocalVariable(const std::string & sVarName,EXPRESSION_TYPE varType)207 	bool GrfBlock::addBNFLocalVariable(const std::string& sVarName, EXPRESSION_TYPE varType) {
208 		if (getParent() != NULL) return getParent()->addBNFLocalVariable(sVarName, varType);
209 		return false;
210 	}
211 
removeVariable(const std::string & sVarName)212 	bool GrfBlock::removeVariable(const std::string& sVarName) {
213 		if (_variables == NULL) return false;
214 		std::map<std::string, EXPRESSION_TYPE>::iterator cursor = _variables->find(sVarName);
215 		if (cursor == _variables->end()) return false;
216 		_variables->erase(cursor);
217 		return true;
218 	}
219 
getLocalVariable(const std::string & sVarName) const220 	EXPRESSION_TYPE GrfBlock::getLocalVariable(const std::string& sVarName) const {
221 		if (_variables != NULL) {
222 			std::map<std::string, EXPRESSION_TYPE>::iterator cursor = _variables->find(sVarName);
223 			if (cursor != _variables->end()) return cursor->second;
224 		}
225 		return UNKNOWN_EXPRTYPE;
226 	}
227 
getVariable(const std::string & sVarName) const228 	EXPRESSION_TYPE GrfBlock::getVariable(const std::string& sVarName) const {
229 		EXPRESSION_TYPE result = getLocalVariable(sVarName);
230 		if (result == UNKNOWN_EXPRTYPE) {
231 			if (getParent() != NULL) return getParent()->getVariable(sVarName);
232 			if ((sVarName == "this") || (sVarName == "project") || (sVarName == "null") || (DtaProject::getInstance().getGlobalVariableType(sVarName) != UNKNOWN_EXPRTYPE)) return NODE_EXPRTYPE;
233 		}
234 		return result;
235 	}
236 
moveVariables(GrfBlock & destinationBlock)237 	void GrfBlock::moveVariables(GrfBlock& destinationBlock) {
238 		if ((_variables != NULL) && !_variables->empty()) {
239 			if (destinationBlock._variables == NULL) destinationBlock._variables = new std::map<std::string, EXPRESSION_TYPE>;
240 			for (std::map<std::string, EXPRESSION_TYPE>::const_iterator i = _variables->begin(); i != _variables->end(); ++i) {
241 				(*destinationBlock._variables)[i->first] = i->second;
242 			}
243 			delete _variables;
244 			_variables = NULL;
245 		}
246 	}
247 
248 
addClass(const std::string & sClassName)249 	DtaClass* GrfBlock::addClass(const std::string& sClassName) {
250 		DtaClass* pClass = getClass(sClassName);
251 		if (pClass != NULL) return NULL;
252 		pClass = new DtaClass(this, sClassName);
253 		if (_classes == NULL) _classes = new std::list<DtaClass*>;
254 		_classes->push_back(pClass);
255 		return pClass;
256 	}
257 
getClass(const std::string & sClassName) const258 	DtaClass* GrfBlock::getClass(const std::string& sClassName) const {
259 		if (_classes != NULL) {
260 			for (std::list<DtaClass*>::const_iterator i = _classes->begin(); i != _classes->end(); ++i) {
261 				DtaClass* pClass = *i;
262 				if (pClass->getName() == sClassName) {
263 					return pClass;
264 				}
265 			}
266 		}
267 		if (getParent() != NULL) return getParent()->getClass(sClassName);
268 		return NULL;
269 	}
270 
removeClass(const std::string & sClassName)271 	bool GrfBlock::removeClass(const std::string& sClassName) {
272 		if (_classes != NULL) {
273 			for (std::list<DtaClass*>::iterator i = _classes->begin(); i != _classes->end(); i++) {
274 				DtaClass* pClass = *i;
275 				if ((pClass != NULL) && (pClass->getName() == sClassName)) {
276 					delete *i;
277 					_classes->erase(i);
278 					return true;
279 				}
280 			}
281 		}
282 		return false;
283 	}
284 
moveClasses(GrfBlock & destinationBlock)285 	void GrfBlock::moveClasses(GrfBlock& destinationBlock) {
286 		if ((_classes != NULL) && !_classes->empty()) {
287 			if (destinationBlock._classes == NULL) destinationBlock._classes = new std::list<DtaClass*>;
288 			do {
289 				DtaClass* pClass = _classes->front();
290 				destinationBlock.removeClass(pClass->getName());
291 				pClass->setBlock(&destinationBlock);
292 				destinationBlock._classes->push_back(pClass);
293 				_classes->pop_front();
294 			} while (!_classes->empty());
295 			delete _classes;
296 			_classes = NULL;
297 		}
298 	}
299 
addTargetLanguageTypeSpecifier(const std::string & sTypeSpec)300 	DtaTargetLanguageTypeSpecifier* GrfBlock::addTargetLanguageTypeSpecifier(const std::string& sTypeSpec) {
301 		DtaTargetLanguageTypeSpecifier* pClass = getTargetLanguageTypeSpecifier(sTypeSpec);
302 		if (pClass != NULL) return NULL;
303 		pClass = new DtaTargetLanguageTypeSpecifier(this, sTypeSpec);
304 		if (_classes == NULL) _classes = new std::list<DtaClass*>;
305 		_classes->push_back(pClass);
306 		return pClass;
307 	}
308 
getTargetLanguageTypeSpecifier(const std::string & sTypeSpec)309 	DtaTargetLanguageTypeSpecifier* GrfBlock::getTargetLanguageTypeSpecifier(const std::string& sTypeSpec) {
310 		if (_classes != NULL) {
311 			for (std::list<DtaClass*>::const_iterator i = _classes->begin(); i != _classes->end(); ++i) {
312 				DtaClass* pClass = *i;
313 				if (pClass->getName() == sTypeSpec) {
314 					DtaTargetLanguageTypeSpecifier* pTypeSpec = dynamic_cast<DtaTargetLanguageTypeSpecifier*>(pClass);
315 					return pTypeSpec;
316 				}
317 			}
318 		}
319 		if (getParent() != NULL) return getParent()->getTargetLanguageTypeSpecifier(sTypeSpec);
320 		return NULL;
321 	}
322 
323 
executeInternal(DtaScriptVariable & visibility)324 	SEQUENCE_INTERRUPTION_LIST GrfBlock::executeInternal(DtaScriptVariable& visibility) {
325 		SEQUENCE_INTERRUPTION_LIST result = NO_INTERRUPTION;
326 		if (hasLocalVariables()) {
327 			DtaScriptVariable localVariables(&visibility, "##stack## block");
328 			for (std::vector<GrfCommand*>::iterator i = _commands.begin(); i != _commands.end(); i++)
329 				if ((result = (*i)->execute(localVariables)) != NO_INTERRUPTION) break;
330 		} else {
331 			for (std::vector<GrfCommand*>::iterator i = _commands.begin(); i != _commands.end(); i++)
332 				if ((result = (*i)->execute(visibility)) != NO_INTERRUPTION) break;
333 		}
334 		return result;
335 	}
336 
executeAt(DtaScriptVariable & visibility,int iPosition)337 	SEQUENCE_INTERRUPTION_LIST GrfBlock::executeAt(DtaScriptVariable& visibility, int iPosition) {
338 		SEQUENCE_INTERRUPTION_LIST result = NO_INTERRUPTION;
339 		if (hasLocalVariables()) {
340 			DtaScriptVariable localVariables(&visibility, "##stack## block");
341 			for (std::vector<GrfCommand*>::iterator i = _commands.begin() + iPosition; i != _commands.end(); i++)
342 				if ((result = (*i)->execute(localVariables)) != NO_INTERRUPTION) break;
343 		} else {
344 			for (std::vector<GrfCommand*>::iterator i = _commands.begin() + iPosition; i != _commands.end(); i++)
345 				if ((result = (*i)->execute(visibility)) != NO_INTERRUPTION) break;
346 		}
347 		return result;
348 	}
349 
executeInto(DtaScriptVariable & visibility,int iStart,int iEnd)350 	SEQUENCE_INTERRUPTION_LIST GrfBlock::executeInto(DtaScriptVariable& visibility, int iStart, int iEnd) {
351 		SEQUENCE_INTERRUPTION_LIST result = NO_INTERRUPTION;
352 		for (int i = iStart; i <= iEnd; i++) {
353 			result = _commands[i]->execute(visibility);
354 			if (result != NO_INTERRUPTION) break;
355 		}
356 		return result;
357 	}
358 
compileCpp(CppCompilerEnvironment & theCompilerEnvironment) const359 	void GrfBlock::compileCpp(CppCompilerEnvironment& theCompilerEnvironment) const {
360 		if ((_functions != NULL) && !_functions->empty() && (dynamic_cast<const GrfScriptBlock*>(this) == 0)) {
361 			std::string sMessage = "\"";
362 			if (this->_sParsingFilePtr != 0) {
363 				sMessage += this->_sParsingFilePtr;
364 			} else {
365 				sMessage += theCompilerEnvironment.getCurrentScriptSession()._sFilename;
366 			}
367 			sMessage += "\": C++ generation doesn't admit a function definition into a block of instructions;\nplease move the following one to the primary scope of the script:\n";
368 			for (std::list<GrfCommand*>::const_iterator i = _functions->begin(); i != _functions->end(); i++) {
369 				sMessage += "\t- " + dynamic_cast<GrfFunction*>(*i)->getSignature() + "\n";
370 			}
371 			throw UtlException(sMessage);
372 		}
373 		bool bBrackets = theCompilerEnvironment.bracketsToNextBlock();
374 		bool bCarriage = theCompilerEnvironment.carriageReturnAfterBlock();
375 		if (!bCarriage) theCompilerEnvironment.carriageReturnAfterBlock(true);
376 		if (bBrackets) {
377 			theCompilerEnvironment.incrementIndentation();
378 			CW_BODY_STREAM << "{";
379 			if (!_commands.empty()) CW_BODY_ENDL;
380 		} else {
381 			theCompilerEnvironment.bracketsToNextBlock(true);
382 		}
383 		std::vector<GrfCommand*>::const_iterator i;
384 		for (i = _commands.begin(); i != _commands.end(); i++) {
385 			(*i)->compileCpp(theCompilerEnvironment);
386 		}
387 		if (bBrackets) {
388 			theCompilerEnvironment.decrementIndentation();
389 			CW_BODY_INDENT << "}";
390 			if (bCarriage) CW_BODY_ENDL;
391 		}
392 	}
393 
compileCppFunctions(CppCompilerEnvironment & theCompilerEnvironment) const394 	void GrfBlock::compileCppFunctions(CppCompilerEnvironment& theCompilerEnvironment) const {
395 		if (_functions != NULL) {
396 			for (std::list<GrfCommand*>::const_iterator i = _functions->begin(); i != _functions->end(); i++) {
397 				theCompilerEnvironment.newFunction(dynamic_cast<GrfFunction*>(*i));
398 			}
399 			for (std::list<GrfCommand*>::const_iterator j = _functions->begin(); j != _functions->end(); j++) {
400 				(*j)->compileCpp(theCompilerEnvironment);
401 			}
402 		}
403 	}
404 
compileCppBNFSequence(CppCompilerEnvironment & theCompilerEnvironment) const405 	void GrfBlock::compileCppBNFSequence(CppCompilerEnvironment& theCompilerEnvironment) const {
406 		std::vector<GrfCommand*>::const_iterator i = getCommands().begin();
407 		for (;;) {
408 			(*i)->compileCpp(theCompilerEnvironment);
409 			i++;
410 			if (i == getCommands().end()) break;
411 			CW_BODY_INDENT << "if (_compilerClauseSuccess) {";CW_BODY_ENDL;
412 			theCompilerEnvironment.incrementIndentation();
413 		}
414 		int j = getNbCommands() - 1;
415 		while (j > 0) {
416 			theCompilerEnvironment.decrementIndentation();
417 			CW_BODY_INDENT << "}";CW_BODY_ENDL;
418 			j--;
419 		}
420 	}
421 
compileCppBetween(CppCompilerEnvironment & theCompilerEnvironment,int iStart,int iEnd) const422 	void GrfBlock::compileCppBetween(CppCompilerEnvironment& theCompilerEnvironment, int iStart, int iEnd) const {
423 		std::vector<GrfCommand*>::const_iterator i;
424 		std::vector<GrfCommand*>::const_iterator endIterator = _commands.begin() + iEnd;
425 		for (i = _commands.begin() + iStart; i != endIterator; i++) {
426 			(*i)->compileCpp(theCompilerEnvironment);
427 		}
428 	}
429 
compileCppAt(CppCompilerEnvironment & theCompilerEnvironment,int iStart) const430 	void GrfBlock::compileCppAt(CppCompilerEnvironment& theCompilerEnvironment, int iStart) const {
431 		std::vector<GrfCommand*>::const_iterator i;
432 		for (i = _commands.begin() + iStart; i != _commands.end(); i++) {
433 			(*i)->compileCpp(theCompilerEnvironment);
434 		}
435 	}
436 }
437