mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-28 03:57:02 +02:00
* minor work on ERM interpreter
This commit is contained in:
parent
66837f1ee0
commit
4ac2d32985
@ -460,7 +460,10 @@ ERMInterpreter::ERMInterpreter()
|
|||||||
|
|
||||||
void ERMInterpreter::executeTrigger( Trigger & trig )
|
void ERMInterpreter::executeTrigger( Trigger & trig )
|
||||||
{
|
{
|
||||||
for(LinePointer lp = trig.line; lp.isValid(); ++lp)
|
//skpi the first line
|
||||||
|
LinePointer lp = trig.line;
|
||||||
|
++lp;
|
||||||
|
for(; lp.isValid(); ++lp)
|
||||||
{
|
{
|
||||||
ERM::TLine curLine = retrieveLine(lp);
|
ERM::TLine curLine = retrieveLine(lp);
|
||||||
if(isATrigger(curLine))
|
if(isATrigger(curLine))
|
||||||
@ -550,9 +553,13 @@ ERM::TLine ERMInterpreter::retrieveLine( LinePointer linePtr ) const
|
|||||||
|
|
||||||
struct ERMExpDispatch : boost::static_visitor<>
|
struct ERMExpDispatch : boost::static_visitor<>
|
||||||
{
|
{
|
||||||
|
ERMInterpreter * owner;
|
||||||
|
ERMExpDispatch(ERMInterpreter * _owner) : owner(_owner)
|
||||||
|
{}
|
||||||
|
|
||||||
void operator()(Ttrigger const& trig) const
|
void operator()(Ttrigger const& trig) const
|
||||||
{
|
{
|
||||||
//the first executed line, check if we should proceed
|
throw EInterpreterError("Triggers cannot be executed!");
|
||||||
}
|
}
|
||||||
void operator()(Tinstruction const& trig) const
|
void operator()(Tinstruction const& trig) const
|
||||||
{
|
{
|
||||||
@ -562,14 +569,19 @@ struct ERMExpDispatch : boost::static_visitor<>
|
|||||||
}
|
}
|
||||||
void operator()(TPostTrigger const& trig) const
|
void operator()(TPostTrigger const& trig) const
|
||||||
{
|
{
|
||||||
|
throw EInterpreterError("Post-triggers cannot be executed!");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CommandExec : boost::static_visitor<>
|
struct CommandExec : boost::static_visitor<>
|
||||||
{
|
{
|
||||||
|
ERMInterpreter * owner;
|
||||||
|
CommandExec(ERMInterpreter * _owner) : owner(_owner)
|
||||||
|
{}
|
||||||
|
|
||||||
void operator()(Tcommand const& cmd) const
|
void operator()(Tcommand const& cmd) const
|
||||||
{
|
{
|
||||||
boost::apply_visitor(ERMExpDispatch(), cmd.cmd);
|
boost::apply_visitor(ERMExpDispatch(owner), cmd.cmd);
|
||||||
std::cout << "Line comment: " << cmd.comment << std::endl;
|
std::cout << "Line comment: " << cmd.comment << std::endl;
|
||||||
}
|
}
|
||||||
void operator()(std::string const& comment) const
|
void operator()(std::string const& comment) const
|
||||||
@ -584,13 +596,17 @@ struct CommandExec : boost::static_visitor<>
|
|||||||
|
|
||||||
struct LineExec : boost::static_visitor<>
|
struct LineExec : boost::static_visitor<>
|
||||||
{
|
{
|
||||||
|
ERMInterpreter * owner;
|
||||||
|
LineExec(ERMInterpreter * _owner) : owner(_owner)
|
||||||
|
{}
|
||||||
|
|
||||||
void operator()(TVExp const& cmd) const
|
void operator()(TVExp const& cmd) const
|
||||||
{
|
{
|
||||||
//printTVExp(cmd);
|
//printTVExp(cmd);
|
||||||
}
|
}
|
||||||
void operator()(TERMline const& cmd) const
|
void operator()(TERMline const& cmd) const
|
||||||
{
|
{
|
||||||
boost::apply_visitor(CommandExec(), cmd);
|
boost::apply_visitor(CommandExec(owner), cmd);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -598,7 +614,7 @@ struct LineExec : boost::static_visitor<>
|
|||||||
|
|
||||||
void ERMInterpreter::executeLine( const LinePointer & lp )
|
void ERMInterpreter::executeLine( const LinePointer & lp )
|
||||||
{
|
{
|
||||||
boost::apply_visitor(LineExec(), scripts[lp]);
|
boost::apply_visitor(LineExec(this), scripts[lp]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ERMInterpreter::init()
|
void ERMInterpreter::init()
|
||||||
@ -893,7 +909,7 @@ void ERMInterpreter::executeTriggerType( VERMInterpreter::TriggerType tt, bool p
|
|||||||
tim.allowNoIdetifier = false;
|
tim.allowNoIdetifier = false;
|
||||||
tim.ermEnv = this;
|
tim.ermEnv = this;
|
||||||
tim.matchToIt = identifier;
|
tim.matchToIt = identifier;
|
||||||
std::vector<Trigger> triggersToTry = triggerList[tt];
|
std::vector<Trigger> & triggersToTry = triggerList[tt];
|
||||||
for(int g=0; g<triggersToTry.size(); ++g)
|
for(int g=0; g<triggersToTry.size(); ++g)
|
||||||
{
|
{
|
||||||
if(tim.tryMatch(&triggersToTry[g]))
|
if(tim.tryMatch(&triggersToTry[g]))
|
||||||
@ -976,3 +992,75 @@ bool TriggerIdentifierMatch::tryMatch( Trigger * interptrig ) const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VERMInterpreter::ERMEnvironment::ERMEnvironment()
|
||||||
|
{
|
||||||
|
for(int g=0; g<NUM_QUICKS; ++g)
|
||||||
|
quickVars[g] = 0;
|
||||||
|
for(int g=0; g<NUM_STANDARDS; ++g)
|
||||||
|
standardVars[g] = 0;
|
||||||
|
//string should be automatically initialized to ""
|
||||||
|
for(int g=0; g<NUM_FLAGS; ++g)
|
||||||
|
flags[g] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
VERMInterpreter::TriggerLocalVars::TriggerLocalVars()
|
||||||
|
{
|
||||||
|
for(int g=0; g<EVAR_NUM; ++g)
|
||||||
|
evar[g] = 0.0;
|
||||||
|
for(int g=0; g<YVAR_NUM; ++g)
|
||||||
|
yvar[g] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VERMInterpreter::Environment::isBound( const std::string & name, bool globalOnly ) const
|
||||||
|
{
|
||||||
|
std::map<std::string, TVOption>::const_iterator it = symbols.find(name);
|
||||||
|
if(globalOnly && parent)
|
||||||
|
{
|
||||||
|
return parent->isBound(name, globalOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
//we have it; if globalOnly is true, lexical parent is false here so we are global env
|
||||||
|
if(it != symbols.end())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
//here, we don;t have it; but parent can have
|
||||||
|
if(parent)
|
||||||
|
return parent->isBound(name, globalOnly);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ERM::TVOption VERMInterpreter::Environment::retrieveValue( const std::string & name ) const
|
||||||
|
{
|
||||||
|
std::map<std::string, TVOption>::const_iterator it = symbols.find(name);
|
||||||
|
if(it == symbols.end())
|
||||||
|
{
|
||||||
|
if(parent)
|
||||||
|
{
|
||||||
|
return parent->retrieveValue(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw ESymbolNotFound(name);
|
||||||
|
}
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VERMInterpreter::Environment::unbind( const std::string & name, EUnbindMode mode )
|
||||||
|
{
|
||||||
|
if(isBound(name, false))
|
||||||
|
{
|
||||||
|
if(symbols.find(name) != symbols.end()) //result of isBound could be from higher lexical env
|
||||||
|
symbols.erase(symbols.find(name));
|
||||||
|
|
||||||
|
if(mode == FULLY_RECURSIVE && parent)
|
||||||
|
parent->unbind(name, mode);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(parent && (mode == RECURSIVE_UNTIL_HIT || mode == FULLY_RECURSIVE))
|
||||||
|
return parent->unbind(name, mode);
|
||||||
|
|
||||||
|
//neither bound nor have lexical parent
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -66,6 +66,29 @@ namespace VERMInterpreter
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct EExecutionError : public EInterpreterProblem
|
||||||
|
{
|
||||||
|
EExecutionError(const std::string & desc) :
|
||||||
|
EInterpreterProblem(desc)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
//internal interpreter error related to execution
|
||||||
|
struct EInterpreterError : public EExecutionError
|
||||||
|
{
|
||||||
|
EInterpreterError(const std::string & desc) :
|
||||||
|
EExecutionError(desc)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
//wrong script
|
||||||
|
struct EScriptExecError : public EExecutionError
|
||||||
|
{
|
||||||
|
EScriptExecError(const std::string & desc) :
|
||||||
|
EExecutionError(desc)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
///main environment class, manages symbols
|
///main environment class, manages symbols
|
||||||
class Environment
|
class Environment
|
||||||
@ -75,60 +98,13 @@ namespace VERMInterpreter
|
|||||||
Environment * parent;
|
Environment * parent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool isBound(const std::string & name, bool globalOnly) const
|
bool isBound(const std::string & name, bool globalOnly) const;
|
||||||
{
|
|
||||||
std::map<std::string, TVOption>::const_iterator it = symbols.find(name);
|
|
||||||
if(globalOnly && parent)
|
|
||||||
{
|
|
||||||
return parent->isBound(name, globalOnly);
|
|
||||||
}
|
|
||||||
|
|
||||||
//we have it; if globalOnly is true, lexical parent is false here so we are global env
|
TVOption retrieveValue(const std::string & name) const;
|
||||||
if(it != symbols.end())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
//here, we don;t have it; but parent can have
|
|
||||||
if(parent)
|
|
||||||
return parent->isBound(name, globalOnly);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TVOption retrieveValue(const std::string & name) const
|
|
||||||
{
|
|
||||||
std::map<std::string, TVOption>::const_iterator it = symbols.find(name);
|
|
||||||
if(it == symbols.end())
|
|
||||||
{
|
|
||||||
if(parent)
|
|
||||||
{
|
|
||||||
return parent->retrieveValue(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw ESymbolNotFound(name);
|
|
||||||
}
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum EUnbindMode{LOCAL, RECURSIVE_UNTIL_HIT, FULLY_RECURSIVE};
|
enum EUnbindMode{LOCAL, RECURSIVE_UNTIL_HIT, FULLY_RECURSIVE};
|
||||||
///returns true if symbols was really unbound
|
///returns true if symbols was really unbound
|
||||||
bool unbind(const std::string & name, EUnbindMode mode)
|
bool unbind(const std::string & name, EUnbindMode mode);
|
||||||
{
|
|
||||||
if(isBound(name, false))
|
|
||||||
{
|
|
||||||
if(symbols.find(name) != symbols.end()) //result of isBound could be from higher lexical env
|
|
||||||
symbols.erase(symbols.find(name));
|
|
||||||
|
|
||||||
if(mode == FULLY_RECURSIVE && parent)
|
|
||||||
parent->unbind(name, mode);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if(parent && (mode == RECURSIVE_UNTIL_HIT || mode == FULLY_RECURSIVE))
|
|
||||||
return parent->unbind(name, mode);
|
|
||||||
|
|
||||||
//neither bound nor have lexical parent
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// All numeric variables are integer variables and have a range of -2147483647...+2147483647
|
// All numeric variables are integer variables and have a range of -2147483647...+2147483647
|
||||||
@ -153,13 +129,7 @@ namespace VERMInterpreter
|
|||||||
|
|
||||||
static const int YVAR_NUM = 100; //number of yvar locals
|
static const int YVAR_NUM = 100; //number of yvar locals
|
||||||
int yvar[YVAR_NUM];
|
int yvar[YVAR_NUM];
|
||||||
TriggerLocalVars()
|
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
|
struct FunctionLocalVars
|
||||||
@ -179,6 +149,7 @@ namespace VERMInterpreter
|
|||||||
|
|
||||||
struct ERMEnvironment
|
struct ERMEnvironment
|
||||||
{
|
{
|
||||||
|
ERMEnvironment();
|
||||||
static const int NUM_QUICKS = 't' - 'f' + 1; //it should be 15
|
static const int NUM_QUICKS = 't' - 'f' + 1; //it should be 15
|
||||||
int quickVars[NUM_QUICKS]; //referenced by letter ('f' to 't' inclusive)
|
int quickVars[NUM_QUICKS]; //referenced by letter ('f' to 't' inclusive)
|
||||||
int & getQuickVar(const char letter)
|
int & getQuickVar(const char letter)
|
||||||
@ -194,6 +165,9 @@ namespace VERMInterpreter
|
|||||||
std::string strings[NUM_STRINGS]; //z-vars (positive indices)
|
std::string strings[NUM_STRINGS]; //z-vars (positive indices)
|
||||||
|
|
||||||
std::map<std::string, ERM::TVarExpNotMacro> macroBindings;
|
std::map<std::string, ERM::TVarExpNotMacro> macroBindings;
|
||||||
|
|
||||||
|
static const int NUM_FLAGS = 1000;
|
||||||
|
bool flags[NUM_FLAGS];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TriggerType
|
struct TriggerType
|
||||||
|
Loading…
x
Reference in New Issue
Block a user