Skip to main content

ryo_executor/engine/impls/
impl_block.rs

1//! ASTRegApply implementation for impl block mutations
2
3use ryo_mutations::basic::{AddImplMutation, RemoveImplMutation};
4use ryo_mutations::MutationResult;
5use ryo_source::pure::{PureGenerics, PureImpl, PureItem};
6use ryo_symbol::SymbolKind;
7
8use crate::engine::{ASTMutationContext, ASTRegApply};
9
10impl ASTRegApply for AddImplMutation {
11    fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
12        // Use the provided symbol_id as the parent module
13        let module_id = self.parent;
14
15        // Verify the target is a module
16        if ctx.symbol_registry.kind(module_id) != Some(SymbolKind::Mod) {
17            return MutationResult {
18                mutation_type: "AddImpl".to_string(),
19                changes: 0,
20                description: format!("Target symbol {} is not a module", module_id),
21            };
22        }
23
24        // Create the impl block
25        let impl_item = PureImpl {
26            attrs: vec![],
27            generics: PureGenerics::default(),
28            is_unsafe: false,
29            trait_: self.trait_name.clone(),
30            self_ty: self.target.clone(),
31            items: vec![],
32        };
33
34        // Register impl - name format: <impl Type> or <impl Trait for Type>
35        let impl_name = if let Some(trait_name) = &self.trait_name {
36            format!("<impl {} for {}>", trait_name, self.target)
37        } else {
38            format!("<impl {}>", self.target)
39        };
40
41        let parent_path = match ctx.symbol_registry.path(module_id) {
42            Some(p) => p,
43            None => {
44                return MutationResult {
45                    mutation_type: "AddImpl".to_string(),
46                    changes: 0,
47                    description: format!("Module {} not found in registry", module_id),
48                };
49            }
50        };
51
52        let impl_path = match parent_path.child(&impl_name) {
53            Ok(p) => p,
54            Err(_) => {
55                return MutationResult {
56                    mutation_type: "AddImpl".to_string(),
57                    changes: 0,
58                    description: format!("Failed to create path for impl '{}'", impl_name),
59                };
60            }
61        };
62
63        match ctx.symbol_registry.register(impl_path, SymbolKind::Impl) {
64            Ok(impl_id) => {
65                ctx.ast_registry
66                    .set(impl_id, PureItem::Impl(impl_item.clone()));
67
68                // Add to module_items for file generation
69                let mut items = ctx
70                    .ast_registry
71                    .get_module_items(module_id)
72                    .cloned()
73                    .unwrap_or_default();
74                items.push(PureItem::Impl(impl_item));
75                ctx.ast_registry.set_module_items(module_id, items);
76
77                MutationResult {
78                    mutation_type: "AddImpl".to_string(),
79                    changes: 1,
80                    description: format!("Added impl {} to module {}", impl_name, module_id),
81                }
82            }
83            Err(e) => MutationResult {
84                mutation_type: "AddImpl".to_string(),
85                changes: 0,
86                description: format!("Failed to register impl '{}': {:?}", impl_name, e),
87            },
88        }
89    }
90}
91
92impl ASTRegApply for RemoveImplMutation {
93    fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
94        // Use the provided symbol_id directly
95        let impl_id = self.symbol_id;
96
97        // Verify the target is an impl block
98        if ctx.symbol_registry.kind(impl_id) != Some(SymbolKind::Impl) {
99            return MutationResult {
100                mutation_type: "RemoveImpl".to_string(),
101                changes: 0,
102                description: format!("Symbol {} is not an impl block", impl_id),
103            };
104        }
105
106        // Remove from AST registry
107        ctx.ast_registry.remove(impl_id);
108
109        MutationResult {
110            mutation_type: "RemoveImpl".to_string(),
111            changes: 1,
112            description: format!("Removed impl block {}", impl_id),
113        }
114    }
115}