sonolus.py 0.3.4__py3-none-any.whl → 0.4.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.

Potentially problematic release.


This version of sonolus.py might be problematic. Click here for more details.

Files changed (64) hide show
  1. sonolus/backend/excepthook.py +30 -0
  2. sonolus/backend/finalize.py +15 -1
  3. sonolus/backend/ops.py +4 -0
  4. sonolus/backend/optimize/allocate.py +5 -5
  5. sonolus/backend/optimize/constant_evaluation.py +124 -19
  6. sonolus/backend/optimize/copy_coalesce.py +15 -12
  7. sonolus/backend/optimize/dead_code.py +7 -6
  8. sonolus/backend/optimize/dominance.py +2 -2
  9. sonolus/backend/optimize/flow.py +54 -8
  10. sonolus/backend/optimize/inlining.py +137 -30
  11. sonolus/backend/optimize/liveness.py +2 -2
  12. sonolus/backend/optimize/optimize.py +15 -1
  13. sonolus/backend/optimize/passes.py +11 -3
  14. sonolus/backend/optimize/simplify.py +137 -8
  15. sonolus/backend/optimize/ssa.py +47 -13
  16. sonolus/backend/place.py +5 -4
  17. sonolus/backend/utils.py +44 -16
  18. sonolus/backend/visitor.py +288 -17
  19. sonolus/build/cli.py +47 -19
  20. sonolus/build/compile.py +12 -5
  21. sonolus/build/engine.py +70 -1
  22. sonolus/build/level.py +3 -3
  23. sonolus/build/project.py +2 -2
  24. sonolus/script/archetype.py +12 -9
  25. sonolus/script/array.py +23 -18
  26. sonolus/script/array_like.py +26 -29
  27. sonolus/script/bucket.py +1 -1
  28. sonolus/script/containers.py +22 -26
  29. sonolus/script/debug.py +20 -43
  30. sonolus/script/effect.py +1 -1
  31. sonolus/script/globals.py +3 -3
  32. sonolus/script/instruction.py +2 -2
  33. sonolus/script/internal/builtin_impls.py +155 -28
  34. sonolus/script/internal/constant.py +13 -3
  35. sonolus/script/internal/context.py +46 -15
  36. sonolus/script/internal/impl.py +9 -3
  37. sonolus/script/internal/introspection.py +8 -1
  38. sonolus/script/internal/native.py +2 -2
  39. sonolus/script/internal/range.py +8 -11
  40. sonolus/script/internal/simulation_context.py +1 -1
  41. sonolus/script/internal/transient.py +2 -2
  42. sonolus/script/internal/value.py +41 -3
  43. sonolus/script/interval.py +13 -13
  44. sonolus/script/iterator.py +53 -107
  45. sonolus/script/level.py +2 -2
  46. sonolus/script/maybe.py +241 -0
  47. sonolus/script/num.py +29 -14
  48. sonolus/script/options.py +1 -1
  49. sonolus/script/particle.py +1 -1
  50. sonolus/script/project.py +24 -5
  51. sonolus/script/quad.py +15 -15
  52. sonolus/script/record.py +48 -44
  53. sonolus/script/runtime.py +22 -18
  54. sonolus/script/sprite.py +1 -1
  55. sonolus/script/stream.py +66 -82
  56. sonolus/script/transform.py +35 -34
  57. sonolus/script/values.py +10 -10
  58. sonolus/script/vec.py +21 -18
  59. {sonolus_py-0.3.4.dist-info → sonolus_py-0.4.1.dist-info}/METADATA +1 -1
  60. sonolus_py-0.4.1.dist-info/RECORD +93 -0
  61. sonolus_py-0.3.4.dist-info/RECORD +0 -92
  62. {sonolus_py-0.3.4.dist-info → sonolus_py-0.4.1.dist-info}/WHEEL +0 -0
  63. {sonolus_py-0.3.4.dist-info → sonolus_py-0.4.1.dist-info}/entry_points.txt +0 -0
  64. {sonolus_py-0.3.4.dist-info → sonolus_py-0.4.1.dist-info}/licenses/LICENSE +0 -0
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()._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
- return Stream[self.type_var_value(T)](max(1, sizeof(self.element_type())) * index + self.offset)
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 has_next(self) -> bool:
519
- return self.current_key in self.stream
520
-
521
- def get(self) -> tuple[int | float, T]:
522
- return self.current_key, self.stream[self.current_key]
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 has_next(self) -> bool:
534
- return self.current_key in self.stream and self.current_key <= self.end_key
535
-
536
- def get(self) -> tuple[int | float, T]:
537
- return self.current_key, self.stream[self.current_key]
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 has_next(self) -> bool:
548
- return self.current_key in self.stream
549
-
550
- def get(self) -> tuple[int | float, T]:
551
- return self.current_key, self.stream[self.current_key]
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 has_next(self) -> bool:
562
- return self.current_key in self.stream
563
-
564
- def get(self) -> int | float:
565
- return self.current_key
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 has_next(self) -> bool:
577
- return self.current_key in self.stream and self.current_key <= self.end_key
578
-
579
- def get(self) -> int | float:
580
- return self.current_key
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 has_next(self) -> bool:
591
- return self.current_key in self.stream
592
-
593
- def get(self) -> int | float:
594
- return self.current_key
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 has_next(self) -> bool:
605
- return self.current_key in self.stream
606
-
607
- def get(self) -> T:
608
- return self.stream[self.current_key]
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 has_next(self) -> bool:
620
- return self.current_key in self.stream and self.current_key <= self.end_key
621
-
622
- def get(self) -> T:
623
- return self.stream[self.current_key]
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 has_next(self) -> bool:
634
- return self.current_key in self.stream
635
-
636
- def get(self) -> T:
637
- return self.stream[self.current_key]
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)
@@ -1,5 +1,6 @@
1
+ from __future__ import annotations
2
+
1
3
  from math import cos, sin
2
- from typing import Self
3
4
 
4
5
  from sonolus.script.interval import lerp, remap
5
6
  from sonolus.script.quad import Quad, QuadLike
@@ -27,7 +28,7 @@ class Transform2d(Record):
27
28
  a22: float
28
29
 
29
30
  @classmethod
30
- def new(cls) -> Self:
31
+ def new(cls) -> Transform2d:
31
32
  """Create a new identity transform.
32
33
 
33
34
  Returns:
@@ -56,7 +57,7 @@ class Transform2d(Record):
56
57
  b20: float,
57
58
  b21: float,
58
59
  b22: float,
59
- ) -> Self:
60
+ ) -> Transform2d:
60
61
  # Multiply by b on the left (b @ a)
61
62
  a00 = self.a00 * b00 + self.a10 * b01 + self.a20 * b02
62
63
  a01 = self.a01 * b00 + self.a11 * b01 + self.a21 * b02
@@ -79,7 +80,7 @@ class Transform2d(Record):
79
80
  a22,
80
81
  )
81
82
 
82
- def translate(self, translation: Vec2, /) -> Self:
83
+ def translate(self, translation: Vec2, /) -> Transform2d:
83
84
  """Translate along the x and y axes and return a new transform.
84
85
 
85
86
  Args:
@@ -100,7 +101,7 @@ class Transform2d(Record):
100
101
  1,
101
102
  )
102
103
 
103
- def scale(self, factor: Vec2, /) -> Self:
104
+ def scale(self, factor: Vec2, /) -> Transform2d:
104
105
  """Scale about the origin and return a new transform.
105
106
 
106
107
  Args:
@@ -121,7 +122,7 @@ class Transform2d(Record):
121
122
  1,
122
123
  )
123
124
 
124
- def scale_about(self, factor: Vec2, /, pivot: Vec2) -> Self:
125
+ def scale_about(self, factor: Vec2, /, pivot: Vec2) -> Transform2d:
125
126
  """Scale about the pivot and return a new transform.
126
127
 
127
128
  Args:
@@ -133,7 +134,7 @@ class Transform2d(Record):
133
134
  """
134
135
  return self.translate(-pivot).scale(factor).translate(pivot)
135
136
 
136
- def rotate(self, angle: float, /) -> Self:
137
+ def rotate(self, angle: float, /) -> Transform2d:
137
138
  """Rotate about the origin and return a new transform.
138
139
 
139
140
  Args:
@@ -156,7 +157,7 @@ class Transform2d(Record):
156
157
  1,
157
158
  )
158
159
 
159
- def rotate_about(self, angle: float, /, pivot: Vec2) -> Self:
160
+ def rotate_about(self, angle: float, /, pivot: Vec2) -> Transform2d:
160
161
  """Rotate about the pivot and return a new transform.
161
162
 
162
163
  Args:
@@ -168,7 +169,7 @@ class Transform2d(Record):
168
169
  """
169
170
  return self.translate(-pivot).rotate(angle).translate(pivot)
170
171
 
171
- def shear_x(self, m: float, /) -> Self:
172
+ def shear_x(self, m: float, /) -> Transform2d:
172
173
  """Shear along the x-axis and return a new transform.
173
174
 
174
175
  Args:
@@ -189,7 +190,7 @@ class Transform2d(Record):
189
190
  1,
190
191
  )
191
192
 
192
- def shear_y(self, m: float, /) -> Self:
193
+ def shear_y(self, m: float, /) -> Transform2d:
193
194
  """Shear along the y-axis and return a new transform.
194
195
 
195
196
  Args:
@@ -210,7 +211,7 @@ class Transform2d(Record):
210
211
  1,
211
212
  )
212
213
 
213
- def simple_perspective_x(self, x: float, /) -> Self:
214
+ def simple_perspective_x(self, x: float, /) -> Transform2d:
214
215
  """Apply perspective along the x-axis with vanishing point at the given x coordinate and return a new transform.
215
216
 
216
217
  Args:
@@ -231,7 +232,7 @@ class Transform2d(Record):
231
232
  1,
232
233
  )
233
234
 
234
- def simple_perspective_y(self, y: float, /) -> Self:
235
+ def simple_perspective_y(self, y: float, /) -> Transform2d:
235
236
  """Apply perspective along the y-axis with vanishing point at the given y coordinate and return a new transform.
236
237
 
237
238
  Args:
@@ -252,7 +253,7 @@ class Transform2d(Record):
252
253
  1,
253
254
  )
254
255
 
255
- def perspective_x(self, foreground_x: float, vanishing_point: Vec2, /) -> Self:
256
+ def perspective_x(self, foreground_x: float, vanishing_point: Vec2, /) -> Transform2d:
256
257
  """Apply a perspective transformation along the x-axis and return a new transform.
257
258
 
258
259
  Args:
@@ -268,7 +269,7 @@ class Transform2d(Record):
268
269
  .translate(Vec2(foreground_x, 0))
269
270
  )
270
271
 
271
- def perspective_y(self, foreground_y: float, vanishing_point: Vec2, /) -> Self:
272
+ def perspective_y(self, foreground_y: float, vanishing_point: Vec2, /) -> Transform2d:
272
273
  """Apply a perspective transformation along the y-axis and return a new transform.
273
274
 
274
275
  Args:
@@ -284,7 +285,7 @@ class Transform2d(Record):
284
285
  .translate(Vec2(0, foreground_y))
285
286
  )
286
287
 
287
- def inverse_perspective_x(self, foreground_x: float, vanishing_point: Vec2, /) -> Self:
288
+ def inverse_perspective_x(self, foreground_x: float, vanishing_point: Vec2, /) -> Transform2d:
288
289
  """Apply the inverse of a perspective transformation along the x-axis and return a new transform.
289
290
 
290
291
  Args:
@@ -300,7 +301,7 @@ class Transform2d(Record):
300
301
  .simple_perspective_x(-vanishing_point.x + foreground_x)
301
302
  )
302
303
 
303
- def inverse_perspective_y(self, foreground_y: float, vanishing_point: Vec2, /) -> Self:
304
+ def inverse_perspective_y(self, foreground_y: float, vanishing_point: Vec2, /) -> Transform2d:
304
305
  """Apply the inverse of a perspective transformation along the y-axis and return a new transform.
305
306
 
306
307
  Args:
@@ -316,7 +317,7 @@ class Transform2d(Record):
316
317
  .simple_perspective_y(-vanishing_point.y + foreground_y)
317
318
  )
318
319
 
319
- def normalize(self) -> Self:
320
+ def normalize(self) -> Transform2d:
320
321
  """Normalize the transform to have a 1 in the bottom right corner and return a new transform.
321
322
 
322
323
  This may fail in some special cases involving perspective transformations where the bottom right corner is 0.
@@ -336,7 +337,7 @@ class Transform2d(Record):
336
337
  1,
337
338
  )
338
339
 
339
- def compose(self, other: Self, /) -> Self:
340
+ def compose(self, other: Transform2d, /) -> Transform2d:
340
341
  """Compose with another transform which is applied after this transform and return a new transform.
341
342
 
342
343
  Args:
@@ -357,7 +358,7 @@ class Transform2d(Record):
357
358
  other.a22,
358
359
  )
359
360
 
360
- def compose_before(self, other: Self, /) -> Self:
361
+ def compose_before(self, other: Transform2d, /) -> Transform2d:
361
362
  """Compose with another transform which is applied before this transform and return a new transform.
362
363
 
363
364
  Args:
@@ -412,7 +413,7 @@ class InvertibleTransform2d(Record):
412
413
  inverse: Transform2d
413
414
 
414
415
  @classmethod
415
- def new(cls) -> Self:
416
+ def new(cls) -> InvertibleTransform2d:
416
417
  """Create a new identity transform.
417
418
 
418
419
  Returns:
@@ -423,7 +424,7 @@ class InvertibleTransform2d(Record):
423
424
  inverse=Transform2d.new(),
424
425
  )
425
426
 
426
- def translate(self, translation: Vec2, /) -> Self:
427
+ def translate(self, translation: Vec2, /) -> InvertibleTransform2d:
427
428
  """Translate along the x and y axes and return a new transform.
428
429
 
429
430
  Args:
@@ -437,7 +438,7 @@ class InvertibleTransform2d(Record):
437
438
  inverse=Transform2d.new().translate(-translation).compose(self.inverse),
438
439
  )
439
440
 
440
- def scale(self, factor: Vec2, /) -> Self:
441
+ def scale(self, factor: Vec2, /) -> InvertibleTransform2d:
441
442
  """Scale about the origin and return a new transform.
442
443
 
443
444
  Args:
@@ -451,7 +452,7 @@ class InvertibleTransform2d(Record):
451
452
  inverse=Transform2d.new().scale(Vec2.one() / factor).compose(self.inverse),
452
453
  )
453
454
 
454
- def scale_about(self, factor: Vec2, /, pivot: Vec2) -> Self:
455
+ def scale_about(self, factor: Vec2, /, pivot: Vec2) -> InvertibleTransform2d:
455
456
  """Scale about the pivot and return a new transform.
456
457
 
457
458
  Args:
@@ -466,7 +467,7 @@ class InvertibleTransform2d(Record):
466
467
  inverse=Transform2d.new().scale_about(Vec2.one() / factor, pivot).compose(self.inverse),
467
468
  )
468
469
 
469
- def rotate(self, angle: float, /) -> Self:
470
+ def rotate(self, angle: float, /) -> InvertibleTransform2d:
470
471
  """Rotate about the origin and return a new transform.
471
472
 
472
473
  Args:
@@ -480,7 +481,7 @@ class InvertibleTransform2d(Record):
480
481
  inverse=Transform2d.new().rotate(-angle).compose(self.inverse),
481
482
  )
482
483
 
483
- def rotate_about(self, angle: float, /, pivot: Vec2) -> Self:
484
+ def rotate_about(self, angle: float, /, pivot: Vec2) -> InvertibleTransform2d:
484
485
  """Rotate about the pivot and return a new transform.
485
486
 
486
487
  Args:
@@ -495,7 +496,7 @@ class InvertibleTransform2d(Record):
495
496
  inverse=Transform2d.new().rotate_about(-angle, pivot).compose(self.inverse),
496
497
  )
497
498
 
498
- def shear_x(self, m: float, /) -> Self:
499
+ def shear_x(self, m: float, /) -> InvertibleTransform2d:
499
500
  """Shear along the x-axis and return a new transform.
500
501
 
501
502
  Args:
@@ -509,7 +510,7 @@ class InvertibleTransform2d(Record):
509
510
  inverse=Transform2d.new().shear_x(-m).compose(self.inverse),
510
511
  )
511
512
 
512
- def shear_y(self, m: float, /) -> Self:
513
+ def shear_y(self, m: float, /) -> InvertibleTransform2d:
513
514
  """Shear along the y-axis and return a new transform.
514
515
 
515
516
  Args:
@@ -523,7 +524,7 @@ class InvertibleTransform2d(Record):
523
524
  inverse=Transform2d.new().shear_y(-m).compose(self.inverse),
524
525
  )
525
526
 
526
- def simple_perspective_x(self, x: float, /) -> Self:
527
+ def simple_perspective_x(self, x: float, /) -> InvertibleTransform2d:
527
528
  """Apply perspective along the x-axis with vanishing point at the given x coordinate and return a new transform.
528
529
 
529
530
  Args:
@@ -537,7 +538,7 @@ class InvertibleTransform2d(Record):
537
538
  inverse=Transform2d.new().simple_perspective_x(-x).compose(self.inverse),
538
539
  )
539
540
 
540
- def simple_perspective_y(self, y: float, /) -> Self:
541
+ def simple_perspective_y(self, y: float, /) -> InvertibleTransform2d:
541
542
  """Apply perspective along the y-axis with vanishing point at the given y coordinate and return a new transform.
542
543
 
543
544
  Args:
@@ -551,7 +552,7 @@ class InvertibleTransform2d(Record):
551
552
  inverse=Transform2d.new().simple_perspective_y(-y).compose(self.inverse),
552
553
  )
553
554
 
554
- def perspective_x(self, foreground_x: float, vanishing_point: Vec2, /) -> Self:
555
+ def perspective_x(self, foreground_x: float, vanishing_point: Vec2, /) -> InvertibleTransform2d:
555
556
  """Apply a perspective transformation along the x-axis and return a new transform.
556
557
 
557
558
  Args:
@@ -566,7 +567,7 @@ class InvertibleTransform2d(Record):
566
567
  inverse=Transform2d.new().inverse_perspective_x(foreground_x, vanishing_point).compose(self.inverse),
567
568
  )
568
569
 
569
- def perspective_y(self, foreground_y: float, vanishing_point: Vec2, /) -> Self:
570
+ def perspective_y(self, foreground_y: float, vanishing_point: Vec2, /) -> InvertibleTransform2d:
570
571
  """Apply a perspective transformation along the y-axis and return a new transform.
571
572
 
572
573
  Args:
@@ -581,7 +582,7 @@ class InvertibleTransform2d(Record):
581
582
  inverse=Transform2d.new().inverse_perspective_y(foreground_y, vanishing_point).compose(self.inverse),
582
583
  )
583
584
 
584
- def normalize(self) -> Self:
585
+ def normalize(self) -> InvertibleTransform2d:
585
586
  """Normalize the transform to have a 1 in the bottom right corner and return a new transform.
586
587
 
587
588
  This may fail in some special cases involving perspective transformations where the bottom right corner is 0.
@@ -594,7 +595,7 @@ class InvertibleTransform2d(Record):
594
595
  inverse=self.inverse.normalize(),
595
596
  )
596
597
 
597
- def compose(self, other: Self, /) -> Self:
598
+ def compose(self, other: InvertibleTransform2d, /) -> InvertibleTransform2d:
598
599
  """Compose with another invertible transform which is applied after this transform and return a new transform.
599
600
 
600
601
  Args:
@@ -608,7 +609,7 @@ class InvertibleTransform2d(Record):
608
609
  inverse=other.inverse.compose(self.inverse),
609
610
  )
610
611
 
611
- def compose_before(self, other: Self, /) -> Self:
612
+ def compose_before(self, other: InvertibleTransform2d, /) -> InvertibleTransform2d:
612
613
  """Compose with another invertible transform which is applied before this transform and return a new transform.
613
614
 
614
615
  Args:
sonolus/script/values.py CHANGED
@@ -5,25 +5,25 @@ from sonolus.script.num import Num
5
5
 
6
6
 
7
7
  @meta_fn
8
- def alloc[T](type_: type[T]) -> T:
8
+ def alloc[T](type_: type[T]) -> T: # type: ignore
9
9
  """Return an uninitialized instance of the given type.
10
10
 
11
11
  Use this carefully as reading from uninitialized memory can lead to unexpected behavior.
12
12
  """
13
13
  type_ = validate_concrete_type(type_)
14
14
  if ctx():
15
- return type_._alloc_()
15
+ return type_._alloc_() # type: ignore
16
16
  else:
17
- return type_._alloc_()._as_py_()
17
+ return type_._alloc_()._as_py_() # type: ignore
18
18
 
19
19
 
20
20
  @meta_fn
21
- def zeros[T](type_: type[T]) -> T:
21
+ def zeros[T](type_: type[T]) -> T: # type: ignore
22
22
  """Make a new instance of the given type initialized with zeros.
23
23
 
24
24
  Generally works the same as the unary `+` operator on record and array types.
25
25
  """
26
- return validate_concrete_type(type_)._zero_()
26
+ return validate_concrete_type(type_)._zero_() # type: ignore
27
27
 
28
28
 
29
29
  @meta_fn
@@ -32,18 +32,18 @@ def copy[T](value: T) -> T:
32
32
 
33
33
  Generally works the same as the unary `+` operator on records and arrays.
34
34
  """
35
- value = validate_value(value)
35
+ value = validate_value(value) # type: ignore
36
36
  if ctx():
37
- return value._copy_()
37
+ return value._copy_() # type: ignore
38
38
  else:
39
- return value._copy_()._as_py_()
39
+ return value._copy_()._as_py_() # type: ignore
40
40
 
41
41
 
42
42
  def swap[T](a: T, b: T):
43
43
  """Swap the values of the two provided mutable values."""
44
44
  temp = copy(a)
45
- a @= b
46
- b @= temp
45
+ a @= b # type: ignore
46
+ b @= temp # type: ignore
47
47
 
48
48
 
49
49
  @meta_fn