Skip to main content

ryo_executor/engine/impls/
struct_def.rs

1//! ASTRegApply implementation for struct mutations
2
3use ryo_mutations::basic::{AddStructMutation, RemoveStructMutation};
4use ryo_mutations::MutationResult;
5use ryo_source::pure::{
6    PureAttrMeta, PureAttribute, PureField, PureFields, PureGenerics, PureItem, PureStruct,
7    PureType, PureVis,
8};
9use ryo_symbol::SymbolKind;
10
11use crate::engine::{ASTMutationContext, ASTRegApply};
12
13impl ASTRegApply for AddStructMutation {
14    fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
15        // Use the provided parent SymbolId
16        let module_id = self.parent;
17
18        // Verify the parent is a module
19        if ctx.symbol_registry.kind(module_id) != Some(SymbolKind::Mod) {
20            return MutationResult {
21                mutation_type: "AddStruct".to_string(),
22                changes: 0,
23                description: format!("Symbol {} is not a module", module_id),
24            };
25        }
26
27        // Check if struct already exists
28        let exists = ctx
29            .symbol_registry
30            .iter()
31            .filter(|(id, _)| ctx.symbol_registry.kind(*id) == Some(SymbolKind::Struct))
32            .any(|(_, path)| path.name() == self.name);
33
34        if exists {
35            return MutationResult {
36                mutation_type: "AddStruct".to_string(),
37                changes: 0,
38                description: format!("Struct '{}' already exists", self.name),
39            };
40        }
41
42        // Create derive attributes
43        let attrs = if !self.derives.is_empty() {
44            vec![PureAttribute {
45                path: "derive".to_string(),
46                meta: PureAttrMeta::List(self.derives.join(", ")),
47                is_inner: false,
48            }]
49        } else {
50            vec![]
51        };
52
53        // Create fields
54        let fields: Vec<PureField> = self
55            .fields
56            .iter()
57            .map(|f| PureField {
58                attrs: vec![],
59                vis: if f.is_pub {
60                    PureVis::Public
61                } else {
62                    PureVis::Private
63                },
64                name: f.name.clone(),
65                ty: PureType::Path(f.ty.clone()),
66            })
67            .collect();
68
69        let struct_item = PureStruct {
70            attrs,
71            vis: if self.is_pub {
72                PureVis::Public
73            } else {
74                PureVis::Private
75            },
76            name: self.name.clone(),
77            generics: PureGenerics::default(),
78            fields: if fields.is_empty() {
79                PureFields::Unit
80            } else {
81                PureFields::Named(fields)
82            },
83        };
84
85        // Register the new struct
86        let struct_path = ctx
87            .symbol_registry
88            .path(module_id)
89            .and_then(|p| p.child(&self.name).ok());
90
91        if let Some(path) = struct_path {
92            if let Ok(struct_id) = ctx.symbol_registry.register(path, SymbolKind::Struct) {
93                ctx.ast_registry
94                    .set(struct_id, PureItem::Struct(struct_item));
95
96                return MutationResult {
97                    mutation_type: "AddStruct".to_string(),
98                    changes: 1,
99                    description: format!("Added struct '{}'", self.name),
100                };
101            }
102        }
103
104        MutationResult {
105            mutation_type: "AddStruct".to_string(),
106            changes: 0,
107            description: format!("Failed to register struct '{}'", self.name),
108        }
109    }
110}
111
112impl ASTRegApply for RemoveStructMutation {
113    fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
114        // Use the provided SymbolId for O(1) access
115        let struct_id = self.struct_id;
116
117        // Verify the struct exists and is a struct
118        if ctx.symbol_registry.kind(struct_id) != Some(SymbolKind::Struct) {
119            return MutationResult {
120                mutation_type: "RemoveStruct".to_string(),
121                changes: 0,
122                description: format!("Symbol {} is not a struct", struct_id),
123            };
124        }
125
126        ctx.ast_registry.remove(struct_id);
127
128        MutationResult {
129            mutation_type: "RemoveStruct".to_string(),
130            changes: 1,
131            description: format!("Removed struct {}", struct_id),
132        }
133    }
134}