ryo-executor 0.1.0

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

use ryo_mutations::basic::{AddStructMutation, RemoveStructMutation};
use ryo_mutations::MutationResult;
use ryo_source::pure::{
    PureAttrMeta, PureAttribute, PureField, PureFields, PureGenerics, PureItem, PureStruct,
    PureType, PureVis,
};
use ryo_symbol::SymbolKind;

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

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

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

        // Check if struct already exists
        let exists = ctx
            .symbol_registry
            .iter()
            .filter(|(id, _)| ctx.symbol_registry.kind(*id) == Some(SymbolKind::Struct))
            .any(|(_, path)| path.name() == self.name);

        if exists {
            return MutationResult {
                mutation_type: "AddStruct".to_string(),
                changes: 0,
                description: format!("Struct '{}' already exists", 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 fields
        let fields: Vec<PureField> = self
            .fields
            .iter()
            .map(|f| PureField {
                attrs: vec![],
                vis: if f.is_pub {
                    PureVis::Public
                } else {
                    PureVis::Private
                },
                name: f.name.clone(),
                ty: PureType::Path(f.ty.clone()),
            })
            .collect();

        let struct_item = PureStruct {
            attrs,
            vis: if self.is_pub {
                PureVis::Public
            } else {
                PureVis::Private
            },
            name: self.name.clone(),
            generics: PureGenerics::default(),
            fields: if fields.is_empty() {
                PureFields::Unit
            } else {
                PureFields::Named(fields)
            },
        };

        // Register the new struct
        let struct_path = ctx
            .symbol_registry
            .path(module_id)
            .and_then(|p| p.child(&self.name).ok());

        if let Some(path) = struct_path {
            if let Ok(struct_id) = ctx.symbol_registry.register(path, SymbolKind::Struct) {
                ctx.ast_registry
                    .set(struct_id, PureItem::Struct(struct_item));

                return MutationResult {
                    mutation_type: "AddStruct".to_string(),
                    changes: 1,
                    description: format!("Added struct '{}'", self.name),
                };
            }
        }

        MutationResult {
            mutation_type: "AddStruct".to_string(),
            changes: 0,
            description: format!("Failed to register struct '{}'", self.name),
        }
    }
}

impl ASTRegApply for RemoveStructMutation {
    fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
        // Use the provided SymbolId for O(1) access
        let struct_id = self.struct_id;

        // Verify the struct exists and is a struct
        if ctx.symbol_registry.kind(struct_id) != Some(SymbolKind::Struct) {
            return MutationResult {
                mutation_type: "RemoveStruct".to_string(),
                changes: 0,
                description: format!("Symbol {} is not a struct", struct_id),
            };
        }

        ctx.ast_registry.remove(struct_id);

        MutationResult {
            mutation_type: "RemoveStruct".to_string(),
            changes: 1,
            description: format!("Removed struct {}", struct_id),
        }
    }
}