ERMInterpreter.cpp 37 KB

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