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 is_mut: false,
74 pat: None,
75 })
76 .collect(),
77 ret: self
78 .return_type
79 .as_ref()
80 .map(|ty| PureType::Path(ty.clone())),
81 body: PureBlock {
82 stmts: vec![PureStmt::Expr(PureExpr::Other(self.body.clone()))],
83 },
84 attrs: Vec::new(),
85 abi: None,
86 };
87
88 let fn_path = match parent_path.child(&self.name) {
90 Ok(p) => p,
91 Err(_) => {
92 return MutationResult {
93 mutation_type: "AddFunction".to_string(),
94 changes: 0,
95 description: format!("Failed to create path for function '{}'", self.name),
96 };
97 }
98 };
99
100 match ctx.symbol_registry.register(fn_path, SymbolKind::Function) {
101 Ok(fn_id) => {
102 ctx.ast_registry.set(fn_id, PureItem::Fn(func));
103 MutationResult {
104 mutation_type: "AddFunction".to_string(),
105 changes: 1,
106 description: format!("Added function '{}' to module {}", self.name, module_id),
107 }
108 }
109 Err(e) => MutationResult {
110 mutation_type: "AddFunction".to_string(),
111 changes: 0,
112 description: format!("Failed to register function '{}': {:?}", self.name, e),
113 },
114 }
115 }
116}
117
118impl ASTRegApply for RemoveFunctionMutation {
119 fn apply_to_registry(&self, ctx: &mut ASTMutationContext) -> MutationResult {
120 let fn_id = self.symbol_id;
122
123 if ctx.symbol_registry.kind(fn_id) != Some(SymbolKind::Function) {
125 return MutationResult {
126 mutation_type: "RemoveFunction".to_string(),
127 changes: 0,
128 description: format!("Symbol {} is not a function", fn_id),
129 };
130 }
131
132 ctx.ast_registry.remove(fn_id);
134
135 MutationResult {
136 mutation_type: "RemoveFunction".to_string(),
137 changes: 1,
138 description: format!("Removed function {}", fn_id),
139 }
140 }
141}