basilisp-lang / basilisp

A Clojure-compatible(-ish) Lisp dialect targeting Python 3.9+
https://basilisp.readthedocs.io
Eclipse Public License 1.0
295 stars 8 forks source link

Error Unquoting deftype across namespaces in macros #1153

Open ikappaki opened 3 days ago

ikappaki commented 3 days ago

Hi,

When trying to unquote a deftype defined in namespace B from namespace A in a macro, the following error occurs:

NameError: name 'TypeOther' is not defined

To reproduce

  1. Create an other.lpy file defining a new type other.lpy
    
    (ns other)

(deftype TypeOther [] (repr [this] "a"))

(TypeOther.)

2. Create an `issue.lpy` file that uses the type in a macro
```clojure
(ns issue
  (:require other)
  (:import other))

(println :type-other (other/TypeOther))

(defmacro issue []
  `(identity ~(other/TypeOther)))

(println :issue (issue))
  1. on the REPL, import the issue namespace, the above error is thrown
    basilisp.user=> (require 'issue)
    :type-other a
    Traceback (most recent call last):
    ...
    File "C:\src\basilisp\src\issue.lpy", line 10, in <module>
    (println :issue (issue))
                    ^^^^^^^
    NameError: name 'TypeOther' is not defined

The same works in Clojure other.clj

(ns other)

(deftype TypeOther []
  Object
  (toString [this] "a"))

issue.clj

(ns issue
  (:require other)
  (:import [other TypeOther]))

(defmacro issue []
  `(identity ~(TypeOther.)))

(println :issue (issue))
user=> (require 'issue)
:issue #object[other.TypeOther 0x3b64ccce a]
nil

Note that to reference the deftype in Clojure, the other namespace must be both :required and the type explicitly :imported.

Encountered while trying to port the hiccup lib to Basilisp for fun in case you are wondering where the latest corner cases are coming from 😅. It goes well so far (praise to your hard work maintaining compatibility with Clojure 🙌), I can compile the lib fine, I'm currently running through the tests. Thanks for the latest fixes.

chrisrink10 commented 3 days ago

Interesting. NameErrors come from the Python VM. So probably the Basilisp compiler is ok with this snippet but emits Python code which makes a direct reference to the name TypeOther rather than a namespaced reference.

I'll have to dig into this more when I have a minute.