sonolus.py 0.1.3__py3-none-any.whl → 0.1.5__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/blocks.py +756 -756
- sonolus/backend/excepthook.py +37 -37
- sonolus/backend/finalize.py +77 -69
- sonolus/backend/interpret.py +7 -7
- sonolus/backend/ir.py +29 -3
- sonolus/backend/mode.py +24 -24
- sonolus/backend/node.py +40 -40
- sonolus/backend/ops.py +197 -197
- sonolus/backend/optimize/__init__.py +0 -0
- sonolus/backend/optimize/allocate.py +126 -0
- sonolus/backend/optimize/constant_evaluation.py +374 -0
- sonolus/backend/optimize/copy_coalesce.py +85 -0
- sonolus/backend/optimize/dead_code.py +185 -0
- sonolus/backend/optimize/dominance.py +96 -0
- sonolus/backend/{flow.py → optimize/flow.py} +122 -92
- sonolus/backend/optimize/inlining.py +137 -0
- sonolus/backend/optimize/liveness.py +177 -0
- sonolus/backend/optimize/optimize.py +44 -0
- sonolus/backend/optimize/passes.py +52 -0
- sonolus/backend/optimize/simplify.py +191 -0
- sonolus/backend/optimize/ssa.py +200 -0
- sonolus/backend/place.py +17 -25
- sonolus/backend/utils.py +58 -48
- sonolus/backend/visitor.py +1151 -882
- sonolus/build/cli.py +7 -1
- sonolus/build/compile.py +88 -90
- sonolus/build/engine.py +10 -5
- sonolus/build/level.py +24 -23
- sonolus/build/node.py +43 -43
- sonolus/script/archetype.py +438 -139
- sonolus/script/array.py +27 -10
- sonolus/script/array_like.py +297 -0
- sonolus/script/bucket.py +253 -191
- sonolus/script/containers.py +257 -51
- sonolus/script/debug.py +26 -10
- sonolus/script/easing.py +365 -0
- sonolus/script/effect.py +191 -131
- sonolus/script/engine.py +71 -4
- sonolus/script/globals.py +303 -269
- sonolus/script/instruction.py +205 -151
- sonolus/script/internal/__init__.py +5 -5
- sonolus/script/internal/builtin_impls.py +255 -144
- sonolus/script/{callbacks.py → internal/callbacks.py} +127 -127
- sonolus/script/internal/constant.py +139 -0
- sonolus/script/internal/context.py +26 -9
- sonolus/script/internal/descriptor.py +17 -17
- sonolus/script/internal/dict_impl.py +65 -0
- sonolus/script/internal/generic.py +6 -9
- sonolus/script/internal/impl.py +38 -13
- sonolus/script/internal/introspection.py +17 -14
- sonolus/script/internal/math_impls.py +121 -0
- sonolus/script/internal/native.py +40 -38
- sonolus/script/internal/random.py +67 -0
- sonolus/script/internal/range.py +81 -0
- sonolus/script/internal/transient.py +51 -0
- sonolus/script/internal/tuple_impl.py +113 -0
- sonolus/script/internal/value.py +3 -3
- sonolus/script/interval.py +338 -112
- sonolus/script/iterator.py +167 -214
- sonolus/script/level.py +24 -0
- sonolus/script/num.py +80 -48
- sonolus/script/options.py +257 -191
- sonolus/script/particle.py +190 -157
- sonolus/script/pointer.py +30 -30
- sonolus/script/print.py +102 -81
- sonolus/script/project.py +8 -0
- sonolus/script/quad.py +263 -0
- sonolus/script/record.py +47 -16
- sonolus/script/runtime.py +52 -1
- sonolus/script/sprite.py +418 -333
- sonolus/script/text.py +409 -407
- sonolus/script/timing.py +114 -42
- sonolus/script/transform.py +332 -48
- sonolus/script/ui.py +216 -160
- sonolus/script/values.py +6 -13
- sonolus/script/vec.py +196 -78
- {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.5.dist-info}/METADATA +1 -1
- sonolus_py-0.1.5.dist-info/RECORD +89 -0
- {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.5.dist-info}/WHEEL +1 -1
- {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.5.dist-info}/licenses/LICENSE +21 -21
- sonolus/backend/allocate.py +0 -51
- sonolus/backend/optimize.py +0 -9
- sonolus/backend/passes.py +0 -6
- sonolus/backend/simplify.py +0 -30
- sonolus/script/comptime.py +0 -160
- sonolus/script/graphics.py +0 -150
- sonolus/script/math.py +0 -92
- sonolus/script/range.py +0 -58
- sonolus_py-0.1.3.dist-info/RECORD +0 -75
- {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.5.dist-info}/entry_points.txt +0 -0
sonolus/script/interval.py
CHANGED
|
@@ -1,112 +1,338 @@
|
|
|
1
|
-
from typing import Self
|
|
2
|
-
|
|
3
|
-
from sonolus.backend.ops import Op
|
|
4
|
-
from sonolus.script.debug import error
|
|
5
|
-
from sonolus.script.internal.native import native_function
|
|
6
|
-
from sonolus.script.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return
|
|
72
|
-
|
|
73
|
-
def
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
def
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
1
|
+
from typing import Self
|
|
2
|
+
|
|
3
|
+
from sonolus.backend.ops import Op
|
|
4
|
+
from sonolus.script.debug import error
|
|
5
|
+
from sonolus.script.internal.native import native_function
|
|
6
|
+
from sonolus.script.num import Num
|
|
7
|
+
from sonolus.script.record import Record
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Interval(Record):
|
|
11
|
+
"""A closed interval.
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
```python
|
|
15
|
+
Interval(start: float, end: float)
|
|
16
|
+
```
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
start: float
|
|
20
|
+
end: float
|
|
21
|
+
|
|
22
|
+
@property
|
|
23
|
+
def length(self) -> float:
|
|
24
|
+
"""The length of the interval.
|
|
25
|
+
|
|
26
|
+
May be negative if the end is less than the start.
|
|
27
|
+
"""
|
|
28
|
+
return self.end - self.start
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def is_empty(self) -> bool:
|
|
32
|
+
"""Whether the interval has length of zero or less."""
|
|
33
|
+
return self.start > self.end
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def mid(self) -> float:
|
|
37
|
+
"""The midpoint of the interval."""
|
|
38
|
+
return (self.start + self.end) / 2
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def tuple(self):
|
|
42
|
+
"""The interval as a tuple."""
|
|
43
|
+
return self.start, self.end
|
|
44
|
+
|
|
45
|
+
def __contains__(self, item: Self | float | int) -> bool:
|
|
46
|
+
"""Check if an item is within the interval.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
item: The item to check. If it is an interval, it must be fully contained within this interval.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
True if the item is within the interval, False otherwise.
|
|
53
|
+
"""
|
|
54
|
+
match item:
|
|
55
|
+
case Interval(start, end):
|
|
56
|
+
return self.start <= start and end <= self.end
|
|
57
|
+
case Num(value):
|
|
58
|
+
return self.start <= value <= self.end
|
|
59
|
+
case _:
|
|
60
|
+
error("Invalid type for interval check")
|
|
61
|
+
|
|
62
|
+
def __add__(self, other: float | int) -> Self:
|
|
63
|
+
"""Add a value to both ends of the interval.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
other: The value to add.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
A new interval with the value added to both ends.
|
|
70
|
+
"""
|
|
71
|
+
return Interval(self.start + other, self.end + other)
|
|
72
|
+
|
|
73
|
+
def __sub__(self, other: float | int) -> Self:
|
|
74
|
+
"""Subtract a value from both ends of the interval.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
other: The value to subtract.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
A new interval with the value subtracted from both ends.
|
|
81
|
+
"""
|
|
82
|
+
return Interval(self.start - other, self.end - other)
|
|
83
|
+
|
|
84
|
+
def __mul__(self, other: float | int) -> Self:
|
|
85
|
+
"""Multiply both ends of the interval by a value.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
other: The value to multiply by.
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
A new interval with both ends multiplied by the value.
|
|
92
|
+
"""
|
|
93
|
+
return Interval(self.start * other, self.end * other)
|
|
94
|
+
|
|
95
|
+
def __truediv__(self, other: float | int) -> Self:
|
|
96
|
+
"""Divide both ends of the interval by a value.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
other: The value to divide by.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
A new interval with both ends divided by the value.
|
|
103
|
+
"""
|
|
104
|
+
return Interval(self.start / other, self.end / other)
|
|
105
|
+
|
|
106
|
+
def __floordiv__(self, other: float | int) -> Self:
|
|
107
|
+
"""Divide both ends of the interval by a value and floor the result.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
other: The value to divide by.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
A new interval with both ends divided by the value and floored.
|
|
114
|
+
"""
|
|
115
|
+
return Interval(self.start // other, self.end // other)
|
|
116
|
+
|
|
117
|
+
def __and__(self, other: Self) -> Self:
|
|
118
|
+
"""Get the intersection of two intervals.
|
|
119
|
+
|
|
120
|
+
The resulting interval will be empty and may have a negative length if the two intervals do not overlap.
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
other: The other interval.
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
A new interval representing the intersection of the two intervals.
|
|
127
|
+
"""
|
|
128
|
+
return Interval(max(self.start, other.start), min(self.end, other.end))
|
|
129
|
+
|
|
130
|
+
def shrink(self, value: float | int) -> Self:
|
|
131
|
+
"""Shrink the interval by a value on both ends.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
value: The value to shrink by.
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
A new interval with the value subtracted from the start and added to the end.
|
|
138
|
+
"""
|
|
139
|
+
return Interval(self.start + value, self.end - value)
|
|
140
|
+
|
|
141
|
+
def expand(self, value: float | int) -> Self:
|
|
142
|
+
"""Expand the interval by a value on both ends.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
value: The value to expand by.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
A new interval with the value subtracted from the start and added to the end.
|
|
149
|
+
"""
|
|
150
|
+
return Interval(self.start - value, self.end + value)
|
|
151
|
+
|
|
152
|
+
def lerp(self, x: float, /) -> float:
|
|
153
|
+
"""Linearly interpolate a value within the interval.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
x: The interpolation factor.
|
|
157
|
+
|
|
158
|
+
Returns:
|
|
159
|
+
The interpolated value.
|
|
160
|
+
"""
|
|
161
|
+
return lerp(self.start, self.end, x)
|
|
162
|
+
|
|
163
|
+
def lerp_clamped(self, x: float, /) -> float:
|
|
164
|
+
"""Linearly interpolate a value within the interval, clamped to the interval.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
x: The interpolation factor.
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
The interpolated value.
|
|
171
|
+
"""
|
|
172
|
+
return lerp_clamped(self.start, self.end, x)
|
|
173
|
+
|
|
174
|
+
def unlerp(self, x: float, /) -> float:
|
|
175
|
+
"""Inverse linear interpolation of a value within the interval.
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
x: The value to unlerp.
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
The unlerped value.
|
|
182
|
+
"""
|
|
183
|
+
return unlerp(self.start, self.end, x)
|
|
184
|
+
|
|
185
|
+
def unlerp_clamped(self, x: float, /) -> float:
|
|
186
|
+
"""Inverse linear interpolation of a value within the interval, clamped to the interval.
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
x: The value to unlerp.
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
The unlerped value.
|
|
193
|
+
"""
|
|
194
|
+
return unlerp_clamped(self.start, self.end, x)
|
|
195
|
+
|
|
196
|
+
def clamp(self, x: float, /) -> float:
|
|
197
|
+
"""Clamp a value to the interval.
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
x: The value to clamp.
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
The clamped value.
|
|
204
|
+
"""
|
|
205
|
+
return clamp(x, self.start, self.end)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@native_function(Op.Lerp)
|
|
209
|
+
def _num_lerp(a, b, x, /):
|
|
210
|
+
return a + (b - a) * x
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
@native_function(Op.LerpClamped)
|
|
214
|
+
def _num_lerp_clamped(a, b, x, /):
|
|
215
|
+
return a + (b - a) * max(0, min(1, x))
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _generic_lerp[T](a: T, b: T, x: float, /) -> T:
|
|
219
|
+
return a + (b - a) * x
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def _generic_lerp_clamped[T](a: T, b: T, x: float, /) -> T:
|
|
223
|
+
return a + (b - a) * max(0, min(1, x))
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def lerp[T](a: T, b: T, x: float, /) -> T:
|
|
227
|
+
"""Linearly interpolate between two values.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
a: The start value.
|
|
231
|
+
b: The end value.
|
|
232
|
+
x: The interpolation factor.
|
|
233
|
+
|
|
234
|
+
Returns:
|
|
235
|
+
The interpolated value.
|
|
236
|
+
"""
|
|
237
|
+
match a, b:
|
|
238
|
+
case (Num(a), Num(b)):
|
|
239
|
+
return _num_lerp(a, b, x)
|
|
240
|
+
case _:
|
|
241
|
+
return _generic_lerp(a, b, x)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def lerp_clamped[T](a: T, b: T, x: float, /) -> T:
|
|
245
|
+
"""Linearly interpolate between two values, clamped to the interval.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
a: The start value.
|
|
249
|
+
b: The end value.
|
|
250
|
+
x: The interpolation factor.
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
The interpolated value.
|
|
254
|
+
"""
|
|
255
|
+
match a, b:
|
|
256
|
+
case (Num(a), Num(b)):
|
|
257
|
+
return _num_lerp_clamped(a, b, x)
|
|
258
|
+
case _:
|
|
259
|
+
return _generic_lerp_clamped(a, b, x)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
@native_function(Op.Unlerp)
|
|
263
|
+
def unlerp(a: float, b: float, x: float, /) -> float:
|
|
264
|
+
"""Inverse linear interpolation.
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
a: The start value.
|
|
268
|
+
b: The end value.
|
|
269
|
+
x: The value to unlerp.
|
|
270
|
+
|
|
271
|
+
Returns:
|
|
272
|
+
The unlerped value.
|
|
273
|
+
"""
|
|
274
|
+
return (x - a) / (b - a)
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
@native_function(Op.UnlerpClamped)
|
|
278
|
+
def unlerp_clamped(a: float, b: float, x: float, /) -> float:
|
|
279
|
+
"""Inverse linear interpolation, clamped to the interval.
|
|
280
|
+
|
|
281
|
+
Args:
|
|
282
|
+
a: The start value.
|
|
283
|
+
b: The end value.
|
|
284
|
+
x: The value to unlerp.
|
|
285
|
+
|
|
286
|
+
Returns:
|
|
287
|
+
The unlerped value.
|
|
288
|
+
"""
|
|
289
|
+
return max(0, min(1, (x - a) / (b - a)))
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
@native_function(Op.Remap)
|
|
293
|
+
def remap(a: float, b: float, c: float, d: float, x: float, /) -> float:
|
|
294
|
+
"""Remap a value from one interval to another.
|
|
295
|
+
|
|
296
|
+
Args:
|
|
297
|
+
a: The start of the input interval.
|
|
298
|
+
b: The end of the input interval.
|
|
299
|
+
c: The start of the output interval.
|
|
300
|
+
d: The end of the output interval.
|
|
301
|
+
x: The value to remap.
|
|
302
|
+
|
|
303
|
+
Returns:
|
|
304
|
+
The remapped value.
|
|
305
|
+
"""
|
|
306
|
+
return c + (d - c) * (x - a) / (b - a)
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
@native_function(Op.RemapClamped)
|
|
310
|
+
def remap_clamped(a: float, b: float, c: float, d: float, x: float, /) -> float:
|
|
311
|
+
"""Remap a value from one interval to another, clamped to the output interval.
|
|
312
|
+
|
|
313
|
+
Args:
|
|
314
|
+
a: The start of the input interval.
|
|
315
|
+
b: The end of the input interval.
|
|
316
|
+
c: The start of the output interval.
|
|
317
|
+
d: The end of the output interval.
|
|
318
|
+
x: The value to remap.
|
|
319
|
+
|
|
320
|
+
Returns:
|
|
321
|
+
The remapped value.
|
|
322
|
+
"""
|
|
323
|
+
return c + (d - c) * max(0, min(1, (x - a) / (b - a)))
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
@native_function(Op.Clamp)
|
|
327
|
+
def clamp(x: float, a: float, b: float, /) -> float:
|
|
328
|
+
"""Clamp a value to an interval.
|
|
329
|
+
|
|
330
|
+
Args:
|
|
331
|
+
x: The value to clamp.
|
|
332
|
+
a: The start of the interval.
|
|
333
|
+
b: The end of the interval.
|
|
334
|
+
|
|
335
|
+
Returns:
|
|
336
|
+
The clamped value.
|
|
337
|
+
"""
|
|
338
|
+
return max(a, min(b, x))
|