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

@@ -65,7 +65,15 @@ def cfg_to_engine_node(entry: BasicBlock):
65
65
  statements.append(FunctionNode(Op.SwitchWithDefault, args))
66
66
  block_statements.append(FunctionNode(Op.Execute, statements))
67
67
  block_statements.append(ConstantNode(value=0))
68
- return FunctionNode(Op.Block, [FunctionNode(Op.JumpLoop, block_statements)])
68
+ result = FunctionNode(Op.Block, [FunctionNode(Op.JumpLoop, block_statements)])
69
+ for block in block_indexes:
70
+ # Clean up without relying on gc
71
+ del block.incoming
72
+ del block.outgoing
73
+ del block.phis
74
+ del block.statements
75
+ del block.test
76
+ return result
69
77
 
70
78
 
71
79
  def ir_to_engine_node(stmt) -> EngineNode:
@@ -24,15 +24,18 @@ class LivenessAnalysis(CompilerPass):
24
24
  block.live_phi_targets = set()
25
25
  block.array_defs_in = set()
26
26
  block.array_defs_out = None
27
+ last_live_set = set()
27
28
  for statement in block.statements:
28
- statement.live = set()
29
+ if isinstance(statement, IRSet):
30
+ last_live_set = set()
31
+ statement.live = last_live_set
29
32
  statement.visited = False
30
33
  statement.uses = self.get_uses(statement, set())
31
34
  statement.defs = self.get_defs(statement)
32
35
  statement.is_array_init = False # True if this may be the first assignment to an array
33
36
  statement.array_defs = self.get_array_defs(statement)
34
37
  if not isinstance(block.test, IRConst):
35
- block.test.live = set()
38
+ block.test.live = last_live_set
36
39
  block.test.uses = self.get_uses(block.test, set())
37
40
  self.preprocess_arrays(entry)
38
41
 
@@ -319,7 +319,6 @@ class Visitor(ast.NodeVisitor):
319
319
  with using_ctx(before_ctx):
320
320
  state_var._set_(0)
321
321
  with using_ctx(return_ctx):
322
- state_var._set_(len(self.return_ctxs) + 1)
323
322
  is_present_var._set_(0)
324
323
  del before_ctx.outgoing[None] # Unlink the state machine body from the call site
325
324
  entry = before_ctx.new_empty_disconnected()
@@ -1007,7 +1006,9 @@ class Visitor(ast.NodeVisitor):
1007
1006
  return validate_value({self.visit(k): self.visit(v) for k, v in zip(node.keys, node.values, strict=True)})
1008
1007
 
1009
1008
  def visit_Set(self, node):
1010
- raise NotImplementedError("Set literals are not supported")
1009
+ from sonolus.script.containers import FrozenNumSet
1010
+
1011
+ return self.handle_call(node, FrozenNumSet.of, *(self.visit(elt) for elt in node.elts))
1011
1012
 
1012
1013
  def visit_ListComp(self, node):
1013
1014
  raise NotImplementedError("List comprehensions are not supported")
sonolus/build/cli.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import argparse
2
+ import gc
2
3
  import importlib
3
4
  import json
4
5
  import shutil
@@ -164,6 +165,10 @@ def main():
164
165
  help="Runtime error checking mode (default: none for build, notify for dev)",
165
166
  )
166
167
 
168
+ gc_group = parser.add_mutually_exclusive_group()
169
+ gc_group.add_argument("--no-gc", action="store_true", default=True, help="Disable garbage collection (default)")
170
+ gc_group.add_argument("--gc", action="store_true", help="Enable garbage collection")
171
+
167
172
  build_components = parser.add_argument_group("build components")
168
173
  build_components.add_argument("--play", action="store_true", help="Build play component")
169
174
  build_components.add_argument("--watch", action="store_true", help="Build watch component")
@@ -219,6 +224,12 @@ def main():
219
224
  else:
220
225
  parser.error("Module argument is required when multiple or no modules are found")
221
226
 
227
+ if args.command in {"build", "check", "dev"}:
228
+ if hasattr(args, "gc") and args.gc:
229
+ gc.enable()
230
+ elif hasattr(args, "no_gc") and args.no_gc:
231
+ gc.disable()
232
+
222
233
  if no_gil():
223
234
  print("Multithreading is enabled")
224
235
  if hasattr(sys, "_jit") and sys._jit.is_enabled():
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import argparse
4
4
  import contextlib
5
+ import gc
5
6
  import http.server
6
7
  import importlib
7
8
  import queue
@@ -331,6 +332,7 @@ def run_server(
331
332
  cmd = command_queue.get()
332
333
  try:
333
334
  cmd.execute(server_state)
335
+ gc.collect()
334
336
  except Exception:
335
337
  print(f"{traceback.format_exc()}\n")
336
338
  prompt_event.set()
@@ -581,7 +581,6 @@ class _BaseArchetype:
581
581
  def _init_fields(cls):
582
582
  if cls._field_init_done:
583
583
  return
584
- cls._field_init_done = True
585
584
  for mro_entry in cls.mro()[1:]:
586
585
  if hasattr(mro_entry, "_field_init_done"):
587
586
  mro_entry._init_fields()
@@ -706,6 +705,7 @@ class _BaseArchetype:
706
705
  [inspect.Parameter(name, inspect.Parameter.POSITIONAL_OR_KEYWORD) for name in cls._memory_fields_]
707
706
  )
708
707
  cls._post_init_fields()
708
+ cls._field_init_done = True
709
709
 
710
710
  @property
711
711
  @abstractmethod
sonolus/script/bucket.py CHANGED
@@ -75,7 +75,7 @@ class JudgmentWindow(Record):
75
75
  @perf_meta_fn
76
76
  def __mul__(self, other: float | int) -> JudgmentWindow:
77
77
  """Multiply the intervals by a scalar."""
78
- return JudgmentWindow._quick_construct(
78
+ return JudgmentWindow._unchecked(
79
79
  perfect=self.perfect * other,
80
80
  great=self.great * other,
81
81
  good=self.good * other,
@@ -84,7 +84,7 @@ class JudgmentWindow(Record):
84
84
  @perf_meta_fn
85
85
  def __add__(self, other: float | int) -> JudgmentWindow:
86
86
  """Add a scalar to the intervals."""
87
- return JudgmentWindow._quick_construct(
87
+ return JudgmentWindow._unchecked(
88
88
  perfect=self.perfect + other,
89
89
  great=self.great + other,
90
90
  good=self.good + other,
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  from collections.abc import Callable
4
4
  from typing import Any, Protocol, Self
5
5
 
6
+ from sonolus.backend.visitor import compile_and_call
6
7
  from sonolus.script.archetype import AnyArchetype, EntityRef
7
8
  from sonolus.script.array import Array
8
9
  from sonolus.script.array_like import ArrayLike, get_positive_index
@@ -441,6 +442,55 @@ class ArraySet[T, Capacity](Record):
441
442
  self._values.clear()
442
443
 
443
444
 
445
+ class FrozenNumSet[Size](Record):
446
+ _values: Array[Num, Size]
447
+
448
+ @classmethod
449
+ @meta_fn
450
+ def of(cls, *values: Num) -> Self:
451
+ if ctx():
452
+ try:
453
+ num_values = [Num._accept_(v) for v in values]
454
+ except TypeError:
455
+ raise TypeError("Only sets of numeric values are supported") from None
456
+ if all(v._is_py_() for v in num_values):
457
+ const_values = [v._as_py_() for v in num_values]
458
+ arr = Array[Num, len(const_values)]._with_value([Num(v) for v in sorted(const_values)])
459
+ return cls(arr)
460
+ else:
461
+ arr = Array[Num, len(values)](*values)
462
+ compile_and_call(arr.sort)
463
+ else:
464
+ arr = Array[Num, len(values)](*sorted(values))
465
+ return cls(arr)
466
+
467
+ def __len__(self) -> int:
468
+ return len(self._values)
469
+
470
+ def __contains__(self, value: Num) -> bool:
471
+ if len(self) < 15:
472
+ for i in range(len(self)): # noqa: SIM110
473
+ if self._values.get_unchecked(i) == value:
474
+ return True
475
+ return False
476
+ else:
477
+ left = 0
478
+ right = len(self) - 1
479
+ while left <= right:
480
+ mid = (left + right) // 2
481
+ mid_value = self._values.get_unchecked(mid)
482
+ if mid_value == value:
483
+ return True
484
+ elif mid_value < value:
485
+ left = mid + 1
486
+ else:
487
+ right = mid - 1
488
+ return False
489
+
490
+ def __iter__(self) -> SonolusIterator[Num]:
491
+ return self._values.__iter__()
492
+
493
+
444
494
  class _ArrayMapEntry[K, V](Record):
445
495
  key: K
446
496
  value: V
sonolus/script/debug.py CHANGED
@@ -143,8 +143,9 @@ def assert_true(value: int | float | bool, message: str | None = None):
143
143
  require(value, message)
144
144
 
145
145
 
146
+ @meta_fn
146
147
  def assert_false(value: int | float | bool, message: str | None = None):
147
- assert_true(not value, message)
148
+ assert_true(value == 0, message)
148
149
 
149
150
 
150
151
  def static_assert(value: int | float | bool, message: str | None = None):
@@ -551,7 +551,11 @@ def context_to_cfg(context: Context) -> BasicBlock:
551
551
  edge = FlowEdge(src=blocks[current], dst=blocks[target], cond=condition)
552
552
  blocks[current].outgoing.add(edge)
553
553
  blocks[target].incoming.add(edge)
554
- return blocks[context]
554
+ result = blocks[context]
555
+ for current in tuple(iter_contexts(context)):
556
+ # Break cycles so memory can be cleaned without gc
557
+ del current.outgoing
558
+ return result
555
559
 
556
560
 
557
561
  def unique[T](iterable: Iterable[T]) -> list[T]:
@@ -77,6 +77,10 @@ def try_validate_value(value: Any) -> Value | None:
77
77
  return TupleImpl._accept_(value)
78
78
  case dict():
79
79
  return DictImpl._accept_(value)
80
+ case set() | frozenset():
81
+ from sonolus.script.containers import FrozenNumSet
82
+
83
+ return FrozenNumSet.of(*value)
80
84
  case (
81
85
  PartialGeneric()
82
86
  | TypeVar()
@@ -90,11 +94,7 @@ def try_validate_value(value: Any) -> Value | None:
90
94
  | super()
91
95
  ):
92
96
  return BasicConstantValue.of(value)
93
- case special_form if value in {
94
- Literal,
95
- Annotated,
96
- Union,
97
- }:
97
+ case special_form if value == Literal or value == Annotated or value == Union: # noqa: PLR1714, SIM109
98
98
  return TypingSpecialFormConstant.of(special_form)
99
99
  case other_type if get_origin(value) in {Literal, Annotated, UnionType, tuple, type}:
100
100
  return BasicConstantValue.of(other_type)
@@ -91,6 +91,12 @@ class TupleImpl(TransientValue):
91
91
  other = TupleImpl._accept_(other)
92
92
  return TupleImpl._accept_(self.value + other.value)
93
93
 
94
+ def __contains__(self, item):
95
+ for element in self.value: # noqa: SIM110
96
+ if element == item:
97
+ return True
98
+ return False
99
+
94
100
  @staticmethod
95
101
  @meta_fn
96
102
  def _is_tuple_impl(value: Any) -> bool:
@@ -78,7 +78,7 @@ class Interval(Record):
78
78
  Returns:
79
79
  A new interval with the value added to both ends.
80
80
  """
81
- return Interval._quick_construct(start=self.start + other, end=self.end + other)
81
+ return Interval._unchecked(start=self.start + other, end=self.end + other)
82
82
 
83
83
  @perf_meta_fn
84
84
  def __sub__(self, other: float | int) -> Interval:
@@ -90,7 +90,7 @@ class Interval(Record):
90
90
  Returns:
91
91
  A new interval with the value subtracted from both ends.
92
92
  """
93
- return Interval._quick_construct(start=self.start - other, end=self.end - other)
93
+ return Interval._unchecked(start=self.start - other, end=self.end - other)
94
94
 
95
95
  @perf_meta_fn
96
96
  def __mul__(self, other: float | int) -> Interval:
@@ -102,7 +102,7 @@ class Interval(Record):
102
102
  Returns:
103
103
  A new interval with both ends multiplied by the value.
104
104
  """
105
- return Interval._quick_construct(start=self.start * other, end=self.end * other)
105
+ return Interval._unchecked(start=self.start * other, end=self.end * other)
106
106
 
107
107
  @perf_meta_fn
108
108
  def __truediv__(self, other: float | int) -> Interval:
@@ -114,7 +114,7 @@ class Interval(Record):
114
114
  Returns:
115
115
  A new interval with both ends divided by the value.
116
116
  """
117
- return Interval._quick_construct(start=self.start / other, end=self.end / other)
117
+ return Interval._unchecked(start=self.start / other, end=self.end / other)
118
118
 
119
119
  @perf_meta_fn
120
120
  def __floordiv__(self, other: float | int) -> Interval:
@@ -126,7 +126,7 @@ class Interval(Record):
126
126
  Returns:
127
127
  A new interval with both ends divided by the value and floored.
128
128
  """
129
- return Interval._quick_construct(start=self.start // other, end=self.end // other)
129
+ return Interval._unchecked(start=self.start // other, end=self.end // other)
130
130
 
131
131
  def __and__(self, other: Interval) -> Interval:
132
132
  """Get the intersection of two intervals.
sonolus/script/record.py CHANGED
@@ -172,7 +172,8 @@ class Record(GenericValue, metaclass=RecordMeta):
172
172
  return result
173
173
 
174
174
  @classmethod
175
- def _quick_construct(cls, **kwargs) -> Self:
175
+ def _unchecked(cls, **kwargs) -> Self:
176
+ # Skips most validation, generally for internal use in frequently-called methods for performance reasons
176
177
  result = object.__new__(cls)
177
178
  for k, v in kwargs.items():
178
179
  if isinstance(v, int | float):
sonolus/script/runtime.py CHANGED
@@ -1157,7 +1157,7 @@ def canvas() -> _PreviewRuntimeCanvas:
1157
1157
  @perf_meta_fn
1158
1158
  def screen() -> Rect:
1159
1159
  """Get the screen boundaries as a rectangle."""
1160
- return Rect._quick_construct(t=1, r=aspect_ratio(), b=-1, l=-aspect_ratio())
1160
+ return Rect._unchecked(t=1, r=aspect_ratio(), b=-1, l=-aspect_ratio())
1161
1161
 
1162
1162
 
1163
1163
  def level_score() -> _LevelScore:
@@ -326,15 +326,16 @@ class Transform2d(Record):
326
326
  A new normalized transform.
327
327
  """
328
328
  assert self.a22 != 0, "Cannot normalize transform with a22 == 0"
329
+ a22 = self.a22 + (self.a22 == 0)
329
330
  return Transform2d(
330
- self.a00 / self.a22,
331
- self.a01 / self.a22,
332
- self.a02 / self.a22,
333
- self.a10 / self.a22,
334
- self.a11 / self.a22,
335
- self.a12 / self.a22,
336
- self.a20 / self.a22,
337
- self.a21 / self.a22,
331
+ self.a00 / a22,
332
+ self.a01 / a22,
333
+ self.a02 / a22,
334
+ self.a10 / a22,
335
+ self.a11 / a22,
336
+ self.a12 / a22,
337
+ self.a20 / a22,
338
+ self.a21 / a22,
338
339
  1,
339
340
  )
340
341
 
sonolus/script/vec.py CHANGED
@@ -4,7 +4,7 @@ from math import pi
4
4
 
5
5
  from sonolus.script.array import Array
6
6
  from sonolus.script.array_like import ArrayLike
7
- from sonolus.script.debug import assert_true
7
+ from sonolus.script.debug import assert_false
8
8
  from sonolus.script.internal.impl import perf_meta_fn
9
9
  from sonolus.script.internal.math_impls import _atan2, _cos, _sin
10
10
  from sonolus.script.num import Num
@@ -135,7 +135,7 @@ class Vec2(Record):
135
135
  Returns:
136
136
  A new vector rotated by the given angle.
137
137
  """
138
- return Vec2._quick_construct(
138
+ return Vec2._unchecked(
139
139
  x=self.x * cos(angle) - self.y * sin(angle),
140
140
  y=self.x * sin(angle) + self.y * cos(angle),
141
141
  )
@@ -157,12 +157,25 @@ class Vec2(Record):
157
157
  def normalize(self) -> Vec2:
158
158
  """Normalize the vector (set the magnitude to 1) and return a new vector.
159
159
 
160
+ If the vector is a zero vector, an assertion error is raised if runtime checks are enabled.
161
+
160
162
  Returns:
161
163
  A new vector with magnitude 1.
162
164
  """
163
- magnitude = (self.x**2 + self.y**2) ** 0.5
164
- assert_true(magnitude != 0, "Cannot normalize a zero vector")
165
- return Vec2._quick_construct(x=self.x / magnitude, y=self.y / magnitude)
165
+ assert_false((self.x == 0) * (self.y == 0), "Cannot normalize a zero vector")
166
+ return self.normalize_or_zero()
167
+
168
+ @perf_meta_fn
169
+ def normalize_or_zero(self) -> Vec2:
170
+ """Normalize the vector (set the magnitude to 1) and return a new vector.
171
+
172
+ If the vector is a zero vector, return a zero vector.
173
+
174
+ Returns:
175
+ A new vector with magnitude 1, or a zero vector if the original vector is zero.
176
+ """
177
+ magnitude = (self.x**2 + self.y**2) ** 0.5 + (self.x == 0) * (self.y == 0) # prevent division by zero
178
+ return Vec2._unchecked(x=self.x / magnitude, y=self.y / magnitude)
166
179
 
167
180
  @perf_meta_fn
168
181
  def orthogonal(self) -> Vec2:
@@ -173,7 +186,7 @@ class Vec2(Record):
173
186
  Returns:
174
187
  A new vector orthogonal to this vector.
175
188
  """
176
- return Vec2._quick_construct(x=-self.y, y=self.x)
189
+ return Vec2._unchecked(x=-self.y, y=self.x)
177
190
 
178
191
  @property
179
192
  def tuple(self) -> tuple[float, float]:
@@ -194,7 +207,7 @@ class Vec2(Record):
194
207
  Returns:
195
208
  A new vector resulting from the addition.
196
209
  """
197
- return Vec2._quick_construct(x=self.x + other.x, y=self.y + other.y)
210
+ return Vec2._unchecked(x=self.x + other.x, y=self.y + other.y)
198
211
 
199
212
  @perf_meta_fn
200
213
  def __sub__(self, other: Vec2) -> Vec2:
@@ -206,7 +219,7 @@ class Vec2(Record):
206
219
  Returns:
207
220
  A new vector resulting from the subtraction.
208
221
  """
209
- return Vec2._quick_construct(x=self.x - other.x, y=self.y - other.y)
222
+ return Vec2._unchecked(x=self.x - other.x, y=self.y - other.y)
210
223
 
211
224
  @perf_meta_fn
212
225
  def __mul__(self, other: Vec2 | float) -> Vec2:
@@ -220,9 +233,9 @@ class Vec2(Record):
220
233
  """
221
234
  match other:
222
235
  case Vec2(x, y):
223
- return Vec2._quick_construct(x=self.x * x, y=self.y * y)
236
+ return Vec2._unchecked(x=self.x * x, y=self.y * y)
224
237
  case Num(factor):
225
- return Vec2._quick_construct(x=self.x * factor, y=self.y * factor)
238
+ return Vec2._unchecked(x=self.x * factor, y=self.y * factor)
226
239
  case _:
227
240
  return NotImplemented
228
241
 
@@ -230,7 +243,7 @@ class Vec2(Record):
230
243
  def __rmul__(self, other):
231
244
  match other:
232
245
  case Num(factor):
233
- return Vec2._quick_construct(x=self.x * factor, y=self.y * factor)
246
+ return Vec2._unchecked(x=self.x * factor, y=self.y * factor)
234
247
  case _:
235
248
  return NotImplemented
236
249
 
@@ -246,9 +259,9 @@ class Vec2(Record):
246
259
  """
247
260
  match other:
248
261
  case Vec2(x, y):
249
- return Vec2._quick_construct(x=self.x / x, y=self.y / y)
262
+ return Vec2._unchecked(x=self.x / x, y=self.y / y)
250
263
  case Num(factor):
251
- return Vec2._quick_construct(x=self.x / factor, y=self.y / factor)
264
+ return Vec2._unchecked(x=self.x / factor, y=self.y / factor)
252
265
  case _:
253
266
  return NotImplemented
254
267
 
@@ -259,7 +272,7 @@ class Vec2(Record):
259
272
  Returns:
260
273
  A new vector with inverted direction.
261
274
  """
262
- return Vec2._quick_construct(x=-self.x, y=-self.y)
275
+ return Vec2._unchecked(x=-self.x, y=-self.y)
263
276
 
264
277
 
265
278
  def pnpoly(vertices: ArrayLike[Vec2] | tuple[Vec2, ...], test: Vec2) -> bool:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sonolus.py
3
- Version: 0.10.8
3
+ Version: 0.11.0
4
4
  Summary: Sonolus engine development in Python
5
5
  Project-URL: Documentation, https://sonolus.py.qwewqa.xyz/
6
6
  Project-URL: Repository, https://github.com/qwewqa/sonolus.py
@@ -3,7 +3,7 @@ sonolus/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  sonolus/backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  sonolus/backend/blocks.py,sha256=3peyb9eYBy0s53xNVJ1KmK4IgoyVkkwG-lqDQ_VZTHc,18531
5
5
  sonolus/backend/excepthook.py,sha256=ezsTi8hPXSUhqZ7-H0rmkWcndBQcZFAShF543zzaEPM,1912
6
- sonolus/backend/finalize.py,sha256=ivl32G7rDSVZl2EEI1HvOHpLdhhOh-ZjavwBZgPe9uA,5286
6
+ sonolus/backend/finalize.py,sha256=kytaqAVyoryWJTyJEbvIGysfxmt_DeCic2oxmrqAPYI,5508
7
7
  sonolus/backend/interpret.py,sha256=B0jqlLmEGoyO2mxpcvwRwV17Tq_gOE9wLNt26Q5QOfs,14306
8
8
  sonolus/backend/ir.py,sha256=eyNXorOQY4zgKOvN4kO1MdJF3sU8H0Qw5RTPqbEjJHY,3854
9
9
  sonolus/backend/mode.py,sha256=NkcPZJm8dn83LX35uP24MtQOCnfRDFZ280dHeEEfauE,613
@@ -11,7 +11,7 @@ sonolus/backend/node.py,sha256=eEzPP14jzWJp2xrZCAaPlNtokxdoqg0bSM7xQiwx1j8,1254
11
11
  sonolus/backend/ops.py,sha256=5weB_vIxbkwCSJuzYZyKUk7vVXsSIEDJYRlvE-2ke8A,10572
12
12
  sonolus/backend/place.py,sha256=7qwV732hZ4WP-9GNN8FQSEKssPJZELip1wLXTWfop7Y,4717
13
13
  sonolus/backend/utils.py,sha256=OwD1EPh8j-hsfkLzeKNzPQojT_3kklpJou0WTJNoCbc,2337
14
- sonolus/backend/visitor.py,sha256=PxxIvhP3AzGS3hZMulaF5CO2aswiBMyZc_Hwo040hTk,64421
14
+ sonolus/backend/visitor.py,sha256=lEq_lkCh74_mK_saE4JeRI9_mM8MMeWRzw4mqJ0Et7c,64450
15
15
  sonolus/backend/optimize/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  sonolus/backend/optimize/allocate.py,sha256=CuumoMphkpQlGRNeKLHT4FBGE0XVj5pwhfNdrqiLFSs,7535
17
17
  sonolus/backend/optimize/constant_evaluation.py,sha256=_u_VfLmd4Rlq9aKyRSeKb47352CXuf8uNgNhNTK1qe0,21510
@@ -20,33 +20,33 @@ sonolus/backend/optimize/dead_code.py,sha256=ZRJ95zJ49R-wZTzJtcSSbl5LYKHWI-byHM3
20
20
  sonolus/backend/optimize/dominance.py,sha256=3jAgXqXTbuYLpXvIm8UB06NkIOLtaoVp7pBVPcLb5vY,3259
21
21
  sonolus/backend/optimize/flow.py,sha256=xUoBpWIYi-NjqXahA6obAZaPvLj_HaDNNv7cO13e2ps,7192
22
22
  sonolus/backend/optimize/inlining.py,sha256=BEXjPbJMGTJbgA4ydC38TbEuYEFqb6oxDS0roZTmuds,10417
23
- sonolus/backend/optimize/liveness.py,sha256=KYQlXdKuwnRvY9JeAjwm1bzPbFwshcUxtYs7ycMRS-M,7279
23
+ sonolus/backend/optimize/liveness.py,sha256=cj0oUrqItVjj58ZQq86nRBO5k0fuTxbmWkvrSv3H-pY,7420
24
24
  sonolus/backend/optimize/optimize.py,sha256=2gW0n1AIlwgVjY6teQlt9YP-GsFUxU-mr1ZqAZamnUo,1672
25
25
  sonolus/backend/optimize/passes.py,sha256=YyFKy6qCwcR_Ua2_SXpcBODfvBbm_ygVYcqloOlfDZI,1911
26
26
  sonolus/backend/optimize/simplify.py,sha256=wvhixe0SfditrGMh0nX0Wt0JR00JqAmz4BKBzMoBAVI,14701
27
27
  sonolus/backend/optimize/ssa.py,sha256=raQO0furQQRPYb8iIBKfNrJlj-_5wqtI4EWNfLZ8QFo,10834
28
28
  sonolus/build/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
- sonolus/build/cli.py,sha256=t6oK0SGU6fkxXVbGu6OuRIHDKD6u4SqXAShdPtatZ-8,10060
29
+ sonolus/build/cli.py,sha256=uLY7JG3PTAb2a1bbjulFlgUGDzsHXyRAfkGV0lbuMgQ,10538
30
30
  sonolus/build/collection.py,sha256=6hniAzriPWBKUeGDkXabNXpbdHiHnqiK9shs6U1OExM,12748
31
31
  sonolus/build/compile.py,sha256=KOmncDKmGfgzC_FWB_LTxAl0s9w4wnaDe-luACMlCVs,8397
32
- sonolus/build/dev_server.py,sha256=xe6C2_dpODk51inL02F3xFMjDueCSay7-XzkR56lapY,10560
32
+ sonolus/build/dev_server.py,sha256=u-p3wVdIPNTHjFLNZzPdW4JlFmeVbqqEle_O3otUhyw,10607
33
33
  sonolus/build/engine.py,sha256=jMymxbBXu-ekv71uU8TF2KbFaHs3yGjyJAztd1SoRDs,14808
34
34
  sonolus/build/level.py,sha256=KLqUAtxIuIqrzeFURJA97rdqjA5pcvYSmwNZQhElaMQ,702
35
35
  sonolus/build/node.py,sha256=gnX71RYDUOK_gYMpinQi-bLWO4csqcfiG5gFmhxzSec,1330
36
36
  sonolus/build/project.py,sha256=Uuz82QtTNFdklrVJ_i7EPp8hSjyOxLU1xAeOloa6G00,8579
37
37
  sonolus/script/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
- sonolus/script/archetype.py,sha256=ck_LR8z0ipVq3T9b735VwvQI2mxVUyjHylr4BFagXT8,49631
38
+ sonolus/script/archetype.py,sha256=J_0E6a183Spez8NTd_jyH0kjIO81Q1a3i6GrNzjyWuw,49631
39
39
  sonolus/script/array.py,sha256=EbrNwl_WuJ0JjjkX0s_VJNXWqvYdm_ljTbyrDEMLGUY,13348
40
40
  sonolus/script/array_like.py,sha256=E6S4TW2muXgcyVkhUASQVt7JSYUkpvdJPgHz6YiSHNo,14708
41
- sonolus/script/bucket.py,sha256=yIod3DgX7Hv7RLe-4Cn81FcydvbkbdMt26FzpRj7oUI,7794
42
- sonolus/script/containers.py,sha256=SnLXflwlX47EMQmTWnSzm9NYCi-as8lWnKzgCIK0PmM,26940
43
- sonolus/script/debug.py,sha256=yYg6EZt3NUOUeph1pu_5cA_2lxs8SZ91v76eOC1Sw-8,7747
41
+ sonolus/script/bucket.py,sha256=LNePLmCwgXfKLmH4Z7ZcTFKWR32eq4AnnagI7jacrsU,7782
42
+ sonolus/script/containers.py,sha256=iZWPVvVr24iHBb8umuYV0LrCkr9Xgj1piWaat_he7-w,28643
43
+ sonolus/script/debug.py,sha256=21_bvhP2cZ4kwS3Spxp8tP6ojIfmthQxlq4gtqrt0lo,7757
44
44
  sonolus/script/easing.py,sha256=2FUJI_nfp990P_armCcRqHm2329O985glJAhSC6tnxs,11379
45
45
  sonolus/script/effect.py,sha256=SfJxSNF3RlPCRXnkt62ZlWhCXw3mmmRCsoMsvTErUP0,7960
46
46
  sonolus/script/engine.py,sha256=etI9dJsQ7V9YZICVNZg54WqpLijPxG8eTPHiV-_EiG8,10687
47
47
  sonolus/script/globals.py,sha256=nlXSNS4NRXsgQU2AJImVIs752h1WqsMnShSKgU011c4,10270
48
48
  sonolus/script/instruction.py,sha256=Dd-14D5Amo8nhPBr6DNyg2lpYw_rqZkT8Kix3HkfE7k,6793
49
- sonolus/script/interval.py,sha256=vnwm3CiB0rurRolA53wRzb_jTPguvOKnie4glE1MwsE,11986
49
+ sonolus/script/interval.py,sha256=-1pnvRmkeBFL4qUvAKzza6h29Hce2oD2GNSUKhoP4QQ,11956
50
50
  sonolus/script/iterator.py,sha256=_ICY_yX7FG0Zbgs3NhVnaIBdVDpAeXjxJ_CQtq30l7Y,3774
51
51
  sonolus/script/level.py,sha256=X3-V99ihruYYCcPdch66dHi_ydCWXXn7epviLLjxW8w,8288
52
52
  sonolus/script/maybe.py,sha256=VYvTWgEfPzoXqI3i3zXhc4dz0pWBVoHmW8FtWH0GQvM,8194
@@ -58,26 +58,26 @@ sonolus/script/pointer.py,sha256=FoOfyD93r0G5d_2BaKfeOT9SqkOP3hq6sqtOs_Rb0c8,151
58
58
  sonolus/script/printing.py,sha256=mNYu9QWiacBBGZrnePZQMVwbbguoelUps9GiOK_aVRU,2096
59
59
  sonolus/script/project.py,sha256=YouKKm6Z9PpwbO9aSA2syZqFv_j1DShVGlENUT565Js,4831
60
60
  sonolus/script/quad.py,sha256=8lZ_5-eWeqePldNGBkNZTuOgS_IRb41URgGwSW4h2T0,14445
61
- sonolus/script/record.py,sha256=BrQ8k-O4WX9FT_EfoRmNnKC1BZM9gWydZ4R4swh3chc,13051
62
- sonolus/script/runtime.py,sha256=TjxcfIIPRH6oxlEjWfLHDj1oo7fPfwTBdwETfnhN7h4,33331
61
+ sonolus/script/record.py,sha256=dyIETowUBqqiM1hyCCAIo4riR9U7ol3vIATjoMCbiJc,13158
62
+ sonolus/script/runtime.py,sha256=IFNHmExpavyXy5Y_X1pfvulsM-VzdcI9domvuj9sunM,33325
63
63
  sonolus/script/sprite.py,sha256=KhQNnq0wKm1tDMQTrlZIr0mL0jPCfojTORzsCK5qO1o,18448
64
64
  sonolus/script/stream.py,sha256=Yot99RLKqJN1XK3x5s_qeV-50qEtuG2U6zbEPWLyvW8,24879
65
65
  sonolus/script/text.py,sha256=wxujIgKYcCfl2AD2_Im8g3vh0lDEHYwTSRZg9wsBPEU,13402
66
66
  sonolus/script/timing.py,sha256=DklMvuxcFg3MzXsecUo6Yhdk7pScOJ7STwXvAiTvLKM,3067
67
- sonolus/script/transform.py,sha256=4aS7-NNzX0v9KMXZ4gIGOaU1Cd-ok7DO_OvIBca0mGU,21418
67
+ sonolus/script/transform.py,sha256=CnSQWTZxHve5CklH6VGM9CB9fJibdh0FNgJdDCsMABk,21419
68
68
  sonolus/script/ui.py,sha256=DYPGWIjHj1IFPxW1zaEuIUQx0b32FJPXtiwCvrtJ6oo,7528
69
69
  sonolus/script/values.py,sha256=6iJG6h4IDlbcK8FH4GENSHOQc7C_7fCGa34wM80qToA,1629
70
- sonolus/script/vec.py,sha256=LueAHrx5pKouHvLaO1nMbl5Plh3UgPn8J7UdJPHWFCM,8840
70
+ sonolus/script/vec.py,sha256=f7keqogIQiRpuQ0dULOFCxFlmvkykoFZMFwYw9P39Kk,9319
71
71
  sonolus/script/internal/__init__.py,sha256=T6rzLoiOUaiSQtaHMZ88SNO-ijSjSSv33TKtUwu-Ms8,136
72
72
  sonolus/script/internal/builtin_impls.py,sha256=1fo6UuWlaLoqpVwFSrFS5BabNeRCdS2T2mjsS4BPYcY,13603
73
73
  sonolus/script/internal/callbacks.py,sha256=vWzJG8uiJoEtsNnbeZPqOHogCwoLpz2D1MnHY2wVV8s,2801
74
74
  sonolus/script/internal/constant.py,sha256=3ycbGkDJVUwcrCZ96vLjAoAARgsvaqDM8rJ_YCrLrvo,4289
75
- sonolus/script/internal/context.py,sha256=56pPjiPy8ZaxY3t5iEufsOMEj6BSy31G-5SoYqS6tPo,19694
75
+ sonolus/script/internal/context.py,sha256=fRvdxkx7EILU54-ogR1HSjLOZnH2PVw2gQri9m86K5Y,19852
76
76
  sonolus/script/internal/descriptor.py,sha256=XRFey-EjiAm_--KsNl-8N0Mi_iyQwlPh68gDp0pKf3E,392
77
77
  sonolus/script/internal/dict_impl.py,sha256=alu_wKGSk1kZajNf64qbe7t71shEzD4N5xNIATH8Swo,1885
78
78
  sonolus/script/internal/error.py,sha256=ZNnsvQVQAnFKzcvsm6-sste2lo-tP5pPI8sD7XlAZWc,490
79
79
  sonolus/script/internal/generic.py,sha256=_3d5Rn_tn214-77fPE67vdbdqt1PQF8-2WB_XDu5YRg,7551
80
- sonolus/script/internal/impl.py,sha256=U9D8A207yBbA-R9Qa9xE9zK4f0uDvGbHuFhwaIO81Ew,3364
80
+ sonolus/script/internal/impl.py,sha256=R88cl4nLcfF0UhA9qdYRBOsl4nMx8ucgz8l7_oRY-l8,3503
81
81
  sonolus/script/internal/introspection.py,sha256=guL9_NR2D3OJAnNpeFdyYkO_vVXk-3KQr2-y4YielM0,1133
82
82
  sonolus/script/internal/math_impls.py,sha256=ox2pBJ6ELRO0LdLn_RZxgHHs_PCgQOHIhmDkwmLxJaU,2975
83
83
  sonolus/script/internal/native.py,sha256=zOuRtgI3XJ_ExyR_ZkvbDABVc_JIWaKl62lFEL_bMaw,2007
@@ -85,10 +85,10 @@ sonolus/script/internal/random.py,sha256=6Ku5edRcDUh7rtqEEYCJz0BQavw69RALsVHS25z
85
85
  sonolus/script/internal/range.py,sha256=j94uV1NTZoCdZ8mOw3v51vD8L7h8l5vZpOAp6breD9I,3521
86
86
  sonolus/script/internal/simulation_context.py,sha256=LGxLTvxbqBIhoe1R-SfwGajNIDwIJMVsHle0kvzd500,4818
87
87
  sonolus/script/internal/transient.py,sha256=y2AWABqF1aoaP6H4_2u4MMpNioC4OsZQCtPyNI0txqo,1634
88
- sonolus/script/internal/tuple_impl.py,sha256=DPNdmmRmupU8Ah4_XKq6-PdT336l4nt15_uCJKQGkkk,3587
88
+ sonolus/script/internal/tuple_impl.py,sha256=WaI5HSF5h03ddXiSHEwzY9ttfsPUItaf86Y5VbZypek,3754
89
89
  sonolus/script/internal/value.py,sha256=OngrCdmY_h6mV2Zgwqhuo4eYFad0kTk6263UAxctZcY,6963
90
- sonolus_py-0.10.8.dist-info/METADATA,sha256=sM3mLK9SKsaOsHkqvVFnWo3JOad7I6M39PWOhOW5QO8,554
91
- sonolus_py-0.10.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
92
- sonolus_py-0.10.8.dist-info/entry_points.txt,sha256=oTYspY_b7SA8TptEMTDxh4-Aj-ZVPnYC9f1lqH6s9G4,54
93
- sonolus_py-0.10.8.dist-info/licenses/LICENSE,sha256=JEKpqVhQYfEc7zg3Mj462sKbKYmO1K7WmvX1qvg9IJk,1067
94
- sonolus_py-0.10.8.dist-info/RECORD,,
90
+ sonolus_py-0.11.0.dist-info/METADATA,sha256=hhf11U7J2Zk1rkB-vixzUjS94Ygoh2R1DZ2jmdhnbC4,554
91
+ sonolus_py-0.11.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
92
+ sonolus_py-0.11.0.dist-info/entry_points.txt,sha256=oTYspY_b7SA8TptEMTDxh4-Aj-ZVPnYC9f1lqH6s9G4,54
93
+ sonolus_py-0.11.0.dist-info/licenses/LICENSE,sha256=JEKpqVhQYfEc7zg3Mj462sKbKYmO1K7WmvX1qvg9IJk,1067
94
+ sonolus_py-0.11.0.dist-info/RECORD,,