sonolus.py 0.10.9__py3-none-any.whl → 0.11.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.
@@ -1,7 +1,7 @@
1
1
  from math import isfinite, isinf, isnan
2
2
 
3
3
  from sonolus.backend.ir import IRConst, IRGet, IRInstr, IRPureInstr, IRSet
4
- from sonolus.backend.node import ConstantNode, EngineNode, FunctionNode
4
+ from sonolus.backend.node import EngineNode, FunctionNode
5
5
  from sonolus.backend.ops import Op
6
6
  from sonolus.backend.optimize.flow import BasicBlock, traverse_cfg_reverse_postorder
7
7
  from sonolus.backend.place import BlockPlace
@@ -18,18 +18,18 @@ def cfg_to_engine_node(entry: BasicBlock):
18
18
  }
19
19
  match outgoing:
20
20
  case {**other} if not other:
21
- statements.append(ConstantNode(value=len(block_indexes)))
21
+ statements.append(len(block_indexes))
22
22
  case {None: target, **other} if not other:
23
- statements.append(ConstantNode(value=block_indexes[target]))
23
+ statements.append(block_indexes[target])
24
24
  case {0: f_branch, None: t_branch, **other} if not other:
25
25
  statements.append(
26
26
  FunctionNode(
27
27
  func=Op.If,
28
- args=[
28
+ args=(
29
29
  ir_to_engine_node(block.test),
30
- ConstantNode(value=block_indexes[t_branch]),
31
- ConstantNode(value=block_indexes[f_branch]),
32
- ],
30
+ block_indexes[t_branch],
31
+ block_indexes[f_branch],
32
+ ),
33
33
  )
34
34
  )
35
35
  case {None: default_branch, **other} if len(other) == 1:
@@ -37,11 +37,11 @@ def cfg_to_engine_node(entry: BasicBlock):
37
37
  statements.append(
38
38
  FunctionNode(
39
39
  func=Op.If,
40
- args=[
40
+ args=(
41
41
  ir_to_engine_node(IRPureInstr(Op.Equal, args=[block.test, IRConst(cond)])),
42
- ConstantNode(value=block_indexes[cond_branch]),
43
- ConstantNode(value=block_indexes[default_branch]),
44
- ],
42
+ block_indexes[cond_branch],
43
+ block_indexes[default_branch],
44
+ ),
45
45
  )
46
46
  )
47
47
  case dict() as targets:
@@ -49,23 +49,31 @@ def cfg_to_engine_node(entry: BasicBlock):
49
49
  default = len(block_indexes)
50
50
  conds = [cond for cond in targets if cond is not None]
51
51
  if min(conds) == 0 and max(conds) == len(conds) - 1 and all(int(cond) == cond for cond in conds):
52
- args.extend(ConstantNode(value=block_indexes[targets[cond]]) for cond in range(len(conds)))
52
+ args.extend(block_indexes[targets[cond]] for cond in range(len(conds)))
53
53
  if None in targets:
54
54
  default = block_indexes[targets[None]]
55
- args.append(ConstantNode(value=default))
56
- statements.append(FunctionNode(Op.SwitchIntegerWithDefault, args))
55
+ args.append(default)
56
+ statements.append(FunctionNode(Op.SwitchIntegerWithDefault, tuple(args)))
57
57
  else:
58
58
  for cond, target in targets.items():
59
59
  if cond is None:
60
60
  default = block_indexes[target]
61
61
  continue
62
- args.append(ConstantNode(value=cond))
63
- args.append(ConstantNode(value=block_indexes[target]))
64
- args.append(ConstantNode(value=default))
65
- statements.append(FunctionNode(Op.SwitchWithDefault, args))
66
- block_statements.append(FunctionNode(Op.Execute, statements))
67
- block_statements.append(ConstantNode(value=0))
68
- return FunctionNode(Op.Block, [FunctionNode(Op.JumpLoop, block_statements)])
62
+ args.append(cond)
63
+ args.append(block_indexes[target])
64
+ args.append(default)
65
+ statements.append(FunctionNode(Op.SwitchWithDefault, tuple(args)))
66
+ block_statements.append(FunctionNode(Op.Execute, tuple(statements)))
67
+ block_statements.append(0)
68
+ result = FunctionNode(Op.Block, (FunctionNode(Op.JumpLoop, tuple(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:
@@ -73,32 +81,30 @@ def ir_to_engine_node(stmt) -> EngineNode:
73
81
  case int(value) | float(value) | IRConst(value=int(value) | float(value)):
74
82
  value = float(value)
75
83
  if value.is_integer():
76
- return ConstantNode(value=int(value))
84
+ return int(value)
77
85
  elif isfinite(value):
78
- return ConstantNode(value=value)
86
+ return value
79
87
  elif isinf(value):
80
88
  # Read values from ROM
81
- return FunctionNode(Op.Get, args=[ConstantNode(value=3000), ConstantNode(value=1 if value > 0 else 2)])
89
+ return FunctionNode(Op.Get, args=(3000, 1 if value > 0 else 2))
82
90
  elif isnan(value):
83
91
  # Read value from ROM
84
- return FunctionNode(Op.Get, args=[ConstantNode(value=3000), ConstantNode(value=0)])
92
+ return FunctionNode(Op.Get, args=(3000, 0))
85
93
  else:
86
94
  raise ValueError(f"Invalid constant value: {value}")
87
95
  case IRPureInstr(op=op, args=args) | IRInstr(op=op, args=args):
88
- return FunctionNode(func=op, args=[ir_to_engine_node(arg) for arg in args])
96
+ return FunctionNode(func=op, args=tuple(ir_to_engine_node(arg) for arg in args))
89
97
  case IRGet(place=place):
90
98
  return ir_to_engine_node(place)
91
99
  case BlockPlace() as place:
92
100
  if place.offset == 0:
93
101
  index = ir_to_engine_node(place.index)
94
102
  elif place.index == 0:
95
- index = ConstantNode(value=place.offset)
103
+ index = place.offset
96
104
  else:
97
- index = FunctionNode(
98
- func=Op.Add, args=[ir_to_engine_node(place.index), ConstantNode(value=place.offset)]
99
- )
100
- return FunctionNode(func=Op.Get, args=[ir_to_engine_node(place.block), index])
105
+ index = FunctionNode(func=Op.Add, args=(ir_to_engine_node(place.index), place.offset))
106
+ return FunctionNode(func=Op.Get, args=(ir_to_engine_node(place.block), index))
101
107
  case IRSet(place=place, value=value):
102
- return FunctionNode(func=Op.Set, args=[*ir_to_engine_node(place).args, ir_to_engine_node(value)])
108
+ return FunctionNode(func=Op.Set, args=(*ir_to_engine_node(place).args, ir_to_engine_node(value)))
103
109
  case _:
104
110
  raise TypeError(f"Unsupported IR statement: {stmt}")
@@ -2,7 +2,7 @@ import math
2
2
  import operator
3
3
  import random
4
4
 
5
- from sonolus.backend.node import ConstantNode, EngineNode
5
+ from sonolus.backend.node import EngineNode, FunctionNode
6
6
  from sonolus.backend.ops import Op
7
7
 
8
8
 
@@ -24,8 +24,8 @@ class Interpreter:
24
24
  self.log = []
25
25
 
26
26
  def run(self, node: EngineNode) -> float:
27
- if isinstance(node, ConstantNode):
28
- return node.value
27
+ if not isinstance(node, FunctionNode):
28
+ return node
29
29
  func = node.func
30
30
  args = node.args
31
31
  match func:
sonolus/backend/node.py CHANGED
@@ -1,40 +1,18 @@
1
1
  import textwrap
2
- from dataclasses import dataclass, field
2
+ from typing import NamedTuple
3
3
 
4
4
  from sonolus.backend.ops import Op
5
5
 
6
- type EngineNode = ConstantNode | FunctionNode
6
+ type EngineNode = int | float | FunctionNode
7
7
 
8
8
 
9
- @dataclass(slots=True)
10
- class ConstantNode:
11
- value: float
12
- _hash: int = field(init=False, repr=False)
13
-
14
- def __post_init__(self):
15
- self._hash = hash(self.value)
16
-
17
- def __hash__(self):
18
- return hash(self.value)
19
-
20
-
21
- @dataclass(slots=True)
22
- class FunctionNode:
9
+ class FunctionNode(NamedTuple):
23
10
  func: Op
24
- args: list[EngineNode]
25
- _hash: int = field(init=False, repr=False)
26
-
27
- def __post_init__(self):
28
- self._hash = hash((self.func, tuple(self.args)))
29
-
30
- def __hash__(self):
31
- return self._hash
11
+ args: tuple[EngineNode, ...]
32
12
 
33
13
 
34
14
  def format_engine_node(node: EngineNode) -> str:
35
- if isinstance(node, ConstantNode):
36
- return str(node.value)
37
- elif isinstance(node, FunctionNode):
15
+ if isinstance(node, FunctionNode):
38
16
  match len(node.args):
39
17
  case 0:
40
18
  return f"{node.func.name}()"
@@ -45,4 +23,4 @@ def format_engine_node(node: EngineNode) -> str:
45
23
  textwrap.indent('\n'.join(format_engine_node(arg) for arg in node.args), ' ')
46
24
  }\n)"
47
25
  else:
48
- raise ValueError(f"Invalid engine node: {node}")
26
+ return str(node)
@@ -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
 
@@ -1006,7 +1006,9 @@ class Visitor(ast.NodeVisitor):
1006
1006
  return validate_value({self.visit(k): self.visit(v) for k, v in zip(node.keys, node.values, strict=True)})
1007
1007
 
1008
1008
  def visit_Set(self, node):
1009
- 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))
1010
1012
 
1011
1013
  def visit_ListComp(self, node):
1012
1014
  raise NotImplementedError("List comprehensions are not supported")
sonolus/build/compile.py CHANGED
@@ -32,9 +32,11 @@ class CompileCache:
32
32
  self._cache = {}
33
33
  self._lock = Lock()
34
34
  self._event = Event()
35
+ self._accessed_hashes = set()
35
36
 
36
37
  def get(self, entry_hash: int) -> EngineNode | None:
37
38
  with self._lock:
39
+ self._accessed_hashes.add(entry_hash)
38
40
  if entry_hash not in self._cache:
39
41
  self._cache[entry_hash] = None # Mark as being compiled
40
42
  return None
@@ -47,10 +49,21 @@ class CompileCache:
47
49
 
48
50
  def set(self, entry_hash: int, node: EngineNode) -> None:
49
51
  with self._lock:
52
+ self._accessed_hashes.add(entry_hash)
50
53
  self._cache[entry_hash] = node
51
54
  self._event.set()
52
55
  self._event.clear()
53
56
 
57
+ def reset_accessed(self) -> None:
58
+ with self._lock:
59
+ self._accessed_hashes.clear()
60
+
61
+ def prune_unaccessed(self) -> None:
62
+ with self._lock:
63
+ unaccessed_hashes = set(self._cache.keys()) - self._accessed_hashes
64
+ for h in unaccessed_hashes:
65
+ del self._cache[h]
66
+
54
67
 
55
68
  def compile_mode(
56
69
  mode: Mode,
@@ -119,6 +119,7 @@ class RebuildCommand:
119
119
  print("Rebuilding...")
120
120
  try:
121
121
  start_time = perf_counter()
122
+ server_state.cache.reset_accessed()
122
123
  server_state.project_state = ProjectContextState.from_build_config(server_state.config)
123
124
  server_state.project = project_module.project
124
125
  build_collection(
@@ -128,6 +129,7 @@ class RebuildCommand:
128
129
  cache=server_state.cache,
129
130
  project_state=server_state.project_state,
130
131
  )
132
+ server_state.cache.prune_unaccessed()
131
133
  end_time = perf_counter()
132
134
  print(f"Rebuild completed in {end_time - start_time:.2f} seconds")
133
135
  except CompilationError:
sonolus/build/node.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from threading import Lock
2
2
  from typing import TypedDict
3
3
 
4
- from sonolus.backend.node import ConstantNode, EngineNode, FunctionNode
4
+ from sonolus.backend.node import EngineNode, FunctionNode
5
5
 
6
6
 
7
7
  class ValueOutputNode(TypedDict):
@@ -32,19 +32,17 @@ class OutputNodeGenerator:
32
32
  return self.indexes[node]
33
33
 
34
34
  match node:
35
- case ConstantNode(value):
36
- index = len(self.nodes)
37
- self.nodes.append({"value": value})
38
- self.indexes[node] = index
39
- return index
40
35
  case FunctionNode(func, args):
41
36
  arg_indexes = [self._add(arg) for arg in args]
42
37
  index = len(self.nodes)
43
38
  self.nodes.append({"func": func.value, "args": arg_indexes})
44
39
  self.indexes[node] = index
45
40
  return index
46
- case _:
47
- raise ValueError("Invalid node")
41
+ case constant:
42
+ index = len(self.nodes)
43
+ self.nodes.append({"value": constant})
44
+ self.indexes[node] = index
45
+ return index
48
46
 
49
47
  def get(self):
50
48
  return self.nodes
@@ -12,6 +12,7 @@ from sonolus.backend.ir import IRConst, IRExpr, IRInstr, IRPureInstr, IRStmt
12
12
  from sonolus.backend.mode import Mode
13
13
  from sonolus.backend.ops import Op
14
14
  from sonolus.script.bucket import Bucket, Judgment
15
+ from sonolus.script.debug import static_error
15
16
  from sonolus.script.internal.callbacks import PLAY_CALLBACKS, PREVIEW_CALLBACKS, WATCH_ARCHETYPE_CALLBACKS, CallbackInfo
16
17
  from sonolus.script.internal.context import ctx
17
18
  from sonolus.script.internal.descriptor import SonolusDescriptor
@@ -581,7 +582,6 @@ class _BaseArchetype:
581
582
  def _init_fields(cls):
582
583
  if cls._field_init_done:
583
584
  return
584
- cls._field_init_done = True
585
585
  for mro_entry in cls.mro()[1:]:
586
586
  if hasattr(mro_entry, "_field_init_done"):
587
587
  mro_entry._init_fields()
@@ -706,6 +706,7 @@ class _BaseArchetype:
706
706
  [inspect.Parameter(name, inspect.Parameter.POSITIONAL_OR_KEYWORD) for name in cls._memory_fields_]
707
707
  )
708
708
  cls._post_init_fields()
709
+ cls._field_init_done = True
709
710
 
710
711
  @property
711
712
  @abstractmethod
@@ -1210,6 +1211,8 @@ class EntityRef[A: _BaseArchetype](Record):
1210
1211
 
1211
1212
  Usage:
1212
1213
  ```python
1214
+ ref = EntityRef[MyArchetype](index=123)
1215
+
1213
1216
  class MyArchetype(PlayArchetype):
1214
1217
  ref_1: EntityRef[OtherArchetype] = imported()
1215
1218
  ref_2: EntityRef[Any] = imported()
@@ -1238,6 +1241,12 @@ class EntityRef[A: _BaseArchetype](Record):
1238
1241
  return hash(id(self._ref_))
1239
1242
  return super().__hash__()
1240
1243
 
1244
+ @meta_fn
1245
+ def __bool__(self):
1246
+ if ctx():
1247
+ static_error("EntityRef cannot be used in a boolean context. Check index directly instead.")
1248
+ return True
1249
+
1241
1250
  @meta_fn
1242
1251
  def get(self) -> A:
1243
1252
  """Get the entity."""
@@ -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,56 @@ 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) < 8:
472
+ return value in self._as_tuple()
473
+ else:
474
+ left = 0
475
+ right = len(self) - 1
476
+ while left <= right:
477
+ mid = (left + right) // 2
478
+ mid_value = self._values.get_unchecked(mid)
479
+ if mid_value == value:
480
+ return True
481
+ elif mid_value < value:
482
+ left = mid + 1
483
+ else:
484
+ right = mid - 1
485
+ return False
486
+
487
+ def __iter__(self) -> SonolusIterator[Num]:
488
+ return self._values.__iter__()
489
+
490
+ @meta_fn
491
+ def _as_tuple(self) -> tuple[Num, ...]:
492
+ return tuple(self._values.get_unchecked(i) for i in range(Num._accept_(len(self))._as_py_()))
493
+
494
+
444
495
  class _ArrayMapEntry[K, V](Record):
445
496
  key: K
446
497
  value: V
@@ -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:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sonolus.py
3
- Version: 0.10.9
3
+ Version: 0.11.1
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,15 +3,15 @@ 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
7
- sonolus/backend/interpret.py,sha256=B0jqlLmEGoyO2mxpcvwRwV17Tq_gOE9wLNt26Q5QOfs,14306
6
+ sonolus/backend/finalize.py,sha256=MRp_ATPreSmBGn8N6iwesS50rFWH9FIiQI6_Ea8RVTM,5090
7
+ sonolus/backend/interpret.py,sha256=dnm0SJFfI4KIE6Ca2tKrLq10XwBC9EPSqN7OOYtA8Ws,14304
8
8
  sonolus/backend/ir.py,sha256=eyNXorOQY4zgKOvN4kO1MdJF3sU8H0Qw5RTPqbEjJHY,3854
9
9
  sonolus/backend/mode.py,sha256=NkcPZJm8dn83LX35uP24MtQOCnfRDFZ280dHeEEfauE,613
10
- sonolus/backend/node.py,sha256=eEzPP14jzWJp2xrZCAaPlNtokxdoqg0bSM7xQiwx1j8,1254
10
+ sonolus/backend/node.py,sha256=w5y2GwSc2E9rQvGJNaMzvPW_FYjjfHw4QDUmKs1dAnc,714
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=UuyOqHlX-On_gHlJTJAYoXFRk63JuAnheLcavVzXQZw,64362
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,7 +20,7 @@ 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
@@ -28,18 +28,18 @@ sonolus/backend/optimize/ssa.py,sha256=raQO0furQQRPYb8iIBKfNrJlj-_5wqtI4EWNfLZ8Q
28
28
  sonolus/build/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
29
  sonolus/build/cli.py,sha256=uLY7JG3PTAb2a1bbjulFlgUGDzsHXyRAfkGV0lbuMgQ,10538
30
30
  sonolus/build/collection.py,sha256=6hniAzriPWBKUeGDkXabNXpbdHiHnqiK9shs6U1OExM,12748
31
- sonolus/build/compile.py,sha256=KOmncDKmGfgzC_FWB_LTxAl0s9w4wnaDe-luACMlCVs,8397
32
- sonolus/build/dev_server.py,sha256=u-p3wVdIPNTHjFLNZzPdW4JlFmeVbqqEle_O3otUhyw,10607
31
+ sonolus/build/compile.py,sha256=YKqldBTWAXz5kzsS9Qmwy3FdrFloYZWvapR5QWsx2G0,8862
32
+ sonolus/build/dev_server.py,sha256=yHD3KGqzebdqcEBOC5JDlNptzlH8Sq4i-DNnh_zXWCA,10705
33
33
  sonolus/build/engine.py,sha256=jMymxbBXu-ekv71uU8TF2KbFaHs3yGjyJAztd1SoRDs,14808
34
34
  sonolus/build/level.py,sha256=KLqUAtxIuIqrzeFURJA97rdqjA5pcvYSmwNZQhElaMQ,702
35
- sonolus/build/node.py,sha256=gnX71RYDUOK_gYMpinQi-bLWO4csqcfiG5gFmhxzSec,1330
35
+ sonolus/build/node.py,sha256=Dhuz_-UlRd-EJC7-AP1NuyvrjHWNo7jGssniRh4dZhI,1239
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=TZ9Semvzh6zHtUyJGN7ZrLYkux4zgqxFhrh-dGiaLEo,49907
39
39
  sonolus/script/array.py,sha256=EbrNwl_WuJ0JjjkX0s_VJNXWqvYdm_ljTbyrDEMLGUY,13348
40
40
  sonolus/script/array_like.py,sha256=E6S4TW2muXgcyVkhUASQVt7JSYUkpvdJPgHz6YiSHNo,14708
41
41
  sonolus/script/bucket.py,sha256=LNePLmCwgXfKLmH4Z7ZcTFKWR32eq4AnnagI7jacrsU,7782
42
- sonolus/script/containers.py,sha256=SnLXflwlX47EMQmTWnSzm9NYCi-as8lWnKzgCIK0PmM,26940
42
+ sonolus/script/containers.py,sha256=KKySXTh_ON9hut1ScMS31ewRNnVd4t7OwpIZg2bPhno,28676
43
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
@@ -72,12 +72,12 @@ sonolus/script/internal/__init__.py,sha256=T6rzLoiOUaiSQtaHMZ88SNO-ijSjSSv33TKtU
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.9.dist-info/METADATA,sha256=iSSv7Kjw-_TmCXbf8qFfFtO3zd8nqyTsQ7YpxgHVoqc,554
91
- sonolus_py-0.10.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
92
- sonolus_py-0.10.9.dist-info/entry_points.txt,sha256=oTYspY_b7SA8TptEMTDxh4-Aj-ZVPnYC9f1lqH6s9G4,54
93
- sonolus_py-0.10.9.dist-info/licenses/LICENSE,sha256=JEKpqVhQYfEc7zg3Mj462sKbKYmO1K7WmvX1qvg9IJk,1067
94
- sonolus_py-0.10.9.dist-info/RECORD,,
90
+ sonolus_py-0.11.1.dist-info/METADATA,sha256=RUqohCNBMfRgWQrbN51EW2yocoNb136sH8eRKCr_T_o,554
91
+ sonolus_py-0.11.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
92
+ sonolus_py-0.11.1.dist-info/entry_points.txt,sha256=oTYspY_b7SA8TptEMTDxh4-Aj-ZVPnYC9f1lqH6s9G4,54
93
+ sonolus_py-0.11.1.dist-info/licenses/LICENSE,sha256=JEKpqVhQYfEc7zg3Mj462sKbKYmO1K7WmvX1qvg9IJk,1067
94
+ sonolus_py-0.11.1.dist-info/RECORD,,