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;
}
// 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
@ -157,6 +169,10 @@ namespace OptionType {
enum OptionType { Alias, Switch, Parameter, ParameterList,
Prefix, PrefixList};
bool IsAlias(OptionType t) {
return (t == Alias);
}
bool IsList (OptionType t) {
return (t == ParameterList || t == PrefixList);
}
@ -245,12 +261,12 @@ struct OptionDescription {
bool isReallyHidden() const;
void setReallyHidden();
bool isParameter() const
{ return OptionType::IsParameter(this->Type); }
bool isSwitch() const
{ return OptionType::IsSwitch(this->Type); }
bool isParameter() const
{ return OptionType::IsParameter(this->Type); }
bool isList() const
{ return OptionType::IsList(this->Type); }
@ -272,7 +288,7 @@ void OptionDescription::Merge (const OptionDescription& other)
}
bool OptionDescription::isAlias() const {
return Type == OptionType::Alias;
return OptionType::IsAlias(this->Type);
}
bool OptionDescription::isMultiVal() const {
@ -365,9 +381,14 @@ class OptionDescriptions {
public:
/// FindOption - exception-throwing wrapper for find().
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& 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
/// OptionDescriptions list
@ -380,8 +401,7 @@ public:
};
const OptionDescription&
OptionDescriptions::FindOption(const std::string& OptName) const
{
OptionDescriptions::FindOption(const std::string& OptName) const {
const_iterator I = Descriptions.find(OptName);
if (I != Descriptions.end())
return I->second;
@ -390,16 +410,39 @@ OptionDescriptions::FindOption(const std::string& OptName) const
}
const OptionDescription&
OptionDescriptions::FindSwitch(const std::string& OptName) const
{
OptionDescriptions::FindSwitch(const std::string& OptName) const {
const OptionDescription& OptDesc = this->FindOption(OptName);
if (!OptDesc.isSwitch())
throw OptName + ": incorrect option type - should be a switch!";
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);
if (I != Descriptions.end()) {
OptionDescription& D = I->second;
@ -1067,6 +1110,93 @@ bool EmitCaseTest0Args(const std::string& TestName, raw_ostream& O) {
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();
bool EmitCaseTest1ArgStr(const std::string& TestName,
const DagInit& d,
@ -1075,8 +1205,7 @@ bool EmitCaseTest1ArgStr(const std::string& TestName,
const std::string& OptName = InitPtrToString(d.getArg(0));
if (TestName == "switch_on") {
const OptionDescription& OptDesc = OptDescs.FindSwitch(OptName);
O << OptDesc.GenVariableName();
apply(EmitSwitchOn(OptDescs), OptName, O);
return true;
}
else if (TestName == "input_languages_contain") {
@ -1092,51 +1221,11 @@ bool EmitCaseTest1ArgStr(const std::string& TestName,
return true;
}
else if (TestName == "not_empty" || TestName == "empty") {
const char* Test = (TestName == "empty") ? "" : "!";
if (OptName == "o") {
O << Test << "OutputFilename.empty()";
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();
}
bool EmitNegate = (TestName == "not_empty");
apply(EmitEmptyTest(EmitNegate, OptDescs), OptName, O);
return true;
}
// TODO: implement any_not_empty, any_empty, switch_on [..], empty [..]
return false;
}
@ -1161,17 +1250,14 @@ bool EmitCaseTest2Args(const std::string& TestName,
checkNumberOfArguments(&d, 2);
const std::string& OptName = InitPtrToString(d.getArg(0));
const std::string& OptArg = InitPtrToString(d.getArg(1));
const OptionDescription& OptDesc = OptDescs.FindOption(OptName);
if (TestName == "parameter_equals") {
if (!OptDesc.isParameter())
throw OptName + ": incorrect option type - should be a parameter!";
const OptionDescription& OptDesc = OptDescs.FindParameter(OptName);
O << OptDesc.GenVariableName() << " == \"" << OptArg << "\"";
return true;
}
else if (TestName == "element_in_list") {
if (!OptDesc.isList())
throw OptName + ": incorrect option type - should be a list!";
const OptionDescription& OptDesc = OptDescs.FindList(OptName);
const std::string& VarName = OptDesc.GenVariableName();
O << "std::find(" << VarName << ".begin(),\n";
O.indent(IndentLevel + Indent1)