AI 24/25 Project Software
Documentation for the AI 24/25 course programming project software
Loading...
Searching...
No Matches
plugin.h
1#ifndef PLUGINS_PLUGIN_H
2#define PLUGINS_PLUGIN_H
3
4#include "options.h"
5#include "plugin_info.h"
6#include "raw_registry.h"
7
8#include "downward/utils/strings.h"
9#include "downward/utils/system.h"
10#include "downward/utils/tuples.h"
11
12#include <any>
13#include <string>
14#include <type_traits>
15#include <typeindex>
16#include <vector>
17
18namespace utils {
19class Context;
20}
21
22namespace downward::cli::plugins {
23class Feature {
24 const Type& type;
25 std::string key;
26 std::string title;
27 std::string synopsis;
28 std::string subcategory;
29 std::vector<ArgumentInfo> arguments;
30 std::vector<PropertyInfo> properties;
31 std::vector<LanguageSupportInfo> language_support;
32 std::vector<NoteInfo> notes;
33
34public:
35 Feature(const Type& type, const std::string& key);
36 virtual ~Feature() = default;
37 Feature(const Feature&) = delete;
38
39 virtual std::any
40 construct(const Options& opts, const ::utils::Context& context) const = 0;
41
42 /* Add option with default value. Use def_val=ArgumentInfo::NO_DEFAULT for
43 optional parameters without default values. */
44 template <typename T>
45 void add_option(
46 const std::string& key,
47 const std::string& help = "",
48 const std::string& default_value = "",
49 const Bounds& bounds = Bounds::unlimited(),
50 bool lazy_construction = false);
51
52 template <typename T>
53 void add_list_option(
54 const std::string& key,
55 const std::string& help = "",
56 const std::string& default_value = "",
57 bool lazy_construction = false);
58
59 void document_subcategory(const std::string& subcategory);
60 void document_title(const std::string& title);
61 void document_synopsis(const std::string& note);
62 void
63 document_property(const std::string& property, const std::string& note);
64 void document_language_support(
65 const std::string& feature,
66 const std::string& note);
67 void document_note(
68 const std::string& title,
69 const std::string& note,
70 bool long_text = false);
71
72 const Type& get_type() const;
73 std::string get_key() const;
74 std::string get_title() const;
75 std::string get_synopsis() const;
76 std::string get_subcategory() const;
77 const std::vector<ArgumentInfo>& get_arguments() const;
78 const std::vector<PropertyInfo>& get_properties() const;
79 const std::vector<LanguageSupportInfo>& get_language_support() const;
80 const std::vector<NoteInfo>& get_notes() const;
81};
82
83template <typename Constructed>
84class FeatureWithDefault : public Feature {
85protected:
86 using Feature::Feature;
87 virtual std::shared_ptr<Constructed>
88 create_component(const Options& options, const ::utils::Context&) const
89 {
90 return std::make_shared<Constructed>(options);
91 }
92};
93
94template <typename Constructed>
95class FeatureWithoutDefault : public Feature {
96protected:
97 using Feature::Feature;
98 virtual std::shared_ptr<Constructed>
99 create_component(const Options&, const ::utils::Context&) const = 0;
100};
101
102template <typename Constructed>
103using FeatureAuto = typename std::conditional<
104 std::is_constructible<Constructed, const Options&>::value,
105 FeatureWithDefault<Constructed>,
106 FeatureWithoutDefault<Constructed>>::type;
107
108template <typename Base, typename Constructed>
109class TypedFeature : public FeatureAuto<Constructed> {
110 using BasePtr = std::shared_ptr<Base>;
111 static_assert(
112 std::is_base_of<Base, Constructed>::value,
113 "Constructed must derive from Base");
114
115public:
116 TypedFeature(const std::string& key)
117 : FeatureAuto<Constructed>(
118 TypeRegistry::instance()->get_type<BasePtr>(),
119 key)
120 {
121 }
122
123 std::any construct(const Options& options, const ::utils::Context& context)
124 const override
125 {
126 std::shared_ptr<Base> ptr = this->create_component(options, context);
127 return std::any(ptr);
128 }
129};
130
131/*
132 Expects constructor arguments of T. Consecutive arguments may be
133 grouped in a tuple. All tuples in the arguments will be flattened
134 before calling the constructor. The resulting arguments will be used
135 as arguments to make_shared.
136*/
137template <typename T, typename... Arguments>
138std::shared_ptr<T> make_shared_from_arg_tuples(Arguments... arguments)
139{
140 return std::apply(
141 [](auto&&... flattened_args) {
142 return std::make_shared<T>(
143 std::forward<decltype(flattened_args)>(flattened_args)...);
144 },
145 ::utils::flatten_tuple(
146 std::tuple<Arguments...>(std::forward<Arguments>(arguments)...)));
147}
148
149class Plugin {
150public:
151 Plugin();
152 virtual ~Plugin() = default;
153 Plugin(const Plugin&) = delete;
154 virtual std::shared_ptr<Feature> create_feature() const = 0;
155};
156
157template <typename T>
158class FeaturePlugin : public Plugin {
159public:
160 FeaturePlugin()
161 : Plugin()
162 {
163 }
164 virtual std::shared_ptr<Feature> create_feature() const override
165 {
166 return std::make_shared<T>();
167 }
168};
169
170/*
171 The CategoryPlugin class contains meta-information for a given
172 category of feature (e.g. "SearchAlgorithm" or "MergeStrategyFactory").
173*/
174class CategoryPlugin {
175 std::type_index pointer_type;
176 std::string class_name;
177
178 /*
179 The category name should be "user-friendly". It is for example used
180 as the name of the wiki page that documents this feature type.
181 It follows wiki conventions (e.g. "Heuristic", "SearchAlgorithm",
182 "ShrinkStrategy").
183 */
184 std::string category_name;
185
186 /*
187 General documentation for the feature type. This is included at
188 the top of the wiki page for this feature type.
189 */
190 std::string synopsis;
191
192 /*
193 TODO: Currently, we do not support variable binding of all categories, so
194 variables can only be used for categories explicitly marked. This might
195 change once we fix the component interaction (issue559). If all feature
196 types can be bound to variables, we can probably get rid of this flag and
197 related code in CategoryPlugin, TypedCategoryPlugin, RawRegistry,
198 Registry, Parser, ...
199 */
200 bool can_be_bound_to_variable;
201
202public:
203 CategoryPlugin(
204 std::type_index pointer_type,
205 const std::string& class_name,
206 const std::string& category_name);
207 virtual ~CategoryPlugin() = default;
208 CategoryPlugin(const CategoryPlugin&) = delete;
209
210 void document_synopsis(const std::string& synopsis);
211 void allow_variable_binding();
212
213 std::type_index get_pointer_type() const;
214 std::string get_category_name() const;
215 std::string get_class_name() const;
216 std::string get_synopsis() const;
217 bool supports_variable_binding() const;
218};
219
220template <typename T>
221class TypedCategoryPlugin : public CategoryPlugin {
222public:
223 TypedCategoryPlugin(const std::string& category_name)
224 : CategoryPlugin(
225 typeid(std::shared_ptr<T>),
226 typeid(std::shared_ptr<T>).name(),
227 category_name)
228 {
229 }
230};
231
232class SubcategoryPlugin {
233 std::string subcategory_name;
234 std::string title;
235 std::string synopsis;
236
237public:
238 SubcategoryPlugin(const std::string& subcategory);
239
240 void document_title(const std::string& title);
241 void document_synopsis(const std::string& synopsis);
242
243 std::string get_subcategory_name() const;
244 std::string get_title() const;
245 std::string get_synopsis() const;
246};
247
248class EnumPlugin {
249 std::type_index type;
250 std::string class_name;
251 EnumInfo enum_info;
252
253public:
254 EnumPlugin(
255 std::type_index type,
256 const std::string& class_name,
257 std::initializer_list<std::pair<std::string, std::string>> enum_values);
258
259 std::type_index get_type() const;
260 std::string get_class_name() const;
261 const EnumInfo& get_enum_info() const;
262};
263
264template <typename T>
265class TypedEnumPlugin : public EnumPlugin {
266public:
267 TypedEnumPlugin(
268 std::initializer_list<std::pair<std::string, std::string>> enum_values)
269 : EnumPlugin(typeid(T), typeid(std::shared_ptr<T>).name(), enum_values)
270 {
271 }
272};
273
274template <typename T>
275void Feature::add_option(
276 const std::string& key,
277 const std::string& help,
278 const std::string& default_value,
279 const Bounds& bounds,
280 bool lazy_construction)
281{
282 arguments.emplace_back(
283 key,
284 help,
285 TypeRegistry::instance()->get_type<T>(),
286 default_value,
287 bounds,
288 lazy_construction);
289}
290
291template <typename T>
292void Feature::add_list_option(
293 const std::string& key,
294 const std::string& help,
295 const std::string& default_value,
296 bool lazy_construction)
297{
298 add_option<std::vector<T>>(
299 key,
300 help,
301 default_value,
302 Bounds::unlimited(),
303 lazy_construction);
304}
305} // namespace downward::cli::plugins
306
307#endif
STL namespace.