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,395 @@
|
|
|
1
|
+
#ifndef C_DCG_BAKE_CONST_H
|
|
2
|
+
#define C_DCG_BAKE_CONST_H
|
|
3
|
+
|
|
4
|
+
#include <stdbool.h>
|
|
5
|
+
#include <stdint.h>
|
|
6
|
+
#include <stdio.h>
|
|
7
|
+
#include <string.h>
|
|
8
|
+
#include <sys/types.h>
|
|
9
|
+
|
|
10
|
+
#include <cbase/allocator_protocol/c_allocator_protocol.h>
|
|
11
|
+
|
|
12
|
+
#include <decision_graph/decision_tree/bake/c_node.h>
|
|
13
|
+
|
|
14
|
+
/*
|
|
15
|
+
* The input family: what a graph is fed rather than what it computes. Two
|
|
16
|
+
* shapes of it:
|
|
17
|
+
*
|
|
18
|
+
* - a literal, which stands for a value: the family adds no field of its own,
|
|
19
|
+
* so base.out IS the value, every constructor here is a base init plus the
|
|
20
|
+
* value it was given, and the string flavours copy their text into a block
|
|
21
|
+
* nested under the node;
|
|
22
|
+
* - a variable, which stands for a value someone else holds: it names the
|
|
23
|
+
* logic group it reads and the key it reads there, and base.out refers to
|
|
24
|
+
* that entry's slot rather than holding a value of its own.
|
|
25
|
+
*
|
|
26
|
+
* Both are inputs because both are known to the graph from the outside - one
|
|
27
|
+
* because it was written into it, the other because it is read out of a store
|
|
28
|
+
* that outlives it.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
// ========== Constants ==========
|
|
32
|
+
|
|
33
|
+
#ifndef DCG_DEF_REPR_TRUE
|
|
34
|
+
#define DCG_DEF_REPR_TRUE "True"
|
|
35
|
+
#endif
|
|
36
|
+
|
|
37
|
+
#ifndef DCG_DEF_REPR_FALSE
|
|
38
|
+
#define DCG_DEF_REPR_FALSE "False"
|
|
39
|
+
#endif
|
|
40
|
+
|
|
41
|
+
// ========== Structs ==========
|
|
42
|
+
|
|
43
|
+
// clang-format off
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @brief A literal input: the base node, holding its value in base.out.
|
|
47
|
+
*
|
|
48
|
+
* A literal carries nothing beyond the base node - the value it stands for is
|
|
49
|
+
* base.out, which is why this struct has no field of its own. It exists so the
|
|
50
|
+
* literals have a name to construct, cast and dispatch on, and so a future
|
|
51
|
+
* per-type payload (a parsed literal, an interned string) has a home that does
|
|
52
|
+
* not touch every other family.
|
|
53
|
+
*
|
|
54
|
+
* The base node must stay the FIRST member: a dcg_constant_node* is therefore
|
|
55
|
+
* a valid dcg_node*, which is what lets the base graph API walk it.
|
|
56
|
+
*/
|
|
57
|
+
typedef struct dcg_constant_node {
|
|
58
|
+
dcg_node base; // The common node header. Must stay first.
|
|
59
|
+
} dcg_constant_node;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @brief A variable input: a node that reads a value out of a logic group.
|
|
63
|
+
*
|
|
64
|
+
* It holds no value of its own - base.out is a REFERENCE to the entry's slot,
|
|
65
|
+
* so reading the variable reads that slot, live. That is what makes it usable
|
|
66
|
+
* as an input to an expression (c_expr.h binds the out slot of its inputs)
|
|
67
|
+
* while the value itself stays where it belongs, in the group's store.
|
|
68
|
+
*
|
|
69
|
+
* `key` names the entry it reads, and the node owns its copy: the key is the
|
|
70
|
+
* node's, so a caller can hand one in and walk away. `logic_group` is the
|
|
71
|
+
* group the entry belongs to, and is NOT owned - a group serves any number of
|
|
72
|
+
* variables, so it outlives them all and is the caller's to release.
|
|
73
|
+
*
|
|
74
|
+
* How the entry is found is the node's OUT slot, and it changes once: a read a
|
|
75
|
+
* store built is born with the entry's OFFSET in it - `VAR_TYPE_INFERRED`, so
|
|
76
|
+
* nothing reads it as a value - and its first evaluation replaces that offset
|
|
77
|
+
* with a reference to the entry itself. An offset rather than a pointer because
|
|
78
|
+
* a store's `slots` block grows, and growing it moves every entry in it: the
|
|
79
|
+
* index survives the move, and the evaluation that spends it runs before the
|
|
80
|
+
* reference it leaves behind can be dangled (see
|
|
81
|
+
* c_dcg_node_mapping_var_node_eval_hook).
|
|
82
|
+
*
|
|
83
|
+
* A variable that reads no store - one bound by hand to another node's slot -
|
|
84
|
+
* carries no offset at all: its slot is the reference, from the bind on.
|
|
85
|
+
*
|
|
86
|
+
* The pair is what the capi's AttrExpression carries: the group gives the
|
|
87
|
+
* store, the key gives the entry in it.
|
|
88
|
+
*
|
|
89
|
+
* The base node must stay the FIRST member: a dcg_variable_node* is therefore
|
|
90
|
+
* a valid dcg_node*.
|
|
91
|
+
*/
|
|
92
|
+
typedef struct dcg_variable_node {
|
|
93
|
+
dcg_node base; // The common node header. Must stay first.
|
|
94
|
+
const char* key; // Entry name in the group's store.
|
|
95
|
+
dcg_logic_group* logic_group; // The parent group whose store this reads.
|
|
96
|
+
} dcg_variable_node;
|
|
97
|
+
|
|
98
|
+
// clang-format on
|
|
99
|
+
|
|
100
|
+
// ========== Forward Declarations ==========
|
|
101
|
+
|
|
102
|
+
// Lifecycle
|
|
103
|
+
static inline dcg_constant_node* c_dcg_node_new_const(dcg_node_type ntype, const char* repr, allocator_protocol* allocator);
|
|
104
|
+
static inline void c_dcg_node_free_const(dcg_constant_node* node);
|
|
105
|
+
|
|
106
|
+
static inline dcg_constant_node* c_dcg_node_new_const_value(const char* repr, dcg_var_t value, allocator_protocol* allocator);
|
|
107
|
+
static inline dcg_constant_node* c_dcg_node_new_const_bool(bool value, allocator_protocol* allocator);
|
|
108
|
+
static inline dcg_constant_node* c_dcg_node_new_const_double(double value, allocator_protocol* allocator);
|
|
109
|
+
static inline dcg_constant_node* c_dcg_node_new_const_int(ssize_t value, allocator_protocol* allocator);
|
|
110
|
+
static inline dcg_constant_node* c_dcg_node_new_const_string(const char* value, allocator_protocol* allocator);
|
|
111
|
+
|
|
112
|
+
// Reading
|
|
113
|
+
static inline const dcg_var_t* c_dcg_node_const_get(const dcg_constant_node* node);
|
|
114
|
+
static inline int c_dcg_node_const_set(dcg_constant_node* node, dcg_var_t value);
|
|
115
|
+
|
|
116
|
+
// Lifecycle - the variable
|
|
117
|
+
static inline dcg_variable_node* c_dcg_node_new_var(const char* repr, const char* key, size_t key_len, dcg_var_t* value, dcg_logic_group* group, allocator_protocol* allocator);
|
|
118
|
+
static inline int c_dcg_node_var_bind(dcg_variable_node* node, dcg_var_t* value);
|
|
119
|
+
static inline void c_dcg_node_free_var(dcg_variable_node* node);
|
|
120
|
+
|
|
121
|
+
// ========== Lifecycle Methods ==========
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @brief Allocate a literal input of an explicit type.
|
|
125
|
+
*
|
|
126
|
+
* A variable is an input too, but not one this block holds: it carries a key
|
|
127
|
+
* and the group it reads, so it is built by c_dcg_node_new_var() instead.
|
|
128
|
+
*
|
|
129
|
+
* @param ntype A literal type (INPUT / TRUE / FALSE / DOUBLE / STRING / INT).
|
|
130
|
+
* @param repr Display text to copy (may be NULL).
|
|
131
|
+
* @param allocator Allocator for the block; NULL falls back to the plain heap.
|
|
132
|
+
* @return The node, or NULL on OOM / invalid type.
|
|
133
|
+
*/
|
|
134
|
+
static inline dcg_constant_node* c_dcg_node_new_const(dcg_node_type ntype, const char* repr, allocator_protocol* allocator) {
|
|
135
|
+
if (!c_dcg_node_type_is_input(ntype) || ntype == DCG_NODE_VARIABLE) return NULL;
|
|
136
|
+
|
|
137
|
+
dcg_constant_node* node = (dcg_constant_node*) c_ap_alloc(sizeof(dcg_constant_node), allocator);
|
|
138
|
+
if (!node) return NULL;
|
|
139
|
+
|
|
140
|
+
if (c_dcg_node_init(&node->base, ntype, repr) != DCG_OK) {
|
|
141
|
+
c_ap_free_owned(node);
|
|
142
|
+
return NULL;
|
|
143
|
+
}
|
|
144
|
+
#if DCG_EVAL_DIRECT_HOOKS
|
|
145
|
+
#endif
|
|
146
|
+
return node;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @brief Tear down a literal and free its buf.
|
|
151
|
+
*
|
|
152
|
+
* The value lives in the base node, so there is nothing else to release: the
|
|
153
|
+
* base teardown frees the repr, the string payload and the node itself.
|
|
154
|
+
*
|
|
155
|
+
* A variable is an input too, but not one this free takes: its block has a
|
|
156
|
+
* different layout, so the dispatcher routes it to c_dcg_node_free_var()
|
|
157
|
+
* instead of casting it to this one.
|
|
158
|
+
*
|
|
159
|
+
* @param node Node to free (NULL-safe).
|
|
160
|
+
*/
|
|
161
|
+
static inline void c_dcg_node_free_const(dcg_constant_node* node) {
|
|
162
|
+
if (!node) return;
|
|
163
|
+
c_dcg_node_free(&node->base);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// ========== Public APIs - Typed Constructors ==========
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @brief Allocate a constant node holding an explicit value.
|
|
170
|
+
*
|
|
171
|
+
* @param repr Display text to copy (may be NULL).
|
|
172
|
+
* @param value Constant payload (a string payload is copied).
|
|
173
|
+
* @param allocator Allocator for the block; NULL falls back to the plain heap.
|
|
174
|
+
* @return The node, or NULL on OOM.
|
|
175
|
+
*/
|
|
176
|
+
static inline dcg_constant_node* c_dcg_node_new_const_value(const char* repr, dcg_var_t value, allocator_protocol* allocator) {
|
|
177
|
+
dcg_constant_node* node = c_dcg_node_new_const(DCG_NODE_INPUT, repr, allocator);
|
|
178
|
+
if (!node) return NULL;
|
|
179
|
+
|
|
180
|
+
if (c_dcg_node_const_set(node, value) != DCG_OK) {
|
|
181
|
+
c_ap_free_owned(node);
|
|
182
|
+
return NULL;
|
|
183
|
+
}
|
|
184
|
+
return node;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* @brief Allocate a boolean constant.
|
|
189
|
+
*
|
|
190
|
+
* The type follows the value (TRUE / FALSE) and so does the repr
|
|
191
|
+
* (DCG_DEF_REPR_TRUE / DCG_DEF_REPR_FALSE), so there is nothing for the caller
|
|
192
|
+
* to tell it that the payload does not already say.
|
|
193
|
+
*
|
|
194
|
+
* @param value Boolean payload.
|
|
195
|
+
* @param allocator Allocator for the block; NULL falls back to the plain heap.
|
|
196
|
+
* @return The node, or NULL on OOM.
|
|
197
|
+
*/
|
|
198
|
+
static inline dcg_constant_node* c_dcg_node_new_const_bool(bool value, allocator_protocol* allocator) {
|
|
199
|
+
dcg_node_type ntype = value ? DCG_NODE_TRUE : DCG_NODE_FALSE;
|
|
200
|
+
dcg_constant_node* node = c_dcg_node_new_const(ntype, value ? DCG_DEF_REPR_TRUE : DCG_DEF_REPR_FALSE, allocator);
|
|
201
|
+
if (!node) return NULL;
|
|
202
|
+
|
|
203
|
+
(void) c_dcg_var_init_bool(&node->base.out, value);
|
|
204
|
+
return node;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* @brief Allocate a double constant, its repr rendered from the value.
|
|
209
|
+
*
|
|
210
|
+
* @param value Double payload.
|
|
211
|
+
* @param allocator Allocator for the block; NULL falls back to the plain heap.
|
|
212
|
+
* @return The node, or NULL on OOM.
|
|
213
|
+
*/
|
|
214
|
+
static inline dcg_constant_node* c_dcg_node_new_const_double(double value, allocator_protocol* allocator) {
|
|
215
|
+
char repr[DCG_NODE_STRING_MAXLEN];
|
|
216
|
+
(void) snprintf(repr, sizeof(repr), "%g", value);
|
|
217
|
+
|
|
218
|
+
dcg_constant_node* node = c_dcg_node_new_const(DCG_NODE_DOUBLE, repr, allocator);
|
|
219
|
+
if (!node) return NULL;
|
|
220
|
+
|
|
221
|
+
(void) c_dcg_var_init_double(&node->base.out, value);
|
|
222
|
+
return node;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* @brief Allocate an integer constant, its repr rendered from the value.
|
|
227
|
+
*
|
|
228
|
+
* @param value Integer payload.
|
|
229
|
+
* @param allocator Allocator for the block; NULL falls back to the plain heap.
|
|
230
|
+
* @return The node, or NULL on OOM.
|
|
231
|
+
*/
|
|
232
|
+
static inline dcg_constant_node* c_dcg_node_new_const_int(ssize_t value, allocator_protocol* allocator) {
|
|
233
|
+
char repr[DCG_NODE_STRING_MAXLEN];
|
|
234
|
+
(void) snprintf(repr, sizeof(repr), "%zd", value);
|
|
235
|
+
|
|
236
|
+
dcg_constant_node* node = c_dcg_node_new_const(DCG_NODE_INT, repr, allocator);
|
|
237
|
+
if (!node) return NULL;
|
|
238
|
+
|
|
239
|
+
(void) c_dcg_var_init_int(&node->base.out, value);
|
|
240
|
+
return node;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* @brief Allocate a string constant owning a copy of the text.
|
|
245
|
+
*
|
|
246
|
+
* The repr is the text itself, as it is for a string-valued expression.
|
|
247
|
+
*
|
|
248
|
+
* @param value Text to copy (may be NULL).
|
|
249
|
+
* @param allocator Allocator for the block; NULL falls back to the plain heap.
|
|
250
|
+
* @return The node, or NULL on OOM.
|
|
251
|
+
*/
|
|
252
|
+
static inline dcg_constant_node* c_dcg_node_new_const_string(const char* value, allocator_protocol* allocator) {
|
|
253
|
+
dcg_constant_node* node = c_dcg_node_new_const(DCG_NODE_STRING, value, allocator);
|
|
254
|
+
if (!node) return NULL;
|
|
255
|
+
|
|
256
|
+
if (c_dcg_node_set_string(&node->base, value) != DCG_OK) {
|
|
257
|
+
c_ap_free_owned(node);
|
|
258
|
+
return NULL;
|
|
259
|
+
}
|
|
260
|
+
return node;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// ========== Public APIs - Reading ==========
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* @brief The value a constant node stands for.
|
|
267
|
+
*
|
|
268
|
+
* @param node Node to read (NULL-safe).
|
|
269
|
+
* @return The value, or NULL.
|
|
270
|
+
*/
|
|
271
|
+
static inline const dcg_var_t* c_dcg_node_const_get(const dcg_constant_node* node) {
|
|
272
|
+
if (!node) return NULL;
|
|
273
|
+
return &node->base.out;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* @brief Replace the value a constant node stands for.
|
|
278
|
+
*
|
|
279
|
+
* A string value is copied into a block nested under the node, so the caller's
|
|
280
|
+
* text can go away at once; the previous string value is released first.
|
|
281
|
+
*
|
|
282
|
+
* @param node Node to modify.
|
|
283
|
+
* @param value New value.
|
|
284
|
+
* @return DCG_OK, or a DCG_ERR_* code.
|
|
285
|
+
*/
|
|
286
|
+
static inline int c_dcg_node_const_set(dcg_constant_node* node, dcg_var_t value) {
|
|
287
|
+
if (!node) return DCG_ERR_INVALID_ARG;
|
|
288
|
+
if (value.dtype == VAR_TYPE_STRING) return c_dcg_node_set_string(&node->base, value.value.as_string);
|
|
289
|
+
node->base.out = value;
|
|
290
|
+
return DCG_OK;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// ========== Public APIs - The Variable Node ==========
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* @brief Allocate a node that reads an entry out of a logic group.
|
|
297
|
+
*
|
|
298
|
+
* The node's out is a REFERENCE to `value`, so the node reads that value live
|
|
299
|
+
* and hands it to whoever reads the node - an expression bound to it, or a
|
|
300
|
+
* caller inspecting the graph. `value` must outlive the node, which is what the
|
|
301
|
+
* group holding it guarantees.
|
|
302
|
+
*
|
|
303
|
+
* A node built with no slot reflects nothing until c_dcg_node_var_bind() gives
|
|
304
|
+
* it one. That is the late half of the pair: a read often has to exist before
|
|
305
|
+
* the store it reads does, and refusing to build one without a slot would only
|
|
306
|
+
* push the same ordering problem onto the caller.
|
|
307
|
+
*
|
|
308
|
+
* When `group` is given the node is allocated as a BLOCK OF THAT GROUP, so the
|
|
309
|
+
* group owns the read: freeing the group releases every variable built over its
|
|
310
|
+
* store, keys included, without the caller tracking them. The key is a nested
|
|
311
|
+
* block of the NODE either way - a variable owns its own key, not the group -
|
|
312
|
+
* so releasing the node releases the key with it.
|
|
313
|
+
*
|
|
314
|
+
* The two lifetimes are therefore nested - value outlives group, group outlives
|
|
315
|
+
* node - and a node that must outlive its group is built with a NULL group and
|
|
316
|
+
* lives on the caller's slot alone. What must NOT happen is the group going
|
|
317
|
+
* while a graph still holds one of its reads: the graph names a block that is
|
|
318
|
+
* gone, and nothing in the node header can tell.
|
|
319
|
+
*
|
|
320
|
+
* @param repr Display text to copy (may be NULL).
|
|
321
|
+
* @param key Entry name to copy; NULL leaves the node naming no entry.
|
|
322
|
+
* @param key_len Length of key. The copy takes exactly this many bytes, so a
|
|
323
|
+
* key that came out of a store - where a name is a pointer
|
|
324
|
+
* and a length, not a C string - needs no termination.
|
|
325
|
+
* @param value Value slot to reflect (must outlive the node; NULL leaves
|
|
326
|
+
* the node reflecting nothing, for c_dcg_node_var_bind()).
|
|
327
|
+
* @param group Group the entry belongs to (not owned; may be NULL, and
|
|
328
|
+
* owning the node when it is given).
|
|
329
|
+
* @param allocator Allocator for the block; NULL derives it from the group,
|
|
330
|
+
* or falls back to the plain heap when there is none.
|
|
331
|
+
* @return The node, or NULL on OOM.
|
|
332
|
+
*/
|
|
333
|
+
static inline dcg_variable_node* c_dcg_node_new_var(const char* repr, const char* key, size_t key_len, dcg_var_t* value, dcg_logic_group* group, allocator_protocol* allocator) {
|
|
334
|
+
dcg_variable_node* node = group ? (dcg_variable_node*) c_ap_alloc_child(sizeof(dcg_variable_node), allocator, group)
|
|
335
|
+
: (dcg_variable_node*) c_ap_alloc(sizeof(dcg_variable_node), allocator);
|
|
336
|
+
if (!node) return NULL;
|
|
337
|
+
|
|
338
|
+
if (c_dcg_node_init(&node->base, DCG_NODE_VARIABLE, repr) != DCG_OK) {
|
|
339
|
+
c_ap_free_owned(node);
|
|
340
|
+
return NULL;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
node->logic_group = group;
|
|
344
|
+
node->key = NULL;
|
|
345
|
+
|
|
346
|
+
if (key) {
|
|
347
|
+
/* The key is the node's own copy, nested under it, so the caller's text
|
|
348
|
+
* can go away at once - and it is copied before the value is bound, so
|
|
349
|
+
* a failure here leaves nothing to unwind. */
|
|
350
|
+
char* copy = (char*) c_ap_alloc_child(key_len + 1, NULL, node);
|
|
351
|
+
if (!copy) {
|
|
352
|
+
c_ap_free_owned(node);
|
|
353
|
+
return NULL;
|
|
354
|
+
}
|
|
355
|
+
memcpy(copy, key, key_len);
|
|
356
|
+
copy[key_len] = '\0';
|
|
357
|
+
node->key = copy;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (value) (void) c_dcg_var_init_ref(&node->base.out, value);
|
|
361
|
+
else (void) c_dcg_var_init(&node->base.out); /* reflects nothing yet */
|
|
362
|
+
return node;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* @brief Give a variable the slot it reads, after it was built.
|
|
367
|
+
*
|
|
368
|
+
* The node's out becomes a reference to `value`, so from here on the read is
|
|
369
|
+
* live: whatever the slot holds when the node is read is what the node reports.
|
|
370
|
+
* Binding again simply points the read somewhere else.
|
|
371
|
+
*
|
|
372
|
+
* @param node Variable node to modify.
|
|
373
|
+
* @param value Value slot to reflect (must outlive the node).
|
|
374
|
+
* @return DCG_OK, or DCG_ERR_INVALID_ARG.
|
|
375
|
+
*/
|
|
376
|
+
static inline int c_dcg_node_var_bind(dcg_variable_node* node, dcg_var_t* value) {
|
|
377
|
+
if (!node || !value) return DCG_ERR_INVALID_ARG;
|
|
378
|
+
return c_dcg_var_init_ref(&node->base.out, value);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* @brief Tear down a variable node and free its buf.
|
|
383
|
+
*
|
|
384
|
+
* The reflected value is the store's, and the group is the caller's, so the
|
|
385
|
+
* base teardown is the whole of it: it releases the repr, the key and the
|
|
386
|
+
* block.
|
|
387
|
+
*
|
|
388
|
+
* @param node Node to free (NULL-safe).
|
|
389
|
+
*/
|
|
390
|
+
static inline void c_dcg_node_free_var(dcg_variable_node* node) {
|
|
391
|
+
if (!node) return;
|
|
392
|
+
c_dcg_node_free(&node->base);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
#endif // C_DCG_BAKE_CONST_H
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
from libcpp cimport bool as c_bool
|
|
2
|
+
|
|
3
|
+
from cbase.allocator_protocol cimport allocator_protocol
|
|
4
|
+
|
|
5
|
+
from .c_node cimport LogicNode, dcg_node, dcg_node_type
|
|
6
|
+
from .c_var cimport dcg_var_t
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
cdef extern from "decision_graph/decision_tree/bake/c_const.h":
|
|
10
|
+
ctypedef struct dcg_constant_node:
|
|
11
|
+
dcg_node base
|
|
12
|
+
|
|
13
|
+
ctypedef struct dcg_variable_node:
|
|
14
|
+
dcg_node base
|
|
15
|
+
const char* key
|
|
16
|
+
dcg_logic_group* logic_group
|
|
17
|
+
|
|
18
|
+
dcg_constant_node* c_dcg_node_new_const(dcg_node_type ntype, const char* repr, allocator_protocol* allocator) noexcept nogil
|
|
19
|
+
void c_dcg_node_free_const(dcg_constant_node* node) noexcept nogil
|
|
20
|
+
|
|
21
|
+
dcg_constant_node* c_dcg_node_new_const_value(const char* repr, dcg_var_t value, allocator_protocol* allocator) noexcept nogil
|
|
22
|
+
dcg_constant_node* c_dcg_node_new_const_bool(c_bool value, allocator_protocol* allocator) noexcept nogil
|
|
23
|
+
dcg_constant_node* c_dcg_node_new_const_double(double value, allocator_protocol* allocator) noexcept nogil
|
|
24
|
+
dcg_constant_node* c_dcg_node_new_const_int(ssize_t value, allocator_protocol* allocator) noexcept nogil
|
|
25
|
+
dcg_constant_node* c_dcg_node_new_const_string(const char* value, allocator_protocol* allocator) noexcept nogil
|
|
26
|
+
const dcg_var_t* c_dcg_node_const_get(const dcg_constant_node* node) noexcept nogil
|
|
27
|
+
int c_dcg_node_const_set(dcg_constant_node* node, dcg_var_t value) noexcept nogil
|
|
28
|
+
|
|
29
|
+
dcg_variable_node* c_dcg_node_new_var(const char* repr, const char* key, size_t key_len, dcg_var_t* value, dcg_logic_group* group, allocator_protocol* allocator) noexcept nogil
|
|
30
|
+
int c_dcg_node_var_bind(dcg_variable_node* node, dcg_var_t* value) noexcept nogil
|
|
31
|
+
void c_dcg_node_free_var(dcg_variable_node* node) noexcept nogil
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
cdef extern from "decision_graph/decision_tree/bake/c_logic_group.h":
|
|
35
|
+
ctypedef struct dcg_logic_group:
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
ctypedef struct dcg_logic_group_manager:
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
dcg_logic_group* c_dcg_lgm_active_group(const dcg_logic_group_manager* mgr) noexcept nogil
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
cdef class ConstantNode(LogicNode):
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
cdef class VariableNode(LogicNode):
|
|
49
|
+
cdef readonly object logic_group
|
|
50
|
+
|
|
51
|
+
cdef void c_bind_slot(self, dcg_var_t* slot)
|
|
52
|
+
|
|
53
|
+
cpdef void c_bind_const(self, ConstantNode node)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
cdef LogicNode c_dcg_node_pypack(object value)
|