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.

Files changed (90) hide show
  1. sonolus/backend/blocks.py +756 -756
  2. sonolus/backend/excepthook.py +37 -37
  3. sonolus/backend/finalize.py +77 -69
  4. sonolus/backend/interpret.py +7 -7
  5. sonolus/backend/ir.py +29 -3
  6. sonolus/backend/mode.py +24 -24
  7. sonolus/backend/node.py +40 -40
  8. sonolus/backend/ops.py +197 -197
  9. sonolus/backend/optimize/__init__.py +0 -0
  10. sonolus/backend/optimize/allocate.py +126 -0
  11. sonolus/backend/optimize/constant_evaluation.py +374 -0
  12. sonolus/backend/optimize/copy_coalesce.py +85 -0
  13. sonolus/backend/optimize/dead_code.py +185 -0
  14. sonolus/backend/optimize/dominance.py +96 -0
  15. sonolus/backend/{flow.py → optimize/flow.py} +122 -92
  16. sonolus/backend/optimize/inlining.py +137 -0
  17. sonolus/backend/optimize/liveness.py +177 -0
  18. sonolus/backend/optimize/optimize.py +44 -0
  19. sonolus/backend/optimize/passes.py +52 -0
  20. sonolus/backend/optimize/simplify.py +191 -0
  21. sonolus/backend/optimize/ssa.py +200 -0
  22. sonolus/backend/place.py +17 -25
  23. sonolus/backend/utils.py +58 -48
  24. sonolus/backend/visitor.py +1151 -882
  25. sonolus/build/cli.py +7 -1
  26. sonolus/build/compile.py +88 -90
  27. sonolus/build/engine.py +10 -5
  28. sonolus/build/level.py +24 -23
  29. sonolus/build/node.py +43 -43
  30. sonolus/script/archetype.py +438 -139
  31. sonolus/script/array.py +27 -10
  32. sonolus/script/array_like.py +297 -0
  33. sonolus/script/bucket.py +253 -191
  34. sonolus/script/containers.py +257 -51
  35. sonolus/script/debug.py +26 -10
  36. sonolus/script/easing.py +365 -0
  37. sonolus/script/effect.py +191 -131
  38. sonolus/script/engine.py +71 -4
  39. sonolus/script/globals.py +303 -269
  40. sonolus/script/instruction.py +205 -151
  41. sonolus/script/internal/__init__.py +5 -5
  42. sonolus/script/internal/builtin_impls.py +255 -144
  43. sonolus/script/{callbacks.py → internal/callbacks.py} +127 -127
  44. sonolus/script/internal/constant.py +139 -0
  45. sonolus/script/internal/context.py +26 -9
  46. sonolus/script/internal/descriptor.py +17 -17
  47. sonolus/script/internal/dict_impl.py +65 -0
  48. sonolus/script/internal/generic.py +6 -9
  49. sonolus/script/internal/impl.py +38 -13
  50. sonolus/script/internal/introspection.py +17 -14
  51. sonolus/script/internal/math_impls.py +121 -0
  52. sonolus/script/internal/native.py +40 -38
  53. sonolus/script/internal/random.py +67 -0
  54. sonolus/script/internal/range.py +81 -0
  55. sonolus/script/internal/transient.py +51 -0
  56. sonolus/script/internal/tuple_impl.py +113 -0
  57. sonolus/script/internal/value.py +3 -3
  58. sonolus/script/interval.py +338 -112
  59. sonolus/script/iterator.py +167 -214
  60. sonolus/script/level.py +24 -0
  61. sonolus/script/num.py +80 -48
  62. sonolus/script/options.py +257 -191
  63. sonolus/script/particle.py +190 -157
  64. sonolus/script/pointer.py +30 -30
  65. sonolus/script/print.py +102 -81
  66. sonolus/script/project.py +8 -0
  67. sonolus/script/quad.py +263 -0
  68. sonolus/script/record.py +47 -16
  69. sonolus/script/runtime.py +52 -1
  70. sonolus/script/sprite.py +418 -333
  71. sonolus/script/text.py +409 -407
  72. sonolus/script/timing.py +114 -42
  73. sonolus/script/transform.py +332 -48
  74. sonolus/script/ui.py +216 -160
  75. sonolus/script/values.py +6 -13
  76. sonolus/script/vec.py +196 -78
  77. {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.5.dist-info}/METADATA +1 -1
  78. sonolus_py-0.1.5.dist-info/RECORD +89 -0
  79. {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.5.dist-info}/WHEEL +1 -1
  80. {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.5.dist-info}/licenses/LICENSE +21 -21
  81. sonolus/backend/allocate.py +0 -51
  82. sonolus/backend/optimize.py +0 -9
  83. sonolus/backend/passes.py +0 -6
  84. sonolus/backend/simplify.py +0 -30
  85. sonolus/script/comptime.py +0 -160
  86. sonolus/script/graphics.py +0 -150
  87. sonolus/script/math.py +0 -92
  88. sonolus/script/range.py +0 -58
  89. sonolus_py-0.1.3.dist-info/RECORD +0 -75
  90. {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.5.dist-info}/entry_points.txt +0 -0
sonolus/script/num.py CHANGED
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
 
4
4
  import operator
5
5
  from collections.abc import Callable, Iterable
6
- from typing import TYPE_CHECKING, Any, Self, TypeIs, final
6
+ from typing import TYPE_CHECKING, Any, Self, TypeIs, final, runtime_checkable
7
7
 
8
8
  from sonolus.backend.ir import IRConst, IRGet, IRPureInstr, IRSet
9
9
  from sonolus.backend.ops import Op
@@ -14,18 +14,18 @@ from sonolus.script.internal.impl import meta_fn
14
14
  from sonolus.script.internal.value import Value
15
15
 
16
16
 
17
- class NumMeta(type):
17
+ class _NumMeta(type):
18
18
  def __instancecheck__(cls, instance):
19
- return isinstance(instance, float | int | bool) or is_num(instance)
19
+ return isinstance(instance, float | int | bool) or _is_num(instance)
20
20
 
21
21
 
22
- def is_num(value: Any) -> TypeIs[Num]:
22
+ def _is_num(value: Any) -> TypeIs[Num]:
23
23
  """Check if a value is a precisely Num instance."""
24
24
  return type.__instancecheck__(Num, value) # type: ignore # noqa: PLC2801
25
25
 
26
26
 
27
27
  @final
28
- class _Num(Value, metaclass=NumMeta):
28
+ class _Num(Value, metaclass=_NumMeta):
29
29
  # This works for ints, floats, and bools
30
30
  # Since we don't support complex numbers, real is equal to the original number
31
31
  __match_args__ = ("real",)
@@ -37,7 +37,7 @@ class _Num(Value, metaclass=NumMeta):
37
37
  raise TypeError("Cannot create a Num from a complex number")
38
38
  if isinstance(data, int):
39
39
  data = float(data)
40
- if is_num(data):
40
+ if _is_num(data):
41
41
  raise InternalError("Cannot create a Num from a Num")
42
42
  self.data = data
43
43
 
@@ -73,7 +73,7 @@ class _Num(Value, metaclass=NumMeta):
73
73
  def _accept_(cls, value: Any) -> Self:
74
74
  if not cls._accepts_(value):
75
75
  raise TypeError(f"Cannot accept {value}")
76
- if is_num(value):
76
+ if _is_num(value):
77
77
  return value
78
78
  return cls(value)
79
79
 
@@ -92,7 +92,7 @@ class _Num(Value, metaclass=NumMeta):
92
92
  value = next(iter(values))
93
93
  return Num(value)
94
94
 
95
- def _to_list_(self) -> list[float | BlockPlace]:
95
+ def _to_list_(self, level_refs: dict[Any, int] | None = None) -> list[float | BlockPlace]:
96
96
  return [self.data]
97
97
 
98
98
  @classmethod
@@ -122,7 +122,10 @@ class _Num(Value, metaclass=NumMeta):
122
122
  raise ValueError("Cannot assign to a number")
123
123
 
124
124
  def _copy_(self) -> Self:
125
- return self
125
+ if ctx():
126
+ return self._get_()
127
+ else:
128
+ return Num(self.data)
126
129
 
127
130
  @classmethod
128
131
  def _alloc_(cls) -> Self:
@@ -168,7 +171,7 @@ class _Num(Value, metaclass=NumMeta):
168
171
  def __eq__(self, other) -> Self:
169
172
  def const_fn(a: Self, b: Self) -> Num | None:
170
173
  if a._is_py_() and b._is_py_():
171
- return Num(a.data == b.data)
174
+ return Num(a._as_py_() == b._as_py_())
172
175
  if a.data == b.data:
173
176
  return Num(True)
174
177
  return None
@@ -184,7 +187,7 @@ class _Num(Value, metaclass=NumMeta):
184
187
  def __ne__(self, other) -> Self:
185
188
  def const_fn(a: Self, b: Self) -> Num | None:
186
189
  if a._is_py_() and b._is_py_():
187
- return Num(a.data != b.data)
190
+ return Num(a._as_py_() != b._as_py_())
188
191
  if a.data == b.data:
189
192
  return Num(False)
190
193
  return None
@@ -195,7 +198,7 @@ class _Num(Value, metaclass=NumMeta):
195
198
  def __lt__(self, other) -> Self:
196
199
  def const_fn(a: Self, b: Self) -> Num | None:
197
200
  if a._is_py_() and b._is_py_():
198
- return Num(a.data < b.data)
201
+ return Num(a._as_py_() < b._as_py_())
199
202
  if a.data == b.data:
200
203
  return Num(False)
201
204
  return None
@@ -206,7 +209,9 @@ class _Num(Value, metaclass=NumMeta):
206
209
  def __le__(self, other) -> Self:
207
210
  def const_fn(a: Self, b: Self) -> Num | None:
208
211
  if a._is_py_() and b._is_py_():
209
- return Num(a.data <= b.data)
212
+ return Num(a._as_py_() <= b._as_py_())
213
+ if a.data == b.data:
214
+ return Num(True)
210
215
  return None
211
216
 
212
217
  return self._bin_op(other, const_fn, Op.LessOr)
@@ -215,7 +220,7 @@ class _Num(Value, metaclass=NumMeta):
215
220
  def __gt__(self, other) -> Self:
216
221
  def const_fn(a: Self, b: Self) -> Num | None:
217
222
  if a._is_py_() and b._is_py_():
218
- return Num(a.data > b.data)
223
+ return Num(a._as_py_() > b._as_py_())
219
224
  if a.data == b.data:
220
225
  return Num(False)
221
226
  return None
@@ -226,7 +231,9 @@ class _Num(Value, metaclass=NumMeta):
226
231
  def __ge__(self, other) -> Self:
227
232
  def const_fn(a: Self, b: Self) -> Num | None:
228
233
  if a._is_py_() and b._is_py_():
229
- return Num(a.data >= b.data)
234
+ return Num(a._as_py_() >= b._as_py_())
235
+ if a.data == b.data:
236
+ return Num(True)
230
237
  return None
231
238
 
232
239
  return self._bin_op(other, const_fn, Op.GreaterOr)
@@ -235,10 +242,10 @@ class _Num(Value, metaclass=NumMeta):
235
242
  def __add__(self, other) -> Self:
236
243
  def const_fn(a: Self, b: Self) -> Num | None:
237
244
  if a._is_py_() and b._is_py_():
238
- return Num(a.data + b.data)
239
- if a._is_py_() and a.data == 0:
245
+ return Num(a._as_py_() + b._as_py_())
246
+ if a._is_py_() and a._as_py_() == 0:
240
247
  return b
241
- if b._is_py_() and b.data == 0:
248
+ if b._is_py_() and b._as_py_() == 0:
242
249
  return a
243
250
  return None
244
251
 
@@ -248,10 +255,10 @@ class _Num(Value, metaclass=NumMeta):
248
255
  def __sub__(self, other) -> Self:
249
256
  def const_fn(a: Self, b: Self) -> Num | None:
250
257
  if a._is_py_() and b._is_py_():
251
- return Num(a.data - b.data)
252
- if a._is_py_() and a.data == 0:
258
+ return Num(a._as_py_() - b._as_py_())
259
+ if a._is_py_() and a._as_py_() == 0:
253
260
  return -b
254
- if b._is_py_() and b.data == 0:
261
+ if b._is_py_() and b._as_py_() == 0:
255
262
  return a
256
263
  return None
257
264
 
@@ -261,16 +268,16 @@ class _Num(Value, metaclass=NumMeta):
261
268
  def __mul__(self, other) -> Self:
262
269
  def const_fn(a: Self, b: Self) -> Num | None:
263
270
  if a._is_py_() and b._is_py_():
264
- return Num(a.data * b.data)
271
+ return Num(a._as_py_() * b._as_py_())
265
272
  if a._is_py_():
266
- if a.data == 0:
273
+ if a._as_py_() == 0:
267
274
  return Num(0)
268
- if a.data == 1:
275
+ if a._as_py_() == 1:
269
276
  return b
270
277
  if b._is_py_():
271
- if b.data == 0:
278
+ if b._as_py_() == 0:
272
279
  return Num(0)
273
- if b.data == 1:
280
+ if b._as_py_() == 1:
274
281
  return a
275
282
  return None
276
283
 
@@ -280,13 +287,13 @@ class _Num(Value, metaclass=NumMeta):
280
287
  def __truediv__(self, other) -> Self:
281
288
  def const_fn(a: Self, b: Self) -> Num | None:
282
289
  if a._is_py_() and b._is_py_():
283
- if b.data == 0:
290
+ if b._as_py_() == 0:
284
291
  return None
285
- return Num(a.data / b.data)
292
+ return Num(a._as_py_() / b._as_py_())
286
293
  if b._is_py_():
287
- if b.data == 1:
294
+ if b._as_py_() == 1:
288
295
  return a
289
- if b.data == -1:
296
+ if b._as_py_() == -1:
290
297
  return -a
291
298
  return None
292
299
 
@@ -296,13 +303,13 @@ class _Num(Value, metaclass=NumMeta):
296
303
  def __floordiv__(self, other) -> Self:
297
304
  def const_fn(a: Self, b: Self) -> Num | None:
298
305
  if a._is_py_() and b._is_py_():
299
- if b.data == 0:
306
+ if b._as_py_() == 0:
300
307
  return None
301
- return Num(a.data // b.data)
308
+ return Num(a._as_py_() // b._as_py_())
302
309
  if b._is_py_():
303
- if b.data == 1:
310
+ if b._as_py_() == 1:
304
311
  return a
305
- if b.data == -1:
312
+ if b._as_py_() == -1:
306
313
  return -a
307
314
  return None
308
315
 
@@ -312,9 +319,9 @@ class _Num(Value, metaclass=NumMeta):
312
319
  def __mod__(self, other) -> Self:
313
320
  def const_fn(a: Self, b: Self) -> Num | None:
314
321
  if a._is_py_() and b._is_py_():
315
- if b.data == 0:
322
+ if b._as_py_() == 0:
316
323
  return None
317
- return Num(a.data % b.data)
324
+ return Num(a._as_py_() % b._as_py_())
318
325
  return None
319
326
 
320
327
  return self._bin_op(other, const_fn, Op.Mod)
@@ -324,13 +331,13 @@ class _Num(Value, metaclass=NumMeta):
324
331
  def const_fn(a: Self, b: Self) -> Num | None:
325
332
  if a._is_py_() and b._is_py_():
326
333
  try:
327
- return Num(a.data**b.data)
334
+ return Num(a._as_py_() ** b._as_py_())
328
335
  except OverflowError:
329
336
  return None
330
337
  if b._is_py_():
331
- if b.data == 0:
338
+ if b._as_py_() == 0:
332
339
  return Num(1)
333
- if b.data == 1:
340
+ if b._as_py_() == 1:
334
341
  return a
335
342
  return None
336
343
 
@@ -360,9 +367,9 @@ class _Num(Value, metaclass=NumMeta):
360
367
  def and_(self, other) -> Self:
361
368
  def const_fn(a: Self, b: Self) -> Num | None:
362
369
  if a._is_py_() and b._is_py_():
363
- return Num(a.data and b.data)
370
+ return Num(a._as_py_() and b._as_py_())
364
371
  if a._is_py_():
365
- if a.data == 0:
372
+ if a._as_py_() == 0:
366
373
  return a
367
374
  else:
368
375
  return b
@@ -373,9 +380,9 @@ class _Num(Value, metaclass=NumMeta):
373
380
  def or_(self, other) -> Self:
374
381
  def const_fn(a: Self, b: Self) -> Num | None:
375
382
  if a._is_py_() and b._is_py_():
376
- return Num(a.data or b.data)
383
+ return Num(a._as_py_() or b._as_py_())
377
384
  if a._is_py_():
378
- if a.data == 0:
385
+ if a._as_py_() == 0:
379
386
  return b
380
387
  else:
381
388
  return a
@@ -396,11 +403,36 @@ class _Num(Value, metaclass=NumMeta):
396
403
 
397
404
 
398
405
  if TYPE_CHECKING:
399
-
400
- class __Num(float, int, bool, _Num): # type: ignore
401
- pass
402
-
403
- Num = __Num | _Num | float | int | bool
406
+ from typing import Protocol
407
+
408
+ @runtime_checkable
409
+ class Num[T](Protocol, int, bool, float):
410
+ def __add__(self, other: T, /) -> Num: ...
411
+ def __sub__(self, other: T, /) -> Num: ...
412
+ def __mul__(self, other: T, /) -> Num: ...
413
+ def __truediv__(self, other: T, /) -> Num: ...
414
+ def __floordiv__(self, other: T, /) -> Num: ...
415
+ def __mod__(self, other: T, /) -> Num: ...
416
+ def __pow__(self, other: T, /) -> Num: ...
417
+
418
+ def __neg__(self, /) -> Num: ...
419
+ def __pos__(self, /) -> Num: ...
420
+ def __abs__(self, /) -> Num: ...
421
+
422
+ def __eq__(self, other: Any, /) -> bool: ...
423
+ def __ne__(self, other: Any, /) -> bool: ...
424
+ def __lt__(self, other: T, /) -> bool: ...
425
+ def __le__(self, other: T, /) -> bool: ...
426
+ def __gt__(self, other: T, /) -> bool: ...
427
+ def __ge__(self, other: T, /) -> bool: ...
428
+
429
+ def __hash__(self, /) -> int: ...
430
+
431
+ @property
432
+ def real(self) -> Num: ...
433
+
434
+ @property
435
+ def imag(self) -> Num: ...
404
436
  else:
405
437
  # Need to do this to satisfy type checkers (especially Pycharm)
406
438
  _Num.__name__ = "Num"