ERMInterpreter.h 22 KB

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