1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// C++ Pointer and Member Access Mutations: POR, MAR
// Included from cpp_tree_sitter_mutations.rs
// ============================================================
// 6. POINTER OPERATOR REPLACEMENT (POR) - C++ SPECIFIC
// ============================================================
/// C++ Pointer Operator Mutation (POR - Pointer Operator Replacement)
/// Handles pointer-specific operators: *, &, ->
pub struct CppPointerOpMutation;
impl TreeSitterMutationOperator for CppPointerOpMutation {
fn name(&self) -> &str {
"CppPointerOp"
}
fn can_mutate(&self, node: &Node, _source: &[u8]) -> bool {
match node.kind() {
"pointer_expression" => true, // * or & in expression context
"field_expression" => {
// Check if it's an arrow operator
let mut cursor = node.walk();
for child in node.children(&mut cursor) {
if child.kind() == "->" {
return true;
}
}
false
}
_ => false,
}
}
fn mutate(&self, node: &Node, source: &[u8]) -> Vec<MutatedSource> {
if node.kind() == "pointer_expression" {
// Find the operator (* or &)
let mut cursor = node.walk();
let mut operator_node = None;
for child in node.children(&mut cursor) {
let kind = child.kind();
if matches!(kind, "*" | "&") {
operator_node = Some(child);
break;
}
}
let operator_node = match operator_node {
Some(n) => n,
None => return vec![],
};
let op_bytes = &source[operator_node.byte_range()];
let _op_text = std::str::from_utf8(op_bytes).unwrap_or("");
// For pointer operators, mutation is tricky
// * (dereference) and & (address-of) can't be simply swapped
// We'll skip mutation for now to avoid semantic errors
return vec![];
}
if node.kind() == "field_expression" {
// Find the -> operator
let mut cursor = node.walk();
let mut operator_node = None;
for child in node.children(&mut cursor) {
if child.kind() == "->" {
operator_node = Some(child);
break;
}
}
let _operator_node = match operator_node {
Some(n) => n,
None => return vec![],
};
// Mutating -> to . would require (*ptr).member
// This is semantically equivalent but syntactically complex
// Skip mutation for now
return vec![];
}
vec![]
}
}
// ============================================================
// 7. MEMBER ACCESS REPLACEMENT (MAR) - C++ SPECIFIC
// ============================================================
/// C++ Member Access Mutation (MAR - Member Access Replacement)
/// Handles member access operators: ., ::
pub struct CppMemberAccessMutation;
impl TreeSitterMutationOperator for CppMemberAccessMutation {
fn name(&self) -> &str {
"CppMemberAccess"
}
fn can_mutate(&self, node: &Node, _source: &[u8]) -> bool {
match node.kind() {
"field_expression" => {
let mut cursor = node.walk();
for child in node.children(&mut cursor) {
if child.kind() == "." {
return true;
}
}
false
}
"qualified_identifier" => {
let mut cursor = node.walk();
for child in node.children(&mut cursor) {
if child.kind() == "::" {
return true;
}
}
false
}
_ => false,
}
}
fn mutate(&self, _node: &Node, _source: &[u8]) -> Vec<MutatedSource> {
// Member access mutations are semantically complex
// . and :: have different meanings (instance vs static/namespace)
// Can't mutate without type information
// Skip mutation for now
vec![]
}
}