瀏覽代碼

* partially done DO receiver

mateuszb 14 年之前
父節點
當前提交
2d36cae2ca
共有 2 個文件被更改,包括 213 次插入130 次删除
  1. 178 126
      lib/ERMInterpreter.cpp
  2. 35 4
      lib/ERMInterpreter.h

+ 178 - 126
lib/ERMInterpreter.cpp

@@ -614,51 +614,7 @@ VR_SPerformer::VR_SPerformer(VRPerformer & _owner) : owner(_owner)
 
 void VR_SPerformer::operator()(ERM::TIexp const& trig) const
 {
-	IexpValStr sv = owner.interp->getIexp(trig);
-	switch(owner.identifier.type)
-	{
-	case IexpValStr::FLOATVAR:
-		switch(sv.type)
-		{
-		case IexpValStr::FLOATVAR:
-			*owner.identifier.val.flvar = *sv.val.flvar;
-			break;
-		default:
-			throw EScriptExecError("Incompatible data types in VR S receiver: expected float var!");
-			break;
-		}
-		break;
-	case IexpValStr::INT:
-		throw EScriptExecError("VR S: value not assignable!");
-		break;
-	case IexpValStr::INTVAR:
-		switch(sv.type)
-		{
-		case IexpValStr::INT:
-			*owner.identifier.val.integervar = sv.val.val;
-			break;
-		case IexpValStr::INTVAR:
-			*owner.identifier.val.integervar = *sv.val.integervar;
-			break;
-		default:
-			throw EScriptExecError("Incompatible data types in VR S receiver: expected int var or constant!");
-			break;
-		}
-		break;
-	case IexpValStr::STRINGVAR:
-		switch(sv.type)
-		{
-		case IexpValStr::STRINGVAR:
-			*owner.identifier.val.stringvar = *sv.val.stringvar;
-			break;
-		default:
-			throw EScriptExecError("Incompatible data types in VR S receiver: expected string var!");
-			break;
-		}
-		break;
-	default:
-		throw EScriptExecError("Wrong type of identifier iexp!");
-	}
+	owner.identifier.setTo(owner.interp->getIexp(trig));
 }
 
 void VR_SPerformer::operator()(TVarConcatString const& cmp) const
@@ -711,23 +667,17 @@ struct ERMExpDispatch : boost::static_visitor<>
 				ERM::Tidentifier ident = trig.identifier.get();
 				if(ident.size() == 1)
 				{
-					ERM::TIdentifierInternal idint = ident[0];
-					if(idint.which() == 0)
-					{
-						IexpValStr ievs = owner->getIexp(boost::get<ERM::TIexp>(idint));
+					IexpValStr ievs = owner->getIexp(ident[0]);
 
-						//see body
-						if(trig.body.is_initialized())
+					//see body
+					if(trig.body.is_initialized())
+					{
+						ERM::Tbody bo = trig.body.get();
+						for(int g=0; g<bo.size(); ++g)
 						{
-							ERM::Tbody bo = trig.body.get();
-							for(int g=0; g<bo.size(); ++g)
-							{
-								boost::apply_visitor(VRPerformer(owner, ievs), bo[g]);
-							}
+							boost::apply_visitor(VRPerformer(owner, ievs), bo[g]);
 						}
 					}
-					else
-						throw EScriptExecError("Identifier of a VR receiver must be a valid i-expression!");
 				}
 				else
 					throw EScriptExecError("VR receiver must be used with exactly one identifier item!");
@@ -735,6 +685,29 @@ struct ERMExpDispatch : boost::static_visitor<>
 			else
 				throw EScriptExecError("VR receiver must be used with an identifier!");
 		}
+		else if(trig.name == "DO")
+		{
+			//perform operations
+			if(trig.identifier.is_initialized())
+			{
+				ERM::Tidentifier tid = trig.identifier.get();
+				if(tid.size() != 4)
+				{
+					throw EScriptExecError("DO receiver takes exactly 4 arguments");
+				}
+				int funNum = owner->getIexp(tid[0]).getInt(),
+					startVal = owner->getIexp(tid[1]).getInt(),
+					stopVal = owner->getIexp(tid[2]).getInt(),
+					increment = owner->getIexp(tid[3]).getInt();
+
+				for(int it = startVal; it < stopVal; it += increment)
+				{
+					owner->getFuncVars(funNum)->getParam(16) = it;
+					//owner->executeTriggerType(TriggerType("FU"), true, );
+					it = owner->getFuncVars(funNum)->getParam(16);
+				}
+			}
+		}
 		else
 		{
 			//unsupported or invalid trigger
@@ -797,7 +770,7 @@ void ERMInterpreter::init()
 	//TODO: reset?
 }
 
-IexpValStr ERMInterpreter::getVar(std::string toFollow, boost::optional<int> initVal)
+IexpValStr ERMInterpreter::getVar(std::string toFollow, boost::optional<int> initVal) const
 {
 	IexpValStr ret;
 	ret.type = IexpValStr::WRONGVAL;
@@ -819,10 +792,7 @@ IexpValStr ERMInterpreter::getVar(std::string toFollow, boost::optional<int> ini
 	if(toFollow.size() == 0)
 	{
 		if(hasInit)
-		{
-			ret.val.val = initV;
-			ret.type = IexpValStr::INT;
-		}
+			ret = IexpValStr(initV);
 		else
 			throw EIexpProblem("No input to getVar!");
 
@@ -852,20 +822,14 @@ IexpValStr ERMInterpreter::getVar(std::string toFollow, boost::optional<int> ini
 					if(initV > 0 && initV <= FunctionLocalVars::NUM_FLOATINGS)
 					{
 						if(curFunc)
-						{
-							ret.val.flvar = &curFunc->getFloat(initV);
-							ret.type = IexpValStr::FLOATVAR;
-						}
+							ret = IexpValStr(&curFunc->getFloat(initV));
 						else
 							throw EIexpProblem("Function context not available!");
 					}
 					else if(initV < 0 && initV >= -TriggerLocalVars::EVAR_NUM)
 					{
 						if(curTrigger)
-						{
-							ret.val.flvar = &curTrigger->ermLocalVars.getEvar(initV);
-							ret.type = IexpValStr::FLOATVAR;
-						}
+							ret = IexpValStr(&curTrigger->ermLocalVars.getEvar(initV));
 						else
 							throw EIexpProblem("No trigger context available!");
 					}
@@ -881,10 +845,7 @@ IexpValStr ERMInterpreter::getVar(std::string toFollow, boost::optional<int> ini
 		else if(cr >= 'f' && cr <= 't')
 		{
 			if(retIt)
-			{
-				ret.val.integervar = &ermGlobalEnv->getQuickVar(cr);
-				ret.type = IexpValStr::INTVAR;
-			}
+				ret = IexpValStr(&ermGlobalEnv->getQuickVar(cr));
 			else
 			{
 				if(hasInit)
@@ -901,10 +862,7 @@ IexpValStr ERMInterpreter::getVar(std::string toFollow, boost::optional<int> ini
 			if(hasInit)
 			{
 				if(retIt)
-				{
-					ret.val.integervar = &ermGlobalEnv->getStandardVar(initV);
-					ret.type = IexpValStr::INTVAR;
-				}
+					ret = IexpValStr(&ermGlobalEnv->getStandardVar(initV));
 				else
 					initV = ermGlobalEnv->getStandardVar(initV);
 			}
@@ -922,10 +880,7 @@ IexpValStr ERMInterpreter::getVar(std::string toFollow, boost::optional<int> ini
 				if(curFunc)
 				{
 					if(retIt)
-					{
-						ret.val.integervar = &curFunc->getParam(initV);
-						ret.type = IexpValStr::INTVAR;
-					}
+						ret = IexpValStr(&curFunc->getParam(initV));
 					else
 						initV = curFunc->getParam(initV);
 				}
@@ -943,10 +898,7 @@ IexpValStr ERMInterpreter::getVar(std::string toFollow, boost::optional<int> ini
 					if(curFunc)
 					{
 						if(retIt)
-						{
-							ret.val.integervar = &curFunc->getLocal(initV);
-							ret.type = IexpValStr::INTVAR;
-						}
+							ret = IexpValStr(&curFunc->getLocal(initV));
 						else
 							initV = curFunc->getLocal(initV);
 					}
@@ -958,10 +910,7 @@ IexpValStr ERMInterpreter::getVar(std::string toFollow, boost::optional<int> ini
 					if(curTrigger)
 					{
 						if(retIt)
-						{
-							ret.val.integervar = &curTrigger->ermLocalVars.getYvar(initV);
-							ret.type = IexpValStr::INTVAR;
-						}
+							ret = IexpValStr(&curTrigger->ermLocalVars.getYvar(initV));
 						else
 							initV = curTrigger->ermLocalVars.getYvar(initV);
 					}
@@ -982,17 +931,11 @@ IexpValStr ERMInterpreter::getVar(std::string toFollow, boost::optional<int> ini
 				{
 					//these C-style casts are here just to shut up compiler errors
 					if(initV > 0 )
-					{
-						ret.val.stringvar = &ermGlobalEnv->getZVar(initV);
-						ret.type = IexpValStr::STRINGVAR;
-					}
+						ret = IexpValStr(&ermGlobalEnv->getZVar(initV));
 					else if(initV < 0)
 					{
 						if(curFunc)
-						{
-							ret.val.stringvar = &curFunc->getString(initV);
-							ret.type = IexpValStr::STRINGVAR;
-						}
+							ret = IexpValStr(&curFunc->getString(initV));
 						else
 							throw EIexpProblem("Function local string variables cannot be used outside functions!");
 					}
@@ -1044,12 +987,7 @@ struct LVL2IexpDisemboweler : boost::static_visitor<IexpValStr>
 	}
 	IexpValStr 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);
-		
-		return processNotMacro(it->second);
+		return env->getIexp(val);
 	}
 };
 
@@ -1065,9 +1003,7 @@ struct LVL1IexpDisemboweler : boost::static_visitor<IexpValStr>
 	{
 		if(dir == IexpDisemboweler::GET)
 		{
-			IexpValStr ret;
-			ret.val.val = constant;
-			ret.type = IexpValStr::INT;
+			IexpValStr ret = IexpValStr(constant);
 		}
 		else
 		{
@@ -1085,6 +1021,26 @@ IexpValStr ERMInterpreter::getIexp( const ERM::TIexp & iexp ) const
 	return boost::apply_visitor(LVL1IexpDisemboweler(const_cast<ERMInterpreter*>(this), IexpDisemboweler::GET), iexp);
 }
 
+IexpValStr ERMInterpreter::getIexp( const ERM::TMacroUsage & macro ) const
+{
+	std::map<std::string, ERM::TVarExpNotMacro>::const_iterator it =
+		ermGlobalEnv->macroBindings.find(macro.macro);
+	if(it == ermGlobalEnv->macroBindings.end())
+		throw EUsageOfUndefinedMacro(macro.macro);
+
+	return getVar(it->second.varsym, it->second.val);
+}
+
+IexpValStr ERMInterpreter::getIexp( const ERM::TIdentifierInternal & tid ) const
+{
+	if(tid.which() == 0)
+	{
+		IexpValStr ievs = getIexp(boost::get<ERM::TIexp>(tid));
+	}
+	else
+		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 )
 {
 	TtriggerListType & triggerList = pre ? triggers : postTriggers;
@@ -1167,32 +1123,20 @@ struct ConditionDisemboweler : boost::static_visitor<bool>
 			switch (rhs.type)
 			{
 			case IexpValStr::FLOATVAR:
-				return compareExp(*lhs.val.flvar, *rhs.val.flvar, cmp.compSign);
+				return compareExp(lhs.getFloat(), rhs.getFloat(), cmp.compSign);
 				break;
 			default:
 				throw EScriptExecError("Incompatible types for comparison");
 			}
 			break;
 		case IexpValStr::INT:
-			switch (rhs.type)
-			{
-			case IexpValStr::INT:
-				return compareExp(lhs.val.val, rhs.val.val, cmp.compSign);
-				break;
-			case IexpValStr::INTVAR:
-				return compareExp(lhs.val.val, *rhs.val.integervar, cmp.compSign);
-			default:
-				throw EScriptExecError("Incompatible types for comparison");
-			}
-			break;
 		case IexpValStr::INTVAR:
 			switch (rhs.type)
 			{
 			case IexpValStr::INT:
-				return compareExp(*lhs.val.integervar, rhs.val.val, cmp.compSign);
-				break;
 			case IexpValStr::INTVAR:
-				return compareExp(*lhs.val.integervar, *rhs.val.integervar, cmp.compSign);
+				return compareExp(lhs.getInt(), rhs.getInt(), cmp.compSign);
+				break;
 			default:
 				throw EScriptExecError("Incompatible types for comparison");
 			}
@@ -1201,7 +1145,7 @@ struct ConditionDisemboweler : boost::static_visitor<bool>
 			switch (rhs.type)
 			{
 			case IexpValStr::STRINGVAR:
-				return compareExp(*lhs.val.stringvar, *rhs.val.stringvar, cmp.compSign);
+				return compareExp(lhs.getString(), rhs.getString(), cmp.compSign);
 				break;
 			default:
 				throw EScriptExecError("Incompatible types for comparison");
@@ -1246,6 +1190,11 @@ bool ERMInterpreter::checkCondition( ERM::Tcondition cond )
 	return ret;
 }
 
+FunctionLocalVars * ERMInterpreter::getFuncVars( int funNum )
+{
+	return funcVars + funNum - 1;
+}
+
 const std::string ERMInterpreter::triggerSymbol = "trigger";
 const std::string ERMInterpreter::postTriggerSymbol = "postTrigger";
 const std::string ERMInterpreter::defunSymbol = "defun";
@@ -1267,11 +1216,12 @@ struct TriggerIdMatchHelper : boost::static_visitor<>
 		switch(val.type)
 		{
 		case IexpValStr::INT:
-			ret = val.val.val;
 		case IexpValStr::INTVAR:
-			ret = *val.val.integervar;
+			ret = val.getInt();
+			break;
 		default:
 			throw EScriptExecError("Incompatible i-exp type!");
+			break;
 		}
 	}
 	void operator()(TArithmeticOp const& arop) const
@@ -1477,3 +1427,105 @@ double & VERMInterpreter::FunctionLocalVars::getFloat( int num )
 
 	return floats[num-1];
 }
+
+void IexpValStr::setTo( const IexpValStr & second )
+{
+	switch(type)
+	{
+	case IexpValStr::FLOATVAR:
+		*val.flvar = second.getFloat();
+		break;
+	case IexpValStr::INT:
+		throw EScriptExecError("VR S: value not assignable!");
+		break;
+	case IexpValStr::INTVAR:
+		*val.integervar = second.getInt();
+		break;
+	case IexpValStr::STRINGVAR:
+		*val.stringvar = second.getString();
+		break;
+	default:
+		throw EScriptExecError("Wrong type of identifier iexp!");
+	}
+}
+
+void IexpValStr::setTo( int val )
+{
+	switch(type)
+	{
+	case INTVAR:
+		*this->val.integervar = val;
+		break;
+	default:
+		throw EIexpProblem("Incompatible type!");
+		break;
+	}
+}
+
+void IexpValStr::setTo( float val )
+{
+	switch(type)
+	{
+	case FLOATVAR:
+		*this->val.flvar = val;
+		break;
+	default:
+		throw EIexpProblem("Incompatible type!");
+		break;
+	}
+}
+
+void IexpValStr::setTo( const std::string & val )
+{
+	switch(type)
+	{
+	case STRINGVAR:
+		*this->val.stringvar = val;
+		break;
+	default:
+		throw EIexpProblem("Incompatible type!");
+		break;
+	}
+}
+
+int IexpValStr::getInt() const
+{
+	switch(type)
+	{
+	case IexpValStr::INT:
+		return val.val;
+		break;
+	case IexpValStr::INTVAR:
+		return *val.integervar;
+		break;
+	default:
+		throw EIexpProblem("Cannot get iexp as int!");
+		break;
+	}
+}
+
+float IexpValStr::getFloat() const
+{
+	switch(type)
+	{
+	case IexpValStr::FLOATVAR:
+		return *val.flvar;
+		break;
+	default:
+		throw EIexpProblem("Cannot get iexp as float!");
+		break;
+	}
+}
+
+std::string IexpValStr::getString() const
+{
+	switch(type)
+	{
+	case IexpValStr::STRINGVAR:
+		return *val.stringvar;
+		break;
+	default:
+		throw EScriptExecError("Cannot get iexp as string!");
+		break;
+	}
+}

+ 35 - 4
lib/ERMInterpreter.h

@@ -160,7 +160,7 @@ namespace VERMInterpreter
 		ERMEnvironment();
 		static const int NUM_QUICKS = 't' - 'f' + 1; //it should be 15
 		int & getQuickVar(const char letter);
-		int & getStandardVar(int num);
+		int & getStandardVar(int num); //get v-variable
 		std::string & getZVar(int num);
 		bool & getFlag(int num);
 
@@ -304,6 +304,7 @@ struct TriggerIdentifierMatch
 
 struct IexpValStr
 {
+private:
 	union
 	{
 		int val;
@@ -311,7 +312,34 @@ struct IexpValStr
 		double * flvar;
 		std::string * stringvar;
 	} val;
+public:
 	enum {WRONGVAL, INT, INTVAR, FLOATVAR, STRINGVAR} type;
+	void setTo(const IexpValStr & second);
+	void setTo(int val);
+	void setTo(float val);
+	void setTo(const std::string & val);
+	int getInt() const;
+	float getFloat() const;
+	std::string getString() const;
+
+	IexpValStr() : type(WRONGVAL)
+	{}
+	IexpValStr(int _val) : type(INT)
+	{
+		val.val = _val;
+	}
+	IexpValStr(int* _val) : type(INTVAR)
+	{
+		val.integervar = _val;
+	}
+	IexpValStr(double * _val) : type(FLOATVAR)
+	{
+		val.flvar = _val;
+	}
+	IexpValStr(std::string * _val) : type(STRINGVAR)
+	{
+		val.stringvar = _val;
+	}
 };
 
 class ERMInterpreter
@@ -337,10 +365,13 @@ class ERMInterpreter
 	TtriggerListType triggers, postTriggers;
 	VERMInterpreter::Trigger * curTrigger;
 	VERMInterpreter::FunctionLocalVars * curFunc;
+	static const int TRIG_FUNC_NUM = 30000;
+	VERMInterpreter::FunctionLocalVars funcVars[TRIG_FUNC_NUM];
+	VERMInterpreter::FunctionLocalVars * getFuncVars(int funNum);
 
-
-	template<typename T> void setIexp(const ERM::TIexp & iexp, const T & val, VERMInterpreter::Trigger * trig = NULL);
 	IexpValStr getIexp(const ERM::TIexp & iexp) const;
+	IexpValStr getIexp(const ERM::TMacroUsage & macro) const;
+	IexpValStr getIexp(const ERM::TIdentifierInternal & tid) const;
 
 	static const std::string triggerSymbol, postTriggerSymbol, defunSymbol;
 
@@ -349,7 +380,7 @@ class ERMInterpreter
 	static bool isCMDATrigger(const ERM::Tcommand & cmd);
 	static bool isATrigger(const ERM::TLine & line);
 	static ERM::EVOtions getExpType(const ERM::TVOption & opt);
-	IexpValStr getVar(std::string toFollow, boost::optional<int> initVal);
+	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
 	void init(); //sets up environment etc.