mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-25 21:38:59 +02:00
* a few data structures for ERM/VERM interpreter
This commit is contained in:
parent
b0cecac5c9
commit
b0ca5b677c
@ -13,8 +13,156 @@
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
namespace spirit = boost::spirit;
|
||||
|
||||
namespace VERMInterpreter
|
||||
{
|
||||
using namespace ERM;
|
||||
|
||||
//different exceptions that can be thrown during interpreting
|
||||
class EInterpreterProblem : public std::exception
|
||||
{};
|
||||
|
||||
class ESymbolNotFound : public EInterpreterProblem
|
||||
{
|
||||
std::string problem;
|
||||
public:
|
||||
ESymbolNotFound(const std::string & sym) : problem(std::string("Symbol ") + sym + std::string(" not found!"))
|
||||
{}
|
||||
|
||||
const char * what() const throw() OVERRIDE
|
||||
{
|
||||
return problem.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///main environment class, manages symbols
|
||||
class Environment
|
||||
{
|
||||
private:
|
||||
std::map<std::string, TVOption> symbols;
|
||||
Environment * lexicalParent;
|
||||
|
||||
public:
|
||||
bool isBound(const std::string & name, bool globalOnly) const
|
||||
{
|
||||
std::map<std::string, TVOption>::const_iterator it = symbols.find(name);
|
||||
if(globalOnly && lexicalParent)
|
||||
{
|
||||
return lexicalParent->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(lexicalParent)
|
||||
return lexicalParent->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(lexicalParent)
|
||||
{
|
||||
return lexicalParent->retrieveValue(name);
|
||||
}
|
||||
|
||||
throw ESymbolNotFound(name);
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
///returns true if symbols was really unbound
|
||||
enum EUnbindMode{LOCAL, RECURSIVE_UNTIL_HIT, FULLY_RECURSIVE};
|
||||
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 && lexicalParent)
|
||||
lexicalParent->unbind(name, mode);
|
||||
|
||||
return true;
|
||||
}
|
||||
if(lexicalParent && (mode == RECURSIVE_UNTIL_HIT || mode == FULLY_RECURSIVE))
|
||||
return lexicalParent->unbind(name, mode);
|
||||
|
||||
//neither bound nor have lexical parent
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// All numeric variables are integer variables and have a range of -2147483647...+2147483647
|
||||
// c stores game active day number //indirect variable
|
||||
// d current value //not an actual variable but a modifier
|
||||
// e1..e100 Function floating point variables //local
|
||||
// e-1..e-100 Trigger local floating point variables //local
|
||||
// 'f'..'t' Standard variables ('quick variables') //global
|
||||
// v1..v1000 Standard variables //global
|
||||
// w1..w100 Hero variables
|
||||
// w101..w200 Hero variables
|
||||
// x1..x16 Function parameters //local
|
||||
// y1..y100 Function local variables //local
|
||||
// y-1..y-100 Trigger-based local integer variables //local
|
||||
// z1..z1000 String variables //global
|
||||
// z-1..z-10 Function local string variables //local
|
||||
|
||||
struct TriggerLocalVars
|
||||
{
|
||||
static const int EVAR_NUM = 100; //number of evar locals
|
||||
double evar[EVAR_NUM]; //negative indices
|
||||
|
||||
static const int YVAR_NUM = 100; //number of yvar locals
|
||||
int yvar[YVAR_NUM];
|
||||
};
|
||||
|
||||
struct FunctionLocalVars
|
||||
{
|
||||
static const int NUM_PARAMETERS = 16; //number of function parameters
|
||||
int params[NUM_PARAMETERS]; //x-vars
|
||||
|
||||
static const int NUM_LOCALS = 100;
|
||||
int locals[NUM_LOCALS]; //y-vars
|
||||
|
||||
static const int NUM_STRINGS = 10;
|
||||
std::string strings[NUM_STRINGS]; //z-vars (negative indices)
|
||||
|
||||
static const int NUM_FLOATINGS = 100;
|
||||
double floats[NUM_FLOATINGS]; //e-vars (positive indices)
|
||||
};
|
||||
|
||||
struct ERMEnvironment
|
||||
{
|
||||
static const int NUM_QUICKS = 't' - 'f' + 1; //it should be 15
|
||||
int quickVars[NUM_QUICKS]; //referenced by letter ('f' to 't' inclusive)
|
||||
|
||||
static const int NUM_STANDARDS = 1000;
|
||||
int standardVars[NUM_STANDARDS]; //v-vars
|
||||
|
||||
static const int NUM_STRINGS = 1000;
|
||||
std::string strings[NUM_STRINGS]; //z-vars (positive indices)
|
||||
};
|
||||
|
||||
//call stack
|
||||
class Stack
|
||||
{
|
||||
std::vector<int> entryPoints; //defines how to pass to current location
|
||||
Environment * env; //most nested VERM environment
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace ERMPrinter
|
||||
{
|
||||
//console printer
|
||||
|
Loading…
x
Reference in New Issue
Block a user