ryo-executor 0.1.0

[experimental] Mutation execution engine for RYO - parallel execution, conflict detection, workspace management
Documentation
//! ASTRegApply implementation for impl block mutations

use ryo_mutations::basic::{AddImplMutation, RemoveImplMutation};
use ryo_mutations::MutationResult;
use ryo_source::pure::{PureGenerics, PureImpl, PureItem};
use ryo_symbol::SymbolKind;

use crate::engine::{ASTMutationContext, ASTRegApply};

impl ASTRegApply for AddImplMutation {
    fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
        // Use the provided symbol_id as the parent module
        let module_id = self.parent;

        // Verify the target is a module
        if ctx.symbol_registry.kind(module_id) != Some(SymbolKind::Mod) {
            return MutationResult {
                mutation_type: "AddImpl".to_string(),
                changes: 0,
                description: format!("Target symbol {} is not a module", module_id),
            };
        }

        // Create the impl block
        let impl_item = PureImpl {
            attrs: vec![],
            generics: PureGenerics::default(),
            is_unsafe: false,
            trait_: self.trait_name.clone(),
            self_ty: self.target.clone(),
            items: vec![],
        };

        // Register impl - name format: <impl Type> or <impl Trait for Type>
        let impl_name = if let Some(trait_name) = &self.trait_name {
            format!("<impl {} for {}>", trait_name, self.target)
        } else {
            format!("<impl {}>", self.target)
        };

        let parent_path = match ctx.symbol_registry.path(module_id) {
            Some(p) => p,
            None => {
                return MutationResult {
                    mutation_type: "AddImpl".to_string(),
                    changes: 0,
                    description: format!("Module {} not found in registry", module_id),
                };
            }
        };

        let impl_path = match parent_path.child(&impl_name) {
            Ok(p) => p,
            Err(_) => {
                return MutationResult {
                    mutation_type: "AddImpl".to_string(),
                    changes: 0,
                    description: format!("Failed to create path for impl '{}'", impl_name),
                };
            }
        };

        match ctx.symbol_registry.register(impl_path, SymbolKind::Impl) {
            Ok(impl_id) => {
                ctx.ast_registry
                    .set(impl_id, PureItem::Impl(impl_item.clone()));

                // Add to module_items for file generation
                let mut items = ctx
                    .ast_registry
                    .get_module_items(module_id)
                    .cloned()
                    .unwrap_or_default();
                items.push(PureItem::Impl(impl_item));
                ctx.ast_registry.set_module_items(module_id, items);

                MutationResult {
                    mutation_type: "AddImpl".to_string(),
                    changes: 1,
                    description: format!("Added impl {} to module {}", impl_name, module_id),
                }
            }
            Err(e) => MutationResult {
                mutation_type: "AddImpl".to_string(),
                changes: 0,
                description: format!("Failed to register impl '{}': {:?}", impl_name, e),
            },
        }
    }
}

impl ASTRegApply for RemoveImplMutation {
    fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
        // Use the provided symbol_id directly
        let impl_id = self.symbol_id;

        // Verify the target is an impl block
        if ctx.symbol_registry.kind(impl_id) != Some(SymbolKind::Impl) {
            return MutationResult {
                mutation_type: "RemoveImpl".to_string(),
                changes: 0,
                description: format!("Symbol {} is not an impl block", impl_id),
            };
        }

        // Remove from AST registry
        ctx.ast_registry.remove(impl_id);

        MutationResult {
            mutation_type: "RemoveImpl".to_string(),
            changes: 1,
            description: format!("Removed impl block {}", impl_id),
        }
    }
}