1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-04-21 12:06:49 +02:00

Merge pull request #2950 from soulsource/feature/make-erm-compile-again

Make ERM compile again.
This commit is contained in:
Ivan Savenko 2023-09-27 15:42:33 +03:00 committed by GitHub
commit 724eb7902e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 151 additions and 142 deletions

View File

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

View File

@ -134,7 +134,7 @@ namespace VERMInterpreter
"TH", "TM" "TH", "TM"
}; };
for(int i=0; i<ARRAY_COUNT(validTriggers); ++i) for(int i=0; i<std::size(validTriggers); ++i)
{ {
if(validTriggers[i] == trig) if(validTriggers[i] == trig)
return static_cast<ETrigType>(i); return static_cast<ETrigType>(i);
@ -278,17 +278,6 @@ namespace VERMInterpreter
VermTreeIterator cdr(); 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 struct VNode
{ {
private: private:

View File

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