ERMInterpreter.cpp 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589
  1. #include "ERMInterpreter.h"
  2. #include <boost/filesystem.hpp>
  3. #include <boost/algorithm/string.hpp>
  4. #include <boost/foreach.hpp>
  5. #include <boost/lexical_cast.hpp>
  6. #include <boost/assign/std/vector.hpp> // for 'operator+=()'
  7. /*
  8. * ERMInterpreter.cpp, part of VCMI engine
  9. *
  10. * Authors: listed in file AUTHORS in main folder
  11. *
  12. * License: GNU General Public License v2.0 or later
  13. * Full text of license available in license.txt file, in main folder
  14. *
  15. */
  16. namespace spirit = boost::spirit;
  17. using namespace VERMInterpreter;
  18. using namespace boost::assign;
  19. namespace ERMPrinter
  20. {
  21. //console printer
  22. using namespace ERM;
  23. struct VarPrinterVisitor : boost::static_visitor<>
  24. {
  25. void operator()(TVarExpNotMacro const& val) const
  26. {
  27. tlog2 << val.varsym;
  28. if(val.val.is_initialized())
  29. {
  30. tlog2 << val.val.get();
  31. }
  32. }
  33. void operator()(TMacroUsage const& val) const
  34. {
  35. tlog2 << "$" << val.macro << "&";
  36. }
  37. };
  38. void varPrinter(const TVarExp & var)
  39. {
  40. boost::apply_visitor(VarPrinterVisitor(), var);
  41. }
  42. struct IExpPrinterVisitor : boost::static_visitor<>
  43. {
  44. void operator()(int const & constant) const
  45. {
  46. tlog2 << constant;
  47. }
  48. void operator()(TVarExp const & var) const
  49. {
  50. varPrinter(var);
  51. }
  52. };
  53. void iexpPrinter(const TIexp & exp)
  54. {
  55. boost::apply_visitor(IExpPrinterVisitor(), exp);
  56. }
  57. struct IdentifierPrinterVisitor : boost::static_visitor<>
  58. {
  59. void operator()(TIexp const& iexp) const
  60. {
  61. iexpPrinter(iexp);
  62. }
  63. void operator()(TArithmeticOp const& arop) const
  64. {
  65. iexpPrinter(arop.lhs);
  66. tlog2 << " " << arop.opcode << " ";
  67. iexpPrinter(arop.rhs);
  68. }
  69. };
  70. void identifierPrinter(const boost::optional<Tidentifier> & id)
  71. {
  72. if(id.is_initialized())
  73. {
  74. tlog2 << "identifier: ";
  75. BOOST_FOREACH(TIdentifierInternal x, id.get())
  76. {
  77. tlog2 << "#";
  78. boost::apply_visitor(IdentifierPrinterVisitor(), x);
  79. }
  80. }
  81. }
  82. struct ConditionCondPrinterVisitor : boost::static_visitor<>
  83. {
  84. void operator()(TComparison const& cmp) const
  85. {
  86. iexpPrinter(cmp.lhs);
  87. tlog2 << " " << cmp.compSign << " ";
  88. iexpPrinter(cmp.rhs);
  89. }
  90. void operator()(int const& flag) const
  91. {
  92. tlog2 << "condflag " << flag;
  93. }
  94. };
  95. void conditionPrinter(const boost::optional<Tcondition> & cond)
  96. {
  97. if(cond.is_initialized())
  98. {
  99. Tcondition condp = cond.get();
  100. tlog2 << " condition: ";
  101. boost::apply_visitor(ConditionCondPrinterVisitor(), condp.cond);
  102. tlog2 << " cond type: " << condp.ctype;
  103. //recursive call
  104. if(condp.rhs.is_initialized())
  105. {
  106. tlog2 << "rhs: ";
  107. boost::optional<Tcondition> rhsc = condp.rhs.get().get();
  108. conditionPrinter(rhsc);
  109. }
  110. else
  111. {
  112. tlog2 << "no rhs; ";
  113. }
  114. }
  115. }
  116. struct BodyVarpPrinterVisitor : boost::static_visitor<>
  117. {
  118. void operator()(TVarExpNotMacro const& cmp) const
  119. {
  120. if(cmp.questionMark.is_initialized())
  121. {
  122. tlog2 << cmp.questionMark.get();
  123. }
  124. if(cmp.val.is_initialized())
  125. {
  126. tlog2 << "val:" << cmp.val.get();
  127. }
  128. tlog2 << "varsym: |" << cmp.varsym << "|";
  129. }
  130. void operator()(TQMacroUsage const& cmp) const
  131. {
  132. tlog2 << "???$$" << cmp.qmacro << "$$";
  133. }
  134. };
  135. struct BodyOptionItemPrinterVisitor : boost::static_visitor<>
  136. {
  137. void operator()(TVarConcatString const& cmp) const
  138. {
  139. tlog2 << "+concat\"";
  140. varPrinter(cmp.var);
  141. tlog2 << " with " << cmp.string.str;
  142. }
  143. void operator()(TStringConstant const& cmp) const
  144. {
  145. tlog2 << " \"" << cmp.str << "\" ";
  146. }
  147. void operator()(TCurriedString const& cmp) const
  148. {
  149. tlog2 << "cs: ";
  150. iexpPrinter(cmp.iexp);
  151. tlog2 << " '" << cmp.string.str << "' ";
  152. }
  153. void operator()(TSemiCompare const& cmp) const
  154. {
  155. tlog2 << cmp.compSign << "; rhs: ";
  156. iexpPrinter(cmp.rhs);
  157. }
  158. void operator()(TMacroUsage const& cmp) const
  159. {
  160. tlog2 << "$$" << cmp.macro << "$$";
  161. }
  162. void operator()(TMacroDef const& cmp) const
  163. {
  164. tlog2 << "@@" << cmp.macro << "@@";
  165. }
  166. void operator()(TIexp const& cmp) const
  167. {
  168. iexpPrinter(cmp);
  169. }
  170. void operator()(TVarpExp const& cmp) const
  171. {
  172. tlog2 << "varp";
  173. boost::apply_visitor(BodyVarpPrinterVisitor(), cmp.var);
  174. }
  175. void operator()(spirit::unused_type const& cmp) const
  176. {
  177. tlog2 << "nothing";
  178. }
  179. };
  180. struct BodyOptionVisitor : boost::static_visitor<>
  181. {
  182. void operator()(TVRLogic const& cmp) const
  183. {
  184. tlog2 << cmp.opcode << " ";
  185. iexpPrinter(cmp.var);
  186. }
  187. void operator()(TVRArithmetic const& cmp) const
  188. {
  189. tlog2 << cmp.opcode << " ";
  190. iexpPrinter(cmp.rhs);
  191. }
  192. void operator()(TNormalBodyOption const& cmp) const
  193. {
  194. tlog2 << cmp.optionCode << "~";
  195. BOOST_FOREACH(TBodyOptionItem optList, cmp.params)
  196. {
  197. boost::apply_visitor(BodyOptionItemPrinterVisitor(), optList);
  198. }
  199. }
  200. };
  201. void bodyPrinter(const Tbody & body)
  202. {
  203. tlog2 << " body items: ";
  204. BOOST_FOREACH(TBodyOption bi, body)
  205. {
  206. tlog2 << " (";
  207. apply_visitor(BodyOptionVisitor(), bi);
  208. tlog2 << ") ";
  209. }
  210. }
  211. struct CommandPrinterVisitor : boost::static_visitor<>
  212. {
  213. void operator()(Ttrigger const& trig) const
  214. {
  215. tlog2 << "trigger: " << trig.name << " ";
  216. identifierPrinter(trig.identifier);
  217. conditionPrinter(trig.condition);
  218. }
  219. void operator()(Tinstruction const& trig) const
  220. {
  221. tlog2 << "instruction: " << trig.name << " ";
  222. identifierPrinter(trig.identifier);
  223. conditionPrinter(trig.condition);
  224. bodyPrinter(trig.body);
  225. }
  226. void operator()(Treceiver const& trig) const
  227. {
  228. tlog2 << "receiver: " << trig.name << " ";
  229. identifierPrinter(trig.identifier);
  230. conditionPrinter(trig.condition);
  231. if(trig.body.is_initialized())
  232. bodyPrinter(trig.body.get());
  233. }
  234. void operator()(TPostTrigger const& trig) const
  235. {
  236. tlog2 << "post trigger: " << trig.name << " ";
  237. identifierPrinter(trig.identifier);
  238. conditionPrinter(trig.condition);
  239. }
  240. };
  241. struct LinePrinterVisitor : boost::static_visitor<>
  242. {
  243. void operator()(Tcommand const& cmd) const
  244. {
  245. CommandPrinterVisitor un;
  246. boost::apply_visitor(un, cmd.cmd);
  247. std::cout << "Line comment: " << cmd.comment << std::endl;
  248. }
  249. void operator()(std::string const& comment) const
  250. {
  251. }
  252. void operator()(spirit::unused_type const& nothing) const
  253. {
  254. }
  255. };
  256. void printERM(const TERMline & ast)
  257. {
  258. tlog2 << "";
  259. boost::apply_visitor(LinePrinterVisitor(), ast);
  260. }
  261. void printTVExp(const TVExp & exp);
  262. struct VOptionPrinterVisitor : boost::static_visitor<>
  263. {
  264. void operator()(TVExp const& cmd) const
  265. {
  266. printTVExp(cmd);
  267. }
  268. void operator()(TSymbol const& cmd) const
  269. {
  270. BOOST_FOREACH(TVModifier mod, cmd.symModifier)
  271. {
  272. tlog2 << mod << " ";
  273. }
  274. tlog2 << cmd.sym;
  275. }
  276. void operator()(char const& cmd) const
  277. {
  278. tlog2 << "'" << cmd << "'";
  279. }
  280. void operator()(int const& cmd) const
  281. {
  282. tlog2 << cmd;
  283. }
  284. void operator()(double const& cmd) const
  285. {
  286. tlog2 << cmd;
  287. }
  288. void operator()(TERMline const& cmd) const
  289. {
  290. printERM(cmd);
  291. }
  292. void operator()(TStringConstant const& cmd) const
  293. {
  294. tlog2 << "^" << cmd.str << "^";
  295. }
  296. };
  297. void printTVExp(const TVExp & exp)
  298. {
  299. BOOST_FOREACH(TVModifier mod, exp.modifier)
  300. {
  301. tlog2 << mod << " ";
  302. }
  303. tlog2 << "[ ";
  304. BOOST_FOREACH(TVOption opt, exp.children)
  305. {
  306. boost::apply_visitor(VOptionPrinterVisitor(), opt);
  307. tlog2 << " ";
  308. }
  309. tlog2 << "]";
  310. }
  311. struct TLPrinterVisitor : boost::static_visitor<>
  312. {
  313. void operator()(TVExp const& cmd) const
  314. {
  315. printTVExp(cmd);
  316. }
  317. void operator()(TERMline const& cmd) const
  318. {
  319. printERM(cmd);
  320. }
  321. };
  322. void printAST(const TLine & ast)
  323. {
  324. boost::apply_visitor(TLPrinterVisitor(), ast);
  325. tlog2 << std::endl;
  326. }
  327. }
  328. void ERMInterpreter::scanForScripts()
  329. {
  330. using namespace boost::filesystem;
  331. //parser checking
  332. if(!exists(DATA_DIR "/Data/s/"))
  333. {
  334. tlog3 << "Warning: Folder " DATA_DIR "/Data/s/ doesn't exist!\n";
  335. return;
  336. }
  337. directory_iterator enddir;
  338. for (directory_iterator dir(DATA_DIR "/Data/s"); dir!=enddir; dir++)
  339. {
  340. if(is_regular(dir->status()))
  341. {
  342. std::string name = dir->path().leaf();
  343. if( boost::algorithm::ends_with(name, ".erm") ||
  344. boost::algorithm::ends_with(name, ".verm") )
  345. {
  346. ERMParser ep(dir->path().string());
  347. FileInfo * finfo = new FileInfo;
  348. finfo->filename = dir->path().string();
  349. std::vector<ERM::TLine> buf = ep.parseFile();
  350. finfo->length = buf.size();
  351. files.push_back(finfo);
  352. for(int g=0; g<buf.size(); ++g)
  353. {
  354. scripts[LinePointer(finfo, g)] = buf[g];
  355. }
  356. }
  357. }
  358. }
  359. }
  360. void ERMInterpreter::printScripts( EPrintMode mode /*= EPrintMode::ALL*/ )
  361. {
  362. std::map< LinePointer, ERM::TLine >::const_iterator prevIt;
  363. for(std::map< LinePointer, ERM::TLine >::const_iterator it = scripts.begin(); it != scripts.end(); ++it)
  364. {
  365. if(it == scripts.begin() || it->first.file != prevIt->first.file)
  366. {
  367. tlog2 << "----------------- script " << it->first.file->filename << " ------------------\n";
  368. }
  369. ERMPrinter::printAST(it->second);
  370. prevIt = it;
  371. }
  372. }
  373. struct ScriptScanner : boost::static_visitor<>
  374. {
  375. ERMInterpreter * interpreter;
  376. LinePointer lp;
  377. ScriptScanner(ERMInterpreter * interpr, const LinePointer & _lp) : interpreter(interpr), lp(_lp)
  378. {}
  379. void operator()(TVExp const& cmd) const
  380. {
  381. //
  382. }
  383. void operator()(TERMline const& cmd) const
  384. {
  385. if(cmd.which() == 0) //TCommand
  386. {
  387. Tcommand tcmd = boost::get<Tcommand>(cmd);
  388. switch (tcmd.cmd.which())
  389. {
  390. case 0: //trigger
  391. {
  392. Trigger trig;
  393. trig.line = lp;
  394. interpreter->triggers[ TriggerType(boost::get<ERM::Ttrigger>(tcmd.cmd).name) ].push_back(trig);
  395. }
  396. break;
  397. case 3: //post trigger
  398. {
  399. Trigger trig;
  400. trig.line = lp;
  401. interpreter->postTriggers[ TriggerType(boost::get<ERM::TPostTrigger>(tcmd.cmd).name) ].push_back(trig);
  402. }
  403. break;
  404. default:
  405. break;
  406. }
  407. }
  408. }
  409. };
  410. void ERMInterpreter::scanScripts()
  411. {
  412. for(std::map< LinePointer, ERM::TLine >::const_iterator it = scripts.begin(); it != scripts.end(); ++it)
  413. {
  414. boost::apply_visitor(ScriptScanner(this, it->first), it->second);
  415. }
  416. }
  417. ERMInterpreter::ERMInterpreter()
  418. {
  419. curFunc = NULL;
  420. curTrigger = NULL;
  421. globalEnv = new Environment();
  422. }
  423. void ERMInterpreter::executeTrigger( Trigger & trig )
  424. {
  425. //skip the first line
  426. LinePointer lp = trig.line;
  427. ++lp;
  428. for(; lp.isValid(); ++lp)
  429. {
  430. ERM::TLine curLine = retrieveLine(lp);
  431. if(isATrigger(curLine))
  432. break;
  433. executeLine(lp);
  434. }
  435. }
  436. bool ERMInterpreter::isATrigger( const ERM::TLine & line )
  437. {
  438. switch(line.which())
  439. {
  440. case 0: //v-exp
  441. {
  442. TVExp vexp = boost::get<TVExp>(line);
  443. if(vexp.children.size() == 0)
  444. return false;
  445. switch (getExpType(vexp.children[0]))
  446. {
  447. case SYMBOL:
  448. {
  449. //TODO: what about sym modifiers?
  450. //TOOD: macros?
  451. ERM::TSymbol sym = boost::get<ERM::TSymbol>(vexp.children[0]);
  452. return sym.sym == triggerSymbol || sym.sym == postTriggerSymbol;
  453. }
  454. break;
  455. case TCMD:
  456. return isCMDATrigger( boost::get<ERM::Tcommand>(vexp.children[0]) );
  457. break;
  458. default:
  459. return false;
  460. break;
  461. }
  462. }
  463. break;
  464. case 1: //erm
  465. {
  466. TERMline line = boost::get<TERMline>(line);
  467. switch(line.which())
  468. {
  469. case 0: //tcmd
  470. return isCMDATrigger( boost::get<ERM::Tcommand>(line) );
  471. break;
  472. default:
  473. return false;
  474. break;
  475. }
  476. }
  477. break;
  478. default:
  479. assert(0); //it should never happen
  480. break;
  481. }
  482. assert(0);
  483. }
  484. ERM::EVOtions ERMInterpreter::getExpType( const ERM::TVOption & opt )
  485. {
  486. //MAINTENANCE: keep it correct!
  487. return static_cast<ERM::EVOtions>(opt.which());
  488. }
  489. bool ERMInterpreter::isCMDATrigger( const ERM::Tcommand & cmd )
  490. {
  491. switch (cmd.cmd.which())
  492. {
  493. case 0: //trigger
  494. case 3: //post trigger
  495. return true;
  496. break;
  497. default:
  498. return false;
  499. break;
  500. }
  501. }
  502. ERM::TLine ERMInterpreter::retrieveLine( LinePointer linePtr ) const
  503. {
  504. return *scripts.find(linePtr);
  505. }
  506. /////////
  507. //code execution
  508. struct VRPerformer;
  509. struct VR_SPerformer : boost::static_visitor<>
  510. {
  511. VRPerformer & owner;
  512. explicit VR_SPerformer(VRPerformer & _owner);
  513. void operator()(TVarConcatString const& cmp) const;
  514. void operator()(TStringConstant const& cmp) const;
  515. void operator()(TCurriedString const& cmp) const;
  516. void operator()(TSemiCompare const& cmp) const;
  517. void operator()(TMacroUsage const& cmp) const;
  518. void operator()(TMacroDef const& cmp) const;
  519. void operator()(TIexp const& cmp) const;
  520. void operator()(TVarpExp const& cmp) const;
  521. void operator()(spirit::unused_type const& cmp) const;
  522. };
  523. struct VRPerformer : boost::static_visitor<>
  524. {
  525. ERMInterpreter * interp;
  526. IexpValStr identifier;
  527. VRPerformer(ERMInterpreter * _interpr, IexpValStr ident) : interp(_interpr), identifier(ident)
  528. {}
  529. void operator()(TVRLogic const& trig) const
  530. {
  531. int valr = interp->getIexp(trig.var).getInt();
  532. switch (trig.opcode)
  533. {
  534. case '&':
  535. const_cast<VRPerformer*>(this)->identifier.setTo(identifier.getInt() & valr);
  536. break;
  537. case '|':
  538. const_cast<VRPerformer*>(this)->identifier.setTo(identifier.getInt() | valr);
  539. break;
  540. case 'X':
  541. const_cast<VRPerformer*>(this)->identifier.setTo(identifier.getInt() ^ valr);
  542. break;
  543. default:
  544. throw EInterpreterError("Wrong opcode in VR logic expression!");
  545. break;
  546. }
  547. }
  548. void operator()(TVRArithmetic const& trig) const
  549. {
  550. IexpValStr rhs = interp->getIexp(trig.rhs);
  551. switch (trig.opcode)
  552. {
  553. case '+':
  554. const_cast<VRPerformer*>(this)->identifier += rhs;
  555. break;
  556. case '-':
  557. const_cast<VRPerformer*>(this)->identifier -= rhs;
  558. break;
  559. case '*':
  560. const_cast<VRPerformer*>(this)->identifier *= rhs;
  561. break;
  562. case ':':
  563. const_cast<VRPerformer*>(this)->identifier /= rhs;
  564. break;
  565. case '%':
  566. const_cast<VRPerformer*>(this)->identifier %= rhs;
  567. break;
  568. default:
  569. throw EInterpreterError("Wrong opcode in VR arithmetic!");
  570. break;
  571. }
  572. }
  573. void operator()(TNormalBodyOption const& trig) const
  574. {
  575. switch(trig.optionCode)
  576. {
  577. case 'S': //setting variable
  578. {
  579. if(trig.params.size() == 1)
  580. {
  581. ERM::TBodyOptionItem boi = trig.params[0];
  582. boost::apply_visitor(VR_SPerformer(*const_cast<VRPerformer*>(this)), boi);
  583. }
  584. else
  585. throw EScriptExecError("VR receiver S option takes exactly 1 parameter!");
  586. }
  587. break;
  588. default:
  589. //not supported or not allowed
  590. break;
  591. }
  592. }
  593. };
  594. VR_SPerformer::VR_SPerformer(VRPerformer & _owner) : owner(_owner)
  595. {}
  596. void VR_SPerformer::operator()(ERM::TIexp const& trig) const
  597. {
  598. owner.identifier.setTo(owner.interp->getIexp(trig));
  599. }
  600. void VR_SPerformer::operator()(TVarConcatString const& cmp) const
  601. {
  602. throw EScriptExecError("String concatenation not allowed in VR S");
  603. }
  604. void VR_SPerformer::operator()(TStringConstant const& cmp) const
  605. {
  606. owner.identifier.setTo(cmp.str);
  607. }
  608. void VR_SPerformer::operator()(TCurriedString const& cmp) const
  609. {
  610. throw EScriptExecError("Curried string not allowed in VR S");
  611. }
  612. void VR_SPerformer::operator()(TSemiCompare const& cmp) const
  613. {
  614. throw EScriptExecError("Incomplete comparison not allowed in VR S");
  615. }
  616. void VR_SPerformer::operator()(TMacroUsage const& cmp) const
  617. {
  618. owner.identifier.setTo(owner.interp->getIexp(cmp));
  619. }
  620. void VR_SPerformer::operator()(TMacroDef const& cmp) const
  621. {
  622. throw EScriptExecError("Macro definition not allowed in VR S");
  623. }
  624. void VR_SPerformer::operator()(TVarpExp const& cmp) const
  625. {
  626. throw EScriptExecError("Write-only variable expression not allowed in VR S");
  627. }
  628. void VR_SPerformer::operator()(spirit::unused_type const& cmp) const
  629. {
  630. throw EScriptExecError("Expression not allowed in VR S");
  631. }
  632. struct ConditionDisemboweler;
  633. struct ERMExpDispatch : boost::static_visitor<>
  634. {
  635. ERMInterpreter * owner;
  636. ERMExpDispatch(ERMInterpreter * _owner) : owner(_owner)
  637. {}
  638. void operator()(Ttrigger const& trig) const
  639. {
  640. throw EInterpreterError("Triggers cannot be executed!");
  641. }
  642. void operator()(Tinstruction const& trig) const
  643. {
  644. }
  645. void operator()(Treceiver const& trig) const
  646. {
  647. if(trig.name == "VR")
  648. {
  649. //check condition
  650. if(trig.condition.is_initialized())
  651. {
  652. if( !owner->checkCondition(trig.condition.get()) )
  653. return;
  654. }
  655. //perform operations
  656. if(trig.identifier.is_initialized())
  657. {
  658. ERM::Tidentifier ident = trig.identifier.get();
  659. if(ident.size() == 1)
  660. {
  661. IexpValStr ievs = owner->getIexp(ident[0]);
  662. //see body
  663. if(trig.body.is_initialized())
  664. {
  665. ERM::Tbody bo = trig.body.get();
  666. for(int g=0; g<bo.size(); ++g)
  667. {
  668. boost::apply_visitor(VRPerformer(owner, ievs), bo[g]);
  669. }
  670. }
  671. }
  672. else
  673. throw EScriptExecError("VR receiver must be used with exactly one identifier item!");
  674. }
  675. else
  676. throw EScriptExecError("VR receiver must be used with an identifier!");
  677. }
  678. else if(trig.name == "DO")
  679. {
  680. //perform operations
  681. if(trig.identifier.is_initialized())
  682. {
  683. ERM::Tidentifier tid = trig.identifier.get();
  684. if(tid.size() != 4)
  685. {
  686. throw EScriptExecError("DO receiver takes exactly 4 arguments");
  687. }
  688. int funNum = owner->getIexp(tid[0]).getInt(),
  689. startVal = owner->getIexp(tid[1]).getInt(),
  690. stopVal = owner->getIexp(tid[2]).getInt(),
  691. increment = owner->getIexp(tid[3]).getInt();
  692. for(int it = startVal; it < stopVal; it += increment)
  693. {
  694. owner->getFuncVars(funNum)->getParam(16) = it;
  695. ERMInterpreter::TIDPattern tip;
  696. std::vector<int> v1;
  697. v1 += funNum;
  698. insert(tip) (v1.size(), v1);
  699. owner->executeTriggerType(TriggerType("FU"), true, tip);
  700. it = owner->getFuncVars(funNum)->getParam(16);
  701. }
  702. }
  703. }
  704. else
  705. {
  706. //unsupported or invalid trigger
  707. }
  708. }
  709. void operator()(TPostTrigger const& trig) const
  710. {
  711. throw EInterpreterError("Post-triggers cannot be executed!");
  712. }
  713. };
  714. struct CommandExec : boost::static_visitor<>
  715. {
  716. ERMInterpreter * owner;
  717. CommandExec(ERMInterpreter * _owner) : owner(_owner)
  718. {}
  719. void operator()(Tcommand const& cmd) const
  720. {
  721. boost::apply_visitor(ERMExpDispatch(owner), cmd.cmd);
  722. std::cout << "Line comment: " << cmd.comment << std::endl;
  723. }
  724. void operator()(std::string const& comment) const
  725. {
  726. //comment - do nothing
  727. }
  728. void operator()(spirit::unused_type const& nothing) const
  729. {
  730. //nothing - do nothing
  731. }
  732. };
  733. struct LineExec : boost::static_visitor<>
  734. {
  735. ERMInterpreter * owner;
  736. LineExec(ERMInterpreter * _owner) : owner(_owner)
  737. {}
  738. void operator()(TVExp const& cmd) const
  739. {
  740. //printTVExp(cmd);
  741. }
  742. void operator()(TERMline const& cmd) const
  743. {
  744. boost::apply_visitor(CommandExec(owner), cmd);
  745. }
  746. };
  747. /////////
  748. void ERMInterpreter::executeLine( const LinePointer & lp )
  749. {
  750. boost::apply_visitor(LineExec(this), scripts[lp]);
  751. }
  752. void ERMInterpreter::init()
  753. {
  754. ermGlobalEnv = new ERMEnvironment();
  755. globalEnv = new Environment();
  756. //TODO: reset?
  757. }
  758. IexpValStr ERMInterpreter::getVar(std::string toFollow, boost::optional<int> initVal) const
  759. {
  760. IexpValStr ret;
  761. ret.type = IexpValStr::WRONGVAL;
  762. int initV;
  763. bool hasInit = false;
  764. if(initVal.is_initialized())
  765. {
  766. initV = initVal.get();
  767. hasInit = true;
  768. }
  769. int endNum = 0;
  770. if(toFollow[0] == 'd')
  771. {
  772. endNum = 1;
  773. //TODO: support
  774. }
  775. if(toFollow.size() == 0)
  776. {
  777. if(hasInit)
  778. ret = IexpValStr(initV);
  779. else
  780. throw EIexpProblem("No input to getVar!");
  781. return ret;
  782. }
  783. //now we have at least one element in toFollow
  784. for(int b=toFollow.size()-1; b>=endNum; --b)
  785. {
  786. bool retIt = b == endNum+1; //if we should return the value are currently at
  787. char cr = toFollow[toFollow.size() - 1];
  788. if(cr == 'c')//write number of current day
  789. {
  790. //TODO
  791. }
  792. else if(cr == 'd') //info for external env - add i/o set
  793. {
  794. throw EIexpProblem("d inside i-expression not allowed!");
  795. }
  796. else if(cr == 'e')
  797. {
  798. if(hasInit)
  799. {
  800. if(retIt)
  801. {
  802. //these C-style cast is here just to shut up compiler errors
  803. if(initV > 0 && initV <= FunctionLocalVars::NUM_FLOATINGS)
  804. {
  805. if(curFunc)
  806. ret = IexpValStr(&curFunc->getFloat(initV));
  807. else
  808. throw EIexpProblem("Function context not available!");
  809. }
  810. else if(initV < 0 && initV >= -TriggerLocalVars::EVAR_NUM)
  811. {
  812. if(curTrigger)
  813. ret = IexpValStr(&curTrigger->ermLocalVars.getEvar(initV));
  814. else
  815. throw EIexpProblem("No trigger context available!");
  816. }
  817. else
  818. throw EIexpProblem("index " + boost::lexical_cast<std::string>(initV) + " not allowed for e array");
  819. }
  820. else
  821. throw EIexpProblem("e variables cannot appear in this context");
  822. }
  823. else
  824. throw EIexpProblem("e variables cannot appear in this context");
  825. }
  826. else if(cr >= 'f' && cr <= 't')
  827. {
  828. if(retIt)
  829. ret = IexpValStr(&ermGlobalEnv->getQuickVar(cr));
  830. else
  831. {
  832. if(hasInit)
  833. throw EIexpProblem("quick variables cannot be used in this context");
  834. else
  835. {
  836. initV = ermGlobalEnv->getQuickVar(cr);
  837. hasInit = true;
  838. }
  839. }
  840. }
  841. else if(cr == 'v') //standard variables
  842. {
  843. if(hasInit)
  844. {
  845. if(retIt)
  846. ret = IexpValStr(&ermGlobalEnv->getStandardVar(initV));
  847. else
  848. initV = ermGlobalEnv->getStandardVar(initV);
  849. }
  850. else
  851. throw EIexpProblem("standard variable cannot be used in this context!");
  852. }
  853. else if(cr == 'w') //local hero variables
  854. {
  855. //TODO
  856. }
  857. else if(cr == 'x') //function parameters
  858. {
  859. if(hasInit)
  860. {
  861. if(curFunc)
  862. {
  863. if(retIt)
  864. ret = IexpValStr(&curFunc->getParam(initV));
  865. else
  866. initV = curFunc->getParam(initV);
  867. }
  868. else throw EIexpProblem("Function parameters cannot be used outside a function!");
  869. }
  870. else
  871. throw EIexpProblem("Specify which function parameter should be used");
  872. }
  873. else if(cr == 'y')
  874. {
  875. if(hasInit)
  876. {
  877. if(initV > 0 && initV <= FunctionLocalVars::NUM_LOCALS)
  878. {
  879. if(curFunc)
  880. {
  881. if(retIt)
  882. ret = IexpValStr(&curFunc->getLocal(initV));
  883. else
  884. initV = curFunc->getLocal(initV);
  885. }
  886. else
  887. throw EIexpProblem("Function local variables cannot be used outside a function!");
  888. }
  889. else if(initV < 0 && initV >= -TriggerLocalVars::YVAR_NUM)
  890. {
  891. if(curTrigger)
  892. {
  893. if(retIt)
  894. ret = IexpValStr(&curTrigger->ermLocalVars.getYvar(initV));
  895. else
  896. initV = curTrigger->ermLocalVars.getYvar(initV);
  897. }
  898. else
  899. throw EIexpProblem("Trigger local variables cannot be used outside triggers!");
  900. }
  901. else
  902. throw EIexpProblem("Wrong argument for function local variable!");
  903. }
  904. else
  905. throw EIexpProblem("y variable cannot be used in this context!");
  906. }
  907. else if(cr == 'z')
  908. {
  909. if(hasInit)
  910. {
  911. if(retIt)
  912. {
  913. //these C-style casts are here just to shut up compiler errors
  914. if(initV > 0 )
  915. ret = IexpValStr(&ermGlobalEnv->getZVar(initV));
  916. else if(initV < 0)
  917. {
  918. if(curFunc)
  919. ret = IexpValStr(&curFunc->getString(initV));
  920. else
  921. throw EIexpProblem("Function local string variables cannot be used outside functions!");
  922. }
  923. else
  924. throw EIexpProblem("Wrong parameter for string variable!");
  925. }
  926. else
  927. throw EIexpProblem("String variables can only be returned!");
  928. }
  929. else
  930. throw EIexpProblem("String variables cannot be used in this context!");
  931. }
  932. else
  933. {
  934. throw EIexpProblem(std::string("Symbol ") + cr + " is not allowed in this context!");
  935. }
  936. }
  937. return ret;
  938. }
  939. namespace IexpDisemboweler
  940. {
  941. enum EDir{GET, SET};
  942. }
  943. struct LVL2IexpDisemboweler : boost::static_visitor<IexpValStr>
  944. {
  945. IexpDisemboweler::EDir dir;
  946. /*const*/ ERMInterpreter * env;
  947. LVL2IexpDisemboweler(/*const*/ ERMInterpreter * _env, IexpDisemboweler::EDir _dir)
  948. : env(_env), dir(_dir) //writes value to given var
  949. {}
  950. IexpValStr processNotMacro(const TVarExpNotMacro & val) const
  951. {
  952. if(val.questionMark.is_initialized())
  953. throw EIexpProblem("Question marks ('?') are not allowed in getter i-expressions");
  954. //const-cast just to do some code-reuse...
  955. return env->getVar(val.varsym, val.val);
  956. }
  957. IexpValStr operator()(TVarExpNotMacro const& val) const
  958. {
  959. return processNotMacro(val);
  960. }
  961. IexpValStr operator()(TMacroUsage const& val) const
  962. {
  963. return env->getIexp(val);
  964. }
  965. };
  966. struct LVL1IexpDisemboweler : boost::static_visitor<IexpValStr>
  967. {
  968. IexpDisemboweler::EDir dir;
  969. /*const*/ ERMInterpreter * env;
  970. LVL1IexpDisemboweler(/*const*/ ERMInterpreter * _env, IexpDisemboweler::EDir _dir)
  971. : env(_env), dir(_dir) //writes value to given var
  972. {}
  973. IexpValStr operator()(int const & constant) const
  974. {
  975. if(dir == IexpDisemboweler::GET)
  976. {
  977. IexpValStr ret = IexpValStr(constant);
  978. }
  979. else
  980. {
  981. throw EIexpProblem("Cannot set a constant!");
  982. }
  983. }
  984. IexpValStr operator()(TVarExp const & var) const
  985. {
  986. return boost::apply_visitor(LVL2IexpDisemboweler(env, dir), var);
  987. }
  988. };
  989. IexpValStr ERMInterpreter::getIexp( const ERM::TIexp & iexp ) const
  990. {
  991. return boost::apply_visitor(LVL1IexpDisemboweler(const_cast<ERMInterpreter*>(this), IexpDisemboweler::GET), iexp);
  992. }
  993. IexpValStr ERMInterpreter::getIexp( const ERM::TMacroUsage & macro ) const
  994. {
  995. std::map<std::string, ERM::TVarExpNotMacro>::const_iterator it =
  996. ermGlobalEnv->macroBindings.find(macro.macro);
  997. if(it == ermGlobalEnv->macroBindings.end())
  998. throw EUsageOfUndefinedMacro(macro.macro);
  999. return getVar(it->second.varsym, it->second.val);
  1000. }
  1001. IexpValStr ERMInterpreter::getIexp( const ERM::TIdentifierInternal & tid ) const
  1002. {
  1003. if(tid.which() == 0)
  1004. {
  1005. IexpValStr ievs = getIexp(boost::get<ERM::TIexp>(tid));
  1006. }
  1007. else
  1008. throw EScriptExecError("Identifier must be a valid i-expression to perform this operation!");
  1009. }
  1010. void ERMInterpreter::executeTriggerType( VERMInterpreter::TriggerType tt, bool pre, const TIDPattern & identifier )
  1011. {
  1012. TtriggerListType & triggerList = pre ? triggers : postTriggers;
  1013. TriggerIdentifierMatch tim;
  1014. tim.allowNoIdetifier = false;
  1015. tim.ermEnv = this;
  1016. tim.matchToIt = identifier;
  1017. std::vector<Trigger> & triggersToTry = triggerList[tt];
  1018. for(int g=0; g<triggersToTry.size(); ++g)
  1019. {
  1020. if(tim.tryMatch(&triggersToTry[g]))
  1021. {
  1022. curTrigger = &triggersToTry[g];
  1023. executeTrigger(triggersToTry[g]);
  1024. }
  1025. }
  1026. }
  1027. ERM::Ttrigger ERMInterpreter::retrieveTrigger( ERM::TLine line )
  1028. {
  1029. if(line.which() == 1)
  1030. {
  1031. ERM::TERMline tl = boost::get<ERM::TERMline>(line);
  1032. if(tl.which() == 0)
  1033. {
  1034. ERM::Tcommand tcm = boost::get<ERM::Tcommand>(line);
  1035. if(tcm.cmd.which() == 0)
  1036. {
  1037. return boost::get<ERM::Ttrigger>(tcm.cmd);
  1038. }
  1039. }
  1040. }
  1041. throw ELineProblem("Given line is not an ERM trigger!");
  1042. }
  1043. template<typename T>
  1044. bool compareExp(const T & lhs, const T & rhs, std::string op)
  1045. {
  1046. if(op == "<")
  1047. {
  1048. return lhs < rhs;
  1049. }
  1050. else if(op == ">")
  1051. {
  1052. return lhs > rhs;
  1053. }
  1054. else if(op == ">=" || op == "=>")
  1055. {
  1056. return lhs >= rhs;
  1057. }
  1058. else if(op == "<=" || op == "=<")
  1059. {
  1060. return lhs <= rhs;
  1061. }
  1062. else if(op == "==")
  1063. {
  1064. return lhs == rhs;
  1065. }
  1066. else if(op == "<>" || op == "><")
  1067. {
  1068. return lhs != rhs;
  1069. }
  1070. else
  1071. throw EScriptExecError(std::string("Wrong comparison sign: ") + op);
  1072. }
  1073. struct ConditionDisemboweler : boost::static_visitor<bool>
  1074. {
  1075. ConditionDisemboweler(ERMInterpreter * _ei) : ei(_ei)
  1076. {}
  1077. bool operator()(TComparison const & cmp) const
  1078. {
  1079. IexpValStr lhs = ei->getIexp(cmp.lhs),
  1080. rhs = ei->getIexp(cmp.rhs);
  1081. switch (lhs.type)
  1082. {
  1083. case IexpValStr::FLOATVAR:
  1084. switch (rhs.type)
  1085. {
  1086. case IexpValStr::FLOATVAR:
  1087. return compareExp(lhs.getFloat(), rhs.getFloat(), cmp.compSign);
  1088. break;
  1089. default:
  1090. throw EScriptExecError("Incompatible types for comparison");
  1091. }
  1092. break;
  1093. case IexpValStr::INT:
  1094. case IexpValStr::INTVAR:
  1095. switch (rhs.type)
  1096. {
  1097. case IexpValStr::INT:
  1098. case IexpValStr::INTVAR:
  1099. return compareExp(lhs.getInt(), rhs.getInt(), cmp.compSign);
  1100. break;
  1101. default:
  1102. throw EScriptExecError("Incompatible types for comparison");
  1103. }
  1104. break;
  1105. case IexpValStr::STRINGVAR:
  1106. switch (rhs.type)
  1107. {
  1108. case IexpValStr::STRINGVAR:
  1109. return compareExp(lhs.getString(), rhs.getString(), cmp.compSign);
  1110. break;
  1111. default:
  1112. throw EScriptExecError("Incompatible types for comparison");
  1113. }
  1114. break;
  1115. default:
  1116. throw EScriptExecError("Wrong type of left iexp!");
  1117. }
  1118. //we should never reach this place
  1119. }
  1120. bool operator()(int const & flag) const
  1121. {
  1122. return ei->ermGlobalEnv->getFlag(flag);
  1123. }
  1124. private:
  1125. ERMInterpreter * ei;
  1126. };
  1127. bool ERMInterpreter::checkCondition( ERM::Tcondition cond )
  1128. {
  1129. bool ret = boost::apply_visitor(ConditionDisemboweler(this), cond.cond);
  1130. if(cond.rhs.is_initialized())
  1131. { //taking care of rhs expression
  1132. bool rhs = checkCondition(cond.rhs.get().get());
  1133. switch (cond.ctype)
  1134. {
  1135. case '&':
  1136. ret &= rhs;
  1137. break;
  1138. case '|':
  1139. ret |= rhs;
  1140. break;
  1141. case 'X':
  1142. ret ^= rhs;
  1143. break;
  1144. default:
  1145. throw EInterpreterProblem(std::string("Strange - wrong condition connection (") + cond.ctype + ") !");
  1146. break;
  1147. }
  1148. }
  1149. return ret;
  1150. }
  1151. FunctionLocalVars * ERMInterpreter::getFuncVars( int funNum )
  1152. {
  1153. return funcVars + funNum - 1;
  1154. }
  1155. const std::string ERMInterpreter::triggerSymbol = "trigger";
  1156. const std::string ERMInterpreter::postTriggerSymbol = "postTrigger";
  1157. const std::string ERMInterpreter::defunSymbol = "defun";
  1158. struct TriggerIdMatchHelper : boost::static_visitor<>
  1159. {
  1160. int & ret;
  1161. ERMInterpreter * interpreter;
  1162. Trigger * trig;
  1163. TriggerIdMatchHelper(int & b, ERMInterpreter * ermint, Trigger * _trig)
  1164. : ret(b), interpreter(ermint), trig(_trig)
  1165. {}
  1166. void operator()(TIexp const& iexp) const
  1167. {
  1168. IexpValStr val = interpreter->getIexp(iexp);
  1169. switch(val.type)
  1170. {
  1171. case IexpValStr::INT:
  1172. case IexpValStr::INTVAR:
  1173. ret = val.getInt();
  1174. break;
  1175. default:
  1176. throw EScriptExecError("Incompatible i-exp type!");
  1177. break;
  1178. }
  1179. }
  1180. void operator()(TArithmeticOp const& arop) const
  1181. {
  1182. //error?!?
  1183. }
  1184. };
  1185. bool TriggerIdentifierMatch::tryMatch( Trigger * interptrig ) const
  1186. {
  1187. bool ret = true;
  1188. const ERM::Ttrigger & trig = ERMInterpreter::retrieveTrigger(ermEnv->retrieveLine(interptrig->line));
  1189. if(trig.identifier.is_initialized())
  1190. {
  1191. ERM::Tidentifier tid = trig.identifier.get();
  1192. std::map< int, std::vector<int> >::const_iterator it = matchToIt.find(tid.size());
  1193. if(it == matchToIt.end())
  1194. ret = false;
  1195. else
  1196. {
  1197. const std::vector<int> & pattern = it->second;
  1198. for(int g=0; g<pattern.size(); ++g)
  1199. {
  1200. int val = -1;
  1201. boost::apply_visitor(TriggerIdMatchHelper(val, ermEnv, interptrig), tid[g]);
  1202. if(pattern[g] != val)
  1203. {
  1204. ret = false;
  1205. }
  1206. }
  1207. ret = true;
  1208. }
  1209. }
  1210. else
  1211. {
  1212. ret = allowNoIdetifier;
  1213. }
  1214. //check condition
  1215. if(ret)
  1216. {
  1217. if(trig.condition.is_initialized())
  1218. {
  1219. return ermEnv->checkCondition(trig.condition.get());
  1220. }
  1221. else //no condition
  1222. return true;
  1223. }
  1224. else
  1225. return false;
  1226. }
  1227. VERMInterpreter::ERMEnvironment::ERMEnvironment()
  1228. {
  1229. for(int g=0; g<NUM_QUICKS; ++g)
  1230. quickVars[g] = 0;
  1231. for(int g=0; g<NUM_STANDARDS; ++g)
  1232. standardVars[g] = 0;
  1233. //string should be automatically initialized to ""
  1234. for(int g=0; g<NUM_FLAGS; ++g)
  1235. flags[g] = false;
  1236. }
  1237. int & VERMInterpreter::ERMEnvironment::getQuickVar( const char letter )
  1238. {
  1239. assert(letter >= 'f' && letter <= 't'); //it should be check by another function, just making sure here
  1240. return quickVars[letter - 'f'];
  1241. }
  1242. int & VERMInterpreter::ERMEnvironment::getStandardVar( int num )
  1243. {
  1244. if(num < 1 || num > NUM_STANDARDS)
  1245. throw EScriptExecError("Number of standard variable out of bounds");
  1246. return standardVars[num-1];
  1247. }
  1248. std::string & VERMInterpreter::ERMEnvironment::getZVar( int num )
  1249. {
  1250. if(num < 1 || num > NUM_STRINGS)
  1251. throw EScriptExecError("Number of string variable out of bounds");
  1252. return strings[num-1];
  1253. }
  1254. bool & VERMInterpreter::ERMEnvironment::getFlag( int num )
  1255. {
  1256. if(num < 1 || num > NUM_FLAGS)
  1257. throw EScriptExecError("Number of flag out of bounds");
  1258. return flags[num-1];
  1259. }
  1260. VERMInterpreter::TriggerLocalVars::TriggerLocalVars()
  1261. {
  1262. for(int g=0; g<EVAR_NUM; ++g)
  1263. evar[g] = 0.0;
  1264. for(int g=0; g<YVAR_NUM; ++g)
  1265. yvar[g] = 0;
  1266. }
  1267. double & VERMInterpreter::TriggerLocalVars::getEvar( int num )
  1268. {
  1269. num = -num;
  1270. if(num < 1 || num > EVAR_NUM)
  1271. throw EScriptExecError("Number of trigger local floating point variable out of bounds");
  1272. return evar[num-1];
  1273. }
  1274. int & VERMInterpreter::TriggerLocalVars::getYvar( int num )
  1275. {
  1276. if(num < 1 || num > YVAR_NUM)
  1277. throw EScriptExecError("Number of trigger local variable out of bounds");
  1278. return yvar[num-1];
  1279. }
  1280. bool VERMInterpreter::Environment::isBound( const std::string & name, bool globalOnly ) const
  1281. {
  1282. std::map<std::string, TVOption>::const_iterator it = symbols.find(name);
  1283. if(globalOnly && parent)
  1284. {
  1285. return parent->isBound(name, globalOnly);
  1286. }
  1287. //we have it; if globalOnly is true, lexical parent is false here so we are global env
  1288. if(it != symbols.end())
  1289. return true;
  1290. //here, we don;t have it; but parent can have
  1291. if(parent)
  1292. return parent->isBound(name, globalOnly);
  1293. return false;
  1294. }
  1295. ERM::TVOption VERMInterpreter::Environment::retrieveValue( const std::string & name ) const
  1296. {
  1297. std::map<std::string, TVOption>::const_iterator it = symbols.find(name);
  1298. if(it == symbols.end())
  1299. {
  1300. if(parent)
  1301. {
  1302. return parent->retrieveValue(name);
  1303. }
  1304. throw ESymbolNotFound(name);
  1305. }
  1306. return it->second;
  1307. }
  1308. bool VERMInterpreter::Environment::unbind( const std::string & name, EUnbindMode mode )
  1309. {
  1310. if(isBound(name, false))
  1311. {
  1312. if(symbols.find(name) != symbols.end()) //result of isBound could be from higher lexical env
  1313. symbols.erase(symbols.find(name));
  1314. if(mode == FULLY_RECURSIVE && parent)
  1315. parent->unbind(name, mode);
  1316. return true;
  1317. }
  1318. if(parent && (mode == RECURSIVE_UNTIL_HIT || mode == FULLY_RECURSIVE))
  1319. return parent->unbind(name, mode);
  1320. //neither bound nor have lexical parent
  1321. return false;
  1322. }
  1323. int & VERMInterpreter::FunctionLocalVars::getParam( int num )
  1324. {
  1325. if(num < 1 || num > NUM_PARAMETERS)
  1326. throw EScriptExecError("Number of parameter out of bounds");
  1327. return params[num-1];
  1328. }
  1329. int & VERMInterpreter::FunctionLocalVars::getLocal( int num )
  1330. {
  1331. if(num < 1 || num > NUM_LOCALS)
  1332. throw EScriptExecError("Number of local variable out of bounds");
  1333. return locals[num-1];
  1334. }
  1335. std::string & VERMInterpreter::FunctionLocalVars::getString( int num )
  1336. {
  1337. num = -num; //we deal with negative indices
  1338. if(num < 1 || num > NUM_PARAMETERS)
  1339. throw EScriptExecError("Number of function local string variable out of bounds");
  1340. return strings[num-1];
  1341. }
  1342. double & VERMInterpreter::FunctionLocalVars::getFloat( int num )
  1343. {
  1344. if(num < 1 || num > NUM_FLOATINGS)
  1345. throw EScriptExecError("Number of float var out of bounds");
  1346. return floats[num-1];
  1347. }
  1348. void IexpValStr::setTo( const IexpValStr & second )
  1349. {
  1350. switch(type)
  1351. {
  1352. case IexpValStr::FLOATVAR:
  1353. *val.flvar = second.getFloat();
  1354. break;
  1355. case IexpValStr::INT:
  1356. throw EScriptExecError("VR S: value not assignable!");
  1357. break;
  1358. case IexpValStr::INTVAR:
  1359. *val.integervar = second.getInt();
  1360. break;
  1361. case IexpValStr::STRINGVAR:
  1362. *val.stringvar = second.getString();
  1363. break;
  1364. default:
  1365. throw EScriptExecError("Wrong type of identifier iexp!");
  1366. }
  1367. }
  1368. void IexpValStr::setTo( int val )
  1369. {
  1370. switch(type)
  1371. {
  1372. case INTVAR:
  1373. *this->val.integervar = val;
  1374. break;
  1375. default:
  1376. throw EIexpProblem("Incompatible type!");
  1377. break;
  1378. }
  1379. }
  1380. void IexpValStr::setTo( float val )
  1381. {
  1382. switch(type)
  1383. {
  1384. case FLOATVAR:
  1385. *this->val.flvar = val;
  1386. break;
  1387. default:
  1388. throw EIexpProblem("Incompatible type!");
  1389. break;
  1390. }
  1391. }
  1392. void IexpValStr::setTo( const std::string & val )
  1393. {
  1394. switch(type)
  1395. {
  1396. case STRINGVAR:
  1397. *this->val.stringvar = val;
  1398. break;
  1399. default:
  1400. throw EIexpProblem("Incompatible type!");
  1401. break;
  1402. }
  1403. }
  1404. int IexpValStr::getInt() const
  1405. {
  1406. switch(type)
  1407. {
  1408. case IexpValStr::INT:
  1409. return val.val;
  1410. break;
  1411. case IexpValStr::INTVAR:
  1412. return *val.integervar;
  1413. break;
  1414. default:
  1415. throw EIexpProblem("Cannot get iexp as int!");
  1416. break;
  1417. }
  1418. }
  1419. float IexpValStr::getFloat() const
  1420. {
  1421. switch(type)
  1422. {
  1423. case IexpValStr::FLOATVAR:
  1424. return *val.flvar;
  1425. break;
  1426. default:
  1427. throw EIexpProblem("Cannot get iexp as float!");
  1428. break;
  1429. }
  1430. }
  1431. std::string IexpValStr::getString() const
  1432. {
  1433. switch(type)
  1434. {
  1435. case IexpValStr::STRINGVAR:
  1436. return *val.stringvar;
  1437. break;
  1438. default:
  1439. throw EScriptExecError("Cannot get iexp as string!");
  1440. break;
  1441. }
  1442. }