Ver código fonte

* minor work on ERM interpreter

mateuszb 14 anos atrás
pai
commit
4ac2d32985
2 arquivos alterados com 125 adições e 63 exclusões
  1. 94 6
      lib/ERMInterpreter.cpp
  2. 31 57
      lib/ERMInterpreter.h

+ 94 - 6
lib/ERMInterpreter.cpp

@@ -460,7 +460,10 @@ ERMInterpreter::ERMInterpreter()
 
 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);
 		if(isATrigger(curLine))
@@ -550,9 +553,13 @@ ERM::TLine ERMInterpreter::retrieveLine( LinePointer linePtr ) const
 
 struct ERMExpDispatch : boost::static_visitor<>
 {
+	ERMInterpreter * owner;
+	ERMExpDispatch(ERMInterpreter * _owner) : owner(_owner)
+	{}
+
 	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
 	{
@@ -562,14 +569,19 @@ struct ERMExpDispatch : boost::static_visitor<>
 	}
 	void operator()(TPostTrigger const& trig) const
 	{
+		throw EInterpreterError("Post-triggers cannot be executed!");
 	}
 };
 
 struct CommandExec : boost::static_visitor<>
 {
+	ERMInterpreter * owner;
+	CommandExec(ERMInterpreter * _owner) : owner(_owner)
+	{}
+
 	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;
 	}
 	void operator()(std::string const& comment) const
@@ -584,13 +596,17 @@ struct CommandExec : boost::static_visitor<>
 
 struct LineExec : boost::static_visitor<>
 {
+	ERMInterpreter * owner;
+	LineExec(ERMInterpreter * _owner) : owner(_owner)
+	{}
+
 	void operator()(TVExp const& cmd) const
 	{
 		//printTVExp(cmd);
 	}
 	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 )
 {
-	boost::apply_visitor(LineExec(), scripts[lp]);
+	boost::apply_visitor(LineExec(this), scripts[lp]);
 }
 
 void ERMInterpreter::init()
@@ -893,7 +909,7 @@ void ERMInterpreter::executeTriggerType( VERMInterpreter::TriggerType tt, bool p
 	tim.allowNoIdetifier = false;
 	tim.ermEnv = this;
 	tim.matchToIt = identifier;
-	std::vector<Trigger> triggersToTry = triggerList[tt];
+	std::vector<Trigger> & triggersToTry = triggerList[tt];
 	for(int g=0; g<triggersToTry.size(); ++g)
 	{
 		if(tim.tryMatch(&triggersToTry[g]))
@@ -976,3 +992,75 @@ bool TriggerIdentifierMatch::tryMatch( Trigger * interptrig ) const
 			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;
+}

+ 31 - 57
lib/ERMInterpreter.h

@@ -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
 	class Environment
@@ -75,60 +98,13 @@ namespace VERMInterpreter
 		Environment * parent;
 
 	public:
-		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
-			if(it != symbols.end())
-				return true;
+		bool isBound(const std::string & name, bool globalOnly) const;
 
-			//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;
-		}
+		TVOption retrieveValue(const std::string & name) const;
 
 		enum EUnbindMode{LOCAL, RECURSIVE_UNTIL_HIT, FULLY_RECURSIVE};
 		///returns true if symbols was really unbound
-		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;
-		}
+		bool unbind(const std::string & name, EUnbindMode mode);
 	};
 
 	//		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
 		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;
-		}
+		TriggerLocalVars();
 	};
 
 	struct FunctionLocalVars
@@ -179,6 +149,7 @@ namespace VERMInterpreter
 
 	struct ERMEnvironment
 	{
+		ERMEnvironment();
 		static const int NUM_QUICKS = 't' - 'f' + 1; //it should be 15
 		int quickVars[NUM_QUICKS]; //referenced by letter ('f' to 't' inclusive)
 		int & getQuickVar(const char letter)
@@ -194,6 +165,9 @@ namespace VERMInterpreter
 		std::string strings[NUM_STRINGS]; //z-vars (positive indices)
 
 		std::map<std::string, ERM::TVarExpNotMacro> macroBindings;
+
+		static const int NUM_FLAGS = 1000;
+		bool flags[NUM_FLAGS];
 	};
 
 	struct TriggerType