<commit_before>(ns com.rpl.specter.macros
  (:use [com.rpl.specter.protocols :only [RichNavigator]])
  (:require [com.rpl.specter.impl :as i]
            [clojure.walk :as cljwalk]))

(defn ^:no-doc determine-params-impls [impls]
  (let [grouped (->> impls (map (fn [[n & body]] [n body])) (into {}))]
    (if-not (= #{'select* 'transform*} (-> grouped keys set))
      (i/throw-illegal "defnav must implement select* and transform*, instead got "
                       (keys grouped)))
    grouped))


(defmacro richnav [params & impls]
  (if (empty? params)
    `(reify RichNavigator ~@impls)
    `(i/direct-nav-obj
       (fn ~params
         (reify RichNavigator
           ~@impls)))))


(defmacro nav [params & impls]
  (let [{[[_ s-structure-sym s-next-fn-sym] & s-body] 'select*
         [[_ t-structure-sym t-next-fn-sym] & t-body] 'transform*} (determine-params-impls impls)]
    `(richnav ~params
       (~'select* [this# vals# ~s-structure-sym next-fn#]
         (let [~s-next-fn-sym (fn [s#] (next-fn# vals# s#))]
           ~@s-body))
       (~'transform* [this# vals# ~t-structure-sym next-fn#]
         (let [~t-next-fn-sym (fn [s#] (next-fn# vals# s#))]
           ~@t-body)))))

(defmacro collector [params [_ [_ structure-sym] & body]]
  `(richnav ~params
     (~'select* [this# vals# ~structure-sym next-fn#]
      (next-fn# (conj vals# (do ~@body)) ~structure-sym))
     (~'transform* [this# vals# ~structure-sym next-fn#]
       (next-fn# (conj vals# (do ~@body)) ~structure-sym))))

(defn- helper-name [name method-name]
  (symbol (str name "-" method-name)))

(defmacro defnav [name params & impls]
  ;; remove the "this" param for the helper
  (let [helpers (for [[mname [_ & mparams] & mbody] impls]
                  `(defn ~(helper-name name mname) [~@params ~@mparams] ~@mbody))
        decls (for [[mname & _] impls]
                `(declare ~(helper-name name mname)))]
    `(do
       ~@decls
       ~@helpers
       (def ~name (nav ~params ~@impls)))))

(defmacro defrichnav [name params & impls]
  `(def ~name (richnav ~params ~@impls)))

(defmacro defcollector [name & body]
  `(def ~name (collector ~@body)))


(defn- late-bound-operation [bindings builder-op impls]
  (let [bindings (partition 2 bindings)
        params (map first bindings)
        curr-params (map second bindings)]
    `(let [builder# (~builder-op [~@params] ~@impls)
           curr-params# [~@curr-params]]
       (if (every? (complement i/dynamic-param?) curr-params#)
         (apply builder# curr-params#)
         ;;TODO: should tag with metadata that the return is a direct navigator
         (com.rpl.specter.impl/->DynamicFunction builder# curr-params#)))))

(defmacro late-bound-nav [bindings & impls]
  (late-bound-operation bindings `nav impls))

(defmacro late-bound-collector [bindings impl]
  (late-bound-operation bindings `collector [impl]))

(defmacro late-bound-richnav [bindings & impls]
  (late-bound-operation bindings `richnav impls))

(defmacro with-inline-debug [& body]<commit_msg>remove todo<commit_after>(ns com.rpl.specter.macros
  (:use [com.rpl.specter.protocols :only [RichNavigator]])
  (:require [com.rpl.specter.impl :as i]
            [clojure.walk :as cljwalk]))

(defn ^:no-doc determine-params-impls [impls]
  (let [grouped (->> impls (map (fn [[n & body]] [n body])) (into {}))]
    (if-not (= #{'select* 'transform*} (-> grouped keys set))
      (i/throw-illegal "defnav must implement select* and transform*, instead got "
                       (keys grouped)))
    grouped))


(defmacro richnav [params & impls]
  (if (empty? params)
    `(reify RichNavigator ~@impls)
    `(i/direct-nav-obj
       (fn ~params
         (reify RichNavigator
           ~@impls)))))


(defmacro nav [params & impls]
  (let [{[[_ s-structure-sym s-next-fn-sym] & s-body] 'select*
         [[_ t-structure-sym t-next-fn-sym] & t-body] 'transform*} (determine-params-impls impls)]
    `(richnav ~params
       (~'select* [this# vals# ~s-structure-sym next-fn#]
         (let [~s-next-fn-sym (fn [s#] (next-fn# vals# s#))]
           ~@s-body))
       (~'transform* [this# vals# ~t-structure-sym next-fn#]
         (let [~t-next-fn-sym (fn [s#] (next-fn# vals# s#))]
           ~@t-body)))))

(defmacro collector [params [_ [_ structure-sym] & body]]
  `(richnav ~params
     (~'select* [this# vals# ~structure-sym next-fn#]
      (next-fn# (conj vals# (do ~@body)) ~structure-sym))
     (~'transform* [this# vals# ~structure-sym next-fn#]
       (next-fn# (conj vals# (do ~@body)) ~structure-sym))))

(defn- helper-name [name method-name]
  (symbol (str name "-" method-name)))

(defmacro defnav [name params & impls]
  ;; remove the "this" param for the helper
  (let [helpers (for [[mname [_ & mparams] & mbody] impls]
                  `(defn ~(helper-name name mname) [~@params ~@mparams] ~@mbody))
        decls (for [[mname & _] impls]
                `(declare ~(helper-name name mname)))]
    `(do
       ~@decls
       ~@helpers
       (def ~name (nav ~params ~@impls)))))

(defmacro defrichnav [name params & impls]
  `(def ~name (richnav ~params ~@impls)))

(defmacro defcollector [name & body]
  `(def ~name (collector ~@body)))


(defn- late-bound-operation [bindings builder-op impls]
  (let [bindings (partition 2 bindings)
        params (map first bindings)
        curr-params (map second bindings)]
    `(let [builder# (~builder-op [~@params] ~@impls)
           curr-params# [~@curr-params]]
       (if (every? (complement i/dynamic-param?) curr-params#)
         (apply builder# curr-params#)
         (com.rpl.specter.impl/->DynamicFunction builder# curr-params#)))))

(defmacro late-bound-nav [bindings & impls]
  (late-bound-operation bindings `nav impls))

(defmacro late-bound-collector [bindings impl]
  (late-bound-operation bindings `collector [impl]))

(defmacro late-bound-richnav [bindings & impls]
  (late-bound-operation bindings `richnav impls))

(defmacro with-inline-debug [& body]
{'fraction_non_alphanumeric': 0.1773109243697479, 'fraction_numerical': 0.0003361344537815126, 'mean_word_length': 2.9966420416386836, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7301072', 'n_tokens_mistral': 2190, 'n_tokens_neox': 2132, 'n_words': 540}