All Downloads are FREE. Search and download functionalities are using the official Maven repository.

name.remal.org$objectweb$asm$tree$MethodNode-generated.kt Maven / Gradle / Ivy

The newest version!
package name.remal
import org.objectweb.asm.tree.*

fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 2) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 2) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null

    fun reset() {
        node1 = null
        node2 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!) ?: return false
                instructions.insert(node2, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node2) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, instructionsGenerator: (node1: T1, node2: T2) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), instructionsGenerator)


fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, filter3: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2, node3: T3) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 3) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 3) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null
    var node3: T3? = null

    fun reset() {
        node1 = null
        node2 = null
        node3 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            null == node3 -> {
                if (!filter3.nodeType.isInstance(node)) return@forEach reset()
                filter3.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node3 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!, node3!!) ?: return false
                instructions.insert(node3, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node3) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, nodeType3: Class, instructionsGenerator: (node1: T1, node2: T2, node3: T3) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), nodeType3.toInstructionNodeFilter(), instructionsGenerator)


fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, filter3: InstructionNodeFilter, filter4: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 4) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 4) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null
    var node3: T3? = null
    var node4: T4? = null

    fun reset() {
        node1 = null
        node2 = null
        node3 = null
        node4 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            null == node3 -> {
                if (!filter3.nodeType.isInstance(node)) return@forEach reset()
                filter3.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node3 = node.uncheckedCast()
            }
            null == node4 -> {
                if (!filter4.nodeType.isInstance(node)) return@forEach reset()
                filter4.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node4 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!, node3!!, node4!!) ?: return false
                instructions.insert(node4, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node4) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, nodeType3: Class, nodeType4: Class, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), nodeType3.toInstructionNodeFilter(), nodeType4.toInstructionNodeFilter(), instructionsGenerator)


fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, filter3: InstructionNodeFilter, filter4: InstructionNodeFilter, filter5: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 5) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 5) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null
    var node3: T3? = null
    var node4: T4? = null
    var node5: T5? = null

    fun reset() {
        node1 = null
        node2 = null
        node3 = null
        node4 = null
        node5 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            null == node3 -> {
                if (!filter3.nodeType.isInstance(node)) return@forEach reset()
                filter3.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node3 = node.uncheckedCast()
            }
            null == node4 -> {
                if (!filter4.nodeType.isInstance(node)) return@forEach reset()
                filter4.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node4 = node.uncheckedCast()
            }
            null == node5 -> {
                if (!filter5.nodeType.isInstance(node)) return@forEach reset()
                filter5.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node5 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!, node3!!, node4!!, node5!!) ?: return false
                instructions.insert(node5, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node5) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, nodeType3: Class, nodeType4: Class, nodeType5: Class, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), nodeType3.toInstructionNodeFilter(), nodeType4.toInstructionNodeFilter(), nodeType5.toInstructionNodeFilter(), instructionsGenerator)


fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, filter3: InstructionNodeFilter, filter4: InstructionNodeFilter, filter5: InstructionNodeFilter, filter6: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 6) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 6) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null
    var node3: T3? = null
    var node4: T4? = null
    var node5: T5? = null
    var node6: T6? = null

    fun reset() {
        node1 = null
        node2 = null
        node3 = null
        node4 = null
        node5 = null
        node6 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            null == node3 -> {
                if (!filter3.nodeType.isInstance(node)) return@forEach reset()
                filter3.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node3 = node.uncheckedCast()
            }
            null == node4 -> {
                if (!filter4.nodeType.isInstance(node)) return@forEach reset()
                filter4.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node4 = node.uncheckedCast()
            }
            null == node5 -> {
                if (!filter5.nodeType.isInstance(node)) return@forEach reset()
                filter5.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node5 = node.uncheckedCast()
            }
            null == node6 -> {
                if (!filter6.nodeType.isInstance(node)) return@forEach reset()
                filter6.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node6 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!, node3!!, node4!!, node5!!, node6!!) ?: return false
                instructions.insert(node6, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node6) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, nodeType3: Class, nodeType4: Class, nodeType5: Class, nodeType6: Class, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), nodeType3.toInstructionNodeFilter(), nodeType4.toInstructionNodeFilter(), nodeType5.toInstructionNodeFilter(), nodeType6.toInstructionNodeFilter(), instructionsGenerator)


fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, filter3: InstructionNodeFilter, filter4: InstructionNodeFilter, filter5: InstructionNodeFilter, filter6: InstructionNodeFilter, filter7: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 7) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 7) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null
    var node3: T3? = null
    var node4: T4? = null
    var node5: T5? = null
    var node6: T6? = null
    var node7: T7? = null

    fun reset() {
        node1 = null
        node2 = null
        node3 = null
        node4 = null
        node5 = null
        node6 = null
        node7 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            null == node3 -> {
                if (!filter3.nodeType.isInstance(node)) return@forEach reset()
                filter3.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node3 = node.uncheckedCast()
            }
            null == node4 -> {
                if (!filter4.nodeType.isInstance(node)) return@forEach reset()
                filter4.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node4 = node.uncheckedCast()
            }
            null == node5 -> {
                if (!filter5.nodeType.isInstance(node)) return@forEach reset()
                filter5.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node5 = node.uncheckedCast()
            }
            null == node6 -> {
                if (!filter6.nodeType.isInstance(node)) return@forEach reset()
                filter6.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node6 = node.uncheckedCast()
            }
            null == node7 -> {
                if (!filter7.nodeType.isInstance(node)) return@forEach reset()
                filter7.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node7 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!, node3!!, node4!!, node5!!, node6!!, node7!!) ?: return false
                instructions.insert(node7, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node7) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, nodeType3: Class, nodeType4: Class, nodeType5: Class, nodeType6: Class, nodeType7: Class, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), nodeType3.toInstructionNodeFilter(), nodeType4.toInstructionNodeFilter(), nodeType5.toInstructionNodeFilter(), nodeType6.toInstructionNodeFilter(), nodeType7.toInstructionNodeFilter(), instructionsGenerator)


fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, filter3: InstructionNodeFilter, filter4: InstructionNodeFilter, filter5: InstructionNodeFilter, filter6: InstructionNodeFilter, filter7: InstructionNodeFilter, filter8: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 8) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 8) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null
    var node3: T3? = null
    var node4: T4? = null
    var node5: T5? = null
    var node6: T6? = null
    var node7: T7? = null
    var node8: T8? = null

    fun reset() {
        node1 = null
        node2 = null
        node3 = null
        node4 = null
        node5 = null
        node6 = null
        node7 = null
        node8 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            null == node3 -> {
                if (!filter3.nodeType.isInstance(node)) return@forEach reset()
                filter3.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node3 = node.uncheckedCast()
            }
            null == node4 -> {
                if (!filter4.nodeType.isInstance(node)) return@forEach reset()
                filter4.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node4 = node.uncheckedCast()
            }
            null == node5 -> {
                if (!filter5.nodeType.isInstance(node)) return@forEach reset()
                filter5.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node5 = node.uncheckedCast()
            }
            null == node6 -> {
                if (!filter6.nodeType.isInstance(node)) return@forEach reset()
                filter6.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node6 = node.uncheckedCast()
            }
            null == node7 -> {
                if (!filter7.nodeType.isInstance(node)) return@forEach reset()
                filter7.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node7 = node.uncheckedCast()
            }
            null == node8 -> {
                if (!filter8.nodeType.isInstance(node)) return@forEach reset()
                filter8.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node8 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!, node3!!, node4!!, node5!!, node6!!, node7!!, node8!!) ?: return false
                instructions.insert(node8, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node8) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, nodeType3: Class, nodeType4: Class, nodeType5: Class, nodeType6: Class, nodeType7: Class, nodeType8: Class, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), nodeType3.toInstructionNodeFilter(), nodeType4.toInstructionNodeFilter(), nodeType5.toInstructionNodeFilter(), nodeType6.toInstructionNodeFilter(), nodeType7.toInstructionNodeFilter(), nodeType8.toInstructionNodeFilter(), instructionsGenerator)


fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, filter3: InstructionNodeFilter, filter4: InstructionNodeFilter, filter5: InstructionNodeFilter, filter6: InstructionNodeFilter, filter7: InstructionNodeFilter, filter8: InstructionNodeFilter, filter9: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 9) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 9) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null
    var node3: T3? = null
    var node4: T4? = null
    var node5: T5? = null
    var node6: T6? = null
    var node7: T7? = null
    var node8: T8? = null
    var node9: T9? = null

    fun reset() {
        node1 = null
        node2 = null
        node3 = null
        node4 = null
        node5 = null
        node6 = null
        node7 = null
        node8 = null
        node9 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            null == node3 -> {
                if (!filter3.nodeType.isInstance(node)) return@forEach reset()
                filter3.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node3 = node.uncheckedCast()
            }
            null == node4 -> {
                if (!filter4.nodeType.isInstance(node)) return@forEach reset()
                filter4.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node4 = node.uncheckedCast()
            }
            null == node5 -> {
                if (!filter5.nodeType.isInstance(node)) return@forEach reset()
                filter5.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node5 = node.uncheckedCast()
            }
            null == node6 -> {
                if (!filter6.nodeType.isInstance(node)) return@forEach reset()
                filter6.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node6 = node.uncheckedCast()
            }
            null == node7 -> {
                if (!filter7.nodeType.isInstance(node)) return@forEach reset()
                filter7.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node7 = node.uncheckedCast()
            }
            null == node8 -> {
                if (!filter8.nodeType.isInstance(node)) return@forEach reset()
                filter8.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node8 = node.uncheckedCast()
            }
            null == node9 -> {
                if (!filter9.nodeType.isInstance(node)) return@forEach reset()
                filter9.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node9 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!, node3!!, node4!!, node5!!, node6!!, node7!!, node8!!, node9!!) ?: return false
                instructions.insert(node9, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node9) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, nodeType3: Class, nodeType4: Class, nodeType5: Class, nodeType6: Class, nodeType7: Class, nodeType8: Class, nodeType9: Class, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), nodeType3.toInstructionNodeFilter(), nodeType4.toInstructionNodeFilter(), nodeType5.toInstructionNodeFilter(), nodeType6.toInstructionNodeFilter(), nodeType7.toInstructionNodeFilter(), nodeType8.toInstructionNodeFilter(), nodeType9.toInstructionNodeFilter(), instructionsGenerator)


fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, filter3: InstructionNodeFilter, filter4: InstructionNodeFilter, filter5: InstructionNodeFilter, filter6: InstructionNodeFilter, filter7: InstructionNodeFilter, filter8: InstructionNodeFilter, filter9: InstructionNodeFilter, filter10: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 10) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 10) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null
    var node3: T3? = null
    var node4: T4? = null
    var node5: T5? = null
    var node6: T6? = null
    var node7: T7? = null
    var node8: T8? = null
    var node9: T9? = null
    var node10: T10? = null

    fun reset() {
        node1 = null
        node2 = null
        node3 = null
        node4 = null
        node5 = null
        node6 = null
        node7 = null
        node8 = null
        node9 = null
        node10 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            null == node3 -> {
                if (!filter3.nodeType.isInstance(node)) return@forEach reset()
                filter3.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node3 = node.uncheckedCast()
            }
            null == node4 -> {
                if (!filter4.nodeType.isInstance(node)) return@forEach reset()
                filter4.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node4 = node.uncheckedCast()
            }
            null == node5 -> {
                if (!filter5.nodeType.isInstance(node)) return@forEach reset()
                filter5.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node5 = node.uncheckedCast()
            }
            null == node6 -> {
                if (!filter6.nodeType.isInstance(node)) return@forEach reset()
                filter6.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node6 = node.uncheckedCast()
            }
            null == node7 -> {
                if (!filter7.nodeType.isInstance(node)) return@forEach reset()
                filter7.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node7 = node.uncheckedCast()
            }
            null == node8 -> {
                if (!filter8.nodeType.isInstance(node)) return@forEach reset()
                filter8.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node8 = node.uncheckedCast()
            }
            null == node9 -> {
                if (!filter9.nodeType.isInstance(node)) return@forEach reset()
                filter9.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node9 = node.uncheckedCast()
            }
            null == node10 -> {
                if (!filter10.nodeType.isInstance(node)) return@forEach reset()
                filter10.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node10 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!, node3!!, node4!!, node5!!, node6!!, node7!!, node8!!, node9!!, node10!!) ?: return false
                instructions.insert(node10, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node10) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, nodeType3: Class, nodeType4: Class, nodeType5: Class, nodeType6: Class, nodeType7: Class, nodeType8: Class, nodeType9: Class, nodeType10: Class, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), nodeType3.toInstructionNodeFilter(), nodeType4.toInstructionNodeFilter(), nodeType5.toInstructionNodeFilter(), nodeType6.toInstructionNodeFilter(), nodeType7.toInstructionNodeFilter(), nodeType8.toInstructionNodeFilter(), nodeType9.toInstructionNodeFilter(), nodeType10.toInstructionNodeFilter(), instructionsGenerator)


fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, filter3: InstructionNodeFilter, filter4: InstructionNodeFilter, filter5: InstructionNodeFilter, filter6: InstructionNodeFilter, filter7: InstructionNodeFilter, filter8: InstructionNodeFilter, filter9: InstructionNodeFilter, filter10: InstructionNodeFilter, filter11: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 11) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 11) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null
    var node3: T3? = null
    var node4: T4? = null
    var node5: T5? = null
    var node6: T6? = null
    var node7: T7? = null
    var node8: T8? = null
    var node9: T9? = null
    var node10: T10? = null
    var node11: T11? = null

    fun reset() {
        node1 = null
        node2 = null
        node3 = null
        node4 = null
        node5 = null
        node6 = null
        node7 = null
        node8 = null
        node9 = null
        node10 = null
        node11 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            null == node3 -> {
                if (!filter3.nodeType.isInstance(node)) return@forEach reset()
                filter3.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node3 = node.uncheckedCast()
            }
            null == node4 -> {
                if (!filter4.nodeType.isInstance(node)) return@forEach reset()
                filter4.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node4 = node.uncheckedCast()
            }
            null == node5 -> {
                if (!filter5.nodeType.isInstance(node)) return@forEach reset()
                filter5.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node5 = node.uncheckedCast()
            }
            null == node6 -> {
                if (!filter6.nodeType.isInstance(node)) return@forEach reset()
                filter6.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node6 = node.uncheckedCast()
            }
            null == node7 -> {
                if (!filter7.nodeType.isInstance(node)) return@forEach reset()
                filter7.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node7 = node.uncheckedCast()
            }
            null == node8 -> {
                if (!filter8.nodeType.isInstance(node)) return@forEach reset()
                filter8.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node8 = node.uncheckedCast()
            }
            null == node9 -> {
                if (!filter9.nodeType.isInstance(node)) return@forEach reset()
                filter9.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node9 = node.uncheckedCast()
            }
            null == node10 -> {
                if (!filter10.nodeType.isInstance(node)) return@forEach reset()
                filter10.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node10 = node.uncheckedCast()
            }
            null == node11 -> {
                if (!filter11.nodeType.isInstance(node)) return@forEach reset()
                filter11.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node11 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!, node3!!, node4!!, node5!!, node6!!, node7!!, node8!!, node9!!, node10!!, node11!!) ?: return false
                instructions.insert(node11, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node11) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, nodeType3: Class, nodeType4: Class, nodeType5: Class, nodeType6: Class, nodeType7: Class, nodeType8: Class, nodeType9: Class, nodeType10: Class, nodeType11: Class, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), nodeType3.toInstructionNodeFilter(), nodeType4.toInstructionNodeFilter(), nodeType5.toInstructionNodeFilter(), nodeType6.toInstructionNodeFilter(), nodeType7.toInstructionNodeFilter(), nodeType8.toInstructionNodeFilter(), nodeType9.toInstructionNodeFilter(), nodeType10.toInstructionNodeFilter(), nodeType11.toInstructionNodeFilter(), instructionsGenerator)


fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, filter3: InstructionNodeFilter, filter4: InstructionNodeFilter, filter5: InstructionNodeFilter, filter6: InstructionNodeFilter, filter7: InstructionNodeFilter, filter8: InstructionNodeFilter, filter9: InstructionNodeFilter, filter10: InstructionNodeFilter, filter11: InstructionNodeFilter, filter12: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11, node12: T12) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 12) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 12) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null
    var node3: T3? = null
    var node4: T4? = null
    var node5: T5? = null
    var node6: T6? = null
    var node7: T7? = null
    var node8: T8? = null
    var node9: T9? = null
    var node10: T10? = null
    var node11: T11? = null
    var node12: T12? = null

    fun reset() {
        node1 = null
        node2 = null
        node3 = null
        node4 = null
        node5 = null
        node6 = null
        node7 = null
        node8 = null
        node9 = null
        node10 = null
        node11 = null
        node12 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            null == node3 -> {
                if (!filter3.nodeType.isInstance(node)) return@forEach reset()
                filter3.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node3 = node.uncheckedCast()
            }
            null == node4 -> {
                if (!filter4.nodeType.isInstance(node)) return@forEach reset()
                filter4.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node4 = node.uncheckedCast()
            }
            null == node5 -> {
                if (!filter5.nodeType.isInstance(node)) return@forEach reset()
                filter5.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node5 = node.uncheckedCast()
            }
            null == node6 -> {
                if (!filter6.nodeType.isInstance(node)) return@forEach reset()
                filter6.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node6 = node.uncheckedCast()
            }
            null == node7 -> {
                if (!filter7.nodeType.isInstance(node)) return@forEach reset()
                filter7.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node7 = node.uncheckedCast()
            }
            null == node8 -> {
                if (!filter8.nodeType.isInstance(node)) return@forEach reset()
                filter8.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node8 = node.uncheckedCast()
            }
            null == node9 -> {
                if (!filter9.nodeType.isInstance(node)) return@forEach reset()
                filter9.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node9 = node.uncheckedCast()
            }
            null == node10 -> {
                if (!filter10.nodeType.isInstance(node)) return@forEach reset()
                filter10.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node10 = node.uncheckedCast()
            }
            null == node11 -> {
                if (!filter11.nodeType.isInstance(node)) return@forEach reset()
                filter11.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node11 = node.uncheckedCast()
            }
            null == node12 -> {
                if (!filter12.nodeType.isInstance(node)) return@forEach reset()
                filter12.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node12 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!, node3!!, node4!!, node5!!, node6!!, node7!!, node8!!, node9!!, node10!!, node11!!, node12!!) ?: return false
                instructions.insert(node12, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node12) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, nodeType3: Class, nodeType4: Class, nodeType5: Class, nodeType6: Class, nodeType7: Class, nodeType8: Class, nodeType9: Class, nodeType10: Class, nodeType11: Class, nodeType12: Class, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11, node12: T12) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), nodeType3.toInstructionNodeFilter(), nodeType4.toInstructionNodeFilter(), nodeType5.toInstructionNodeFilter(), nodeType6.toInstructionNodeFilter(), nodeType7.toInstructionNodeFilter(), nodeType8.toInstructionNodeFilter(), nodeType9.toInstructionNodeFilter(), nodeType10.toInstructionNodeFilter(), nodeType11.toInstructionNodeFilter(), nodeType12.toInstructionNodeFilter(), instructionsGenerator)


fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, filter3: InstructionNodeFilter, filter4: InstructionNodeFilter, filter5: InstructionNodeFilter, filter6: InstructionNodeFilter, filter7: InstructionNodeFilter, filter8: InstructionNodeFilter, filter9: InstructionNodeFilter, filter10: InstructionNodeFilter, filter11: InstructionNodeFilter, filter12: InstructionNodeFilter, filter13: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11, node12: T12, node13: T13) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 13) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 13) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null
    var node3: T3? = null
    var node4: T4? = null
    var node5: T5? = null
    var node6: T6? = null
    var node7: T7? = null
    var node8: T8? = null
    var node9: T9? = null
    var node10: T10? = null
    var node11: T11? = null
    var node12: T12? = null
    var node13: T13? = null

    fun reset() {
        node1 = null
        node2 = null
        node3 = null
        node4 = null
        node5 = null
        node6 = null
        node7 = null
        node8 = null
        node9 = null
        node10 = null
        node11 = null
        node12 = null
        node13 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            null == node3 -> {
                if (!filter3.nodeType.isInstance(node)) return@forEach reset()
                filter3.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node3 = node.uncheckedCast()
            }
            null == node4 -> {
                if (!filter4.nodeType.isInstance(node)) return@forEach reset()
                filter4.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node4 = node.uncheckedCast()
            }
            null == node5 -> {
                if (!filter5.nodeType.isInstance(node)) return@forEach reset()
                filter5.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node5 = node.uncheckedCast()
            }
            null == node6 -> {
                if (!filter6.nodeType.isInstance(node)) return@forEach reset()
                filter6.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node6 = node.uncheckedCast()
            }
            null == node7 -> {
                if (!filter7.nodeType.isInstance(node)) return@forEach reset()
                filter7.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node7 = node.uncheckedCast()
            }
            null == node8 -> {
                if (!filter8.nodeType.isInstance(node)) return@forEach reset()
                filter8.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node8 = node.uncheckedCast()
            }
            null == node9 -> {
                if (!filter9.nodeType.isInstance(node)) return@forEach reset()
                filter9.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node9 = node.uncheckedCast()
            }
            null == node10 -> {
                if (!filter10.nodeType.isInstance(node)) return@forEach reset()
                filter10.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node10 = node.uncheckedCast()
            }
            null == node11 -> {
                if (!filter11.nodeType.isInstance(node)) return@forEach reset()
                filter11.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node11 = node.uncheckedCast()
            }
            null == node12 -> {
                if (!filter12.nodeType.isInstance(node)) return@forEach reset()
                filter12.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node12 = node.uncheckedCast()
            }
            null == node13 -> {
                if (!filter13.nodeType.isInstance(node)) return@forEach reset()
                filter13.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node13 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!, node3!!, node4!!, node5!!, node6!!, node7!!, node8!!, node9!!, node10!!, node11!!, node12!!, node13!!) ?: return false
                instructions.insert(node13, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node13) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, nodeType3: Class, nodeType4: Class, nodeType5: Class, nodeType6: Class, nodeType7: Class, nodeType8: Class, nodeType9: Class, nodeType10: Class, nodeType11: Class, nodeType12: Class, nodeType13: Class, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11, node12: T12, node13: T13) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), nodeType3.toInstructionNodeFilter(), nodeType4.toInstructionNodeFilter(), nodeType5.toInstructionNodeFilter(), nodeType6.toInstructionNodeFilter(), nodeType7.toInstructionNodeFilter(), nodeType8.toInstructionNodeFilter(), nodeType9.toInstructionNodeFilter(), nodeType10.toInstructionNodeFilter(), nodeType11.toInstructionNodeFilter(), nodeType12.toInstructionNodeFilter(), nodeType13.toInstructionNodeFilter(), instructionsGenerator)


fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, filter3: InstructionNodeFilter, filter4: InstructionNodeFilter, filter5: InstructionNodeFilter, filter6: InstructionNodeFilter, filter7: InstructionNodeFilter, filter8: InstructionNodeFilter, filter9: InstructionNodeFilter, filter10: InstructionNodeFilter, filter11: InstructionNodeFilter, filter12: InstructionNodeFilter, filter13: InstructionNodeFilter, filter14: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11, node12: T12, node13: T13, node14: T14) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 14) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 14) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null
    var node3: T3? = null
    var node4: T4? = null
    var node5: T5? = null
    var node6: T6? = null
    var node7: T7? = null
    var node8: T8? = null
    var node9: T9? = null
    var node10: T10? = null
    var node11: T11? = null
    var node12: T12? = null
    var node13: T13? = null
    var node14: T14? = null

    fun reset() {
        node1 = null
        node2 = null
        node3 = null
        node4 = null
        node5 = null
        node6 = null
        node7 = null
        node8 = null
        node9 = null
        node10 = null
        node11 = null
        node12 = null
        node13 = null
        node14 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            null == node3 -> {
                if (!filter3.nodeType.isInstance(node)) return@forEach reset()
                filter3.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node3 = node.uncheckedCast()
            }
            null == node4 -> {
                if (!filter4.nodeType.isInstance(node)) return@forEach reset()
                filter4.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node4 = node.uncheckedCast()
            }
            null == node5 -> {
                if (!filter5.nodeType.isInstance(node)) return@forEach reset()
                filter5.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node5 = node.uncheckedCast()
            }
            null == node6 -> {
                if (!filter6.nodeType.isInstance(node)) return@forEach reset()
                filter6.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node6 = node.uncheckedCast()
            }
            null == node7 -> {
                if (!filter7.nodeType.isInstance(node)) return@forEach reset()
                filter7.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node7 = node.uncheckedCast()
            }
            null == node8 -> {
                if (!filter8.nodeType.isInstance(node)) return@forEach reset()
                filter8.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node8 = node.uncheckedCast()
            }
            null == node9 -> {
                if (!filter9.nodeType.isInstance(node)) return@forEach reset()
                filter9.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node9 = node.uncheckedCast()
            }
            null == node10 -> {
                if (!filter10.nodeType.isInstance(node)) return@forEach reset()
                filter10.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node10 = node.uncheckedCast()
            }
            null == node11 -> {
                if (!filter11.nodeType.isInstance(node)) return@forEach reset()
                filter11.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node11 = node.uncheckedCast()
            }
            null == node12 -> {
                if (!filter12.nodeType.isInstance(node)) return@forEach reset()
                filter12.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node12 = node.uncheckedCast()
            }
            null == node13 -> {
                if (!filter13.nodeType.isInstance(node)) return@forEach reset()
                filter13.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node13 = node.uncheckedCast()
            }
            null == node14 -> {
                if (!filter14.nodeType.isInstance(node)) return@forEach reset()
                filter14.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node14 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!, node3!!, node4!!, node5!!, node6!!, node7!!, node8!!, node9!!, node10!!, node11!!, node12!!, node13!!, node14!!) ?: return false
                instructions.insert(node14, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node14) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, nodeType3: Class, nodeType4: Class, nodeType5: Class, nodeType6: Class, nodeType7: Class, nodeType8: Class, nodeType9: Class, nodeType10: Class, nodeType11: Class, nodeType12: Class, nodeType13: Class, nodeType14: Class, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11, node12: T12, node13: T13, node14: T14) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), nodeType3.toInstructionNodeFilter(), nodeType4.toInstructionNodeFilter(), nodeType5.toInstructionNodeFilter(), nodeType6.toInstructionNodeFilter(), nodeType7.toInstructionNodeFilter(), nodeType8.toInstructionNodeFilter(), nodeType9.toInstructionNodeFilter(), nodeType10.toInstructionNodeFilter(), nodeType11.toInstructionNodeFilter(), nodeType12.toInstructionNodeFilter(), nodeType13.toInstructionNodeFilter(), nodeType14.toInstructionNodeFilter(), instructionsGenerator)


fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, filter3: InstructionNodeFilter, filter4: InstructionNodeFilter, filter5: InstructionNodeFilter, filter6: InstructionNodeFilter, filter7: InstructionNodeFilter, filter8: InstructionNodeFilter, filter9: InstructionNodeFilter, filter10: InstructionNodeFilter, filter11: InstructionNodeFilter, filter12: InstructionNodeFilter, filter13: InstructionNodeFilter, filter14: InstructionNodeFilter, filter15: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11, node12: T12, node13: T13, node14: T14, node15: T15) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 15) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 15) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null
    var node3: T3? = null
    var node4: T4? = null
    var node5: T5? = null
    var node6: T6? = null
    var node7: T7? = null
    var node8: T8? = null
    var node9: T9? = null
    var node10: T10? = null
    var node11: T11? = null
    var node12: T12? = null
    var node13: T13? = null
    var node14: T14? = null
    var node15: T15? = null

    fun reset() {
        node1 = null
        node2 = null
        node3 = null
        node4 = null
        node5 = null
        node6 = null
        node7 = null
        node8 = null
        node9 = null
        node10 = null
        node11 = null
        node12 = null
        node13 = null
        node14 = null
        node15 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            null == node3 -> {
                if (!filter3.nodeType.isInstance(node)) return@forEach reset()
                filter3.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node3 = node.uncheckedCast()
            }
            null == node4 -> {
                if (!filter4.nodeType.isInstance(node)) return@forEach reset()
                filter4.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node4 = node.uncheckedCast()
            }
            null == node5 -> {
                if (!filter5.nodeType.isInstance(node)) return@forEach reset()
                filter5.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node5 = node.uncheckedCast()
            }
            null == node6 -> {
                if (!filter6.nodeType.isInstance(node)) return@forEach reset()
                filter6.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node6 = node.uncheckedCast()
            }
            null == node7 -> {
                if (!filter7.nodeType.isInstance(node)) return@forEach reset()
                filter7.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node7 = node.uncheckedCast()
            }
            null == node8 -> {
                if (!filter8.nodeType.isInstance(node)) return@forEach reset()
                filter8.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node8 = node.uncheckedCast()
            }
            null == node9 -> {
                if (!filter9.nodeType.isInstance(node)) return@forEach reset()
                filter9.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node9 = node.uncheckedCast()
            }
            null == node10 -> {
                if (!filter10.nodeType.isInstance(node)) return@forEach reset()
                filter10.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node10 = node.uncheckedCast()
            }
            null == node11 -> {
                if (!filter11.nodeType.isInstance(node)) return@forEach reset()
                filter11.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node11 = node.uncheckedCast()
            }
            null == node12 -> {
                if (!filter12.nodeType.isInstance(node)) return@forEach reset()
                filter12.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node12 = node.uncheckedCast()
            }
            null == node13 -> {
                if (!filter13.nodeType.isInstance(node)) return@forEach reset()
                filter13.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node13 = node.uncheckedCast()
            }
            null == node14 -> {
                if (!filter14.nodeType.isInstance(node)) return@forEach reset()
                filter14.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node14 = node.uncheckedCast()
            }
            null == node15 -> {
                if (!filter15.nodeType.isInstance(node)) return@forEach reset()
                filter15.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node15 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!, node3!!, node4!!, node5!!, node6!!, node7!!, node8!!, node9!!, node10!!, node11!!, node12!!, node13!!, node14!!, node15!!) ?: return false
                instructions.insert(node15, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node15) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, nodeType3: Class, nodeType4: Class, nodeType5: Class, nodeType6: Class, nodeType7: Class, nodeType8: Class, nodeType9: Class, nodeType10: Class, nodeType11: Class, nodeType12: Class, nodeType13: Class, nodeType14: Class, nodeType15: Class, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11, node12: T12, node13: T13, node14: T14, node15: T15) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), nodeType3.toInstructionNodeFilter(), nodeType4.toInstructionNodeFilter(), nodeType5.toInstructionNodeFilter(), nodeType6.toInstructionNodeFilter(), nodeType7.toInstructionNodeFilter(), nodeType8.toInstructionNodeFilter(), nodeType9.toInstructionNodeFilter(), nodeType10.toInstructionNodeFilter(), nodeType11.toInstructionNodeFilter(), nodeType12.toInstructionNodeFilter(), nodeType13.toInstructionNodeFilter(), nodeType14.toInstructionNodeFilter(), nodeType15.toInstructionNodeFilter(), instructionsGenerator)


fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, filter3: InstructionNodeFilter, filter4: InstructionNodeFilter, filter5: InstructionNodeFilter, filter6: InstructionNodeFilter, filter7: InstructionNodeFilter, filter8: InstructionNodeFilter, filter9: InstructionNodeFilter, filter10: InstructionNodeFilter, filter11: InstructionNodeFilter, filter12: InstructionNodeFilter, filter13: InstructionNodeFilter, filter14: InstructionNodeFilter, filter15: InstructionNodeFilter, filter16: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11, node12: T12, node13: T13, node14: T14, node15: T15, node16: T16) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 16) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 16) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null
    var node3: T3? = null
    var node4: T4? = null
    var node5: T5? = null
    var node6: T6? = null
    var node7: T7? = null
    var node8: T8? = null
    var node9: T9? = null
    var node10: T10? = null
    var node11: T11? = null
    var node12: T12? = null
    var node13: T13? = null
    var node14: T14? = null
    var node15: T15? = null
    var node16: T16? = null

    fun reset() {
        node1 = null
        node2 = null
        node3 = null
        node4 = null
        node5 = null
        node6 = null
        node7 = null
        node8 = null
        node9 = null
        node10 = null
        node11 = null
        node12 = null
        node13 = null
        node14 = null
        node15 = null
        node16 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            null == node3 -> {
                if (!filter3.nodeType.isInstance(node)) return@forEach reset()
                filter3.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node3 = node.uncheckedCast()
            }
            null == node4 -> {
                if (!filter4.nodeType.isInstance(node)) return@forEach reset()
                filter4.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node4 = node.uncheckedCast()
            }
            null == node5 -> {
                if (!filter5.nodeType.isInstance(node)) return@forEach reset()
                filter5.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node5 = node.uncheckedCast()
            }
            null == node6 -> {
                if (!filter6.nodeType.isInstance(node)) return@forEach reset()
                filter6.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node6 = node.uncheckedCast()
            }
            null == node7 -> {
                if (!filter7.nodeType.isInstance(node)) return@forEach reset()
                filter7.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node7 = node.uncheckedCast()
            }
            null == node8 -> {
                if (!filter8.nodeType.isInstance(node)) return@forEach reset()
                filter8.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node8 = node.uncheckedCast()
            }
            null == node9 -> {
                if (!filter9.nodeType.isInstance(node)) return@forEach reset()
                filter9.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node9 = node.uncheckedCast()
            }
            null == node10 -> {
                if (!filter10.nodeType.isInstance(node)) return@forEach reset()
                filter10.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node10 = node.uncheckedCast()
            }
            null == node11 -> {
                if (!filter11.nodeType.isInstance(node)) return@forEach reset()
                filter11.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node11 = node.uncheckedCast()
            }
            null == node12 -> {
                if (!filter12.nodeType.isInstance(node)) return@forEach reset()
                filter12.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node12 = node.uncheckedCast()
            }
            null == node13 -> {
                if (!filter13.nodeType.isInstance(node)) return@forEach reset()
                filter13.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node13 = node.uncheckedCast()
            }
            null == node14 -> {
                if (!filter14.nodeType.isInstance(node)) return@forEach reset()
                filter14.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node14 = node.uncheckedCast()
            }
            null == node15 -> {
                if (!filter15.nodeType.isInstance(node)) return@forEach reset()
                filter15.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node15 = node.uncheckedCast()
            }
            null == node16 -> {
                if (!filter16.nodeType.isInstance(node)) return@forEach reset()
                filter16.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node16 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!, node3!!, node4!!, node5!!, node6!!, node7!!, node8!!, node9!!, node10!!, node11!!, node12!!, node13!!, node14!!, node15!!, node16!!) ?: return false
                instructions.insert(node16, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node16) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, nodeType3: Class, nodeType4: Class, nodeType5: Class, nodeType6: Class, nodeType7: Class, nodeType8: Class, nodeType9: Class, nodeType10: Class, nodeType11: Class, nodeType12: Class, nodeType13: Class, nodeType14: Class, nodeType15: Class, nodeType16: Class, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11, node12: T12, node13: T13, node14: T14, node15: T15, node16: T16) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), nodeType3.toInstructionNodeFilter(), nodeType4.toInstructionNodeFilter(), nodeType5.toInstructionNodeFilter(), nodeType6.toInstructionNodeFilter(), nodeType7.toInstructionNodeFilter(), nodeType8.toInstructionNodeFilter(), nodeType9.toInstructionNodeFilter(), nodeType10.toInstructionNodeFilter(), nodeType11.toInstructionNodeFilter(), nodeType12.toInstructionNodeFilter(), nodeType13.toInstructionNodeFilter(), nodeType14.toInstructionNodeFilter(), nodeType15.toInstructionNodeFilter(), nodeType16.toInstructionNodeFilter(), instructionsGenerator)


fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, filter3: InstructionNodeFilter, filter4: InstructionNodeFilter, filter5: InstructionNodeFilter, filter6: InstructionNodeFilter, filter7: InstructionNodeFilter, filter8: InstructionNodeFilter, filter9: InstructionNodeFilter, filter10: InstructionNodeFilter, filter11: InstructionNodeFilter, filter12: InstructionNodeFilter, filter13: InstructionNodeFilter, filter14: InstructionNodeFilter, filter15: InstructionNodeFilter, filter16: InstructionNodeFilter, filter17: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11, node12: T12, node13: T13, node14: T14, node15: T15, node16: T16, node17: T17) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 17) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 17) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null
    var node3: T3? = null
    var node4: T4? = null
    var node5: T5? = null
    var node6: T6? = null
    var node7: T7? = null
    var node8: T8? = null
    var node9: T9? = null
    var node10: T10? = null
    var node11: T11? = null
    var node12: T12? = null
    var node13: T13? = null
    var node14: T14? = null
    var node15: T15? = null
    var node16: T16? = null
    var node17: T17? = null

    fun reset() {
        node1 = null
        node2 = null
        node3 = null
        node4 = null
        node5 = null
        node6 = null
        node7 = null
        node8 = null
        node9 = null
        node10 = null
        node11 = null
        node12 = null
        node13 = null
        node14 = null
        node15 = null
        node16 = null
        node17 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            null == node3 -> {
                if (!filter3.nodeType.isInstance(node)) return@forEach reset()
                filter3.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node3 = node.uncheckedCast()
            }
            null == node4 -> {
                if (!filter4.nodeType.isInstance(node)) return@forEach reset()
                filter4.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node4 = node.uncheckedCast()
            }
            null == node5 -> {
                if (!filter5.nodeType.isInstance(node)) return@forEach reset()
                filter5.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node5 = node.uncheckedCast()
            }
            null == node6 -> {
                if (!filter6.nodeType.isInstance(node)) return@forEach reset()
                filter6.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node6 = node.uncheckedCast()
            }
            null == node7 -> {
                if (!filter7.nodeType.isInstance(node)) return@forEach reset()
                filter7.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node7 = node.uncheckedCast()
            }
            null == node8 -> {
                if (!filter8.nodeType.isInstance(node)) return@forEach reset()
                filter8.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node8 = node.uncheckedCast()
            }
            null == node9 -> {
                if (!filter9.nodeType.isInstance(node)) return@forEach reset()
                filter9.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node9 = node.uncheckedCast()
            }
            null == node10 -> {
                if (!filter10.nodeType.isInstance(node)) return@forEach reset()
                filter10.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node10 = node.uncheckedCast()
            }
            null == node11 -> {
                if (!filter11.nodeType.isInstance(node)) return@forEach reset()
                filter11.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node11 = node.uncheckedCast()
            }
            null == node12 -> {
                if (!filter12.nodeType.isInstance(node)) return@forEach reset()
                filter12.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node12 = node.uncheckedCast()
            }
            null == node13 -> {
                if (!filter13.nodeType.isInstance(node)) return@forEach reset()
                filter13.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node13 = node.uncheckedCast()
            }
            null == node14 -> {
                if (!filter14.nodeType.isInstance(node)) return@forEach reset()
                filter14.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node14 = node.uncheckedCast()
            }
            null == node15 -> {
                if (!filter15.nodeType.isInstance(node)) return@forEach reset()
                filter15.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node15 = node.uncheckedCast()
            }
            null == node16 -> {
                if (!filter16.nodeType.isInstance(node)) return@forEach reset()
                filter16.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node16 = node.uncheckedCast()
            }
            null == node17 -> {
                if (!filter17.nodeType.isInstance(node)) return@forEach reset()
                filter17.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node17 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!, node3!!, node4!!, node5!!, node6!!, node7!!, node8!!, node9!!, node10!!, node11!!, node12!!, node13!!, node14!!, node15!!, node16!!, node17!!) ?: return false
                instructions.insert(node17, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node17) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, nodeType3: Class, nodeType4: Class, nodeType5: Class, nodeType6: Class, nodeType7: Class, nodeType8: Class, nodeType9: Class, nodeType10: Class, nodeType11: Class, nodeType12: Class, nodeType13: Class, nodeType14: Class, nodeType15: Class, nodeType16: Class, nodeType17: Class, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11, node12: T12, node13: T13, node14: T14, node15: T15, node16: T16, node17: T17) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), nodeType3.toInstructionNodeFilter(), nodeType4.toInstructionNodeFilter(), nodeType5.toInstructionNodeFilter(), nodeType6.toInstructionNodeFilter(), nodeType7.toInstructionNodeFilter(), nodeType8.toInstructionNodeFilter(), nodeType9.toInstructionNodeFilter(), nodeType10.toInstructionNodeFilter(), nodeType11.toInstructionNodeFilter(), nodeType12.toInstructionNodeFilter(), nodeType13.toInstructionNodeFilter(), nodeType14.toInstructionNodeFilter(), nodeType15.toInstructionNodeFilter(), nodeType16.toInstructionNodeFilter(), nodeType17.toInstructionNodeFilter(), instructionsGenerator)


fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, filter3: InstructionNodeFilter, filter4: InstructionNodeFilter, filter5: InstructionNodeFilter, filter6: InstructionNodeFilter, filter7: InstructionNodeFilter, filter8: InstructionNodeFilter, filter9: InstructionNodeFilter, filter10: InstructionNodeFilter, filter11: InstructionNodeFilter, filter12: InstructionNodeFilter, filter13: InstructionNodeFilter, filter14: InstructionNodeFilter, filter15: InstructionNodeFilter, filter16: InstructionNodeFilter, filter17: InstructionNodeFilter, filter18: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11, node12: T12, node13: T13, node14: T14, node15: T15, node16: T16, node17: T17, node18: T18) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 18) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 18) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null
    var node3: T3? = null
    var node4: T4? = null
    var node5: T5? = null
    var node6: T6? = null
    var node7: T7? = null
    var node8: T8? = null
    var node9: T9? = null
    var node10: T10? = null
    var node11: T11? = null
    var node12: T12? = null
    var node13: T13? = null
    var node14: T14? = null
    var node15: T15? = null
    var node16: T16? = null
    var node17: T17? = null
    var node18: T18? = null

    fun reset() {
        node1 = null
        node2 = null
        node3 = null
        node4 = null
        node5 = null
        node6 = null
        node7 = null
        node8 = null
        node9 = null
        node10 = null
        node11 = null
        node12 = null
        node13 = null
        node14 = null
        node15 = null
        node16 = null
        node17 = null
        node18 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            null == node3 -> {
                if (!filter3.nodeType.isInstance(node)) return@forEach reset()
                filter3.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node3 = node.uncheckedCast()
            }
            null == node4 -> {
                if (!filter4.nodeType.isInstance(node)) return@forEach reset()
                filter4.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node4 = node.uncheckedCast()
            }
            null == node5 -> {
                if (!filter5.nodeType.isInstance(node)) return@forEach reset()
                filter5.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node5 = node.uncheckedCast()
            }
            null == node6 -> {
                if (!filter6.nodeType.isInstance(node)) return@forEach reset()
                filter6.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node6 = node.uncheckedCast()
            }
            null == node7 -> {
                if (!filter7.nodeType.isInstance(node)) return@forEach reset()
                filter7.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node7 = node.uncheckedCast()
            }
            null == node8 -> {
                if (!filter8.nodeType.isInstance(node)) return@forEach reset()
                filter8.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node8 = node.uncheckedCast()
            }
            null == node9 -> {
                if (!filter9.nodeType.isInstance(node)) return@forEach reset()
                filter9.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node9 = node.uncheckedCast()
            }
            null == node10 -> {
                if (!filter10.nodeType.isInstance(node)) return@forEach reset()
                filter10.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node10 = node.uncheckedCast()
            }
            null == node11 -> {
                if (!filter11.nodeType.isInstance(node)) return@forEach reset()
                filter11.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node11 = node.uncheckedCast()
            }
            null == node12 -> {
                if (!filter12.nodeType.isInstance(node)) return@forEach reset()
                filter12.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node12 = node.uncheckedCast()
            }
            null == node13 -> {
                if (!filter13.nodeType.isInstance(node)) return@forEach reset()
                filter13.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node13 = node.uncheckedCast()
            }
            null == node14 -> {
                if (!filter14.nodeType.isInstance(node)) return@forEach reset()
                filter14.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node14 = node.uncheckedCast()
            }
            null == node15 -> {
                if (!filter15.nodeType.isInstance(node)) return@forEach reset()
                filter15.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node15 = node.uncheckedCast()
            }
            null == node16 -> {
                if (!filter16.nodeType.isInstance(node)) return@forEach reset()
                filter16.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node16 = node.uncheckedCast()
            }
            null == node17 -> {
                if (!filter17.nodeType.isInstance(node)) return@forEach reset()
                filter17.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node17 = node.uncheckedCast()
            }
            null == node18 -> {
                if (!filter18.nodeType.isInstance(node)) return@forEach reset()
                filter18.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node18 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!, node3!!, node4!!, node5!!, node6!!, node7!!, node8!!, node9!!, node10!!, node11!!, node12!!, node13!!, node14!!, node15!!, node16!!, node17!!, node18!!) ?: return false
                instructions.insert(node18, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node18) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, nodeType3: Class, nodeType4: Class, nodeType5: Class, nodeType6: Class, nodeType7: Class, nodeType8: Class, nodeType9: Class, nodeType10: Class, nodeType11: Class, nodeType12: Class, nodeType13: Class, nodeType14: Class, nodeType15: Class, nodeType16: Class, nodeType17: Class, nodeType18: Class, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11, node12: T12, node13: T13, node14: T14, node15: T15, node16: T16, node17: T17, node18: T18) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), nodeType3.toInstructionNodeFilter(), nodeType4.toInstructionNodeFilter(), nodeType5.toInstructionNodeFilter(), nodeType6.toInstructionNodeFilter(), nodeType7.toInstructionNodeFilter(), nodeType8.toInstructionNodeFilter(), nodeType9.toInstructionNodeFilter(), nodeType10.toInstructionNodeFilter(), nodeType11.toInstructionNodeFilter(), nodeType12.toInstructionNodeFilter(), nodeType13.toInstructionNodeFilter(), nodeType14.toInstructionNodeFilter(), nodeType15.toInstructionNodeFilter(), nodeType16.toInstructionNodeFilter(), nodeType17.toInstructionNodeFilter(), nodeType18.toInstructionNodeFilter(), instructionsGenerator)


fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, filter3: InstructionNodeFilter, filter4: InstructionNodeFilter, filter5: InstructionNodeFilter, filter6: InstructionNodeFilter, filter7: InstructionNodeFilter, filter8: InstructionNodeFilter, filter9: InstructionNodeFilter, filter10: InstructionNodeFilter, filter11: InstructionNodeFilter, filter12: InstructionNodeFilter, filter13: InstructionNodeFilter, filter14: InstructionNodeFilter, filter15: InstructionNodeFilter, filter16: InstructionNodeFilter, filter17: InstructionNodeFilter, filter18: InstructionNodeFilter, filter19: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11, node12: T12, node13: T13, node14: T14, node15: T15, node16: T16, node17: T17, node18: T18, node19: T19) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 19) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 19) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null
    var node3: T3? = null
    var node4: T4? = null
    var node5: T5? = null
    var node6: T6? = null
    var node7: T7? = null
    var node8: T8? = null
    var node9: T9? = null
    var node10: T10? = null
    var node11: T11? = null
    var node12: T12? = null
    var node13: T13? = null
    var node14: T14? = null
    var node15: T15? = null
    var node16: T16? = null
    var node17: T17? = null
    var node18: T18? = null
    var node19: T19? = null

    fun reset() {
        node1 = null
        node2 = null
        node3 = null
        node4 = null
        node5 = null
        node6 = null
        node7 = null
        node8 = null
        node9 = null
        node10 = null
        node11 = null
        node12 = null
        node13 = null
        node14 = null
        node15 = null
        node16 = null
        node17 = null
        node18 = null
        node19 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            null == node3 -> {
                if (!filter3.nodeType.isInstance(node)) return@forEach reset()
                filter3.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node3 = node.uncheckedCast()
            }
            null == node4 -> {
                if (!filter4.nodeType.isInstance(node)) return@forEach reset()
                filter4.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node4 = node.uncheckedCast()
            }
            null == node5 -> {
                if (!filter5.nodeType.isInstance(node)) return@forEach reset()
                filter5.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node5 = node.uncheckedCast()
            }
            null == node6 -> {
                if (!filter6.nodeType.isInstance(node)) return@forEach reset()
                filter6.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node6 = node.uncheckedCast()
            }
            null == node7 -> {
                if (!filter7.nodeType.isInstance(node)) return@forEach reset()
                filter7.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node7 = node.uncheckedCast()
            }
            null == node8 -> {
                if (!filter8.nodeType.isInstance(node)) return@forEach reset()
                filter8.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node8 = node.uncheckedCast()
            }
            null == node9 -> {
                if (!filter9.nodeType.isInstance(node)) return@forEach reset()
                filter9.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node9 = node.uncheckedCast()
            }
            null == node10 -> {
                if (!filter10.nodeType.isInstance(node)) return@forEach reset()
                filter10.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node10 = node.uncheckedCast()
            }
            null == node11 -> {
                if (!filter11.nodeType.isInstance(node)) return@forEach reset()
                filter11.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node11 = node.uncheckedCast()
            }
            null == node12 -> {
                if (!filter12.nodeType.isInstance(node)) return@forEach reset()
                filter12.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node12 = node.uncheckedCast()
            }
            null == node13 -> {
                if (!filter13.nodeType.isInstance(node)) return@forEach reset()
                filter13.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node13 = node.uncheckedCast()
            }
            null == node14 -> {
                if (!filter14.nodeType.isInstance(node)) return@forEach reset()
                filter14.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node14 = node.uncheckedCast()
            }
            null == node15 -> {
                if (!filter15.nodeType.isInstance(node)) return@forEach reset()
                filter15.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node15 = node.uncheckedCast()
            }
            null == node16 -> {
                if (!filter16.nodeType.isInstance(node)) return@forEach reset()
                filter16.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node16 = node.uncheckedCast()
            }
            null == node17 -> {
                if (!filter17.nodeType.isInstance(node)) return@forEach reset()
                filter17.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node17 = node.uncheckedCast()
            }
            null == node18 -> {
                if (!filter18.nodeType.isInstance(node)) return@forEach reset()
                filter18.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node18 = node.uncheckedCast()
            }
            null == node19 -> {
                if (!filter19.nodeType.isInstance(node)) return@forEach reset()
                filter19.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node19 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!, node3!!, node4!!, node5!!, node6!!, node7!!, node8!!, node9!!, node10!!, node11!!, node12!!, node13!!, node14!!, node15!!, node16!!, node17!!, node18!!, node19!!) ?: return false
                instructions.insert(node19, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node19) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, nodeType3: Class, nodeType4: Class, nodeType5: Class, nodeType6: Class, nodeType7: Class, nodeType8: Class, nodeType9: Class, nodeType10: Class, nodeType11: Class, nodeType12: Class, nodeType13: Class, nodeType14: Class, nodeType15: Class, nodeType16: Class, nodeType17: Class, nodeType18: Class, nodeType19: Class, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11, node12: T12, node13: T13, node14: T14, node15: T15, node16: T16, node17: T17, node18: T18, node19: T19) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), nodeType3.toInstructionNodeFilter(), nodeType4.toInstructionNodeFilter(), nodeType5.toInstructionNodeFilter(), nodeType6.toInstructionNodeFilter(), nodeType7.toInstructionNodeFilter(), nodeType8.toInstructionNodeFilter(), nodeType9.toInstructionNodeFilter(), nodeType10.toInstructionNodeFilter(), nodeType11.toInstructionNodeFilter(), nodeType12.toInstructionNodeFilter(), nodeType13.toInstructionNodeFilter(), nodeType14.toInstructionNodeFilter(), nodeType15.toInstructionNodeFilter(), nodeType16.toInstructionNodeFilter(), nodeType17.toInstructionNodeFilter(), nodeType18.toInstructionNodeFilter(), nodeType19.toInstructionNodeFilter(), instructionsGenerator)


fun  MethodNode.replaceInstructions(filter1: InstructionNodeFilter, filter2: InstructionNodeFilter, filter3: InstructionNodeFilter, filter4: InstructionNodeFilter, filter5: InstructionNodeFilter, filter6: InstructionNodeFilter, filter7: InstructionNodeFilter, filter8: InstructionNodeFilter, filter9: InstructionNodeFilter, filter10: InstructionNodeFilter, filter11: InstructionNodeFilter, filter12: InstructionNodeFilter, filter13: InstructionNodeFilter, filter14: InstructionNodeFilter, filter15: InstructionNodeFilter, filter16: InstructionNodeFilter, filter17: InstructionNodeFilter, filter18: InstructionNodeFilter, filter19: InstructionNodeFilter, filter20: InstructionNodeFilter, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11, node12: T12, node13: T13, node14: T14, node15: T15, node16: T16, node17: T17, node18: T18, node19: T19, node20: T20) -> InsnList?): Boolean {
    val instructions = this.instructions ?: return false
    if (instructions.size() < 20) return false

    val unusedLabelNodes = this.unusedLabelNodes
    if (instructions.size() - unusedLabelNodes.size < 20) return false

    fun canBeUsed(node: AbstractInsnNode) = node !is LineNumberNode && node !in unusedLabelNodes

    var node1: T1? = null
    var node2: T2? = null
    var node3: T3? = null
    var node4: T4? = null
    var node5: T5? = null
    var node6: T6? = null
    var node7: T7? = null
    var node8: T8? = null
    var node9: T9? = null
    var node10: T10? = null
    var node11: T11? = null
    var node12: T12? = null
    var node13: T13? = null
    var node14: T14? = null
    var node15: T15? = null
    var node16: T16? = null
    var node17: T17? = null
    var node18: T18? = null
    var node19: T19? = null
    var node20: T20? = null

    fun reset() {
        node1 = null
        node2 = null
        node3 = null
        node4 = null
        node5 = null
        node6 = null
        node7 = null
        node8 = null
        node9 = null
        node10 = null
        node11 = null
        node12 = null
        node13 = null
        node14 = null
        node15 = null
        node16 = null
        node17 = null
        node18 = null
        node19 = null
        node20 = null
    }

    instructions.forEach { node ->
        if (!canBeUsed(node)) return@forEach
        when {
            null == node1 -> {
                if (!filter1.nodeType.isInstance(node)) return@forEach reset()
                filter1.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node1 = node.uncheckedCast()
            }
            null == node2 -> {
                if (!filter2.nodeType.isInstance(node)) return@forEach reset()
                filter2.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node2 = node.uncheckedCast()
            }
            null == node3 -> {
                if (!filter3.nodeType.isInstance(node)) return@forEach reset()
                filter3.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node3 = node.uncheckedCast()
            }
            null == node4 -> {
                if (!filter4.nodeType.isInstance(node)) return@forEach reset()
                filter4.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node4 = node.uncheckedCast()
            }
            null == node5 -> {
                if (!filter5.nodeType.isInstance(node)) return@forEach reset()
                filter5.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node5 = node.uncheckedCast()
            }
            null == node6 -> {
                if (!filter6.nodeType.isInstance(node)) return@forEach reset()
                filter6.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node6 = node.uncheckedCast()
            }
            null == node7 -> {
                if (!filter7.nodeType.isInstance(node)) return@forEach reset()
                filter7.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node7 = node.uncheckedCast()
            }
            null == node8 -> {
                if (!filter8.nodeType.isInstance(node)) return@forEach reset()
                filter8.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node8 = node.uncheckedCast()
            }
            null == node9 -> {
                if (!filter9.nodeType.isInstance(node)) return@forEach reset()
                filter9.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node9 = node.uncheckedCast()
            }
            null == node10 -> {
                if (!filter10.nodeType.isInstance(node)) return@forEach reset()
                filter10.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node10 = node.uncheckedCast()
            }
            null == node11 -> {
                if (!filter11.nodeType.isInstance(node)) return@forEach reset()
                filter11.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node11 = node.uncheckedCast()
            }
            null == node12 -> {
                if (!filter12.nodeType.isInstance(node)) return@forEach reset()
                filter12.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node12 = node.uncheckedCast()
            }
            null == node13 -> {
                if (!filter13.nodeType.isInstance(node)) return@forEach reset()
                filter13.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node13 = node.uncheckedCast()
            }
            null == node14 -> {
                if (!filter14.nodeType.isInstance(node)) return@forEach reset()
                filter14.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node14 = node.uncheckedCast()
            }
            null == node15 -> {
                if (!filter15.nodeType.isInstance(node)) return@forEach reset()
                filter15.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node15 = node.uncheckedCast()
            }
            null == node16 -> {
                if (!filter16.nodeType.isInstance(node)) return@forEach reset()
                filter16.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node16 = node.uncheckedCast()
            }
            null == node17 -> {
                if (!filter17.nodeType.isInstance(node)) return@forEach reset()
                filter17.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node17 = node.uncheckedCast()
            }
            null == node18 -> {
                if (!filter18.nodeType.isInstance(node)) return@forEach reset()
                filter18.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node18 = node.uncheckedCast()
            }
            null == node19 -> {
                if (!filter19.nodeType.isInstance(node)) return@forEach reset()
                filter19.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node19 = node.uncheckedCast()
            }
            null == node20 -> {
                if (!filter20.nodeType.isInstance(node)) return@forEach reset()
                filter20.predicate.let { if (null != it && !it(InstructionNodeContext(node.uncheckedCast(), node.getPrevious(::canBeUsed), node.getNext(::canBeUsed)))) return@forEach reset() }
                node20 = node.uncheckedCast()
            }
            else -> {
                val newInstructions = instructionsGenerator(node1!!, node2!!, node3!!, node4!!, node5!!, node6!!, node7!!, node8!!, node9!!, node10!!, node11!!, node12!!, node13!!, node14!!, node15!!, node16!!, node17!!, node18!!, node19!!, node20!!) ?: return false
                instructions.insert(node20, newInstructions)
                var curNode: AbstractInsnNode = node1!!
                while(true) {
                    val next = curNode.next ?: break
                    instructions.remove(curNode)
                    if (curNode == node20) break
                    curNode = next
                }
                return true
            }
        }
    }

    return false
}

fun  MethodNode.replaceInstructions(nodeType1: Class, nodeType2: Class, nodeType3: Class, nodeType4: Class, nodeType5: Class, nodeType6: Class, nodeType7: Class, nodeType8: Class, nodeType9: Class, nodeType10: Class, nodeType11: Class, nodeType12: Class, nodeType13: Class, nodeType14: Class, nodeType15: Class, nodeType16: Class, nodeType17: Class, nodeType18: Class, nodeType19: Class, nodeType20: Class, instructionsGenerator: (node1: T1, node2: T2, node3: T3, node4: T4, node5: T5, node6: T6, node7: T7, node8: T8, node9: T9, node10: T10, node11: T11, node12: T12, node13: T13, node14: T14, node15: T15, node16: T16, node17: T17, node18: T18, node19: T19, node20: T20) -> InsnList) = replaceInstructions(nodeType1.toInstructionNodeFilter(), nodeType2.toInstructionNodeFilter(), nodeType3.toInstructionNodeFilter(), nodeType4.toInstructionNodeFilter(), nodeType5.toInstructionNodeFilter(), nodeType6.toInstructionNodeFilter(), nodeType7.toInstructionNodeFilter(), nodeType8.toInstructionNodeFilter(), nodeType9.toInstructionNodeFilter(), nodeType10.toInstructionNodeFilter(), nodeType11.toInstructionNodeFilter(), nodeType12.toInstructionNodeFilter(), nodeType13.toInstructionNodeFilter(), nodeType14.toInstructionNodeFilter(), nodeType15.toInstructionNodeFilter(), nodeType16.toInstructionNodeFilter(), nodeType17.toInstructionNodeFilter(), nodeType18.toInstructionNodeFilter(), nodeType19.toInstructionNodeFilter(), nodeType20.toInstructionNodeFilter(), instructionsGenerator)





© 2015 - 2025 Weber Informatics LLC | Privacy Policy