ryo_executor/engine/impls/
function.rs1use ryo_mutations::basic::{AddFunctionMutation, RemoveFunctionMutation};
4use ryo_mutations::MutationResult;
5use ryo_source::pure::{
6 PureBlock, PureExpr, PureFn, PureGenerics, PureItem, PureParam, PureStmt, PureType, PureVis,
7};
8use ryo_symbol::SymbolKind;
9
10use crate::engine::{ASTMutationContext, ASTRegApply};
11
12impl ASTRegApply for AddFunctionMutation {
13 fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
14 let module_id = self.parent;
16
17 if ctx.symbol_registry.kind(module_id) != Some(SymbolKind::Mod) {
19 return MutationResult {
20 mutation_type: "AddFunction".to_string(),
21 changes: 0,
22 description: format!("Target symbol {} is not a module", module_id),
23 };
24 }
25
26 let parent_path = match ctx.symbol_registry.path(module_id) {
28 Some(p) => p,
29 None => {
30 return MutationResult {
31 mutation_type: "AddFunction".to_string(),
32 changes: 0,
33 description: format!("Module {} not found in registry", module_id),
34 };
35 }
36 };
37
38 let exists = ctx
39 .symbol_registry
40 .iter()
41 .filter(|(id, _)| ctx.symbol_registry.kind(*id) == Some(SymbolKind::Function))
42 .any(|(_, path)| {
43 path.parent().as_ref() == Some(parent_path) && path.name() == self.name
44 });
45
46 if exists {
47 return MutationResult {
48 mutation_type: "AddFunction".to_string(),
49 changes: 0,
50 description: format!("Function '{}' already exists in module", self.name),
51 };
52 }
53
54 let func = PureFn {
56 name: self.name.clone(),
57 vis: if self.is_pub {
58 PureVis::Public
59 } else {
60 PureVis::Private
61 },
62 is_async: false,
63 is_async_inferred: false,
64 is_const: false,
65 is_unsafe: false,
66 generics: PureGenerics::default(),
67 params: self
68 .params
69 .iter()
70 .map(|(name, ty)| PureParam::Typed {
71 name: name.clone(),
72 ty: PureType::Path(ty.clone()),
73 })
74 .collect(),
75 ret: self
76 .return_type
77 .as_ref()
78 .map(|ty| PureType::Path(ty.clone())),
79 body: PureBlock {
80 stmts: vec![PureStmt::Expr(PureExpr::Other(self.body.clone()))],
81 },
82 attrs: Vec::new(),
83 abi: None,
84 };
85
86 let fn_path = match parent_path.child(&self.name) {
88 Ok(p) => p,
89 Err(_) => {
90 return MutationResult {
91 mutation_type: "AddFunction".to_string(),
92 changes: 0,
93 description: format!("Failed to create path for function '{}'", self.name),
94 };
95 }
96 };
97
98 match ctx.symbol_registry.register(fn_path, SymbolKind::Function) {
99 Ok(fn_id) => {
100 ctx.ast_registry.set(fn_id, PureItem::Fn(func));
101 MutationResult {
102 mutation_type: "AddFunction".to_string(),
103 changes: 1,
104 description: format!("Added function '{}' to module {}", self.name, module_id),
105 }
106 }
107 Err(e) => MutationResult {
108 mutation_type: "AddFunction".to_string(),
109 changes: 0,
110 description: format!("Failed to register function '{}': {:?}", self.name, e),
111 },
112 }
113 }
114}
115
116impl ASTRegApply for RemoveFunctionMutation {
117 fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
118 let fn_id = self.symbol_id;
120
121 if ctx.symbol_registry.kind(fn_id) != Some(SymbolKind::Function) {
123 return MutationResult {
124 mutation_type: "RemoveFunction".to_string(),
125 changes: 0,
126 description: format!("Symbol {} is not a function", fn_id),
127 };
128 }
129
130 ctx.ast_registry.remove(fn_id);
132
133 MutationResult {
134 mutation_type: "RemoveFunction".to_string(),
135 changes: 1,
136 description: format!("Removed function {}", fn_id),
137 }
138 }
139}