jgpc42 / insn

Functional JVM bytecode generation for Clojure.
Eclipse Public License 1.0
198 stars 5 forks source link

Question: how to express call to default method of interface #11

Closed borkdude closed 2 years ago

borkdude commented 2 years ago

Given the following example:

(ns user)

(require '[insn.core :as insn])

(def class-data
  {:name 'my.pkg.Iterator
   :version 1.8
   :interfaces ['java.util.Iterator]
   :fields [{:flags #{:public :static}, :name "VALUE", :type :boolean, :value true}]
   :methods [{:flags #{:public}, :name "hasNext"
              :desc [:boolean]
              :emit [[:getstatic :this "VALUE" :boolean]
                     [:ireturn]]}
             {:flags #{:public}, :name "remove"
              :emit [[:aload 0]
                     [:invokespecial java.util.Iterator :remove [:void]]
                     [:return]]}]})

(def result (insn/visit class-data))

(def class-object (insn/define class-data))

(-> class-object .newInstance (.hasNext))

The last expression returns true. But when I call the remove method, which is supposed to call the default method of the interface, I get:

(-> class-object .newInstance (.remove))
1. Unhandled java.lang.IncompatibleClassChangeError
   Method 'void java.util.Iterator.remove()' must be InterfaceMethodref constant

In Java this would be:

  java.util.Iterator.super.remove();

How can I write this?

borkdude commented 2 years ago

I kind of figured it out. I need the overload and pass the boolean itf true:

(.visitMethodInsn v &op (util/class-desc cls)
                         mname (util/method-desc desc) true)

but this is currently not supported by insn. Could this be added?

borkdude commented 2 years ago

Btw, if you're open to adding this option, I could try a PR myself. It would be a nice opportunity to learn more about this library.

jgpc42 commented 2 years ago

Sorry for the late reply; I was away from the computer this weekend.

Thanks for bringing this deficiency to my attention. As you noted, this should be a trivial change and I'd be happy to add support for this.

Unless you'd rather send a PR, I'll include this feature along with upgrading the project to test against Clojure 1.11, which I've had on my todo list. I should have this done in the next day or two.

Thanks again.

borkdude commented 2 years ago

Oh, please go ahead :)

jgpc42 commented 2 years ago

I just pushed version 0.5.3 which includes support for the interface flag. Here's a test case adapted from this issue.

Let me know if you have any more issues. Thanks.

borkdude commented 2 years ago

Thanks a lot!