1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-05-17 22:22:59 +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 void VR_SPerformer::operator()(ERM::TIexp const& trig) const
{ {
IexpValStr sv = owner.interp->getIexp(trig); owner.identifier.setTo(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!");
}
} }
void VR_SPerformer::operator()(TVarConcatString const& cmp) const void VR_SPerformer::operator()(TVarConcatString const& cmp) const
@ -711,10 +667,7 @@ struct ERMExpDispatch : boost::static_visitor<>
ERM::Tidentifier ident = trig.identifier.get(); ERM::Tidentifier ident = trig.identifier.get();
if(ident.size() == 1) if(ident.size() == 1)
{ {
ERM::TIdentifierInternal idint = ident[0]; IexpValStr ievs = owner->getIexp(ident[0]);
if(idint.which() == 0)
{
IexpValStr ievs = owner->getIexp(boost::get<ERM::TIexp>(idint));
//see body //see body
if(trig.body.is_initialized()) if(trig.body.is_initialized())
@ -726,15 +679,35 @@ struct ERMExpDispatch : boost::static_visitor<>
} }
} }
} }
else
throw EScriptExecError("Identifier of a VR receiver must be a valid i-expression!");
}
else else
throw EScriptExecError("VR receiver must be used with exactly one identifier item!"); throw EScriptExecError("VR receiver must be used with exactly one identifier item!");
} }
else else
throw EScriptExecError("VR receiver must be used with an identifier!"); 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 else
{ {
//unsupported or invalid trigger //unsupported or invalid trigger
@ -797,7 +770,7 @@ void ERMInterpreter::init()
//TODO: reset? //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; IexpValStr ret;
ret.type = IexpValStr::WRONGVAL; ret.type = IexpValStr::WRONGVAL;
@ -819,10 +792,7 @@ IexpValStr ERMInterpreter::getVar(std::string toFollow, boost::optional<int> ini
if(toFollow.size() == 0) if(toFollow.size() == 0)
{ {
if(hasInit) if(hasInit)
{ ret = IexpValStr(initV);
ret.val.val = initV;
ret.type = IexpValStr::INT;
}
else else
throw EIexpProblem("No input to getVar!"); 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(initV > 0 && initV <= FunctionLocalVars::NUM_FLOATINGS)
{ {
if(curFunc) if(curFunc)
{ ret = IexpValStr(&curFunc->getFloat(initV));
ret.val.flvar = &curFunc->getFloat(initV);
ret.type = IexpValStr::FLOATVAR;
}
else else
throw EIexpProblem("Function context not available!"); throw EIexpProblem("Function context not available!");
} }
else if(initV < 0 && initV >= -TriggerLocalVars::EVAR_NUM) else if(initV < 0 && initV >= -TriggerLocalVars::EVAR_NUM)
{ {
if(curTrigger) if(curTrigger)
{ ret = IexpValStr(&curTrigger->ermLocalVars.getEvar(initV));
ret.val.flvar = &curTrigger->ermLocalVars.getEvar(initV);
ret.type = IexpValStr::FLOATVAR;
}
else else
throw EIexpProblem("No trigger context available!"); 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') else if(cr >= 'f' && cr <= 't')
{ {
if(retIt) if(retIt)
{ ret = IexpValStr(&ermGlobalEnv->getQuickVar(cr));
ret.val.integervar = &ermGlobalEnv->getQuickVar(cr);
ret.type = IexpValStr::INTVAR;
}
else else
{ {
if(hasInit) if(hasInit)
@ -901,10 +862,7 @@ IexpValStr ERMInterpreter::getVar(std::string toFollow, boost::optional<int> ini
if(hasInit) if(hasInit)
{ {
if(retIt) if(retIt)
{ ret = IexpValStr(&ermGlobalEnv->getStandardVar(initV));
ret.val.integervar = &ermGlobalEnv->getStandardVar(initV);
ret.type = IexpValStr::INTVAR;
}
else else
initV = ermGlobalEnv->getStandardVar(initV); initV = ermGlobalEnv->getStandardVar(initV);
} }
@ -922,10 +880,7 @@ IexpValStr ERMInterpreter::getVar(std::string toFollow, boost::optional<int> ini
if(curFunc) if(curFunc)
{ {
if(retIt) if(retIt)
{ ret = IexpValStr(&curFunc->getParam(initV));
ret.val.integervar = &curFunc->getParam(initV);
ret.type = IexpValStr::INTVAR;
}
else else
initV = curFunc->getParam(initV); initV = curFunc->getParam(initV);
} }
@ -943,10 +898,7 @@ IexpValStr ERMInterpreter::getVar(std::string toFollow, boost::optional<int> ini
if(curFunc) if(curFunc)
{ {
if(retIt) if(retIt)
{ ret = IexpValStr(&curFunc->getLocal(initV));
ret.val.integervar = &curFunc->getLocal(initV);
ret.type = IexpValStr::INTVAR;
}
else else
initV = curFunc->getLocal(initV); initV = curFunc->getLocal(initV);
} }
@ -958,10 +910,7 @@ IexpValStr ERMInterpreter::getVar(std::string toFollow, boost::optional<int> ini
if(curTrigger) if(curTrigger)
{ {
if(retIt) if(retIt)
{ ret = IexpValStr(&curTrigger->ermLocalVars.getYvar(initV));
ret.val.integervar = &curTrigger->ermLocalVars.getYvar(initV);
ret.type = IexpValStr::INTVAR;
}
else else
initV = curTrigger->ermLocalVars.getYvar(initV); 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 //these C-style casts are here just to shut up compiler errors
if(initV > 0 ) if(initV > 0 )
{ ret = IexpValStr(&ermGlobalEnv->getZVar(initV));
ret.val.stringvar = &ermGlobalEnv->getZVar(initV);
ret.type = IexpValStr::STRINGVAR;
}
else if(initV < 0) else if(initV < 0)
{ {
if(curFunc) if(curFunc)
{ ret = IexpValStr(&curFunc->getString(initV));
ret.val.stringvar = &curFunc->getString(initV);
ret.type = IexpValStr::STRINGVAR;
}
else else
throw EIexpProblem("Function local string variables cannot be used outside functions!"); 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 IexpValStr operator()(TMacroUsage const& val) const
{ {
std::map<std::string, ERM::TVarExpNotMacro>::const_iterator it = return env->getIexp(val);
env->ermGlobalEnv->macroBindings.find(val .macro);
if(it == env->ermGlobalEnv->macroBindings.end())
throw EUsageOfUndefinedMacro(val.macro);
return processNotMacro(it->second);
} }
}; };
@ -1065,9 +1003,7 @@ struct LVL1IexpDisemboweler : boost::static_visitor<IexpValStr>
{ {
if(dir == IexpDisemboweler::GET) if(dir == IexpDisemboweler::GET)
{ {
IexpValStr ret; IexpValStr ret = IexpValStr(constant);
ret.val.val = constant;
ret.type = IexpValStr::INT;
} }
else 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); 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 ) void ERMInterpreter::executeTriggerType( VERMInterpreter::TriggerType tt, bool pre, const std::map< int, std::vector<int> > & identifier )
{ {
TtriggerListType & triggerList = pre ? triggers : postTriggers; TtriggerListType & triggerList = pre ? triggers : postTriggers;
@ -1167,32 +1123,20 @@ struct ConditionDisemboweler : boost::static_visitor<bool>
switch (rhs.type) switch (rhs.type)
{ {
case IexpValStr::FLOATVAR: case IexpValStr::FLOATVAR:
return compareExp(*lhs.val.flvar, *rhs.val.flvar, cmp.compSign); return compareExp(lhs.getFloat(), rhs.getFloat(), cmp.compSign);
break; break;
default: default:
throw EScriptExecError("Incompatible types for comparison"); throw EScriptExecError("Incompatible types for comparison");
} }
break; break;
case IexpValStr::INT: 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: case IexpValStr::INTVAR:
switch (rhs.type) switch (rhs.type)
{ {
case IexpValStr::INT: case IexpValStr::INT:
return compareExp(*lhs.val.integervar, rhs.val.val, cmp.compSign);
break;
case IexpValStr::INTVAR: case IexpValStr::INTVAR:
return compareExp(*lhs.val.integervar, *rhs.val.integervar, cmp.compSign); return compareExp(lhs.getInt(), rhs.getInt(), cmp.compSign);
break;
default: default:
throw EScriptExecError("Incompatible types for comparison"); throw EScriptExecError("Incompatible types for comparison");
} }
@ -1201,7 +1145,7 @@ struct ConditionDisemboweler : boost::static_visitor<bool>
switch (rhs.type) switch (rhs.type)
{ {
case IexpValStr::STRINGVAR: case IexpValStr::STRINGVAR:
return compareExp(*lhs.val.stringvar, *rhs.val.stringvar, cmp.compSign); return compareExp(lhs.getString(), rhs.getString(), cmp.compSign);
break; break;
default: default:
throw EScriptExecError("Incompatible types for comparison"); throw EScriptExecError("Incompatible types for comparison");
@ -1246,6 +1190,11 @@ bool ERMInterpreter::checkCondition( ERM::Tcondition cond )
return ret; return ret;
} }
FunctionLocalVars * ERMInterpreter::getFuncVars( int funNum )
{
return funcVars + funNum - 1;
}
const std::string ERMInterpreter::triggerSymbol = "trigger"; const std::string ERMInterpreter::triggerSymbol = "trigger";
const std::string ERMInterpreter::postTriggerSymbol = "postTrigger"; const std::string ERMInterpreter::postTriggerSymbol = "postTrigger";
const std::string ERMInterpreter::defunSymbol = "defun"; const std::string ERMInterpreter::defunSymbol = "defun";
@ -1267,11 +1216,12 @@ struct TriggerIdMatchHelper : boost::static_visitor<>
switch(val.type) switch(val.type)
{ {
case IexpValStr::INT: case IexpValStr::INT:
ret = val.val.val;
case IexpValStr::INTVAR: case IexpValStr::INTVAR:
ret = *val.val.integervar; ret = val.getInt();
break;
default: default:
throw EScriptExecError("Incompatible i-exp type!"); throw EScriptExecError("Incompatible i-exp type!");
break;
} }
} }
void operator()(TArithmeticOp const& arop) const void operator()(TArithmeticOp const& arop) const
@ -1477,3 +1427,105 @@ double & VERMInterpreter::FunctionLocalVars::getFloat( int num )
return floats[num-1]; 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(); ERMEnvironment();
static const int NUM_QUICKS = 't' - 'f' + 1; //it should be 15 static const int NUM_QUICKS = 't' - 'f' + 1; //it should be 15
int & getQuickVar(const char letter); int & getQuickVar(const char letter);
int & getStandardVar(int num); int & getStandardVar(int num); //get v-variable
std::string & getZVar(int num); std::string & getZVar(int num);
bool & getFlag(int num); bool & getFlag(int num);
@ -304,6 +304,7 @@ struct TriggerIdentifierMatch
struct IexpValStr struct IexpValStr
{ {
private:
union union
{ {
int val; int val;
@ -311,7 +312,34 @@ struct IexpValStr
double * flvar; double * flvar;
std::string * stringvar; std::string * stringvar;
} val; } val;
public:
enum {WRONGVAL, INT, INTVAR, FLOATVAR, STRINGVAR} type; 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 class ERMInterpreter
@ -337,10 +365,13 @@ class ERMInterpreter
TtriggerListType triggers, postTriggers; TtriggerListType triggers, postTriggers;
VERMInterpreter::Trigger * curTrigger; VERMInterpreter::Trigger * curTrigger;
VERMInterpreter::FunctionLocalVars * curFunc; 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::TIexp & iexp) const;
IexpValStr getIexp(const ERM::TMacroUsage & macro) const;
IexpValStr getIexp(const ERM::TIdentifierInternal & tid) const;
static const std::string triggerSymbol, postTriggerSymbol, defunSymbol; static const std::string triggerSymbol, postTriggerSymbol, defunSymbol;
@ -349,7 +380,7 @@ class ERMInterpreter
static bool isCMDATrigger(const ERM::Tcommand & cmd); static bool isCMDATrigger(const ERM::Tcommand & cmd);
static bool isATrigger(const ERM::TLine & line); static bool isATrigger(const ERM::TLine & line);
static ERM::EVOtions getExpType(const ERM::TVOption & opt); 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: public:
void executeTriggerType(VERMInterpreter::TriggerType tt, bool pre, const std::map< int, std::vector<int> > & identifier); //use this to run triggers 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. void init(); //sets up environment etc.