Przeglądaj źródła

* arithmetic and boolean operations on variables
* hopefully working DO receiver

mateuszb 14 lat temu
rodzic
commit
743df272e4
2 zmienionych plików z 196 dodań i 13 usunięć
  1. 70 12
      lib/ERMInterpreter.cpp
  2. 126 1
      lib/ERMInterpreter.h

+ 70 - 12
lib/ERMInterpreter.cpp

@@ -4,6 +4,7 @@
 #include <boost/algorithm/string.hpp>
 #include <boost/foreach.hpp>
 #include <boost/lexical_cast.hpp>
+#include <boost/assign/std/vector.hpp> // for 'operator+=()'
 
 /*
  * ERMInterpreter.cpp, part of VCMI engine
@@ -17,6 +18,7 @@
 
 namespace spirit = boost::spirit;
 using namespace VERMInterpreter;
+using namespace boost::assign;
 
 namespace ERMPrinter
 {
@@ -580,11 +582,47 @@ struct VRPerformer : boost::static_visitor<>
 
 	void operator()(TVRLogic const& trig) const
 	{
-		//TODO
+		int valr = interp->getIexp(trig.var).getInt();
+		switch (trig.opcode)
+		{
+		case '&':
+			const_cast<VRPerformer*>(this)->identifier.setTo(identifier.getInt() & valr);
+			break;
+		case '|':
+			const_cast<VRPerformer*>(this)->identifier.setTo(identifier.getInt() | valr);
+			break;
+		case 'X':
+			const_cast<VRPerformer*>(this)->identifier.setTo(identifier.getInt() ^ valr);
+			break;
+		default:
+			throw EInterpreterError("Wrong opcode in VR logic expression!");
+			break;
+		}
 	}
 	void operator()(TVRArithmetic const& trig) const
 	{
-		//TODO
+		IexpValStr rhs = interp->getIexp(trig.rhs);
+		switch (trig.opcode)
+		{
+		case '+':
+			const_cast<VRPerformer*>(this)->identifier += rhs;
+			break;
+		case '-':
+			const_cast<VRPerformer*>(this)->identifier -= rhs;
+			break;
+		case '*':
+			const_cast<VRPerformer*>(this)->identifier *= rhs;
+			break;
+		case ':':
+			const_cast<VRPerformer*>(this)->identifier /= rhs;
+			break;
+		case '%':
+			const_cast<VRPerformer*>(this)->identifier %= rhs;
+			break;
+		default:
+			throw EInterpreterError("Wrong opcode in VR arithmetic!");
+			break;
+		}
 	}
 	void operator()(TNormalBodyOption const& trig) const
 	{
@@ -618,21 +656,37 @@ void VR_SPerformer::operator()(ERM::TIexp const& trig) const
 }
 
 void VR_SPerformer::operator()(TVarConcatString const& cmp) const
-{}
+{
+	throw EScriptExecError("String concatenation not allowed in VR S");
+}
 void VR_SPerformer::operator()(TStringConstant const& cmp) const
-{}
+{
+	owner.identifier.setTo(cmp.str);
+}
 void VR_SPerformer::operator()(TCurriedString const& cmp) const
-{}
+{
+	throw EScriptExecError("Curried string not allowed in VR S");
+}
 void VR_SPerformer::operator()(TSemiCompare const& cmp) const
-{}
+{
+	throw EScriptExecError("Incomplete comparison not allowed in VR S");
+}
 void VR_SPerformer::operator()(TMacroUsage const& cmp) const
-{}
+{
+	owner.identifier.setTo(owner.interp->getIexp(cmp));
+}
 void VR_SPerformer::operator()(TMacroDef const& cmp) const
-{}
+{
+	throw EScriptExecError("Macro definition not allowed in VR S");
+}
 void VR_SPerformer::operator()(TVarpExp const& cmp) const
-{}
+{
+	throw EScriptExecError("Write-only variable expression not allowed in VR S");
+}
 void VR_SPerformer::operator()(spirit::unused_type const& cmp) const
-{}
+{
+	throw EScriptExecError("Expression not allowed in VR S");
+}
 
 struct ConditionDisemboweler;
 
@@ -703,7 +757,11 @@ struct ERMExpDispatch : boost::static_visitor<>
 				for(int it = startVal; it < stopVal; it += increment)
 				{
 					owner->getFuncVars(funNum)->getParam(16) = it;
-					//owner->executeTriggerType(TriggerType("FU"), true, );
+					ERMInterpreter::TIDPattern tip;
+					std::vector<int> v1;
+					v1 += funNum;
+					insert(tip) (v1.size(), v1);
+					owner->executeTriggerType(TriggerType("FU"), true, tip);
 					it = owner->getFuncVars(funNum)->getParam(16);
 				}
 			}
@@ -1041,7 +1099,7 @@ IexpValStr ERMInterpreter::getIexp( const ERM::TIdentifierInternal & tid ) const
 		throw EScriptExecError("Identifier must be a valid i-expression to perform this operation!");
 }
 
-void ERMInterpreter::executeTriggerType( VERMInterpreter::TriggerType tt, bool pre, const std::map< int, std::vector<int> > & identifier )
+void ERMInterpreter::executeTriggerType( VERMInterpreter::TriggerType tt, bool pre, const TIDPattern & identifier )
 {
 	TtriggerListType & triggerList = pre ? triggers : postTriggers;
 

+ 126 - 1
lib/ERMInterpreter.h

@@ -340,6 +340,129 @@ public:
 	{
 		val.stringvar = _val;
 	}
+
+#define OPERATOR_DEFINITION_FULL(OPSIGN) \
+	template<typename T> \
+	IexpValStr operator OPSIGN(const T & sec) const \
+	{ \
+		IexpValStr ret = *this; \
+		switch (type) \
+		{ \
+		case INT: \
+		case INTVAR: \
+			ret.setTo(ret.getInt() OPSIGN sec); \
+			break; \
+		case FLOATVAR: \
+			ret.setTo(ret.getFloat() OPSIGN sec); \
+			break; \
+		case STRINGVAR: \
+			ret.setTo(ret.getString() OPSIGN sec); \
+			break; \
+		} \
+		return ret; \
+	} \
+	IexpValStr operator OPSIGN(const IexpValStr & sec) const \
+	{ \
+		IexpValStr ret = *this; \
+		switch (type) \
+		{ \
+		case INT: \
+		case INTVAR: \
+			ret.setTo(ret.getInt() OPSIGN sec.getInt()); \
+			break; \
+		case FLOATVAR: \
+			ret.setTo(ret.getFloat() OPSIGN sec.getFloat()); \
+			break; \
+		case STRINGVAR: \
+			ret.setTo(ret.getString() OPSIGN sec.getString()); \
+			break; \
+		} \
+		return ret; \
+	} \
+	template<typename T> \
+	IexpValStr & operator OPSIGN ## = (const T & sec) \
+	{ \
+		*this = *this OPSIGN sec; \
+		return *this; \
+	}
+
+#define OPERATOR_DEFINITION(OPSIGN) \
+	template<typename T> \
+	IexpValStr operator OPSIGN(const T & sec) const \
+	{ \
+		IexpValStr ret = *this; \
+		switch (type) \
+		{ \
+		case INT: \
+		case INTVAR: \
+			ret.setTo(ret.getInt() OPSIGN sec); \
+			break; \
+		case FLOATVAR: \
+			ret.setTo(ret.getFloat() OPSIGN sec); \
+			break; \
+		} \
+		return ret; \
+	} \
+	IexpValStr operator OPSIGN(const IexpValStr & sec) const \
+	{ \
+		IexpValStr ret = *this; \
+		switch (type) \
+		{ \
+		case INT: \
+		case INTVAR: \
+			ret.setTo(ret.getInt() OPSIGN sec.getInt()); \
+			break; \
+		case FLOATVAR: \
+			ret.setTo(ret.getFloat() OPSIGN sec.getFloat()); \
+			break; \
+		} \
+		return ret; \
+	} \
+	template<typename T> \
+	IexpValStr & operator OPSIGN ## = (const T & sec) \
+	{ \
+		*this = *this OPSIGN sec; \
+		return *this; \
+	}
+
+#define OPERATOR_DEFINITION_INTEGER(OPSIGN) \
+	template<typename T> \
+	IexpValStr operator OPSIGN(const T & sec) const \
+	{ \
+		IexpValStr ret = *this; \
+		switch (type) \
+		{ \
+		case INT: \
+		case INTVAR: \
+			ret.setTo(ret.getInt() OPSIGN sec); \
+			break; \
+		} \
+		return ret; \
+	} \
+	IexpValStr operator OPSIGN(const IexpValStr & sec) const \
+	{ \
+		IexpValStr ret = *this; \
+		switch (type) \
+		{ \
+		case INT: \
+		case INTVAR: \
+			ret.setTo(ret.getInt() OPSIGN sec.getInt()); \
+			break; \
+		} \
+		return ret; \
+	} \
+	template<typename T> \
+	IexpValStr & operator OPSIGN ## = (const T & sec) \
+	{ \
+		*this = *this OPSIGN sec; \
+		return *this; \
+	}
+
+	OPERATOR_DEFINITION_FULL(+)
+	OPERATOR_DEFINITION(-)
+	OPERATOR_DEFINITION(*)
+	OPERATOR_DEFINITION(/)
+	OPERATOR_DEFINITION_INTEGER(%)
 };
 
 class ERMInterpreter
@@ -351,6 +474,7 @@ class ERMInterpreter
 	friend struct LVL2IexpDisemboweler;
 	friend struct VR_SPerformer;
 	friend struct ERMExpDispatch;
+	friend struct VRPerformer;
 
 	std::vector<VERMInterpreter::FileInfo*> files;
 	std::vector< VERMInterpreter::FileInfo* > fileInfos;
@@ -382,7 +506,8 @@ class ERMInterpreter
 	static ERM::EVOtions getExpType(const ERM::TVOption & opt);
 	IexpValStr getVar(std::string toFollow, boost::optional<int> initVal) const;
 public:
-	void executeTriggerType(VERMInterpreter::TriggerType tt, bool pre, const std::map< int, std::vector<int> > & identifier); //use this to run triggers
+	typedef std::map< int, std::vector<int> > TIDPattern;
+	void executeTriggerType(VERMInterpreter::TriggerType tt, bool pre, const TIDPattern & identifier); //use this to run triggers
 	void init(); //sets up environment etc.
 	void scanForScripts();