diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a45f425..e2d66dbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added -* Added support for referring imported Python names as by `from ... import ...` (#1154) + * Added support for referring imported Python names as by `from ... import ...` (#1154) + +### Fixed + * Fix a bug where protocols with methods with leading hyphens in the could not be defined (#1230) + * Fix a bug where attempting to `:refer` a non-existent Var from another namespace would throw an unhelpful exception (#1231) ## [v0.3.8] ### Added diff --git a/src/basilisp/core.lpy b/src/basilisp/core.lpy index 5f4e1b41..7878fab9 100644 --- a/src/basilisp/core.lpy +++ b/src/basilisp/core.lpy @@ -5235,8 +5235,12 @@ (seq refer-opt) (let [new-ns-interns (ns-interns new-ns)] (doseq [var-sym refer-opt] - (let [var (get new-ns-interns var-sym)] - (.add-refer current-ns var-sym var)))) + (if-let [var (get new-ns-interns var-sym)] + (.add-refer current-ns var-sym var) + (throw + (ex-info "Cannot find Var in the given namespace" + {:namespace new-ns + :var var-sym}))))) :else nil))))) nil)) @@ -6463,18 +6467,28 @@ :method ~method-name :object-type obj-type#}))))) arglists)))) - (let [dotted-method-name (symbol (str "." (name method-name)))] - `(.register ~(vary-meta method-name assoc :no-warn-on-var-indirection true) - ~interface-name - (fn ~method-name - ~@(map (fn [[obj-sym & args]] - (let [has-varargs (some #(= '& %) args) - clean-args (filter #(not= '& %) args)] - (list `[~obj-sym ~@args] - (if has-varargs - `(apply-method ~obj-sym ~method-name ~@clean-args) - `(~dotted-method-name ~obj-sym ~@clean-args))))) - arglists))))])) + `(.register ~(vary-meta method-name assoc :no-warn-on-var-indirection true) + ~interface-name + (fn ~method-name + ~@(map (fn [[obj-sym & args]] + (let [has-varargs (some #(= '& %) args) + clean-args (filter #(not= '& %) args)] + (list `[~obj-sym ~@args] + (cond + has-varargs + `(apply-method ~obj-sym ~method-name ~@clean-args) + + ;; methods starting with "-" will be interpreted + ;; by the compiler as a property access (which + ;; prohibit arguments to be provided), so we have + ;; to hack around that by accessing the method as + ;; a property and then calling it + (.startswith (name method-name) "-") + `((. ~obj-sym ~method-name) ~@clean-args) + + :else + `(. ~obj-sym ~method-name ~@clean-args))))) + arglists)))])) ;; For each protocol, the following keys are defined: ;; diff --git a/tests/basilisp/test_core_fns.lpy b/tests/basilisp/test_core_fns.lpy index 04394482..9baf4172 100644 --- a/tests/basilisp/test_core_fns.lpy +++ b/tests/basilisp/test_core_fns.lpy @@ -1778,6 +1778,9 @@ (ex-info "This is an exception" {}))))) (is (= :a redeffable)))) +(deftest require-test + (is (thrown? basilisp.lang.exception/ExceptionInfo (require '[basilisp.set :refer [non-existent-var]])))) + (deftest requiring-resolve-test (is (thrown? basilisp.lang.exception/ExceptionInfo (requiring-resolve 'a-symbol))) (is (thrown? basilisp.lang.exception/ExceptionInfo (requiring-resolve :a-keyword))) diff --git a/tests/basilisp/test_protocols.lpy b/tests/basilisp/test_protocols.lpy index 490e3c54..697fe8cf 100644 --- a/tests/basilisp/test_protocols.lpy +++ b/tests/basilisp/test_protocols.lpy @@ -4,6 +4,23 @@ [basilisp.string :as str] [basilisp.test :refer [deftest is are testing]])) +(defprotocol ProtocolWithLeadingHyphenMethod + (-method [this] [this arg1] [this arg1 & args])) + +(extend-protocol ProtocolWithLeadingHyphenMethod + python/str + (-method [this] + "no args") + (-method [this arg1] + "1 arg") + (-method [this arg1 & args] + "varargs")) + +(deftest protocol-method-name-test + (is (= "no args" (-method ""))) + (is (= "1 arg" (-method "" "other"))) + (is (= "varargs" (-method "" "other" "rest")))) + (defprotocol Shape (area [this]))