(ns nal.deriver.list-expansion
(:require [nal.deriver.utils :refer [walk]]
[clojure.string :as s])) | |
(def max-elements-in-list 7) | |
Finds the first :list element in the rule. | (defn get-list
[prefix statement]
(cond
(and (keyword? statement) (s/starts-with? (str statement) prefix))
statement
(coll? statement) (some identity (map #(get-list prefix %) statement))
:default nil)) |
Generates n symbols with prefix. | (defn gen-symbols [prefix n] (map #(symbol (str prefix (inc %))) (range n))) |
Replaces :list/ with symbols. | (defn replace-list-elemets
[statement l list-name n]
(walk statement
(and (coll? el) (some #{l} el))
(mapcat (fn [e] (if (= l e)
(concat '() (gen-symbols list-name n))
(list e))) el))) |
Fetches name of the list. | (defn list-name [l] (->> l str (drop 6) s/join)) |
(defn expand-:from-element
"Expands :from/ element in rule, so as a result will be created n rules, in
each of them :form/A will be replaced with A1 or A2 or A3, etc."
[statement from-name list-name n]
(map (fn [idx]
(walk statement
(= from-name el) (symbol (str list-name idx))))
(range 1 (inc n)))) | |
Expands rules with :list/ elements, as a result will be created 5 rules, where :list/ will be replaced with A1, A1 A2, ..., A1..A5. | (defn generate-all-lists
[r]
(let [list (get-list ":list" r)
l-name (list-name list)]
(mapcat #(let [st (replace-list-elemets r list l-name %)]
(if-let [from-name (get-list ":from" st)]
(expand-:from-element st from-name l-name %)
[st]))
(range 1 (inc max-elements-in-list))))) |
Checks if rule contains any :list element. | (defn contains-list? [r] (get-list ":list" r)) |