From 36fb9b0b6e0bb74515792d8492c7b368566fa914 Mon Sep 17 00:00:00 2001 From: mateuszb Date: Sat, 16 Apr 2011 17:39:38 +0000 Subject: [PATCH] * some progress in VERM interpreter --- lib/ERMInterpreter.cpp | 211 ++++++++++++++++++++++++++++++++++++++++- lib/ERMInterpreter.h | 63 ++++++++++-- lib/VCMI_Lib.cpp | 5 +- 3 files changed, 268 insertions(+), 11 deletions(-) diff --git a/lib/ERMInterpreter.cpp b/lib/ERMInterpreter.cpp index 762c0d479..cbd3834a9 100644 --- a/lib/ERMInterpreter.cpp +++ b/lib/ERMInterpreter.cpp @@ -402,11 +402,53 @@ void ERMInterpreter::printScripts( EPrintMode mode /*= EPrintMode::ALL*/ ) } } +struct ScriptScanner : boost::static_visitor<> +{ + ERMInterpreter * interpreter; + LinePointer lp; + + ScriptScanner(ERMInterpreter * interpr, const LinePointer & _lp) : interpreter(interpr), lp(_lp) + {} + + void operator()(TVExp const& cmd) const + { + // + } + void operator()(TERMline const& cmd) const + { + if(cmd.which() == 0) //TCommand + { + Tcommand tcmd = boost::get(cmd); + switch (tcmd.cmd.which()) + { + case 0: //trigger + { + Trigger trig; + trig.line = lp; + interpreter->triggers[ TriggerType(boost::get(tcmd.cmd).name) ].push_back(trig); + } + break; + case 3: //post trigger + { + Trigger trig; + trig.line = lp; + interpreter->postTriggers[ TriggerType(boost::get(tcmd.cmd).name) ].push_back(trig); + } + break; + default: + + break; + } + } + + } +}; + void ERMInterpreter::scanScripts() { for(std::map< LinePointer, ERM::TLine >::const_iterator it = scripts.begin(); it != scripts.end(); ++it) { - + boost::apply_visitor(ScriptScanner(this, it->first), it->second); } } @@ -442,7 +484,7 @@ bool ERMInterpreter::isATrigger( const ERM::TLine & line ) case SYMBOL: { //TODO: what about sym modifiers? - //TOOD: macros + //TOOD: macros? ERM::TSymbol sym = boost::get(vexp.children[0]); return sym.sym == triggerSymbol || sym.sym == postTriggerSymbol; } @@ -502,11 +544,176 @@ ERM::TLine ERMInterpreter::retrieveLine( LinePointer linePtr ) const return *scripts.find(linePtr); } +///////// +//code execution + +struct ERMExpDispatch : boost::static_visitor<> +{ + void operator()(Ttrigger const& trig) const + { + //the first executed line, check if we should proceed + } + void operator()(Tinstruction const& trig) const + { + } + void operator()(Treceiver const& trig) const + { + } + void operator()(TPostTrigger const& trig) const + { + } +}; + +struct CommandExec : boost::static_visitor<> +{ + void operator()(Tcommand const& cmd) const + { + boost::apply_visitor(ERMExpDispatch(), cmd.cmd); + std::cout << "Line comment: " << cmd.comment << std::endl; + } + void operator()(std::string const& comment) const + { + //comment - do nothing + } + void operator()(spirit::unused_type const& nothing) const + { + //nothing - do nothing + } +}; + +struct LineExec : boost::static_visitor<> +{ + void operator()(TVExp const& cmd) const + { + //printTVExp(cmd); + } + void operator()(TERMline const& cmd) const + { + boost::apply_visitor(CommandExec(), cmd); + } +}; + +///////// + void ERMInterpreter::executeLine( const LinePointer & lp ) { + boost::apply_visitor(LineExec(), scripts[lp]); +} +void ERMInterpreter::init() +{ + ermGlobalEnv = new ERMEnvironment(); + globalEnv = new Environment(); + //TODO: reset? +} + +struct ERMExecEnvironment +{ + ERMEnvironment * ermGlobalEnv; + Trigger * trigEnv; + ERMExecEnvironment(ERMEnvironment * erm, Trigger * trig = NULL) : ermGlobalEnv(erm), trigEnv(trig) + {} +}; + +template +struct LVL2GetIexpDisemboweler : boost::static_visitor<> +{ + T & out; + const ERMExecEnvironment * env; + LVL2GetIexpDisemboweler(T & ret, const ERMExecEnvironment * _env) : out(ret), env(_env) //writes value to given var + {} + + void processNotMacro(const TVarExpNotMacro & val) const + { + if(val.questionMark.is_initialized()) + throw EIexpGetterProblem("Question marks ('?') are not allowed in getter i-expressions"); + + //TODO: finish it + } + + void operator()(TVarExpNotMacro const& val) const + { + processNotMacro(val); + } + void operator()(TMacroUsage const& val) const + { + std::map::const_iterator it = + env->ermGlobalEnv->macroBindings.find(val .macro); + if(it == env->ermGlobalEnv->macroBindings.end()) + throw EUsageOfUndefinedMacro(val.macro); + else + processNotMacro(it->second); + } +}; + +template +struct LVL1GetIexpDisemboweler : boost::static_visitor<> +{ + T & out; + const ERMExecEnvironment * env; + LVL1GetIexpDisemboweler(T & ret, const ERMExecEnvironment * _env) : out(ret), env(_env) //writes value to given var + {} + void operator()(int const & constant) const + { + out = constant; + } + void operator()(TVarExp const & var) const + { + + } +}; + +template +T ERMInterpreter::getIexp( const ERM::TIexp & iexp, const Trigger * trig /*= NULL*/ ) const +{ + T ret; + boost::apply_visitor(LVL1GetIexpDisemboweler(ret, ERMExecEnvironment(ermGlobalEnv, trig)), iexp); + return ret; } const std::string ERMInterpreter::triggerSymbol = "trigger"; const std::string ERMInterpreter::postTriggerSymbol = "postTrigger"; +const std::string ERMInterpreter::defunSymbol = "defun"; + +struct TriggerIdMatchHelper : boost::static_visitor<> +{ + int & ret; + TriggerIdMatchHelper(int & b) : ret(b) + {} + + void operator()(TIexp const& iexp) const + { + + } + void operator()(TArithmeticOp const& arop) const + { + //error?!? + } +}; + +bool TriggerIdentifierMatch::tryMatch( const ERM::Ttrigger & trig ) const +{ + if(trig.identifier.is_initialized()) + { + ERM::Tidentifier tid = trig.identifier.get(); + std::map< int, std::vector >::const_iterator it = matchToIt.find(tid.size()); + if(it == matchToIt.end()) + return false; + else + { + const std::vector & pattern = it->second; + for(int g=0; g -#include /* * ERMInterpreter.h, part of VCMI engine @@ -27,7 +25,8 @@ namespace VERMInterpreter { return problem.c_str(); } - ~EInterpreterProblem() throw(); + ~EInterpreterProblem() throw() + {} EInterpreterProblem(const std::string & problemDesc) : problem(problemDesc) {} }; @@ -46,6 +45,20 @@ namespace VERMInterpreter {} }; + struct EUsageOfUndefinedMacro : public EInterpreterProblem + { + EUsageOfUndefinedMacro(const std::string & macro) : + EInterpreterProblem(std::string("Macro ") + macro + " is undefined") + {} + }; + + struct EIexpGetterProblem : public EInterpreterProblem + { + EIexpGetterProblem(const std::string & desc) : + EInterpreterProblem(desc) + {} + }; + ///main environment class, manages symbols class Environment @@ -133,6 +146,13 @@ namespace VERMInterpreter static const int YVAR_NUM = 100; //number of yvar locals int yvar[YVAR_NUM]; + TriggerLocalVars() + { + for(int g=0; g macroBindings; }; struct TriggerType @@ -186,6 +208,11 @@ namespace VERMInterpreter throw EInvalidTrigger(trig); } + bool operator<(const TriggerType & t2) const + { + return type < t2.type; + } + TriggerType(const std::string & sym) { type = convertTrigger(sym); @@ -204,6 +231,9 @@ namespace VERMInterpreter const FileInfo * file; //non-owning int lineNum; + LinePointer() : file(NULL) + {} + LinePointer(const FileInfo * finfo, int line) : file(finfo), lineNum(line) {} @@ -227,7 +257,7 @@ namespace VERMInterpreter } bool isValid() const { - return lineNum < file->length; + return file && lineNum < file->length; } }; @@ -265,22 +295,40 @@ namespace VERMInterpreter LinePointer line; TriggerLocalVars ermLocalVars; Stack * stack; //where we are stuck at execution + Trigger() : stack(NULL) + {} }; } +struct TriggerIdentifierMatch +{ + bool allowNoIdetifier; + std::map< int, std::vector > matchToIt; //match subidentifiers to these numbers + + static const int MAX_SUBIDENTIFIERS = 16; + bool tryMatch(const ERM::Ttrigger & trig) const; +}; + class ERMInterpreter { + friend class ScriptScanner; + std::vector files; - std::vector< boost::shared_ptr > fileInfos; + std::vector< VERMInterpreter::FileInfo* > fileInfos; std::map scripts; std::map lexicalEnvs; ERM::TLine retrieveLine(VERMInterpreter::LinePointer linePtr) const; VERMInterpreter::Environment * globalEnv; - std::map > triggers; + VERMInterpreter::ERMEnvironment * ermGlobalEnv; + std::map > triggers, postTriggers; - static const std::string triggerSymbol, postTriggerSymbol; + + template void setIexp(const ERM::TIexp & iexp, const T & val, VERMInterpreter::Trigger * trig = NULL); + template T getIexp(const ERM::TIexp & iexp, const VERMInterpreter::Trigger * trig = NULL) const; + + static const std::string triggerSymbol, postTriggerSymbol, defunSymbol; void executeLine(const VERMInterpreter::LinePointer & lp); void executeTrigger(VERMInterpreter::Trigger & trig); @@ -288,6 +336,7 @@ class ERMInterpreter static bool isATrigger(const ERM::TLine & line); static ERM::EVOtions getExpType(const ERM::TVOption & opt); public: + void init(); //sets up environment etc. void scanForScripts(); enum EPrintMode{ALL, ERM_ONLY, VERM_ONLY}; diff --git a/lib/VCMI_Lib.cpp b/lib/VCMI_Lib.cpp index 2087a7b91..2577ddf52 100644 --- a/lib/VCMI_Lib.cpp +++ b/lib/VCMI_Lib.cpp @@ -52,9 +52,10 @@ DLL_EXPORT void initDLL(CConsoleHandler *Console, std::ostream *Logfile) } HANDLE_EXCEPTION; -// ERMInterpreter ei; + ERMInterpreter ei; // ei.scanForScripts(); -// ei.printScripts(); +// //ei.printScripts(); +// ei.scanScripts(); } DLL_EXPORT void loadToIt(std::string &dest, const std::string &src, int &iter, int mode)