docc 0.8.3 (0d44999b)
C++ API Reference
Loading...
Searching...
No Matches
options.h
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4#include <stdexcept>
5#include <string>
6#include <string_view>
7#include <type_traits>
8#include <unordered_map>
9#include <variant>
10#include <vector>
11
12namespace sdfg {
13
14enum class OptionType { Bool, Int, Double, String };
15
16using OptionValue = std::variant<bool, int64_t, double, std::string>;
17
18template<class T>
20 if constexpr (std::is_same_v<T, bool>) {
21 return OptionType::Bool;
22 } else if constexpr (std::is_same_v<T, int64_t>) {
23 return OptionType::Int;
24 } else if constexpr (std::is_same_v<T, double>) {
25 return OptionType::Double;
26 } else {
27 static_assert(std::is_same_v<T, std::string>, "Unsupported option type");
28 return OptionType::String;
29 }
30}
31
32struct OptionSpec {
33 std::string key;
36 std::string doc;
37};
38
39template<class T>
40struct OptionKey {
41 std::string_view key;
42 constexpr explicit OptionKey(std::string_view k) : key(k) {
43 }
44
45 // Build the registry spec from this handle so key and type aren't restated.
46 OptionSpec spec(T default_value, std::string doc) const {
47 return {std::string(key), option_type_of<T>(), OptionValue{std::move(default_value)}, std::move(doc)};
48 }
49};
50
51// Defined below; referenced by Options::set_option for registry-validated sets.
52class OptionRegistry;
53
54// A per-run bag of option values, keyed by option name. Shared by passes,
55// analyses, and any helper that is handed one; not tied to passes.
56class Options {
57public:
58 void set(std::string key, OptionValue value) {
59 values_.insert_or_assign(std::move(key), std::move(value));
60 }
61
62 // Validate `key` against `registry` and store `value`, coercing it to the
63 // option's declared type (e.g. an integer literal supplied for a Double
64 // option). Throws if the key is unknown or the value type is incompatible.
65 void set_option(const OptionRegistry& registry, const std::string& key, const OptionValue& value);
66
67 bool has(std::string_view key) const {
68 return values_.find(std::string(key)) != values_.end();
69 }
70
71 template<class T>
72 T get(const OptionKey<T>& key, T fallback = T{}) const {
73 auto it = values_.find(std::string(key.key));
74 if (it == values_.end()) {
75 return fallback;
76 }
77 if (auto* v = std::get_if<T>(&it->second)) {
78 return *v;
79 }
80 return fallback;
81 }
82
83 // Shared empty bag so consumers run with defaults when nothing is forwarded.
84 static const Options& empty() {
85 static const Options e;
86 return e;
87 }
88
89private:
90 std::unordered_map<std::string, OptionValue> values_;
91};
92
93// Registry of option specs for discovery/validation. Options are registered
94// independently of who consumes them (passes, analyses, helpers).
96public:
97 void register_option(const OptionSpec& spec) {
98 if (!options_.emplace(spec.key, spec).second) {
99 throw std::runtime_error("Duplicate option key: " + spec.key);
100 }
101 }
102
103 const std::unordered_map<std::string, OptionSpec>& options() const {
104 return options_;
105 }
106
107 const OptionSpec* find_option(std::string_view key) const {
108 auto it = options_.find(std::string(key));
109 return it == options_.end() ? nullptr : &it->second;
110 }
111
112private:
113 std::unordered_map<std::string, OptionSpec> options_;
114};
115
116inline void Options::set_option(const OptionRegistry& registry, const std::string& key, const OptionValue& value) {
117 const OptionSpec* spec = registry.find_option(key);
118 if (spec == nullptr) {
119 throw std::runtime_error("Unknown option: " + key);
120 }
121 switch (spec->type) {
122 case OptionType::Bool:
123 if (const auto* b = std::get_if<bool>(&value)) {
124 set(key, OptionValue{*b});
125 } else {
126 throw std::runtime_error("Option '" + key + "' expects a bool value");
127 }
128 break;
129 case OptionType::Int:
130 if (const auto* i = std::get_if<int64_t>(&value)) {
131 set(key, OptionValue{*i});
132 } else if (const auto* b = std::get_if<bool>(&value)) {
133 set(key, OptionValue{static_cast<int64_t>(*b)});
134 } else {
135 throw std::runtime_error("Option '" + key + "' expects an int value");
136 }
137 break;
139 if (const auto* d = std::get_if<double>(&value)) {
140 set(key, OptionValue{*d});
141 } else if (const auto* i = std::get_if<int64_t>(&value)) {
142 set(key, OptionValue{static_cast<double>(*i)});
143 } else {
144 throw std::runtime_error("Option '" + key + "' expects a double value");
145 }
146 break;
148 if (const auto* s = std::get_if<std::string>(&value)) {
149 set(key, OptionValue{*s});
150 } else {
151 throw std::runtime_error("Option '" + key + "' expects a string value");
152 }
153 break;
154 }
155}
156
157} // namespace sdfg
Definition options.h:95
const std::unordered_map< std::string, OptionSpec > & options() const
Definition options.h:103
void register_option(const OptionSpec &spec)
Definition options.h:97
const OptionSpec * find_option(std::string_view key) const
Definition options.h:107
Definition options.h:56
T get(const OptionKey< T > &key, T fallback=T{}) const
Definition options.h:72
bool has(std::string_view key) const
Definition options.h:67
static const Options & empty()
Definition options.h:84
void set(std::string key, OptionValue value)
Definition options.h:58
void set_option(const OptionRegistry &registry, const std::string &key, const OptionValue &value)
Definition options.h:116
Definition analysis.h:7
std::variant< bool, int64_t, double, std::string > OptionValue
Definition options.h:16
OptionType
Definition options.h:14
@ Int
Definition options.h:14
@ String
Definition options.h:14
@ Bool
Definition options.h:14
@ Double
Definition options.h:14
constexpr OptionType option_type_of()
Definition options.h:19
Definition options.h:40
OptionSpec spec(T default_value, std::string doc) const
Definition options.h:46
std::string_view key
Definition options.h:41
constexpr OptionKey(std::string_view k)
Definition options.h:42
Definition options.h:32
OptionType type
Definition options.h:34
std::string key
Definition options.h:33
OptionValue default_value
Definition options.h:35
std::string doc
Definition options.h:36