Skip to content

Instantly share code, notes, and snippets.

@michaelsbradleyjr
Last active November 5, 2021 21:36
  • Star 12 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save michaelsbradleyjr/7509505 to your computer and use it in GitHub Desktop.
Macros and functions which facilitate the development and debugging of other macros and their supporting functions within a ClojureScript project.
(ns my-cljs.macros.debug
(:require [cljs.analyzer :as cljs]
clojure.walk))
(declare ap
cljs-macroexpand*
cljs-macroexpand-1*
cljs-macroexpand-all*
cljs-macroexpand
cljs-macroexpand-1
cljs-macroexpand-all
debug-*
->compiler-console
->js-log
debug-*->*
debug->cons
debug-1->cons
debug-all->cons
debug->js
debug-1->js
debug-all->js
defalias
debug
debug-1
debug-all
expand-symbol
ppstring
prccon)
(def ^:dynamic *out-fn* nil)
;; macros and supporting funcs for macro dev and debug in ClojureScript projects
;; -----------------------------------------------------------------------------
(defmacro ^{:private true} ap
[f]
`(apply ~f (conj 'args '&env)))
(defn cljs-macroexpand*
[env form]
(let [ex (cljs-macroexpand-1* env form)]
(if (identical? ex form)
form
(recur env ex))))
(defn cljs-macroexpand-1*
[env form]
(cljs/macroexpand-1 env form))
(defn cljs-macroexpand-all*
[env form]
(clojure.walk/prewalk (fn [x] (if (seq? x) (cljs-macroexpand* env x) x)) form))
(defmacro cljs-macroexpand
[& args]
(ap cljs-macroexpand*))
(defmacro cljs-macroexpand-1
[& args]
(ap cljs-macroexpand-1*))
(defmacro cljs-macroexpand-all
[& args]
(ap cljs-macroexpand-all*))
(defn- debug-*
[env which expander args]
(let [args (if (< (count args) 2) (conj args nil) args)
[descrip form] args
expanded (expander env form)
expstrng (str "\n"
(str "DESCRIPTION: " (or descrip "(no description supplied)"))
"\n"
"\n"
(str "BEFORE " which
"\n"
"\n"
(ppstring form))
"\n"
(str "AFTER " which
"\n"
"\n"
(ppstring expanded))
"\n")]
(*out-fn* expstrng)))
(defn- ->compiler-console
[val]
`(do ~(prccon val)))
(defn- ->js-log
[val]
`(do (.log js/console ~val)))
(defmacro ^{:private true} debug-*->*
[which out-fn]
(list 'binding ['*out-fn* out-fn]
(list 'debug-* '&env which (symbol (str "cljs-" which "*")) 'args)))
(defmacro debug->cons
[& args]
(debug-*->* "macroexpand" ->compiler-console))
(defmacro debug-1->cons
[& args]
(debug-*->* "macroexpand-1" ->compiler-console))
(defmacro debug-all->cons
[& args]
(debug-*->* "macroexpand-all" ->compiler-console))
(defmacro debug->js
[& args]
(debug-*->* "macroexpand" ->js-log))
(defmacro debug-1->js
[& args]
(debug-*->* "macroexpand-1" ->js-log))
(defmacro debug-all->js
[& args]
(debug-*->* "macroexpand-all" ->js-log))
(defmacro ^{:private true} defalias
([name orig]
`(do
(alter-meta!
(if (.hasRoot (var ~orig))
(def ~name (.getRawRoot (var ~orig)))
(def ~name))
#(conj (dissoc % :macro)
(apply dissoc (meta (var ~orig)) (remove #{:macro} (keys %)))))
(var ~name)))
([name orig doc]
(list `defalias (with-meta name (assoc (meta name) :doc doc)) orig)))
(defalias debug debug->cons)
(defalias debug-1 debug-1->cons)
(defalias debug-all debug-all->cons)
(defn expand-symbol
"Resolves a symbol to a namespaced symbol, relative to some environment as
obtained with &env within a macro definition."
[env sym]
(:name (cljs/resolve-var env sym)))
(defn ppstring
[v]
(with-out-str (clojure.pprint/pprint v)))
(defn prccon
"Prints to the compiler's console at compile time. Sprinkle as needed within
macros and their supporting functions to facilitate debugging during
development."
[& args]
(binding [*out* *err*]
(apply println args)))
@b1412
Copy link

b1412 commented Oct 10, 2015

Nice! They helped me.

@arichiardi
Copy link

It helped me too, the debug function for some reason prints three times but it is not a big deal

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