ERMInterpreter.cpp 30 KB

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