-
Notifications
You must be signed in to change notification settings - Fork 110
/
schema.cljc
156 lines (119 loc) · 4.78 KB
/
schema.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
(ns clara.rules.schema
"Schema definition of Clara data structures using Prismatic's Schema library. This includes structures for rules and queries, as well as the schema
for the underlying Rete network itself. This can be used by tools or other libraries working with rules."
(:require [schema.core :as s]))
(s/defn condition-type :- (s/enum :or :not :and :exists :fact :accumulator :test)
"Returns the type of node in a LHS condition expression."
[condition]
(if (map? condition) ; Leaf nodes are maps, per the schema
(cond
(:type condition) :fact
(:accumulator condition) :accumulator
:else :test)
;; Otherwise the node must a sequential that starts with the boolean operator.
(first condition)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Rule and query structure schema.
(def SExpr
(s/pred seq? "s-expression"))
(def FactCondition
{:type s/Any ;(s/either s/Keyword (s/pred symbol?))
:constraints [SExpr]
;; Original constraints preserved for tooling in case a transformation was applied to the condition.
(s/optional-key :original-constraints) [SExpr]
(s/optional-key :fact-binding) s/Keyword
(s/optional-key :args) s/Any
})
(def AccumulatorCondition
{:accumulator s/Any
:from FactCondition
(s/optional-key :result-binding) s/Keyword})
(def TestCondition
{:constraints [SExpr]})
(def LeafCondition
(s/conditional
:type FactCondition
:accumulator AccumulatorCondition
:else TestCondition))
(declare Condition)
(def BooleanCondition
[(s/one (s/enum :or :not :and :exists) "operator")
(s/recursive #'Condition)])
(def Condition
(s/conditional
sequential? BooleanCondition
map? LeafCondition))
(def Rule
{;; :ns-name is currently used to eval the :rhs form of a rule in the same
;; context that it was originally defined in. It is optional and only used
;; when given. It may be used for other purposes in the future.
(s/optional-key :ns-name) s/Symbol
(s/optional-key :name) (s/cond-pre s/Str s/Keyword)
(s/optional-key :doc) s/Str
(s/optional-key :props) {s/Keyword s/Any}
(s/optional-key :env) {s/Keyword s/Any}
:lhs [Condition]
:rhs s/Any})
(def Query
{(s/optional-key :name) (s/cond-pre s/Str s/Keyword)
(s/optional-key :doc) s/Str
(s/optional-key :props) {s/Keyword s/Any}
(s/optional-key :env) {s/Keyword s/Any}
:lhs [Condition]
:params #{s/Keyword}})
(def Production
(s/conditional
:rhs Rule
:else Query))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Schema for the Rete network itself.
(def ConditionNode
{:node-type (s/enum :join :negation :test :accumulator)
:condition LeafCondition
;; Captured environment in which the condition was defined, like closed variables.
;; Most rules (such as those defined by defrule) have no surrounding
;; environment, but user generated rules might.
(s/optional-key :env) {s/Keyword s/Any}
;; Variables used to join to other expressions in the network.
(s/optional-key :join-bindings) #{s/Keyword}
;; Variable bindings used by expressions in this node.
:used-bindings #{s/Keyword}
;; Variable bindings used in the constraints that are not present in the ancestors of this node.
:new-bindings #{s/Keyword}
;; An expression used to filter joined data.
(s/optional-key :join-filter-expressions) LeafCondition
;; Bindings used to perform non-hash joins in the join filter expression.
;; this is a subset of :used-bindings.
(s/optional-key :join-filter-join-bindings) #{s/Keyword}
;; The expression to create the accumulator.
(s/optional-key :accumulator) s/Any
;; The optional fact or accumulator result binding.
(s/optional-key :result-binding) s/Keyword})
(def ProductionNode
{:node-type (s/enum :production :query)
;; Rule for rule nodes.
(s/optional-key :production) Rule
;; Query for query nodes.
(s/optional-key :query) Query
;; Bindings used in the rule right-hand side.
(s/optional-key :bindings) #{s/Keyword}})
;; Alpha network schema.
(def AlphaNode
{:condition FactCondition
;; Opional environment for the alpha node.
(s/optional-key :env) {s/Keyword s/Any}
;; IDs of the beta nodes that are the children.
:beta-children [s/Num]})
;; A graph representing the beta side of the rete network.
(def BetaGraph
{;; Edges from parent to child nodes.
:forward-edges {s/Int #{s/Int}}
;; Edges from child to parent nodes.
:backward-edges {s/Int #{s/Int}}
;; Map of identifier to condition nodes.
:id-to-condition-node {s/Int (s/cond-pre (s/eq :clara.rules.compiler/root-condition)
ConditionNode)}
;; Map of identifier to query or rule nodes.
:id-to-production-node {s/Int ProductionNode}
;; Map of identifier to new bindings created by the corresponding node.
:id-to-new-bindings {s/Int #{s/Keyword}}})