1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-05-13 22:06:58 +02:00

* partially done DO receiver

This commit is contained in:
mateuszb 2011-05-06 19:32:04 +00:00
parent 98577e402f
commit 2d36cae2ca
2 changed files with 213 additions and 130 deletions

View File

@ -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;
}
}

View File

@ -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.