Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Userland macros receives RCF env as &env instead of standard clojure &env value #74

Open
ggeoffrey opened this issue Jan 29, 2023 · 6 comments

Comments

@ggeoffrey
Copy link
Member

Reported by @didibus

A minimal repro is welcome

@ggeoffrey
Copy link
Member Author

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]}}
;; => ✅

@ggeoffrey
Copy link
Member Author

ggeoffrey commented Jan 29, 2023

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.

@dustingetz
Copy link
Member

  • can we monkey-patch the Expr class visibility from userland
  • can we reify something duck typed that matches most userland calls?
  • what is cljs impact

@dustingetz
Copy link
Member

dustingetz commented Jan 29, 2023

@didibus
Copy link

didibus commented Jan 30, 2023

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

@didibus
Copy link

didibus commented Feb 1, 2023

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants