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 module dextool.plugin.mutate.backend.mutation_type.aor; 11 12 import std.algorithm : filter, among; 13 import std.array : array; 14 import std.range : only; 15 import std.typecons : Tuple; 16 17 import dextool.plugin.mutate.backend.type; 18 import dextool.clang_extensions : OpKind; 19 20 import dextool.plugin.mutate.backend.analyze.ast; 21 22 /// Information used to intelligently generate ror mutants; 23 struct AorInfo { 24 Kind operator; 25 Type lhs; 26 Type rhs; 27 } 28 29 auto aorMutations(AorInfo info) @safe { 30 // TODO: for AORs it is probably better to do one op and then lhs+rhs. 31 alias Rval = Tuple!(Mutation.Kind[], "op", Mutation.Kind[], "lhs", Mutation.Kind[], "rhs"); 32 33 Rval rval; 34 switch (info.operator) with (Mutation.Kind) { 35 case Kind.OpAdd: 36 rval = Rval([aorMul, aorDiv, aorRem, aorSub], null, null); 37 break; 38 case Kind.OpDiv: 39 rval = Rval([aorMul, aorRem, aorAdd, aorSub], null, null); 40 break; 41 case Kind.OpMod: 42 rval = Rval([aorMul, aorDiv, aorAdd, aorSub], null, null); 43 break; 44 case Kind.OpMul: 45 rval = Rval([aorDiv, aorRem, aorAdd, aorSub], null, null); 46 break; 47 case Kind.OpSub: 48 rval = Rval([aorMul, aorDiv, aorRem, aorAdd], null, null); 49 break; 50 case Kind.OpAssignAdd: 51 rval = Rval([aorDivAssign, aorRemAssign, 52 aorMulAssign, aorSubAssign], null, null); 53 break; 54 case Kind.OpAssignDiv: 55 rval = Rval([aorAddAssign, aorRemAssign, 56 aorMulAssign, aorSubAssign], null, null); 57 break; 58 case Kind.OpAssignMod: 59 rval = Rval([aorAddAssign, aorDivAssign, 60 aorMulAssign, aorSubAssign], null, null); 61 break; 62 case Kind.OpAssignMul: 63 rval = Rval([aorAddAssign, aorDivAssign, 64 aorRemAssign, aorSubAssign], null, null); 65 break; 66 case Kind.OpAssignSub: 67 rval = Rval([aorAddAssign, aorDivAssign, 68 aorRemAssign, aorMulAssign], null, null); 69 break; 70 default: 71 } 72 73 // modulo do not work when either side is a floating point. 74 if (info.lhs is null || info.rhs is null) { 75 // do nothing 76 } else if (info.lhs.kind == TypeKind.continues || info.rhs.kind == TypeKind.continues) { 77 rval.op = rval.op.filter!(a => !a.among(Mutation.Kind.aorRem, 78 Mutation.Kind.aorRemAssign)).array; 79 } 80 81 return rval; 82 } 83 84 immutable Mutation.Kind[] aorMutationsAll; 85 immutable Mutation.Kind[] aorAssignMutationsAll; 86 87 shared static this() { 88 with (Mutation.Kind) { 89 aorMutationsAll = [ 90 aorMul, aorDiv, aorRem, aorAdd, aorSub, aorLhs, aorRhs 91 ]; 92 aorAssignMutationsAll = [ 93 aorMulAssign, aorDivAssign, aorRemAssign, aorAddAssign, aorSubAssign 94 ]; 95 } 96 }