Open ggeoffrey opened 1 year ago
Minimal repro:
(defmacro my-test-macro [a]
(prn &env)
`[~a])
;; No RCF
(let [a 1]
(my-test-macro a))
;; => {a #object[clojure.lang.Compiler$LocalBinding 0x58d44b9f "clojure.lang.Compiler$LocalBinding@58d44b9f"]}
;; => [1]
;; From inside RCF
(tests
(let [a 1]
(my-test-macro a)) := [1])
;; => {a {:op :binding, :name a, :init {:op :const, :env {:locals {}, :namespaces {}, :ns hyperfiddle.rcf-test}, :form 1}, :form a, :local :let, :children [:init]}}
;; => ✅
It is not clear to me if one can construct a valid instances of LocalBinding. If it is possible then maybe RCF could reconstruct the clojure &env from its own environment.
I tried to produce an instance of LocalBinding, but got an IllegalAccessError
failed to access class clojure.lang.Compiler$Expr
which has package level visibility.
I'm using &env to get all current locals, their primitive type, and their attached metadata.
In my macro, I do the following:
(map (fn[[_k v]] (meta (.-sym v))) &env)
To get all local symbols from &env
.
I also do this:
(try
(when-some [java-class (.getJavaClass expr-ast)]
{:class java-class
:primitive? (.isPrimitive java-class)})
(catch Exception _e))
On each LocalBinding returned from &env
to get the type of the local and it is a primitive or not.
I believe this is the type for what &env returns: https://www.javadoc.io/doc/org.clojure/clojure/1.11.1/clojure/lang/Compiler.LocalBinding.html
So I saw that riddley macro-expander I think seems to create LocalBindings as it macro-expands: https://github.com/ztellman/riddley/blob/master/src/riddley/compiler.clj#L55 and https://github.com/ztellman/riddley/blob/master/src/riddley/Util.java#L8 which you could also do in Clojure I guess.
It does seem you have to somewhat update the Compiler about it, or the creation of the LocalBinding will throw an IllegalAccessError or something of that sort.
Might be a lead?
Reported by @didibus
A minimal repro is welcome