Implement any_[not_]empty and list versions of switch_on and [not_]empty.

Useful for OptionPreprocessor.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84728 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Mikhail Glushenkov 2009-10-21 02:13:13 +00:00
parent c1ae8c9b8f
commit 4858a1d51e

View File

@ -146,6 +146,18 @@ void checkedIncrement(I& P, I E, S ErrorString) {
throw ErrorString; throw ErrorString;
} }
// apply is needed because C++'s syntax doesn't let us construct a function
// object and call it in the same statement.
template<typename F, typename T0>
void apply(F Fun, T0& Arg0) {
return Fun(Arg0);
}
template<typename F, typename T0, typename T1>
void apply(F Fun, T0& Arg0, T1& Arg1) {
return Fun(Arg0, Arg1);
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
/// Back-end specific code /// Back-end specific code
@ -157,6 +169,10 @@ namespace OptionType {
enum OptionType { Alias, Switch, Parameter, ParameterList, enum OptionType { Alias, Switch, Parameter, ParameterList,
Prefix, PrefixList}; Prefix, PrefixList};
bool IsAlias(OptionType t) {
return (t == Alias);
}
bool IsList (OptionType t) { bool IsList (OptionType t) {
return (t == ParameterList || t == PrefixList); return (t == ParameterList || t == PrefixList);
} }
@ -245,12 +261,12 @@ struct OptionDescription {
bool isReallyHidden() const; bool isReallyHidden() const;
void setReallyHidden(); void setReallyHidden();
bool isParameter() const
{ return OptionType::IsParameter(this->Type); }
bool isSwitch() const bool isSwitch() const
{ return OptionType::IsSwitch(this->Type); } { return OptionType::IsSwitch(this->Type); }
bool isParameter() const
{ return OptionType::IsParameter(this->Type); }
bool isList() const bool isList() const
{ return OptionType::IsList(this->Type); } { return OptionType::IsList(this->Type); }
@ -272,7 +288,7 @@ void OptionDescription::Merge (const OptionDescription& other)
} }
bool OptionDescription::isAlias() const { bool OptionDescription::isAlias() const {
return Type == OptionType::Alias; return OptionType::IsAlias(this->Type);
} }
bool OptionDescription::isMultiVal() const { bool OptionDescription::isMultiVal() const {
@ -365,9 +381,14 @@ class OptionDescriptions {
public: public:
/// FindOption - exception-throwing wrapper for find(). /// FindOption - exception-throwing wrapper for find().
const OptionDescription& FindOption(const std::string& OptName) const; const OptionDescription& FindOption(const std::string& OptName) const;
/// FindSwitch - wrapper for FindOption that throws in case the option is not
/// a switch. // Wrappers for FindOption that throw an exception in case the option has a
// wrong type.
const OptionDescription& FindSwitch(const std::string& OptName) const; const OptionDescription& FindSwitch(const std::string& OptName) const;
const OptionDescription& FindParameter(const std::string& OptName) const;
const OptionDescription& FindList(const std::string& OptName) const;
const OptionDescription&
FindListOrParameter(const std::string& OptName) const;
/// insertDescription - Insert new OptionDescription into /// insertDescription - Insert new OptionDescription into
/// OptionDescriptions list /// OptionDescriptions list
@ -380,8 +401,7 @@ public:
}; };
const OptionDescription& const OptionDescription&
OptionDescriptions::FindOption(const std::string& OptName) const OptionDescriptions::FindOption(const std::string& OptName) const {
{
const_iterator I = Descriptions.find(OptName); const_iterator I = Descriptions.find(OptName);
if (I != Descriptions.end()) if (I != Descriptions.end())
return I->second; return I->second;
@ -390,16 +410,39 @@ OptionDescriptions::FindOption(const std::string& OptName) const
} }
const OptionDescription& const OptionDescription&
OptionDescriptions::FindSwitch(const std::string& OptName) const OptionDescriptions::FindSwitch(const std::string& OptName) const {
{
const OptionDescription& OptDesc = this->FindOption(OptName); const OptionDescription& OptDesc = this->FindOption(OptName);
if (!OptDesc.isSwitch()) if (!OptDesc.isSwitch())
throw OptName + ": incorrect option type - should be a switch!"; throw OptName + ": incorrect option type - should be a switch!";
return OptDesc; return OptDesc;
} }
void OptionDescriptions::InsertDescription (const OptionDescription& o) const OptionDescription&
{ OptionDescriptions::FindList(const std::string& OptName) const {
const OptionDescription& OptDesc = this->FindOption(OptName);
if (!OptDesc.isList())
throw OptName + ": incorrect option type - should be a list!";
return OptDesc;
}
const OptionDescription&
OptionDescriptions::FindParameter(const std::string& OptName) const {
const OptionDescription& OptDesc = this->FindOption(OptName);
if (!OptDesc.isParameter())
throw OptName + ": incorrect option type - should be a parameter!";
return OptDesc;
}
const OptionDescription&
OptionDescriptions::FindListOrParameter(const std::string& OptName) const {
const OptionDescription& OptDesc = this->FindOption(OptName);
if (!OptDesc.isList() && !OptDesc.isParameter())
throw OptName
+ ": incorrect option type - should be a list or parameter!";
return OptDesc;
}
void OptionDescriptions::InsertDescription (const OptionDescription& o) {
container_type::iterator I = Descriptions.find(o.Name); container_type::iterator I = Descriptions.find(o.Name);
if (I != Descriptions.end()) { if (I != Descriptions.end()) {
OptionDescription& D = I->second; OptionDescription& D = I->second;
@ -1067,6 +1110,93 @@ bool EmitCaseTest0Args(const std::string& TestName, raw_ostream& O) {
return false; return false;
} }
/// EmitListTest - Helper function used by EmitCaseTest1ArgList().
template <typename F>
void EmitListTest(const ListInit& L, const char* LogicOp,
F Callback, raw_ostream& O)
{
// This is a lot like EmitLogicalOperationTest, but works on ListInits instead
// of Dags...
bool isFirst = true;
for (ListInit::const_iterator B = L.begin(), E = L.end(); B != E; ++B) {
if (isFirst)
isFirst = false;
else
O << " || ";
Callback(InitPtrToString(*B), O);
}
}
// Callbacks for use with EmitListTest.
class EmitSwitchOn {
const OptionDescriptions& OptDescs_;
public:
EmitSwitchOn(const OptionDescriptions& OptDescs) : OptDescs_(OptDescs)
{}
void operator()(const std::string& OptName, raw_ostream& O) const {
const OptionDescription& OptDesc = OptDescs_.FindSwitch(OptName);
O << OptDesc.GenVariableName();
}
};
class EmitEmptyTest {
bool EmitNegate_;
const OptionDescriptions& OptDescs_;
public:
EmitEmptyTest(bool EmitNegate, const OptionDescriptions& OptDescs)
: EmitNegate_(EmitNegate), OptDescs_(OptDescs)
{}
void operator()(const std::string& OptName, raw_ostream& O) const {
const char* Neg = (EmitNegate_ ? "!" : "");
if (OptName == "o") {
O << Neg << "OutputFilename.empty()";
}
else {
const OptionDescription& OptDesc = OptDescs_.FindListOrParameter(OptName);
O << Neg << OptDesc.GenVariableName() << ".empty()";
}
}
};
/// EmitCaseTest1ArgList - Helper function used by EmitCaseTest1Arg();
bool EmitCaseTest1ArgList(const std::string& TestName,
const DagInit& d,
const OptionDescriptions& OptDescs,
raw_ostream& O) {
const ListInit& L = *static_cast<ListInit*>(d.getArg(0));
if (TestName == "any_switch_on") {
EmitListTest(L, "||", EmitSwitchOn(OptDescs), O);
return true;
}
else if (TestName == "switch_on") {
EmitListTest(L, "&&", EmitSwitchOn(OptDescs), O);
return true;
}
else if (TestName == "any_not_empty") {
EmitListTest(L, "||", EmitEmptyTest(true, OptDescs), O);
return true;
}
else if (TestName == "any_empty") {
EmitListTest(L, "||", EmitEmptyTest(false, OptDescs), O);
return true;
}
else if (TestName == "not_empty") {
EmitListTest(L, "&&", EmitEmptyTest(true, OptDescs), O);
return true;
}
else if (TestName == "empty") {
EmitListTest(L, "&&", EmitEmptyTest(false, OptDescs), O);
return true;
}
return false;
}
/// EmitCaseTest1ArgStr - Helper function used by EmitCaseTest1Arg(); /// EmitCaseTest1ArgStr - Helper function used by EmitCaseTest1Arg();
bool EmitCaseTest1ArgStr(const std::string& TestName, bool EmitCaseTest1ArgStr(const std::string& TestName,
const DagInit& d, const DagInit& d,
@ -1075,8 +1205,7 @@ bool EmitCaseTest1ArgStr(const std::string& TestName,
const std::string& OptName = InitPtrToString(d.getArg(0)); const std::string& OptName = InitPtrToString(d.getArg(0));
if (TestName == "switch_on") { if (TestName == "switch_on") {
const OptionDescription& OptDesc = OptDescs.FindSwitch(OptName); apply(EmitSwitchOn(OptDescs), OptName, O);
O << OptDesc.GenVariableName();
return true; return true;
} }
else if (TestName == "input_languages_contain") { else if (TestName == "input_languages_contain") {
@ -1092,50 +1221,10 @@ bool EmitCaseTest1ArgStr(const std::string& TestName,
return true; return true;
} }
else if (TestName == "not_empty" || TestName == "empty") { else if (TestName == "not_empty" || TestName == "empty") {
const char* Test = (TestName == "empty") ? "" : "!"; bool EmitNegate = (TestName == "not_empty");
apply(EmitEmptyTest(EmitNegate, OptDescs), OptName, O);
if (OptName == "o") {
O << Test << "OutputFilename.empty()";
return true; return true;
} }
else {
const OptionDescription& OptDesc = OptDescs.FindOption(OptName);
if (OptDesc.isSwitch())
throw OptName
+ ": incorrect option type - should be a list or parameter!";
O << Test << OptDesc.GenVariableName() << ".empty()";
return true;
}
}
return false;
}
/// EmitCaseTest1ArgList - Helper function used by EmitCaseTest1Arg();
bool EmitCaseTest1ArgList(const std::string& TestName,
const DagInit& d,
const OptionDescriptions& OptDescs,
raw_ostream& O) {
const ListInit& L = *static_cast<ListInit*>(d.getArg(0));
if (TestName == "any_switch_on") {
bool isFirst = true;
for (ListInit::const_iterator B = L.begin(), E = L.end(); B != E; ++B) {
const std::string& OptName = InitPtrToString(*B);
const OptionDescription& OptDesc = OptDescs.FindSwitch(OptName);
if (isFirst)
isFirst = false;
else
O << " || ";
O << OptDesc.GenVariableName();
}
return true;
}
// TODO: implement any_not_empty, any_empty, switch_on [..], empty [..]
return false; return false;
} }
@ -1161,17 +1250,14 @@ bool EmitCaseTest2Args(const std::string& TestName,
checkNumberOfArguments(&d, 2); checkNumberOfArguments(&d, 2);
const std::string& OptName = InitPtrToString(d.getArg(0)); const std::string& OptName = InitPtrToString(d.getArg(0));
const std::string& OptArg = InitPtrToString(d.getArg(1)); const std::string& OptArg = InitPtrToString(d.getArg(1));
const OptionDescription& OptDesc = OptDescs.FindOption(OptName);
if (TestName == "parameter_equals") { if (TestName == "parameter_equals") {
if (!OptDesc.isParameter()) const OptionDescription& OptDesc = OptDescs.FindParameter(OptName);
throw OptName + ": incorrect option type - should be a parameter!";
O << OptDesc.GenVariableName() << " == \"" << OptArg << "\""; O << OptDesc.GenVariableName() << " == \"" << OptArg << "\"";
return true; return true;
} }
else if (TestName == "element_in_list") { else if (TestName == "element_in_list") {
if (!OptDesc.isList()) const OptionDescription& OptDesc = OptDescs.FindList(OptName);
throw OptName + ": incorrect option type - should be a list!";
const std::string& VarName = OptDesc.GenVariableName(); const std::string& VarName = OptDesc.GenVariableName();
O << "std::find(" << VarName << ".begin(),\n"; O << "std::find(" << VarName << ".begin(),\n";
O.indent(IndentLevel + Indent1) O.indent(IndentLevel + Indent1)