From 7a2150f5063dc2aeca67f3a0b5985aab8dfa6aa0 Mon Sep 17 00:00:00 2001 From: YehorBoiar Date: Fri, 4 Oct 2024 15:25:51 +0100 Subject: [PATCH] Added docstring to rewrite and Reduction --- conjure_oxide/src/main.rs | 29 ++++++- .../conjure_core/src/rule_engine/rewrite.rs | 84 +++++++++++++++++-- crates/conjure_core/src/rule_engine/rule.rs | 35 +++++++- 3 files changed, 139 insertions(+), 9 deletions(-) diff --git a/conjure_oxide/src/main.rs b/conjure_oxide/src/main.rs index 6347e809de..c4b6c2412a 100644 --- a/conjure_oxide/src/main.rs +++ b/conjure_oxide/src/main.rs @@ -214,8 +214,8 @@ pub fn main() -> AnyhowResult<()> { #[cfg(test)] mod tests { - use conjure_oxide::{get_example_model, get_example_model_by_path}; - + use conjure_core::{rule_engine::rewrite_model, Model}; + use conjure_oxide::{get_example_model, get_example_model_by_path, RuleSet}; #[test] fn test_get_example_model_success() { let filename = "input"; @@ -239,4 +239,29 @@ mod tests { let filepath = ""; get_example_model_by_path(filepath).unwrap_err(); } + + #[test] + fn test_rewrite_model() { + let model = Model::new(); + let ruleset = RuleSet::default(); + + // Call the `rewrite_model` function with the created model and ruleset + let result = rewrite_model(&model, &vec![&ruleset]); + + // Assert that the rewrite was successful and the model has been modified as expected + match result { + Ok(updated_model) => { + assert_eq!( + updated_model.constraints, 2, + "The model should be updated with new constraint values" + ); + assert_eq!( + updated_model.context.read().unwrap().stats.rewriter_runs, + 1, + "The stats should reflect that one rewrite operation occurred" + ); + } + Err(_) => panic!("Rewrite failed unexpectedly"), + } + } } diff --git a/crates/conjure_core/src/rule_engine/rewrite.rs b/crates/conjure_core/src/rule_engine/rewrite.rs index 90b42dc13c..4ac0dd4a66 100644 --- a/crates/conjure_core/src/rule_engine/rewrite.rs +++ b/crates/conjure_core/src/rule_engine/rewrite.rs @@ -52,12 +52,52 @@ fn optimizations_enabled() -> bool { } } -/// Rewrites the model by applying the rules to all constraints. +/// Rewrites the given model by applying a set of rules to all its constraints. /// -/// Any side-effects such as symbol table updates and top-level constraints are applied to the returned model. +/// This function iteratively applies transformations to the model's constraints using the specified rule sets. +/// It returns a modified version of the model with all applicable rules applied, ensuring that any side-effects +/// such as updates to the symbol table and top-level constraints are properly reflected in the returned model. +/// +/// # Parameters +/// - `model`: A reference to the [`Model`] to be rewritten. The function will clone this model to produce a modified version. +/// - `rule_sets`: A vector of references to [`RuleSet`]s that define the rules to be applied to the model's constraints. +/// Each `RuleSet` is expected to contain a collection of rules that can transform one or more constraints +/// within the model. The lifetime parameter `'a` ensures that the rules' references are valid for the +/// duration of the function execution. /// /// # Returns -/// A copy of the model after all, if any, possible rules are applied to its constraints. +/// - `Ok(Model)`: If successful, it returns a modified copy of the [`Model`] after all applicable rules have been +/// applied. This new model includes any side-effects such as updates to the symbol table or modifications +/// to the constraints. +/// - `Err(RewriteError)`: If an error occurs during rule application (e.g., invalid rules or failed constraints), +/// it returns a [`RewriteError`] with details about the failure. +/// +/// # Side-Effects +/// - When the model is rewritten, related data structures such as the symbol table (which tracks variable names and types) +/// or other top-level constraints may also be updated to reflect these changes. These updates are applied to the returned model, +/// ensuring that all related components stay consistent and aligned with the changes made during the rewrite. +/// - The function collects statistics about the rewriting process, including the number of rule applications +/// and the total runtime of the rewriter. These statistics are then stored in the model's context for +/// performance monitoring and analysis. +/// +/// # Example +/// ``` +/// // Add an example +/// ``` +/// +/// # Performance Considerations +/// - The function checks if optimizations are enabled before applying rules, which may affect the performance +/// of the rewriting process. +/// - Depending on the size of the model and the number of rules, the rewriting process might take a significant +/// amount of time. Use the statistics collected (`rewriter_run_time` and `rewriter_rule_application_attempts`) +/// to monitor and optimize performance. +/// +/// # Panics +/// - This function may panic if the model's context is unavailable or if there is an issue with locking the context. +/// +/// # See Also +/// - [`get_rule_priorities`]: Retrieves the priorities for the given rules. +/// - [`rewrite_iteration`]: Executes a single iteration of rewriting the model using the specified rules. pub fn rewrite_model<'a>( model: &Model, rule_sets: &Vec<&'a RuleSet<'a>>, @@ -91,9 +131,43 @@ pub fn rewrite_model<'a>( Ok(new_model) } +/// Attempts to apply a set of rules to the given expression and its sub-expressions in the model. +/// +/// This function recursively traverses the provided expression, applying any applicable rules from the given set. +/// If a rule is successfully applied to the expression or any of its sub-expressions, it returns a `Reduction` +/// containing the new expression, modified top-level constraints, and any changes to symbols. If no rules can be +/// applied at any level, it returns `None`. +/// +/// # Parameters +/// - `expression`: A reference to the [`Expression`] to be rewritten. This is the main expression that the function +/// attempts to modify using the given rules. +/// - `model`: A reference to the [`Model`] that provides context and additional constraints for evaluating the rules. +/// - `rules`: A vector of references to [`Rule`]s that define the transformations to apply to the expression. +/// - `apply_optimizations`: A boolean flag that indicates whether optimization checks should be applied during the rewriting process. +/// If `true`, the function skips already "clean" (fully optimized or processed) expressions and marks them accordingly +/// to avoid redundant work. +/// - `stats`: A mutable reference to [`RewriterStats`] to collect statistics about the rule application process, such as +/// the number of rules applied and the time taken for each iteration. +/// /// # Returns -/// - Some() after applying the first applicable rule to `expr` or a sub-expression. -/// - None if no rule is applicable to the expression or any sub-expression. +/// - `Some()`: A [`Reduction`] containing the new expression and any associated modifications if a rule was applied +/// to `expr` or one of its sub-expressions. +/// - `None`: If no rule is applicable to the expression or any of its sub-expressions. +/// +/// # Side-Effects +/// - If `apply_optimizations` is enabled, the function will skip "clean" expressions and mark successfully rewritten +/// expressions as "dirty". This is done to avoid unnecessary recomputation of expressions that have already been +/// optimized or processed. +/// +/// # Example +/// ``` +/// // Add an example +/// ``` +/// +/// # Notes +/// - This function works recursively, meaning it traverses all sub-expressions within the given `expression` to find the +/// first rule that can be applied. If a rule is applied, it immediately returns the modified expression and stops +/// further traversal for that branch. fn rewrite_iteration<'a>( expression: &'a Expression, model: &'a Model, diff --git a/crates/conjure_core/src/rule_engine/rule.rs b/crates/conjure_core/src/rule_engine/rule.rs index 224d3c6c2c..99a698429f 100644 --- a/crates/conjure_core/src/rule_engine/rule.rs +++ b/crates/conjure_core/src/rule_engine/rule.rs @@ -16,9 +16,40 @@ pub enum ApplicationError { DomainError, } -/// The result of applying a rule to an expression. +/// Represents the result of applying a rule to an expression within a model. +/// +/// A `Reduction` encapsulates the changes made to a model during a rule application. +/// It includes a new expression to replace the original one, an optional top-level constraint +/// to be added to the model, and any updates to the model's symbol table. +/// +/// This struct allows for representing side-effects of rule applications, ensuring that +/// all modifications, including symbol table expansions and additional constraints, are +/// accounted for and can be applied to the model consistently. +/// +/// # Fields +/// - `new_expression`: The updated [`Expression`] that replaces the original one after applying the rule. +/// - `new_top`: An additional top-level [`Expression`] constraint that should be added to the model. If no top-level +/// constraint is needed, this field can be set to `Expression::Nothing`. +/// - `symbols`: A [`SymbolTable`] containing any new symbol definitions or modifications to be added to the model's +/// symbol table. If no symbols are modified, this field can be set to an empty symbol table. +/// +/// # Usage +/// A `Reduction` can be created using one of the provided constructors: +/// - [`Reduction::new`]: Creates a reduction with a new expression, top-level constraint, and symbol modifications. +/// - [`Reduction::pure`]: Creates a reduction with only a new expression and no side-effects on the symbol table or constraints. +/// - [`Reduction::with_symbols`]: Creates a reduction with a new expression and symbol table modifications, but no top-level constraint. +/// - [`Reduction::with_top`]: Creates a reduction with a new expression and a top-level constraint, but no symbol table modifications. +/// +/// The `apply` method allows for applying the changes represented by the `Reduction` to a [`Model`]. +/// +/// # Example +/// ``` +/// // Need to add an example +/// ``` /// -/// Contains an expression to replace the original, a top-level constraint to add to the top of the constraint AST, and an expansion to the model symbol table. +/// # See Also +/// - [`ApplicationResult`]: Represents the result of applying a rule, which may either be a `Reduction` or an `ApplicationError`. +/// - [`Model`]: The structure to which the `Reduction` changes are applied. #[non_exhaustive] #[derive(Clone, Debug)] pub struct Reduction {