ERMInterpreter.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  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. ///main environment class, manages symbols
  83. class Environment
  84. {
  85. private:
  86. std::map<std::string, TVOption> symbols;
  87. Environment * parent;
  88. public:
  89. bool isBound(const std::string & name, bool globalOnly) const;
  90. TVOption retrieveValue(const std::string & name) const;
  91. enum EUnbindMode{LOCAL, RECURSIVE_UNTIL_HIT, FULLY_RECURSIVE};
  92. ///returns true if symbol was really unbound
  93. bool unbind(const std::string & name, EUnbindMode mode);
  94. };
  95. // All numeric variables are integer variables and have a range of -2147483647...+2147483647
  96. // c stores game active day number //indirect variable
  97. // d current value //not an actual variable but a modifier
  98. // e1..e100 Function floating point variables //local
  99. // e-1..e-100 Trigger local floating point variables //local
  100. // 'f'..'t' Standard variables ('quick variables') //global
  101. // v1..v1000 Standard variables //global
  102. // w1..w100 Hero variables
  103. // w101..w200 Hero variables
  104. // x1..x16 Function parameters //local
  105. // y1..y100 Function local variables //local
  106. // y-1..y-100 Trigger-based local integer variables //local
  107. // z1..z1000 String variables //global
  108. // z-1..z-10 Function local string variables //local
  109. struct TriggerLocalVars
  110. {
  111. static const int EVAR_NUM = 100; //number of evar locals
  112. static const int YVAR_NUM = 100; //number of yvar locals
  113. TriggerLocalVars();
  114. double & getEvar(int num);
  115. int & getYvar(int num);
  116. private:
  117. double evar[EVAR_NUM]; //negative indices
  118. int yvar[YVAR_NUM];
  119. };
  120. struct FunctionLocalVars
  121. {
  122. static const int NUM_PARAMETERS = 16; //number of function parameters
  123. static const int NUM_LOCALS = 100;
  124. static const int NUM_STRINGS = 10;
  125. static const int NUM_FLOATINGS = 100;
  126. int & getParam(int num);
  127. int & getLocal(int num);
  128. std::string & getString(int num);
  129. double & getFloat(int num);
  130. void reset();
  131. private:
  132. int params[NUM_PARAMETERS]; //x-vars
  133. int locals[NUM_LOCALS]; //y-vars
  134. std::string strings[NUM_STRINGS]; //z-vars (negative indices)
  135. double floats[NUM_FLOATINGS]; //e-vars (positive indices)
  136. };
  137. struct ERMEnvironment
  138. {
  139. ERMEnvironment();
  140. static const int NUM_QUICKS = 't' - 'f' + 1; //it should be 15
  141. int & getQuickVar(const char letter); //'f' - 't' variables
  142. int & getStandardVar(int num); //get v-variable
  143. std::string & getZVar(int num);
  144. bool & getFlag(int num);
  145. static const int NUM_STANDARDS = 10000;
  146. static const int NUM_STRINGS = 1000;
  147. std::map<std::string, ERM::TVarExpNotMacro> macroBindings;
  148. static const int NUM_FLAGS = 1000;
  149. private:
  150. int quickVars[NUM_QUICKS]; //referenced by letter ('f' to 't' inclusive)
  151. int standardVars[NUM_STANDARDS]; //v-vars
  152. std::string strings[NUM_STRINGS]; //z-vars (positive indices)
  153. bool flags[NUM_FLAGS];
  154. };
  155. struct TriggerType
  156. {
  157. //the same order of trigger types in this enum and in validTriggers array is obligatory!
  158. enum ETrigType{AE, BA, BF, BG, BR, CM, CO, FU, GE, GM, HE, HL, HM, IP, LE, MF, MG, MM, MR,
  159. MW, OB, PI, SN, TH, TM} type;
  160. static ETrigType convertTrigger(const std::string & trig)
  161. {
  162. static const std::string validTriggers[] = {"AE", "BA", "BF", "BG", "BR", "CM", "CO", "FU",
  163. "GE", "GM", "HE", "HL", "HM", "IP", "LE", "MF", "MG", "MM", "MR", "MW", "OB", "PI", "SN",
  164. "TH", "TM"};
  165. for(int i=0; i<ARRAY_COUNT(validTriggers); ++i)
  166. {
  167. if(validTriggers[i] == trig)
  168. return static_cast<ETrigType>(i);
  169. }
  170. throw EInvalidTrigger(trig);
  171. }
  172. bool operator<(const TriggerType & t2) const
  173. {
  174. return type < t2.type;
  175. }
  176. TriggerType(const std::string & sym)
  177. {
  178. type = convertTrigger(sym);
  179. }
  180. };
  181. struct FileInfo
  182. {
  183. std::string filename;
  184. int length;
  185. };
  186. struct LinePointer
  187. {
  188. const FileInfo * file; //non-owning
  189. int lineNum;
  190. int realLineNum;
  191. LinePointer() : file(NULL)
  192. {}
  193. LinePointer(const FileInfo * finfo, int line, int _realLineNum) : file(finfo), lineNum(line),
  194. realLineNum(_realLineNum)
  195. {}
  196. //lexicographical order
  197. bool operator<(const LinePointer & rhs) const
  198. {
  199. if(file->filename != rhs.file->filename)
  200. return file->filename < rhs.file->filename;
  201. return lineNum < rhs.lineNum;
  202. }
  203. bool operator!=(const LinePointer & rhs) const
  204. {
  205. return file->filename != rhs.file->filename || lineNum != rhs.lineNum;
  206. }
  207. LinePointer & operator++()
  208. {
  209. ++lineNum;
  210. return *this;
  211. }
  212. bool isValid() const
  213. {
  214. return file && lineNum < file->length;
  215. }
  216. };
  217. struct LexicalPtr
  218. {
  219. LinePointer line; //where to start
  220. std::vector<int> entryPoints; //defines how to pass to current location
  221. bool operator<(const LexicalPtr & sec) const
  222. {
  223. if(line != sec.line)
  224. return line < sec.line;
  225. if(entryPoints.size() != sec.entryPoints.size())
  226. return entryPoints.size() < sec.entryPoints.size();
  227. for(int g=0; g<entryPoints.size(); ++g)
  228. {
  229. if(entryPoints[g] < sec.entryPoints[g])
  230. return true;
  231. }
  232. return false;
  233. }
  234. };
  235. //call stack, represents dynamic range
  236. struct Stack
  237. {
  238. std::vector<LexicalPtr> stack;
  239. };
  240. struct Trigger
  241. {
  242. LinePointer line;
  243. TriggerLocalVars ermLocalVars;
  244. Stack * stack; //where we are stuck at execution
  245. Trigger() : stack(NULL)
  246. {}
  247. };
  248. //verm goodies
  249. struct VSymbol
  250. {
  251. std::string text;
  252. VSymbol(const std::string & txt) : text(txt)
  253. {}
  254. };
  255. typedef boost::variant<char, double, int, std::string> TLiteral;
  256. struct VNIL
  257. {};
  258. struct VNode;
  259. struct VOptionList;
  260. typedef boost::variant<VNIL, boost::recursive_wrapper<VNode>, VSymbol, TLiteral, ERM::Tcommand> VOption; //options in v-expression, VNIl should be the default
  261. struct VermTreeIterator
  262. {
  263. private:
  264. friend struct VOptionList;
  265. VOptionList & parent;
  266. enum Estate {CAR, CDR} state;
  267. public:
  268. VermTreeIterator(VOptionList & _parent) : parent(_parent)
  269. {}
  270. VermTreeIterator & operator=(const VOption & opt);
  271. VermTreeIterator & operator=(const std::vector<VOption> & opt);
  272. VermTreeIterator & operator=(const VOptionList & opt);
  273. };
  274. struct VOptionList
  275. {
  276. std::vector<VOption> elements;
  277. VermTreeIterator car()
  278. {
  279. VermTreeIterator ret(*this);
  280. ret.state = VermTreeIterator::CAR;
  281. return ret;
  282. }
  283. VermTreeIterator cdr()
  284. {
  285. VermTreeIterator ret(*this);
  286. ret.state = VermTreeIterator::CDR;
  287. return ret;
  288. }
  289. bool isNil() const
  290. {
  291. return elements.size() == 0;
  292. }
  293. };
  294. struct OptionConverterVisitor : boost::static_visitor<VOption>
  295. {
  296. VOption operator()(ERM::TVExp const& cmd) const;
  297. VOption operator()(ERM::TSymbol const& cmd) const;
  298. VOption operator()(char const& cmd) const;
  299. VOption operator()(double const& cmd) const;
  300. VOption operator()(int const& cmd) const;
  301. VOption operator()(ERM::Tcommand const& cmd) const;
  302. VOption operator()(ERM::TStringConstant const& cmd) const;
  303. };
  304. struct VNode
  305. {
  306. private:
  307. void processModifierList(const std::vector<TVModifier> & modifierList);
  308. public:
  309. VOptionList children;
  310. VNode( const ERM::TVExp & exp);
  311. VNode( const VOptionList & cdren );
  312. VNode( const ERM::TSymbol & sym ); //only in case sym has modifiers!
  313. VNode( const VOption & first, const VOptionList & rest); //merges given arguments into [a, rest];
  314. void setVnode( const VOption & first, const VOptionList & rest);
  315. };
  316. }
  317. class ERMInterpreter;
  318. struct TriggerIdentifierMatch
  319. {
  320. bool allowNoIdetifier;
  321. std::map< int, std::vector<int> > matchToIt; //match subidentifiers to these numbers
  322. static const int MAX_SUBIDENTIFIERS = 16;
  323. ERMInterpreter * ermEnv;
  324. bool tryMatch(VERMInterpreter::Trigger * interptrig) const;
  325. };
  326. struct IexpValStr
  327. {
  328. private:
  329. union
  330. {
  331. int val;
  332. int * integervar;
  333. double * flvar;
  334. std::string * stringvar;
  335. } val;
  336. public:
  337. std::string name;
  338. std::string getName() const;
  339. enum {WRONGVAL, INT, INTVAR, FLOATVAR, STRINGVAR} type;
  340. void setTo(const IexpValStr & second);
  341. void setTo(int val);
  342. void setTo(float val);
  343. void setTo(const std::string & val);
  344. int getInt() const;
  345. float getFloat() const;
  346. std::string getString() const;
  347. IexpValStr() : type(WRONGVAL)
  348. {}
  349. IexpValStr(int _val) : type(INT)
  350. {
  351. val.val = _val;
  352. }
  353. IexpValStr(int* _val) : type(INTVAR)
  354. {
  355. val.integervar = _val;
  356. }
  357. IexpValStr(double * _val) : type(FLOATVAR)
  358. {
  359. val.flvar = _val;
  360. }
  361. IexpValStr(std::string * _val) : type(STRINGVAR)
  362. {
  363. val.stringvar = _val;
  364. }
  365. #define OPERATOR_DEFINITION_FULL(OPSIGN) \
  366. template<typename T> \
  367. IexpValStr operator OPSIGN(const T & sec) const \
  368. { \
  369. IexpValStr ret = *this; \
  370. switch (type) \
  371. { \
  372. case INT: \
  373. case INTVAR: \
  374. ret.setTo(ret.getInt() OPSIGN sec); \
  375. break; \
  376. case FLOATVAR: \
  377. ret.setTo(ret.getFloat() OPSIGN sec); \
  378. break; \
  379. case STRINGVAR: \
  380. ret.setTo(ret.getString() OPSIGN sec); \
  381. break; \
  382. } \
  383. return ret; \
  384. } \
  385. IexpValStr operator OPSIGN(const IexpValStr & sec) const \
  386. { \
  387. IexpValStr ret = *this; \
  388. switch (type) \
  389. { \
  390. case INT: \
  391. case INTVAR: \
  392. ret.setTo(ret.getInt() OPSIGN sec.getInt()); \
  393. break; \
  394. case FLOATVAR: \
  395. ret.setTo(ret.getFloat() OPSIGN sec.getFloat()); \
  396. break; \
  397. case STRINGVAR: \
  398. ret.setTo(ret.getString() OPSIGN sec.getString()); \
  399. break; \
  400. } \
  401. return ret; \
  402. } \
  403. template<typename T> \
  404. IexpValStr & operator OPSIGN ## = (const T & sec) \
  405. { \
  406. *this = *this OPSIGN sec; \
  407. return *this; \
  408. }
  409. #define OPERATOR_DEFINITION(OPSIGN) \
  410. template<typename T> \
  411. IexpValStr operator OPSIGN(const T & sec) const \
  412. { \
  413. IexpValStr ret = *this; \
  414. switch (type) \
  415. { \
  416. case INT: \
  417. case INTVAR: \
  418. ret.setTo(ret.getInt() OPSIGN sec); \
  419. break; \
  420. case FLOATVAR: \
  421. ret.setTo(ret.getFloat() OPSIGN sec); \
  422. break; \
  423. } \
  424. return ret; \
  425. } \
  426. IexpValStr operator OPSIGN(const IexpValStr & sec) const \
  427. { \
  428. IexpValStr ret = *this; \
  429. switch (type) \
  430. { \
  431. case INT: \
  432. case INTVAR: \
  433. ret.setTo(ret.getInt() OPSIGN sec.getInt()); \
  434. break; \
  435. case FLOATVAR: \
  436. ret.setTo(ret.getFloat() OPSIGN sec.getFloat()); \
  437. break; \
  438. } \
  439. return ret; \
  440. } \
  441. template<typename T> \
  442. IexpValStr & operator OPSIGN ## = (const T & sec) \
  443. { \
  444. *this = *this OPSIGN sec; \
  445. return *this; \
  446. }
  447. #define OPERATOR_DEFINITION_INTEGER(OPSIGN) \
  448. template<typename T> \
  449. IexpValStr operator OPSIGN(const T & sec) const \
  450. { \
  451. IexpValStr ret = *this; \
  452. switch (type) \
  453. { \
  454. case INT: \
  455. case INTVAR: \
  456. ret.setTo(ret.getInt() OPSIGN sec); \
  457. break; \
  458. } \
  459. return ret; \
  460. } \
  461. IexpValStr operator OPSIGN(const IexpValStr & sec) const \
  462. { \
  463. IexpValStr ret = *this; \
  464. switch (type) \
  465. { \
  466. case INT: \
  467. case INTVAR: \
  468. ret.setTo(ret.getInt() OPSIGN sec.getInt()); \
  469. break; \
  470. } \
  471. return ret; \
  472. } \
  473. template<typename T> \
  474. IexpValStr & operator OPSIGN ## = (const T & sec) \
  475. { \
  476. *this = *this OPSIGN sec; \
  477. return *this; \
  478. }
  479. OPERATOR_DEFINITION_FULL(+)
  480. OPERATOR_DEFINITION(-)
  481. OPERATOR_DEFINITION(*)
  482. OPERATOR_DEFINITION(/)
  483. OPERATOR_DEFINITION_INTEGER(%)
  484. };
  485. class ERMInterpreter : public CScriptingModule
  486. {
  487. /*not so*/ public:
  488. // friend class ScriptScanner;
  489. // friend class TriggerIdMatchHelper;
  490. // friend class TriggerIdentifierMatch;
  491. // friend class ConditionDisemboweler;
  492. // friend struct LVL2IexpDisemboweler;
  493. // friend struct VR_SPerformer;
  494. // friend struct ERMExpDispatch;
  495. // friend struct VRPerformer;
  496. std::vector<VERMInterpreter::FileInfo*> files;
  497. std::vector< VERMInterpreter::FileInfo* > fileInfos;
  498. std::map<VERMInterpreter::LinePointer, ERM::TLine> scripts;
  499. std::map<VERMInterpreter::LexicalPtr, VERMInterpreter::Environment> lexicalEnvs;
  500. ERM::TLine &retrieveLine(VERMInterpreter::LinePointer linePtr);
  501. static ERM::TTriggerBase & retrieveTrigger(ERM::TLine &line);
  502. VERMInterpreter::Environment * globalEnv;
  503. VERMInterpreter::ERMEnvironment * ermGlobalEnv;
  504. typedef std::map<VERMInterpreter::TriggerType, std::vector<VERMInterpreter::Trigger> > TtriggerListType;
  505. TtriggerListType triggers, postTriggers;
  506. VERMInterpreter::Trigger * curTrigger;
  507. VERMInterpreter::FunctionLocalVars * curFunc;
  508. static const int TRIG_FUNC_NUM = 30000;
  509. VERMInterpreter::FunctionLocalVars funcVars[TRIG_FUNC_NUM+1]; //+1 because we use [0] as a global set of y-vars
  510. VERMInterpreter::FunctionLocalVars * getFuncVars(int funNum); //0 is a global func-like set
  511. IexpValStr getIexp(const ERM::TIexp & iexp) const;
  512. IexpValStr getIexp(const ERM::TMacroUsage & macro) const;
  513. IexpValStr getIexp(const ERM::TIdentifierInternal & tid) const;
  514. IexpValStr getIexp(const ERM::TVarpExp & tid) const;
  515. IexpValStr getIexp(const ERM::TBodyOptionItem & opit) const;
  516. static const std::string triggerSymbol, postTriggerSymbol, defunSymbol;
  517. void executeLine(const VERMInterpreter::LinePointer & lp);
  518. void executeTrigger(VERMInterpreter::Trigger & trig, int funNum = -1, std::vector<int> funParams=std::vector<int>());
  519. static bool isCMDATrigger(const ERM::Tcommand & cmd);
  520. static bool isATrigger(const ERM::TLine & line);
  521. static ERM::EVOtions getExpType(const ERM::TVOption & opt);
  522. IexpValStr getVar(std::string toFollow, boost::optional<int> initVal) const;
  523. std::string processERMString(std::string ermstring);
  524. public:
  525. typedef std::map< int, std::vector<int> > TIDPattern;
  526. void executeInstructions(); //called when starting a new game, before most of the map settings are done
  527. void executeTriggerType(VERMInterpreter::TriggerType tt, bool pre, const TIDPattern & identifier, const std::vector<int> &funParams=std::vector<int>()); //use this to run triggers
  528. void executeTriggerType(const char *trigger, int id); //convenience version of above, for pre-trigger when there is only one argument
  529. void executeTriggerType(const char *trigger); //convenience version of above, for pre-trigger when there are no args
  530. void setCurrentlyVisitedObj(int3 pos); //sets v998 - v1000 to given value
  531. void scanForScripts();
  532. enum EPrintMode{ALL, ERM_ONLY, VERM_ONLY};
  533. void printScripts(EPrintMode mode = ALL);
  534. void scanScripts(); //scans for functions, triggers etc.
  535. ERMInterpreter();
  536. bool checkCondition( ERM::Tcondition cond );
  537. int getRealLine(int lineNum);
  538. //overload CScriptingModule
  539. virtual void heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visitedObj, bool start) OVERRIDE;
  540. virtual void init() OVERRIDE;//sets up environment etc.
  541. virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) OVERRIDE;
  542. const CGObjectInstance *getObjFrom(int3 pos);
  543. template <typename T>
  544. const T *getObjFromAs(int3 pos)
  545. {
  546. const T* obj = dynamic_cast<const T*>(getObjFrom(pos));
  547. if(obj)
  548. return obj;
  549. else
  550. throw VERMInterpreter::EScriptExecError("Wrong cast attempted, object is not of a desired type!");
  551. }
  552. };