sonolus.py 0.3.4__py3-none-any.whl → 0.4.0__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.
Potentially problematic release.
This version of sonolus.py might be problematic. Click here for more details.
- sonolus/backend/excepthook.py +30 -0
- sonolus/backend/finalize.py +15 -1
- sonolus/backend/ops.py +4 -0
- sonolus/backend/optimize/allocate.py +5 -5
- sonolus/backend/optimize/constant_evaluation.py +124 -19
- sonolus/backend/optimize/copy_coalesce.py +15 -12
- sonolus/backend/optimize/dead_code.py +7 -6
- sonolus/backend/optimize/dominance.py +2 -2
- sonolus/backend/optimize/flow.py +54 -8
- sonolus/backend/optimize/inlining.py +137 -30
- sonolus/backend/optimize/liveness.py +2 -2
- sonolus/backend/optimize/optimize.py +15 -1
- sonolus/backend/optimize/passes.py +11 -3
- sonolus/backend/optimize/simplify.py +137 -8
- sonolus/backend/optimize/ssa.py +47 -13
- sonolus/backend/place.py +5 -4
- sonolus/backend/utils.py +24 -0
- sonolus/backend/visitor.py +260 -17
- sonolus/build/cli.py +47 -19
- sonolus/build/compile.py +12 -5
- sonolus/build/engine.py +70 -1
- sonolus/build/level.py +3 -3
- sonolus/build/project.py +2 -2
- sonolus/script/archetype.py +12 -9
- sonolus/script/array.py +23 -18
- sonolus/script/array_like.py +26 -29
- sonolus/script/bucket.py +1 -1
- sonolus/script/containers.py +22 -26
- sonolus/script/debug.py +20 -43
- sonolus/script/effect.py +1 -1
- sonolus/script/globals.py +3 -3
- sonolus/script/instruction.py +2 -2
- sonolus/script/internal/builtin_impls.py +155 -28
- sonolus/script/internal/constant.py +13 -3
- sonolus/script/internal/context.py +46 -15
- sonolus/script/internal/impl.py +9 -3
- sonolus/script/internal/introspection.py +8 -1
- sonolus/script/internal/native.py +2 -2
- sonolus/script/internal/range.py +8 -11
- sonolus/script/internal/simulation_context.py +1 -1
- sonolus/script/internal/transient.py +2 -2
- sonolus/script/internal/value.py +41 -3
- sonolus/script/interval.py +13 -13
- sonolus/script/iterator.py +38 -107
- sonolus/script/maybe.py +139 -0
- sonolus/script/num.py +17 -2
- sonolus/script/options.py +1 -1
- sonolus/script/particle.py +1 -1
- sonolus/script/project.py +24 -5
- sonolus/script/quad.py +15 -15
- sonolus/script/record.py +16 -12
- sonolus/script/runtime.py +22 -18
- sonolus/script/sprite.py +1 -1
- sonolus/script/stream.py +66 -82
- sonolus/script/transform.py +35 -34
- sonolus/script/values.py +10 -10
- sonolus/script/vec.py +21 -18
- {sonolus_py-0.3.4.dist-info → sonolus_py-0.4.0.dist-info}/METADATA +1 -1
- sonolus_py-0.4.0.dist-info/RECORD +93 -0
- sonolus_py-0.3.4.dist-info/RECORD +0 -92
- {sonolus_py-0.3.4.dist-info → sonolus_py-0.4.0.dist-info}/WHEEL +0 -0
- {sonolus_py-0.3.4.dist-info → sonolus_py-0.4.0.dist-info}/entry_points.txt +0 -0
- {sonolus_py-0.3.4.dist-info → sonolus_py-0.4.0.dist-info}/licenses/LICENSE +0 -0
sonolus/script/quad.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import Protocol
|
|
3
|
+
from typing import Protocol
|
|
4
4
|
|
|
5
5
|
from sonolus.script.record import Record
|
|
6
6
|
from sonolus.script.values import zeros
|
|
@@ -57,7 +57,7 @@ class Quad(Record):
|
|
|
57
57
|
"""The center of the quad."""
|
|
58
58
|
return (self.bl + self.tr + self.tl + self.br) / 4
|
|
59
59
|
|
|
60
|
-
def translate(self, translation: Vec2, /) ->
|
|
60
|
+
def translate(self, translation: Vec2, /) -> Quad:
|
|
61
61
|
"""Translate the quad by the given translation and return a new quad."""
|
|
62
62
|
return Quad(
|
|
63
63
|
bl=self.bl + translation,
|
|
@@ -66,7 +66,7 @@ class Quad(Record):
|
|
|
66
66
|
br=self.br + translation,
|
|
67
67
|
)
|
|
68
68
|
|
|
69
|
-
def scale(self, factor: Vec2, /) ->
|
|
69
|
+
def scale(self, factor: Vec2, /) -> Quad:
|
|
70
70
|
"""Scale the quad by the given factor about the origin and return a new quad."""
|
|
71
71
|
return Quad(
|
|
72
72
|
bl=self.bl * factor,
|
|
@@ -75,7 +75,7 @@ class Quad(Record):
|
|
|
75
75
|
br=self.br * factor,
|
|
76
76
|
)
|
|
77
77
|
|
|
78
|
-
def scale_about(self, factor: Vec2, /, pivot: Vec2) ->
|
|
78
|
+
def scale_about(self, factor: Vec2, /, pivot: Vec2) -> Quad:
|
|
79
79
|
"""Scale the quad by the given factor about the given pivot and return a new quad."""
|
|
80
80
|
return Quad(
|
|
81
81
|
bl=(self.bl - pivot) * factor + pivot,
|
|
@@ -84,7 +84,7 @@ class Quad(Record):
|
|
|
84
84
|
br=(self.br - pivot) * factor + pivot,
|
|
85
85
|
)
|
|
86
86
|
|
|
87
|
-
def scale_centered(self, factor: Vec2, /) ->
|
|
87
|
+
def scale_centered(self, factor: Vec2, /) -> Quad:
|
|
88
88
|
"""Scale the quad by the given factor about its center and return a new quad."""
|
|
89
89
|
return Quad(
|
|
90
90
|
bl=self.bl * factor,
|
|
@@ -93,7 +93,7 @@ class Quad(Record):
|
|
|
93
93
|
br=self.br * factor,
|
|
94
94
|
).translate(self.center * (Vec2(1, 1) - factor))
|
|
95
95
|
|
|
96
|
-
def rotate(self, angle: float, /) ->
|
|
96
|
+
def rotate(self, angle: float, /) -> Quad:
|
|
97
97
|
"""Rotate the quad by the given angle about the origin and return a new quad.
|
|
98
98
|
|
|
99
99
|
Args:
|
|
@@ -114,7 +114,7 @@ class Quad(Record):
|
|
|
114
114
|
angle: float,
|
|
115
115
|
/,
|
|
116
116
|
pivot: Vec2,
|
|
117
|
-
) ->
|
|
117
|
+
) -> Quad:
|
|
118
118
|
"""Rotate the quad by the given angle about the given pivot and return a new quad.
|
|
119
119
|
|
|
120
120
|
Args:
|
|
@@ -131,7 +131,7 @@ class Quad(Record):
|
|
|
131
131
|
br=self.br.rotate_about(angle, pivot),
|
|
132
132
|
)
|
|
133
133
|
|
|
134
|
-
def rotate_centered(self, angle: float, /) ->
|
|
134
|
+
def rotate_centered(self, angle: float, /) -> Quad:
|
|
135
135
|
"""Rotate the quad by the given angle about its center and return a new quad.
|
|
136
136
|
|
|
137
137
|
Args:
|
|
@@ -142,7 +142,7 @@ class Quad(Record):
|
|
|
142
142
|
"""
|
|
143
143
|
return self.rotate_about(angle, self.center)
|
|
144
144
|
|
|
145
|
-
def permute(self, count: int = 1, /) ->
|
|
145
|
+
def permute(self, count: int = 1, /) -> Quad:
|
|
146
146
|
"""Perform a cyclic permutation of the quad's vertices and return a new quad.
|
|
147
147
|
|
|
148
148
|
On a square, this operation is equivalent to rotating the square counterclockwise 90 degrees `count` times.
|
|
@@ -269,7 +269,7 @@ class Rect(Record):
|
|
|
269
269
|
br=self.br,
|
|
270
270
|
)
|
|
271
271
|
|
|
272
|
-
def translate(self, translation: Vec2, /) ->
|
|
272
|
+
def translate(self, translation: Vec2, /) -> Rect:
|
|
273
273
|
"""Translate the rectangle by the given translation and return a new rectangle."""
|
|
274
274
|
return Rect(
|
|
275
275
|
t=self.t + translation.y,
|
|
@@ -278,7 +278,7 @@ class Rect(Record):
|
|
|
278
278
|
l=self.l + translation.x,
|
|
279
279
|
)
|
|
280
280
|
|
|
281
|
-
def scale(self, factor: Vec2, /) ->
|
|
281
|
+
def scale(self, factor: Vec2, /) -> Rect:
|
|
282
282
|
"""Scale the rectangle by the given factor about the origin and return a new rectangle."""
|
|
283
283
|
return Rect(
|
|
284
284
|
t=self.t * factor.y,
|
|
@@ -287,7 +287,7 @@ class Rect(Record):
|
|
|
287
287
|
l=self.l * factor.x,
|
|
288
288
|
)
|
|
289
289
|
|
|
290
|
-
def scale_about(self, factor: Vec2, /, pivot: Vec2) ->
|
|
290
|
+
def scale_about(self, factor: Vec2, /, pivot: Vec2) -> Rect:
|
|
291
291
|
"""Scale the rectangle by the given factor about the given pivot and return a new rectangle."""
|
|
292
292
|
return Rect(
|
|
293
293
|
t=(self.t - pivot.y) * factor.y + pivot.y,
|
|
@@ -296,7 +296,7 @@ class Rect(Record):
|
|
|
296
296
|
l=(self.l - pivot.x) * factor.x + pivot.x,
|
|
297
297
|
)
|
|
298
298
|
|
|
299
|
-
def scale_centered(self, factor: Vec2, /) ->
|
|
299
|
+
def scale_centered(self, factor: Vec2, /) -> Rect:
|
|
300
300
|
"""Scale the rectangle by the given factor about its center and return a new rectangle."""
|
|
301
301
|
return Rect(
|
|
302
302
|
t=self.t * factor.y,
|
|
@@ -305,7 +305,7 @@ class Rect(Record):
|
|
|
305
305
|
l=self.l * factor.x,
|
|
306
306
|
).translate(self.center * (Vec2(1, 1) - factor))
|
|
307
307
|
|
|
308
|
-
def expand(self, expansion: Vec2, /) ->
|
|
308
|
+
def expand(self, expansion: Vec2, /) -> Rect:
|
|
309
309
|
"""Expand the rectangle by the given amount and return a new rectangle."""
|
|
310
310
|
return Rect(
|
|
311
311
|
t=self.t + expansion.y,
|
|
@@ -314,7 +314,7 @@ class Rect(Record):
|
|
|
314
314
|
l=self.l - expansion.x,
|
|
315
315
|
)
|
|
316
316
|
|
|
317
|
-
def shrink(self, shrinkage: Vec2, /) ->
|
|
317
|
+
def shrink(self, shrinkage: Vec2, /) -> Rect:
|
|
318
318
|
"""Shrink the rectangle by the given amount and return a new rectangle."""
|
|
319
319
|
return Rect(
|
|
320
320
|
t=self.t - shrinkage.y,
|
sonolus/script/record.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import inspect
|
|
4
|
+
from abc import ABCMeta
|
|
4
5
|
from collections.abc import Iterable
|
|
5
6
|
from inspect import getmro
|
|
6
7
|
from typing import Any, ClassVar, Self, TypeVar, dataclass_transform, get_origin
|
|
@@ -20,7 +21,7 @@ from sonolus.script.internal.value import BackingSource, DataValue, Value
|
|
|
20
21
|
from sonolus.script.num import Num
|
|
21
22
|
|
|
22
23
|
|
|
23
|
-
class RecordMeta(
|
|
24
|
+
class RecordMeta(ABCMeta):
|
|
24
25
|
@meta_fn
|
|
25
26
|
def __pos__[T](cls: type[T]) -> T:
|
|
26
27
|
"""Create a zero-initialized record instance."""
|
|
@@ -183,7 +184,7 @@ class Record(GenericValue, metaclass=RecordMeta):
|
|
|
183
184
|
result = object.__new__(cls)
|
|
184
185
|
result._value = {
|
|
185
186
|
field.name: field.type._from_backing_source_(
|
|
186
|
-
lambda offset, field_offset=field.offset: source((Num(offset) + Num(field_offset)).ir())
|
|
187
|
+
lambda offset, field_offset=field.offset: source((Num(offset) + Num(field_offset)).ir()) # type: ignore
|
|
187
188
|
)
|
|
188
189
|
for field in cls._fields
|
|
189
190
|
}
|
|
@@ -234,10 +235,10 @@ class Record(GenericValue, metaclass=RecordMeta):
|
|
|
234
235
|
def _get_(self) -> Self:
|
|
235
236
|
return self
|
|
236
237
|
|
|
237
|
-
def _set_(self, value:
|
|
238
|
+
def _set_(self, value: Any):
|
|
238
239
|
raise TypeError("Record does not support _set_")
|
|
239
240
|
|
|
240
|
-
def _copy_from_(self, value:
|
|
241
|
+
def _copy_from_(self, value: Any):
|
|
241
242
|
value = self._accept_(value)
|
|
242
243
|
for field in self._fields:
|
|
243
244
|
field.__set__(self, field.__get__(value))
|
|
@@ -259,14 +260,14 @@ class Record(GenericValue, metaclass=RecordMeta):
|
|
|
259
260
|
return result
|
|
260
261
|
|
|
261
262
|
def __str__(self):
|
|
262
|
-
return (
|
|
263
|
-
|
|
264
|
-
)
|
|
263
|
+
return f"{self.__class__.__name__}({
|
|
264
|
+
', '.join(f'{field.name}={field.get_internal(self)}' for field in self._fields)
|
|
265
|
+
})"
|
|
265
266
|
|
|
266
267
|
def __repr__(self):
|
|
267
|
-
return (
|
|
268
|
-
|
|
269
|
-
)
|
|
268
|
+
return f"{self.__class__.__name__}({
|
|
269
|
+
', '.join(f'{field.name}={field.get_internal(self)!r}' for field in self._fields)
|
|
270
|
+
})"
|
|
270
271
|
|
|
271
272
|
@meta_fn
|
|
272
273
|
def __eq__(self, other: Any) -> bool:
|
|
@@ -309,16 +310,19 @@ class Record(GenericValue, metaclass=RecordMeta):
|
|
|
309
310
|
|
|
310
311
|
|
|
311
312
|
class _RecordField(SonolusDescriptor):
|
|
312
|
-
def __init__(self, name: str, type_: type[Value], index: int, offset: int):
|
|
313
|
+
def __init__(self, name: str, type_: type[Value] | Any, index: int, offset: int):
|
|
313
314
|
self.name = name
|
|
314
315
|
self.type = type_
|
|
315
316
|
self.index = index
|
|
316
317
|
self.offset = offset
|
|
317
318
|
|
|
319
|
+
def get_internal(self, instance: Record) -> Value:
|
|
320
|
+
return instance._value[self.name]
|
|
321
|
+
|
|
318
322
|
def __get__(self, instance: Record | None, owner=None):
|
|
319
323
|
if instance is None:
|
|
320
324
|
return self
|
|
321
|
-
result = instance._value[self.name].
|
|
325
|
+
result = instance._value[self.name]._get_readonly_()
|
|
322
326
|
if ctx():
|
|
323
327
|
return result
|
|
324
328
|
else:
|
sonolus/script/runtime.py
CHANGED
|
@@ -698,7 +698,7 @@ class _TouchArray:
|
|
|
698
698
|
|
|
699
699
|
@_runtime_skin_transform
|
|
700
700
|
class _SkinTransform:
|
|
701
|
-
value: Array[Array[float, 4], 4]
|
|
701
|
+
value: Array[Array[float, 4], 4] # type: ignore
|
|
702
702
|
|
|
703
703
|
@property
|
|
704
704
|
@meta_fn
|
|
@@ -719,7 +719,7 @@ class _SkinTransform:
|
|
|
719
719
|
|
|
720
720
|
@_runtime_particle_transform
|
|
721
721
|
class _ParticleTransform:
|
|
722
|
-
value: Array[Array[float, 4], 4]
|
|
722
|
+
value: Array[Array[float, 4], 4] # type: ignore
|
|
723
723
|
|
|
724
724
|
@property
|
|
725
725
|
@meta_fn
|
|
@@ -857,25 +857,25 @@ def is_debug() -> bool:
|
|
|
857
857
|
@meta_fn
|
|
858
858
|
def is_play() -> bool:
|
|
859
859
|
"""Check if the game is running in play mode."""
|
|
860
|
-
return ctx() and ctx().global_state.mode == Mode.PLAY
|
|
860
|
+
return bool(ctx() and ctx().global_state.mode == Mode.PLAY)
|
|
861
861
|
|
|
862
862
|
|
|
863
863
|
@meta_fn
|
|
864
864
|
def is_preview() -> bool:
|
|
865
865
|
"""Check if the game is running in preview mode."""
|
|
866
|
-
return ctx() and ctx().global_state.mode == Mode.PREVIEW
|
|
866
|
+
return bool(ctx() and ctx().global_state.mode == Mode.PREVIEW)
|
|
867
867
|
|
|
868
868
|
|
|
869
869
|
@meta_fn
|
|
870
870
|
def is_watch() -> bool:
|
|
871
871
|
"""Check if the game is running in watch mode."""
|
|
872
|
-
return ctx() and ctx().global_state.mode == Mode.WATCH
|
|
872
|
+
return bool(ctx() and ctx().global_state.mode == Mode.WATCH)
|
|
873
873
|
|
|
874
874
|
|
|
875
875
|
@meta_fn
|
|
876
876
|
def is_tutorial() -> bool:
|
|
877
877
|
"""Check if the game is running in tutorial mode."""
|
|
878
|
-
return ctx() and ctx().global_state.mode == Mode.TUTORIAL
|
|
878
|
+
return bool(ctx() and ctx().global_state.mode == Mode.TUTORIAL)
|
|
879
879
|
|
|
880
880
|
|
|
881
881
|
@meta_fn
|
|
@@ -884,7 +884,7 @@ def is_preprocessing() -> bool:
|
|
|
884
884
|
|
|
885
885
|
Returns True if the current callback is one of preprocess, spawn_order, spawn_time, or despawn_time.
|
|
886
886
|
"""
|
|
887
|
-
return ctx() and ctx().callback in {"preprocess", "spawnOrder", "spawnTime", "despawnTime"}
|
|
887
|
+
return bool(ctx() and ctx().callback in {"preprocess", "spawnOrder", "spawnTime", "despawnTime"})
|
|
888
888
|
|
|
889
889
|
|
|
890
890
|
@meta_fn
|
|
@@ -1058,12 +1058,16 @@ def prev_time() -> float:
|
|
|
1058
1058
|
def touches() -> ArrayLike[Touch]:
|
|
1059
1059
|
"""Get the current touches of the game."""
|
|
1060
1060
|
if not ctx():
|
|
1061
|
-
return Array[Touch, 0]()
|
|
1061
|
+
return Array[Touch, 0]() # type: ignore
|
|
1062
1062
|
match ctx().global_state.mode:
|
|
1063
1063
|
case Mode.PLAY:
|
|
1064
|
-
return ArrayPointer[Touch]
|
|
1064
|
+
return ArrayPointer[Touch]._raw(
|
|
1065
|
+
size=Num._accept_(_PlayRuntimeUpdate.touch_count),
|
|
1066
|
+
block=Num._accept_(ctx().blocks.RuntimeTouchArray),
|
|
1067
|
+
offset=Num._accept_(0),
|
|
1068
|
+
)
|
|
1065
1069
|
case _:
|
|
1066
|
-
return Array[Touch, 0]()
|
|
1070
|
+
return Array[Touch, 0]() # type: ignore
|
|
1067
1071
|
|
|
1068
1072
|
|
|
1069
1073
|
@meta_fn
|
|
@@ -1098,24 +1102,24 @@ def navigation_direction() -> int:
|
|
|
1098
1102
|
|
|
1099
1103
|
def skin_transform() -> Transform2d:
|
|
1100
1104
|
"""Get the global skin transform."""
|
|
1101
|
-
return _SkinTransform.transform
|
|
1105
|
+
return _SkinTransform.transform # type: ignore
|
|
1102
1106
|
|
|
1103
1107
|
|
|
1104
1108
|
@meta_fn
|
|
1105
1109
|
def set_skin_transform(value: Transform2d):
|
|
1106
1110
|
"""Set the global skin transform."""
|
|
1107
|
-
_SkinTransform.transform._copy_from_(value)
|
|
1111
|
+
_SkinTransform.transform._copy_from_(value) # type: ignore
|
|
1108
1112
|
|
|
1109
1113
|
|
|
1110
1114
|
def particle_transform() -> Transform2d:
|
|
1111
1115
|
"""Get the global particle transform."""
|
|
1112
|
-
return _ParticleTransform.transform
|
|
1116
|
+
return _ParticleTransform.transform # type: ignore
|
|
1113
1117
|
|
|
1114
1118
|
|
|
1115
1119
|
@meta_fn
|
|
1116
1120
|
def set_particle_transform(value: Transform2d):
|
|
1117
1121
|
"""Set the global particle transform."""
|
|
1118
|
-
_ParticleTransform.transform._copy_from_(value)
|
|
1122
|
+
_ParticleTransform.transform._copy_from_(value) # type: ignore
|
|
1119
1123
|
|
|
1120
1124
|
|
|
1121
1125
|
def background() -> Quad:
|
|
@@ -1142,12 +1146,12 @@ _runtime_ui = RuntimeUi()
|
|
|
1142
1146
|
|
|
1143
1147
|
def runtime_ui() -> RuntimeUi:
|
|
1144
1148
|
"""Get the runtime UI configuration."""
|
|
1145
|
-
return _runtime_ui
|
|
1149
|
+
return _runtime_ui # type: ignore
|
|
1146
1150
|
|
|
1147
1151
|
|
|
1148
1152
|
def canvas() -> _PreviewRuntimeCanvas:
|
|
1149
1153
|
"""Get the preview canvas."""
|
|
1150
|
-
return _PreviewRuntimeCanvas
|
|
1154
|
+
return _PreviewRuntimeCanvas # type: ignore
|
|
1151
1155
|
|
|
1152
1156
|
|
|
1153
1157
|
def screen() -> Rect:
|
|
@@ -1157,9 +1161,9 @@ def screen() -> Rect:
|
|
|
1157
1161
|
|
|
1158
1162
|
def level_score() -> _LevelScore:
|
|
1159
1163
|
"""Get the level score configuration."""
|
|
1160
|
-
return _LevelScore
|
|
1164
|
+
return _LevelScore # type: ignore
|
|
1161
1165
|
|
|
1162
1166
|
|
|
1163
1167
|
def level_life() -> _LevelLife:
|
|
1164
1168
|
"""Get the level life configuration."""
|
|
1165
|
-
return _LevelLife
|
|
1169
|
+
return _LevelLife # type: ignore
|
sonolus/script/sprite.py
CHANGED
sonolus/script/stream.py
CHANGED
|
@@ -13,6 +13,7 @@ from sonolus.script.internal.introspection import get_field_specifiers
|
|
|
13
13
|
from sonolus.script.internal.native import native_function
|
|
14
14
|
from sonolus.script.internal.value import BackingValue, Value
|
|
15
15
|
from sonolus.script.iterator import SonolusIterator
|
|
16
|
+
from sonolus.script.maybe import Maybe, Nothing, Some
|
|
16
17
|
from sonolus.script.num import Num
|
|
17
18
|
from sonolus.script.record import Record
|
|
18
19
|
from sonolus.script.runtime import prev_time, time
|
|
@@ -48,7 +49,7 @@ class _StreamDataField(SonolusDescriptor):
|
|
|
48
49
|
|
|
49
50
|
def __get__(self, instance, owner):
|
|
50
51
|
_check_can_read_or_write_stream()
|
|
51
|
-
return self._get().
|
|
52
|
+
return self._get()._get_readonly_()
|
|
52
53
|
|
|
53
54
|
def __set__(self, instance, value):
|
|
54
55
|
_check_can_write_stream()
|
|
@@ -136,7 +137,7 @@ class _StreamBacking(BackingValue):
|
|
|
136
137
|
id: Num
|
|
137
138
|
index: Num
|
|
138
139
|
|
|
139
|
-
def __init__(self, stream_id: int, index: Num):
|
|
140
|
+
def __init__(self, stream_id: int, index: Num | int | float):
|
|
140
141
|
super().__init__()
|
|
141
142
|
self.id = Num._accept_(stream_id)
|
|
142
143
|
self.index = Num._accept_(index)
|
|
@@ -240,10 +241,10 @@ class Stream[T](Record):
|
|
|
240
241
|
# We still need to store something to preserve the key, so this is a special case.
|
|
241
242
|
_stream_set(self.offset, key, 0)
|
|
242
243
|
else:
|
|
243
|
-
for i, v in enumerate(value._to_list_()):
|
|
244
|
+
for i, v in enumerate(cast(Value, value)._to_list_()):
|
|
244
245
|
_stream_set(self.offset + i, key, Num(v))
|
|
245
246
|
|
|
246
|
-
def next_key(self, key: int | float) -> int:
|
|
247
|
+
def next_key(self, key: int | float) -> int | float:
|
|
247
248
|
"""Get the next key, or the key unchanged if it is the last key or the stream is empty.
|
|
248
249
|
|
|
249
250
|
If the key is in the stream and there is a next key, returns the next key.
|
|
@@ -251,13 +252,13 @@ class Stream[T](Record):
|
|
|
251
252
|
_check_can_read_stream()
|
|
252
253
|
return _stream_get_next_key(self.offset, key)
|
|
253
254
|
|
|
254
|
-
def next_key_or_default(self, key: int | float, default: int | float) -> int:
|
|
255
|
+
def next_key_or_default(self, key: int | float, default: int | float) -> int | float:
|
|
255
256
|
"""Get the next key, or the default value if there is no next key."""
|
|
256
257
|
_check_can_read_stream()
|
|
257
258
|
next_key = self.next_key(key)
|
|
258
259
|
return next_key if next_key > key else default
|
|
259
260
|
|
|
260
|
-
def previous_key(self, key: int | float) -> int:
|
|
261
|
+
def previous_key(self, key: int | float) -> int | float:
|
|
261
262
|
"""Get the previous key, or the key unchanged if it is the first key or the stream is empty.
|
|
262
263
|
|
|
263
264
|
If the key is in the stream and there is a previous key, returns the previous key.
|
|
@@ -265,7 +266,7 @@ class Stream[T](Record):
|
|
|
265
266
|
_check_can_read_stream()
|
|
266
267
|
return _stream_get_previous_key(self.offset, key)
|
|
267
268
|
|
|
268
|
-
def previous_key_or_default(self, key: int | float, default: int | float) -> int:
|
|
269
|
+
def previous_key_or_default(self, key: int | float, default: int | float) -> int | float:
|
|
269
270
|
"""Get the previous key, or the default value if there is no previous key."""
|
|
270
271
|
_check_can_read_stream()
|
|
271
272
|
previous_key = self.previous_key(key)
|
|
@@ -283,12 +284,12 @@ class Stream[T](Record):
|
|
|
283
284
|
previous_key = self.previous_key(key)
|
|
284
285
|
return previous_key < key
|
|
285
286
|
|
|
286
|
-
def next_key_inclusive(self, key: int | float) -> int:
|
|
287
|
+
def next_key_inclusive(self, key: int | float) -> int | float:
|
|
287
288
|
"""Like `next_key`, but returns the key itself if it is in the stream."""
|
|
288
289
|
_check_can_read_stream()
|
|
289
290
|
return key if key in self else self.next_key(key)
|
|
290
291
|
|
|
291
|
-
def previous_key_inclusive(self, key: int | float) -> int:
|
|
292
|
+
def previous_key_inclusive(self, key: int | float) -> int | float:
|
|
292
293
|
"""Like `previous_key`, but returns the key itself if it is in the stream."""
|
|
293
294
|
_check_can_read_stream()
|
|
294
295
|
return key if key in self else self.previous_key(key)
|
|
@@ -508,21 +509,20 @@ class StreamGroup[T, Size](Record):
|
|
|
508
509
|
_check_can_read_or_write_stream()
|
|
509
510
|
assert index in self
|
|
510
511
|
# Size 0 elements still need 1 stream to preserve the key.
|
|
511
|
-
|
|
512
|
+
t = self.type_var_value(T)
|
|
513
|
+
return Stream[t](max(1, sizeof(self.element_type())) * index + self.offset)
|
|
512
514
|
|
|
513
515
|
|
|
514
516
|
class _StreamAscIterator[T](Record, SonolusIterator[tuple[int | float, T]]):
|
|
515
517
|
stream: Stream[T]
|
|
516
518
|
current_key: int | float
|
|
517
519
|
|
|
518
|
-
def
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
def advance(self):
|
|
525
|
-
self.current_key = self.stream.next_key_or_default(self.current_key, inf)
|
|
520
|
+
def next(self) -> Maybe[tuple[int | float, T]]:
|
|
521
|
+
if self.current_key in self.stream:
|
|
522
|
+
result = (self.current_key, self.stream[self.current_key])
|
|
523
|
+
self.current_key = self.stream.next_key_or_default(self.current_key, inf)
|
|
524
|
+
return Some(result)
|
|
525
|
+
return Nothing
|
|
526
526
|
|
|
527
527
|
|
|
528
528
|
class _StreamBoundedAscIterator[T](Record, SonolusIterator[tuple[int | float, T]]):
|
|
@@ -530,42 +530,36 @@ class _StreamBoundedAscIterator[T](Record, SonolusIterator[tuple[int | float, T]
|
|
|
530
530
|
current_key: int | float
|
|
531
531
|
end_key: int | float
|
|
532
532
|
|
|
533
|
-
def
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
def advance(self):
|
|
540
|
-
self.current_key = self.stream.next_key_or_default(self.current_key, inf)
|
|
533
|
+
def next(self) -> Maybe[tuple[int | float, T]]:
|
|
534
|
+
if self.current_key in self.stream and self.current_key <= self.end_key:
|
|
535
|
+
result = (self.current_key, self.stream[self.current_key])
|
|
536
|
+
self.current_key = self.stream.next_key_or_default(self.current_key, inf)
|
|
537
|
+
return Some(result)
|
|
538
|
+
return Nothing
|
|
541
539
|
|
|
542
540
|
|
|
543
541
|
class _StreamDescIterator[T](Record, SonolusIterator[tuple[int | float, T]]):
|
|
544
542
|
stream: Stream[T]
|
|
545
543
|
current_key: int | float
|
|
546
544
|
|
|
547
|
-
def
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
def advance(self):
|
|
554
|
-
self.current_key = self.stream.previous_key_or_default(self.current_key, -inf)
|
|
545
|
+
def next(self) -> Maybe[tuple[int | float, T]]:
|
|
546
|
+
if self.current_key in self.stream:
|
|
547
|
+
result = (self.current_key, self.stream[self.current_key])
|
|
548
|
+
self.current_key = self.stream.previous_key_or_default(self.current_key, -inf)
|
|
549
|
+
return Some(result)
|
|
550
|
+
return Nothing
|
|
555
551
|
|
|
556
552
|
|
|
557
553
|
class _StreamAscKeyIterator[T](Record, SonolusIterator[int | float]):
|
|
558
554
|
stream: Stream[T]
|
|
559
555
|
current_key: int | float
|
|
560
556
|
|
|
561
|
-
def
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
def advance(self):
|
|
568
|
-
self.current_key = self.stream.next_key_or_default(self.current_key, inf)
|
|
557
|
+
def next(self) -> Maybe[int | float]:
|
|
558
|
+
if self.current_key in self.stream:
|
|
559
|
+
result = self.current_key
|
|
560
|
+
self.current_key = self.stream.next_key_or_default(self.current_key, inf)
|
|
561
|
+
return Some(result)
|
|
562
|
+
return Nothing
|
|
569
563
|
|
|
570
564
|
|
|
571
565
|
class _StreamBoundedAscKeyIterator[T](Record, SonolusIterator[int | float]):
|
|
@@ -573,42 +567,36 @@ class _StreamBoundedAscKeyIterator[T](Record, SonolusIterator[int | float]):
|
|
|
573
567
|
current_key: int | float
|
|
574
568
|
end_key: int | float
|
|
575
569
|
|
|
576
|
-
def
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
def advance(self):
|
|
583
|
-
self.current_key = self.stream.next_key_or_default(self.current_key, inf)
|
|
570
|
+
def next(self) -> Maybe[int | float]:
|
|
571
|
+
if self.current_key in self.stream and self.current_key <= self.end_key:
|
|
572
|
+
result = self.current_key
|
|
573
|
+
self.current_key = self.stream.next_key_or_default(self.current_key, inf)
|
|
574
|
+
return Some(result)
|
|
575
|
+
return Nothing
|
|
584
576
|
|
|
585
577
|
|
|
586
578
|
class _StreamDescKeyIterator[T](Record, SonolusIterator[int | float]):
|
|
587
579
|
stream: Stream[T]
|
|
588
580
|
current_key: int | float
|
|
589
581
|
|
|
590
|
-
def
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
def advance(self):
|
|
597
|
-
self.current_key = self.stream.previous_key_or_default(self.current_key, -inf)
|
|
582
|
+
def next(self) -> Maybe[int | float]:
|
|
583
|
+
if self.current_key in self.stream:
|
|
584
|
+
result = self.current_key
|
|
585
|
+
self.current_key = self.stream.previous_key_or_default(self.current_key, -inf)
|
|
586
|
+
return Some(result)
|
|
587
|
+
return Nothing
|
|
598
588
|
|
|
599
589
|
|
|
600
590
|
class _StreamAscValueIterator[T](Record, SonolusIterator[T]):
|
|
601
591
|
stream: Stream[T]
|
|
602
592
|
current_key: int | float
|
|
603
593
|
|
|
604
|
-
def
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
def advance(self):
|
|
611
|
-
self.current_key = self.stream.next_key_or_default(self.current_key, inf)
|
|
594
|
+
def next(self) -> Maybe[T]:
|
|
595
|
+
if self.current_key in self.stream:
|
|
596
|
+
result = self.stream[self.current_key]
|
|
597
|
+
self.current_key = self.stream.next_key_or_default(self.current_key, inf)
|
|
598
|
+
return Some(result)
|
|
599
|
+
return Nothing
|
|
612
600
|
|
|
613
601
|
|
|
614
602
|
class _StreamBoundedAscValueIterator[T](Record, SonolusIterator[T]):
|
|
@@ -616,28 +604,24 @@ class _StreamBoundedAscValueIterator[T](Record, SonolusIterator[T]):
|
|
|
616
604
|
current_key: int | float
|
|
617
605
|
end_key: int | float
|
|
618
606
|
|
|
619
|
-
def
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
def advance(self):
|
|
626
|
-
self.current_key = self.stream.next_key_or_default(self.current_key, inf)
|
|
607
|
+
def next(self) -> Maybe[T]:
|
|
608
|
+
if self.current_key in self.stream and self.current_key <= self.end_key:
|
|
609
|
+
result = self.stream[self.current_key]
|
|
610
|
+
self.current_key = self.stream.next_key_or_default(self.current_key, inf)
|
|
611
|
+
return Some(result)
|
|
612
|
+
return Nothing
|
|
627
613
|
|
|
628
614
|
|
|
629
615
|
class _StreamDescValueIterator[T](Record, SonolusIterator[T]):
|
|
630
616
|
stream: Stream[T]
|
|
631
617
|
current_key: int | float
|
|
632
618
|
|
|
633
|
-
def
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
def advance(self):
|
|
640
|
-
self.current_key = self.stream.previous_key_or_default(self.current_key, -inf)
|
|
619
|
+
def next(self) -> Maybe[T]:
|
|
620
|
+
if self.current_key in self.stream:
|
|
621
|
+
result = self.stream[self.current_key]
|
|
622
|
+
self.current_key = self.stream.previous_key_or_default(self.current_key, -inf)
|
|
623
|
+
return Some(result)
|
|
624
|
+
return Nothing
|
|
641
625
|
|
|
642
626
|
|
|
643
627
|
@native_function(Op.StreamGetNextKey)
|