ERMInterpreter.h 22 KB

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