MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
ComputeGrammar.hpp
Go to the documentation of this file.
1#pragma once
2
4
6
7namespace MayaFlux::Yantra {
8
9/**
10 * @class ComputationGrammar
11 * @brief Core grammar system for rule-based computation in Maya Flux
12 *
13 * The ComputationGrammar provides a powerful, declarative system for defining how
14 * computational operations should be applied based on input data characteristics,
15 * execution context, and user-defined rules. This enables intelligent, adaptive
16 * computation that can select appropriate operations dynamically.
17 *
18 * ## Core Concepts
19 *
20 * **Rules**: Define when and how operations should be applied. Each rule contains:
21 * - Matching logic to determine if the rule applies to given input
22 * - Execution logic that performs the actual computation
23 * - Metadata for organization, prioritization, and optimization
24 *
25 * **Contexts**: Categorize rules by computational domain (temporal, spectral, etc.)
26 * for efficient lookup and logical organization.
27 *
28 * **Priority System**: Higher priority rules are evaluated first, allowing for
29 * hierarchical decision making and exception handling.
30 *
31 * ## Usage Patterns
32 *
33 * ### Simple Rule Creation
34 * ```cpp
35 * ComputationGrammar grammar;
36 *
37 * // Add a rule for mathematical transformations on double vectors
38 * grammar.create_rule("gain_amplification")
39 * .with_context(ComputationContext::TEMPORAL)
40 * .with_priority(100)
41 * .matches_type<std::vector<double>>()
42 * .executes([](const std::any& input, const ExecutionContext& ctx) {
43 * // Custom transformation logic
44 * return input; // simplified
45 * })
46 * .build();
47 * ```
48 *
49 * ### Complex Matcher Combinations
50 * ```cpp
51 * auto complex_matcher = UniversalMatcher::combine_and({
52 * UniversalMatcher::create_type_matcher<std::vector<Kakshya::DataVariant>>(),
53 * UniversalMatcher::create_context_matcher(ComputationContext::SPECTRAL),
54 * UniversalMatcher::create_parameter_matcher("frequency_range", std::string("audio"))
55 * });
56 *
57 * grammar.create_rule("spectral_filter")
58 * .matches_custom(complex_matcher)
59 * .executes([](const std::any& input, const ExecutionContext& ctx) {
60 * // Spectral filtering logic
61 * return input;
62 * })
63 * .build();
64 * ```
65 *
66 * ### Operation Integration
67 * ```cpp
68 * // Create rule that automatically applies MathematicalTransformer
69 * grammar.add_operation_rule<MathematicalTransformer<>>(
70 * "auto_normalize",
71 * ComputationContext::MATHEMATICAL,
72 * UniversalMatcher::create_type_matcher<std::vector<Kakshya::DataVariant>>(),
73 * {{"operation", std::string("normalize")}, {"target_peak", 1.0}},
74 * 75 // priority
75 * );
76 * ```
77 */
78class MAYAFLUX_API ComputationGrammar {
79public:
80 /**
81 * @struct Rule
82 * @brief Represents a computation rule with matching and execution logic
83 *
84 * Rules are the fundamental building blocks of the grammar system. Each rule
85 * encapsulates the logic for determining when it should be applied (matcher)
86 * and what computation it should perform (executor), along with metadata
87 * for organization and optimization.
88 */
89 struct MAYAFLUX_API Rule {
90 /**
91 * @brief Type alias for matcher functions used in computation rules
92 */
93 using Executor = std::function<std::any(const std::any&, const ExecutionContext&)>;
94
95 std::string name; ///< Unique identifier for this rule
96 std::string description; ///< Human-readable description of what the rule does
97 ComputationContext context {}; ///< Computational context this rule operates in
98 int priority = 0; ///< Execution priority (higher values evaluated first)
99 std::optional<Portal::Graphics::ShaderSpec> gpu_spec; ///< When set, executor receives a GPU-backed operation
100
101 UniversalMatcher::MatcherFunc matcher; ///< Function that determines if rule applies
102 Executor executor; ///< Function that performs the computation
103
104 std::vector<std::string> dependencies; ///< Names of rules that must execute before this one
105 std::unordered_map<std::string, std::any> default_parameters; ///< Default parameters for the rule's operation
106
107 std::chrono::milliseconds max_execution_time { 0 }; ///< Maximum allowed execution time (0 = unlimited)
108 ExecutionMode preferred_execution_mode = ExecutionMode::SYNC; ///< Preferred execution mode for this rule
109
110 std::type_index target_operation_type = std::type_index(typeid(void)); ///< Type of operation this rule creates (for type-based queries)
111
112 std::vector<std::string> tags; ///< Arbitrary tags for categorization and search
113 };
114
115 /**
116 * @brief Add a rule to the grammar
117 * @param rule Rule to add to the grammar system
118 *
119 * Rules are automatically sorted by priority (highest first) and indexed by context
120 * for efficient lookup. The rule's name must be unique within the grammar.
121 *
122 * @note Rules with higher priority values are evaluated first during matching
123 */
124 void add_rule(Rule rule)
125 {
126 std::string rule_name = rule.name;
127 ComputationContext rule_context = rule.context;
128
129 auto insert_pos = std::ranges::upper_bound(m_rules, rule,
130 [](const Rule& a, const Rule& b) { return a.priority > b.priority; });
131 m_rules.insert(insert_pos, std::move(rule));
132
133 m_context_index[rule_context].push_back(rule_name);
134 }
135
136 /**
137 * @brief Find the best matching rule for the given input
138 * @param input Input data to match against rules
139 * @param context Execution context containing parameters and metadata
140 * @return First rule that matches the input/context, or nullopt if no match
141 *
142 * Rules are evaluated in priority order (highest first). The first rule whose
143 * matcher function returns true is considered the best match. This allows for
144 * hierarchical decision making where specific rules can override general ones.
145 *
146 * @note The matcher function receives both the input data and execution context,
147 * allowing for complex matching logic based on data type, content, and context
148 */
149 std::optional<Rule> find_best_match(const std::any& input, const ExecutionContext& context) const
150 {
151 for (const auto& rule : m_rules) {
152 if (rule.matcher(input, context)) {
153 return rule;
154 }
155 }
156 return std::nullopt;
157 }
158
159 /**
160 * @brief Execute a specific rule by name
161 * @param rule_name Name of the rule to execute
162 * @param input Input data for the rule's executor
163 * @param context Execution context containing parameters and metadata
164 * @return Result of rule execution, or nullopt if rule not found or doesn't match
165 *
166 * Finds the named rule and executes it if its matcher function returns true
167 * for the given input and context. This allows for explicit rule invocation
168 * when the specific rule to apply is known.
169 *
170 * @note The rule's matcher is still evaluated even when invoked by name,
171 * ensuring that rules maintain their matching contracts
172 */
173 std::optional<std::any> execute_rule(const std::string& rule_name,
174 const std::any& input,
175 const ExecutionContext& context) const
176 {
177 auto it = std::ranges::find_if(m_rules,
178 [&rule_name](const Rule& rule) { return rule.name == rule_name; });
179
180 if (it != m_rules.end() && it->matcher(input, context)) {
181 return it->executor(input, context);
182 }
183 return std::nullopt;
184 }
185
186 /**
187 * @brief Get all rule names for a specific computation context
188 * @param context The computation context to query
189 * @return Vector of rule names that belong to the specified context
190 *
191 * Useful for discovering what rules are available for a particular computational
192 * domain (e.g., all temporal processing rules) or for building context-specific
193 * processing pipelines.
194 */
195 std::vector<std::string> get_rules_by_context(ComputationContext context) const
196 {
197 auto it = m_context_index.find(context);
198 return it != m_context_index.end() ? it->second : std::vector<std::string> {};
199 }
200
201 /**
202 * @brief Get rules that target a specific operation type
203 * @tparam OperationType The operation type to search for
204 * @return Vector of rule names that create or target the specified operation type
205 *
206 * Enables type-based rule discovery, useful for finding all rules that can
207 * create instances of a particular operation type or for verifying rule coverage
208 * for specific operation types.
209 *
210 * Example:
211 * ```cpp
212 * auto math_rules = grammar.get_rules_for_operation_type<MathematicalTransformer<>>();
213 * // Returns names of all rules that create MathematicalTransformer instances
214 * ```
215 */
216 template <typename OperationType>
217 std::vector<std::string> get_rules_for_operation_type() const
218 {
219 std::vector<std::string> matching_rules;
220 auto target_type = std::type_index(typeid(OperationType));
221
222 for (const auto& rule : m_rules) {
223 if (rule.target_operation_type == target_type) {
224 matching_rules.push_back(rule.name);
225 }
226 }
227 return matching_rules;
228 }
229
230 /**
231 * @brief Helper to add concrete operation rules with automatic executor generation
232 * @tparam ConcreteOpType The concrete operation type to instantiate
233 * @tparam OpArgs Constructor argument types for the operation
234 * @param rule_name Unique name for this rule
235 * @param context Computation context for the rule
236 * @param matcher Matcher function to determine when rule applies
237 * @param op_parameters Parameters to configure the operation instance
238 * @param priority Execution priority (default: 50)
239 * @param op_args Constructor arguments for the operation
240 *
241 * Creates a rule that automatically instantiates and configures a concrete operation
242 * type when matched. This is the preferred way to integrate existing operations
243 * into the grammar system, as it handles type safety and parameter application
244 * automatically.
245 *
246 * The generated executor:
247 * 1. Creates an instance of ConcreteOpType with the provided constructor arguments
248 * 2. Applies the op_parameters using set_parameter()
249 * 3. Applies additional parameters from the execution context
250 * 4. Executes the operation on the input data
251 *
252 * Example:
253 * ```cpp
254 * grammar.add_operation_rule<SpectralTransformer<>>(
255 * "pitch_shift_rule",
256 * ComputationContext::SPECTRAL,
257 * UniversalMatcher::create_type_matcher<std::vector<Kakshya::DataVariant>>(),
258 * {{"operation", std::string("pitch_shift")}, {"pitch_ratio", 1.5}},
259 * 80 // priority
260 * );
261 * ```
262 */
263 template <typename ConcreteOpType, typename... OpArgs>
264 void add_operation_rule(const std::string& rule_name,
265 ComputationContext context,
267 const std::unordered_map<std::string, std::any>& op_parameters = {},
268 int priority = 50,
269 OpArgs&&... op_args)
270 {
271 Rule rule;
272 rule.name = rule_name;
273 rule.context = context;
274 rule.priority = priority;
275 rule.matcher = std::move(matcher);
276 rule.target_operation_type = std::type_index(typeid(ConcreteOpType));
277
278 auto captured_args = std::make_tuple(std::forward<OpArgs>(op_args)...);
279
280 rule.executor = [op_parameters, captured_args = std::move(captured_args)](const std::any& input, const ExecutionContext& ctx) -> std::any {
281 auto operation = std::apply([&op_parameters](auto&&... args) {
282 return create_configured_operation<ConcreteOpType>(op_parameters, std::forward<decltype(args)>(args)...);
283 },
284 captured_args);
285
286 apply_context_parameters(operation, ctx);
287
288 auto typed_input = safe_any_cast_or_throw<DataIO>(input);
289 return operation->apply_operation(typed_input);
290 };
291
292 add_rule(std::move(rule));
293 }
294
295 /**
296 * @class RuleBuilder
297 * @brief Fluent interface for building rules with method chaining
298 *
299 * The RuleBuilder provides a clean, readable way to construct complex rules
300 * using method chaining. This pattern makes rule creation more expressive
301 * and helps catch configuration errors at compile time.
302 *
303 * Example usage:
304 * ```cpp
305 * grammar.create_rule("complex_temporal_rule")
306 * .with_context(ComputationContext::TEMPORAL)
307 * .with_priority(75)
308 * .with_description("Applies gain when signal is quiet")
309 * .matches_type<std::vector<double>>()
310 * .targets_operation<MathematicalTransformer<>>()
311 * .with_tags({"audio", "gain", "dynamic"})
312 * .executes([](const std::any& input, const ExecutionContext& ctx) {
313 * // Custom logic here
314 * return input;
315 * })
316 * .build();
317 * ```
318 */
319 class MAYAFLUX_API RuleBuilder {
320 private:
321 Rule m_rule; ///< Rule being constructed
322 ComputationGrammar* m_grammar; ///< Reference to parent grammar
323
324 public:
325 /**
326 * @brief Constructs a RuleBuilder for the specified grammar
327 * @param grammar Parent grammar that will receive the built rule
328 * @param name Unique name for the rule being built
329 */
330 explicit RuleBuilder(ComputationGrammar* grammar, std::string name)
331 : m_grammar(grammar)
332 {
333 m_rule.name = std::move(name);
334 }
335
336 /**
337 * @brief Sets the computation context for this rule
338 * @param context The computational context (temporal, spectral, etc.)
339 * @return Reference to this builder for method chaining
340 */
342 {
343 m_rule.context = context;
344 return *this;
345 }
346
347 /**
348 * @brief Sets the execution priority for this rule
349 * @param priority Priority value (higher values evaluated first)
350 * @return Reference to this builder for method chaining
351 */
353 {
354 m_rule.priority = priority;
355 return *this;
356 }
357
358 /**
359 * @brief Sets a human-readable description for this rule
360 * @param description Description of what the rule does
361 * @return Reference to this builder for method chaining
362 */
363 RuleBuilder& with_description(std::string description)
364 {
365 m_rule.description = std::move(description);
366 return *this;
367 }
368
369 /**
370 * @brief Sets the matcher to check for a specific data type
371 * @tparam DataType The ComputeData type to match against
372 * @return Reference to this builder for method chaining
373 *
374 * Creates a type-based matcher that returns true when the input
375 * data is of the specified type. This is the most common matching
376 * strategy for type-specific operations.
377 */
378 template <ComputeData DataType>
380 {
381 m_rule.matcher = UniversalMatcher::create_type_matcher<DataType>();
382 return *this;
383 }
384
385 /**
386 * @brief Sets a custom matcher function
387 * @param matcher Custom matcher function
388 * @return Reference to this builder for method chaining
389 *
390 * Allows for complex matching logic based on data content, context
391 * parameters, or combinations of multiple criteria. Use this when
392 * simple type matching is insufficient.
393 */
395 {
396 m_rule.matcher = std::move(matcher);
397 return *this;
398 }
399
400 /**
401 * @brief Sets the executor function for this rule
402 * @tparam Func Function type (usually a lambda)
403 * @param executor Function that performs the computation
404 * @return Reference to this builder for method chaining
405 *
406 * The executor function receives the input data and execution context,
407 * and returns the result of the computation. This is where the actual
408 * work of the rule is performed.
409 *
410 * If with_gpu_backend() was called, the executor wrapper attaches a
411 * ShaderExecutionContext to the operation before invoking the user
412 * lambda. The user lambda receives the already-GPU-backed operation
413 * transparently and serves as the CPU fallback if GPU setup fails.
414 */
415 template <typename Func>
416 RuleBuilder& executes(Func&& executor)
417 {
418 if (m_rule.gpu_spec.has_value()) {
419 auto spec = *m_rule.gpu_spec;
420 m_rule.executor = [func = std::forward<Func>(executor), spec = std::move(spec)](
421 const std::any& input, const ExecutionContext& ctx) -> std::any {
422 const auto cfg = config_from_spec(spec);
423 const auto bindings = bindings_from_spec(spec);
424
425 if (cfg.shader_id != Portal::Graphics::INVALID_SHADER) {
426 auto gpu_exec = std::make_shared<ShaderExecutionContext<>>(cfg, bindings);
427 ExecutionContext patched = ctx;
428 patched.execution_metadata["_gpu_exec"] = gpu_exec;
429 return func(input, patched);
430 }
431 return func(input, ctx);
432 };
433 } else {
434 m_rule.executor = [func = std::forward<Func>(executor)](
435 const std::any& input, const ExecutionContext& ctx) -> std::any {
436 return func(input, ctx);
437 };
438 }
439 return *this;
440 }
441
442 /**
443 * @brief Sets the target operation type for this rule
444 * @tparam OperationType The operation type this rule creates or targets
445 * @return Reference to this builder for method chaining
446 *
447 * Used for type-based rule queries and validation. Helps organize
448 * rules by the types of operations they create or work with.
449 */
450 template <typename OperationType>
452 {
453 m_rule.target_operation_type = std::type_index(typeid(OperationType));
454 return *this;
455 }
456
457 /**
458 * @brief Sets arbitrary tags for this rule
459 * @param tags Vector of tag strings for categorization
460 * @return Reference to this builder for method chaining
461 *
462 * Tags provide flexible categorization and search capabilities.
463 * Useful for organizing rules by domain, use case, or other
464 * arbitrary criteria.
465 */
466 RuleBuilder& with_tags(std::vector<std::string> tags)
467 {
468 m_rule.tags = std::move(tags);
469 return *this;
470 }
471
472 /**
473 * @brief Attach a ShaderSpec GPU backend to this rule.
474 *
475 * When set, the executor wrapper builds a ShaderExecutionContext from
476 * the spec via config_from_spec() and bindings_from_spec() and calls
477 * set_gpu_backend() on the operation before dispatching. Falls back to
478 * the CPU executor if shader compilation fails.
479 *
480 * Must be called before executes() to take effect, as executes() reads
481 * the stored spec when wrapping the user lambda.
482 *
483 * @param spec ShaderSpec produced by ShaderSpec::Assemble::build().
484 */
486 {
487 m_rule.gpu_spec = std::move(spec);
488 return *this;
489 }
490
491 /**
492 * @brief Finalizes and adds the rule to the grammar
493 *
494 * This method must be called to complete rule construction.
495 * The built rule is added to the parent grammar and sorted
496 * by priority for efficient matching.
497 *
498 * @note After calling build(), this RuleBuilder should not be used again
499 */
500 void build()
501 {
502 m_grammar->add_rule(std::move(m_rule));
503 }
504 };
505
506 /**
507 * @brief Create a rule builder for fluent rule construction
508 * @param name Unique name for the rule
509 * @return RuleBuilder instance for method chaining
510 *
511 * This is the entry point for the fluent rule building interface.
512 * Returns a RuleBuilder that can be used to configure and build
513 * a rule using method chaining.
514 *
515 * Example:
516 * ```cpp
517 * auto builder = grammar.create_rule("my_rule");
518 * builder.with_context(ComputationContext::MATHEMATICAL)
519 * .matches_type<std::vector<double>>()
520 * .executes([](const auto& input, const auto& ctx) { return input; })
521 * .build();
522 * ```
523 */
524 RuleBuilder create_rule(const std::string& name)
525 {
526 return RuleBuilder(this, name);
527 }
528
529 /**
530 * @brief Get the total number of rules in the grammar
531 * @return Number of rules currently registered
532 */
533 [[nodiscard]] size_t get_rule_count() const { return m_rules.size(); }
534
535 /**
536 * @brief Get all rule names in the grammar
537 * @return Vector of all rule names, ordered by priority
538 */
539 [[nodiscard]] std::vector<std::string> get_all_rule_names() const
540 {
541 std::vector<std::string> names;
542 names.reserve(m_rules.size());
543 std::ranges::transform(m_rules, std::back_inserter(names),
544 [](const Rule& rule) { return rule.name; });
545 return names;
546 }
547
548 /**
549 * @brief Check if a rule with the given name exists
550 * @param rule_name Name to check
551 * @return True if rule exists, false otherwise
552 */
553 [[nodiscard]] bool has_rule(const std::string& rule_name) const
554 {
555 return std::ranges::any_of(m_rules,
556 [&rule_name](const Rule& rule) { return rule.name == rule_name; });
557 }
558
559 /**
560 * @brief Remove a rule by name
561 * @param rule_name Name of rule to remove
562 * @return True if rule was removed, false if not found
563 *
564 * Removes the rule from both the main rule list and the context index.
565 * This is useful for dynamic rule management and grammar updates.
566 */
567 bool remove_rule(const std::string& rule_name)
568 {
569 auto it = std::ranges::find_if(m_rules,
570 [&rule_name](const Rule& rule) { return rule.name == rule_name; });
571
572 if (it != m_rules.end()) {
573 ComputationContext context = it->context;
574 m_rules.erase(it);
575
576 auto& context_rules = m_context_index[context];
577 std::erase_if(context_rules,
578 [&](const std::string& name) {
579 return name == rule_name;
580 });
581
582 return true;
583 }
584 return false;
585 }
586
587 /**
588 * @brief Clear all rules from the grammar
589 *
590 * Removes all rules and clears all indices. Useful for resetting
591 * the grammar to a clean state or for testing scenarios.
592 */
594 {
595 m_rules.clear();
596 m_context_index.clear();
597 }
598
599private:
600 std::vector<Rule> m_rules; ///< All rules sorted by priority (highest first)
601 std::unordered_map<ComputationContext, std::vector<std::string>> m_context_index; ///< Index of rule names by context for fast lookup
602};
603
604} // namespace MayaFlux::Yantra
Core::GlobalInputConfig input
Definition Config.cpp:38
size_t a
size_t b
void build()
Finalizes and adds the rule to the grammar.
RuleBuilder(ComputationGrammar *grammar, std::string name)
Constructs a RuleBuilder for the specified grammar.
RuleBuilder & with_context(ComputationContext context)
Sets the computation context for this rule.
RuleBuilder & matches_type()
Sets the matcher to check for a specific data type.
RuleBuilder & with_gpu_backend(Portal::Graphics::ShaderSpec spec)
Attach a ShaderSpec GPU backend to this rule.
ComputationGrammar * m_grammar
Reference to parent grammar.
RuleBuilder & executes(Func &&executor)
Sets the executor function for this rule.
RuleBuilder & with_tags(std::vector< std::string > tags)
Sets arbitrary tags for this rule.
RuleBuilder & matches_custom(UniversalMatcher::MatcherFunc matcher)
Sets a custom matcher function.
RuleBuilder & with_priority(int priority)
Sets the execution priority for this rule.
RuleBuilder & with_description(std::string description)
Sets a human-readable description for this rule.
RuleBuilder & targets_operation()
Sets the target operation type for this rule.
Fluent interface for building rules with method chaining.
bool remove_rule(const std::string &rule_name)
Remove a rule by name.
RuleBuilder create_rule(const std::string &name)
Create a rule builder for fluent rule construction.
std::unordered_map< ComputationContext, std::vector< std::string > > m_context_index
Index of rule names by context for fast lookup.
std::optional< Rule > find_best_match(const std::any &input, const ExecutionContext &context) const
Find the best matching rule for the given input.
std::vector< std::string > get_rules_for_operation_type() const
Get rules that target a specific operation type.
size_t get_rule_count() const
Get the total number of rules in the grammar.
void clear_all_rules()
Clear all rules from the grammar.
std::vector< std::string > get_all_rule_names() const
Get all rule names in the grammar.
std::vector< std::string > get_rules_by_context(ComputationContext context) const
Get all rule names for a specific computation context.
bool has_rule(const std::string &rule_name) const
Check if a rule with the given name exists.
void add_operation_rule(const std::string &rule_name, ComputationContext context, UniversalMatcher::MatcherFunc matcher, const std::unordered_map< std::string, std::any > &op_parameters={}, int priority=50, OpArgs &&... op_args)
Helper to add concrete operation rules with automatic executor generation.
std::optional< std::any > execute_rule(const std::string &rule_name, const std::any &input, const ExecutionContext &context) const
Execute a specific rule by name.
void add_rule(Rule rule)
Add a rule to the grammar.
std::vector< Rule > m_rules
All rules sorted by priority (highest first)
Core grammar system for rule-based computation in Maya Flux.
std::function< bool(const std::any &, const ExecutionContext &)> MatcherFunc
ComputationContext
Defines the computational contexts in which rules can be applied.
OperationType
Operation categories for organization and discovery.
ExecutionMode
Execution paradigms for operations.
GpuComputeConfig config_from_spec(const Portal::Graphics::ShaderSpec &spec)
Derive a GpuComputeConfig from a ShaderSpec.
std::vector< GpuBufferBinding > bindings_from_spec(const Portal::Graphics::ShaderSpec &spec)
Derive a GpuBufferBinding list from a ShaderSpec.
Complete declarative description of a generated compute shader.
std::optional< Portal::Graphics::ShaderSpec > gpu_spec
When set, executor receives a GPU-backed operation.
ComputationContext context
Computational context this rule operates in.
std::type_index target_operation_type
Type of operation this rule creates (for type-based queries)
int priority
Execution priority (higher values evaluated first)
std::unordered_map< std::string, std::any > default_parameters
Default parameters for the rule's operation.
Executor executor
Function that performs the computation.
std::string description
Human-readable description of what the rule does.
std::string name
Unique identifier for this rule.
std::vector< std::string > tags
Arbitrary tags for categorization and search.
std::vector< std::string > dependencies
Names of rules that must execute before this one.
UniversalMatcher::MatcherFunc matcher
Function that determines if rule applies.
std::function< std::any(const std::any &, const ExecutionContext &)> Executor
Type alias for matcher functions used in computation rules.
Represents a computation rule with matching and execution logic.
std::unordered_map< std::string, std::any > execution_metadata
Arbitrary metadata parameters used by operations.
Context information controlling how a compute operation executes.