From ccf93c896afc8baa3823759b4da408cb1f5b4feb Mon Sep 17 00:00:00 2001 From: Yogthos Date: Mon, 22 Jun 2026 10:25:35 -0400 Subject: [PATCH] Resolve :use/:only refers, refer-aware syntax-quote, alias-aware resolve MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three related namespace-resolution fixes surfaced porting the clojure.tools.logging library, all general: - chez-register-spec! treats a :use :only vector like :require :refer, so a (:use [ns :only [names]]) clause actually brings those names in. Before, a bare reference to an :only'd name resolved to nil. - syntax-quote (hc-sq-symbol) qualifies a referred name to its SOURCE namespace, not the compile namespace — so a macro that syntax-quotes a referred var (e.g. clojure.tools.logging/spy reaching clojure.pprint's pprint) expands correctly. - resolve consults :as aliases and :refers like ns-resolve does; (resolve 'alias/name) was returning nil because the alias wasn't expanded. --- host/chez/host-contract.ss | 6 ++++++ host/chez/ns.ss | 15 +++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/host/chez/host-contract.ss b/host/chez/host-contract.ss index 1d1ef33..b5a0a01 100644 --- a/host/chez/host-contract.ss +++ b/host/chez/host-contract.ss @@ -225,6 +225,12 @@ ((hc-special-symbol? nm) form) ; special form: leave bare ((hc-interop-head? nm) form) ; interop (.method / Class. / .-field): bare ((var-cell-lookup "clojure.core" nm) (jolt-symbol "clojure.core" nm)) + ;; a name referred into the compile ns (:require :refer / :use :only) + ;; qualifies to its SOURCE ns, not the compile ns — so a macro that + ;; syntax-quotes a referred var (e.g. clojure.tools.logging/spy using + ;; clojure.pprint's pprint) expands to the real var. + ((chez-resolve-refer (chez-actx-cns ctx) nm) + => (lambda (target) (jolt-symbol target nm))) (else (jolt-symbol (chez-actx-cns ctx) nm))) ; else: qualify to compile ns ;; qualified: if the ns part is an :as alias in the compile ns, resolve it ;; to the target namespace — Clojure resolves the alias part of a qualified diff --git a/host/chez/ns.ss b/host/chez/ns.ss index e20e0f2..8a8cf76 100644 --- a/host/chez/ns.ss +++ b/host/chez/ns.ss @@ -67,7 +67,9 @@ (cond ((string=? (keyword-t-name k) "as") (when (symbol-t? v) (chez-register-alias! cns (symbol-t-name v) target))) - ((string=? (keyword-t-name k) "refer") + ;; :refer (require) and :only (use) both bring unqualified names + ;; into cns resolving to target/name. + ((or (string=? (keyword-t-name k) "refer") (string=? (keyword-t-name k) "only")) (cond ;; :refer :all — bring in every public var (require :refer :all) ((and (keyword? v) (string=? (keyword-t-name v) "all")) @@ -196,11 +198,16 @@ ;; resolve: an unqualified symbol resolves in the current ns then clojure.core; a ;; qualified one in its own ns. Returns the var iff genuinely defined, else nil — ;; never interns an empty cell (var-cell-lookup is non-creating). +;; resolve `sym` in the current ns: a qualified ns part is read as an :as alias +;; (then a real ns); an unqualified name resolves in the current ns, its :refers, +;; then clojure.core. (ns-resolve does the same against an explicit ns.) (define (jolt-resolve sym) - (let* ((sns (symbol-t-ns sym)) (nm (symbol-t-name sym)) + (let* ((cns (chez-current-ns)) + (sns (symbol-t-ns sym)) (nm (symbol-t-name sym)) (c (if (string? sns) - (var-cell-lookup sns nm) - (or (var-cell-lookup (chez-current-ns) nm) + (var-cell-lookup (or (chez-resolve-alias cns sns) sns) nm) + (or (var-cell-lookup cns nm) + (let ((ref (chez-resolve-refer cns nm))) (and ref (var-cell-lookup ref nm))) (var-cell-lookup "clojure.core" nm))))) (if (and c (var-cell-defined? c)) c jolt-nil)))