ERMInterpreter.cpp 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882
  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()(TMacroUsage const& cmp) const
  132. {
  133. tlog2 << "???$$" << cmp.macro << "$$";
  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<LineInfo> 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].realLineNum)] = buf[g].tl;
  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( VERMInterpreter::Trigger & trig, int funNum /*= -1*/, std::vector<int> funParams/*=std::vector<int>()*/ )
  425. {
  426. //function-related logic
  427. if(funNum != -1)
  428. {
  429. curFunc = getFuncVars(funNum);
  430. for(int g=1; g<=FunctionLocalVars::NUM_PARAMETERS; ++g)
  431. {
  432. curFunc->getParam(g) = g-1 < funParams.size() ? funParams[g-1] : 0;
  433. }
  434. }
  435. //skip the first line
  436. LinePointer lp = trig.line;
  437. ++lp;
  438. for(; lp.isValid(); ++lp)
  439. {
  440. ERM::TLine curLine = retrieveLine(lp);
  441. if(isATrigger(curLine))
  442. break;
  443. executeLine(lp);
  444. }
  445. curFunc = NULL;
  446. }
  447. bool ERMInterpreter::isATrigger( const ERM::TLine & line )
  448. {
  449. switch(line.which())
  450. {
  451. case 0: //v-exp
  452. {
  453. TVExp vexp = boost::get<TVExp>(line);
  454. if(vexp.children.size() == 0)
  455. return false;
  456. switch (getExpType(vexp.children[0]))
  457. {
  458. case SYMBOL:
  459. {
  460. //TODO: what about sym modifiers?
  461. //TOOD: macros?
  462. ERM::TSymbol sym = boost::get<ERM::TSymbol>(vexp.children[0]);
  463. return sym.sym == triggerSymbol || sym.sym == postTriggerSymbol;
  464. }
  465. break;
  466. case TCMD:
  467. return isCMDATrigger( boost::get<ERM::Tcommand>(vexp.children[0]) );
  468. break;
  469. default:
  470. return false;
  471. break;
  472. }
  473. }
  474. break;
  475. case 1: //erm
  476. {
  477. TERMline ermline = boost::get<TERMline>(line);
  478. switch(ermline.which())
  479. {
  480. case 0: //tcmd
  481. return isCMDATrigger( boost::get<ERM::Tcommand>(ermline) );
  482. break;
  483. default:
  484. return false;
  485. break;
  486. }
  487. }
  488. break;
  489. default:
  490. assert(0); //it should never happen
  491. break;
  492. }
  493. assert(0);
  494. }
  495. ERM::EVOtions ERMInterpreter::getExpType( const ERM::TVOption & opt )
  496. {
  497. //MAINTENANCE: keep it correct!
  498. return static_cast<ERM::EVOtions>(opt.which());
  499. }
  500. bool ERMInterpreter::isCMDATrigger( const ERM::Tcommand & cmd )
  501. {
  502. switch (cmd.cmd.which())
  503. {
  504. case 0: //trigger
  505. case 3: //post trigger
  506. return true;
  507. break;
  508. default:
  509. return false;
  510. break;
  511. }
  512. }
  513. ERM::TLine ERMInterpreter::retrieveLine( LinePointer linePtr ) const
  514. {
  515. return scripts.find(linePtr)->second;
  516. }
  517. /////////
  518. //code execution
  519. template<typename OwnerType>
  520. struct StandardBodyOptionItemVisitor : boost::static_visitor<>
  521. {
  522. OwnerType & owner;
  523. explicit StandardBodyOptionItemVisitor(OwnerType & _owner) : owner(_owner)
  524. {}
  525. virtual void operator()(TVarConcatString const& cmp) const
  526. {
  527. throw EScriptExecError("String concatenation not allowed in this receiver");
  528. }
  529. virtual void operator()(TStringConstant const& cmp) const
  530. {
  531. throw EScriptExecError("String constant not allowed in this receiver");
  532. }
  533. virtual void operator()(TCurriedString const& cmp) const
  534. {
  535. throw EScriptExecError("Curried string not allowed in this receiver");
  536. }
  537. virtual void operator()(TSemiCompare const& cmp) const
  538. {
  539. throw EScriptExecError("Semi comparison not allowed in this receiver");
  540. }
  541. // virtual void operator()(TMacroUsage const& cmp) const
  542. // {
  543. // throw EScriptExecError("Macro usage not allowed in this receiver");
  544. // }
  545. virtual void operator()(TMacroDef const& cmp) const
  546. {
  547. throw EScriptExecError("Macro definition not allowed in this receiver");
  548. }
  549. virtual void operator()(TIexp const& cmp) const
  550. {
  551. throw EScriptExecError("i-expression not allowed in this receiver");
  552. }
  553. virtual void operator()(TVarpExp const& cmp) const
  554. {
  555. throw EScriptExecError("Varp expression not allowed in this receiver");
  556. }
  557. virtual void operator()(spirit::unused_type const& cmp) const
  558. {
  559. throw EScriptExecError("\'Nothing\' not allowed in this receiver");
  560. }
  561. };
  562. template<typename T>
  563. struct StandardReceiverVisitor : boost::static_visitor<>
  564. {
  565. ERMInterpreter * interp;
  566. T identifier;
  567. StandardReceiverVisitor(ERMInterpreter * _interpr, T ident) : interp(_interpr), identifier(ident)
  568. {}
  569. virtual void operator()(TVRLogic const& trig) const
  570. {
  571. throw EScriptExecError("VR logic not allowed in this receiver!");
  572. }
  573. virtual void operator()(TVRArithmetic const& trig) const
  574. {
  575. throw EScriptExecError("VR arithmetic not allowed in this receiver!");
  576. }
  577. virtual void operator()(TNormalBodyOption const& trig) const = 0;
  578. };
  579. struct VRPerformer;
  580. struct VR_SPerformer : StandardBodyOptionItemVisitor<VRPerformer>
  581. {
  582. explicit VR_SPerformer(VRPerformer & _owner);
  583. using StandardBodyOptionItemVisitor<VRPerformer>::operator();
  584. void operator()(TStringConstant const& cmp) const OVERRIDE;
  585. void operator()(TIexp const& cmp) const OVERRIDE;
  586. };
  587. struct VRPerformer : StandardReceiverVisitor<IexpValStr>
  588. {
  589. VRPerformer(ERMInterpreter * _interpr, IexpValStr ident) : StandardReceiverVisitor(_interpr, ident)
  590. {}
  591. void operator()(TVRLogic const& trig) const OVERRIDE
  592. {
  593. int valr = interp->getIexp(trig.var).getInt();
  594. switch (trig.opcode)
  595. {
  596. case '&':
  597. const_cast<VRPerformer*>(this)->identifier.setTo(identifier.getInt() & valr);
  598. break;
  599. case '|':
  600. const_cast<VRPerformer*>(this)->identifier.setTo(identifier.getInt() | valr);
  601. break;
  602. case 'X':
  603. const_cast<VRPerformer*>(this)->identifier.setTo(identifier.getInt() ^ valr);
  604. break;
  605. default:
  606. throw EInterpreterError("Wrong opcode in VR logic expression!");
  607. break;
  608. }
  609. }
  610. void operator()(TVRArithmetic const& trig) const OVERRIDE
  611. {
  612. IexpValStr rhs = interp->getIexp(trig.rhs);
  613. switch (trig.opcode)
  614. {
  615. case '+':
  616. const_cast<VRPerformer*>(this)->identifier += rhs;
  617. break;
  618. case '-':
  619. const_cast<VRPerformer*>(this)->identifier -= rhs;
  620. break;
  621. case '*':
  622. const_cast<VRPerformer*>(this)->identifier *= rhs;
  623. break;
  624. case ':':
  625. const_cast<VRPerformer*>(this)->identifier /= rhs;
  626. break;
  627. case '%':
  628. const_cast<VRPerformer*>(this)->identifier %= rhs;
  629. break;
  630. default:
  631. throw EInterpreterError("Wrong opcode in VR arithmetic!");
  632. break;
  633. }
  634. }
  635. void operator()(TNormalBodyOption const& trig) const
  636. {
  637. switch(trig.optionCode)
  638. {
  639. case 'C': //setting/checking v vars
  640. {
  641. //TODO
  642. }
  643. break;
  644. case 'H': //checking if string is empty
  645. {
  646. //TODO
  647. }
  648. break;
  649. case 'M': //string operations
  650. {
  651. //TODO
  652. }
  653. break;
  654. case 'R': //random variables
  655. {
  656. //TODO
  657. }
  658. break;
  659. case 'S': //setting variable
  660. {
  661. if(trig.params.size() == 1)
  662. {
  663. ERM::TBodyOptionItem boi = trig.params[0];
  664. boost::apply_visitor(VR_SPerformer(*const_cast<VRPerformer*>(this)), boi);
  665. }
  666. else
  667. throw EScriptExecError("VR receiver S option takes exactly 1 parameter!");
  668. }
  669. break;
  670. case 'T': //random variables
  671. {
  672. //TODO
  673. }
  674. break;
  675. case 'U': //search for a substring
  676. {
  677. //TODO
  678. }
  679. break;
  680. case 'V': //convert string to value
  681. {
  682. //TODO
  683. }
  684. break;
  685. default:
  686. throw EScriptExecError("Wrong VR receiver option!");
  687. break;
  688. }
  689. }
  690. };
  691. VR_SPerformer::VR_SPerformer(VRPerformer & _owner) : StandardBodyOptionItemVisitor(_owner)
  692. {}
  693. void VR_SPerformer::operator()(ERM::TIexp const& trig) const
  694. {
  695. owner.identifier.setTo(owner.interp->getIexp(trig));
  696. }
  697. void VR_SPerformer::operator()(TStringConstant const& cmp) const
  698. {
  699. owner.identifier.setTo(cmp.str);
  700. }
  701. struct ConditionDisemboweler;
  702. struct OBPerformer;
  703. struct OB_UPerformer : StandardBodyOptionItemVisitor<OBPerformer>
  704. {
  705. explicit OB_UPerformer(OBPerformer & owner) : StandardBodyOptionItemVisitor(owner)
  706. {}
  707. using StandardBodyOptionItemVisitor<OBPerformer>::operator();
  708. virtual void operator()(TIexp const& cmp) const;
  709. virtual void operator()(TVarpExp const& cmp) const;
  710. };
  711. struct OBPerformer : StandardReceiverVisitor<int3>
  712. {
  713. OBPerformer(ERMInterpreter * _interpr, int3 objPos) : StandardReceiverVisitor(_interpr, objPos)
  714. {}
  715. using StandardReceiverVisitor<int3>::operator(); //it removes compilation error... not sure why it *must* be here
  716. void operator()(TNormalBodyOption const& trig) const
  717. {
  718. switch(trig.optionCode)
  719. {
  720. case 'B': //removes description hint
  721. {
  722. //TODO
  723. }
  724. break;
  725. case 'C': //sgc of control word of object
  726. {
  727. //TODO
  728. }
  729. break;
  730. case 'D': //disable gamer to use object
  731. {
  732. //TODO
  733. }
  734. break;
  735. case 'E': //enable gamer to use object
  736. {
  737. //TODO
  738. }
  739. break;
  740. case 'H': //replace hint for object
  741. {
  742. //TODO
  743. }
  744. break;
  745. case 'M': //disabling messages and questions
  746. {
  747. //TODO
  748. }
  749. break;
  750. case 'R': //enable all gamers to use object
  751. {
  752. //TODO
  753. }
  754. break;
  755. case 'S': //disable all gamers to use object
  756. {
  757. //TODO
  758. }
  759. break;
  760. case 'T': //sgc of obj type
  761. {
  762. //TODO
  763. }
  764. break;
  765. case 'U': //sgc of obj subtype
  766. {
  767. if(trig.params.size() == 1)
  768. boost::apply_visitor(OB_UPerformer(const_cast<OBPerformer&>(*this)), trig.params[0]);
  769. else
  770. throw EScriptExecError("OB:U takes exactly one parameter!");
  771. }
  772. break;
  773. default:
  774. throw EScriptExecError("Wrong OB receiver option!");
  775. break;
  776. }
  777. }
  778. };
  779. void OB_UPerformer::operator()( TIexp const& cmp ) const
  780. {
  781. IexpValStr val = owner.interp->getIexp(cmp);
  782. }
  783. void OB_UPerformer::operator()( TVarpExp const& cmp ) const
  784. {
  785. IexpValStr val = owner.interp->getIexp(cmp);
  786. }
  787. struct ERMExpDispatch : boost::static_visitor<>
  788. {
  789. ERMInterpreter * owner;
  790. ERMExpDispatch(ERMInterpreter * _owner) : owner(_owner)
  791. {}
  792. void operator()(Ttrigger const& trig) const
  793. {
  794. throw EInterpreterError("Triggers cannot be executed!");
  795. }
  796. void operator()(Tinstruction const& trig) const
  797. {
  798. }
  799. void operator()(Treceiver const& trig) const
  800. {
  801. struct HLP
  802. {
  803. ERMInterpreter * ei;
  804. HLP(ERMInterpreter * interp) : ei(interp)
  805. {}
  806. int3 getPosFromIdentifier(ERM::Tidentifier tid, bool allowDummyFourth)
  807. {
  808. switch(tid.size())
  809. {
  810. case 1:
  811. {
  812. int num = ei->getIexp(tid[0]).getInt();
  813. return int3(ei->ermGlobalEnv->getStandardVar(num),
  814. ei->ermGlobalEnv->getStandardVar(num+1),
  815. ei->ermGlobalEnv->getStandardVar(num+2));
  816. }
  817. break;
  818. case 3:
  819. case 4:
  820. if(tid.size() == 4 && !allowDummyFourth)
  821. throw EScriptExecError("4 items in identifirer are not allowed for this receiver!");
  822. return int3(ei->getIexp(tid[0]).getInt(),
  823. ei->getIexp(tid[1]).getInt(),
  824. ei->getIexp(tid[2]).getInt());
  825. break;
  826. default:
  827. throw EScriptExecError("This receiver takes 1 or 3 items in identifier!");
  828. break;
  829. }
  830. }
  831. };
  832. if(trig.name == "VR")
  833. {
  834. //check condition
  835. if(trig.condition.is_initialized())
  836. {
  837. if( !owner->checkCondition(trig.condition.get()) )
  838. return;
  839. }
  840. //perform operations
  841. if(trig.identifier.is_initialized())
  842. {
  843. ERM::Tidentifier ident = trig.identifier.get();
  844. if(ident.size() == 1)
  845. {
  846. IexpValStr ievs = owner->getIexp(ident[0]);
  847. //see body
  848. if(trig.body.is_initialized())
  849. {
  850. ERM::Tbody bo = trig.body.get();
  851. for(int g=0; g<bo.size(); ++g)
  852. {
  853. boost::apply_visitor(VRPerformer(owner, ievs), bo[g]);
  854. }
  855. }
  856. }
  857. else
  858. throw EScriptExecError("VR receiver must be used with exactly one identifier item!");
  859. }
  860. else
  861. throw EScriptExecError("VR receiver must be used with an identifier!");
  862. }
  863. else if(trig.name == "DO")
  864. {
  865. //perform operations
  866. if(trig.identifier.is_initialized())
  867. {
  868. ERM::Tidentifier tid = trig.identifier.get();
  869. if(tid.size() != 4)
  870. {
  871. throw EScriptExecError("DO receiver takes exactly 4 arguments");
  872. }
  873. int funNum = owner->getIexp(tid[0]).getInt(),
  874. startVal = owner->getIexp(tid[1]).getInt(),
  875. stopVal = owner->getIexp(tid[2]).getInt(),
  876. increment = owner->getIexp(tid[3]).getInt();
  877. for(int it = startVal; it < stopVal; it += increment)
  878. {
  879. std::vector<int> params(FunctionLocalVars::NUM_PARAMETERS, 0);
  880. params.back() = it;
  881. //owner->getFuncVars(funNum)->getParam(16) = it;
  882. ERMInterpreter::TIDPattern tip;
  883. std::vector<int> v1;
  884. v1 += funNum;
  885. insert(tip) (v1.size(), v1);
  886. owner->executeTriggerType(TriggerType("FU"), true, tip, params);
  887. it = owner->getFuncVars(funNum)->getParam(16);
  888. }
  889. }
  890. }
  891. else if(trig.name == "MO")
  892. {
  893. int3 objPos;
  894. if(trig.identifier.is_initialized())
  895. {
  896. ERM::Tidentifier tid = trig.identifier.get();
  897. objPos = HLP(owner).getPosFromIdentifier(tid, true);
  898. }
  899. else
  900. throw EScriptExecError("MO receiver must have an identifier!");
  901. }
  902. else if(trig.name == "OB")
  903. {
  904. int3 objPos;
  905. if(trig.identifier.is_initialized())
  906. {
  907. ERM::Tidentifier tid = trig.identifier.get();
  908. objPos = HLP(owner).getPosFromIdentifier(tid, false);
  909. //execute body
  910. if(trig.body.is_initialized())
  911. {
  912. ERM::Tbody bo = trig.body.get();
  913. for(int g=0; g<bo.size(); ++g)
  914. {
  915. boost::apply_visitor(OBPerformer(owner, objPos), bo[g]);
  916. }
  917. }
  918. else
  919. throw EScriptExecError("OB receiver must have body!");
  920. }
  921. else
  922. throw EScriptExecError("OB receiver must have an identifier!");
  923. }
  924. else
  925. {
  926. //not supported or invalid trigger
  927. }
  928. }
  929. void operator()(TPostTrigger const& trig) const
  930. {
  931. throw EInterpreterError("Post-triggers cannot be executed!");
  932. }
  933. };
  934. struct CommandExec : boost::static_visitor<>
  935. {
  936. ERMInterpreter * owner;
  937. CommandExec(ERMInterpreter * _owner) : owner(_owner)
  938. {}
  939. void operator()(Tcommand const& cmd) const
  940. {
  941. boost::apply_visitor(ERMExpDispatch(owner), cmd.cmd);
  942. std::cout << "Line comment: " << cmd.comment << std::endl;
  943. }
  944. void operator()(std::string const& comment) const
  945. {
  946. //comment - do nothing
  947. }
  948. void operator()(spirit::unused_type const& nothing) const
  949. {
  950. //nothing - do nothing
  951. }
  952. };
  953. struct LineExec : boost::static_visitor<>
  954. {
  955. ERMInterpreter * owner;
  956. LineExec(ERMInterpreter * _owner) : owner(_owner)
  957. {}
  958. void operator()(TVExp const& cmd) const
  959. {
  960. //printTVExp(cmd);
  961. }
  962. void operator()(TERMline const& cmd) const
  963. {
  964. boost::apply_visitor(CommandExec(owner), cmd);
  965. }
  966. };
  967. /////////
  968. void ERMInterpreter::executeLine( const LinePointer & lp )
  969. {
  970. tlog0 << "Executing line nr " << getRealLine(lp.lineNum) << " (internal " << lp.lineNum << ") from " << lp.file << std::endl;
  971. boost::apply_visitor(LineExec(this), scripts[lp]);
  972. }
  973. void ERMInterpreter::init()
  974. {
  975. ermGlobalEnv = new ERMEnvironment();
  976. globalEnv = new Environment();
  977. //TODO: reset?
  978. for(int g = 0; g < ARRAY_COUNT(funcVars); ++g)
  979. funcVars[g].reset();
  980. }
  981. IexpValStr ERMInterpreter::getVar(std::string toFollow, boost::optional<int> initVal) const
  982. {
  983. IexpValStr ret;
  984. ret.type = IexpValStr::WRONGVAL;
  985. int initV;
  986. bool hasInit = false;
  987. if(initVal.is_initialized())
  988. {
  989. initV = initVal.get();
  990. hasInit = true;
  991. }
  992. int endNum = 0;
  993. if(toFollow[0] == 'd')
  994. {
  995. endNum = 1;
  996. //TODO: support
  997. }
  998. if(toFollow.size() == 0)
  999. {
  1000. if(hasInit)
  1001. ret = IexpValStr(initV);
  1002. else
  1003. throw EIexpProblem("No input to getVar!");
  1004. return ret;
  1005. }
  1006. //now we have at least one element in toFollow
  1007. for(int b=toFollow.size()-1; b>=endNum; --b)
  1008. {
  1009. bool retIt = b == endNum/*+1*/; //if we should return the value are currently at
  1010. char cr = toFollow[b];
  1011. if(cr == 'c')//write number of current day
  1012. {
  1013. //TODO
  1014. }
  1015. else if(cr == 'd') //info for external env - add i/o set
  1016. {
  1017. throw EIexpProblem("d inside i-expression not allowed!");
  1018. }
  1019. else if(cr == 'e')
  1020. {
  1021. if(hasInit)
  1022. {
  1023. if(retIt)
  1024. {
  1025. //these C-style cast is here just to shut up compiler errors
  1026. if(initV > 0 && initV <= FunctionLocalVars::NUM_FLOATINGS)
  1027. {
  1028. if(curFunc)
  1029. ret = IexpValStr(&curFunc->getFloat(initV));
  1030. else
  1031. throw EIexpProblem("Function context not available!");
  1032. }
  1033. else if(initV < 0 && initV >= -TriggerLocalVars::EVAR_NUM)
  1034. {
  1035. if(curTrigger)
  1036. ret = IexpValStr(&curTrigger->ermLocalVars.getEvar(initV));
  1037. else
  1038. throw EIexpProblem("No trigger context available!");
  1039. }
  1040. else
  1041. throw EIexpProblem("index " + boost::lexical_cast<std::string>(initV) + " not allowed for e array");
  1042. }
  1043. else
  1044. throw EIexpProblem("e variables cannot appear in this context");
  1045. }
  1046. else
  1047. throw EIexpProblem("e variables cannot appear in this context");
  1048. }
  1049. else if(cr >= 'f' && cr <= 't')
  1050. {
  1051. if(retIt)
  1052. ret = IexpValStr(&ermGlobalEnv->getQuickVar(cr));
  1053. else
  1054. {
  1055. if(hasInit)
  1056. throw EIexpProblem("quick variables cannot be used in this context");
  1057. else
  1058. {
  1059. initV = ermGlobalEnv->getQuickVar(cr);
  1060. hasInit = true;
  1061. }
  1062. }
  1063. }
  1064. else if(cr == 'v') //standard variables
  1065. {
  1066. if(hasInit)
  1067. {
  1068. if(retIt)
  1069. ret = IexpValStr(&ermGlobalEnv->getStandardVar(initV));
  1070. else
  1071. initV = ermGlobalEnv->getStandardVar(initV);
  1072. }
  1073. else
  1074. throw EIexpProblem("standard variable cannot be used in this context!");
  1075. }
  1076. else if(cr == 'w') //local hero variables
  1077. {
  1078. //TODO
  1079. }
  1080. else if(cr == 'x') //function parameters
  1081. {
  1082. if(hasInit)
  1083. {
  1084. if(curFunc)
  1085. {
  1086. if(retIt)
  1087. ret = IexpValStr(&curFunc->getParam(initV));
  1088. else
  1089. initV = curFunc->getParam(initV);
  1090. }
  1091. else throw EIexpProblem("Function parameters cannot be used outside a function!");
  1092. }
  1093. else
  1094. throw EIexpProblem("Specify which function parameter should be used");
  1095. }
  1096. else if(cr == 'y')
  1097. {
  1098. if(hasInit)
  1099. {
  1100. if(initV > 0 && initV <= FunctionLocalVars::NUM_LOCALS)
  1101. {
  1102. int &valPtr = curFunc ? curFunc->getLocal(initV) : const_cast<ERMInterpreter&>(*this).getFuncVars(0)->getLocal(initV); //retreive local var if in function or use global set otherwise
  1103. if(retIt)
  1104. ret = IexpValStr(&valPtr);
  1105. else
  1106. initV = curFunc->getLocal(initV);
  1107. }
  1108. else if(initV < 0 && initV >= -TriggerLocalVars::YVAR_NUM)
  1109. {
  1110. if(curTrigger)
  1111. {
  1112. if(retIt)
  1113. ret = IexpValStr(&curTrigger->ermLocalVars.getYvar(initV));
  1114. else
  1115. initV = curTrigger->ermLocalVars.getYvar(initV);
  1116. }
  1117. else
  1118. throw EIexpProblem("Trigger local variables cannot be used outside triggers!");
  1119. }
  1120. else
  1121. throw EIexpProblem("Wrong argument for function local variable!");
  1122. }
  1123. else
  1124. throw EIexpProblem("y variable cannot be used in this context!");
  1125. }
  1126. else if(cr == 'z')
  1127. {
  1128. if(hasInit)
  1129. {
  1130. if(retIt)
  1131. {
  1132. //these C-style casts are here just to shut up compiler errors
  1133. if(initV > 0 )
  1134. ret = IexpValStr(&ermGlobalEnv->getZVar(initV));
  1135. else if(initV < 0)
  1136. {
  1137. if(curFunc)
  1138. ret = IexpValStr(&curFunc->getString(initV));
  1139. else
  1140. throw EIexpProblem("Function local string variables cannot be used outside functions!");
  1141. }
  1142. else
  1143. throw EIexpProblem("Wrong parameter for string variable!");
  1144. }
  1145. else
  1146. throw EIexpProblem("String variables can only be returned!");
  1147. }
  1148. else
  1149. throw EIexpProblem("String variables cannot be used in this context!");
  1150. }
  1151. else
  1152. {
  1153. throw EIexpProblem(std::string("Symbol ") + cr + " is not allowed in this context!");
  1154. }
  1155. }
  1156. return ret;
  1157. }
  1158. namespace IexpDisemboweler
  1159. {
  1160. enum EDir{GET, SET};
  1161. }
  1162. struct LVL2IexpDisemboweler : boost::static_visitor<IexpValStr>
  1163. {
  1164. IexpDisemboweler::EDir dir;
  1165. /*const*/ ERMInterpreter * env;
  1166. LVL2IexpDisemboweler(/*const*/ ERMInterpreter * _env, IexpDisemboweler::EDir _dir)
  1167. : env(_env), dir(_dir) //writes value to given var
  1168. {}
  1169. IexpValStr processNotMacro(const TVarExpNotMacro & val) const
  1170. {
  1171. if(val.questionMark.is_initialized())
  1172. throw EIexpProblem("Question marks ('?') are not allowed in getter i-expressions");
  1173. //const-cast just to do some code-reuse...
  1174. return env->getVar(val.varsym, val.val);
  1175. }
  1176. IexpValStr operator()(TVarExpNotMacro const& val) const
  1177. {
  1178. return processNotMacro(val);
  1179. }
  1180. IexpValStr operator()(TMacroUsage const& val) const
  1181. {
  1182. return env->getIexp(val);
  1183. }
  1184. };
  1185. struct LVL1IexpDisemboweler : boost::static_visitor<IexpValStr>
  1186. {
  1187. IexpDisemboweler::EDir dir;
  1188. /*const*/ ERMInterpreter * env;
  1189. LVL1IexpDisemboweler(/*const*/ ERMInterpreter * _env, IexpDisemboweler::EDir _dir)
  1190. : env(_env), dir(_dir) //writes value to given var
  1191. {}
  1192. IexpValStr operator()(int const & constant) const
  1193. {
  1194. if(dir == IexpDisemboweler::GET)
  1195. {
  1196. return IexpValStr(constant);
  1197. }
  1198. else
  1199. {
  1200. throw EIexpProblem("Cannot set a constant!");
  1201. }
  1202. }
  1203. IexpValStr operator()(TVarExp const & var) const
  1204. {
  1205. return boost::apply_visitor(LVL2IexpDisemboweler(env, dir), var);
  1206. }
  1207. };
  1208. IexpValStr ERMInterpreter::getIexp( const ERM::TIexp & iexp ) const
  1209. {
  1210. return boost::apply_visitor(LVL1IexpDisemboweler(const_cast<ERMInterpreter*>(this), IexpDisemboweler::GET), iexp);
  1211. }
  1212. IexpValStr ERMInterpreter::getIexp( const ERM::TMacroUsage & macro ) const
  1213. {
  1214. std::map<std::string, ERM::TVarExpNotMacro>::const_iterator it =
  1215. ermGlobalEnv->macroBindings.find(macro.macro);
  1216. if(it == ermGlobalEnv->macroBindings.end())
  1217. throw EUsageOfUndefinedMacro(macro.macro);
  1218. return getVar(it->second.varsym, it->second.val);
  1219. }
  1220. IexpValStr ERMInterpreter::getIexp( const ERM::TIdentifierInternal & tid ) const
  1221. {
  1222. if(tid.which() == 0)
  1223. {
  1224. return getIexp(boost::get<ERM::TIexp>(tid));
  1225. }
  1226. else
  1227. throw EScriptExecError("Identifier must be a valid i-expression to perform this operation!");
  1228. }
  1229. IexpValStr ERMInterpreter::getIexp( const ERM::TVarpExp & tid ) const
  1230. {
  1231. return boost::apply_visitor(LVL2IexpDisemboweler(const_cast<ERMInterpreter*>(this), IexpDisemboweler::GET), tid.var);
  1232. }
  1233. void ERMInterpreter::executeTriggerType( VERMInterpreter::TriggerType tt, bool pre, const TIDPattern & identifier, const std::vector<int> &funParams/*=std::vector<int>()*/ )
  1234. {
  1235. struct HLP
  1236. {
  1237. static int calcFunNum(VERMInterpreter::TriggerType tt, const TIDPattern & identifier)
  1238. {
  1239. if(tt.type != VERMInterpreter::TriggerType::FU)
  1240. return -1;
  1241. return identifier.begin()->second[0];
  1242. }
  1243. };
  1244. TtriggerListType & triggerList = pre ? triggers : postTriggers;
  1245. TriggerIdentifierMatch tim;
  1246. tim.allowNoIdetifier = false;
  1247. tim.ermEnv = this;
  1248. tim.matchToIt = identifier;
  1249. std::vector<Trigger> & triggersToTry = triggerList[tt];
  1250. for(int g=0; g<triggersToTry.size(); ++g)
  1251. {
  1252. if(tim.tryMatch(&triggersToTry[g]))
  1253. {
  1254. curTrigger = &triggersToTry[g];
  1255. executeTrigger(triggersToTry[g], HLP::calcFunNum(tt, identifier), funParams);
  1256. }
  1257. }
  1258. }
  1259. void ERMInterpreter::executeTriggerType(const char *trigger, int id)
  1260. {
  1261. TIDPattern tip;
  1262. tip[0] = std::vector<int>(1, id);
  1263. executeTriggerType(VERMInterpreter::TriggerType(trigger), true, tip);
  1264. }
  1265. void ERMInterpreter::executeTriggerType(const char *trigger)
  1266. {
  1267. executeTriggerType(VERMInterpreter::TriggerType(trigger), true, TIDPattern());
  1268. }
  1269. ERM::Ttrigger ERMInterpreter::retrieveTrigger( ERM::TLine line )
  1270. {
  1271. if(line.which() == 1)
  1272. {
  1273. ERM::TERMline tl = boost::get<ERM::TERMline>(line);
  1274. if(tl.which() == 0)
  1275. {
  1276. ERM::Tcommand tcm = boost::get<ERM::Tcommand>(tl);
  1277. if(tcm.cmd.which() == 0)
  1278. {
  1279. return boost::get<ERM::Ttrigger>(tcm.cmd);
  1280. }
  1281. throw ELineProblem("Given line is not a trigger!");
  1282. }
  1283. throw ELineProblem("Given line is not a command!");
  1284. }
  1285. throw ELineProblem("Given line is not an ERM trigger!");
  1286. }
  1287. template<typename T>
  1288. bool compareExp(const T & lhs, const T & rhs, std::string op)
  1289. {
  1290. if(op == "<")
  1291. {
  1292. return lhs < rhs;
  1293. }
  1294. else if(op == ">")
  1295. {
  1296. return lhs > rhs;
  1297. }
  1298. else if(op == ">=" || op == "=>")
  1299. {
  1300. return lhs >= rhs;
  1301. }
  1302. else if(op == "<=" || op == "=<")
  1303. {
  1304. return lhs <= rhs;
  1305. }
  1306. else if(op == "==")
  1307. {
  1308. return lhs == rhs;
  1309. }
  1310. else if(op == "<>" || op == "><")
  1311. {
  1312. return lhs != rhs;
  1313. }
  1314. else
  1315. throw EScriptExecError(std::string("Wrong comparison sign: ") + op);
  1316. }
  1317. struct ConditionDisemboweler : boost::static_visitor<bool>
  1318. {
  1319. ConditionDisemboweler(ERMInterpreter * _ei) : ei(_ei)
  1320. {}
  1321. bool operator()(TComparison const & cmp) const
  1322. {
  1323. IexpValStr lhs = ei->getIexp(cmp.lhs),
  1324. rhs = ei->getIexp(cmp.rhs);
  1325. switch (lhs.type)
  1326. {
  1327. case IexpValStr::FLOATVAR:
  1328. switch (rhs.type)
  1329. {
  1330. case IexpValStr::FLOATVAR:
  1331. return compareExp(lhs.getFloat(), rhs.getFloat(), cmp.compSign);
  1332. break;
  1333. default:
  1334. throw EScriptExecError("Incompatible types for comparison");
  1335. }
  1336. break;
  1337. case IexpValStr::INT:
  1338. case IexpValStr::INTVAR:
  1339. switch (rhs.type)
  1340. {
  1341. case IexpValStr::INT:
  1342. case IexpValStr::INTVAR:
  1343. return compareExp(lhs.getInt(), rhs.getInt(), cmp.compSign);
  1344. break;
  1345. default:
  1346. throw EScriptExecError("Incompatible types for comparison");
  1347. }
  1348. break;
  1349. case IexpValStr::STRINGVAR:
  1350. switch (rhs.type)
  1351. {
  1352. case IexpValStr::STRINGVAR:
  1353. return compareExp(lhs.getString(), rhs.getString(), cmp.compSign);
  1354. break;
  1355. default:
  1356. throw EScriptExecError("Incompatible types for comparison");
  1357. }
  1358. break;
  1359. default:
  1360. throw EScriptExecError("Wrong type of left iexp!");
  1361. }
  1362. //we should never reach this place
  1363. }
  1364. bool operator()(int const & flag) const
  1365. {
  1366. return ei->ermGlobalEnv->getFlag(flag);
  1367. }
  1368. private:
  1369. ERMInterpreter * ei;
  1370. };
  1371. bool ERMInterpreter::checkCondition( ERM::Tcondition cond )
  1372. {
  1373. bool ret = boost::apply_visitor(ConditionDisemboweler(this), cond.cond);
  1374. if(cond.rhs.is_initialized())
  1375. { //taking care of rhs expression
  1376. bool rhs = checkCondition(cond.rhs.get().get());
  1377. switch (cond.ctype)
  1378. {
  1379. case '&':
  1380. ret &= rhs;
  1381. break;
  1382. case '|':
  1383. ret |= rhs;
  1384. break;
  1385. case 'X':
  1386. ret ^= rhs;
  1387. break;
  1388. default:
  1389. throw EInterpreterProblem(std::string("Strange - wrong condition connection (") + cond.ctype + ") !");
  1390. break;
  1391. }
  1392. }
  1393. return ret;
  1394. }
  1395. FunctionLocalVars * ERMInterpreter::getFuncVars( int funNum )
  1396. {
  1397. if(funNum >= ARRAY_COUNT(funcVars) || funNum < 0)
  1398. throw EScriptExecError("Attempt of accessing variables of function with index out of boundaries!");
  1399. return funcVars + funNum;
  1400. }
  1401. void ERMInterpreter::executeInstructions()
  1402. {
  1403. //TODO implement me
  1404. }
  1405. int ERMInterpreter::getRealLine(int lineNum)
  1406. {
  1407. for(std::map<VERMInterpreter::LinePointer, ERM::TLine>::const_iterator i = scripts.begin(); i != scripts.end(); i++)
  1408. if(i->first.lineNum == lineNum)
  1409. return i->first.realLineNum;
  1410. return -1;
  1411. }
  1412. void ERMInterpreter::setCurrentlyVisitedObj( int3 pos )
  1413. {
  1414. ermGlobalEnv->getStandardVar(998) = pos.x;
  1415. ermGlobalEnv->getStandardVar(999) = pos.y;
  1416. ermGlobalEnv->getStandardVar(1000) = pos.z;
  1417. }
  1418. const std::string ERMInterpreter::triggerSymbol = "trigger";
  1419. const std::string ERMInterpreter::postTriggerSymbol = "postTrigger";
  1420. const std::string ERMInterpreter::defunSymbol = "defun";
  1421. struct TriggerIdMatchHelper : boost::static_visitor<>
  1422. {
  1423. int & ret;
  1424. ERMInterpreter * interpreter;
  1425. Trigger * trig;
  1426. TriggerIdMatchHelper(int & b, ERMInterpreter * ermint, Trigger * _trig)
  1427. : ret(b), interpreter(ermint), trig(_trig)
  1428. {}
  1429. void operator()(TIexp const& iexp) const
  1430. {
  1431. IexpValStr val = interpreter->getIexp(iexp);
  1432. switch(val.type)
  1433. {
  1434. case IexpValStr::INT:
  1435. case IexpValStr::INTVAR:
  1436. ret = val.getInt();
  1437. break;
  1438. default:
  1439. throw EScriptExecError("Incompatible i-exp type!");
  1440. break;
  1441. }
  1442. }
  1443. void operator()(TArithmeticOp const& arop) const
  1444. {
  1445. //error?!?
  1446. }
  1447. };
  1448. bool TriggerIdentifierMatch::tryMatch( Trigger * interptrig ) const
  1449. {
  1450. bool ret = true;
  1451. const ERM::Ttrigger & trig = ERMInterpreter::retrieveTrigger(ermEnv->retrieveLine(interptrig->line));
  1452. if(trig.identifier.is_initialized())
  1453. {
  1454. ERM::Tidentifier tid = trig.identifier.get();
  1455. std::map< int, std::vector<int> >::const_iterator it = matchToIt.find(tid.size());
  1456. if(it == matchToIt.end())
  1457. ret = false;
  1458. else
  1459. {
  1460. const std::vector<int> & pattern = it->second;
  1461. for(int g=0; g<pattern.size(); ++g)
  1462. {
  1463. int val = -1;
  1464. boost::apply_visitor(TriggerIdMatchHelper(val, ermEnv, interptrig), tid[g]);
  1465. if(pattern[g] != val)
  1466. {
  1467. ret = false;
  1468. }
  1469. }
  1470. }
  1471. }
  1472. else
  1473. {
  1474. ret = allowNoIdetifier;
  1475. }
  1476. //check condition
  1477. if(ret)
  1478. {
  1479. if(trig.condition.is_initialized())
  1480. {
  1481. return ermEnv->checkCondition(trig.condition.get());
  1482. }
  1483. else //no condition
  1484. return true;
  1485. }
  1486. else
  1487. return false;
  1488. }
  1489. VERMInterpreter::ERMEnvironment::ERMEnvironment()
  1490. {
  1491. for(int g=0; g<NUM_QUICKS; ++g)
  1492. quickVars[g] = 0;
  1493. for(int g=0; g<NUM_STANDARDS; ++g)
  1494. standardVars[g] = 0;
  1495. //string should be automatically initialized to ""
  1496. for(int g=0; g<NUM_FLAGS; ++g)
  1497. flags[g] = false;
  1498. }
  1499. int & VERMInterpreter::ERMEnvironment::getQuickVar( const char letter )
  1500. {
  1501. assert(letter >= 'f' && letter <= 't'); //it should be check by another function, just making sure here
  1502. return quickVars[letter - 'f'];
  1503. }
  1504. int & VERMInterpreter::ERMEnvironment::getStandardVar( int num )
  1505. {
  1506. if(num < 1 || num > NUM_STANDARDS)
  1507. throw EScriptExecError("Number of standard variable out of bounds");
  1508. return standardVars[num-1];
  1509. }
  1510. std::string & VERMInterpreter::ERMEnvironment::getZVar( int num )
  1511. {
  1512. if(num < 1 || num > NUM_STRINGS)
  1513. throw EScriptExecError("Number of string variable out of bounds");
  1514. return strings[num-1];
  1515. }
  1516. bool & VERMInterpreter::ERMEnvironment::getFlag( int num )
  1517. {
  1518. if(num < 1 || num > NUM_FLAGS)
  1519. throw EScriptExecError("Number of flag out of bounds");
  1520. return flags[num-1];
  1521. }
  1522. VERMInterpreter::TriggerLocalVars::TriggerLocalVars()
  1523. {
  1524. for(int g=0; g<EVAR_NUM; ++g)
  1525. evar[g] = 0.0;
  1526. for(int g=0; g<YVAR_NUM; ++g)
  1527. yvar[g] = 0;
  1528. }
  1529. double & VERMInterpreter::TriggerLocalVars::getEvar( int num )
  1530. {
  1531. num = -num;
  1532. if(num < 1 || num > EVAR_NUM)
  1533. throw EScriptExecError("Number of trigger local floating point variable out of bounds");
  1534. return evar[num-1];
  1535. }
  1536. int & VERMInterpreter::TriggerLocalVars::getYvar( int num )
  1537. {
  1538. num = -num; //we handle negative indices
  1539. if(num < 1 || num > YVAR_NUM)
  1540. throw EScriptExecError("Number of trigger local variable out of bounds");
  1541. return yvar[num-1];
  1542. }
  1543. bool VERMInterpreter::Environment::isBound( const std::string & name, bool globalOnly ) const
  1544. {
  1545. std::map<std::string, TVOption>::const_iterator it = symbols.find(name);
  1546. if(globalOnly && parent)
  1547. {
  1548. return parent->isBound(name, globalOnly);
  1549. }
  1550. //we have it; if globalOnly is true, lexical parent is false here so we are global env
  1551. if(it != symbols.end())
  1552. return true;
  1553. //here, we don;t have it; but parent can have
  1554. if(parent)
  1555. return parent->isBound(name, globalOnly);
  1556. return false;
  1557. }
  1558. ERM::TVOption VERMInterpreter::Environment::retrieveValue( const std::string & name ) const
  1559. {
  1560. std::map<std::string, TVOption>::const_iterator it = symbols.find(name);
  1561. if(it == symbols.end())
  1562. {
  1563. if(parent)
  1564. {
  1565. return parent->retrieveValue(name);
  1566. }
  1567. throw ESymbolNotFound(name);
  1568. }
  1569. return it->second;
  1570. }
  1571. bool VERMInterpreter::Environment::unbind( const std::string & name, EUnbindMode mode )
  1572. {
  1573. if(isBound(name, false))
  1574. {
  1575. if(symbols.find(name) != symbols.end()) //result of isBound could be from higher lexical env
  1576. symbols.erase(symbols.find(name));
  1577. if(mode == FULLY_RECURSIVE && parent)
  1578. parent->unbind(name, mode);
  1579. return true;
  1580. }
  1581. if(parent && (mode == RECURSIVE_UNTIL_HIT || mode == FULLY_RECURSIVE))
  1582. return parent->unbind(name, mode);
  1583. //neither bound nor have lexical parent
  1584. return false;
  1585. }
  1586. int & VERMInterpreter::FunctionLocalVars::getParam( int num )
  1587. {
  1588. if(num < 1 || num > NUM_PARAMETERS)
  1589. throw EScriptExecError("Number of parameter out of bounds");
  1590. return params[num-1];
  1591. }
  1592. int & VERMInterpreter::FunctionLocalVars::getLocal( int num )
  1593. {
  1594. if(num < 1 || num > NUM_LOCALS)
  1595. throw EScriptExecError("Number of local variable out of bounds");
  1596. return locals[num-1];
  1597. }
  1598. std::string & VERMInterpreter::FunctionLocalVars::getString( int num )
  1599. {
  1600. num = -num; //we deal with negative indices
  1601. if(num < 1 || num > NUM_PARAMETERS)
  1602. throw EScriptExecError("Number of function local string variable out of bounds");
  1603. return strings[num-1];
  1604. }
  1605. double & VERMInterpreter::FunctionLocalVars::getFloat( int num )
  1606. {
  1607. if(num < 1 || num > NUM_FLOATINGS)
  1608. throw EScriptExecError("Number of float var out of bounds");
  1609. return floats[num-1];
  1610. }
  1611. void VERMInterpreter::FunctionLocalVars::reset()
  1612. {
  1613. for(int g=0; g<ARRAY_COUNT(params); ++g)
  1614. params[g] = 0;
  1615. for(int g=0; g<ARRAY_COUNT(locals); ++g)
  1616. locals[g] = 0;
  1617. for(int g=0; g<ARRAY_COUNT(strings); ++g)
  1618. strings[g] = "";
  1619. for(int g=0; g<ARRAY_COUNT(floats); ++g)
  1620. floats[g] = 0.0;
  1621. }
  1622. void IexpValStr::setTo( const IexpValStr & second )
  1623. {
  1624. switch(type)
  1625. {
  1626. case IexpValStr::FLOATVAR:
  1627. *val.flvar = second.getFloat();
  1628. break;
  1629. case IexpValStr::INT:
  1630. throw EScriptExecError("VR S: value not assignable!");
  1631. break;
  1632. case IexpValStr::INTVAR:
  1633. *val.integervar = second.getInt();
  1634. break;
  1635. case IexpValStr::STRINGVAR:
  1636. *val.stringvar = second.getString();
  1637. break;
  1638. default:
  1639. throw EScriptExecError("Wrong type of identifier iexp!");
  1640. }
  1641. }
  1642. void IexpValStr::setTo( int val )
  1643. {
  1644. switch(type)
  1645. {
  1646. case INTVAR:
  1647. *this->val.integervar = val;
  1648. break;
  1649. default:
  1650. throw EIexpProblem("Incompatible type!");
  1651. break;
  1652. }
  1653. }
  1654. void IexpValStr::setTo( float val )
  1655. {
  1656. switch(type)
  1657. {
  1658. case FLOATVAR:
  1659. *this->val.flvar = val;
  1660. break;
  1661. default:
  1662. throw EIexpProblem("Incompatible type!");
  1663. break;
  1664. }
  1665. }
  1666. void IexpValStr::setTo( const std::string & val )
  1667. {
  1668. switch(type)
  1669. {
  1670. case STRINGVAR:
  1671. *this->val.stringvar = val;
  1672. break;
  1673. default:
  1674. throw EIexpProblem("Incompatible type!");
  1675. break;
  1676. }
  1677. }
  1678. int IexpValStr::getInt() const
  1679. {
  1680. switch(type)
  1681. {
  1682. case IexpValStr::INT:
  1683. return val.val;
  1684. break;
  1685. case IexpValStr::INTVAR:
  1686. return *val.integervar;
  1687. break;
  1688. default:
  1689. throw EIexpProblem("Cannot get iexp as int!");
  1690. break;
  1691. }
  1692. }
  1693. float IexpValStr::getFloat() const
  1694. {
  1695. switch(type)
  1696. {
  1697. case IexpValStr::FLOATVAR:
  1698. return *val.flvar;
  1699. break;
  1700. default:
  1701. throw EIexpProblem("Cannot get iexp as float!");
  1702. break;
  1703. }
  1704. }
  1705. std::string IexpValStr::getString() const
  1706. {
  1707. switch(type)
  1708. {
  1709. case IexpValStr::STRINGVAR:
  1710. return *val.stringvar;
  1711. break;
  1712. default:
  1713. throw EScriptExecError("Cannot get iexp as string!");
  1714. break;
  1715. }
  1716. }