1
0
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:
mateuszb 2011-04-08 19:24:30 +00:00
parent b0cecac5c9
commit b0ca5b677c

View File

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