1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

* some progress in VERM interpreter

This commit is contained in:
mateuszb 2011-04-16 17:39:38 +00:00
parent 3241e7c8f8
commit 36fb9b0b6e
3 changed files with 268 additions and 11 deletions

View File

@ -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<Tcommand>(cmd);
switch (tcmd.cmd.which())
{
case 0: //trigger
{
Trigger trig;
trig.line = lp;
interpreter->triggers[ TriggerType(boost::get<ERM::Ttrigger>(tcmd.cmd).name) ].push_back(trig);
}
break;
case 3: //post trigger
{
Trigger trig;
trig.line = lp;
interpreter->postTriggers[ TriggerType(boost::get<ERM::TPostTrigger>(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<ERM::TSymbol>(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<typename T>
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<std::string, ERM::TVarExpNotMacro>::const_iterator it =
env->ermGlobalEnv->macroBindings.find(val .macro);
if(it == env->ermGlobalEnv->macroBindings.end())
throw EUsageOfUndefinedMacro(val.macro);
else
processNotMacro(it->second);
}
};
template<typename T>
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<typename T>
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<int> >::const_iterator it = matchToIt.find(tid.size());
if(it == matchToIt.end())
return false;
else
{
const std::vector<int> & pattern = it->second;
for(int g=0; g<pattern.size(); ++g)
{
int val = -1;
boost::apply_visitor(TriggerIdMatchHelper(val), tid[g]);
return pattern[g] == val;
}
}
}
else
{
if(allowNoIdetifier)
return true;
}
}

View File

@ -1,8 +1,6 @@
#pragma once
#include "../global.h"
#include "ERMParser.h"
#include <boost/smart_ptr.hpp>
#include <boost/shared_ptr.hpp>
/*
* 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<EVAR_NUM; ++g)
evar[g] = 0.0;
for(int g=0; g<YVAR_NUM; ++g)
yvar[g] = 0;
}
};
struct FunctionLocalVars
@ -165,6 +185,8 @@ namespace VERMInterpreter
static const int NUM_STRINGS = 1000;
std::string strings[NUM_STRINGS]; //z-vars (positive indices)
std::map<std::string, ERM::TVarExpNotMacro> 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<int> > 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<VERMInterpreter::FileInfo*> files;
std::vector< boost::shared_ptr<VERMInterpreter::FileInfo> > fileInfos;
std::vector< VERMInterpreter::FileInfo* > fileInfos;
std::map<VERMInterpreter::LinePointer, ERM::TLine> scripts;
std::map<VERMInterpreter::LexicalPtr, VERMInterpreter::Environment> lexicalEnvs;
ERM::TLine retrieveLine(VERMInterpreter::LinePointer linePtr) const;
VERMInterpreter::Environment * globalEnv;
std::map<VERMInterpreter::TriggerType, std::vector<VERMInterpreter::Trigger> > triggers;
VERMInterpreter::ERMEnvironment * ermGlobalEnv;
std::map<VERMInterpreter::TriggerType, std::vector<VERMInterpreter::Trigger> > triggers, postTriggers;
static const std::string triggerSymbol, postTriggerSymbol;
template<typename T> void setIexp(const ERM::TIexp & iexp, const T & val, VERMInterpreter::Trigger * trig = NULL);
template<typename T> 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};

View File

@ -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)