clj-java-decompiler icon indicating copy to clipboard operation
clj-java-decompiler copied to clipboard

Try using CFR for decompilation

Open NoahTheDuke opened this issue 1 year ago • 0 comments

Hearing that Procyon can't decompile leftn made me wonder if other decompilers could. So I whipped this up, and it works (with a lot of unfortunate differences in output formatting).

I don't expect you to use this, but it does demonstrate that it could work.

(decompile
 (letfn [(foo [s]
              (println
               (str "Hello," s " decompiler!")))]
   (foo "world and")))

produces

// Decompiling class: clj_java_decompiler/core$fn__13864
/*
 * Decompiled with CFR 0.152.
 */
package clj_java_decompiler;

import clj_java_decompiler.core$fn__13864$foo__13865;
import clojure.lang.AFunction;
import clojure.lang.IFn;

public final class core$fn__13864
extends AFunction {
    /*
     * WARNING - void declaration
     */
    public static Object invokeStatic() {
        void foo;
        core$fn__13864$foo__13865 core$fn__13864$foo__13865 = null;
        core$fn__13864$foo__13865 = new core$fn__13864$foo__13865();
        return ((IFn)foo).invoke("world and");
    }

    @Override
    public Object invoke() {
        return core$fn__13864.invokeStatic();
    }
}


// Decompiling class: clj_java_decompiler/core$fn__13864$foo__13865
/*
 * Decompiled with CFR 0.152.
 */
package clj_java_decompiler;

import clojure.lang.AFunction;
import clojure.lang.IFn;
import clojure.lang.RT;
import clojure.lang.Var;

public final class core$fn__13864$foo__13865
extends AFunction {
    public static final Var __println = RT.var("clojure.core", "println");
    public static final Var __str = RT.var("clojure.core", "str");

    @Override
    public Object invoke(Object s) {
        core$fn__13864$foo__13865 this_ = null;
        return __println.invoke(__str.invoke("Hello,", s, " decompiler!"));
    }
}


// Decompiling class: cjd__init
/*
 * Decompiled with CFR 0.152.
 */
import clj_java_decompiler.core$fn__13864;
import clojure.lang.Compiler;
import clojure.lang.IFn;
import clojure.lang.RT;
import clojure.lang.Var;

public class cjd__init {
    public static void load() {
        Object object = ((IFn)new core$fn__13864()).invoke();
    }

    static {
        Compiler.pushNSandLoader(RT.classForName("cjd__init").getClassLoader());
        try {
            cjd__init.load();
        }
        catch (Throwable throwable) {
            Var.popThreadBindings();
            throw throwable;
        }
        Var.popThreadBindings();
    }
}

NoahTheDuke avatar Aug 02 '24 15:08 NoahTheDuke