1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-22 22:13:35 +02:00

Make ERM compile again.

This is not a proper clean up. It does not bring the code up to the
current state of the rest of the codebase. However, the module now
compiles again.
This commit is contained in:
Andreas Grois 2023-09-25 21:26:23 +02:00
parent b89fa254fc
commit 6225d8585d
3 changed files with 151 additions and 142 deletions

View File

@ -163,7 +163,7 @@ namespace ERMConverter
Variable operator()(const TVarExpNotMacro & val) const
{
if(val.val.has_value())
return Variable(val.varsym, val.val.get());
return Variable(val.varsym, *val.val);
else
return Variable(val.varsym, 0);
}
@ -392,7 +392,7 @@ namespace ERMConverter
if(trig.params.has_value())
{
for(auto & p : trig.params.get())
for(auto & p : *trig.params)
optionParams.push_back(std::visit(BodyOption(), p));
}
@ -572,7 +572,7 @@ namespace ERMConverter
{
if(option.params.has_value())
{
for(auto & p : option.params.get())
for(auto & p : *option.params)
{
std::string macroName = std::visit(MC_S(), p);
@ -739,7 +739,7 @@ namespace ERMConverter
if(trig.params.has_value())
{
for(auto & p : trig.params.get())
for(auto & p : *trig.params)
optionParams.push_back(std::visit(BodyOption(), p));
}
@ -759,10 +759,10 @@ namespace ERMConverter
break;
case 'H': //checking if string is empty
{
if(!trig.params.has_value() || trig.params.get().size() != 1)
if(!trig.params.has_value() || trig.params->size() != 1)
throw EScriptExecError("VR:H option takes exactly 1 parameter!");
std::string opt = std::visit(VR_H(), trig.params.get()[0]);
std::string opt = std::visit(VR_H(), (*trig.params)[0]);
boost::format fmt("ERM.VR(%s):H(%s)");
fmt % v.str() % opt;
putLine(fmt.str());
@ -770,10 +770,10 @@ namespace ERMConverter
break;
case 'U':
{
if(!trig.params.has_value() || trig.params.get().size() != 1)
if(!trig.params.has_value() || trig.params->size() != 1)
throw EScriptExecError("VR:H/U need 1 parameter!");
std::string opt = std::visit(VR_S(), trig.params.get()[0]);
std::string opt = std::visit(VR_S(), (*trig.params)[0]);
boost::format fmt("ERM.VR(%s):%c(%s)");
fmt % v.str() % (trig.optionCode) % opt;
putLine(fmt.str());
@ -781,10 +781,10 @@ namespace ERMConverter
break;
case 'M': //string operations
{
if(!trig.params.has_value() || trig.params.get().size() < 2)
if(!trig.params.has_value() || trig.params->size() < 2)
throw EScriptExecError("VR:M needs at least 2 parameters!");
std::string opt = std::visit(VR_X(), trig.params.get()[0]);
std::string opt = std::visit(VR_X(), (*trig.params)[0]);
int paramIndex = 1;
if(opt == "3")
@ -795,16 +795,16 @@ namespace ERMConverter
}
else
{
auto target = std::visit(VR_X(), trig.params.get()[paramIndex++]);
auto target = std::visit(VR_X(), (*trig.params)[paramIndex++]);
boost::format fmt("%s = ERM.VR(%s):M%s(");
fmt % target % v.str() % opt;
put(fmt.str());
}
for(int i = paramIndex; i < trig.params.get().size(); i++)
for(int i = paramIndex; i < trig.params->size(); i++)
{
opt = std::visit(VR_X(), trig.params.get()[i]);
opt = std::visit(VR_X(), (*trig.params)[i]);
if(i > paramIndex) put(",");
put(opt);
}
@ -814,10 +814,10 @@ namespace ERMConverter
break;
case 'X': //bit xor
{
if(!trig.params.has_value() || trig.params.get().size() != 1)
if(!trig.params.has_value() || trig.params->size() != 1)
throw EScriptExecError("VR:X option takes exactly 1 parameter!");
std::string opt = std::visit(VR_X(), trig.params.get()[0]);
std::string opt = std::visit(VR_X(), (*trig.params)[0]);
boost::format fmt("%s = bit.bxor(%s, %s)");
fmt % v.str() % v.str() % opt;putLine(fmt.str());
@ -831,10 +831,10 @@ namespace ERMConverter
break;
case 'S': //setting variable
{
if(!trig.params.has_value() || trig.params.get().size() != 1)
if(!trig.params.has_value() || trig.params->size() != 1)
throw EScriptExecError("VR:S option takes exactly 1 parameter!");
std::string opt = std::visit(VR_S(), trig.params.get()[0]);
std::string opt = std::visit(VR_S(), (*trig.params)[0]);
put(v.str());
put(" = ");
put(opt);
@ -849,10 +849,10 @@ namespace ERMConverter
break;
case 'V': //convert string to value
{
if(!trig.params.has_value() || trig.params.get().size() != 1)
if(!trig.params.has_value() || trig.params->size() != 1)
throw EScriptExecError("VR:V option takes exactly 1 parameter!");
std::string opt = std::visit(VR_X(), trig.params.get()[0]);
std::string opt = std::visit(VR_X(), (*trig.params)[0]);
boost::format fmt("%s = tostring(%s)");
fmt % v.str() % opt;
putLine(fmt.str());
@ -877,7 +877,7 @@ namespace ERMConverter
{
if(body.has_value())
{
const ERM::Tbody & bo = body.get();
const ERM::Tbody & bo = *body;
for(int g=0; g<bo.size(); ++g)
{
std::visit(visitor, bo[g]);
@ -975,7 +975,7 @@ namespace ERMConverter
if(body.has_value())
{
const ERM::Tbody & bo = body.get();
const ERM::Tbody & bo = *body;
if(bo.size() == 1)
{
boost::format fmt("ERM.%s(%s)");
@ -983,7 +983,7 @@ namespace ERMConverter
fmt % params;
GenericReceiver gr(out, fmt.str(), (name == "DO"));
bo[0].apply_visitor(gr);
std::visit(gr,bo[0]);
}
else
{
@ -1044,7 +1044,7 @@ namespace ERMConverter
break;
}
convertConditionInner(cond.rhs.get().get(), op);
convertConditionInner(cond.rhs->get(), op);
}
}
@ -1067,7 +1067,7 @@ namespace ERMConverter
break;
}
convertConditionInner(cond.rhs.get().get(), cond.ctype);
convertConditionInner(cond.rhs->get(), cond.ctype);
}
putLine(" then ");
@ -1081,7 +1081,7 @@ namespace ERMConverter
if(name=="if")
{
if(condition.has_value())
convertCondition(condition.get());
convertCondition(*condition);
else
putLine("if true then");
}
@ -1097,7 +1097,7 @@ namespace ERMConverter
{
if(condition.has_value())
{
convertCondition(condition.get());
convertCondition(*condition);
convert(name, identifier, body);
putLine("end");
}
@ -1181,7 +1181,7 @@ namespace ERMConverter
{
(*out) << "{}";
}
void operator()(const VNode & opt) const;
void operator()(const boost::recursive_wrapper<VNode> & opt) const;
void operator()(const VSymbol & opt) const
{
@ -1192,7 +1192,7 @@ namespace ERMConverter
TLiteralEval tmp;
(*out) << std::visit(tmp, opt);
}
void operator()(ERM const ::Tcommand & opt) const
void operator()(const ERM::Tcommand & opt) const
{
//this is how FP works, evaluation == producing side effects
//TODO: can we evaluate to smth more useful?
@ -1202,9 +1202,9 @@ namespace ERMConverter
}
};
void VOptionEval::operator()(const VNode & opt) const
void VOptionEval::operator()(const boost::recursive_wrapper<VNode> & opt) const
{
VNode tmpn(opt);
VNode tmpn(opt.get());
(*out) << "{";
@ -1375,35 +1375,35 @@ struct ScriptScanner
}
void operator()(const TERMline & cmd) const
{
if(cmd.which() == 0) //TCommand
if(std::holds_alternative<Tcommand>(cmd)) //TCommand
{
Tcommand tcmd = std::get<Tcommand>(cmd);
switch (tcmd.cmd.which())
struct Visitor
{
case 0: //trigger
void operator()(const ERM::Ttrigger& t) const
{
Trigger trig;
trig.line = lp;
interpreter->triggers[ TriggerType(std::get<ERM::Ttrigger>(tcmd.cmd).name) ].push_back(trig);
trig.line = l;
i->triggers[ TriggerType(t.name) ].push_back(trig);
}
break;
case 1: //instruction
void operator()(const ERM::Tinstruction&) const
{
interpreter->instructions.push_back(lp);
i->instructions.push_back(l);
}
break;
case 3: //post trigger
void operator()(const ERM::Treceiver&) const {}
void operator()(const ERM::TPostTrigger& pt) const
{
Trigger trig;
trig.line = lp;
interpreter->postTriggers[ TriggerType(std::get<ERM::TPostTrigger>(tcmd.cmd).name) ].push_back(trig);
trig.line = l;
i->postTriggers[ TriggerType(pt.name) ].push_back(trig);
}
break;
default:
break;
}
}
const decltype(interpreter)& i;
const LinePointer& l;
};
Visitor v{interpreter, lp};
std::visit(v, tcmd.cmd);
}
}
};
@ -1421,68 +1421,85 @@ ERMInterpreter::~ERMInterpreter()
bool ERMInterpreter::isATrigger( const ERM::TLine & line )
{
switch(line.which())
if(std::holds_alternative<ERM::TVExp>(line))
{
case 0: //v-exp
{
TVExp vexp = std::get<TVExp>(line);
if(vexp.children.empty())
return false;
TVExp vexp = std::get<TVExp>(line);
if(vexp.children.empty())
return false;
switch (getExpType(vexp.children[0]))
{
case SYMBOL:
return false;
break;
case TCMD:
return isCMDATrigger( std::get<ERM::Tcommand>(vexp.children[0]) );
break;
default:
return false;
break;
}
}
break;
case 1: //erm
switch (getExpType(vexp.children[0]))
{
TERMline ermline = std::get<TERMline>(line);
switch(ermline.which())
{
case 0: //tcmd
return isCMDATrigger( std::get<ERM::Tcommand>(ermline) );
break;
default:
return false;
break;
}
case SYMBOL:
return false;
break;
case TCMD:
return isCMDATrigger( std::get<ERM::Tcommand>(vexp.children[0]) );
break;
default:
return false;
break;
}
break;
default:
assert(0); //it should never happen
break;
}
assert(0);
else if(std::holds_alternative<TERMline>(line))
{
TERMline ermline = std::get<TERMline>(line);
return std::holds_alternative<ERM::Tcommand>(ermline) && isCMDATrigger( std::get<ERM::Tcommand>(ermline) );
}
else
{
assert(0);
}
return false;
}
ERM::EVOtions ERMInterpreter::getExpType(const ERM::TVOption & opt)
{
//MAINTENANCE: keep it correct!
return static_cast<ERM::EVOtions>(opt.which());
struct Visitor
{
ERM::EVOtions operator()(const boost::recursive_wrapper<ERM::TVExp>&) const
{
return ERM::EVOtions::VEXP;
}
ERM::EVOtions operator()(const ERM::TSymbol&) const
{
return ERM::EVOtions::SYMBOL;
}
ERM::EVOtions operator()(char) const
{
return ERM::EVOtions::CHAR;
}
ERM::EVOtions operator()(double) const
{
return ERM::EVOtions::DOUBLE;
}
ERM::EVOtions operator()(int) const
{
return ERM::EVOtions::INT;
}
ERM::EVOtions operator()(const ERM::Tcommand&) const
{
return ERM::EVOtions::TCMD;
}
ERM::EVOtions operator()(const ERM::TStringConstant&) const
{
return ERM::EVOtions::STRINGC;
}
};
const Visitor v;
return std::visit(v, opt);
}
bool ERMInterpreter::isCMDATrigger(const ERM::Tcommand & cmd)
{
switch (cmd.cmd.which())
struct Visitor
{
case 0: //trigger
case 3: //post trigger
return true;
break;
default:
return false;
break;
}
bool operator()(const ERM::Ttrigger&) const { return true; }
bool operator()(const ERM::TPostTrigger&) const { return true; }
bool operator()(const ERM::Tinstruction&) const { return false; }
bool operator()(const ERM::Treceiver&) const { return false; }
};
const Visitor v;
return std::visit(v, cmd.cmd);
}
ERM::TLine & ERMInterpreter::retrieveLine(const LinePointer & linePtr)
@ -1492,17 +1509,17 @@ ERM::TLine & ERMInterpreter::retrieveLine(const LinePointer & linePtr)
ERM::TTriggerBase & ERMInterpreter::retrieveTrigger(ERM::TLine & line)
{
if(line.which() == 1)
if(std::holds_alternative<ERM::TERMline>(line))
{
ERM::TERMline &tl = std::get<ERM::TERMline>(line);
if(tl.which() == 0)
if(std::holds_alternative<ERM::Tcommand>(tl))
{
ERM::Tcommand &tcm = std::get<ERM::Tcommand>(tl);
if(tcm.cmd.which() == 0)
if(std::holds_alternative<ERM::Ttrigger>(tcm.cmd))
{
return std::get<ERM::Ttrigger>(tcm.cmd);
}
else if(tcm.cmd.which() == 3)
else if(std::holds_alternative<ERM::TPostTrigger>(tcm.cmd))
{
return std::get<ERM::TPostTrigger>(tcm.cmd);
}
@ -1569,6 +1586,40 @@ namespace VERMInterpreter
{
VOption convertToVOption(const ERM::TVOption & tvo)
{
struct OptionConverterVisitor
{
VOption operator()(const boost::recursive_wrapper<ERM::TVExp>& cmd) const
{
return boost::recursive_wrapper<VNode>(VNode(cmd.get()));
}
VOption operator()(const ERM::TSymbol & cmd) const
{
if(cmd.symModifier.empty())
return VSymbol(cmd.sym);
else
return boost::recursive_wrapper<VNode>(VNode(cmd));
}
VOption operator()(const char & cmd) const
{
return TLiteral(cmd);
}
VOption operator()(const double & cmd) const
{
return TLiteral(cmd);
}
VOption operator()(const int & cmd) const
{
return TLiteral(cmd);
}
VOption operator()(const ERM::Tcommand & cmd) const
{
return cmd;
}
VOption operator()(const ERM::TStringConstant & cmd) const
{
return TLiteral(cmd.str);
}
};
return std::visit(OptionConverterVisitor(), tvo);
}
@ -1706,38 +1757,6 @@ namespace VERMInterpreter
return ret;
}
VOption OptionConverterVisitor::operator()(ERM const ::TVExp & cmd) const
{
return VNode(cmd);
}
VOption OptionConverterVisitor::operator()(ERM const ::TSymbol & cmd) const
{
if(cmd.symModifier.empty())
return VSymbol(cmd.sym);
else
return VNode(cmd);
}
VOption OptionConverterVisitor::operator()(const char & cmd) const
{
return TLiteral(cmd);
}
VOption OptionConverterVisitor::operator()(const double & cmd) const
{
return TLiteral(cmd);
}
VOption OptionConverterVisitor::operator()(const int & cmd) const
{
return TLiteral(cmd);
}
VOption OptionConverterVisitor::operator()(ERM const ::Tcommand & cmd) const
{
return cmd;
}
VOption OptionConverterVisitor::operator()(ERM const ::TStringConstant & cmd) const
{
return TLiteral(cmd.str);
}
VermTreeIterator VOptionList::cdr()
{
VermTreeIterator ret(*this);

View File

@ -134,7 +134,7 @@ namespace VERMInterpreter
"TH", "TM"
};
for(int i=0; i<ARRAY_COUNT(validTriggers); ++i)
for(int i=0; i<std::size(validTriggers); ++i)
{
if(validTriggers[i] == trig)
return static_cast<ETrigType>(i);
@ -278,17 +278,6 @@ namespace VERMInterpreter
VermTreeIterator cdr();
};
struct OptionConverterVisitor
{
VOption operator()(ERM const ::TVExp & cmd) const;
VOption operator()(ERM const ::TSymbol & cmd) const;
VOption operator()(const char & cmd) const;
VOption operator()(const double & cmd) const;
VOption operator()(const int & cmd) const;
VOption operator()(ERM const ::Tcommand & cmd) const;
VOption operator()(ERM const ::TStringConstant & cmd) const;
};
struct VNode
{
private:

View File

@ -10,6 +10,7 @@
#pragma once
#include <boost/spirit/home/support/unused.hpp>
#include <boost/variant/recursive_wrapper.hpp>
namespace spirit = boost::spirit;