From b0ca5b677c3e3e7d46ca74de24f183579e801ae6 Mon Sep 17 00:00:00 2001 From: mateuszb Date: Fri, 8 Apr 2011 19:24:30 +0000 Subject: [PATCH] * a few data structures for ERM/VERM interpreter --- lib/ERMInterpreter.cpp | 148 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) diff --git a/lib/ERMInterpreter.cpp b/lib/ERMInterpreter.cpp index ac31e364f..f2fbdfd04 100644 --- a/lib/ERMInterpreter.cpp +++ b/lib/ERMInterpreter.cpp @@ -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 symbols; + Environment * lexicalParent; + + public: + bool isBound(const std::string & name, bool globalOnly) const + { + std::map::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::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 entryPoints; //defines how to pass to current location + Environment * env; //most nested VERM environment + }; +} + + + namespace ERMPrinter { //console printer