|
28 | 28 | #include "ConfigFragment.h"
|
29 | 29 | #include "support/Logger.h"
|
30 | 30 | #include "support/Trace.h"
|
| 31 | +#include "llvm/ADT/STLExtras.h" |
31 | 32 | #include "llvm/ADT/StringRef.h"
|
| 33 | +#include "llvm/ADT/StringSwitch.h" |
32 | 34 | #include "llvm/Support/Regex.h"
|
33 | 35 | #include "llvm/Support/SMLoc.h"
|
34 | 36 | #include "llvm/Support/SourceMgr.h"
|
@@ -80,9 +82,56 @@ struct FragmentCompiler {
|
80 | 82 | return Result;
|
81 | 83 | }
|
82 | 84 |
|
| 85 | + // Helper with similar API to StringSwitch, for parsing enum values. |
| 86 | + template <typename T> class EnumSwitch { |
| 87 | + FragmentCompiler &Outer; |
| 88 | + llvm::StringRef EnumName; |
| 89 | + const Located<std::string> &Input; |
| 90 | + llvm::Optional<T> Result; |
| 91 | + llvm::SmallVector<llvm::StringLiteral, 8> ValidValues; |
| 92 | + |
| 93 | + public: |
| 94 | + EnumSwitch(llvm::StringRef EnumName, const Located<std::string> &In, |
| 95 | + FragmentCompiler &Outer) |
| 96 | + : Outer(Outer), EnumName(EnumName), Input(In) {} |
| 97 | + |
| 98 | + EnumSwitch &map(llvm::StringLiteral Name, T Value) { |
| 99 | + assert(!llvm::is_contained(ValidValues, Name) && "Duplicate value!"); |
| 100 | + ValidValues.push_back(Name); |
| 101 | + if (!Result && *Input == Name) |
| 102 | + Result = Value; |
| 103 | + return *this; |
| 104 | + } |
| 105 | + |
| 106 | + llvm::Optional<T> value() { |
| 107 | + if (!Result) |
| 108 | + Outer.diag( |
| 109 | + Warning, |
| 110 | + llvm::formatv("Invalid {0} value '{1}'. Valid values are {2}.", |
| 111 | + EnumName, *Input, llvm::join(ValidValues, ", ")) |
| 112 | + .str(), |
| 113 | + Input.Range); |
| 114 | + return Result; |
| 115 | + }; |
| 116 | + }; |
| 117 | + |
| 118 | + // Attempt to parse a specified string into an enum. |
| 119 | + // Yields llvm::None and produces a diagnostic on failure. |
| 120 | + // |
| 121 | + // Optional<T> Value = compileEnum<En>("Foo", Frag.Foo) |
| 122 | + // .map("Foo", Enum::Foo) |
| 123 | + // .map("Bar", Enum::Bar) |
| 124 | + // .value(); |
| 125 | + template <typename T> |
| 126 | + EnumSwitch<T> compileEnum(llvm::StringRef EnumName, |
| 127 | + const Located<std::string> &In) { |
| 128 | + return EnumSwitch<T>(EnumName, In, *this); |
| 129 | + } |
| 130 | + |
83 | 131 | void compile(Fragment &&F) {
|
84 | 132 | compile(std::move(F.If));
|
85 | 133 | compile(std::move(F.CompileFlags));
|
| 134 | + compile(std::move(F.Index)); |
86 | 135 | }
|
87 | 136 |
|
88 | 137 | void compile(Fragment::IfBlock &&F) {
|
@@ -148,7 +197,20 @@ struct FragmentCompiler {
|
148 | 197 | }
|
149 | 198 | }
|
150 | 199 |
|
| 200 | + void compile(Fragment::IndexBlock &&F) { |
| 201 | + if (F.Background) { |
| 202 | + if (auto Val = compileEnum<Config::BackgroundPolicy>("Background", |
| 203 | + **F.Background) |
| 204 | + .map("Build", Config::BackgroundPolicy::Build) |
| 205 | + .map("Skip", Config::BackgroundPolicy::Skip) |
| 206 | + .value()) |
| 207 | + Out.Apply.push_back([Val](Config &C) { C.Index.Background = *Val; }); |
| 208 | + } |
| 209 | + } |
| 210 | + |
151 | 211 | constexpr static llvm::SourceMgr::DiagKind Error = llvm::SourceMgr::DK_Error;
|
| 212 | + constexpr static llvm::SourceMgr::DiagKind Warning = |
| 213 | + llvm::SourceMgr::DK_Warning; |
152 | 214 | void diag(llvm::SourceMgr::DiagKind Kind, llvm::StringRef Message,
|
153 | 215 | llvm::SMRange Range) {
|
154 | 216 | if (Range.isValid() && SourceMgr != nullptr)
|
|
0 commit comments