// Path: src/main/java/io/disassemble/asm/visitor/expr/ExprExtractor.java
// public class ExprExtractor {
// 
//     private static final String EMPTY_STRING = "";
// 
//     public static String extract(BasicExpr expr) {
//         AbstractInsnNode insn = expr.insn();
//         if (insn instanceof IntInsnNode) {
//             int operand = ((IntInsnNode) insn).operand;
//             return Integer.toString(operand);
//         } else if (insn instanceof LdcInsnNode) {
//             Object ldc = ((LdcInsnNode) insn).cst;
//             return (ldc == null ? "null" : ldc.toString());
//         }
//         return EMPTY_STRING;
//     }
// }


import io.disassemble.asm.ClassMethod;
import io.disassemble.asm.visitor.expr.ExprExtractor;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import static org.objectweb.asm.Opcodes.*;

    public String decompile(boolean opaque) {
        String[] args = args(opaque);
        return (owner() + '.' + name() + '(' + String.join(", ", (CharSequence[]) args) + ')');
    }

    // This obviously needs to be improved, it's for debugging purposes, currently.
    private boolean hasOpaque() {
        BasicExpr expr = children.peekLast();
        return expr.opcode() == LDC && ((LdcInsnNode) expr.insn).cst instanceof Number;
    }

    public String[] args(boolean opaque) {
        if (children.isEmpty()) {
            return new String[0];
        }
        boolean skipFirst = (opcode() != INVOKESTATIC && opcode() != INVOKEDYNAMIC);
        String[] args = new String[skipFirst ? (children.size() - 1) : children.size()];
        boolean stripped = false;
        if (opaque && hasOpaque()) {
            args = new String[args.length - 1];
            stripped = true;
        }
        int idx = 0;
        for (BasicExpr child : children) {
            if (skipFirst && child == children.peekFirst()) {
                continue;
            } else if (stripped && (idx + 1) > args.length) {
                continue;
            }
// Path: src/main/java/io/disassemble/asm/visitor/expr/ExprExtractor.java
// public class ExprExtractor {
// 
//     private static final String EMPTY_STRING = "";
// 
//     public static String extract(BasicExpr expr) {
//         AbstractInsnNode insn = expr.insn();
//         if (insn instanceof IntInsnNode) {
//             int operand = ((IntInsnNode) insn).operand;
//             return Integer.toString(operand);
//         } else if (insn instanceof LdcInsnNode) {
//             Object ldc = ((LdcInsnNode) insn).cst;
//             return (ldc == null ? "null" : ldc.toString());
//         }
//         return EMPTY_STRING;
//     }
// }


// Path: src/main/java/io/disassemble/asm/visitor/expr/node/MethodExpr.java
import io.disassemble.asm.ClassMethod;
import io.disassemble.asm.visitor.expr.ExprExtractor;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import static org.objectweb.asm.Opcodes.*;


    public String decompile(boolean opaque) {
        String[] args = args(opaque);
        return (owner() + '.' + name() + '(' + String.join(", ", (CharSequence[]) args) + ')');
    }

    // This obviously needs to be improved, it's for debugging purposes, currently.
    private boolean hasOpaque() {
        BasicExpr expr = children.peekLast();
        return expr.opcode() == LDC && ((LdcInsnNode) expr.insn).cst instanceof Number;
    }

    public String[] args(boolean opaque) {
        if (children.isEmpty()) {
            return new String[0];
        }
        boolean skipFirst = (opcode() != INVOKESTATIC && opcode() != INVOKEDYNAMIC);
        String[] args = new String[skipFirst ? (children.size() - 1) : children.size()];
        boolean stripped = false;
        if (opaque && hasOpaque()) {
            args = new String[args.length - 1];
            stripped = true;
        }
        int idx = 0;
        for (BasicExpr child : children) {
            if (skipFirst && child == children.peekFirst()) {
                continue;
            } else if (stripped && (idx + 1) > args.length) {
                continue;
            }
            String val = ExprExtractor.extract(child);