metac 0.0.1__py3-none-any.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.
- metac/__init__.py +6 -0
- metac/array.py +402 -0
- metac/assignable.py +26 -0
- metac/autotest/__init__.py +298 -0
- metac/autotest/__main__.py +11 -0
- metac/autotest/concepts.py +772 -0
- metac/autotest/elements.py +241 -0
- metac/autotest/matrix.py +150 -0
- metac/autotest/template/@module@.py +10 -0
- metac/avl_set.py +703 -0
- metac/bisectable.py +86 -0
- metac/bit_array.py +440 -0
- metac/bit_vector.py +940 -0
- metac/btree_map.py +151 -0
- metac/btree_set.py +734 -0
- metac/chained_hash_map.py +108 -0
- metac/chained_hash_set.py +365 -0
- metac/circular_buffer.py +802 -0
- metac/cmake/__init__.py +75 -0
- metac/cmake/__main__.py +12 -0
- metac/container.py +119 -0
- metac/core.py +1489 -0
- metac/counter.py +712 -0
- metac/deque.py +440 -0
- metac/doc/__init__.py +73 -0
- metac/doc/__main__.py +11 -0
- metac/doc/catalog.py +387 -0
- metac/doc/containers.md +118 -0
- metac/doc/design.md +174 -0
- metac/doc/mainpage.md +137 -0
- metac/doc/template/.gitignore +12 -0
- metac/doc/template/@module@.py +17 -0
- metac/doc/template/Doxyfile +21 -0
- metac/doc/template/catalog.py +1 -0
- metac/doc/tutorial.md +166 -0
- metac/flat_map.py +157 -0
- metac/flat_multimap.py +394 -0
- metac/flat_multiset.py +100 -0
- metac/flat_set.py +58 -0
- metac/flat_sets.py +459 -0
- metac/hash.py +48 -0
- metac/hashed.py +33 -0
- metac/indexable.py +65 -0
- metac/insertable.py +36 -0
- metac/intrusive_hash_map.py +155 -0
- metac/intrusive_hash_set.py +409 -0
- metac/intrusive_option.py +80 -0
- metac/list.py +309 -0
- metac/mapping.py +460 -0
- metac/memory.py +60 -0
- metac/meson/__init__.py +63 -0
- metac/meson/__main__.py +12 -0
- metac/module.py +506 -0
- metac/multimap.py +566 -0
- metac/multimapping.py +97 -0
- metac/multiset.py +386 -0
- metac/option.py +51 -0
- metac/options.py +326 -0
- metac/ordered.py +37 -0
- metac/packet.py +536 -0
- metac/priority_queue.py +299 -0
- metac/project/__init__.py +63 -0
- metac/project/__main__.py +11 -0
- metac/project/cmake/__init__.py +71 -0
- metac/project/cmake/__main__.py +10 -0
- metac/project/cmake/template/.gitignore +3 -0
- metac/project/cmake/template/.vscode/launch.json +13 -0
- metac/project/cmake/template/@project@.code-workspace +12 -0
- metac/project/cmake/template/CMakeLists.txt +45 -0
- metac/project/cmake/template/CMakePresets.json +206 -0
- metac/project/cmake/template/cmake/MetaC.cmake +121 -0
- metac/project/meson/__init__.py +70 -0
- metac/project/meson/__main__.py +10 -0
- metac/project/meson/template/.gitignore +4 -0
- metac/project/meson/template/.vscode/launch.json +13 -0
- metac/project/meson/template/@project@.code-workspace +12 -0
- metac/project/meson/template/meson.build +110 -0
- metac/project/meson/template/meson.options +5 -0
- metac/project/scons/__init__.py +71 -0
- metac/project/scons/__main__.py +10 -0
- metac/project/scons/template/.gitignore +11 -0
- metac/project/scons/template/.vscode/launch.json +14 -0
- metac/project/scons/template/.vscode/tasks.json +28 -0
- metac/project/scons/template/@project@.code-workspace +12 -0
- metac/project/scons/template/SConstruct +55 -0
- metac/project/scons/template/site_scons/site_tools/metac.py +91 -0
- metac/properties.py +11 -0
- metac/queue.py +255 -0
- metac/random.py +176 -0
- metac/range.py +184 -0
- metac/rb_set.py +630 -0
- metac/record.py +205 -0
- metac/reference.py +216 -0
- metac/sample/__init__.py +41 -0
- metac/sample/__main__.py +12 -0
- metac/sample/template/@module@.c +10 -0
- metac/sample/template/@module@.py +15 -0
- metac/scaffolder.py +56 -0
- metac/scons/__init__.py +159 -0
- metac/scons/__main__.py +12 -0
- metac/sequential.py +35 -0
- metac/set.py +341 -0
- metac/sortable.py +127 -0
- metac/stack.py +240 -0
- metac/std.py +118 -0
- metac/string.py +385 -0
- metac/string_buffer.py +567 -0
- metac/test/__init__.py +269 -0
- metac/test/__main__.py +11 -0
- metac/test/avl_int2int_map.py +160 -0
- metac/test/btree_int2int_map.py +198 -0
- metac/test/chained_cstring_hash_set.py +147 -0
- metac/test/chained_cstring_int_hash_map.py +118 -0
- metac/test/chained_functional_hash_set.py +100 -0
- metac/test/chained_int2int_hash_map.py +154 -0
- metac/test/chained_int_hash_set.py +268 -0
- metac/test/composite_packet.py +107 -0
- metac/test/content_variant.py +135 -0
- metac/test/cstring.py +7 -0
- metac/test/cstring_circular_buffer.py +172 -0
- metac/test/cstring_deque.py +259 -0
- metac/test/cstring_flat_multiset.py +46 -0
- metac/test/cstring_priority_queue.py +48 -0
- metac/test/cstring_queue.py +212 -0
- metac/test/cstring_tiered_vector.py +65 -0
- metac/test/cstring_vector.py +101 -0
- metac/test/custom_composite.py +82 -0
- metac/test/custom_composite_arc.py +28 -0
- metac/test/derived_move.py +53 -0
- metac/test/flat_cstring_int_map.py +82 -0
- metac/test/flat_cstring_int_multimap.py +121 -0
- metac/test/flat_int2int_map.py +184 -0
- metac/test/flat_int2int_multimap.py +242 -0
- metac/test/functional.py +132 -0
- metac/test/functional_vector.py +89 -0
- metac/test/int_array.py +269 -0
- metac/test/int_avl_set.py +329 -0
- metac/test/int_btree_set.py +329 -0
- metac/test/int_circular_buffer.py +457 -0
- metac/test/int_deque.py +302 -0
- metac/test/int_flat_multiset.py +252 -0
- metac/test/int_flat_set.py +294 -0
- metac/test/int_inlined_vector.py +377 -0
- metac/test/int_intrusive_option.py +168 -0
- metac/test/int_list.py +266 -0
- metac/test/int_option.py +189 -0
- metac/test/int_packet.py +228 -0
- metac/test/int_priority_queue.py +113 -0
- metac/test/int_queue.py +274 -0
- metac/test/int_rb_set.py +329 -0
- metac/test/int_stack.py +267 -0
- metac/test/int_tiered_vector.py +309 -0
- metac/test/int_treap_set.py +362 -0
- metac/test/int_vector.py +306 -0
- metac/test/intrusive_cstring_hash_set.py +85 -0
- metac/test/intrusive_custom_composite_arc_hash_set.py +86 -0
- metac/test/intrusive_int2int_hash_map.py +102 -0
- metac/test/intrusive_int_hash_set.py +233 -0
- metac/test/intrusive_primitive_arc_hash_set.py +86 -0
- metac/test/minimal_composite.py +49 -0
- metac/test/primitive_arc.py +28 -0
- metac/test/primitive_raw.py +27 -0
- metac/test/primitive_record.py +41 -0
- metac/test/rb_int2int_map.py +177 -0
- metac/test/rb_vector_multimap.py +228 -0
- metac/test/string_buffer.py +136 -0
- metac/test/template/@module@.py +10 -0
- metac/test/test_bit_array.py +309 -0
- metac/test/test_bit_vector.py +389 -0
- metac/test/test_counter.py +416 -0
- metac/test/test_emplacement.py +292 -0
- metac/test/test_module.py +190 -0
- metac/test/test_optional.py +437 -0
- metac/test/test_string.py +83 -0
- metac/test/test_traits.py +552 -0
- metac/test/treap_cstring_int_hash_map.py +118 -0
- metac/test/treap_int2int_hash_map.py +160 -0
- metac/tiered_vector.py +468 -0
- metac/traversable.py +43 -0
- metac/treap_set.py +764 -0
- metac/tree_map.py +110 -0
- metac/variant.py +231 -0
- metac/vector.py +629 -0
- metac-0.0.1.dist-info/METADATA +380 -0
- metac-0.0.1.dist-info/RECORD +188 -0
- metac-0.0.1.dist-info/WHEEL +5 -0
- metac-0.0.1.dist-info/licenses/LICENSE +26 -0
- metac-0.0.1.dist-info/top_level.txt +1 -0
metac/__init__.py
ADDED
metac/array.py
ADDED
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
import metac.std as std
|
|
2
|
+
from metac.hash import XorRot
|
|
3
|
+
from metac.assignable import Assignable
|
|
4
|
+
from metac.sortable import Sortable
|
|
5
|
+
from metac.sequential import Sequential
|
|
6
|
+
from metac.range import DirectAccess
|
|
7
|
+
from metac.container import _Range
|
|
8
|
+
from metac.core import inout, Callable, Indirection, _StructRenderer
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
#
|
|
12
|
+
class Array(_StructRenderer, Assignable, Sortable, Sequential):
|
|
13
|
+
|
|
14
|
+
brief = "Fixed-size stack-allocated contiguous sequence container"
|
|
15
|
+
|
|
16
|
+
def __init__(self, name, element, size, *args, index=std.size_t, sorting_operations=True, hasher=XorRot(), dependencies=(), **kwargs):
|
|
17
|
+
self._size = int(size)
|
|
18
|
+
if self._size < 1:
|
|
19
|
+
raise ValueError(f"Array size must be at least 1, got {self._size}")
|
|
20
|
+
super().__init__(name, element, index, *args, sorting_operations=sorting_operations, hasher=hasher, dependencies=(*dependencies, std.assert_h, std.string_h), **kwargs)
|
|
21
|
+
self.range = Range(self)
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def constructible(self):
|
|
25
|
+
return True
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def default_constructible(self):
|
|
29
|
+
return self.element.default_constructible or self.element.zero_initializable
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def destructible(self):
|
|
33
|
+
return self.element.destructible
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def copyable(self):
|
|
37
|
+
return self.element.copyable
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def moveable(self):
|
|
41
|
+
return self.element.moveable
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def swappable(self):
|
|
45
|
+
return self.element.swappable
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def comparable(self):
|
|
49
|
+
return self.element.comparable
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def orderable(self):
|
|
53
|
+
return False
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def hashable(self):
|
|
57
|
+
return self.element.hashable
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def zero_initializable(self):
|
|
61
|
+
return self.element.zero_initializable
|
|
62
|
+
|
|
63
|
+
def _element(self, target, index):
|
|
64
|
+
return self.element.variable(f"{target}->elements[{index}]")
|
|
65
|
+
|
|
66
|
+
def _target_size(self, target):
|
|
67
|
+
return str(self._size)
|
|
68
|
+
|
|
69
|
+
def _render_struct(self, stream, header):
|
|
70
|
+
super()._render_struct(stream, header)
|
|
71
|
+
stream.append(f"""
|
|
72
|
+
struct {self.name} {{
|
|
73
|
+
{self.element} elements[{self._size}]; /**< @private */
|
|
74
|
+
}};
|
|
75
|
+
""")
|
|
76
|
+
|
|
77
|
+
def __setup__(self):
|
|
78
|
+
super().__setup__()
|
|
79
|
+
|
|
80
|
+
self.description = f"""
|
|
81
|
+
Fixed-size direct access sequence container holding exactly {self._size} elements.
|
|
82
|
+
Allocates no dynamic heap memory, storing elements inline in a contiguous C array.
|
|
83
|
+
Supports bidirectional element traversal via the corresponding @ref {self.range} iterator
|
|
84
|
+
as well as direct indexed access to its elements.
|
|
85
|
+
|
|
86
|
+
The closest C++ equivalent is [std::array<>](https://en.cppreference.com/w/cpp/container/array).
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
target_i = self.element.variable("target->elements[index]")
|
|
90
|
+
source_i = self.element.variable("source->elements[index]")
|
|
91
|
+
left_i = self.element.variable("left->elements[index]")
|
|
92
|
+
right_i = self.element.variable("right->elements[index]")
|
|
93
|
+
|
|
94
|
+
with self.empty as m:
|
|
95
|
+
m.inline_code = f"""
|
|
96
|
+
assert(target);
|
|
97
|
+
return 0;
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
with self.size as m:
|
|
101
|
+
m.inline_code = f"""
|
|
102
|
+
assert(target);
|
|
103
|
+
return {self._size};
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
with self.indexed as m:
|
|
107
|
+
m.inline_code = f"""
|
|
108
|
+
assert(target);
|
|
109
|
+
return {m.index} < {self._size};
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
with self.create as m:
|
|
113
|
+
if self.element.zero_initializable:
|
|
114
|
+
m.inline_code = f"""
|
|
115
|
+
assert(target);
|
|
116
|
+
memset(target->elements, 0, sizeof(target->elements));
|
|
117
|
+
"""
|
|
118
|
+
else:
|
|
119
|
+
m.code = f"""
|
|
120
|
+
size_t index;
|
|
121
|
+
assert(target);
|
|
122
|
+
for(index = 0; index < {self._size}; ++index) {{
|
|
123
|
+
{self.element.create(target_i)};
|
|
124
|
+
}}
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
with self.method(None, "fill", {"target": inout(self), "element": self.element}, constraint=lambda: self.element.copyable, brief="Fill all array elements with a copy of the given value",
|
|
128
|
+
description="""
|
|
129
|
+
Assigns the given value to every element of the array. Previous elements are destroyed if needed.
|
|
130
|
+
|
|
131
|
+
@param[in,out] target the array to fill
|
|
132
|
+
@param[in] element the value to assign to every position
|
|
133
|
+
""") as m:
|
|
134
|
+
destroy_i = self.element.destroy(target_i) if self.element.destructible else ""
|
|
135
|
+
m.code = lambda m: f"""
|
|
136
|
+
size_t index;
|
|
137
|
+
assert(target);
|
|
138
|
+
for(index = 0; index < {self._size}; ++index) {{
|
|
139
|
+
{destroy_i};
|
|
140
|
+
{self.element.copy(target_i, m.element)};
|
|
141
|
+
}}
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
if self.destructible:
|
|
145
|
+
with self.destroy as m:
|
|
146
|
+
m.code = f"""
|
|
147
|
+
size_t index;
|
|
148
|
+
assert(target);
|
|
149
|
+
for(index = 0; index < {self._size}; ++index) {{
|
|
150
|
+
{self.element.destroy(target_i)};
|
|
151
|
+
}}
|
|
152
|
+
"""
|
|
153
|
+
|
|
154
|
+
with self.copy as m:
|
|
155
|
+
m.code = lambda m: f"""
|
|
156
|
+
size_t index;
|
|
157
|
+
assert(target);
|
|
158
|
+
assert(source);
|
|
159
|
+
for(index = 0; index < {self._size}; ++index) {{
|
|
160
|
+
{self.element.copy(target_i, source_i)};
|
|
161
|
+
}}
|
|
162
|
+
"""
|
|
163
|
+
|
|
164
|
+
with self.move as m:
|
|
165
|
+
m.code = f"""
|
|
166
|
+
size_t index;
|
|
167
|
+
assert(target);
|
|
168
|
+
assert(source);
|
|
169
|
+
for(index = 0; index < {self._size}; ++index) {{
|
|
170
|
+
{self.element.move(target_i, source_i)};
|
|
171
|
+
}}
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
with self.swap as m:
|
|
175
|
+
m.code = f"""
|
|
176
|
+
size_t index;
|
|
177
|
+
assert(left);
|
|
178
|
+
assert(right);
|
|
179
|
+
for(index = 0; index < {self._size}; ++index) {{
|
|
180
|
+
{self.element.swap(left_i, right_i)};
|
|
181
|
+
}}
|
|
182
|
+
"""
|
|
183
|
+
|
|
184
|
+
with self.get as m:
|
|
185
|
+
result = m.result.variable("result")
|
|
186
|
+
slot = self.element.variable(f"target->elements[{m.index}]")
|
|
187
|
+
m.inline_code = lambda m: f"""
|
|
188
|
+
{result.definition};
|
|
189
|
+
assert(target);
|
|
190
|
+
assert({self.indexed(m.target, m.index)});
|
|
191
|
+
{self.element.copy(result, slot)};
|
|
192
|
+
return {result};
|
|
193
|
+
"""
|
|
194
|
+
|
|
195
|
+
with self.view as m:
|
|
196
|
+
slot = self.element.variable(f"target->elements[{m.index}]")
|
|
197
|
+
m.inline_code = f"""
|
|
198
|
+
assert(target);
|
|
199
|
+
assert({self.indexed(m.target, m.index)});
|
|
200
|
+
return {slot.bind(m.result)};
|
|
201
|
+
"""
|
|
202
|
+
|
|
203
|
+
with self.set as m:
|
|
204
|
+
slot = self.element.variable(f"target->elements[{m.index}]")
|
|
205
|
+
destroy_slot = self.element.destroy(slot) if self.element.destructible else ""
|
|
206
|
+
m.inline_code = lambda m: f"""
|
|
207
|
+
assert(target);
|
|
208
|
+
assert({self.indexed(m.target, m.index)});
|
|
209
|
+
{destroy_slot};
|
|
210
|
+
{self.element.copy(slot, m.element)};
|
|
211
|
+
"""
|
|
212
|
+
|
|
213
|
+
with self.method(None, "emplace", {"target": inout(self), "index": self.index} | self.element.constructor_parameters,
|
|
214
|
+
constraint=lambda: self.element.emplaceable, brief="Construct the element at index in place",
|
|
215
|
+
description="""
|
|
216
|
+
Constructs the element in place with the forwarded parameters, associating it with
|
|
217
|
+
the index - the element previously held at the index is destroyed first.
|
|
218
|
+
|
|
219
|
+
@param[in,out] target the array to update
|
|
220
|
+
@param[in] index the index to construct the element at
|
|
221
|
+
""") as m:
|
|
222
|
+
def _emplace_code(m):
|
|
223
|
+
create_args = [getattr(m, name) for name in self.element.constructor_parameters]
|
|
224
|
+
slot = self.element.variable(f"target->elements[{m.index}]")
|
|
225
|
+
destroy_slot = self.element.destroy(slot) if self.element.destructible else ""
|
|
226
|
+
return f"""
|
|
227
|
+
assert(target);
|
|
228
|
+
assert({self.indexed(m.target, m.index)});
|
|
229
|
+
{destroy_slot};
|
|
230
|
+
{self.element.create(slot, *create_args)};
|
|
231
|
+
"""
|
|
232
|
+
m.code = _emplace_code
|
|
233
|
+
|
|
234
|
+
with self.method(self.element, "front", {"target": self}, constraint=lambda: self.element.copyable,
|
|
235
|
+
references=(self.get,),
|
|
236
|
+
brief="Get a copy of the front element",
|
|
237
|
+
description="""
|
|
238
|
+
Returns a copy of the first element in the array.
|
|
239
|
+
|
|
240
|
+
@param[in] target the array to read from
|
|
241
|
+
@return a copy of the first element
|
|
242
|
+
""") as m:
|
|
243
|
+
m.inline_code = lambda m: f"""
|
|
244
|
+
assert(target);
|
|
245
|
+
return {self.get(m.target, 0)};
|
|
246
|
+
"""
|
|
247
|
+
|
|
248
|
+
with self.method(self.element.view_type, ("front", "view"), {"target": self},
|
|
249
|
+
references=(self.view,),
|
|
250
|
+
brief="Get a constant view of the front element",
|
|
251
|
+
description="""
|
|
252
|
+
Returns a constant view of the first element in the array without copying it.
|
|
253
|
+
|
|
254
|
+
@param[in] target the array to read from
|
|
255
|
+
@return a constant view of the first element
|
|
256
|
+
""") as m:
|
|
257
|
+
m.inline_code = f"""
|
|
258
|
+
assert(target);
|
|
259
|
+
return {self.view(m.target, 0)};
|
|
260
|
+
"""
|
|
261
|
+
|
|
262
|
+
with self.method(self.element, "back", {"target": self}, constraint=lambda: self.element.copyable,
|
|
263
|
+
references=(self.get,),
|
|
264
|
+
brief="Get a copy of the back element",
|
|
265
|
+
description="""
|
|
266
|
+
Returns a copy of the last element in the array.
|
|
267
|
+
|
|
268
|
+
@param[in] target the array to read from
|
|
269
|
+
@return a copy of the last element
|
|
270
|
+
""") as m:
|
|
271
|
+
m.inline_code = lambda m: f"""
|
|
272
|
+
assert(target);
|
|
273
|
+
return {self.get(m.target, self._size - 1)};
|
|
274
|
+
"""
|
|
275
|
+
|
|
276
|
+
with self.method(self.element.view_type, ("back", "view"), {"target": self},
|
|
277
|
+
references=(self.view,),
|
|
278
|
+
brief="Get a constant view of the back element",
|
|
279
|
+
description="""
|
|
280
|
+
Returns a constant view of the last element in the array without copying it.
|
|
281
|
+
|
|
282
|
+
@param[in] target the array to read from
|
|
283
|
+
@return a constant view of the last element
|
|
284
|
+
""") as m:
|
|
285
|
+
m.inline_code = f"""
|
|
286
|
+
assert(target);
|
|
287
|
+
return {self.view(m.target, self._size - 1)};
|
|
288
|
+
"""
|
|
289
|
+
|
|
290
|
+
with self.method(Indirection(self.element), "data", {"target": inout(self)}, brief="Get pointer to the underlying array",
|
|
291
|
+
description="""
|
|
292
|
+
Returns a pointer to the contiguous array storage.
|
|
293
|
+
|
|
294
|
+
@param[in,out] target the array to inspect
|
|
295
|
+
@return a pointer to the first element
|
|
296
|
+
""") as m:
|
|
297
|
+
m.inline_code = f"""
|
|
298
|
+
assert(target);
|
|
299
|
+
return target->elements;
|
|
300
|
+
"""
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
#
|
|
304
|
+
class Range(_Range, DirectAccess):
|
|
305
|
+
|
|
306
|
+
brief = "Direct access range over array"
|
|
307
|
+
|
|
308
|
+
def _render_struct(self, stream, header):
|
|
309
|
+
super()._render_struct(stream, header)
|
|
310
|
+
stream.append(f"""
|
|
311
|
+
struct {self.name} {{
|
|
312
|
+
{Indirection(self.iterable, constant=True)} iterable; /**< @private */
|
|
313
|
+
{self.iterable.index} front, /**< @private */ back; /**< @private */
|
|
314
|
+
}};
|
|
315
|
+
""")
|
|
316
|
+
|
|
317
|
+
def __setup__(self):
|
|
318
|
+
super().__setup__()
|
|
319
|
+
|
|
320
|
+
with self.method(Callable.Parameter(self), "new", {"iterable": self.iterable}, brief="Create range spanning the array",
|
|
321
|
+
description="""
|
|
322
|
+
Creates a range over the array elements. The range must not outlive the array.
|
|
323
|
+
|
|
324
|
+
@param[in] iterable the array to span
|
|
325
|
+
@return the range covering the whole array
|
|
326
|
+
""") as m:
|
|
327
|
+
result = m.result.variable("result")
|
|
328
|
+
m.inline_code = f"""
|
|
329
|
+
{result.definition};
|
|
330
|
+
assert(iterable);
|
|
331
|
+
result.iterable = iterable;
|
|
332
|
+
result.front = 0;
|
|
333
|
+
result.back = {self.iterable._size};
|
|
334
|
+
return {result};
|
|
335
|
+
"""
|
|
336
|
+
|
|
337
|
+
with self.empty as m:
|
|
338
|
+
m.inline_code = f"""
|
|
339
|
+
assert(target);
|
|
340
|
+
return target->front >= target->back;
|
|
341
|
+
"""
|
|
342
|
+
|
|
343
|
+
with self.front as m:
|
|
344
|
+
m.inline_code = lambda: f"""
|
|
345
|
+
assert(target);
|
|
346
|
+
assert(!{self.empty(m.target)});
|
|
347
|
+
return {self.iterable.get("target->iterable", "target->front")};
|
|
348
|
+
"""
|
|
349
|
+
|
|
350
|
+
with self.front_view as m:
|
|
351
|
+
m.inline_code = lambda: f"""
|
|
352
|
+
assert(target);
|
|
353
|
+
assert(!{self.empty(m.target)});
|
|
354
|
+
return {self.iterable.view("target->iterable", "target->front")};
|
|
355
|
+
"""
|
|
356
|
+
|
|
357
|
+
with self.move_front as m:
|
|
358
|
+
m.inline_code = f"""
|
|
359
|
+
assert(target);
|
|
360
|
+
assert(!{self.empty(m.target)});
|
|
361
|
+
++target->front;
|
|
362
|
+
"""
|
|
363
|
+
|
|
364
|
+
with self.back as m:
|
|
365
|
+
m.inline_code = lambda: f"""
|
|
366
|
+
assert(target);
|
|
367
|
+
assert(!{self.empty(m.target)});
|
|
368
|
+
return {self.iterable.get("target->iterable", "target->back - 1")};
|
|
369
|
+
"""
|
|
370
|
+
|
|
371
|
+
with self.back_view as m:
|
|
372
|
+
m.inline_code = lambda: f"""
|
|
373
|
+
assert(target);
|
|
374
|
+
assert(!{self.empty(m.target)});
|
|
375
|
+
return {self.iterable.view("target->iterable", "target->back - 1")};
|
|
376
|
+
"""
|
|
377
|
+
|
|
378
|
+
with self.move_back as m:
|
|
379
|
+
m.inline_code = f"""
|
|
380
|
+
assert(target);
|
|
381
|
+
assert(!{self.empty(m.target)});
|
|
382
|
+
--target->back;
|
|
383
|
+
"""
|
|
384
|
+
|
|
385
|
+
with self.get as m:
|
|
386
|
+
m.inline_code = lambda: f"""
|
|
387
|
+
assert(target);
|
|
388
|
+
return {self.iterable.get("target->iterable", "target->front + index")};
|
|
389
|
+
"""
|
|
390
|
+
|
|
391
|
+
with self.view as m:
|
|
392
|
+
m.inline_code = lambda: f"""
|
|
393
|
+
assert(target);
|
|
394
|
+
return {self.iterable.view("target->iterable", "target->front + index")};
|
|
395
|
+
"""
|
|
396
|
+
|
|
397
|
+
with self.size as m:
|
|
398
|
+
m.inline_code = f"""
|
|
399
|
+
assert(target);
|
|
400
|
+
assert(target->back >= target->front);
|
|
401
|
+
return target->back - target->front;
|
|
402
|
+
"""
|
metac/assignable.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from metac.core import inout
|
|
2
|
+
from metac.indexable import Indexable
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
# Capability mixin declaring position-addressed assignment for collections reachable
|
|
6
|
+
# by index - the writable half of the Indexable read protocol (assignability implies
|
|
7
|
+
# indexability). Multimapping mixes Indexable without Assignable since replacing "the
|
|
8
|
+
# element at a key" is ambiguous under duplicate keys.
|
|
9
|
+
class Assignable(Indexable):
|
|
10
|
+
|
|
11
|
+
def __setup__(self):
|
|
12
|
+
super().__setup__()
|
|
13
|
+
|
|
14
|
+
valid_index = lambda: self.index.comparable or self.index.orderable
|
|
15
|
+
|
|
16
|
+
self.method(None, "set", {"target": inout(self), "index": self.index, "element": self.element}, constraint=lambda: valid_index() and self.element.copyable, brief="Set the element at index",
|
|
17
|
+
description="""
|
|
18
|
+
Associates the element with the index - either storing it at the brand new entry
|
|
19
|
+
or replacing the contents of the element already held at the index in place.
|
|
20
|
+
The cost matches the underlying implementation: expected O(1) for hash-based and direct-indexed
|
|
21
|
+
containers, expected O(log n) for tree-based containers.
|
|
22
|
+
|
|
23
|
+
@param[in,out] target the collection to update
|
|
24
|
+
@param[in] index the index to assign the element at
|
|
25
|
+
@param[in] element the element to store - the element previously held at the index is destroyed
|
|
26
|
+
""")
|