1 /**
2 Copyright: Copyright (c) 2018, Joakim Brännström. All rights reserved.
3 License: MPL-2
4 Author: Joakim Brännström (joakim.brannstrom@gmx.com)
5 
6 This Source Code Form is subject to the terms of the Mozilla Public License,
7 v.2.0. If a copy of the MPL was not distributed with this file, You can obtain
8 one at http://mozilla.org/MPL/2.0/.
9 
10 #SPC-plugin_mutate_mutation_ror
11 */
12 module dextool.plugin.mutate.backend.mutation_type.ror;
13 
14 import dextool.plugin.mutate.backend.type;
15 import dextool.clang_extensions : OpKind;
16 
17 /** Produce the mutations that can be applied on an operator.
18  *
19  * Params:
20  *  op = the c/c++ operator in the AST
21  *  tyi = type info about the expressions on the sides of the operator
22  *
23  * The resulting schema is intended to be:
24  * normal + pointer - float - enum - bool
25  *
26  * The schema when used is:
27  * ror = normal - float - enum - bool
28  * rorp = pointer - float - enum - bool
29  *
30  * See SPC-plugin_mutate_mutation_ror for the subsumed table.
31  */
32 auto rorMutations(const OpKind op, const OpTypeInfo tyi) @safe pure nothrow {
33     import std.typecons : Tuple, Nullable;
34     import std.algorithm : among;
35 
36     alias Rval = Tuple!(Mutation.Kind[], "op", Mutation.Kind[], "expr");
37 
38     Nullable!Rval rval;
39 
40     with (Mutation.Kind) {
41         if (op.among(OpKind.LT, OpKind.OO_Less)) {
42             rval = Rval([rorLE, rorpLE, rorNE, rorpNE], [rorFalse]);
43         } else if (op.among(OpKind.GT, OpKind.OO_Greater)) {
44             rval = Rval([rorGE, rorpGE, rorNE, rorpNE], [rorFalse]);
45         } else if (op.among(OpKind.LE, OpKind.OO_LessEqual)) {
46             rval = Rval([rorLT, rorpLT, rorEQ, rorpEQ], [rorTrue]);
47         } else if (op.among(OpKind.GE, OpKind.OO_GreaterEqual)) {
48             rval = Rval([rorGT, rorpGT, rorEQ, rorpEQ], [rorTrue]);
49         } else if (op.among(OpKind.EQ, OpKind.OO_EqualEqual)) {
50             rval = Rval([rorLE, rorpLE, rorGE, rorpGE], [rorFalse]);
51         } else if (op.among(OpKind.NE, OpKind.OO_ExclaimEqual)) {
52             rval = Rval([rorLT, rorpLT, rorGT, rorpGT], [rorTrue]);
53         }
54     }
55 
56     // #SPC-plugin_mutate_mutation_ror_float
57     void floatingPointSchema() {
58         with (Mutation.Kind) {
59             if (op.among(OpKind.LT, OpKind.OO_Less)) {
60                 rval.op = [rorGT, rorpGT];
61             } else if (op.among(OpKind.GT, OpKind.OO_Greater)) {
62                 rval.op = [rorLT, rorpLT];
63             } else if (op.among(OpKind.LE, OpKind.OO_LessEqual)) {
64                 rval.op = [rorGT, rorpGT];
65             } else if (op.among(OpKind.GE, OpKind.OO_GreaterEqual)) {
66                 rval.op = [rorLT, rorpLT];
67             }
68         }
69     }
70 
71     // #SPC-plugin_mutate_mutation_ror_enum
72     void enumSchema() {
73         with (Mutation.Kind) {
74             if (op.among(OpKind.EQ, OpKind.OO_EqualEqual)) {
75                 if (tyi == OpTypeInfo.enumLhsIsMin) {
76                     rval.op = [rorLE, rorpLE];
77                 } else if (tyi == OpTypeInfo.enumLhsIsMax) {
78                     rval.op = [rorGE, rorpGE];
79                 } else if (tyi == OpTypeInfo.enumRhsIsMin) {
80                     rval.op = [rorGE, rorpGE];
81                 } else if (tyi == OpTypeInfo.enumRhsIsMax) {
82                     rval.op = [rorLE, rorpLE];
83                 }
84             } else if (op.among(OpKind.NE, OpKind.OO_ExclaimEqual)) {
85                 if (tyi == OpTypeInfo.enumLhsIsMin) {
86                     rval.op = [rorLT, rorpLT];
87                 } else if (tyi == OpTypeInfo.enumLhsIsMax) {
88                     rval.op = [rorGT, rorpGT];
89                 } else if (tyi == OpTypeInfo.enumRhsIsMin) {
90                     rval.op = [rorGT, rorpGT];
91                 } else if (tyi == OpTypeInfo.enumRhsIsMax) {
92                     rval.op = [rorLT, rorpLT];
93                 }
94             }
95         }
96     }
97 
98     // #SPC-plugin_mutate_mutation_ror_ptr
99     void pointerSchema() {
100         with (Mutation.Kind) {
101             if (op.among(OpKind.EQ, OpKind.OO_EqualEqual)) {
102                 rval.op = [rorLE, rorGE, rorpNE];
103             } else if (op.among(OpKind.NE, OpKind.OO_ExclaimEqual)) {
104                 rval.op = [rorLT, rorGT, rorpEQ];
105             }
106         }
107     }
108 
109     // #SPC-plugin_mutate_mutation_ror_bool
110     void boolSchema() {
111         with (Mutation.Kind) {
112             if (op.among(OpKind.EQ, OpKind.OO_EqualEqual)) {
113                 rval.op = [rorNE, rorpNE];
114             } else if (op.among(OpKind.NE, OpKind.OO_ExclaimEqual)) {
115                 rval.op = [rorEQ, rorpEQ];
116             }
117         }
118     }
119 
120     if (tyi == OpTypeInfo.floatingPoint)
121         floatingPointSchema();
122     else if (tyi.among(OpTypeInfo.enumLhsIsMin, OpTypeInfo.enumLhsIsMax,
123             OpTypeInfo.enumRhsIsMin, OpTypeInfo.enumRhsIsMax))
124         enumSchema();
125     else if (tyi == OpTypeInfo.pointer)
126         pointerSchema();
127     else if (tyi == OpTypeInfo.boolean)
128         boolSchema();
129 
130     return rval;
131 }
132 
133 immutable bool[OpKind] isRor;
134 
135 immutable Mutation.Kind[] rorMutationsAll;
136 immutable Mutation.Kind[] rorpMutationsAll;
137 
138 shared static this() {
139     // dfmt off
140     with (OpKind) {
141     isRor =
142         [
143         LT: true, // "<"
144         GT: true, // ">"
145         LE: true, // "<="
146         GE: true, // ">="
147         EQ: true, // "=="
148         NE: true, // "!="
149         OO_Less: true, // "<"
150         OO_Greater: true, // ">"
151         OO_EqualEqual: true, // "=="
152         OO_ExclaimEqual: true, // "!="
153         OO_LessEqual: true, // "<="
154         OO_GreaterEqual: true, // ">="
155         ];
156     }
157     // dfmt on
158 
159     with (Mutation.Kind) {
160         rorMutationsAll = [rorLT, rorLE, rorGT, rorGE, rorEQ, rorNE, rorTrue, rorFalse];
161         rorpMutationsAll = [rorpLT, rorpLE, rorpGT, rorpGE, rorpEQ, rorpNE, rorTrue, rorFalse];
162     }
163 }