ERMInterpreter.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937
  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. for(LinePointer lp = trig.line; lp.isValid(); ++lp)
  422. {
  423. ERM::TLine curLine = retrieveLine(lp);
  424. if(isATrigger(curLine))
  425. break;
  426. executeLine(lp);
  427. }
  428. }
  429. bool ERMInterpreter::isATrigger( const ERM::TLine & line )
  430. {
  431. switch(line.which())
  432. {
  433. case 0: //v-exp
  434. {
  435. TVExp vexp = boost::get<TVExp>(line);
  436. if(vexp.children.size() == 0)
  437. return false;
  438. switch (getExpType(vexp.children[0]))
  439. {
  440. case SYMBOL:
  441. {
  442. //TODO: what about sym modifiers?
  443. //TOOD: macros?
  444. ERM::TSymbol sym = boost::get<ERM::TSymbol>(vexp.children[0]);
  445. return sym.sym == triggerSymbol || sym.sym == postTriggerSymbol;
  446. }
  447. break;
  448. case TCMD:
  449. return isCMDATrigger( boost::get<ERM::Tcommand>(vexp.children[0]) );
  450. break;
  451. default:
  452. return false;
  453. break;
  454. }
  455. }
  456. break;
  457. case 1: //erm
  458. {
  459. TERMline line = boost::get<TERMline>(line);
  460. switch(line.which())
  461. {
  462. case 0: //tcmd
  463. return isCMDATrigger( boost::get<ERM::Tcommand>(line) );
  464. break;
  465. default:
  466. return false;
  467. break;
  468. }
  469. }
  470. break;
  471. default:
  472. assert(0); //it should never happen
  473. break;
  474. }
  475. assert(0);
  476. }
  477. ERM::EVOtions ERMInterpreter::getExpType( const ERM::TVOption & opt )
  478. {
  479. //MAINTENANCE: keep it correct!
  480. return static_cast<ERM::EVOtions>(opt.which());
  481. }
  482. bool ERMInterpreter::isCMDATrigger( const ERM::Tcommand & cmd )
  483. {
  484. switch (cmd.cmd.which())
  485. {
  486. case 0: //trigger
  487. case 3: //post trigger
  488. return true;
  489. break;
  490. default:
  491. return false;
  492. break;
  493. }
  494. }
  495. ERM::TLine ERMInterpreter::retrieveLine( LinePointer linePtr ) const
  496. {
  497. return *scripts.find(linePtr);
  498. }
  499. /////////
  500. //code execution
  501. struct ERMExpDispatch : boost::static_visitor<>
  502. {
  503. void operator()(Ttrigger const& trig) const
  504. {
  505. //the first executed line, check if we should proceed
  506. }
  507. void operator()(Tinstruction const& trig) const
  508. {
  509. }
  510. void operator()(Treceiver const& trig) const
  511. {
  512. }
  513. void operator()(TPostTrigger const& trig) const
  514. {
  515. }
  516. };
  517. struct CommandExec : boost::static_visitor<>
  518. {
  519. void operator()(Tcommand const& cmd) const
  520. {
  521. boost::apply_visitor(ERMExpDispatch(), cmd.cmd);
  522. std::cout << "Line comment: " << cmd.comment << std::endl;
  523. }
  524. void operator()(std::string const& comment) const
  525. {
  526. //comment - do nothing
  527. }
  528. void operator()(spirit::unused_type const& nothing) const
  529. {
  530. //nothing - do nothing
  531. }
  532. };
  533. struct LineExec : boost::static_visitor<>
  534. {
  535. void operator()(TVExp const& cmd) const
  536. {
  537. //printTVExp(cmd);
  538. }
  539. void operator()(TERMline const& cmd) const
  540. {
  541. boost::apply_visitor(CommandExec(), cmd);
  542. }
  543. };
  544. /////////
  545. void ERMInterpreter::executeLine( const LinePointer & lp )
  546. {
  547. boost::apply_visitor(LineExec(), scripts[lp]);
  548. }
  549. void ERMInterpreter::init()
  550. {
  551. ermGlobalEnv = new ERMEnvironment();
  552. globalEnv = new Environment();
  553. //TODO: reset?
  554. }
  555. struct ERMExecEnvironment
  556. {
  557. ERMEnvironment * ermGlobalEnv;
  558. Trigger * trigEnv;
  559. FunctionLocalVars * funcVars;
  560. ERMExecEnvironment(ERMEnvironment * erm, Trigger * trig = NULL, FunctionLocalVars * funvars = NULL)
  561. : ermGlobalEnv(erm), trigEnv(trig), funcVars(funvars)
  562. {}
  563. template<typename T>
  564. T* getVar(std::string toFollow, boost::optional<int> initVal)
  565. {
  566. int initV;
  567. bool hasInit = false;
  568. if(initVal.is_initialized())
  569. {
  570. initV = initVal.get();
  571. hasInit = true;
  572. }
  573. int endNum = 0;
  574. if(toFollow[0] == 'd')
  575. {
  576. endNum = 1;
  577. //TODO: support
  578. }
  579. T* ret;
  580. for(int b=toFollow.size()-1; b>=endNum; --b)
  581. {
  582. bool retIt = b == endNum+1; //if we should return the value are currently at
  583. char cr = toFollow[toFollow.size() - 1];
  584. if(cr == 'c')//write number of current day
  585. {
  586. //TODO
  587. }
  588. else if(cr == 'd') //info for external env - add i/o set
  589. {
  590. throw EIexpProblem("d inside i-expression not allowed!");
  591. }
  592. else if(cr == 'e')
  593. {
  594. if(hasInit)
  595. {
  596. if(retIt)
  597. {
  598. //these C-style cast is here just to shut up compiler errors
  599. if(initV > 0 && initV <= FunctionLocalVars::NUM_FLOATINGS)
  600. {
  601. if(funcVars)
  602. ret = (T*)funcVars->floats + initV - 1;
  603. else
  604. throw EIexpProblem("Function context not available!");
  605. }
  606. else if(initV < 0 && initV >= -TriggerLocalVars::EVAR_NUM)
  607. {
  608. if(trigEnv)
  609. ret = (T*)trigEnv->ermLocalVars.evar - initV + 1; //minus is important!
  610. else
  611. throw EIexpProblem("No trigger context available!");
  612. }
  613. else
  614. throw EIexpProblem("index " + boost::lexical_cast<std::string>(initV) + " not allowed for e array");
  615. }
  616. else
  617. throw EIexpProblem("e variables cannot appear in this context");
  618. }
  619. else
  620. throw EIexpProblem("e variables cannot appear in this context");
  621. }
  622. else if(cr >= 'f' && cr <= 't')
  623. {
  624. if(retIt)
  625. ret = &ermGlobalEnv->getQuickVar(cr);
  626. else
  627. {
  628. if(hasInit)
  629. throw EIexpProblem("quick variables cannot be used in this context");
  630. else
  631. {
  632. initV = ermGlobalEnv->getQuickVar(cr);
  633. hasInit = true;
  634. }
  635. }
  636. }
  637. else if(cr == 'v') //standard variables
  638. {
  639. if(hasInit)
  640. {
  641. if(initV > 0 && initV <= ERMEnvironment::NUM_STANDARDS)
  642. {
  643. if(retIt)
  644. ret = ermGlobalEnv->standardVars + initV - 1;
  645. else
  646. initV = ermGlobalEnv->standardVars[initV-1];
  647. }
  648. else
  649. throw EIexpProblem("standard variable index out of range");
  650. }
  651. else
  652. throw EIexpProblem("standard variable cannot be used in this context!");
  653. }
  654. else if(cr == 'w') //local hero variables
  655. {
  656. //TODO
  657. }
  658. else if(cr == 'x') //function parameters
  659. {
  660. if(hasInit)
  661. {
  662. if(initV > 0 && initV <= FunctionLocalVars::NUM_PARAMETERS)
  663. {
  664. if(funcVars)
  665. {
  666. if(retIt)
  667. ret = funcVars->params + initV-1;
  668. else
  669. initV = funcVars->params[initV-1];
  670. }
  671. else throw EIexpProblem("Function parameters cannot be used outside a function!");
  672. }
  673. else
  674. throw EIexpProblem("Parameter number out of range");
  675. }
  676. else
  677. throw EIexpProblem("Specify which function parameter should be used");
  678. }
  679. else if(cr == 'y')
  680. {
  681. if(hasInit)
  682. {
  683. if(initV > 0 && initV <= FunctionLocalVars::NUM_LOCALS)
  684. {
  685. if(funcVars)
  686. {
  687. if(retIt)
  688. ret = funcVars->locals + initV-1;
  689. else
  690. initV = funcVars->params[initV - 1];
  691. }
  692. else
  693. throw EIexpProblem("Function local variables cannot be used outside a function!");
  694. }
  695. else if(initV < 0 && initV >= -TriggerLocalVars::YVAR_NUM)
  696. {
  697. if(trigEnv)
  698. {
  699. if(retIt)
  700. ret = trigEnv->ermLocalVars.yvar - initV + 1;
  701. else
  702. initV = trigEnv->ermLocalVars.yvar[-initV + 1];
  703. }
  704. else
  705. throw EIexpProblem("Trigger local variables cannot be used outside triggers!");
  706. }
  707. else
  708. throw EIexpProblem("Wrong argument for function local variable!");
  709. }
  710. else
  711. throw EIexpProblem("y variable cannot be used in this context!");
  712. }
  713. else if(cr == 'z')
  714. {
  715. if(hasInit)
  716. {
  717. if(retIt)
  718. {
  719. //these C-style casts are here just to shut up compiler errors
  720. if(initV > 0 && initV <= ermGlobalEnv->NUM_STRINGS)
  721. {
  722. ret = (T*)ermGlobalEnv->strings + initV - 1;
  723. }
  724. else if(initV < 0 && initV >= -FunctionLocalVars::NUM_STRINGS)
  725. {
  726. if(funcVars)
  727. {
  728. ret = (T*)funcVars->strings + initV - 1;
  729. }
  730. else
  731. throw EIexpProblem("Function local string variables cannot be used outside functions!");
  732. }
  733. else
  734. throw EIexpProblem("Wrong parameter for string variable!");
  735. }
  736. else
  737. throw EIexpProblem("String variables can only be returned!");
  738. }
  739. else
  740. throw EIexpProblem("String variables cannot be used in this context!");
  741. }
  742. else
  743. {
  744. throw EIexpProblem(std::string("Symbol ") + cr + " is not allowed in this context!");
  745. }
  746. }
  747. return ret;
  748. }
  749. };
  750. namespace IexpDisemboweler
  751. {
  752. enum EDir{GET, SET};
  753. }
  754. template<typename T>
  755. struct LVL2IexpDisemboweler : boost::static_visitor<>
  756. {
  757. T * inout;
  758. IexpDisemboweler::EDir dir;
  759. /*const*/ ERMExecEnvironment * env;
  760. LVL2IexpDisemboweler(T * in_out, /*const*/ ERMExecEnvironment * _env, IexpDisemboweler::EDir _dir)
  761. : inout(in_out), env(_env), dir(_dir) //writes value to given var
  762. {}
  763. void processNotMacro(const TVarExpNotMacro & val) const
  764. {
  765. if(val.questionMark.is_initialized())
  766. throw EIexpProblem("Question marks ('?') are not allowed in getter i-expressions");
  767. //const-cast just to do some code-reuse...
  768. *inout = *const_cast<ERMExecEnvironment*>(env)->getVar<T>(val.varsym, val.val);
  769. }
  770. void operator()(TVarExpNotMacro const& val) const
  771. {
  772. processNotMacro(val);
  773. }
  774. void operator()(TMacroUsage const& val) const
  775. {
  776. std::map<std::string, ERM::TVarExpNotMacro>::const_iterator it =
  777. env->ermGlobalEnv->macroBindings.find(val .macro);
  778. if(it == env->ermGlobalEnv->macroBindings.end())
  779. throw EUsageOfUndefinedMacro(val.macro);
  780. else
  781. processNotMacro(it->second);
  782. }
  783. };
  784. template<typename T>
  785. struct LVL1IexpDisemboweler : boost::static_visitor<>
  786. {
  787. T * inout;
  788. IexpDisemboweler::EDir dir;
  789. /*const*/ ERMExecEnvironment * env;
  790. LVL1IexpDisemboweler(T * in_out, /*const*/ ERMExecEnvironment * _env, IexpDisemboweler::EDir _dir)
  791. : inout(in_out), env(_env), dir(_dir) //writes value to given var
  792. {}
  793. void operator()(int const & constant) const
  794. {
  795. if(dir == IexpDisemboweler::GET)
  796. {
  797. *inout = constant;
  798. }
  799. else
  800. {
  801. throw EIexpProblem("Cannot set a constant!");
  802. }
  803. }
  804. void operator()(TVarExp const & var) const
  805. {
  806. boost::apply_visitor(LVL2IexpDisemboweler<T>(inout, env, dir), var);
  807. }
  808. };
  809. template<typename T>
  810. T ERMInterpreter::getIexp( const ERM::TIexp & iexp, /*const*/ Trigger * trig /*= NULL*/, /*const*/ FunctionLocalVars * fun /*= NULL*/) const
  811. {
  812. T ret;
  813. ERMExecEnvironment env(ermGlobalEnv, trig, fun);
  814. boost::apply_visitor(LVL1IexpDisemboweler<T>(&ret, &env, IexpDisemboweler::GET), iexp);
  815. return ret;
  816. }
  817. const std::string ERMInterpreter::triggerSymbol = "trigger";
  818. const std::string ERMInterpreter::postTriggerSymbol = "postTrigger";
  819. const std::string ERMInterpreter::defunSymbol = "defun";
  820. struct TriggerIdMatchHelper : boost::static_visitor<>
  821. {
  822. int & ret;
  823. ERMInterpreter * interpreter;
  824. Trigger * trig;
  825. TriggerIdMatchHelper(int & b, ERMInterpreter * ermint, Trigger * _trig)
  826. : ret(b), interpreter(ermint), trig(_trig)
  827. {}
  828. void operator()(TIexp const& iexp) const
  829. {
  830. ret = interpreter->getIexp<int>(iexp, trig);
  831. }
  832. void operator()(TArithmeticOp const& arop) const
  833. {
  834. //error?!?
  835. }
  836. };
  837. bool TriggerIdentifierMatch::tryMatch( Trigger * interptrig, const ERM::Ttrigger & trig ) const
  838. {
  839. if(trig.identifier.is_initialized())
  840. {
  841. ERM::Tidentifier tid = trig.identifier.get();
  842. std::map< int, std::vector<int> >::const_iterator it = matchToIt.find(tid.size());
  843. if(it == matchToIt.end())
  844. return false;
  845. else
  846. {
  847. const std::vector<int> & pattern = it->second;
  848. for(int g=0; g<pattern.size(); ++g)
  849. {
  850. int val = -1;
  851. boost::apply_visitor(TriggerIdMatchHelper(val, ermEnv, interptrig), tid[g]);
  852. return pattern[g] == val;
  853. }
  854. }
  855. }
  856. else
  857. {
  858. if(allowNoIdetifier)
  859. return true;
  860. }
  861. }