ryo_mutations/idiom/
introduce_variable.rs1use ryo_source::pure::PureExpr;
19use ryo_symbol::SymbolId;
20
21use crate::Mutation;
22
23#[derive(Debug, Clone)]
25pub struct IntroduceVariableMutation {
26 pub target_expr: PureExpr,
28 pub var_name: String,
30 pub target_fn: Option<SymbolId>,
32 pub is_mut: bool,
34}
35
36impl IntroduceVariableMutation {
37 pub fn new(target_expr: PureExpr, var_name: impl Into<String>) -> Self {
38 Self {
39 target_expr,
40 var_name: var_name.into(),
41 target_fn: None,
42 is_mut: false,
43 }
44 }
45
46 pub fn in_function(mut self, id: SymbolId) -> Self {
48 self.target_fn = Some(id);
49 self
50 }
51
52 pub fn mutable(mut self) -> Self {
54 self.is_mut = true;
55 self
56 }
57}
58
59impl Mutation for IntroduceVariableMutation {
60 fn describe(&self) -> String {
61 format!("Introduce variable '{}'", self.var_name)
62 }
63
64 fn mutation_type(&self) -> &'static str {
65 "IntroduceVariable"
66 }
67
68 fn box_clone(&self) -> Box<dyn Mutation> {
69 Box::new(self.clone())
70 }
71}
72
73#[derive(Debug, Clone, Default)]
75pub struct FindDuplicateExpressions {
76 pub min_complexity: usize,
78 pub min_occurrences: usize,
80}
81
82impl FindDuplicateExpressions {
83 pub fn new() -> Self {
84 Self {
85 min_complexity: 3,
86 min_occurrences: 2,
87 }
88 }
89
90 pub fn complexity(expr: &PureExpr) -> usize {
92 let mut count = 1;
93 match expr {
94 PureExpr::Binary { left, right, .. } => {
95 count += Self::complexity(left) + Self::complexity(right);
96 }
97 PureExpr::Unary { expr: inner, .. } => {
98 count += Self::complexity(inner);
99 }
100 PureExpr::Call { func, args } => {
101 count += Self::complexity(func);
102 for arg in args {
103 count += Self::complexity(arg);
104 }
105 }
106 PureExpr::MethodCall { receiver, args, .. } => {
107 count += Self::complexity(receiver);
108 for arg in args {
109 count += Self::complexity(arg);
110 }
111 }
112 PureExpr::Field { expr: inner, .. } => {
113 count += Self::complexity(inner);
114 }
115 PureExpr::Index { expr: inner, index } => {
116 count += Self::complexity(inner) + Self::complexity(index);
117 }
118 _ => {}
119 }
120 count
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127
128 fn make_binary_expr() -> PureExpr {
129 PureExpr::Binary {
131 op: "+".to_string(),
132 left: Box::new(PureExpr::Path("a".to_string())),
133 right: Box::new(PureExpr::Binary {
134 op: "*".to_string(),
135 left: Box::new(PureExpr::Path("b".to_string())),
136 right: Box::new(PureExpr::Path("c".to_string())),
137 }),
138 }
139 }
140
141 #[test]
142 fn test_complexity() {
143 let simple = PureExpr::Path("x".to_string());
144 assert_eq!(FindDuplicateExpressions::complexity(&simple), 1);
145
146 let complex = make_binary_expr();
147 assert_eq!(FindDuplicateExpressions::complexity(&complex), 5); }
149}