PyDecisionGraph 0.3.2.post1__cp315-cp315-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- decision_graph/__infra__.pxd +1 -0
- decision_graph/__init__.pxd +1 -0
- decision_graph/__init__.py +39 -0
- decision_graph/decision_tree/__init__.pxd +2 -0
- decision_graph/decision_tree/__init__.py +85 -0
- decision_graph/decision_tree/bake/__infra__.pxd +502 -0
- decision_graph/decision_tree/bake/__init__.pxd +502 -0
- decision_graph/decision_tree/bake/__init__.py +29 -0
- decision_graph/decision_tree/bake/c_action.cp315-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_action.h +324 -0
- decision_graph/decision_tree/bake/c_action.pxd +54 -0
- decision_graph/decision_tree/bake/c_action.pyi +126 -0
- decision_graph/decision_tree/bake/c_action.pyx +65 -0
- decision_graph/decision_tree/bake/c_allocator_protocol.cp315-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_allocator_protocol.pxd +24 -0
- decision_graph/decision_tree/bake/c_allocator_protocol.pyi +61 -0
- decision_graph/decision_tree/bake/c_allocator_protocol.pyx +109 -0
- decision_graph/decision_tree/bake/c_bake.cp315-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_bake.h +629 -0
- decision_graph/decision_tree/bake/c_bake.pxd +52 -0
- decision_graph/decision_tree/bake/c_bake.pyi +151 -0
- decision_graph/decision_tree/bake/c_bake.pyx +142 -0
- decision_graph/decision_tree/bake/c_collections.cp315-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_collections.h +692 -0
- decision_graph/decision_tree/bake/c_collections.pxd +52 -0
- decision_graph/decision_tree/bake/c_collections.pyi +193 -0
- decision_graph/decision_tree/bake/c_collections.pyx +161 -0
- decision_graph/decision_tree/bake/c_const.cp315-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_const.h +395 -0
- decision_graph/decision_tree/bake/c_const.pxd +56 -0
- decision_graph/decision_tree/bake/c_const.pyi +305 -0
- decision_graph/decision_tree/bake/c_const.pyx +278 -0
- decision_graph/decision_tree/bake/c_edge.cp315-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_edge.h +511 -0
- decision_graph/decision_tree/bake/c_edge.pxd +117 -0
- decision_graph/decision_tree/bake/c_edge.pyi +192 -0
- decision_graph/decision_tree/bake/c_edge.pyx +270 -0
- decision_graph/decision_tree/bake/c_eval.h +848 -0
- decision_graph/decision_tree/bake/c_eval.pxd +40 -0
- decision_graph/decision_tree/bake/c_expr.cp315-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_expr.h +1900 -0
- decision_graph/decision_tree/bake/c_expr.pxd +129 -0
- decision_graph/decision_tree/bake/c_expr.pyi +280 -0
- decision_graph/decision_tree/bake/c_expr.pyx +272 -0
- decision_graph/decision_tree/bake/c_hierarchy.cp315-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_hierarchy.h +731 -0
- decision_graph/decision_tree/bake/c_hierarchy.pxd +71 -0
- decision_graph/decision_tree/bake/c_hierarchy.pyi +409 -0
- decision_graph/decision_tree/bake/c_hierarchy.pyx +277 -0
- decision_graph/decision_tree/bake/c_logic_group.cp315-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_logic_group.h +1226 -0
- decision_graph/decision_tree/bake/c_logic_group.pxd +162 -0
- decision_graph/decision_tree/bake/c_logic_group.pyi +264 -0
- decision_graph/decision_tree/bake/c_logic_group.pyx +308 -0
- decision_graph/decision_tree/bake/c_node.cp315-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_node.h +2660 -0
- decision_graph/decision_tree/bake/c_node.pxd +381 -0
- decision_graph/decision_tree/bake/c_node.pyi +438 -0
- decision_graph/decision_tree/bake/c_node.pyx +639 -0
- decision_graph/decision_tree/bake/c_reconstruct.cp315-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_reconstruct.pxd +63 -0
- decision_graph/decision_tree/bake/c_reconstruct.pyi +60 -0
- decision_graph/decision_tree/bake/c_reconstruct.pyx +252 -0
- decision_graph/decision_tree/bake/c_var.cp315-win_amd64.pyd +0 -0
- decision_graph/decision_tree/bake/c_var.h +2054 -0
- decision_graph/decision_tree/bake/c_var.pxd +205 -0
- decision_graph/decision_tree/bake/c_var.pyi +271 -0
- decision_graph/decision_tree/bake/c_var.pyx +228 -0
- decision_graph/decision_tree/capi/__infra__.pxd +33 -0
- decision_graph/decision_tree/capi/__init__.pxd +33 -0
- decision_graph/decision_tree/capi/__init__.py +57 -0
- decision_graph/decision_tree/capi/c_abc.cp315-win_amd64.pyd +0 -0
- decision_graph/decision_tree/capi/c_abc.pxd +246 -0
- decision_graph/decision_tree/capi/c_abc.pyi +770 -0
- decision_graph/decision_tree/capi/c_abc.pyx +1532 -0
- decision_graph/decision_tree/capi/c_collection.cp315-win_amd64.pyd +0 -0
- decision_graph/decision_tree/capi/c_collection.pxd +22 -0
- decision_graph/decision_tree/capi/c_collection.pyi +245 -0
- decision_graph/decision_tree/capi/c_collection.pyx +138 -0
- decision_graph/decision_tree/capi/c_node.cp315-win_amd64.pyd +0 -0
- decision_graph/decision_tree/capi/c_node.pxd +95 -0
- decision_graph/decision_tree/capi/c_node.pyi +492 -0
- decision_graph/decision_tree/capi/c_node.pyx +551 -0
- decision_graph/decision_tree/exc.py +189 -0
- decision_graph/decision_tree/native/__init__.py +57 -0
- decision_graph/decision_tree/native/abc.py +1167 -0
- decision_graph/decision_tree/native/collection.py +134 -0
- decision_graph/decision_tree/native/node.py +521 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_action.c +16320 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_action.h +324 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_allocator_protocol.c +12473 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_bake.c +16485 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_bake.h +629 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_collections.c +17381 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_collections.h +692 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_const.c +20815 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_const.h +395 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_edge.c +20696 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_edge.h +511 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_eval.h +848 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_expr.c +22065 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_expr.h +1900 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_hierarchy.c +23267 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_hierarchy.h +731 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_logic_group.c +22434 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_logic_group.h +1226 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_node.c +28385 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_node.h +2660 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_reconstruct.c +15955 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_var.c +16881 -0
- decision_graph/includes/decision_graph/decision_tree/bake/c_var.h +2054 -0
- decision_graph/includes/decision_graph/decision_tree/capi/c_abc.c +59196 -0
- decision_graph/includes/decision_graph/decision_tree/capi/c_collection.c +19967 -0
- decision_graph/includes/decision_graph/decision_tree/capi/c_node.c +39229 -0
- decision_graph/logic_group/__init__.py +25 -0
- decision_graph/logic_group/base.py +100 -0
- decision_graph/logic_group/pending_request.py +384 -0
- decision_graph/webui/__init__.py +24 -0
- decision_graph/webui/bake/__init__.py +65 -0
- decision_graph/webui/bake/app.py +488 -0
- decision_graph/webui/bake/static/d3.v7.min.js +2 -0
- decision_graph/webui/bake/static/script.js +1440 -0
- decision_graph/webui/bake/static/style.css +920 -0
- decision_graph/webui/bake/templates/index.html +183 -0
- decision_graph/webui/bake/templates/offline.html +184 -0
- decision_graph/webui/capi/__init__.py +54 -0
- decision_graph/webui/capi/app.py +366 -0
- decision_graph/webui/capi/main.py +53 -0
- decision_graph/webui/capi/static/d3.v7.min.js +2 -0
- decision_graph/webui/capi/static/script.js +1026 -0
- decision_graph/webui/capi/static/style.css +656 -0
- decision_graph/webui/capi/templates/index.html +93 -0
- decision_graph/webui/capi/templates/offline.html +94 -0
- decision_graph/webui/native/__init__.py +54 -0
- decision_graph/webui/native/app.py +366 -0
- decision_graph/webui/native/main.py +53 -0
- decision_graph/webui/native/static/d3.v7.min.js +2 -0
- decision_graph/webui/native/static/script.js +1026 -0
- decision_graph/webui/native/static/style.css +656 -0
- decision_graph/webui/native/templates/index.html +93 -0
- decision_graph/webui/native/templates/offline.html +94 -0
- pydecisiongraph-0.3.2.post1.dist-info/METADATA +136 -0
- pydecisiongraph-0.3.2.post1.dist-info/RECORD +148 -0
- pydecisiongraph-0.3.2.post1.dist-info/WHEEL +5 -0
- pydecisiongraph-0.3.2.post1.dist-info/licenses/LICENSE +373 -0
- pydecisiongraph-0.3.2.post1.dist-info/top_level.txt +2 -0
- tests/bake_c_evaluator.cp315-win_amd64.pyd +0 -0
- tests/bake_eval_probe.cp315-win_amd64.pyd +0 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
"""The constant layer: the values a graph is given, and the reads of a store.
|
|
2
|
+
|
|
3
|
+
Two node types, and they are opposites. A constant CARRIES a value: what it
|
|
4
|
+
stands for is in the node, and a caller can let the Python object go the moment
|
|
5
|
+
it is built. A variable READS one: its value lives elsewhere - in a store's
|
|
6
|
+
entry, or in another node's slot it was bound to - and the node is the read of
|
|
7
|
+
it, so what it answers with is what that place holds at the moment it is read.
|
|
8
|
+
|
|
9
|
+
Both compose: an operand of an expression, a leaf of a branch.
|
|
10
|
+
|
|
11
|
+
Both compose with a Python value as readily as with a node: a value with no node
|
|
12
|
+
of its own becomes the literal that carries it, so ``5 + read`` and ``read + 5``
|
|
13
|
+
build the same nodes as the forms written out with a ``ConstantNode``.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from typing import Any
|
|
17
|
+
|
|
18
|
+
from .c_expr import BinaryExpression, UnaryExpression
|
|
19
|
+
from .c_logic_group import LogicGroup
|
|
20
|
+
from .c_node import LogicNode
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ConstantNode(LogicNode):
|
|
24
|
+
"""A literal input: the value it stands for is in the node.
|
|
25
|
+
|
|
26
|
+
The C type follows the value - a bool is a true or a false node, an int an
|
|
27
|
+
int, a float a double, a str a string - so there is nothing for a caller to
|
|
28
|
+
say that the value does not already say.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __init__(self, value: Any, *, repr: str | None = None) -> None:
|
|
32
|
+
"""Build a literal for a Python value.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
value: The literal: a bool, an int, a float or a str.
|
|
36
|
+
repr: Display text to copy; the value's own text when not given.
|
|
37
|
+
|
|
38
|
+
Raises:
|
|
39
|
+
TypeError: When the value has no node type - a container, None.
|
|
40
|
+
MemoryError: When the block cannot be allocated.
|
|
41
|
+
"""
|
|
42
|
+
...
|
|
43
|
+
|
|
44
|
+
def __add__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
45
|
+
"""Compose a sum expression with another node."""
|
|
46
|
+
...
|
|
47
|
+
|
|
48
|
+
def __radd__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
49
|
+
"""Compose a sum expression with a Python value on the left."""
|
|
50
|
+
...
|
|
51
|
+
|
|
52
|
+
def __sub__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
53
|
+
"""Compose a difference expression with another node."""
|
|
54
|
+
...
|
|
55
|
+
|
|
56
|
+
def __rsub__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
57
|
+
"""Compose a difference expression with a Python value on the left."""
|
|
58
|
+
...
|
|
59
|
+
|
|
60
|
+
def __mul__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
61
|
+
"""Compose a product expression with another node."""
|
|
62
|
+
...
|
|
63
|
+
|
|
64
|
+
def __rmul__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
65
|
+
"""Compose a product expression with a Python value on the left."""
|
|
66
|
+
...
|
|
67
|
+
|
|
68
|
+
def __truediv__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
69
|
+
"""Compose a division expression with another node."""
|
|
70
|
+
...
|
|
71
|
+
|
|
72
|
+
def __rtruediv__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
73
|
+
"""Compose a division expression with a Python value on the left."""
|
|
74
|
+
...
|
|
75
|
+
|
|
76
|
+
def __floordiv__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
77
|
+
"""Compose a floor-division expression with another node."""
|
|
78
|
+
...
|
|
79
|
+
|
|
80
|
+
def __rfloordiv__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
81
|
+
"""Compose a floor-division expression with a Python value on the left."""
|
|
82
|
+
...
|
|
83
|
+
|
|
84
|
+
def __pow__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
85
|
+
"""Compose a power expression with another node."""
|
|
86
|
+
...
|
|
87
|
+
|
|
88
|
+
def __rpow__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
89
|
+
"""Compose a power expression with a Python value on the left."""
|
|
90
|
+
...
|
|
91
|
+
|
|
92
|
+
def __neg__(self) -> UnaryExpression:
|
|
93
|
+
"""Compose a negation of this literal."""
|
|
94
|
+
...
|
|
95
|
+
|
|
96
|
+
def __eq__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
97
|
+
"""Compose an equality CONDITION with another node.
|
|
98
|
+
|
|
99
|
+
Comparing two nodes builds the comparison node, as it does in the capi -
|
|
100
|
+
the result is a branch, not a bool.
|
|
101
|
+
"""
|
|
102
|
+
...
|
|
103
|
+
|
|
104
|
+
def __ne__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
105
|
+
"""Compose an inequality condition with another node."""
|
|
106
|
+
...
|
|
107
|
+
|
|
108
|
+
def __hash__(self) -> int:
|
|
109
|
+
"""Hash by the C block's address, so a node can key a dict."""
|
|
110
|
+
...
|
|
111
|
+
|
|
112
|
+
def __lt__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
113
|
+
"""Compose a less-than condition with another node."""
|
|
114
|
+
...
|
|
115
|
+
|
|
116
|
+
def __le__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
117
|
+
"""Compose a less-or-equal condition with another node."""
|
|
118
|
+
...
|
|
119
|
+
|
|
120
|
+
def __gt__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
121
|
+
"""Compose a greater-than condition with another node."""
|
|
122
|
+
...
|
|
123
|
+
|
|
124
|
+
def __ge__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
125
|
+
"""Compose a greater-or-equal condition with another node."""
|
|
126
|
+
...
|
|
127
|
+
|
|
128
|
+
def __and__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
129
|
+
"""Compose a conjunction with another node."""
|
|
130
|
+
...
|
|
131
|
+
|
|
132
|
+
def __rand__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
133
|
+
"""Compose a conjunction with a Python value on the left."""
|
|
134
|
+
...
|
|
135
|
+
|
|
136
|
+
def __or__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
137
|
+
"""Compose a disjunction with another node."""
|
|
138
|
+
...
|
|
139
|
+
|
|
140
|
+
def __ror__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
141
|
+
"""Compose a disjunction with a Python value on the left."""
|
|
142
|
+
...
|
|
143
|
+
|
|
144
|
+
def __invert__(self) -> UnaryExpression:
|
|
145
|
+
"""Compose the negation of this literal as a condition."""
|
|
146
|
+
...
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def value(self) -> Any:
|
|
150
|
+
"""The value the literal holds, read by the value's own tag."""
|
|
151
|
+
...
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class VariableNode(LogicNode):
|
|
155
|
+
"""A variable input: a node that reads a value rather than holding one.
|
|
156
|
+
|
|
157
|
+
It holds no value of its own: what it reads is the slot it was bound to, and
|
|
158
|
+
the read is live - whatever that slot holds when the node is read is what the
|
|
159
|
+
node reports. A node built without a slot reflects nothing until one is
|
|
160
|
+
given.
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
def __init__(self, *, key: str | None = None, repr: str | None = None) -> None:
|
|
164
|
+
"""Build a read of an entry.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
key: Entry name in the group it is built inside, if any.
|
|
168
|
+
repr: Display text to copy.
|
|
169
|
+
|
|
170
|
+
Raises:
|
|
171
|
+
MemoryError: When the block cannot be allocated.
|
|
172
|
+
"""
|
|
173
|
+
...
|
|
174
|
+
|
|
175
|
+
def c_bind_const(self, node: ConstantNode) -> None:
|
|
176
|
+
"""Read a literal's slot, so the read follows the value it holds.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
node: The literal whose value this read reflects.
|
|
180
|
+
|
|
181
|
+
Raises:
|
|
182
|
+
RuntimeError: When the C layer refuses the binding.
|
|
183
|
+
"""
|
|
184
|
+
...
|
|
185
|
+
|
|
186
|
+
def __add__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
187
|
+
"""Compose a sum expression with another node."""
|
|
188
|
+
...
|
|
189
|
+
|
|
190
|
+
def __radd__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
191
|
+
"""Compose a sum expression with a Python value on the left."""
|
|
192
|
+
...
|
|
193
|
+
|
|
194
|
+
def __sub__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
195
|
+
"""Compose a difference expression with another node."""
|
|
196
|
+
...
|
|
197
|
+
|
|
198
|
+
def __rsub__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
199
|
+
"""Compose a difference expression with a Python value on the left."""
|
|
200
|
+
...
|
|
201
|
+
|
|
202
|
+
def __mul__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
203
|
+
"""Compose a product expression with another node."""
|
|
204
|
+
...
|
|
205
|
+
|
|
206
|
+
def __rmul__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
207
|
+
"""Compose a product expression with a Python value on the left."""
|
|
208
|
+
...
|
|
209
|
+
|
|
210
|
+
def __truediv__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
211
|
+
"""Compose a division expression with another node."""
|
|
212
|
+
...
|
|
213
|
+
|
|
214
|
+
def __rtruediv__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
215
|
+
"""Compose a division expression with a Python value on the left."""
|
|
216
|
+
...
|
|
217
|
+
|
|
218
|
+
def __floordiv__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
219
|
+
"""Compose a floor-division expression with another node."""
|
|
220
|
+
...
|
|
221
|
+
|
|
222
|
+
def __rfloordiv__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
223
|
+
"""Compose a floor-division expression with a Python value on the left."""
|
|
224
|
+
...
|
|
225
|
+
|
|
226
|
+
def __pow__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
227
|
+
"""Compose a power expression with another node."""
|
|
228
|
+
...
|
|
229
|
+
|
|
230
|
+
def __rpow__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
231
|
+
"""Compose a power expression with a Python value on the left."""
|
|
232
|
+
...
|
|
233
|
+
|
|
234
|
+
def __neg__(self) -> UnaryExpression:
|
|
235
|
+
"""Compose a negation of this read."""
|
|
236
|
+
...
|
|
237
|
+
|
|
238
|
+
def __eq__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
239
|
+
"""Compose an equality CONDITION with another node."""
|
|
240
|
+
...
|
|
241
|
+
|
|
242
|
+
def __ne__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
243
|
+
"""Compose an inequality condition with another node."""
|
|
244
|
+
...
|
|
245
|
+
|
|
246
|
+
def __hash__(self) -> int:
|
|
247
|
+
"""Hash by the C block's address, so a node can key a dict."""
|
|
248
|
+
...
|
|
249
|
+
|
|
250
|
+
def __lt__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
251
|
+
"""Compose a less-than condition with another node."""
|
|
252
|
+
...
|
|
253
|
+
|
|
254
|
+
def __le__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
255
|
+
"""Compose a less-or-equal condition with another node."""
|
|
256
|
+
...
|
|
257
|
+
|
|
258
|
+
def __gt__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
259
|
+
"""Compose a greater-than condition with another node."""
|
|
260
|
+
...
|
|
261
|
+
|
|
262
|
+
def __ge__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
263
|
+
"""Compose a greater-or-equal condition with another node."""
|
|
264
|
+
...
|
|
265
|
+
|
|
266
|
+
def __and__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
267
|
+
"""Compose a conjunction with another node."""
|
|
268
|
+
...
|
|
269
|
+
|
|
270
|
+
def __rand__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
271
|
+
"""Compose a conjunction with a Python value on the left."""
|
|
272
|
+
...
|
|
273
|
+
|
|
274
|
+
def __or__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
275
|
+
"""Compose a disjunction with another node."""
|
|
276
|
+
...
|
|
277
|
+
|
|
278
|
+
def __ror__(self, other: LogicNode | bool | int | float | str) -> BinaryExpression:
|
|
279
|
+
"""Compose a disjunction with a Python value on the left."""
|
|
280
|
+
...
|
|
281
|
+
|
|
282
|
+
def __invert__(self) -> UnaryExpression:
|
|
283
|
+
"""Compose the negation of this read as a condition."""
|
|
284
|
+
...
|
|
285
|
+
|
|
286
|
+
@property
|
|
287
|
+
def value(self) -> Any:
|
|
288
|
+
"""The value the read stands for, read through its binding."""
|
|
289
|
+
...
|
|
290
|
+
|
|
291
|
+
@property
|
|
292
|
+
def key(self) -> str | None:
|
|
293
|
+
"""The store entry this read names, or None when it names none."""
|
|
294
|
+
...
|
|
295
|
+
|
|
296
|
+
@property
|
|
297
|
+
def logic_group(self) -> LogicGroup | None:
|
|
298
|
+
"""The group this read belongs to, or None for a standalone node.
|
|
299
|
+
|
|
300
|
+
The C field is an untyped pointer because the node layer cannot name a
|
|
301
|
+
group without an upward edge (DEPENDENCY.md 4.2); what it holds is the
|
|
302
|
+
group the read was built inside, which is a store's entry in the case
|
|
303
|
+
that matters - see ``c_collections.AttrExpression``.
|
|
304
|
+
"""
|
|
305
|
+
...
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
from cpython.unicode cimport PyUnicode_AsUTF8, PyUnicode_AsUTF8AndSize, PyUnicode_FromString
|
|
2
|
+
|
|
3
|
+
from .c_allocator_protocol cimport DCG_DEFAULT_ALLOCATOR
|
|
4
|
+
from .c_expr cimport BinaryExpression, UnaryExpression, dcg_op_code
|
|
5
|
+
from .c_node cimport c_dcg_node_set_repr
|
|
6
|
+
from .c_var cimport c_dcg_var_pypack, c_dcg_var_pyunpack, dcg_ret_code
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
cdef class ConstantNode(LogicNode):
|
|
10
|
+
def __init__(self, object value, *, str repr=None):
|
|
11
|
+
cdef dcg_constant_node* node = NULL
|
|
12
|
+
cdef int ret_code
|
|
13
|
+
|
|
14
|
+
if isinstance(value, bool):
|
|
15
|
+
node = c_dcg_node_new_const_bool(value, DCG_DEFAULT_ALLOCATOR)
|
|
16
|
+
elif isinstance(value, int):
|
|
17
|
+
node = c_dcg_node_new_const_int(value, DCG_DEFAULT_ALLOCATOR)
|
|
18
|
+
elif isinstance(value, float):
|
|
19
|
+
node = c_dcg_node_new_const_double(value, DCG_DEFAULT_ALLOCATOR)
|
|
20
|
+
elif isinstance(value, str):
|
|
21
|
+
node = c_dcg_node_new_const_string(PyUnicode_AsUTF8(value), DCG_DEFAULT_ALLOCATOR)
|
|
22
|
+
else:
|
|
23
|
+
raise TypeError(f'A constant cannot hold {type(value).__name__}: bake has no node type for it.')
|
|
24
|
+
|
|
25
|
+
if not node:
|
|
26
|
+
raise MemoryError('Failed to allocate the ConstantNode.')
|
|
27
|
+
|
|
28
|
+
self.header = &node.base
|
|
29
|
+
self.owner = True
|
|
30
|
+
|
|
31
|
+
if repr is not None:
|
|
32
|
+
ret_code = c_dcg_node_set_repr(self.header, PyUnicode_AsUTF8(repr))
|
|
33
|
+
if ret_code != dcg_ret_code.DCG_OK:
|
|
34
|
+
raise RuntimeError(f'c_dcg_node_set_repr failed with err code: {ret_code}')
|
|
35
|
+
|
|
36
|
+
self.c_register_node()
|
|
37
|
+
|
|
38
|
+
# === Python Operators ===
|
|
39
|
+
#
|
|
40
|
+
# A constant composes into an expression the same way an expression does,
|
|
41
|
+
# and it names the expression classes directly: the two families are the
|
|
42
|
+
# concrete structures of one layer, and a sub-dependency inside a layer is
|
|
43
|
+
# allowed (DEPENDENCY.md rule 2). The operand is the node base, which is the
|
|
44
|
+
# one type both families can name.
|
|
45
|
+
|
|
46
|
+
def __add__(self, object other):
|
|
47
|
+
return BinaryExpression(dcg_op_code.DCG_OP_ADD, self, c_dcg_node_pypack(other))
|
|
48
|
+
|
|
49
|
+
def __radd__(self, object other):
|
|
50
|
+
return BinaryExpression(dcg_op_code.DCG_OP_ADD, c_dcg_node_pypack(other), self)
|
|
51
|
+
|
|
52
|
+
def __sub__(self, object other):
|
|
53
|
+
return BinaryExpression(dcg_op_code.DCG_OP_SUB, self, c_dcg_node_pypack(other))
|
|
54
|
+
|
|
55
|
+
def __rsub__(self, object other):
|
|
56
|
+
return BinaryExpression(dcg_op_code.DCG_OP_SUB, c_dcg_node_pypack(other), self)
|
|
57
|
+
|
|
58
|
+
def __mul__(self, object other):
|
|
59
|
+
return BinaryExpression(dcg_op_code.DCG_OP_MUL, self, c_dcg_node_pypack(other))
|
|
60
|
+
|
|
61
|
+
def __rmul__(self, object other):
|
|
62
|
+
return BinaryExpression(dcg_op_code.DCG_OP_MUL, c_dcg_node_pypack(other), self)
|
|
63
|
+
|
|
64
|
+
def __truediv__(self, object other):
|
|
65
|
+
return BinaryExpression(dcg_op_code.DCG_OP_DIV, self, c_dcg_node_pypack(other))
|
|
66
|
+
|
|
67
|
+
def __rtruediv__(self, object other):
|
|
68
|
+
return BinaryExpression(dcg_op_code.DCG_OP_DIV, c_dcg_node_pypack(other), self)
|
|
69
|
+
|
|
70
|
+
def __floordiv__(self, object other):
|
|
71
|
+
return BinaryExpression(dcg_op_code.DCG_OP_FLOORDIV, self, c_dcg_node_pypack(other))
|
|
72
|
+
|
|
73
|
+
def __rfloordiv__(self, object other):
|
|
74
|
+
return BinaryExpression(dcg_op_code.DCG_OP_FLOORDIV, c_dcg_node_pypack(other), self)
|
|
75
|
+
|
|
76
|
+
def __pow__(self, object other):
|
|
77
|
+
return BinaryExpression(dcg_op_code.DCG_OP_POW, self, c_dcg_node_pypack(other))
|
|
78
|
+
|
|
79
|
+
def __rpow__(self, object other):
|
|
80
|
+
return BinaryExpression(dcg_op_code.DCG_OP_POW, c_dcg_node_pypack(other), self)
|
|
81
|
+
|
|
82
|
+
def __neg__(self):
|
|
83
|
+
return UnaryExpression(dcg_op_code.DCG_OP_NEG, self)
|
|
84
|
+
|
|
85
|
+
def __eq__(self, object other):
|
|
86
|
+
return BinaryExpression(dcg_op_code.DCG_OP_EQ, self, c_dcg_node_pypack(other))
|
|
87
|
+
|
|
88
|
+
def __ne__(self, object other):
|
|
89
|
+
return BinaryExpression(dcg_op_code.DCG_OP_NE, self, c_dcg_node_pypack(other))
|
|
90
|
+
|
|
91
|
+
def __hash__(self):
|
|
92
|
+
return hash(self.address)
|
|
93
|
+
|
|
94
|
+
def __lt__(self, object other):
|
|
95
|
+
return BinaryExpression(dcg_op_code.DCG_OP_LT, self, c_dcg_node_pypack(other))
|
|
96
|
+
|
|
97
|
+
def __le__(self, object other):
|
|
98
|
+
return BinaryExpression(dcg_op_code.DCG_OP_LE, self, c_dcg_node_pypack(other))
|
|
99
|
+
|
|
100
|
+
def __gt__(self, object other):
|
|
101
|
+
return BinaryExpression(dcg_op_code.DCG_OP_GT, self, c_dcg_node_pypack(other))
|
|
102
|
+
|
|
103
|
+
def __ge__(self, object other):
|
|
104
|
+
return BinaryExpression(dcg_op_code.DCG_OP_GE, self, c_dcg_node_pypack(other))
|
|
105
|
+
|
|
106
|
+
def __and__(self, object other):
|
|
107
|
+
return BinaryExpression(dcg_op_code.DCG_OP_AND, self, c_dcg_node_pypack(other))
|
|
108
|
+
|
|
109
|
+
def __rand__(self, object other):
|
|
110
|
+
return BinaryExpression(dcg_op_code.DCG_OP_AND, c_dcg_node_pypack(other), self)
|
|
111
|
+
|
|
112
|
+
def __or__(self, object other):
|
|
113
|
+
return BinaryExpression(dcg_op_code.DCG_OP_OR, self, c_dcg_node_pypack(other))
|
|
114
|
+
|
|
115
|
+
def __ror__(self, object other):
|
|
116
|
+
return BinaryExpression(dcg_op_code.DCG_OP_OR, c_dcg_node_pypack(other), self)
|
|
117
|
+
|
|
118
|
+
def __invert__(self):
|
|
119
|
+
return UnaryExpression(dcg_op_code.DCG_OP_NOT, self)
|
|
120
|
+
|
|
121
|
+
# === Python Properties ===
|
|
122
|
+
|
|
123
|
+
property value:
|
|
124
|
+
def __get__(self):
|
|
125
|
+
if not self.header:
|
|
126
|
+
raise RuntimeError(f'<{self.__class__.__name__}> not initialized!')
|
|
127
|
+
return c_dcg_var_pyunpack(c_dcg_node_const_get(<dcg_constant_node*> self.header))
|
|
128
|
+
|
|
129
|
+
def __set__(self, object value):
|
|
130
|
+
import warnings
|
|
131
|
+
warnings.warn('[DBG] Updating a const node value is debug only, do not use this in prod env. after the value update, a PermissionError will be raised intensionally!')
|
|
132
|
+
|
|
133
|
+
cdef dcg_var_t slot
|
|
134
|
+
c_dcg_var_pypack(&slot, value)
|
|
135
|
+
|
|
136
|
+
cdef int ret_code = c_dcg_node_const_set(<dcg_constant_node*> self.header, slot)
|
|
137
|
+
if ret_code != dcg_ret_code.DCG_OK:
|
|
138
|
+
raise RuntimeError(f'c_dcg_node_const_set failed with err code: {ret_code}')
|
|
139
|
+
|
|
140
|
+
warnings.warn(f'[DBG] {self} value slot updated! Raising PermissionError!')
|
|
141
|
+
raise PermissionError(f'Must not update value of a {self.__class__.__name__}')
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
cdef class VariableNode(LogicNode):
|
|
145
|
+
def __init__(self, *, str key=None, str repr=None):
|
|
146
|
+
cdef dcg_variable_node* node
|
|
147
|
+
cdef Py_ssize_t key_len = 0
|
|
148
|
+
cdef const char* c_key = PyUnicode_AsUTF8AndSize(key, &key_len) if key else NULL
|
|
149
|
+
cdef dcg_logic_group* active_logic_group = c_dcg_lgm_active_group(LogicNode.c_get_manager())
|
|
150
|
+
|
|
151
|
+
node = c_dcg_node_new_var(
|
|
152
|
+
PyUnicode_AsUTF8(repr) if repr is not None else NULL,
|
|
153
|
+
c_key,
|
|
154
|
+
key_len,
|
|
155
|
+
NULL,
|
|
156
|
+
active_logic_group,
|
|
157
|
+
DCG_DEFAULT_ALLOCATOR,
|
|
158
|
+
)
|
|
159
|
+
if not node:
|
|
160
|
+
raise MemoryError('Failed to allocate the VariableNode.')
|
|
161
|
+
|
|
162
|
+
self.header = &node.base
|
|
163
|
+
# With a group given the node is a block OF THAT GROUP, and the group
|
|
164
|
+
# releases it - so the wrapper owns nothing and must free nothing.
|
|
165
|
+
self.owner = active_logic_group == NULL
|
|
166
|
+
self.c_register_node()
|
|
167
|
+
|
|
168
|
+
# === Cython Internal Binding ===
|
|
169
|
+
|
|
170
|
+
cdef void c_bind_slot(self, dcg_var_t* slot):
|
|
171
|
+
cdef int ret_code = c_dcg_node_var_bind(<dcg_variable_node*> self.header, slot)
|
|
172
|
+
if ret_code != dcg_ret_code.DCG_OK:
|
|
173
|
+
raise RuntimeError(f'c_dcg_node_var_bind failed with err code: {ret_code}')
|
|
174
|
+
|
|
175
|
+
# === Python Interfaces ===
|
|
176
|
+
|
|
177
|
+
cpdef void c_bind_const(self, ConstantNode node):
|
|
178
|
+
self.c_bind_slot(&node.header.out)
|
|
179
|
+
|
|
180
|
+
# === Python Operators ===
|
|
181
|
+
|
|
182
|
+
def __add__(self, object other):
|
|
183
|
+
return BinaryExpression(dcg_op_code.DCG_OP_ADD, self, c_dcg_node_pypack(other))
|
|
184
|
+
|
|
185
|
+
def __radd__(self, object other):
|
|
186
|
+
return BinaryExpression(dcg_op_code.DCG_OP_ADD, c_dcg_node_pypack(other), self)
|
|
187
|
+
|
|
188
|
+
def __sub__(self, object other):
|
|
189
|
+
return BinaryExpression(dcg_op_code.DCG_OP_SUB, self, c_dcg_node_pypack(other))
|
|
190
|
+
|
|
191
|
+
def __rsub__(self, object other):
|
|
192
|
+
return BinaryExpression(dcg_op_code.DCG_OP_SUB, c_dcg_node_pypack(other), self)
|
|
193
|
+
|
|
194
|
+
def __mul__(self, object other):
|
|
195
|
+
return BinaryExpression(dcg_op_code.DCG_OP_MUL, self, c_dcg_node_pypack(other))
|
|
196
|
+
|
|
197
|
+
def __rmul__(self, object other):
|
|
198
|
+
return BinaryExpression(dcg_op_code.DCG_OP_MUL, c_dcg_node_pypack(other), self)
|
|
199
|
+
|
|
200
|
+
def __truediv__(self, object other):
|
|
201
|
+
return BinaryExpression(dcg_op_code.DCG_OP_DIV, self, c_dcg_node_pypack(other))
|
|
202
|
+
|
|
203
|
+
def __rtruediv__(self, object other):
|
|
204
|
+
return BinaryExpression(dcg_op_code.DCG_OP_DIV, c_dcg_node_pypack(other), self)
|
|
205
|
+
|
|
206
|
+
def __floordiv__(self, object other):
|
|
207
|
+
return BinaryExpression(dcg_op_code.DCG_OP_FLOORDIV, self, c_dcg_node_pypack(other))
|
|
208
|
+
|
|
209
|
+
def __rfloordiv__(self, object other):
|
|
210
|
+
return BinaryExpression(dcg_op_code.DCG_OP_FLOORDIV, c_dcg_node_pypack(other), self)
|
|
211
|
+
|
|
212
|
+
def __pow__(self, object other):
|
|
213
|
+
return BinaryExpression(dcg_op_code.DCG_OP_POW, self, c_dcg_node_pypack(other))
|
|
214
|
+
|
|
215
|
+
def __rpow__(self, object other):
|
|
216
|
+
return BinaryExpression(dcg_op_code.DCG_OP_POW, c_dcg_node_pypack(other), self)
|
|
217
|
+
|
|
218
|
+
def __neg__(self):
|
|
219
|
+
return UnaryExpression(dcg_op_code.DCG_OP_NEG, self)
|
|
220
|
+
|
|
221
|
+
def __eq__(self, object other):
|
|
222
|
+
return BinaryExpression(dcg_op_code.DCG_OP_EQ, self, c_dcg_node_pypack(other))
|
|
223
|
+
|
|
224
|
+
def __ne__(self, object other):
|
|
225
|
+
return BinaryExpression(dcg_op_code.DCG_OP_NE, self, c_dcg_node_pypack(other))
|
|
226
|
+
|
|
227
|
+
def __hash__(self):
|
|
228
|
+
return hash(self.address)
|
|
229
|
+
|
|
230
|
+
def __lt__(self, object other):
|
|
231
|
+
return BinaryExpression(dcg_op_code.DCG_OP_LT, self, c_dcg_node_pypack(other))
|
|
232
|
+
|
|
233
|
+
def __le__(self, object other):
|
|
234
|
+
return BinaryExpression(dcg_op_code.DCG_OP_LE, self, c_dcg_node_pypack(other))
|
|
235
|
+
|
|
236
|
+
def __gt__(self, object other):
|
|
237
|
+
return BinaryExpression(dcg_op_code.DCG_OP_GT, self, c_dcg_node_pypack(other))
|
|
238
|
+
|
|
239
|
+
def __ge__(self, object other):
|
|
240
|
+
return BinaryExpression(dcg_op_code.DCG_OP_GE, self, c_dcg_node_pypack(other))
|
|
241
|
+
|
|
242
|
+
def __and__(self, object other):
|
|
243
|
+
return BinaryExpression(dcg_op_code.DCG_OP_AND, self, c_dcg_node_pypack(other))
|
|
244
|
+
|
|
245
|
+
def __rand__(self, object other):
|
|
246
|
+
return BinaryExpression(dcg_op_code.DCG_OP_AND, c_dcg_node_pypack(other), self)
|
|
247
|
+
|
|
248
|
+
def __or__(self, object other):
|
|
249
|
+
return BinaryExpression(dcg_op_code.DCG_OP_OR, self, c_dcg_node_pypack(other))
|
|
250
|
+
|
|
251
|
+
def __ror__(self, object other):
|
|
252
|
+
return BinaryExpression(dcg_op_code.DCG_OP_OR, c_dcg_node_pypack(other), self)
|
|
253
|
+
|
|
254
|
+
def __invert__(self):
|
|
255
|
+
return UnaryExpression(dcg_op_code.DCG_OP_NOT, self)
|
|
256
|
+
|
|
257
|
+
# === Python Properties ===
|
|
258
|
+
|
|
259
|
+
property value:
|
|
260
|
+
def __get__(self):
|
|
261
|
+
if not self.header:
|
|
262
|
+
raise RuntimeError(f'<{self.__class__.__name__}> not initialized!')
|
|
263
|
+
return c_dcg_var_pyunpack(&self.header.out)
|
|
264
|
+
|
|
265
|
+
property key:
|
|
266
|
+
def __get__(self):
|
|
267
|
+
if not self.header:
|
|
268
|
+
raise RuntimeError(f'<{self.__class__.__name__}> not initialized!')
|
|
269
|
+
cdef dcg_variable_node* node = <dcg_variable_node*> self.header
|
|
270
|
+
if not node.key:
|
|
271
|
+
return None
|
|
272
|
+
return PyUnicode_FromString(node.key)
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
cdef LogicNode c_dcg_node_pypack(object value):
|
|
276
|
+
if isinstance(value, LogicNode):
|
|
277
|
+
return value
|
|
278
|
+
return ConstantNode(value)
|
|
Binary file
|