ERMInterpreter.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888
  1. #pragma once
  2. #include "../global.h"
  3. #include "ERMParser.h"
  4. #include "IGameEventsReceiver.h"
  5. #include "ERMScriptModule.h"
  6. /*
  7. * ERMInterpreter.h, 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 VERMInterpreter
  16. {
  17. using namespace ERM;
  18. //different exceptions that can be thrown during interpreting
  19. class EInterpreterProblem : public std::exception
  20. {
  21. std::string problem;
  22. public:
  23. const char * what() const throw() OVERRIDE
  24. {
  25. return problem.c_str();
  26. }
  27. ~EInterpreterProblem() throw()
  28. {}
  29. EInterpreterProblem(const std::string & problemDesc) : problem(problemDesc)
  30. {}
  31. };
  32. struct ESymbolNotFound : public EInterpreterProblem
  33. {
  34. ESymbolNotFound(const std::string & sym) :
  35. EInterpreterProblem(std::string("Symbol \"") + sym + std::string("\" not found!"))
  36. {}
  37. };
  38. struct EInvalidTrigger : public EInterpreterProblem
  39. {
  40. EInvalidTrigger(const std::string & sym) :
  41. EInterpreterProblem(std::string("Trigger \"") + sym + std::string("\" is invalid!"))
  42. {}
  43. };
  44. struct EUsageOfUndefinedMacro : public EInterpreterProblem
  45. {
  46. EUsageOfUndefinedMacro(const std::string & macro) :
  47. EInterpreterProblem(std::string("Macro ") + macro + " is undefined")
  48. {}
  49. };
  50. struct EIexpProblem : public EInterpreterProblem
  51. {
  52. EIexpProblem(const std::string & desc) :
  53. EInterpreterProblem(desc)
  54. {}
  55. };
  56. struct ELineProblem : public EInterpreterProblem
  57. {
  58. ELineProblem(const std::string & desc) :
  59. EInterpreterProblem(desc)
  60. {}
  61. };
  62. struct EExecutionError : public EInterpreterProblem
  63. {
  64. EExecutionError(const std::string & desc) :
  65. EInterpreterProblem(desc)
  66. {}
  67. };
  68. //internal interpreter error related to execution
  69. struct EInterpreterError : public EExecutionError
  70. {
  71. EInterpreterError(const std::string & desc) :
  72. EExecutionError(desc)
  73. {}
  74. };
  75. //wrong script
  76. struct EScriptExecError : public EExecutionError
  77. {
  78. EScriptExecError(const std::string & desc) :
  79. EExecutionError(desc)
  80. {}
  81. };
  82. //wrong script
  83. struct EVermScriptExecError : public EScriptExecError
  84. {
  85. EVermScriptExecError(const std::string & desc) :
  86. EScriptExecError(desc)
  87. {}
  88. };
  89. // All numeric variables are integer variables and have a range of -2147483647...+2147483647
  90. // c stores game active day number //indirect variable
  91. // d current value //not an actual variable but a modifier
  92. // e1..e100 Function floating point variables //local
  93. // e-1..e-100 Trigger local floating point variables //local
  94. // 'f'..'t' Standard variables ('quick variables') //global
  95. // v1..v1000 Standard variables //global
  96. // w1..w100 Hero variables
  97. // w101..w200 Hero variables
  98. // x1..x16 Function parameters //local
  99. // y1..y100 Function local variables //local
  100. // y-1..y-100 Trigger-based local integer variables //local
  101. // z1..z1000 String variables //global
  102. // z-1..z-10 Function local string variables //local
  103. struct TriggerLocalVars
  104. {
  105. static const int EVAR_NUM = 100; //number of evar locals
  106. static const int YVAR_NUM = 100; //number of yvar locals
  107. TriggerLocalVars();
  108. double & getEvar(int num);
  109. int & getYvar(int num);
  110. private:
  111. double evar[EVAR_NUM]; //negative indices
  112. int yvar[YVAR_NUM];
  113. };
  114. struct FunctionLocalVars
  115. {
  116. static const int NUM_PARAMETERS = 16; //number of function parameters
  117. static const int NUM_LOCALS = 100;
  118. static const int NUM_STRINGS = 10;
  119. static const int NUM_FLOATINGS = 100;
  120. int & getParam(int num);
  121. int & getLocal(int num);
  122. std::string & getString(int num);
  123. double & getFloat(int num);
  124. void reset();
  125. private:
  126. int params[NUM_PARAMETERS]; //x-vars
  127. int locals[NUM_LOCALS]; //y-vars
  128. std::string strings[NUM_STRINGS]; //z-vars (negative indices)
  129. double floats[NUM_FLOATINGS]; //e-vars (positive indices)
  130. };
  131. struct ERMEnvironment
  132. {
  133. ERMEnvironment();
  134. static const int NUM_QUICKS = 't' - 'f' + 1; //it should be 15
  135. int & getQuickVar(const char letter); //'f' - 't' variables
  136. int & getStandardVar(int num); //get v-variable
  137. std::string & getZVar(int num);
  138. bool & getFlag(int num);
  139. static const int NUM_STANDARDS = 10000;
  140. static const int NUM_STRINGS = 1000;
  141. std::map<std::string, ERM::TVarExpNotMacro> macroBindings;
  142. static const int NUM_FLAGS = 1000;
  143. private:
  144. int quickVars[NUM_QUICKS]; //referenced by letter ('f' to 't' inclusive)
  145. int standardVars[NUM_STANDARDS]; //v-vars
  146. std::string strings[NUM_STRINGS]; //z-vars (positive indices)
  147. bool flags[NUM_FLAGS];
  148. };
  149. struct TriggerType
  150. {
  151. //the same order of trigger types in this enum and in validTriggers array is obligatory!
  152. enum ETrigType{AE, BA, BF, BG, BR, CM, CO, FU, GE, GM, HE, HL, HM, IP, LE, MF, MG, MM, MR,
  153. MW, OB, PI, SN, TH, TM} type;
  154. static ETrigType convertTrigger(const std::string & trig)
  155. {
  156. static const std::string validTriggers[] = {"AE", "BA", "BF", "BG", "BR", "CM", "CO", "FU",
  157. "GE", "GM", "HE", "HL", "HM", "IP", "LE", "MF", "MG", "MM", "MR", "MW", "OB", "PI", "SN",
  158. "TH", "TM"};
  159. for(int i=0; i<ARRAY_COUNT(validTriggers); ++i)
  160. {
  161. if(validTriggers[i] == trig)
  162. return static_cast<ETrigType>(i);
  163. }
  164. throw EInvalidTrigger(trig);
  165. }
  166. bool operator<(const TriggerType & t2) const
  167. {
  168. return type < t2.type;
  169. }
  170. TriggerType(const std::string & sym)
  171. {
  172. type = convertTrigger(sym);
  173. }
  174. };
  175. struct FileInfo
  176. {
  177. std::string filename;
  178. int length;
  179. };
  180. struct LinePointer
  181. {
  182. const FileInfo * file; //non-owning
  183. int lineNum;
  184. int realLineNum;
  185. LinePointer() : file(NULL)
  186. {}
  187. LinePointer(const FileInfo * finfo, int line, int _realLineNum) : file(finfo), lineNum(line),
  188. realLineNum(_realLineNum)
  189. {}
  190. //lexicographical order
  191. bool operator<(const LinePointer & rhs) const
  192. {
  193. if(file->filename != rhs.file->filename)
  194. return file->filename < rhs.file->filename;
  195. return lineNum < rhs.lineNum;
  196. }
  197. bool operator!=(const LinePointer & rhs) const
  198. {
  199. return file->filename != rhs.file->filename || lineNum != rhs.lineNum;
  200. }
  201. LinePointer & operator++()
  202. {
  203. ++lineNum;
  204. return *this;
  205. }
  206. bool isValid() const
  207. {
  208. return file && lineNum < file->length;
  209. }
  210. };
  211. struct LexicalPtr
  212. {
  213. LinePointer line; //where to start
  214. std::vector<int> entryPoints; //defines how to pass to current location
  215. bool operator<(const LexicalPtr & sec) const
  216. {
  217. if(line != sec.line)
  218. return line < sec.line;
  219. if(entryPoints.size() != sec.entryPoints.size())
  220. return entryPoints.size() < sec.entryPoints.size();
  221. for(int g=0; g<entryPoints.size(); ++g)
  222. {
  223. if(entryPoints[g] < sec.entryPoints[g])
  224. return true;
  225. }
  226. return false;
  227. }
  228. };
  229. //call stack, represents dynamic range
  230. struct Stack
  231. {
  232. std::vector<LexicalPtr> stack;
  233. };
  234. struct Trigger
  235. {
  236. LinePointer line;
  237. TriggerLocalVars ermLocalVars;
  238. Stack * stack; //where we are stuck at execution
  239. Trigger() : stack(NULL)
  240. {}
  241. };
  242. //verm goodies
  243. struct VSymbol
  244. {
  245. std::string text;
  246. VSymbol(const std::string & txt) : text(txt)
  247. {}
  248. };
  249. struct VNode;
  250. struct VOptionList;
  251. struct VNIL
  252. {};
  253. typedef boost::variant<char, double, int, std::string> TLiteral;
  254. //for operator <, but this one seems to be implemented in boost alerady
  255. struct _opLTvis : boost::static_visitor<bool>
  256. {
  257. const TLiteral & lhs;
  258. _opLTvis(const TLiteral & _lhs) : lhs(_lhs)
  259. {}
  260. template<typename OP>
  261. bool operator()(OP const & rhs) const
  262. {
  263. return boost::get<OP>(lhs) < rhs;
  264. }
  265. };
  266. // bool operator<(const TLiteral & t1, const TLiteral & t2)
  267. // {
  268. // if(t1.type() == t2.type())
  269. // {
  270. // return boost::apply_visitor(_opLTvis(t1), t2);
  271. // }
  272. // throw EVermScriptExecError("These types are incomparable!");
  273. // }
  274. //for operator <=
  275. struct _opLEvis : boost::static_visitor<bool>
  276. {
  277. const TLiteral & lhs;
  278. _opLEvis(const TLiteral & _lhs) : lhs(_lhs)
  279. {}
  280. template<typename OP>
  281. bool operator()(OP const & rhs) const
  282. {
  283. return boost::get<OP>(lhs) <= rhs;
  284. }
  285. };
  286. bool operator<=(const TLiteral & t1, const TLiteral & t2);
  287. //operator >
  288. struct _opGTvis : boost::static_visitor<bool>
  289. {
  290. const TLiteral & lhs;
  291. _opGTvis(const TLiteral & _lhs) : lhs(_lhs)
  292. {}
  293. template<typename OP>
  294. bool operator()(OP const & rhs) const
  295. {
  296. return boost::get<OP>(lhs) <= rhs;
  297. }
  298. };
  299. bool operator>(const TLiteral & t1, const TLiteral & t2);
  300. //operator >=
  301. struct _opGEvis : boost::static_visitor<bool>
  302. {
  303. const TLiteral & lhs;
  304. _opGEvis(const TLiteral & _lhs) : lhs(_lhs)
  305. {}
  306. template<typename OP>
  307. bool operator()(OP const & rhs) const
  308. {
  309. return boost::get<OP>(lhs) <= rhs;
  310. }
  311. };
  312. bool operator>=(const TLiteral & t1, const TLiteral & t2);
  313. //VFunc
  314. struct VFunc;
  315. //VOption & stuff
  316. typedef boost::variant<VNIL, boost::recursive_wrapper<VNode>, VSymbol, TLiteral, ERM::Tcommand, boost::recursive_wrapper<VFunc> > VOption; //options in v-expression, VNIl should be the default
  317. template<typename T, typename SecType>
  318. T& getAs(SecType & opt)
  319. {
  320. if(opt.type() == typeid(T))
  321. return boost::get<T>(opt);
  322. else
  323. throw EVermScriptExecError("Wrong type!");
  324. }
  325. template<typename T, typename SecType>
  326. bool isA(const SecType & opt)
  327. {
  328. if(opt.type() == typeid(T))
  329. return true;
  330. else
  331. return false;
  332. }
  333. //why it doesn't work?
  334. // template<typename TBasicVariant>
  335. // struct IntVarinant : public TBasicVariant
  336. // {
  337. // template<typename T>
  338. // bool isA() const
  339. // {
  340. // return type() == typeid(T);
  341. // }
  342. // template<typename T>
  343. // T getAs()
  344. // {
  345. // if(isA<T>())
  346. // return boost::get<T>(*this);
  347. // else
  348. // throw EVermScriptExecError("Getting improved variant with wrongly specified type");
  349. // }
  350. //
  351. // IntVarinant(const VNode & val) : TBasicVariant(val)
  352. // {}
  353. // IntVarinant(const VNIL & val) : TBasicVariant(val)
  354. // {}
  355. // IntVarinant(const TLiteral & val) : TBasicVariant(val)
  356. // {}
  357. // IntVarinant(const VSymbol & val) : TBasicVariant(val)
  358. // {}
  359. // IntVarinant(const int & val) : TBasicVariant(val)
  360. // {}
  361. // IntVarinant(const char & val) : TBasicVariant(val)
  362. // {}
  363. // IntVarinant(const double & val) : TBasicVariant(val)
  364. // {}
  365. // IntVarinant(const ERM::Tcommand & val) : TBasicVariant(val)
  366. // {}
  367. // TBasicVariant & getAsPlaintVariant()
  368. // {
  369. // return *this;
  370. // }
  371. //
  372. // IntVarinant()
  373. // {}
  374. // };
  375. ///main environment class, manages symbols
  376. class Environment
  377. {
  378. private:
  379. std::map<std::string, VOption> symbols;
  380. Environment * parent;
  381. public:
  382. Environment() : parent(NULL)
  383. {}
  384. void setPatent(Environment * _parent);
  385. Environment * getPatent() const;
  386. enum EIsBoundMode {GLOBAL_ONLY, LOCAL_ONLY, ANYWHERE};
  387. bool isBound(const std::string & name, EIsBoundMode mode) const;
  388. VOption & retrieveValue(const std::string & name);
  389. enum EUnbindMode{LOCAL, RECURSIVE_UNTIL_HIT, FULLY_RECURSIVE};
  390. ///returns true if symbol was really unbound
  391. bool unbind(const std::string & name, EUnbindMode mode);
  392. void localBind(std::string name, const VOption & sym);
  393. void bindAtFirstHit(std::string name, const VOption & sym); //if symbol is locally defines, it gets overwritten; otherwise it is bind globally
  394. };
  395. //this class just introduces a new dynamic range when instantiated, nothing more
  396. class IntroduceDynamicEnv
  397. {
  398. public:
  399. IntroduceDynamicEnv();
  400. ~IntroduceDynamicEnv();
  401. };
  402. struct VermTreeIterator
  403. {
  404. private:
  405. friend struct VOptionList;
  406. VOptionList * parent;
  407. enum Estate {NORM, CAR} state;
  408. int basePos; //car/cdr offset
  409. public:
  410. VermTreeIterator(VOptionList & _parent) : parent(&_parent), basePos(0), state(NORM)
  411. {}
  412. VermTreeIterator() : parent(NULL), state(NORM)
  413. {}
  414. VermTreeIterator & operator=(const VOption & opt);
  415. VermTreeIterator & operator=(const std::vector<VOption> & opt);
  416. VermTreeIterator & operator=(const VOptionList & opt);
  417. VOption & getAsItem();
  418. VermTreeIterator getAsCDR();
  419. VOptionList getAsList();
  420. VOption & getIth(int i);
  421. size_t size() const;
  422. VermTreeIterator& operator=(const VermTreeIterator & rhs)
  423. {
  424. if(this == &rhs)
  425. {
  426. return *this;
  427. }
  428. parent = rhs.parent;
  429. state = rhs.state;
  430. basePos = rhs.basePos;
  431. return *this;
  432. }
  433. };
  434. struct VOptionList : public std::vector<VOption>
  435. {
  436. private:
  437. friend struct VermTreeIterator;
  438. public:
  439. VermTreeIterator car();
  440. VermTreeIterator cdr();
  441. bool isNil() const;
  442. };
  443. struct VFunc
  444. {
  445. enum Eopt {DEFAULT, LT, GT, LE, GE, ADD, SUB, MULT, DIV, MOD} option;
  446. std::vector<VSymbol> args;
  447. VOptionList body;
  448. VFunc(const VOptionList & _body) : body(_body), option(DEFAULT)
  449. {}
  450. VFunc(Eopt func) : option(func)
  451. {}
  452. VFunc& operator=(const VFunc & rhs)
  453. {
  454. if(this == &rhs)
  455. {
  456. return *this;
  457. }
  458. args = rhs.args;
  459. body = rhs.body;
  460. return *this;
  461. }
  462. VOption operator()(VermTreeIterator params);
  463. };
  464. struct OptionConverterVisitor : boost::static_visitor<VOption>
  465. {
  466. VOption operator()(ERM::TVExp const& cmd) const;
  467. VOption operator()(ERM::TSymbol const& cmd) const;
  468. VOption operator()(char const& cmd) const;
  469. VOption operator()(double const& cmd) const;
  470. VOption operator()(int const& cmd) const;
  471. VOption operator()(ERM::Tcommand const& cmd) const;
  472. VOption operator()(ERM::TStringConstant const& cmd) const;
  473. };
  474. struct VNode
  475. {
  476. private:
  477. void processModifierList(const std::vector<TVModifier> & modifierList);
  478. public:
  479. VOptionList children;
  480. VNode( const ERM::TVExp & exp);
  481. VNode( const VOptionList & cdren );
  482. VNode( const ERM::TSymbol & sym ); //only in case sym has modifiers!
  483. VNode( const VOption & first, const VOptionList & rest); //merges given arguments into [a, rest];
  484. void setVnode( const VOption & first, const VOptionList & rest);
  485. };
  486. //v printer
  487. struct _VLITPrinter : boost::static_visitor<void>
  488. {
  489. void operator()(const std::string & par) const
  490. {
  491. tlog1 << "^" << par << "^";
  492. }
  493. template<typename T>
  494. void operator()(const T & par) const
  495. {
  496. tlog1 << par;
  497. }
  498. };
  499. struct _VOPTPrinter : boost::static_visitor<void>
  500. {
  501. void operator()(VNIL const& opt) const
  502. {
  503. tlog1 << "[]";
  504. }
  505. void operator()(VNode const& opt) const
  506. {
  507. tlog1 << "[";
  508. for(int g=0; g<opt.children.size(); ++g)
  509. {
  510. boost::apply_visitor(_VOPTPrinter(), opt.children[g]);
  511. tlog1 << " ";
  512. }
  513. tlog1 << "]";
  514. }
  515. void operator()(VSymbol const& opt) const
  516. {
  517. tlog1 << opt.text;
  518. }
  519. void operator()(TLiteral const& opt) const
  520. {
  521. boost::apply_visitor(_VLITPrinter(), opt);
  522. }
  523. void operator()(ERM::Tcommand const& opt) const
  524. {
  525. tlog1 << "--erm--";
  526. }
  527. void operator()(VFunc const& opt) const
  528. {
  529. tlog1 << "function";
  530. }
  531. };
  532. void printVOption(const VOption & opt);
  533. }
  534. class ERMInterpreter;
  535. struct TriggerIdentifierMatch
  536. {
  537. bool allowNoIdetifier;
  538. std::map< int, std::vector<int> > matchToIt; //match subidentifiers to these numbers
  539. static const int MAX_SUBIDENTIFIERS = 16;
  540. ERMInterpreter * ermEnv;
  541. bool tryMatch(VERMInterpreter::Trigger * interptrig) const;
  542. };
  543. struct IexpValStr
  544. {
  545. private:
  546. union
  547. {
  548. int val;
  549. int * integervar;
  550. double * flvar;
  551. std::string * stringvar;
  552. } val;
  553. public:
  554. std::string name;
  555. std::string getName() const;
  556. enum {WRONGVAL, INT, INTVAR, FLOATVAR, STRINGVAR} type;
  557. void setTo(const IexpValStr & second);
  558. void setTo(int val);
  559. void setTo(float val);
  560. void setTo(const std::string & val);
  561. int getInt() const;
  562. float getFloat() const;
  563. std::string getString() const;
  564. IexpValStr() : type(WRONGVAL)
  565. {}
  566. IexpValStr(int _val) : type(INT)
  567. {
  568. val.val = _val;
  569. }
  570. IexpValStr(int* _val) : type(INTVAR)
  571. {
  572. val.integervar = _val;
  573. }
  574. IexpValStr(double * _val) : type(FLOATVAR)
  575. {
  576. val.flvar = _val;
  577. }
  578. IexpValStr(std::string * _val) : type(STRINGVAR)
  579. {
  580. val.stringvar = _val;
  581. }
  582. #define OPERATOR_DEFINITION_FULL(OPSIGN) \
  583. template<typename T> \
  584. IexpValStr operator OPSIGN(const T & sec) const \
  585. { \
  586. IexpValStr ret = *this; \
  587. switch (type) \
  588. { \
  589. case INT: \
  590. case INTVAR: \
  591. ret.setTo(ret.getInt() OPSIGN sec); \
  592. break; \
  593. case FLOATVAR: \
  594. ret.setTo(ret.getFloat() OPSIGN sec); \
  595. break; \
  596. case STRINGVAR: \
  597. ret.setTo(ret.getString() OPSIGN sec); \
  598. break; \
  599. } \
  600. return ret; \
  601. } \
  602. IexpValStr operator OPSIGN(const IexpValStr & sec) const \
  603. { \
  604. IexpValStr ret = *this; \
  605. switch (type) \
  606. { \
  607. case INT: \
  608. case INTVAR: \
  609. ret.setTo(ret.getInt() OPSIGN sec.getInt()); \
  610. break; \
  611. case FLOATVAR: \
  612. ret.setTo(ret.getFloat() OPSIGN sec.getFloat()); \
  613. break; \
  614. case STRINGVAR: \
  615. ret.setTo(ret.getString() OPSIGN sec.getString()); \
  616. break; \
  617. } \
  618. return ret; \
  619. } \
  620. template<typename T> \
  621. IexpValStr & operator OPSIGN ## = (const T & sec) \
  622. { \
  623. *this = *this OPSIGN sec; \
  624. return *this; \
  625. }
  626. #define OPERATOR_DEFINITION(OPSIGN) \
  627. template<typename T> \
  628. IexpValStr operator OPSIGN(const T & sec) const \
  629. { \
  630. IexpValStr ret = *this; \
  631. switch (type) \
  632. { \
  633. case INT: \
  634. case INTVAR: \
  635. ret.setTo(ret.getInt() OPSIGN sec); \
  636. break; \
  637. case FLOATVAR: \
  638. ret.setTo(ret.getFloat() OPSIGN sec); \
  639. break; \
  640. } \
  641. return ret; \
  642. } \
  643. IexpValStr operator OPSIGN(const IexpValStr & sec) const \
  644. { \
  645. IexpValStr ret = *this; \
  646. switch (type) \
  647. { \
  648. case INT: \
  649. case INTVAR: \
  650. ret.setTo(ret.getInt() OPSIGN sec.getInt()); \
  651. break; \
  652. case FLOATVAR: \
  653. ret.setTo(ret.getFloat() OPSIGN sec.getFloat()); \
  654. break; \
  655. } \
  656. return ret; \
  657. } \
  658. template<typename T> \
  659. IexpValStr & operator OPSIGN ## = (const T & sec) \
  660. { \
  661. *this = *this OPSIGN sec; \
  662. return *this; \
  663. }
  664. #define OPERATOR_DEFINITION_INTEGER(OPSIGN) \
  665. template<typename T> \
  666. IexpValStr operator OPSIGN(const T & sec) const \
  667. { \
  668. IexpValStr ret = *this; \
  669. switch (type) \
  670. { \
  671. case INT: \
  672. case INTVAR: \
  673. ret.setTo(ret.getInt() OPSIGN sec); \
  674. break; \
  675. } \
  676. return ret; \
  677. } \
  678. IexpValStr operator OPSIGN(const IexpValStr & sec) const \
  679. { \
  680. IexpValStr ret = *this; \
  681. switch (type) \
  682. { \
  683. case INT: \
  684. case INTVAR: \
  685. ret.setTo(ret.getInt() OPSIGN sec.getInt()); \
  686. break; \
  687. } \
  688. return ret; \
  689. } \
  690. template<typename T> \
  691. IexpValStr & operator OPSIGN ## = (const T & sec) \
  692. { \
  693. *this = *this OPSIGN sec; \
  694. return *this; \
  695. }
  696. OPERATOR_DEFINITION_FULL(+)
  697. OPERATOR_DEFINITION(-)
  698. OPERATOR_DEFINITION(*)
  699. OPERATOR_DEFINITION(/)
  700. OPERATOR_DEFINITION_INTEGER(%)
  701. };
  702. class ERMInterpreter : public CScriptingModule
  703. {
  704. /*not so*/ public:
  705. // friend class ScriptScanner;
  706. // friend class TriggerIdMatchHelper;
  707. // friend class TriggerIdentifierMatch;
  708. // friend class ConditionDisemboweler;
  709. // friend struct LVL2IexpDisemboweler;
  710. // friend struct VR_SPerformer;
  711. // friend struct ERMExpDispatch;
  712. // friend struct VRPerformer;
  713. std::vector<VERMInterpreter::FileInfo*> files;
  714. std::vector< VERMInterpreter::FileInfo* > fileInfos;
  715. std::map<VERMInterpreter::LinePointer, ERM::TLine> scripts;
  716. std::map<VERMInterpreter::LexicalPtr, VERMInterpreter::Environment> lexicalEnvs;
  717. ERM::TLine &retrieveLine(VERMInterpreter::LinePointer linePtr);
  718. static ERM::TTriggerBase & retrieveTrigger(ERM::TLine &line);
  719. VERMInterpreter::Environment * globalEnv;
  720. VERMInterpreter::ERMEnvironment * ermGlobalEnv;
  721. typedef std::map<VERMInterpreter::TriggerType, std::vector<VERMInterpreter::Trigger> > TtriggerListType;
  722. TtriggerListType triggers, postTriggers;
  723. VERMInterpreter::Trigger * curTrigger;
  724. VERMInterpreter::FunctionLocalVars * curFunc;
  725. static const int TRIG_FUNC_NUM = 30000;
  726. VERMInterpreter::FunctionLocalVars funcVars[TRIG_FUNC_NUM+1]; //+1 because we use [0] as a global set of y-vars
  727. VERMInterpreter::FunctionLocalVars * getFuncVars(int funNum); //0 is a global func-like set
  728. IexpValStr getIexp(const ERM::TIexp & iexp) const;
  729. IexpValStr getIexp(const ERM::TMacroUsage & macro) const;
  730. IexpValStr getIexp(const ERM::TIdentifierInternal & tid) const;
  731. IexpValStr getIexp(const ERM::TVarpExp & tid) const;
  732. IexpValStr getIexp(const ERM::TBodyOptionItem & opit) const;
  733. static const std::string triggerSymbol, postTriggerSymbol, defunSymbol;
  734. void executeLine(const VERMInterpreter::LinePointer & lp);
  735. void executeTrigger(VERMInterpreter::Trigger & trig, int funNum = -1, std::vector<int> funParams=std::vector<int>());
  736. static bool isCMDATrigger(const ERM::Tcommand & cmd);
  737. static bool isATrigger(const ERM::TLine & line);
  738. static ERM::EVOtions getExpType(const ERM::TVOption & opt);
  739. IexpValStr getVar(std::string toFollow, boost::optional<int> initVal) const;
  740. std::string processERMString(std::string ermstring);
  741. VERMInterpreter::VOption eval( VERMInterpreter::VOption line, VERMInterpreter::Environment * env = NULL );
  742. VERMInterpreter::VOptionList evalEach( VERMInterpreter::VermTreeIterator list, VERMInterpreter::Environment * env = NULL );
  743. public:
  744. typedef std::map< int, std::vector<int> > TIDPattern;
  745. void executeInstructions(); //called when starting a new game, before most of the map settings are done
  746. void executeTriggerType(VERMInterpreter::TriggerType tt, bool pre, const TIDPattern & identifier, const std::vector<int> &funParams=std::vector<int>()); //use this to run triggers
  747. void executeTriggerType(const char *trigger, int id); //convenience version of above, for pre-trigger when there is only one argument
  748. void executeTriggerType(const char *trigger); //convenience version of above, for pre-trigger when there are no args
  749. void setCurrentlyVisitedObj(int3 pos); //sets v998 - v1000 to given value
  750. void scanForScripts();
  751. enum EPrintMode{ALL, ERM_ONLY, VERM_ONLY};
  752. void printScripts(EPrintMode mode = ALL);
  753. void scanScripts(); //scans for functions, triggers etc.
  754. ERMInterpreter();
  755. bool checkCondition( ERM::Tcondition cond );
  756. int getRealLine(int lineNum);
  757. //overload CScriptingModule
  758. virtual void heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visitedObj, bool start) OVERRIDE;
  759. virtual void init() OVERRIDE;//sets up environment etc.
  760. virtual void executeUserCommand(const std::string &cmd) OVERRIDE;
  761. virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) OVERRIDE;
  762. const CGObjectInstance *getObjFrom(int3 pos);
  763. template <typename T>
  764. const T *getObjFromAs(int3 pos)
  765. {
  766. const T* obj = dynamic_cast<const T*>(getObjFrom(pos));
  767. if(obj)
  768. return obj;
  769. else
  770. throw VERMInterpreter::EScriptExecError("Wrong cast attempted, object is not of a desired type!");
  771. }
  772. };