0

I am following this series to learn how clojure compiler works.

I tried to invoke eval method of StaticMethodExpr using below codes

(ns clojure.lang
  (:use clojure.core)
  (:import [clojure.lang Compiler Compiler$C]))

(def form (read-string "(+ 1 1)") )

(def expr (Compiler/analyze Compiler$C/EXPRESSION form))

(.eval expr)

but no luck and throw IllegalArgumentException:

Unhandled java.lang.IllegalArgumentException
   Can't call public method of non-public class: public
   java.lang.Object clojure.lang.Compiler$StaticMethodExpr.eval()

Is there anything I was missing or is this a bug in jdk ?

1 Answer 1

1

You can still call the method using reflection:

(let [m (.getDeclaredMethod clojure.lang.Compiler$Expr "eval" (make-array Class 0))]
  (.setAccessible m true)
  (defn -eval [expr]
    (.invoke m expr (object-array 0))))

(-eval (clojure.lang.Compiler/analyze clojure.lang.Compiler$C/EXPRESSION '(+ 1 2)))
;= 3

This should be good enough if your goal is to explore.

A reflection-free Java program could call this method on the result of analysing (+ 1 2) via a reference of type clojure.lang.Compiler.HostExpr, which is public, even though neither the declaring interface of clojure.lang.Compiler.Expr nor the actual runtime type are public, so I suppose it is somewhat surprising that setAccessible is required.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.