Skip to content

Instantly share code, notes, and snippets.

@borkdude
Last active October 29, 2020 02:23
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save borkdude/a391146ad81a06c28fb97ccdc1f64d44 to your computer and use it in GitHub Desktop.
Save borkdude/a391146ad81a06c28fb97ccdc1f64d44 to your computer and use it in GitHub Desktop.
Spec grep: find usages or reify in clojure.core with two or more interfaces. This idea has been implemented in a library now: https://github.com/borkdude/grasp
;; see https://github.com/borkdude/grasp for a more elaborate implementation
(ns script
(:require [clojure.java.io :as io]
[clojure.pprint :refer [pprint]]
[edamame.core :as e]))
(def clojure-core (slurp (io/resource "clojure/core.clj")))
(def parsed (e/parse-string-all clojure-core
{:all true :auto-resolve '{:current clojure.core}}))
(require '[clojure.spec.alpha :as s])
(s/def ::clause (s/cat :sym symbol? :lists (s/+ list?)))
;; find usages of reify with at least two interfaces
(s/def ::pattern
(s/cat :reify #{'reify}
:clauses (s/cat :clause ::clause :clauses (s/+ ::clause))))
(defn matches
[tree spec]
(->> tree
(tree-seq seqable? seq)
(filter #(s/valid? spec %))))
(doseq [m (matches parsed ::pattern)]
(prn (meta m))
(pprint m)
(println))
@borkdude
Copy link
Author

borkdude commented Oct 28, 2020

Output:

{:row 6974, :col 5, :end-row 6988, :end-col 56}
(reify
 clojure.lang.IDeref
 (deref [_] (deref-future fut))
 clojure.lang.IBlockingDeref
 (deref
  [_ timeout-ms timeout-val]
  (deref-future fut timeout-ms timeout-val))
 clojure.lang.IPending
 (isRealized [_] (.isDone fut))
 java.util.concurrent.Future
 (get [_] (.get fut))
 (get [_ timeout unit] (.get fut timeout unit))
 (isCancelled [_] (.isCancelled fut))
 (isDone [_] (.isDone fut))
 (cancel [_ interrupt?] (.cancel fut interrupt?)))

{:row 7107, :col 5, :end-row 7125, :end-col 16}
(reify
 clojure.lang.IDeref
 (deref [_] (.await d) @v)
 clojure.lang.IBlockingDeref
 (deref
  [_ timeout-ms timeout-val]
  (if
   (.await d timeout-ms java.util.concurrent.TimeUnit/MILLISECONDS)
   @v
   timeout-val))
 clojure.lang.IPending
 (isRealized [this] (zero? (.getCount d)))
 clojure.lang.IFn
 (invoke
  [this x]
  (when
   (and (pos? (.getCount d)) (compare-and-set! v d x))
   (.countDown d)
   this)))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment