Skip to content

Instantly share code, notes, and snippets.

@escherize
Created August 7, 2024 20:34
Show Gist options
  • Save escherize/82ab64010ece3f076d4014ccf3d17d53 to your computer and use it in GitHub Desktop.
Save escherize/82ab64010ece3f076d4014ccf3d17d53 to your computer and use it in GitHub Desktop.
(ns cycloj.core
(:require [clojure.walk :as walk]
[clojure.repl :as repl]
[clojure.edn :as edn]
[clojure.string :as str]))
(defn r-rresolve [s]
(try (resolve s)
(catch Exception e (try (requiring-resolve s)
(catch Exception e nil)))))
;; (try (slurp (:file (meta (r-rresolve sym))))
;; (catch Exception _ nil))
(defn find-source [sym verbose?]
(when-let [resolved (r-rresolve sym)]
(when verbose? (println "RESOLVED" sym))
(let [{:keys [file line]} (meta resolved)
o (or
(some->> (try (slurp file)
(catch Exception _ nil))
str/split-lines
(drop (dec line))
(str/join "\n")
read-string)
(some-> (try (repl/source (symbol sym))
(catch Exception _ nil))
;; (#(do (def x %) %))
(with-out-str)
(read-string)))]
(when o
(when verbose? (println "FOUND SOURCE FOR" sym " to be :\n" o))
o))))
(defn cyclo-count
([form]
(cyclo-count form (atom 1) #{} false))
([form *n seen verbose?]
(when verbose? (println "FORM: " form))
(walk/postwalk
(fn [s]
(when verbose?
(println "walking " s))
(cond
(#{'if
'if-not
'if-let
'when
'when-not
'when-let
'if-some
'for
'doseq
'dotimes
'loop
'reduce
'transduce} s)
(swap! *n inc)
(and
(coll? s)
(not (#{'defn} (first s)))
(not (contains? seen (first s)))
(find-source (first s) verbose?))
(swap! *n + (cyclo-count
(find-source (first s) verbose?)
(atom 0)
(conj seen (first s))
verbose?))
(and
(coll? s)
(#{'and 'or} (first s)))
(let [exit-branches (- (count s) 1)]
(swap! *n + exit-branches))
(and
(coll? s)
(#{'some-> 'some->>} (first s)))
(let [exit-branches (- (count s) 2)]
(swap! *n + exit-branches))
(and
(coll? s)
(= (first s) 'condp))
(let [exit-branches (quot (- (count s) 2) 2)]
(swap! *n + exit-branches))
(and
(coll? s)
(#{'case 'cond} (first s)))
(let [exit-branches (dec (quot (count s) 2))]
(swap! *n + exit-branches)))
s)
form)
@*n))
(comment
;; macro expand first
;; recursive fns?
(cyclo-count '(+ 1 2))
;; => 1
(cyclo-count '(if x 1 2))
;; => 2
(cyclo-count '(if x (when y 1) 3))
;; => 3
(cyclo-count '(case a 1 b 2 3))
;; => 3
(cyclo-count '(cond a 1 b 2 c 3))
;; => 3
(cyclo-count '(cond a 1 b 2 c 3 d 4))
4
)
(comment
(defn f [x] (if x true false))
(defn g [y] (if (f 3) (f 4) (f 5)))
(cyclo-count '(g 3))
;; => 57
)
(comment
(cyclo-count '(f 3))
(cyclo-count '(g 5))
;; => 57
(cyclo-count '(g (g 5)))
;; => 113
)
(comment
(cyclo-count
'(defn g [y] (if (f 3) (f 4) (f 5))))
)
(comment
(defn h [z] (if (g 3) (g 4) (g 5))))
(comment
(cyclo-count '(f 1)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment