ERMInterpreter.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957
  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)
  28. : 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
  152. {
  153. AE,
  154. BA,
  155. BF,
  156. BG,
  157. BR,
  158. CM,
  159. CO,
  160. FU,
  161. GE,
  162. GM,
  163. HE,
  164. HL,
  165. HM,
  166. IP,
  167. LE,
  168. MF,
  169. MG,
  170. MM,
  171. MR,
  172. MW,
  173. OB,
  174. PI,
  175. SN,
  176. TH,
  177. TM
  178. } type;
  179. static ETrigType convertTrigger(const std::string & trig)
  180. {
  181. static const std::string validTriggers[] =
  182. {
  183. "AE", "BA", "BF", "BG", "BR", "CM", "CO", "FU",
  184. "GE", "GM", "HE", "HL", "HM", "IP", "LE", "MF", "MG", "MM", "MR", "MW", "OB", "PI", "SN",
  185. "TH", "TM"
  186. };
  187. for(int i = 0; i < ARRAY_COUNT(validTriggers); ++i)
  188. {
  189. if(validTriggers[i] == trig)
  190. return static_cast<ETrigType>(i);
  191. }
  192. throw EInvalidTrigger(trig);
  193. }
  194. bool operator<(const TriggerType & t2) const
  195. {
  196. return type < t2.type;
  197. }
  198. TriggerType(const std::string & sym)
  199. {
  200. type = convertTrigger(sym);
  201. }
  202. };
  203. struct FileInfo
  204. {
  205. std::string filename;
  206. int length;
  207. };
  208. struct LinePointer
  209. {
  210. const FileInfo * file; //non-owning
  211. int lineNum;
  212. int realLineNum;
  213. LinePointer()
  214. : file(nullptr)
  215. {}
  216. LinePointer(const FileInfo * finfo, int line, int _realLineNum)
  217. : file(finfo), lineNum(line), realLineNum(_realLineNum)
  218. {}
  219. //lexicographical order
  220. bool operator<(const LinePointer & rhs) const
  221. {
  222. if(file->filename != rhs.file->filename)
  223. return file->filename < rhs.file->filename;
  224. return lineNum < rhs.lineNum;
  225. }
  226. bool operator!=(const LinePointer & rhs) const
  227. {
  228. return file->filename != rhs.file->filename || lineNum != rhs.lineNum;
  229. }
  230. LinePointer & operator++()
  231. {
  232. ++lineNum;
  233. return *this;
  234. }
  235. bool isValid() const
  236. {
  237. return file && lineNum < file->length;
  238. }
  239. };
  240. struct LexicalPtr
  241. {
  242. LinePointer line; //where to start
  243. std::vector<int> entryPoints; //defines how to pass to current location
  244. bool operator<(const LexicalPtr & sec) const
  245. {
  246. if(line != sec.line)
  247. return line < sec.line;
  248. if(entryPoints.size() != sec.entryPoints.size())
  249. return entryPoints.size() < sec.entryPoints.size();
  250. for(int g = 0; g < entryPoints.size(); ++g)
  251. {
  252. if(entryPoints[g] < sec.entryPoints[g])
  253. return true;
  254. }
  255. return false;
  256. }
  257. };
  258. //call stack, represents dynamic range
  259. struct Stack
  260. {
  261. std::vector<LexicalPtr> stack;
  262. };
  263. struct Trigger
  264. {
  265. LinePointer line;
  266. TriggerLocalVars ermLocalVars;
  267. Stack * stack; //where we are stuck at execution
  268. Trigger()
  269. : stack(nullptr)
  270. {}
  271. };
  272. //verm goodies
  273. struct VSymbol
  274. {
  275. std::string text;
  276. VSymbol(const std::string & txt)
  277. : text(txt)
  278. {}
  279. };
  280. struct VNode;
  281. struct VOptionList;
  282. struct VNIL
  283. {};
  284. typedef boost::variant<char, double, int, std::string> TLiteral;
  285. //for operator <, but this one seems to be implemented in boost alerady
  286. struct _opLTvis : boost::static_visitor<bool>
  287. {
  288. const TLiteral & lhs;
  289. _opLTvis(const TLiteral & _lhs)
  290. : 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. // {
  300. // if(t1.type() == t2.type())
  301. // {
  302. // return boost::apply_visitor(_opLTvis(t1), t2);
  303. // }
  304. // throw EVermScriptExecError("These types are incomparable!");
  305. // }
  306. //for operator <=
  307. struct _opLEvis : boost::static_visitor<bool>
  308. {
  309. const TLiteral & lhs;
  310. _opLEvis(const TLiteral & _lhs)
  311. : lhs(_lhs)
  312. {}
  313. template<typename OP>
  314. bool operator()(OP const & rhs) const
  315. {
  316. return boost::get<OP>(lhs) <= rhs;
  317. }
  318. };
  319. bool operator<=(const TLiteral & t1, const TLiteral & t2);
  320. //operator >
  321. struct _opGTvis : boost::static_visitor<bool>
  322. {
  323. const TLiteral & lhs;
  324. _opGTvis(const TLiteral & _lhs)
  325. : lhs(_lhs)
  326. {}
  327. template<typename OP>
  328. bool operator()(OP const & rhs) const
  329. {
  330. return boost::get<OP>(lhs) > rhs;
  331. }
  332. };
  333. bool operator>(const TLiteral & t1, const TLiteral & t2);
  334. //operator >=
  335. struct _opGEvis : boost::static_visitor<bool>
  336. {
  337. const TLiteral & lhs;
  338. _opGEvis(const TLiteral & _lhs)
  339. : lhs(_lhs)
  340. {}
  341. template<typename OP>
  342. bool operator()(OP const & rhs) const
  343. {
  344. return boost::get<OP>(lhs) >= rhs;
  345. }
  346. };
  347. bool operator>=(const TLiteral & t1, const TLiteral & t2);
  348. //operator =
  349. struct _opEQvis : boost::static_visitor<bool>
  350. {
  351. const TLiteral & lhs;
  352. _opEQvis(const TLiteral & _lhs)
  353. : lhs(_lhs)
  354. {}
  355. template<typename OP>
  356. bool operator()(OP const & rhs) const
  357. {
  358. return boost::get<OP>(lhs) == rhs;
  359. }
  360. };
  361. //VFunc
  362. struct VFunc;
  363. //VOption & stuff
  364. 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
  365. template<typename T, typename SecType>
  366. T & getAs(SecType & opt)
  367. {
  368. if(opt.type() == typeid(T))
  369. return boost::get<T>(opt);
  370. else
  371. throw EVermScriptExecError("Wrong type!");
  372. }
  373. template<typename T, typename SecType>
  374. bool isA(const SecType & opt)
  375. {
  376. if(opt.type() == typeid(T))
  377. return true;
  378. else
  379. return false;
  380. }
  381. //why it doesn't work?
  382. // template<typename TBasicVariant>
  383. // struct IntVarinant : public TBasicVariant
  384. // {
  385. // template<typename T>
  386. // bool isA() const
  387. // {
  388. // return type() == typeid(T);
  389. // }
  390. // template<typename T>
  391. // T getAs()
  392. // {
  393. // if(isA<T>())
  394. // return boost::get<T>(*this);
  395. // else
  396. // throw EVermScriptExecError("Getting improved variant with wrongly specified type");
  397. // }
  398. //
  399. // IntVarinant(const VNode & val) : TBasicVariant(val)
  400. // {}
  401. // IntVarinant(const VNIL & val) : TBasicVariant(val)
  402. // {}
  403. // IntVarinant(const TLiteral & val) : TBasicVariant(val)
  404. // {}
  405. // IntVarinant(const VSymbol & val) : TBasicVariant(val)
  406. // {}
  407. // IntVarinant(const int & val) : TBasicVariant(val)
  408. // {}
  409. // IntVarinant(const char & val) : TBasicVariant(val)
  410. // {}
  411. // IntVarinant(const double & val) : TBasicVariant(val)
  412. // {}
  413. // IntVarinant(const ERM::Tcommand & val) : TBasicVariant(val)
  414. // {}
  415. // TBasicVariant & getAsPlaintVariant()
  416. // {
  417. // return *this;
  418. // }
  419. //
  420. // IntVarinant()
  421. // {}
  422. // };
  423. ///main environment class, manages symbols
  424. class Environment
  425. {
  426. private:
  427. std::map<std::string, VOption> symbols;
  428. Environment * parent;
  429. public:
  430. Environment()
  431. : parent(nullptr)
  432. {}
  433. void setPatent(Environment * _parent);
  434. Environment * getPatent() const;
  435. enum EIsBoundMode
  436. {
  437. GLOBAL_ONLY,
  438. LOCAL_ONLY,
  439. ANYWHERE
  440. };
  441. bool isBound(const std::string & name, EIsBoundMode mode) const;
  442. VOption & retrieveValue(const std::string & name);
  443. enum EUnbindMode
  444. {
  445. LOCAL,
  446. RECURSIVE_UNTIL_HIT,
  447. FULLY_RECURSIVE
  448. };
  449. ///returns true if symbol was really unbound
  450. bool unbind(const std::string & name, EUnbindMode mode);
  451. void localBind(std::string name, const VOption & sym);
  452. void bindAtFirstHit(std::string name, const VOption & sym); //if symbol is locally defines, it gets overwritten; otherwise it is bind globally
  453. };
  454. //this class just introduces a new dynamic range when instantiated, nothing more
  455. class IntroduceDynamicEnv
  456. {
  457. public:
  458. IntroduceDynamicEnv();
  459. ~IntroduceDynamicEnv();
  460. };
  461. struct VermTreeIterator
  462. {
  463. private:
  464. friend struct VOptionList;
  465. VOptionList * parent;
  466. enum Estate
  467. {
  468. NORM,
  469. CAR
  470. } state;
  471. int basePos; //car/cdr offset
  472. public:
  473. VermTreeIterator(VOptionList & _parent)
  474. : parent(&_parent), state(NORM), basePos(0)
  475. {}
  476. VermTreeIterator()
  477. : parent(nullptr), state(NORM)
  478. {}
  479. VermTreeIterator & operator=(const VOption & opt);
  480. VermTreeIterator & operator=(const std::vector<VOption> & opt);
  481. VermTreeIterator & operator=(const VOptionList & opt);
  482. VOption & getAsItem();
  483. VermTreeIterator getAsCDR();
  484. VOptionList getAsList();
  485. VOption & getIth(int i);
  486. size_t size() const;
  487. VermTreeIterator & operator=(const VermTreeIterator & rhs)
  488. {
  489. if(this == &rhs)
  490. {
  491. return *this;
  492. }
  493. parent = rhs.parent;
  494. state = rhs.state;
  495. basePos = rhs.basePos;
  496. return *this;
  497. }
  498. };
  499. struct VOptionList : public std::vector<VOption>
  500. {
  501. private:
  502. friend struct VermTreeIterator;
  503. public:
  504. VermTreeIterator car();
  505. VermTreeIterator cdr();
  506. bool isNil() const;
  507. };
  508. struct VFunc
  509. {
  510. enum Eopt
  511. {
  512. DEFAULT,
  513. LT,
  514. GT,
  515. LE,
  516. GE,
  517. EQ,
  518. ADD,
  519. SUB,
  520. MULT,
  521. DIV,
  522. MOD
  523. } option;
  524. std::vector<VSymbol> args;
  525. VOptionList body;
  526. bool macro; //true - act as macro, false - act as function
  527. VFunc(const VOptionList & _body, bool asMacro = false)
  528. : option(DEFAULT), body(_body), macro(asMacro)
  529. {}
  530. VFunc(Eopt func)
  531. : option(func), macro(false)
  532. {}
  533. VFunc & operator=(const VFunc & rhs)
  534. {
  535. if(this == &rhs)
  536. {
  537. return *this;
  538. }
  539. args = rhs.args;
  540. body = rhs.body;
  541. return *this;
  542. }
  543. VOption operator()(VermTreeIterator params);
  544. };
  545. struct OptionConverterVisitor : boost::static_visitor<VOption>
  546. {
  547. VOption operator()(ERM::TVExp const & cmd) const;
  548. VOption operator()(ERM::TSymbol const & cmd) const;
  549. VOption operator()(char const & cmd) const;
  550. VOption operator()(double const & cmd) const;
  551. VOption operator()(int const & cmd) const;
  552. VOption operator()(ERM::Tcommand const & cmd) const;
  553. VOption operator()(ERM::TStringConstant const & cmd) const;
  554. };
  555. struct VNode
  556. {
  557. private:
  558. void processModifierList(const std::vector<TVModifier> & modifierList, bool asSymbol);
  559. public:
  560. VOptionList children;
  561. VNode(const ERM::TVExp & exp);
  562. VNode(const VOptionList & cdren);
  563. VNode(const ERM::TSymbol & sym); //only in case sym has modifiers!
  564. VNode(const VOption & first, const VOptionList & rest); //merges given arguments into [a, rest];
  565. void setVnode(const VOption & first, const VOptionList & rest);
  566. };
  567. //v printer
  568. void printVOption(const VOption & opt);
  569. }
  570. class ERMInterpreter;
  571. struct TriggerIdentifierMatch
  572. {
  573. bool allowNoIdetifier;
  574. std::map<int, std::vector<int>> matchToIt; //match subidentifiers to these numbers
  575. static const int MAX_SUBIDENTIFIERS = 16;
  576. ERMInterpreter * ermEnv;
  577. bool tryMatch(VERMInterpreter::Trigger * interptrig) const;
  578. };
  579. struct IexpValStr
  580. {
  581. private:
  582. union
  583. {
  584. int val;
  585. int * integervar;
  586. double * flvar;
  587. std::string * stringvar;
  588. } val;
  589. public:
  590. std::string name;
  591. std::string getName() const;
  592. enum
  593. {
  594. WRONGVAL,
  595. INT,
  596. INTVAR,
  597. FLOATVAR,
  598. STRINGVAR
  599. } type;
  600. void setTo(const IexpValStr & second);
  601. void setTo(int val);
  602. void setTo(double val);
  603. void setTo(const std::string & val);
  604. int getInt() const;
  605. double getFloat() const;
  606. std::string getString() const;
  607. IexpValStr()
  608. : type(WRONGVAL)
  609. {}
  610. IexpValStr(int _val)
  611. : type(INT)
  612. {
  613. val.val = _val;
  614. }
  615. IexpValStr(int * _val)
  616. : type(INTVAR)
  617. {
  618. val.integervar = _val;
  619. }
  620. IexpValStr(double * _val)
  621. : type(FLOATVAR)
  622. {
  623. val.flvar = _val;
  624. }
  625. IexpValStr(std::string * _val)
  626. : type(STRINGVAR)
  627. {
  628. val.stringvar = _val;
  629. }
  630. #define OPERATOR_DEFINITION_FULL(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. case FLOATVAR: \
  642. ret.setTo(ret.getFloat() OPSIGN sec); \
  643. break; \
  644. case STRINGVAR: \
  645. ret.setTo(ret.getString() OPSIGN sec); \
  646. break; \
  647. } \
  648. return ret; \
  649. } \
  650. IexpValStr operator OPSIGN(const IexpValStr &sec) const \
  651. { \
  652. IexpValStr ret = *this; \
  653. switch(type) \
  654. { \
  655. case INT: \
  656. case INTVAR: \
  657. ret.setTo(ret.getInt() OPSIGN sec.getInt()); \
  658. break; \
  659. case FLOATVAR: \
  660. ret.setTo(ret.getFloat() OPSIGN sec.getFloat()); \
  661. break; \
  662. case STRINGVAR: \
  663. ret.setTo(ret.getString() OPSIGN sec.getString()); \
  664. break; \
  665. } \
  666. return ret; \
  667. } \
  668. template<typename T> \
  669. IexpValStr & operator OPSIGN ## = (const T &sec) \
  670. { \
  671. *this = *this OPSIGN sec; \
  672. return *this; \
  673. }
  674. #define OPERATOR_DEFINITION(OPSIGN) \
  675. template<typename T> \
  676. IexpValStr operator OPSIGN(const T & sec) const \
  677. { \
  678. IexpValStr ret = *this; \
  679. switch(type) \
  680. { \
  681. case INT: \
  682. case INTVAR: \
  683. ret.setTo(ret.getInt() OPSIGN sec); \
  684. break; \
  685. case FLOATVAR: \
  686. ret.setTo(ret.getFloat() OPSIGN sec); \
  687. break; \
  688. } \
  689. return ret; \
  690. } \
  691. IexpValStr operator OPSIGN(const IexpValStr &sec) const \
  692. { \
  693. IexpValStr ret = *this; \
  694. switch(type) \
  695. { \
  696. case INT: \
  697. case INTVAR: \
  698. ret.setTo(ret.getInt() OPSIGN sec.getInt()); \
  699. break; \
  700. case FLOATVAR: \
  701. ret.setTo(ret.getFloat() OPSIGN sec.getFloat()); \
  702. break; \
  703. } \
  704. return ret; \
  705. } \
  706. template<typename T> \
  707. IexpValStr & operator OPSIGN ## = (const T &sec) \
  708. { \
  709. *this = *this OPSIGN sec; \
  710. return *this; \
  711. }
  712. #define OPERATOR_DEFINITION_INTEGER(OPSIGN) \
  713. template<typename T> \
  714. IexpValStr operator OPSIGN(const T & sec) const \
  715. { \
  716. IexpValStr ret = *this; \
  717. switch(type) \
  718. { \
  719. case INT: \
  720. case INTVAR: \
  721. ret.setTo(ret.getInt() OPSIGN sec); \
  722. break; \
  723. } \
  724. return ret; \
  725. } \
  726. IexpValStr operator OPSIGN(const IexpValStr &sec) const \
  727. { \
  728. IexpValStr ret = *this; \
  729. switch(type) \
  730. { \
  731. case INT: \
  732. case INTVAR: \
  733. ret.setTo(ret.getInt() OPSIGN sec.getInt()); \
  734. break; \
  735. } \
  736. return ret; \
  737. } \
  738. template<typename T> \
  739. IexpValStr & operator OPSIGN ## = (const T &sec) \
  740. { \
  741. *this = *this OPSIGN sec; \
  742. return *this; \
  743. }
  744. OPERATOR_DEFINITION_FULL(+)
  745. OPERATOR_DEFINITION(-)
  746. OPERATOR_DEFINITION(*)
  747. OPERATOR_DEFINITION(/)
  748. OPERATOR_DEFINITION_INTEGER(%)
  749. };
  750. class ERMInterpreter : public CScriptingModule
  751. {
  752. /*not so*/
  753. public:
  754. // friend class ScriptScanner;
  755. // friend class TriggerIdMatchHelper;
  756. // friend class TriggerIdentifierMatch;
  757. // friend class ConditionDisemboweler;
  758. // friend struct LVL2IexpDisemboweler;
  759. // friend struct VR_SPerformer;
  760. // friend struct ERMExpDispatch;
  761. // friend struct VRPerformer;
  762. std::vector<VERMInterpreter::FileInfo *> files;
  763. std::vector<VERMInterpreter::FileInfo *> fileInfos;
  764. std::map<VERMInterpreter::LinePointer, ERM::TLine> scripts;
  765. std::map<VERMInterpreter::LexicalPtr, VERMInterpreter::Environment> lexicalEnvs;
  766. ERM::TLine & retrieveLine(VERMInterpreter::LinePointer linePtr);
  767. static ERM::TTriggerBase & retrieveTrigger(ERM::TLine & line);
  768. VERMInterpreter::Environment * globalEnv;
  769. VERMInterpreter::ERMEnvironment * ermGlobalEnv;
  770. typedef std::map<VERMInterpreter::TriggerType, std::vector<VERMInterpreter::Trigger>> TtriggerListType;
  771. TtriggerListType triggers, postTriggers;
  772. VERMInterpreter::Trigger * curTrigger;
  773. VERMInterpreter::FunctionLocalVars * curFunc;
  774. static const int TRIG_FUNC_NUM = 30000;
  775. VERMInterpreter::FunctionLocalVars funcVars[TRIG_FUNC_NUM + 1]; //+1 because we use [0] as a global set of y-vars
  776. VERMInterpreter::FunctionLocalVars * getFuncVars(int funNum); //0 is a global func-like set
  777. IexpValStr getIexp(const ERM::TIexp & iexp) const;
  778. IexpValStr getIexp(const ERM::TMacroUsage & macro) const;
  779. IexpValStr getIexp(const ERM::TIdentifierInternal & tid) const;
  780. IexpValStr getIexp(const ERM::TVarpExp & tid) const;
  781. IexpValStr getIexp(const ERM::TBodyOptionItem & opit) const;
  782. static const std::string triggerSymbol, postTriggerSymbol, defunSymbol;
  783. void executeLine(const VERMInterpreter::LinePointer & lp);
  784. void executeLine(const ERM::TLine & line);
  785. void executeTrigger(VERMInterpreter::Trigger & trig, int funNum = -1, std::vector<int> funParams = std::vector<int>());
  786. static bool isCMDATrigger(const ERM::Tcommand & cmd);
  787. static bool isATrigger(const ERM::TLine & line);
  788. static ERM::EVOtions getExpType(const ERM::TVOption & opt);
  789. IexpValStr getVar(std::string toFollow, boost::optional<int> initVal) const;
  790. std::string processERMString(std::string ermstring);
  791. VERMInterpreter::VOption eval(VERMInterpreter::VOption line, VERMInterpreter::Environment * env = nullptr);
  792. VERMInterpreter::VOptionList evalEach(VERMInterpreter::VermTreeIterator list, VERMInterpreter::Environment * env = nullptr);
  793. public:
  794. typedef std::map<int, std::vector<int>> TIDPattern;
  795. void executeInstructions(); //called when starting a new game, before most of the map settings are done
  796. void executeTriggerType(VERMInterpreter::TriggerType tt, bool pre, const TIDPattern & identifier, const std::vector<int> & funParams = std::vector<int>()); //use this to run triggers
  797. void executeTriggerType(const char * trigger, int id); //convenience version of above, for pre-trigger when there is only one argument
  798. void executeTriggerType(const char * trigger); //convenience version of above, for pre-trigger when there are no args
  799. void setCurrentlyVisitedObj(int3 pos); //sets v998 - v1000 to given value
  800. void scanForScripts();
  801. enum EPrintMode
  802. {
  803. ALL,
  804. ERM_ONLY,
  805. VERM_ONLY
  806. };
  807. void printScripts(EPrintMode mode = ALL);
  808. void scanScripts(); //scans for functions, triggers etc.
  809. ERMInterpreter();
  810. bool checkCondition(ERM::Tcondition cond);
  811. int getRealLine(const VERMInterpreter::LinePointer & lp);
  812. //overload CScriptingModule
  813. virtual void heroVisit(const CGHeroInstance * visitor, const CGObjectInstance * visitedObj, bool start) override;
  814. virtual void init() override; //sets up environment etc.
  815. virtual void executeUserCommand(const std::string & cmd) override;
  816. virtual void giveInfoCB(CPrivilagedInfoCallback * cb) override;
  817. virtual void giveActionCB(IGameEventRealizer * cb) override;
  818. virtual void battleStart(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side) override;
  819. const CGObjectInstance * getObjFrom(int3 pos);
  820. template<typename T>
  821. const T * getObjFromAs(int3 pos)
  822. {
  823. const T * obj = dynamic_cast<const T *>(getObjFrom(pos));
  824. if(obj)
  825. return obj;
  826. else
  827. throw VERMInterpreter::EScriptExecError("Wrong cast attempted, object is not of a desired type!");
  828. }
  829. };