ryo-executor 0.1.0

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

use ryo_mutations::basic::{AddEnumMutation, RemoveEnumMutation};
use ryo_mutations::MutationResult;
use ryo_source::pure::{
    PureAttrMeta, PureAttribute, PureEnum, PureGenerics, PureItem, PureVariant, PureVis,
};
use ryo_symbol::SymbolKind;

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

impl ASTRegApply for AddEnumMutation {
    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: "AddEnum".to_string(),
                changes: 0,
                description: format!("Target symbol {:?} is not a module", module_id),
            };
        }

        // Check if enum already exists in this module
        let parent_path = match ctx.symbol_registry.path(module_id) {
            Some(p) => p,
            None => {
                return MutationResult {
                    mutation_type: "AddEnum".to_string(),
                    changes: 0,
                    description: format!("Module {:?} not found in registry", module_id),
                };
            }
        };

        let exists = ctx
            .symbol_registry
            .iter()
            .filter(|(id, _)| ctx.symbol_registry.kind(*id) == Some(SymbolKind::Enum))
            .any(|(_, path)| {
                path.parent().as_ref() == Some(parent_path) && path.name() == self.name
            });

        if exists {
            return MutationResult {
                mutation_type: "AddEnum".to_string(),
                changes: 0,
                description: format!("Enum '{}' already exists in module", self.name),
            };
        }

        // Create derive attributes
        let attrs = if !self.derives.is_empty() {
            vec![PureAttribute {
                path: "derive".to_string(),
                meta: PureAttrMeta::List(self.derives.join(", ")),
                is_inner: false,
            }]
        } else {
            vec![]
        };

        // Create variants
        let variants: Vec<PureVariant> = self
            .variants
            .iter()
            .map(|(name, fields)| PureVariant {
                attrs: vec![],
                name: name.clone(),
                fields: fields.clone(),
                discriminant: None,
            })
            .collect();

        let enum_item = PureEnum {
            attrs,
            vis: if self.is_pub {
                PureVis::Public
            } else {
                PureVis::Private
            },
            name: self.name.clone(),
            generics: PureGenerics::default(),
            variants,
        };

        // Register the new enum
        let enum_path = match parent_path.child(&self.name) {
            Ok(p) => p,
            Err(_) => {
                return MutationResult {
                    mutation_type: "AddEnum".to_string(),
                    changes: 0,
                    description: format!("Failed to create path for enum '{}'", self.name),
                };
            }
        };

        match ctx.symbol_registry.register(enum_path, SymbolKind::Enum) {
            Ok(enum_id) => {
                ctx.ast_registry.set(enum_id, PureItem::Enum(enum_item));
                MutationResult {
                    mutation_type: "AddEnum".to_string(),
                    changes: 1,
                    description: format!("Added enum '{}' to module {:?}", self.name, module_id),
                }
            }
            Err(e) => MutationResult {
                mutation_type: "AddEnum".to_string(),
                changes: 0,
                description: format!("Failed to register enum '{}': {:?}", self.name, e),
            },
        }
    }
}

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

        // Verify the target is an enum
        if ctx.symbol_registry.kind(enum_id) != Some(SymbolKind::Enum) {
            return MutationResult {
                mutation_type: "RemoveEnum".to_string(),
                changes: 0,
                description: format!("Symbol {:?} is not an enum", enum_id),
            };
        }

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

        MutationResult {
            mutation_type: "RemoveEnum".to_string(),
            changes: 1,
            description: format!("Removed enum {:?}", enum_id),
        }
    }
}