PyDecisionGraph 0.3.2.post1__cp315-cp315t-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.cp315t-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.cp315t-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.cp315t-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.cp315t-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.cp315t-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.cp315t-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.cp315t-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.cp315t-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.cp315t-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.cp315t-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.cp315t-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.cp315t-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.cp315t-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.cp315t-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.cp315t-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.cp315t-win_amd64.pyd +0 -0
- tests/bake_eval_probe.cp315t-win_amd64.pyd +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from libcpp cimport bool as c_bool
|
|
2
|
+
|
|
3
|
+
from cbase.allocator_protocol cimport allocator_protocol
|
|
4
|
+
from cbase.bytemap cimport bytemap
|
|
5
|
+
|
|
6
|
+
from .c_const cimport VariableNode, dcg_variable_node
|
|
7
|
+
from .c_logic_group cimport LogicGroup, dcg_logic_group
|
|
8
|
+
from .c_node cimport dcg_node
|
|
9
|
+
from .c_var cimport dcg_var_t, dcg_var_type
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
cdef extern from "decision_graph/decision_tree/bake/c_collections.h":
|
|
13
|
+
const size_t DCG_MAPPING_DEFAULT_CAPACITY
|
|
14
|
+
|
|
15
|
+
ctypedef struct dcg_mapping_lgroup:
|
|
16
|
+
dcg_logic_group base
|
|
17
|
+
bytemap idx_mapping
|
|
18
|
+
dcg_var_t* slots
|
|
19
|
+
size_t n_slots
|
|
20
|
+
size_t capacity
|
|
21
|
+
c_bool frozen
|
|
22
|
+
|
|
23
|
+
dcg_mapping_lgroup* c_dcg_mapping_lgroup_new(const char* name, size_t capacity, allocator_protocol* allocator) noexcept nogil
|
|
24
|
+
void c_dcg_mapping_lgroup_dealloc(dcg_mapping_lgroup* lgroup) noexcept nogil
|
|
25
|
+
void c_dcg_mapping_lgroup_free(dcg_mapping_lgroup* lgroup) noexcept nogil
|
|
26
|
+
void c_dcg_mapping_lgroup_clear(dcg_mapping_lgroup* lgroup) noexcept nogil
|
|
27
|
+
|
|
28
|
+
int c_dcg_mapping_lgroup_set(dcg_mapping_lgroup* lgroup, const char* key, size_t key_len, dcg_var_t* value) noexcept nogil
|
|
29
|
+
int c_dcg_mapping_lgroup_set_ref(dcg_mapping_lgroup* lgroup, const char* key, size_t key_len, dcg_var_t* value) noexcept nogil
|
|
30
|
+
int c_dcg_mapping_lgroup_set_ptr(dcg_mapping_lgroup* lgroup, const char* key, size_t key_len, void* value) noexcept nogil
|
|
31
|
+
int c_dcg_mapping_lgroup_set_double(dcg_mapping_lgroup* lgroup, const char* key, size_t key_len, double value) noexcept nogil
|
|
32
|
+
int c_dcg_mapping_lgroup_set_int(dcg_mapping_lgroup* lgroup, const char* key, size_t key_len, ssize_t value) noexcept nogil
|
|
33
|
+
int c_dcg_mapping_lgroup_set_offset(dcg_mapping_lgroup* lgroup, const char* key, size_t key_len, ssize_t value) noexcept nogil
|
|
34
|
+
int c_dcg_mapping_lgroup_set_bool(dcg_mapping_lgroup* lgroup, const char* key, size_t key_len, c_bool value) noexcept nogil
|
|
35
|
+
|
|
36
|
+
dcg_variable_node* c_dcg_mapping_lgroup_get_node(dcg_mapping_lgroup* lgroup, const char* key, size_t key_len, allocator_protocol* allocator) noexcept nogil
|
|
37
|
+
|
|
38
|
+
int c_dcg_node_mapping_var_node_eval_hook(dcg_node* header, void* user_data) noexcept nogil
|
|
39
|
+
|
|
40
|
+
dcg_var_t* c_dcg_mapping_lgroup_get_slot(const dcg_mapping_lgroup* lgroup, const char* key, size_t key_len) noexcept nogil
|
|
41
|
+
int c_dcg_mapping_lgroup_get_create_slot(dcg_mapping_lgroup* lgroup, const char* key, size_t key_len, const dcg_var_type* var_type, dcg_var_t** out) noexcept nogil
|
|
42
|
+
int c_dcg_mapping_lgroup_get_var_idx(const dcg_mapping_lgroup* lgroup, const char* key, size_t key_len, size_t* out_index) noexcept nogil
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
cdef class LogicMapping(LogicGroup):
|
|
46
|
+
cdef dcg_var_t* c_get_slot(self, const char* key, size_t key_len)
|
|
47
|
+
|
|
48
|
+
cdef dcg_var_t* c_get_create_slot(self, const char* key, size_t key_len, const dcg_var_type* var_type) except NULL
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
cdef class AttrExpression(VariableNode):
|
|
52
|
+
pass
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"""The collection layer: the store a build reads its inputs from.
|
|
2
|
+
|
|
3
|
+
A mapping is a logic group whose entries are keyed by name - the store a build
|
|
4
|
+
runs inside. What is wrapped here is the store, and the read of one entry: the
|
|
5
|
+
capi's ``LogicMapping`` and its ``AttrExpression``, with the read changed from a
|
|
6
|
+
Python expression evaluated later into a node of the graph, which is what a bake
|
|
7
|
+
graph needs.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from .c_const import VariableNode
|
|
13
|
+
from .c_logic_group import LogicGroup
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class LogicMapping(LogicGroup):
|
|
17
|
+
"""A group that holds values, keyed by name.
|
|
18
|
+
|
|
19
|
+
Reading is how entries come to exist: ``mapping[name]`` is a read, not a
|
|
20
|
+
lookup - an entry the store does not hold yet is reserved, and the read
|
|
21
|
+
points at the empty slot, so a graph can be written against a store that is
|
|
22
|
+
filled in later. An entry's type is decided when a value lands in it, which
|
|
23
|
+
is why a read of one is answered by the store rather than by the read's own
|
|
24
|
+
binding.
|
|
25
|
+
|
|
26
|
+
A store's shape is its own to close: ``frozen`` refuses a new entry from then
|
|
27
|
+
on, and leaves what the store already holds - values, reads, writes - working.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, *, name: str | None = None, capacity: int = 0, parent: LogicGroup | None = None, **kwargs: Any) -> None:
|
|
31
|
+
"""Build a store.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
name: The store's name - part of every read's display text, and
|
|
35
|
+
refused when it is long enough to overflow that text.
|
|
36
|
+
capacity: Initial room for entries; the layer's default when 0.
|
|
37
|
+
parent: The group it is built inside, if any.
|
|
38
|
+
|
|
39
|
+
Raises:
|
|
40
|
+
ValueError: When the name is too long for the display buffer.
|
|
41
|
+
MemoryError: When the block cannot be allocated.
|
|
42
|
+
"""
|
|
43
|
+
...
|
|
44
|
+
|
|
45
|
+
def __getitem__(self, key: str) -> AttrExpression:
|
|
46
|
+
"""The read of an entry, reserving the entry when it is new.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
key: Entry name.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
The read - a node of the graph, not the value.
|
|
53
|
+
|
|
54
|
+
Raises:
|
|
55
|
+
KeyError: When the store is frozen and the key is new.
|
|
56
|
+
"""
|
|
57
|
+
...
|
|
58
|
+
|
|
59
|
+
def __getattr__(self, key: str) -> AttrExpression:
|
|
60
|
+
"""The same read, written as an attribute.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
key: Entry name.
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
The read of that entry.
|
|
67
|
+
"""
|
|
68
|
+
...
|
|
69
|
+
|
|
70
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
|
71
|
+
"""Put a value in an entry, reserving the entry when it is new.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
key: Entry name.
|
|
75
|
+
value: Value to store: a bool, int, float, str, or a node's value.
|
|
76
|
+
|
|
77
|
+
Raises:
|
|
78
|
+
RuntimeError: When the C layer refuses the write.
|
|
79
|
+
KeyError: When the store is frozen and the key is new.
|
|
80
|
+
"""
|
|
81
|
+
...
|
|
82
|
+
|
|
83
|
+
def __contains__(self, key: str) -> bool:
|
|
84
|
+
"""Whether an entry is held. Asking does not reserve one.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
key: Entry name.
|
|
88
|
+
"""
|
|
89
|
+
...
|
|
90
|
+
|
|
91
|
+
def __len__(self) -> int:
|
|
92
|
+
"""The entries held, reserved ones included."""
|
|
93
|
+
...
|
|
94
|
+
|
|
95
|
+
def __bool__(self) -> bool:
|
|
96
|
+
"""True when the store holds an entry, reserved ones included."""
|
|
97
|
+
...
|
|
98
|
+
|
|
99
|
+
def update(self, *args: Any, **kwargs: Any) -> None:
|
|
100
|
+
"""Write several entries at once, as :meth:`dict.update` does.
|
|
101
|
+
|
|
102
|
+
Accepts one positional argument - a mapping, or an iterable of key/value
|
|
103
|
+
pairs - and any number of keyword arguments, and writes each pair the way
|
|
104
|
+
``store[key] = value`` does: an entry the store does not hold is reserved
|
|
105
|
+
for it.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
*args: At most one mapping or iterable of pairs.
|
|
109
|
+
**kwargs: Entries to write, by name.
|
|
110
|
+
|
|
111
|
+
Raises:
|
|
112
|
+
TypeError: When more than one positional argument is given.
|
|
113
|
+
RuntimeError: When the C layer refuses a write.
|
|
114
|
+
KeyError: When the store is frozen and a key is new.
|
|
115
|
+
"""
|
|
116
|
+
...
|
|
117
|
+
|
|
118
|
+
def clear(self) -> None:
|
|
119
|
+
"""Empty the store, entry by entry.
|
|
120
|
+
|
|
121
|
+
Every entry is dropped - its value released and its name forgotten -
|
|
122
|
+
while the store itself stays where it was, so ``len`` is 0 afterwards and
|
|
123
|
+
a key the store held is a new entry again. Freezing is not exempt: it
|
|
124
|
+
seals a store's SHAPE against new entries, and this is a store's contents
|
|
125
|
+
leaving.
|
|
126
|
+
|
|
127
|
+
The entries are emptied in place rather than the block being moved, so a
|
|
128
|
+
read built over one keeps a valid address - it reports an unfilled entry,
|
|
129
|
+
not rubbish. What it no longer reports is the value that was there.
|
|
130
|
+
"""
|
|
131
|
+
...
|
|
132
|
+
|
|
133
|
+
@property
|
|
134
|
+
def frozen(self) -> bool:
|
|
135
|
+
"""Whether the store is sealed against new entries.
|
|
136
|
+
|
|
137
|
+
What the store already holds is unaffected: freezing seals its SHAPE,
|
|
138
|
+
not its contents.
|
|
139
|
+
"""
|
|
140
|
+
...
|
|
141
|
+
|
|
142
|
+
@frozen.setter
|
|
143
|
+
def frozen(self, value: bool) -> None:
|
|
144
|
+
"""Seal or unseal the store."""
|
|
145
|
+
...
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class AttrExpression(VariableNode):
|
|
149
|
+
"""The read of one entry in the store a build is inside.
|
|
150
|
+
|
|
151
|
+
A variable node that names the group it reads, which is the whole of the
|
|
152
|
+
difference between this and a bare variable: an entry is what it reads, and
|
|
153
|
+
the store is what answers.
|
|
154
|
+
|
|
155
|
+
A read begins holding WHERE its entry is - the entry's offset in the store,
|
|
156
|
+
which no growth of the store can invalidate - and is resolved to the entry
|
|
157
|
+
itself by its FIRST evaluation, which is where its type comes from. From then
|
|
158
|
+
on the read holds that entry, and the values it reports are the entry's live
|
|
159
|
+
ones for as long as they keep the type it was resolved to.
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
def __init__(self, name: str) -> None:
|
|
163
|
+
"""Build the read of an entry in the active store.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
name: Entry name.
|
|
167
|
+
|
|
168
|
+
Raises:
|
|
169
|
+
RuntimeError: When no group is active.
|
|
170
|
+
TypeError: When the active group is not a store.
|
|
171
|
+
KeyError: When the store is sealed and the entry is new.
|
|
172
|
+
"""
|
|
173
|
+
...
|
|
174
|
+
|
|
175
|
+
@property
|
|
176
|
+
def value(self) -> Any:
|
|
177
|
+
"""The entry's value, read from the store of the moment.
|
|
178
|
+
|
|
179
|
+
The value is read live either way: through the entry's offset while the
|
|
180
|
+
read has not been evaluated, and through the entry itself once it has.
|
|
181
|
+
None when the entry holds nothing yet.
|
|
182
|
+
"""
|
|
183
|
+
...
|
|
184
|
+
|
|
185
|
+
@property
|
|
186
|
+
def logic_group(self) -> LogicMapping:
|
|
187
|
+
"""The store this read names - never None for a read.
|
|
188
|
+
|
|
189
|
+
The base declares the field untyped (the node layer cannot name a group
|
|
190
|
+
without an upward edge, DEPENDENCY.md 4.2); a read is only ever built
|
|
191
|
+
against a store, which is what makes this precise rather than optional.
|
|
192
|
+
"""
|
|
193
|
+
...
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
from cpython.unicode cimport PyUnicode_AsUTF8, PyUnicode_AsUTF8AndSize, PyUnicode_FromStringAndSize
|
|
2
|
+
|
|
3
|
+
from .c_allocator_protocol cimport DCG_DEFAULT_ALLOCATOR
|
|
4
|
+
from .c_logic_group cimport LGM
|
|
5
|
+
from .c_node cimport DCG_NODE_STRING_MAXLEN
|
|
6
|
+
from .c_var cimport c_dcg_var_pypack, c_dcg_var_pyunpack, dcg_ret_code, dcg_var_type
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
cdef class LogicMapping(LogicGroup):
|
|
10
|
+
def __init__(self, *, str name=None, size_t capacity=0, LogicGroup parent=None, **kwargs):
|
|
11
|
+
if name is not None and len(name) > DCG_NODE_STRING_MAXLEN // 4:
|
|
12
|
+
raise ValueError(
|
|
13
|
+
f'A mapping name is part of its reads\' display text: {len(name)} characters leaves no room '
|
|
14
|
+
f'for an entry name. Keep it under {DCG_NODE_STRING_MAXLEN // 4}.'
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
cdef dcg_mapping_lgroup* lgroup = c_dcg_mapping_lgroup_new(
|
|
18
|
+
PyUnicode_AsUTF8(name) if name is not None else NULL,
|
|
19
|
+
capacity,
|
|
20
|
+
DCG_DEFAULT_ALLOCATOR,
|
|
21
|
+
)
|
|
22
|
+
if not lgroup:
|
|
23
|
+
raise MemoryError(f'Failed to allocate {self.__class__.__name__}({name!r}).')
|
|
24
|
+
|
|
25
|
+
# The base group is the first member, so a mapping IS a group.
|
|
26
|
+
self.header = <dcg_logic_group*> lgroup
|
|
27
|
+
self.owner = True
|
|
28
|
+
if parent is not None:
|
|
29
|
+
self.header.parent = parent.header
|
|
30
|
+
LGM.register(self)
|
|
31
|
+
|
|
32
|
+
cdef void c_free_header(self):
|
|
33
|
+
c_dcg_mapping_lgroup_free(<dcg_mapping_lgroup*> self.header)
|
|
34
|
+
|
|
35
|
+
# === Cython Internal Binding ===
|
|
36
|
+
|
|
37
|
+
cdef dcg_var_t* c_get_slot(self, const char* key, size_t key_len):
|
|
38
|
+
return c_dcg_mapping_lgroup_get_slot(<dcg_mapping_lgroup*> self.header, key, key_len)
|
|
39
|
+
|
|
40
|
+
cdef dcg_var_t* c_get_create_slot(self, const char* key, size_t key_len, const dcg_var_type* var_type) except NULL:
|
|
41
|
+
cdef dcg_mapping_lgroup* lgroup = <dcg_mapping_lgroup*> self.header
|
|
42
|
+
cdef dcg_var_t* slot = NULL
|
|
43
|
+
cdef int ret_code = c_dcg_mapping_lgroup_get_create_slot(lgroup, key, key_len, var_type, &slot)
|
|
44
|
+
|
|
45
|
+
if ret_code != dcg_ret_code.DCG_OK:
|
|
46
|
+
if ret_code == dcg_ret_code.DCG_ERR_BUSY:
|
|
47
|
+
raise KeyError(f'<{self.__class__.__name__}> is frozen: no entry named {PyUnicode_FromStringAndSize(key, key_len)!r}.')
|
|
48
|
+
raise RuntimeError(f'c_dcg_mapping_lgroup_get_create_slot failed with err code: {ret_code}')
|
|
49
|
+
return slot
|
|
50
|
+
|
|
51
|
+
# === Python Interfaces ===
|
|
52
|
+
|
|
53
|
+
def __getitem__(self, str key):
|
|
54
|
+
return AttrExpression(key)
|
|
55
|
+
|
|
56
|
+
def __getattr__(self, str key):
|
|
57
|
+
return AttrExpression(key)
|
|
58
|
+
|
|
59
|
+
def __setitem__(self, str key, object value):
|
|
60
|
+
cdef Py_ssize_t key_len = 0
|
|
61
|
+
cdef const char* c_key = PyUnicode_AsUTF8AndSize(key, &key_len)
|
|
62
|
+
cdef dcg_var_t packed
|
|
63
|
+
|
|
64
|
+
c_dcg_var_pypack(&packed, value)
|
|
65
|
+
|
|
66
|
+
cdef int ret_code = c_dcg_mapping_lgroup_set(<dcg_mapping_lgroup*> self.header, c_key, key_len, &packed)
|
|
67
|
+
if ret_code != dcg_ret_code.DCG_OK:
|
|
68
|
+
raise RuntimeError(f'c_dcg_mapping_lgroup_set failed with err code: {ret_code}')
|
|
69
|
+
|
|
70
|
+
def __contains__(self, str key):
|
|
71
|
+
cdef Py_ssize_t key_len = 0
|
|
72
|
+
cdef const char* c_key = PyUnicode_AsUTF8AndSize(key, &key_len)
|
|
73
|
+
return c_dcg_mapping_lgroup_get_slot(<dcg_mapping_lgroup*> self.header, c_key, key_len) != NULL
|
|
74
|
+
|
|
75
|
+
def __len__(self):
|
|
76
|
+
return (<dcg_mapping_lgroup*> self.header).n_slots
|
|
77
|
+
|
|
78
|
+
def __bool__(self):
|
|
79
|
+
return bool((<dcg_mapping_lgroup*> self.header).n_slots)
|
|
80
|
+
|
|
81
|
+
def update(self, *args, **kwargs):
|
|
82
|
+
if len(args) > 1:
|
|
83
|
+
raise TypeError(f'update expected at most 1 argument, got {len(args)}')
|
|
84
|
+
|
|
85
|
+
if args:
|
|
86
|
+
other = args[0]
|
|
87
|
+
if hasattr(other, 'keys'):
|
|
88
|
+
for key in other.keys():
|
|
89
|
+
self[key] = other[key]
|
|
90
|
+
else:
|
|
91
|
+
for key, value in other:
|
|
92
|
+
self[key] = value
|
|
93
|
+
|
|
94
|
+
for key, value in kwargs.items():
|
|
95
|
+
self[key] = value
|
|
96
|
+
|
|
97
|
+
def clear(self):
|
|
98
|
+
c_dcg_mapping_lgroup_clear(<dcg_mapping_lgroup*> self.header)
|
|
99
|
+
|
|
100
|
+
property frozen:
|
|
101
|
+
def __get__(self):
|
|
102
|
+
if not self.header:
|
|
103
|
+
return False
|
|
104
|
+
return bool((<dcg_mapping_lgroup*> self.header).frozen)
|
|
105
|
+
|
|
106
|
+
def __set__(self, bint value):
|
|
107
|
+
(<dcg_mapping_lgroup*> self.header).frozen = value
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
cdef class AttrExpression(VariableNode):
|
|
111
|
+
def __init__(self, str name):
|
|
112
|
+
cdef object active = LGM.active_group
|
|
113
|
+
cdef LogicMapping mapping
|
|
114
|
+
cdef Py_ssize_t key_len = 0
|
|
115
|
+
|
|
116
|
+
if active is None:
|
|
117
|
+
raise RuntimeError(f'No logic group is active: a {self.__class__.__name__} reads the store a build runs inside.')
|
|
118
|
+
if not isinstance(active, LogicMapping):
|
|
119
|
+
raise TypeError(f'The active group is a {type(active).__name__}, not a LogicMapping: there is no store to read {name!r} from.')
|
|
120
|
+
|
|
121
|
+
mapping = <LogicMapping> active
|
|
122
|
+
|
|
123
|
+
cdef const char* key = PyUnicode_AsUTF8AndSize(name, &key_len)
|
|
124
|
+
|
|
125
|
+
# A read names its entry, so the entry is created when the name is new -
|
|
126
|
+
# reserved, since the read names no type of its own.
|
|
127
|
+
mapping.c_get_create_slot(key, key_len, NULL)
|
|
128
|
+
|
|
129
|
+
cdef dcg_variable_node* node = c_dcg_mapping_lgroup_get_node(<dcg_mapping_lgroup*> mapping.header, key, key_len, DCG_DEFAULT_ALLOCATOR)
|
|
130
|
+
if not node:
|
|
131
|
+
raise MemoryError(f'Failed to allocate the {self.__class__.__name__}.')
|
|
132
|
+
|
|
133
|
+
self.header = &node.base
|
|
134
|
+
# The group owns the reads built over its store - it is what allocates
|
|
135
|
+
# them - so this wrapper releases nothing, and it holds the group instead,
|
|
136
|
+
# which is what keeps the store alive for as long as the read is.
|
|
137
|
+
self.owner = False
|
|
138
|
+
self.logic_group = mapping
|
|
139
|
+
self.c_register_node()
|
|
140
|
+
|
|
141
|
+
# === Python Properties ===
|
|
142
|
+
|
|
143
|
+
property value:
|
|
144
|
+
def __get__(self):
|
|
145
|
+
if not self.header:
|
|
146
|
+
raise RuntimeError(f'<{self.__class__.__name__}> not initialized!')
|
|
147
|
+
|
|
148
|
+
cdef dcg_variable_node* node = <dcg_variable_node*> self.header
|
|
149
|
+
if not node.key:
|
|
150
|
+
return None
|
|
151
|
+
|
|
152
|
+
cdef dcg_mapping_lgroup* lgroup = <dcg_mapping_lgroup*> (<LogicMapping> self.logic_group).header
|
|
153
|
+
cdef dcg_var_t* slot = &node.base.out
|
|
154
|
+
|
|
155
|
+
# The read knows WHERE its entry is: until it has been evaluated that
|
|
156
|
+
# is an offset in its own slot - no name lookup, and nothing that a
|
|
157
|
+
# growth of the store can invalidate - and from then on the slot IS
|
|
158
|
+
# the entry, read through.
|
|
159
|
+
if slot.dtype == dcg_var_type.VAR_TYPE_INFERRED or slot.dtype == dcg_var_type.VAR_TYPE_OFFSET:
|
|
160
|
+
return c_dcg_var_pyunpack(&lgroup.slots[slot.value.as_offset])
|
|
161
|
+
return c_dcg_var_pyunpack(slot)
|
|
Binary file
|