فهرست منبع

* some progress in VERM interpreter

mateuszb 14 سال پیش
والد
کامیت
36fb9b0b6e
3فایلهای تغییر یافته به همراه268 افزوده شده و 11 حذف شده
  1. 209 2
      lib/ERMInterpreter.cpp
  2. 56 7
      lib/ERMInterpreter.h
  3. 3 2
      lib/VCMI_Lib.cpp

+ 209 - 2
lib/ERMInterpreter.cpp

@@ -402,11 +402,53 @@ void ERMInterpreter::printScripts( EPrintMode mode /*= EPrintMode::ALL*/ )
 	}
 }
 
+struct ScriptScanner : boost::static_visitor<>
+{
+	ERMInterpreter * interpreter;
+	LinePointer lp;
+
+	ScriptScanner(ERMInterpreter * interpr, const LinePointer & _lp) : interpreter(interpr), lp(_lp)
+	{}
+
+	void operator()(TVExp const& cmd) const
+	{
+		//
+	}
+	void operator()(TERMline const& cmd) const
+	{
+		if(cmd.which() == 0) //TCommand
+		{
+			Tcommand tcmd = boost::get<Tcommand>(cmd);
+			switch (tcmd.cmd.which())
+			{
+			case 0: //trigger
+				{
+					Trigger trig;
+					trig.line = lp;
+					interpreter->triggers[ TriggerType(boost::get<ERM::Ttrigger>(tcmd.cmd).name) ].push_back(trig);
+				}
+				break;
+			case 3: //post trigger
+				{
+					Trigger trig;
+					trig.line = lp;
+					interpreter->postTriggers[ TriggerType(boost::get<ERM::TPostTrigger>(tcmd.cmd).name) ].push_back(trig);
+				}
+				break;
+			default:
+
+				break;
+			}
+		}
+		
+	}
+};
+
 void ERMInterpreter::scanScripts()
 {
 	for(std::map< LinePointer, ERM::TLine >::const_iterator it = scripts.begin(); it != scripts.end(); ++it)
 	{
-
+		boost::apply_visitor(ScriptScanner(this, it->first), it->second);
 	}
 }
 
@@ -442,7 +484,7 @@ bool ERMInterpreter::isATrigger( const ERM::TLine & line )
 			case SYMBOL:
 				{
 					//TODO: what about sym modifiers?
-					//TOOD: macros
+					//TOOD: macros?
 					ERM::TSymbol sym = boost::get<ERM::TSymbol>(vexp.children[0]);
 					return sym.sym == triggerSymbol || sym.sym == postTriggerSymbol;
 				}
@@ -502,11 +544,176 @@ ERM::TLine ERMInterpreter::retrieveLine( LinePointer linePtr ) const
 	return *scripts.find(linePtr);
 }
 
+/////////
+//code execution
+
+struct ERMExpDispatch : boost::static_visitor<>
+{
+	void operator()(Ttrigger const& trig) const
+	{
+		//the first executed line, check if we should proceed
+	}
+	void operator()(Tinstruction const& trig) const
+	{
+	}
+	void operator()(Treceiver const& trig) const
+	{
+	}
+	void operator()(TPostTrigger const& trig) const
+	{
+	}
+};
+
+struct CommandExec : boost::static_visitor<>
+{
+	void operator()(Tcommand const& cmd) const
+	{
+		boost::apply_visitor(ERMExpDispatch(), cmd.cmd);
+		std::cout << "Line comment: " << cmd.comment << std::endl;
+	}
+	void operator()(std::string const& comment) const
+	{
+		//comment - do nothing
+	}
+	void operator()(spirit::unused_type const& nothing) const
+	{
+		//nothing - do nothing
+	}
+};
+
+struct LineExec : boost::static_visitor<>
+{
+	void operator()(TVExp const& cmd) const
+	{
+		//printTVExp(cmd);
+	}
+	void operator()(TERMline const& cmd) const
+	{
+		boost::apply_visitor(CommandExec(), cmd);
+	}
+};
+
+/////////
+
 void ERMInterpreter::executeLine( const LinePointer & lp )
 {
+	boost::apply_visitor(LineExec(), scripts[lp]);
+}
+
+void ERMInterpreter::init()
+{
+	ermGlobalEnv = new ERMEnvironment();
+	globalEnv = new Environment();
+	//TODO: reset?
+}
+
+struct ERMExecEnvironment
+{
+	ERMEnvironment * ermGlobalEnv;
+	Trigger * trigEnv;
+	ERMExecEnvironment(ERMEnvironment * erm, Trigger * trig = NULL) : ermGlobalEnv(erm), trigEnv(trig)
+	{}
+};
+
+template<typename T>
+struct LVL2GetIexpDisemboweler : boost::static_visitor<>
+{
+	T & out;
+	const ERMExecEnvironment * env;
+	LVL2GetIexpDisemboweler(T & ret, const ERMExecEnvironment * _env) : out(ret), env(_env) //writes value to given var
+	{}
+
+	void processNotMacro(const TVarExpNotMacro & val) const
+	{
+		if(val.questionMark.is_initialized())
+			throw EIexpGetterProblem("Question marks ('?') are not allowed in getter i-expressions");
+
+		//TODO: finish it
+	}
+
+	void operator()(TVarExpNotMacro const& val) const
+	{
+		processNotMacro(val);
+	}
+	void operator()(TMacroUsage const& val) const
+	{
+		std::map<std::string, ERM::TVarExpNotMacro>::const_iterator it =
+			env->ermGlobalEnv->macroBindings.find(val	.macro);
+		if(it == env->ermGlobalEnv->macroBindings.end())
+			throw EUsageOfUndefinedMacro(val.macro);
+		else
+			processNotMacro(it->second);
+	}
+};
+
+template<typename T>
+struct LVL1GetIexpDisemboweler : boost::static_visitor<>
+{
+	T & out;
+	const ERMExecEnvironment * env;
+	LVL1GetIexpDisemboweler(T & ret, const ERMExecEnvironment * _env) : out(ret), env(_env) //writes value to given var
+	{}
+	void operator()(int const & constant) const
+	{
+		out = constant;
+	}
+	void operator()(TVarExp const & var) const
+	{
+		
+	}
+};
 
+template<typename T>
+T ERMInterpreter::getIexp( const ERM::TIexp & iexp, const Trigger * trig /*= NULL*/ ) const
+{
+	T ret;
+	boost::apply_visitor(LVL1GetIexpDisemboweler(ret, ERMExecEnvironment(ermGlobalEnv, trig)), iexp);
+	return ret;
 }
 
 const std::string ERMInterpreter::triggerSymbol = "trigger";
 const std::string ERMInterpreter::postTriggerSymbol = "postTrigger";
+const std::string ERMInterpreter::defunSymbol = "defun";
+
 
+struct TriggerIdMatchHelper : boost::static_visitor<>
+{
+	int & ret;
+	TriggerIdMatchHelper(int & b) : ret(b)
+	{}
+
+	void operator()(TIexp const& iexp) const
+	{
+		
+	}
+	void operator()(TArithmeticOp const& arop) const
+	{
+		//error?!?
+	}
+};
+
+bool TriggerIdentifierMatch::tryMatch( const ERM::Ttrigger & trig ) const
+{
+	if(trig.identifier.is_initialized())
+	{
+		ERM::Tidentifier tid = trig.identifier.get();
+		std::map< int, std::vector<int> >::const_iterator it = matchToIt.find(tid.size());
+		if(it == matchToIt.end())
+			return false;
+		else
+		{
+			const std::vector<int> & pattern = it->second;
+			for(int g=0; g<pattern.size(); ++g)
+			{
+				int val = -1;
+				boost::apply_visitor(TriggerIdMatchHelper(val), tid[g]);
+				return pattern[g] == val;
+			}
+		}
+	}
+	else
+	{
+		if(allowNoIdetifier)
+			return true;
+	}
+}

+ 56 - 7
lib/ERMInterpreter.h

@@ -1,8 +1,6 @@
 #pragma once
 #include "../global.h"
 #include "ERMParser.h"
-#include <boost/smart_ptr.hpp>
-#include <boost/shared_ptr.hpp>
 
 /*
  * ERMInterpreter.h, part of VCMI engine
@@ -27,7 +25,8 @@ namespace VERMInterpreter
 		{
 			return problem.c_str();
 		}
-		~EInterpreterProblem() throw();
+		~EInterpreterProblem() throw()
+		{}
 		EInterpreterProblem(const std::string & problemDesc) : problem(problemDesc)
 		{}
 	};
@@ -46,6 +45,20 @@ namespace VERMInterpreter
 		{}
 	};
 
+	struct EUsageOfUndefinedMacro : public EInterpreterProblem
+	{
+		EUsageOfUndefinedMacro(const std::string & macro) :
+			EInterpreterProblem(std::string("Macro ") + macro + " is undefined")
+		{}
+	};
+
+	struct EIexpGetterProblem : public EInterpreterProblem
+	{
+		EIexpGetterProblem(const std::string & desc) :
+			EInterpreterProblem(desc)
+		{}
+	};
+
 
 	///main environment class, manages symbols
 	class Environment
@@ -133,6 +146,13 @@ 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;
+		}
 	};
 
 	struct FunctionLocalVars
@@ -165,6 +185,8 @@ namespace VERMInterpreter
 
 		static const int NUM_STRINGS = 1000;
 		std::string strings[NUM_STRINGS]; //z-vars (positive indices)
+
+		std::map<std::string, ERM::TVarExpNotMacro> macroBindings;
 	};
 
 	struct TriggerType
@@ -186,6 +208,11 @@ namespace VERMInterpreter
 			throw EInvalidTrigger(trig);
 		}
 
+		bool operator<(const TriggerType & t2) const
+		{
+			return type < t2.type;
+		}
+
 		TriggerType(const std::string & sym)
 		{
 			type = convertTrigger(sym);
@@ -204,6 +231,9 @@ namespace VERMInterpreter
 		const FileInfo * file; //non-owning
 		int lineNum;
 
+		LinePointer() : file(NULL)
+		{}
+
 		LinePointer(const FileInfo * finfo, int line) : file(finfo), lineNum(line)
 		{}
 
@@ -227,7 +257,7 @@ namespace VERMInterpreter
 		}
 		bool isValid() const
 		{
-			return lineNum < file->length;
+			return file && lineNum < file->length;
 		}
 	};
 
@@ -265,22 +295,40 @@ namespace VERMInterpreter
 		LinePointer line;
 		TriggerLocalVars ermLocalVars;
 		Stack * stack; //where we are stuck at execution
+		Trigger() : stack(NULL)
+		{}
 	};
 
 }
 
+struct TriggerIdentifierMatch
+{
+	bool allowNoIdetifier;
+	std::map< int, std::vector<int> > matchToIt; //match subidentifiers to these numbers
+
+	static const int MAX_SUBIDENTIFIERS = 16;
+	bool tryMatch(const ERM::Ttrigger & trig) const;
+};
+
 class ERMInterpreter
 {
+	friend class ScriptScanner;
+
 	std::vector<VERMInterpreter::FileInfo*> files;
-	std::vector< boost::shared_ptr<VERMInterpreter::FileInfo> > fileInfos;
+	std::vector< VERMInterpreter::FileInfo* > fileInfos;
 	std::map<VERMInterpreter::LinePointer, ERM::TLine> scripts;
 	std::map<VERMInterpreter::LexicalPtr, VERMInterpreter::Environment> lexicalEnvs;
 	ERM::TLine retrieveLine(VERMInterpreter::LinePointer linePtr) const;
 
 	VERMInterpreter::Environment * globalEnv;
-	std::map<VERMInterpreter::TriggerType, std::vector<VERMInterpreter::Trigger> > triggers;
+	VERMInterpreter::ERMEnvironment * ermGlobalEnv;
+	std::map<VERMInterpreter::TriggerType, std::vector<VERMInterpreter::Trigger> > triggers, postTriggers;
+
+
+	template<typename T> void setIexp(const ERM::TIexp & iexp, const T & val, VERMInterpreter::Trigger * trig = NULL);
+	template<typename T> T getIexp(const ERM::TIexp & iexp, const VERMInterpreter::Trigger * trig = NULL) const;
 
-	static const std::string triggerSymbol, postTriggerSymbol;
+	static const std::string triggerSymbol, postTriggerSymbol, defunSymbol;
 
 	void executeLine(const VERMInterpreter::LinePointer & lp);
 	void executeTrigger(VERMInterpreter::Trigger & trig);
@@ -288,6 +336,7 @@ class ERMInterpreter
 	static bool isATrigger(const ERM::TLine & line);
 	static ERM::EVOtions getExpType(const ERM::TVOption & opt);
 public:
+	void init(); //sets up environment etc.
 	void scanForScripts();
 
 	enum EPrintMode{ALL, ERM_ONLY, VERM_ONLY};

+ 3 - 2
lib/VCMI_Lib.cpp

@@ -52,9 +52,10 @@ DLL_EXPORT void initDLL(CConsoleHandler *Console, std::ostream *Logfile)
 	} HANDLE_EXCEPTION;
 
 
-//  	ERMInterpreter ei;
+ 	ERMInterpreter ei;
 //  	ei.scanForScripts();
-//  	ei.printScripts();
+//  	//ei.printScripts();
+// 	ei.scanScripts();
 }
 
 DLL_EXPORT void loadToIt(std::string &dest, const std::string &src, int &iter, int mode)