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

Macros defined in ClojureDart cannot reference previously defined functions in same namespace #324

Open
dmg46664 opened this issue Oct 25, 2024 · 3 comments

Comments

@dmg46664
Copy link

Describe the bug

Clojure dart is not able to handle this scenario where a function is defined and used in a subsequent macro.

To Reproduce

(defn gensyms [amt]
  (vec (repeatedly amt gensym)))

(defmacro mk-comp-navs []
  ;; rest of fn altered for brevity...
  (gensyms 1)
  )
Syntax error compiling at (test.cljd:14:3).
Faulty form (defmacro mk-comp-navs [] (gensyms 1))

Expected behavior

This should work.

No doubt because of ClojureDart's two phase macro-expansion, it's not aware of the function defined a few lines above.

This is something that is possible in cljs, so presumably the two phases need to work more in parallel than in sequence, or effectively behave as such.

Assume you're aware of cljs quirks https://code.thheller.com/blog/shadow-cljs/2019/10/12/clojurescript-macros.html
but these require defining aliases etc.

Additional context

I was trying to convert the specter library and came across a problem running the following code.

Pointing cljd at more clj code will highlight more differences with the language. More reason to champion the following suggestion ;-)
https://clojurians.slack.com/archives/C03A6GE8D32/p1729680676173319

I suggest this difference go under the Completeness status of the project given the difference with Clojure core.

@cgrand
Copy link
Contributor

cgrand commented Oct 25, 2024

Add ^:macro-support to the defn name

@dmg46664
Copy link
Author

@cgrand And for defn- and def (reading between the lines) 😆

@dmg46664
Copy link
Author

dmg46664 commented Oct 29, 2024

Hi @cgrand ,

I tried the following in core.cljd

(def
  ^{:macro true
    :macro-support true <------------ here
    :doc "Same as (def name (fn [params* ] exprs*)) or (def
    name (fn ([params* ] exprs*)+)) with any doc-string or attrs added
    to the var metadata. prepost-map defines a map with optional keys
    :pre and :post that contain collections of pre or post conditions."
   :arglists '([name doc-string? attr-map? [params*] prepost-map? body]
                [name doc-string? attr-map? ([params*] prepost-map? body)+ attr-map?])}
 defn (fn defn [&form &env fname & fdecl]

but this didn't solve it.
No doubt I'm bulldozing my way through, not understanding the larger framework. 🤔

So before I go down rabbit holes I thought I'd ask if there are resources that describe:

  1. An overview of how the compiler/core works. (I found the following super useful for cljs https://www.youtube.com/watch?v=kBKIGj1_WAo)
  2. Tools/flags/processes for getting debug output from the compiler when it gets to certain namespaces/sexps. No doubt you have tricks to get at contextual information (presuming that the compiler progresses in a clojurey immutable manner).

Perhaps a doc/working-on-the-compiler.md ?

Edit: Seems the same was asked here #16

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

2 participants