diff --git a/lib/ERMInterpreter.cpp b/lib/ERMInterpreter.cpp index dee3d072f..e89c49783 100644 --- a/lib/ERMInterpreter.cpp +++ b/lib/ERMInterpreter.cpp @@ -4,6 +4,7 @@ #include #include #include +#include // 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(this)->identifier.setTo(identifier.getInt() & valr); + break; + case '|': + const_cast(this)->identifier.setTo(identifier.getInt() | valr); + break; + case 'X': + const_cast(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(this)->identifier += rhs; + break; + case '-': + const_cast(this)->identifier -= rhs; + break; + case '*': + const_cast(this)->identifier *= rhs; + break; + case ':': + const_cast(this)->identifier /= rhs; + break; + case '%': + const_cast(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 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 > & identifier ) +void ERMInterpreter::executeTriggerType( VERMInterpreter::TriggerType tt, bool pre, const TIDPattern & identifier ) { TtriggerListType & triggerList = pre ? triggers : postTriggers; diff --git a/lib/ERMInterpreter.h b/lib/ERMInterpreter.h index 2a575d09b..f4afe26bc 100644 --- a/lib/ERMInterpreter.h +++ b/lib/ERMInterpreter.h @@ -340,6 +340,129 @@ public: { val.stringvar = _val; } + +#define OPERATOR_DEFINITION_FULL(OPSIGN) \ + template \ + 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 \ + IexpValStr & operator OPSIGN ## = (const T & sec) \ + { \ + *this = *this OPSIGN sec; \ + return *this; \ + } + +#define OPERATOR_DEFINITION(OPSIGN) \ + template \ + 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 \ + IexpValStr & operator OPSIGN ## = (const T & sec) \ + { \ + *this = *this OPSIGN sec; \ + return *this; \ + } + +#define OPERATOR_DEFINITION_INTEGER(OPSIGN) \ + template \ + 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 \ + 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 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 initVal) const; public: - void executeTriggerType(VERMInterpreter::TriggerType tt, bool pre, const std::map< int, std::vector > & identifier); //use this to run triggers + typedef std::map< int, std::vector > TIDPattern; + void executeTriggerType(VERMInterpreter::TriggerType tt, bool pre, const TIDPattern & identifier); //use this to run triggers void init(); //sets up environment etc. void scanForScripts();