ERMInterpreter.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  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. //operator =
  314. struct _opEQvis : boost::static_visitor<bool>
  315. {
  316. const TLiteral & lhs;
  317. _opEQvis(const TLiteral & _lhs) : lhs(_lhs)
  318. {}
  319. template<typename OP>
  320. bool operator()(OP const & rhs) const
  321. {
  322. return boost::get<OP>(lhs) == rhs;
  323. }
  324. };
  325. //VFunc
  326. struct VFunc;
  327. //VOption & stuff
  328. 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
  329. template<typename T, typename SecType>
  330. T& getAs(SecType & opt)
  331. {
  332. if(opt.type() == typeid(T))
  333. return boost::get<T>(opt);
  334. else
  335. throw EVermScriptExecError("Wrong type!");
  336. }
  337. template<typename T, typename SecType>
  338. bool isA(const SecType & opt)
  339. {
  340. if(opt.type() == typeid(T))
  341. return true;
  342. else
  343. return false;
  344. }
  345. //why it doesn't work?
  346. // template<typename TBasicVariant>
  347. // struct IntVarinant : public TBasicVariant
  348. // {
  349. // template<typename T>
  350. // bool isA() const
  351. // {
  352. // return type() == typeid(T);
  353. // }
  354. // template<typename T>
  355. // T getAs()
  356. // {
  357. // if(isA<T>())
  358. // return boost::get<T>(*this);
  359. // else
  360. // throw EVermScriptExecError("Getting improved variant with wrongly specified type");
  361. // }
  362. //
  363. // IntVarinant(const VNode & val) : TBasicVariant(val)
  364. // {}
  365. // IntVarinant(const VNIL & val) : TBasicVariant(val)
  366. // {}
  367. // IntVarinant(const TLiteral & val) : TBasicVariant(val)
  368. // {}
  369. // IntVarinant(const VSymbol & val) : TBasicVariant(val)
  370. // {}
  371. // IntVarinant(const int & val) : TBasicVariant(val)
  372. // {}
  373. // IntVarinant(const char & val) : TBasicVariant(val)
  374. // {}
  375. // IntVarinant(const double & val) : TBasicVariant(val)
  376. // {}
  377. // IntVarinant(const ERM::Tcommand & val) : TBasicVariant(val)
  378. // {}
  379. // TBasicVariant & getAsPlaintVariant()
  380. // {
  381. // return *this;
  382. // }
  383. //
  384. // IntVarinant()
  385. // {}
  386. // };
  387. ///main environment class, manages symbols
  388. class Environment
  389. {
  390. private:
  391. std::map<std::string, VOption> symbols;
  392. Environment * parent;
  393. public:
  394. Environment() : parent(NULL)
  395. {}
  396. void setPatent(Environment * _parent);
  397. Environment * getPatent() const;
  398. enum EIsBoundMode {GLOBAL_ONLY, LOCAL_ONLY, ANYWHERE};
  399. bool isBound(const std::string & name, EIsBoundMode mode) const;
  400. VOption & retrieveValue(const std::string & name);
  401. enum EUnbindMode{LOCAL, RECURSIVE_UNTIL_HIT, FULLY_RECURSIVE};
  402. ///returns true if symbol was really unbound
  403. bool unbind(const std::string & name, EUnbindMode mode);
  404. void localBind(std::string name, const VOption & sym);
  405. void bindAtFirstHit(std::string name, const VOption & sym); //if symbol is locally defines, it gets overwritten; otherwise it is bind globally
  406. };
  407. //this class just introduces a new dynamic range when instantiated, nothing more
  408. class IntroduceDynamicEnv
  409. {
  410. public:
  411. IntroduceDynamicEnv();
  412. ~IntroduceDynamicEnv();
  413. };
  414. struct VermTreeIterator
  415. {
  416. private:
  417. friend struct VOptionList;
  418. VOptionList * parent;
  419. enum Estate {NORM, CAR} state;
  420. int basePos; //car/cdr offset
  421. public:
  422. VermTreeIterator(VOptionList & _parent) : parent(&_parent), state(NORM), basePos(0)
  423. {}
  424. VermTreeIterator() : parent(NULL), state(NORM)
  425. {}
  426. VermTreeIterator & operator=(const VOption & opt);
  427. VermTreeIterator & operator=(const std::vector<VOption> & opt);
  428. VermTreeIterator & operator=(const VOptionList & opt);
  429. VOption & getAsItem();
  430. VermTreeIterator getAsCDR();
  431. VOptionList getAsList();
  432. VOption & getIth(int i);
  433. size_t size() const;
  434. VermTreeIterator& operator=(const VermTreeIterator & rhs)
  435. {
  436. if(this == &rhs)
  437. {
  438. return *this;
  439. }
  440. parent = rhs.parent;
  441. state = rhs.state;
  442. basePos = rhs.basePos;
  443. return *this;
  444. }
  445. };
  446. struct VOptionList : public std::vector<VOption>
  447. {
  448. private:
  449. friend struct VermTreeIterator;
  450. public:
  451. VermTreeIterator car();
  452. VermTreeIterator cdr();
  453. bool isNil() const;
  454. };
  455. struct VFunc
  456. {
  457. enum Eopt {DEFAULT, LT, GT, LE, GE, EQ, ADD, SUB, MULT, DIV, MOD} option;
  458. std::vector<VSymbol> args;
  459. VOptionList body;
  460. bool macro; //true - act as macro, false - act as function
  461. VFunc(const VOptionList & _body, bool asMacro = false) : option(DEFAULT), body(_body), macro(asMacro)
  462. {}
  463. VFunc(Eopt func) : option(func), macro(false)
  464. {}
  465. VFunc& operator=(const VFunc & rhs)
  466. {
  467. if(this == &rhs)
  468. {
  469. return *this;
  470. }
  471. args = rhs.args;
  472. body = rhs.body;
  473. return *this;
  474. }
  475. VOption operator()(VermTreeIterator params);
  476. };
  477. struct OptionConverterVisitor : boost::static_visitor<VOption>
  478. {
  479. VOption operator()(ERM::TVExp const& cmd) const;
  480. VOption operator()(ERM::TSymbol const& cmd) const;
  481. VOption operator()(char const& cmd) const;
  482. VOption operator()(double const& cmd) const;
  483. VOption operator()(int const& cmd) const;
  484. VOption operator()(ERM::Tcommand const& cmd) const;
  485. VOption operator()(ERM::TStringConstant const& cmd) const;
  486. };
  487. struct VNode
  488. {
  489. private:
  490. void processModifierList(const std::vector<TVModifier> & modifierList, bool asSymbol);
  491. public:
  492. VOptionList children;
  493. VNode( const ERM::TVExp & exp);
  494. VNode( const VOptionList & cdren );
  495. VNode( const ERM::TSymbol & sym ); //only in case sym has modifiers!
  496. VNode( const VOption & first, const VOptionList & rest); //merges given arguments into [a, rest];
  497. void setVnode( const VOption & first, const VOptionList & rest);
  498. };
  499. //v printer
  500. void printVOption(const VOption & opt);
  501. }
  502. class ERMInterpreter;
  503. struct TriggerIdentifierMatch
  504. {
  505. bool allowNoIdetifier;
  506. std::map< int, std::vector<int> > matchToIt; //match subidentifiers to these numbers
  507. static const int MAX_SUBIDENTIFIERS = 16;
  508. ERMInterpreter * ermEnv;
  509. bool tryMatch(VERMInterpreter::Trigger * interptrig) const;
  510. };
  511. struct IexpValStr
  512. {
  513. private:
  514. union
  515. {
  516. int val;
  517. int * integervar;
  518. double * flvar;
  519. std::string * stringvar;
  520. } val;
  521. public:
  522. std::string name;
  523. std::string getName() const;
  524. enum {WRONGVAL, INT, INTVAR, FLOATVAR, STRINGVAR} type;
  525. void setTo(const IexpValStr & second);
  526. void setTo(int val);
  527. void setTo(float val);
  528. void setTo(const std::string & val);
  529. int getInt() const;
  530. float getFloat() const;
  531. std::string getString() const;
  532. IexpValStr() : type(WRONGVAL)
  533. {}
  534. IexpValStr(int _val) : type(INT)
  535. {
  536. val.val = _val;
  537. }
  538. IexpValStr(int* _val) : type(INTVAR)
  539. {
  540. val.integervar = _val;
  541. }
  542. IexpValStr(double * _val) : type(FLOATVAR)
  543. {
  544. val.flvar = _val;
  545. }
  546. IexpValStr(std::string * _val) : type(STRINGVAR)
  547. {
  548. val.stringvar = _val;
  549. }
  550. #define OPERATOR_DEFINITION_FULL(OPSIGN) \
  551. template<typename T> \
  552. IexpValStr operator OPSIGN(const T & sec) const \
  553. { \
  554. IexpValStr ret = *this; \
  555. switch (type) \
  556. { \
  557. case INT: \
  558. case INTVAR: \
  559. ret.setTo(ret.getInt() OPSIGN sec); \
  560. break; \
  561. case FLOATVAR: \
  562. ret.setTo(ret.getFloat() OPSIGN sec); \
  563. break; \
  564. case STRINGVAR: \
  565. ret.setTo(ret.getString() OPSIGN sec); \
  566. break; \
  567. } \
  568. return ret; \
  569. } \
  570. IexpValStr operator OPSIGN(const IexpValStr & sec) const \
  571. { \
  572. IexpValStr ret = *this; \
  573. switch (type) \
  574. { \
  575. case INT: \
  576. case INTVAR: \
  577. ret.setTo(ret.getInt() OPSIGN sec.getInt()); \
  578. break; \
  579. case FLOATVAR: \
  580. ret.setTo(ret.getFloat() OPSIGN sec.getFloat()); \
  581. break; \
  582. case STRINGVAR: \
  583. ret.setTo(ret.getString() OPSIGN sec.getString()); \
  584. break; \
  585. } \
  586. return ret; \
  587. } \
  588. template<typename T> \
  589. IexpValStr & operator OPSIGN ## = (const T & sec) \
  590. { \
  591. *this = *this OPSIGN sec; \
  592. return *this; \
  593. }
  594. #define OPERATOR_DEFINITION(OPSIGN) \
  595. template<typename T> \
  596. IexpValStr operator OPSIGN(const T & sec) const \
  597. { \
  598. IexpValStr ret = *this; \
  599. switch (type) \
  600. { \
  601. case INT: \
  602. case INTVAR: \
  603. ret.setTo(ret.getInt() OPSIGN sec); \
  604. break; \
  605. case FLOATVAR: \
  606. ret.setTo(ret.getFloat() OPSIGN sec); \
  607. break; \
  608. } \
  609. return ret; \
  610. } \
  611. IexpValStr operator OPSIGN(const IexpValStr & sec) const \
  612. { \
  613. IexpValStr ret = *this; \
  614. switch (type) \
  615. { \
  616. case INT: \
  617. case INTVAR: \
  618. ret.setTo(ret.getInt() OPSIGN sec.getInt()); \
  619. break; \
  620. case FLOATVAR: \
  621. ret.setTo(ret.getFloat() OPSIGN sec.getFloat()); \
  622. break; \
  623. } \
  624. return ret; \
  625. } \
  626. template<typename T> \
  627. IexpValStr & operator OPSIGN ## = (const T & sec) \
  628. { \
  629. *this = *this OPSIGN sec; \
  630. return *this; \
  631. }
  632. #define OPERATOR_DEFINITION_INTEGER(OPSIGN) \
  633. template<typename T> \
  634. IexpValStr operator OPSIGN(const T & sec) const \
  635. { \
  636. IexpValStr ret = *this; \
  637. switch (type) \
  638. { \
  639. case INT: \
  640. case INTVAR: \
  641. ret.setTo(ret.getInt() OPSIGN sec); \
  642. break; \
  643. } \
  644. return ret; \
  645. } \
  646. IexpValStr operator OPSIGN(const IexpValStr & sec) const \
  647. { \
  648. IexpValStr ret = *this; \
  649. switch (type) \
  650. { \
  651. case INT: \
  652. case INTVAR: \
  653. ret.setTo(ret.getInt() OPSIGN sec.getInt()); \
  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. OPERATOR_DEFINITION_FULL(+)
  665. OPERATOR_DEFINITION(-)
  666. OPERATOR_DEFINITION(*)
  667. OPERATOR_DEFINITION(/)
  668. OPERATOR_DEFINITION_INTEGER(%)
  669. };
  670. class ERMInterpreter : public CScriptingModule
  671. {
  672. /*not so*/ public:
  673. // friend class ScriptScanner;
  674. // friend class TriggerIdMatchHelper;
  675. // friend class TriggerIdentifierMatch;
  676. // friend class ConditionDisemboweler;
  677. // friend struct LVL2IexpDisemboweler;
  678. // friend struct VR_SPerformer;
  679. // friend struct ERMExpDispatch;
  680. // friend struct VRPerformer;
  681. std::vector<VERMInterpreter::FileInfo*> files;
  682. std::vector< VERMInterpreter::FileInfo* > fileInfos;
  683. std::map<VERMInterpreter::LinePointer, ERM::TLine> scripts;
  684. std::map<VERMInterpreter::LexicalPtr, VERMInterpreter::Environment> lexicalEnvs;
  685. ERM::TLine &retrieveLine(VERMInterpreter::LinePointer linePtr);
  686. static ERM::TTriggerBase & retrieveTrigger(ERM::TLine &line);
  687. VERMInterpreter::Environment * globalEnv;
  688. VERMInterpreter::ERMEnvironment * ermGlobalEnv;
  689. typedef std::map<VERMInterpreter::TriggerType, std::vector<VERMInterpreter::Trigger> > TtriggerListType;
  690. TtriggerListType triggers, postTriggers;
  691. VERMInterpreter::Trigger * curTrigger;
  692. VERMInterpreter::FunctionLocalVars * curFunc;
  693. static const int TRIG_FUNC_NUM = 30000;
  694. VERMInterpreter::FunctionLocalVars funcVars[TRIG_FUNC_NUM+1]; //+1 because we use [0] as a global set of y-vars
  695. VERMInterpreter::FunctionLocalVars * getFuncVars(int funNum); //0 is a global func-like set
  696. IexpValStr getIexp(const ERM::TIexp & iexp) const;
  697. IexpValStr getIexp(const ERM::TMacroUsage & macro) const;
  698. IexpValStr getIexp(const ERM::TIdentifierInternal & tid) const;
  699. IexpValStr getIexp(const ERM::TVarpExp & tid) const;
  700. IexpValStr getIexp(const ERM::TBodyOptionItem & opit) const;
  701. static const std::string triggerSymbol, postTriggerSymbol, defunSymbol;
  702. void executeLine(const VERMInterpreter::LinePointer & lp);
  703. void executeTrigger(VERMInterpreter::Trigger & trig, int funNum = -1, std::vector<int> funParams=std::vector<int>());
  704. static bool isCMDATrigger(const ERM::Tcommand & cmd);
  705. static bool isATrigger(const ERM::TLine & line);
  706. static ERM::EVOtions getExpType(const ERM::TVOption & opt);
  707. IexpValStr getVar(std::string toFollow, boost::optional<int> initVal) const;
  708. std::string processERMString(std::string ermstring);
  709. VERMInterpreter::VOption eval( VERMInterpreter::VOption line, VERMInterpreter::Environment * env = NULL );
  710. VERMInterpreter::VOptionList evalEach( VERMInterpreter::VermTreeIterator list, VERMInterpreter::Environment * env = NULL );
  711. public:
  712. typedef std::map< int, std::vector<int> > TIDPattern;
  713. void executeInstructions(); //called when starting a new game, before most of the map settings are done
  714. void executeTriggerType(VERMInterpreter::TriggerType tt, bool pre, const TIDPattern & identifier, const std::vector<int> &funParams=std::vector<int>()); //use this to run triggers
  715. void executeTriggerType(const char *trigger, int id); //convenience version of above, for pre-trigger when there is only one argument
  716. void executeTriggerType(const char *trigger); //convenience version of above, for pre-trigger when there are no args
  717. void setCurrentlyVisitedObj(int3 pos); //sets v998 - v1000 to given value
  718. void scanForScripts();
  719. enum EPrintMode{ALL, ERM_ONLY, VERM_ONLY};
  720. void printScripts(EPrintMode mode = ALL);
  721. void scanScripts(); //scans for functions, triggers etc.
  722. ERMInterpreter();
  723. bool checkCondition( ERM::Tcondition cond );
  724. int getRealLine(int lineNum);
  725. //overload CScriptingModule
  726. virtual void heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visitedObj, bool start) OVERRIDE;
  727. virtual void init() OVERRIDE;//sets up environment etc.
  728. virtual void executeUserCommand(const std::string &cmd) OVERRIDE;
  729. virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) OVERRIDE;
  730. const CGObjectInstance *getObjFrom(int3 pos);
  731. template <typename T>
  732. const T *getObjFromAs(int3 pos)
  733. {
  734. const T* obj = dynamic_cast<const T*>(getObjFrom(pos));
  735. if(obj)
  736. return obj;
  737. else
  738. throw VERMInterpreter::EScriptExecError("Wrong cast attempted, object is not of a desired type!");
  739. }
  740. };