core: defprotocol accepts docstring + keyword options (honeysql)

Clojure's defprotocol takes an optional docstring and leading keyword
options (:extend-via-metadata true) before the signatures; jolt's macro
fed the option keyword to (first sig). honeysql declares its InlineValue
protocol exactly that way — with the fix, all four honeysql namespaces
load unmodified from git and the formatter produces correct sqlvecs for
selects/inserts/updates/deletes/joins/:inline. Listed in libraries.md.
This commit is contained in:
Yogthos 2026-06-11 22:56:12 -04:00
parent b2c9970583
commit e1a6d77b0c
3 changed files with 19 additions and 1 deletions

View file

@ -12,5 +12,7 @@ Libraries confirmed to load and pass their conformance checks on Jolt
on the [ring-app example](https://github.com/jolt-lang/examples/tree/main/ring-app)'s
spork/http adapter
* [ring-codec](https://github.com/ring-clojure/ring-codec)
* [honeysql](https://github.com/seancorfield/honeysql) — full formatter + helpers
(select/insert/update/delete/joins/:inline), loaded unmodified from git
* [clojure.jdbc](https://github.com/yogthos/clojure.jdbc) — as [jolt-lang/db](https://github.com/jolt-lang/db)'s
`jdbc.core`, reimplemented over janet sqlite3/pq drivers (SQLite + PostgreSQL)

View file

@ -295,7 +295,15 @@
;; instead of evaluating its fields. methods is a {kw {:name str}} map (only :name
;; is consulted). Each method is a thin dispatch fn over protocol-dispatch.
(defmacro defprotocol [pname & sigs]
(let [methods (reduce (fn [m sig]
;; Clojure's defprotocol takes an optional docstring and leading keyword
;; options (:extend-via-metadata true, honeysql uses it) before the method
;; signatures — drop them (metadata extension is a JVM dispatch detail).
(let [sigs (loop [s sigs]
(cond
(string? (first s)) (recur (rest s))
(keyword? (first s)) (recur (rest (rest s)))
:else s))
methods (reduce (fn [m sig]
(assoc m (keyword (name (first sig))) {:name (name (first sig))}))
{} sigs)]
`(do

View file

@ -48,3 +48,11 @@
"(do (deftype P [n]) (.-n (P. 5)))"]
["dot ctor + method" "5"
"(do (defprotocol G (val-of [_])) (deftype P [n] G (val-of [_] n)) (val-of (P. 5)))"])
# defprotocol accepts Clojure's optional docstring + leading keyword options
# before the signatures (honeysql: :extend-via-metadata true).
(defspec "protocols / defprotocol options"
["docstring + option + method" ":hi"
"(do (defprotocol Pdoc \"docs\" :extend-via-metadata true (greet [x])) (extend-protocol Pdoc String (greet [s] :hi)) (greet \"x\"))"]
["option only" "3"
"(do (defprotocol Popt :extend-via-metadata true (plus2 [x])) (extend-protocol Popt Long (plus2 [n] (+ n 2))) (plus2 1))"])