Skip to main content

ryo_executor/engine/impls/
variant.rs

1//! ASTRegApply implementation for variant mutations
2
3use ryo_mutations::basic::{AddVariantMutation, RemoveVariantMutation};
4use ryo_mutations::MutationResult;
5use ryo_source::pure::{PureItem, PureVariant};
6
7use crate::engine::{ASTMutationContext, ASTRegApply, ModificationType, MutationEvent};
8
9impl ASTRegApply for AddVariantMutation {
10    fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
11        let target_id = self.enum_id;
12
13        // Get the AST for this symbol
14        let item = match ctx.ast_registry.get(target_id) {
15            Some(item) => item.clone(),
16            None => {
17                return MutationResult {
18                    mutation_type: "AddVariant".to_string(),
19                    changes: 0,
20                    description: format!("AST not found for {:?}", target_id),
21                };
22            }
23        };
24
25        // Modify the item
26        let new_item = match item {
27            PureItem::Enum(mut e) => {
28                // Check if variant already exists
29                if e.variants.iter().any(|v| v.name == self.variant_name) {
30                    return MutationResult {
31                        mutation_type: "AddVariant".to_string(),
32                        changes: 0,
33                        description: format!(
34                            "Variant '{}' already exists in {:?}",
35                            self.variant_name, target_id
36                        ),
37                    };
38                }
39
40                e.variants.push(PureVariant {
41                    attrs: Vec::new(),
42                    name: self.variant_name.clone(),
43                    fields: self.fields.clone(),
44                    discriminant: None,
45                });
46                PureItem::Enum(e)
47            }
48            _ => {
49                return MutationResult {
50                    mutation_type: "AddVariant".to_string(),
51                    changes: 0,
52                    description: format!("{:?} is not an enum", target_id),
53                };
54            }
55        };
56
57        // Update the registry
58        ctx.set_ast(target_id, new_item);
59
60        // Emit event
61        ctx.emit(MutationEvent::SymbolModified {
62            id: target_id,
63            modification: ModificationType::VariantAdded(self.variant_name.clone()),
64        });
65
66        MutationResult {
67            mutation_type: "AddVariant".to_string(),
68            changes: 1,
69            description: format!("Added variant '{}' to {:?}", self.variant_name, target_id),
70        }
71    }
72}
73
74impl ASTRegApply for RemoveVariantMutation {
75    fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
76        let target_id = self.enum_id;
77
78        // Get the AST for this symbol
79        let item = match ctx.ast_registry.get(target_id) {
80            Some(item) => item.clone(),
81            None => {
82                return MutationResult {
83                    mutation_type: "RemoveVariant".to_string(),
84                    changes: 0,
85                    description: format!("AST not found for {:?}", target_id),
86                };
87            }
88        };
89
90        // Modify the item
91        let (new_item, removed) = match item {
92            PureItem::Enum(mut e) => {
93                let original_len = e.variants.len();
94                e.variants.retain(|v| v.name != self.variant_name);
95                let removed = e.variants.len() < original_len;
96                (PureItem::Enum(e), removed)
97            }
98            _ => {
99                return MutationResult {
100                    mutation_type: "RemoveVariant".to_string(),
101                    changes: 0,
102                    description: format!("{:?} is not an enum", target_id),
103                };
104            }
105        };
106
107        if removed {
108            // Update the registry
109            ctx.set_ast(target_id, new_item);
110
111            // Emit event
112            ctx.emit(MutationEvent::SymbolModified {
113                id: target_id,
114                modification: ModificationType::VariantRemoved(self.variant_name.clone()),
115            });
116        }
117
118        MutationResult {
119            mutation_type: "RemoveVariant".to_string(),
120            changes: if removed { 1 } else { 0 },
121            description: if removed {
122                format!(
123                    "Removed variant '{}' from {:?}",
124                    self.variant_name, target_id
125                )
126            } else {
127                format!(
128                    "Variant '{}' not found in {:?}",
129                    self.variant_name, target_id
130                )
131            },
132        }
133    }
134}