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