/
hiccup.cljc
78 lines (68 loc) · 2.86 KB
/
hiccup.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
(ns cark.behavior-tree.hiccup
"Provides the services for parsing and compiling the hiccup notation to
a static tree."
(:require [clojure.spec.alpha :as s]
[expound.alpha :as expound]
[cark.behavior-tree.tree :as tree]
[cark.behavior-tree.type :as type]
[cark.behavior-tree.hiccup.spec :as hs]))
(defn prepare
"Prepares the hiccup tree by removing the nil nodes and splicing the
:<> node children into its parent node"
[hiccup]
(let [[tag & rest-h] hiccup
[params rest-h] (if (map? (first rest-h))
[(first rest-h) (rest rest-h)]
[{} rest-h])
children (->> rest-h
(filter identity)
(map prepare)
(reduce (fn [result child]
(if-let [children (and (map? child)
(:splice child))]
(into result children)
(conj result child)))
[]))]
(if (= :<> tag)
{:splice children}
(into [tag params] children))))
(defn parse
"Parses an hiccup behavior tree, returning the parse tree"
([hiccup]
(parse hiccup ::hs/node))
([hiccup spec]
(let [hiccup (prepare hiccup)
parsed (s/conform spec hiccup)]
(if (= ::s/invalid parsed)
(throw (ex-info (str "Failed to parse hiccup tree.\n"
(expound/expound-str spec hiccup))
{:reason (s/explain-data spec hiccup)
:hiccup hiccup}))
parsed))))
(declare parsed->node)
(defn parsed-children->tree
"Compiles the children hiccup nodes, returning their ids and the
updated tree in a pair vector"
[children tree]
(reduce (fn [[ids tree] parsed-node]
(let [[id tree] (parsed->node parsed-node tree)]
[(conj ids id) tree]))
[[] tree] children))
(defn parsed->node
"Compiles a node, setting its meta data and compiled closure in the tree.
This returns the node id and the updated tree."
[parsed tree]
(let [{:keys [tag params children]} parsed
[children-ids tree] (parsed-children->tree children tree)
type (type/get-type tag)
[id tree] (tree/get-next-id tree)
[node tree] ((type/get-compile-func type) tree id tag params children-ids)
tree (tree/set-node-meta tree id {:children-ids children-ids
:tag tag
:params params})]
[id (tree/set-node tree id node)]))
(defn parsed->tree
"Compiles a parsed hiccup tree to a tree, setting its root node id"
[tree parsed]
(let [[id tree] (parsed->node parsed tree)]
(tree/set-root-node-id tree id)))