sonolus.py 0.1.8__py3-none-any.whl → 0.1.9__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.

@@ -42,6 +42,7 @@ def cfg_to_engine_node(entry: BasicBlock):
42
42
  for cond, target in targets.items():
43
43
  if cond is None:
44
44
  default = block_indexes[target]
45
+ continue
45
46
  args.append(ConstantNode(value=cond))
46
47
  args.append(ConstantNode(value=block_indexes[target]))
47
48
  args.append(ConstantNode(value=default))
@@ -55,7 +56,7 @@ def ir_to_engine_node(stmt) -> EngineNode:
55
56
  match stmt:
56
57
  case int() | float():
57
58
  return ConstantNode(value=float(stmt))
58
- case IRConst(value=value):
59
+ case IRConst(value=int(value) | float(value)):
59
60
  return ConstantNode(value=value)
60
61
  case IRPureInstr(op=op, args=args) | IRInstr(op=op, args=args):
61
62
  return FunctionNode(func=op, args=[ir_to_engine_node(arg) for arg in args])
@@ -39,20 +39,29 @@ class CopyCoalesce(CompilerPass):
39
39
  interference = self.get_interference(entry)
40
40
  copies = self.get_copies(entry)
41
41
 
42
- mapping = {}
42
+ mapping: dict[TempBlock, set[TempBlock]] = {}
43
43
 
44
44
  for target, sources in copies.items():
45
45
  for source in sources:
46
- if source in mapping:
47
- continue
48
46
  if source in interference.get(target, set()):
49
47
  continue
50
- mapping[source] = mapping.get(target, target)
48
+ combined_mapping = mapping.get(target, {target}) | mapping.get(source, {source})
51
49
  combined_interference = interference.get(target, set()) | interference.get(source, set())
52
- interference[source] = combined_interference
53
- interference[target] = combined_interference
50
+ for place in combined_mapping:
51
+ mapping[place] = combined_mapping
52
+ interference[place] = combined_interference
53
+ for place in combined_interference:
54
+ interference[place].update(combined_mapping)
55
+
56
+ canonical_mapping = {}
57
+ for place, group in mapping.items():
58
+ if place in canonical_mapping:
59
+ continue
60
+ canonical = min(group)
61
+ for member in group:
62
+ canonical_mapping[member] = canonical
54
63
 
55
- return mapping
64
+ return canonical_mapping
56
65
 
57
66
  def get_interference(self, entry: BasicBlock) -> dict[TempBlock, set[TempBlock]]:
58
67
  result = {}
@@ -335,6 +335,8 @@ class Visitor(ast.NodeVisitor):
335
335
  has_next = self.ensure_boolean_num(self.handle_call(node, iterator.has_next))
336
336
  if has_next._is_py_() and not has_next._as_py_():
337
337
  # The loop will never run, continue after evaluating the condition
338
+ self.loop_head_ctxs.pop()
339
+ self.break_ctxs.pop()
338
340
  for stmt in node.orelse:
339
341
  self.visit(stmt)
340
342
  return
@@ -348,13 +350,14 @@ class Visitor(ast.NodeVisitor):
348
350
  self.visit(stmt)
349
351
  ctx().branch_to_loop_header(header_ctx)
350
352
 
353
+ self.loop_head_ctxs.pop()
354
+ break_ctxs = self.break_ctxs.pop()
355
+
351
356
  set_ctx(else_ctx)
352
357
  for stmt in node.orelse:
353
358
  self.visit(stmt)
354
359
  else_end_ctx = ctx()
355
360
 
356
- self.loop_head_ctxs.pop()
357
- break_ctxs = self.break_ctxs.pop()
358
361
  after_ctx = Context.meet([else_end_ctx, *break_ctxs])
359
362
  set_ctx(after_ctx)
360
363
 
@@ -365,11 +368,30 @@ class Visitor(ast.NodeVisitor):
365
368
  self.break_ctxs.append([])
366
369
  set_ctx(header_ctx)
367
370
  test = self.ensure_boolean_num(self.visit(node.test))
368
- if test._is_py_() and not test._as_py_():
369
- # The loop will never run, continue after evaluating the condition
370
- for stmt in node.orelse:
371
- self.visit(stmt)
372
- return
371
+ if test._is_py_():
372
+ if test._as_py_():
373
+ # The loop will run until a break / return
374
+ body_ctx = ctx().branch(None)
375
+ set_ctx(body_ctx)
376
+ for stmt in node.body:
377
+ self.visit(stmt)
378
+ ctx().branch_to_loop_header(header_ctx)
379
+
380
+ self.loop_head_ctxs.pop()
381
+ break_ctxs = self.break_ctxs.pop()
382
+
383
+ # Skip the else block
384
+
385
+ after_ctx = Context.meet([ctx().into_dead(), *break_ctxs])
386
+ set_ctx(after_ctx)
387
+ return
388
+ else:
389
+ # The loop will never run, continue after evaluating the condition
390
+ self.loop_head_ctxs.pop()
391
+ self.break_ctxs.pop()
392
+ for stmt in node.orelse:
393
+ self.visit(stmt)
394
+ return
373
395
  ctx().test = test.ir()
374
396
  body_ctx = ctx().branch(None)
375
397
  else_ctx = ctx().branch(0)
@@ -379,13 +401,14 @@ class Visitor(ast.NodeVisitor):
379
401
  self.visit(stmt)
380
402
  ctx().branch_to_loop_header(header_ctx)
381
403
 
404
+ self.loop_head_ctxs.pop()
405
+ break_ctxs = self.break_ctxs.pop()
406
+
382
407
  set_ctx(else_ctx)
383
408
  for stmt in node.orelse:
384
409
  self.visit(stmt)
385
410
  else_end_ctx = ctx()
386
411
 
387
- self.loop_head_ctxs.pop()
388
- break_ctxs = self.break_ctxs.pop()
389
412
  after_ctx = Context.meet([else_end_ctx, *break_ctxs])
390
413
  set_ctx(after_ctx)
391
414
 
sonolus/build/compile.py CHANGED
@@ -36,15 +36,14 @@ def compile_mode(
36
36
  if archetypes is not None:
37
37
  archetype_entries = []
38
38
  for archetype in archetypes:
39
+ archetype._init_fields()
39
40
  archetype_data = {
40
41
  "name": archetype.name,
41
42
  "hasInput": archetype.is_scored,
42
43
  "imports": [{"name": name, "index": index} for name, index in archetype._imported_keys_.items()],
43
44
  }
44
45
  if mode == Mode.PLAY:
45
- archetype_data["exports"] = [
46
- {"name": name, "index": index} for name, index in archetype._exported_keys_.items()
47
- ]
46
+ archetype_data["exports"] = [*archetype._exported_keys_]
48
47
  for cb_name, cb_info in archetype._supported_callbacks_.items():
49
48
  cb = getattr(archetype, cb_name)
50
49
  if cb in archetype._default_callbacks_:
sonolus/build/level.py CHANGED
@@ -11,11 +11,12 @@ def package_level_data(
11
11
  def build_level_data(
12
12
  level_data: LevelData,
13
13
  ):
14
- level_refs = {entity: i for i, entity in enumerate(level_data.entities)}
14
+ level_refs = {entity: f"{i}_{entity.name}" for i, entity in enumerate(level_data.entities)}
15
15
  return {
16
16
  "bgmOffset": level_data.bgm_offset,
17
17
  "entities": [
18
18
  {
19
+ "name": level_refs[entity],
19
20
  "archetype": entity.name,
20
21
  "data": entity._level_data_entries(level_refs),
21
22
  }
@@ -62,7 +62,9 @@ class _ArchetypeField(SonolusDescriptor):
62
62
  result = _deref(ctx().blocks.EntityData, self.offset, self.type)
63
63
  case _ArchetypeReferenceData(index=index):
64
64
  result = _deref(
65
- ctx().blocks.EntityDataArray, self.offset + index * _ENTITY_DATA_SIZE, self.type
65
+ ctx().blocks.EntityDataArray,
66
+ Num._accept_(self.offset) + index * _ENTITY_DATA_SIZE,
67
+ self.type,
66
68
  )
67
69
  case _ArchetypeLevelData(values=values):
68
70
  result = values[self.name]
@@ -108,7 +110,9 @@ class _ArchetypeField(SonolusDescriptor):
108
110
  target = _deref(ctx().blocks.EntityData, self.offset, self.type)
109
111
  case _ArchetypeReferenceData(index=index):
110
112
  target = _deref(
111
- ctx().blocks.EntityDataArray, self.offset + index * _ENTITY_DATA_SIZE, self.type
113
+ ctx().blocks.EntityDataArray,
114
+ Num._accept_(self.offset) + index * _ENTITY_DATA_SIZE,
115
+ self.type,
112
116
  )
113
117
  case _ArchetypeLevelData(values=values):
114
118
  target = values[self.name]
@@ -119,7 +123,7 @@ class _ArchetypeField(SonolusDescriptor):
119
123
  raise TypeError(f"Expected {self.type}, got {type(value)}")
120
124
  for k, v in value._to_flat_dict_(self.data_name).items():
121
125
  index = instance._exported_keys_[k]
122
- ctx().add_statements(IRInstr(Op.ExportValue, [IRConst(index), Num._accept_(v).ir()]))
126
+ ctx().add_statements(IRInstr(Op.ExportValue, [IRConst(index), Num(v).ir()]))
123
127
  return
124
128
  case _ArchetypeReferenceData():
125
129
  raise RuntimeError("Exported fields of other entities are not accessible")
@@ -342,6 +346,7 @@ class _BaseArchetype:
342
346
  is_scored: ClassVar[bool] = False
343
347
 
344
348
  def __init__(self, *args, **kwargs):
349
+ self._init_fields()
345
350
  if ctx():
346
351
  raise RuntimeError("The Archetype constructor is only for defining level data")
347
352
  bound = self._data_constructor_signature_.bind_partial(*args, **kwargs)
@@ -354,10 +359,12 @@ class _BaseArchetype:
354
359
 
355
360
  @classmethod
356
361
  def _new(cls):
362
+ cls._init_fields()
357
363
  return object.__new__(cls)
358
364
 
359
365
  @classmethod
360
366
  def _for_compilation(cls):
367
+ cls._init_fields()
361
368
  result = cls._new()
362
369
  result._data_ = _ArchetypeSelfData()
363
370
  return result
@@ -369,6 +376,13 @@ class _BaseArchetype:
369
376
  result._data_ = _ArchetypeReferenceData(index=Num._accept_(index))
370
377
  return result
371
378
 
379
+ @classmethod
380
+ @meta_fn
381
+ def is_at(cls, index: Num) -> bool:
382
+ if not ctx():
383
+ raise RuntimeError("is_at is only available during compilation")
384
+ return entity_info_at(index).archetype_id == cls.id()
385
+
372
386
  @classmethod
373
387
  @meta_fn
374
388
  def id(cls):
@@ -396,6 +410,7 @@ class _BaseArchetype:
396
410
  Args:
397
411
  **kwargs: Entity memory values to inject by field name as defined in the Archetype.
398
412
  """
413
+ cls._init_fields()
399
414
  if not ctx():
400
415
  raise RuntimeError("Spawn is only allowed within a callback")
401
416
  archetype_id = cls.id()
@@ -408,16 +423,21 @@ class _BaseArchetype:
408
423
 
409
424
  @classmethod
410
425
  def schema(cls) -> ArchetypeSchema:
426
+ cls._init_fields()
411
427
  return {"name": cls.name or "unnamed", "fields": list(cls._imported_fields_)}
412
428
 
413
- def _level_data_entries(self, level_refs: dict[Any, int] | None = None):
429
+ def _level_data_entries(self, level_refs: dict[Any, str] | None = None):
430
+ self._init_fields()
414
431
  if not isinstance(self._data_, _ArchetypeLevelData):
415
432
  raise RuntimeError("Entity is not level data")
416
433
  entries = []
417
434
  for name, value in self._data_.values.items():
418
435
  field_info = self._imported_fields_.get(name)
419
436
  for k, v in value._to_flat_dict_(field_info.data_name, level_refs).items():
420
- entries.append({"name": k, "value": v})
437
+ if isinstance(v, str):
438
+ entries.append({"name": k, "ref": v})
439
+ else:
440
+ entries.append({"name": k, "value": v})
421
441
  return entries
422
442
 
423
443
  def __init_subclass__(cls, **kwargs):
@@ -430,7 +450,22 @@ class _BaseArchetype:
430
450
  raise TypeError("Cannot subclass Archetypes")
431
451
  if cls.name is None:
432
452
  cls.name = cls.__name__
433
- field_specifiers = get_field_specifiers(cls, skip={"name", "is_scored"}).items()
453
+ cls._callbacks_ = []
454
+ for name in cls._supported_callbacks_:
455
+ cb = getattr(cls, name)
456
+ if cb in cls._default_callbacks_:
457
+ continue
458
+ cls._callbacks_.append(cb)
459
+ cls._field_init_done = False
460
+
461
+ @classmethod
462
+ def _init_fields(cls):
463
+ if cls._field_init_done:
464
+ return
465
+ cls._field_init_done = True
466
+ field_specifiers = get_field_specifiers(
467
+ cls, skip={"name", "is_scored", "_callbacks_", "_field_init_done"}
468
+ ).items()
434
469
  cls._imported_fields_ = {}
435
470
  cls._exported_fields_ = {}
436
471
  cls._memory_fields_ = {}
@@ -506,12 +541,6 @@ class _BaseArchetype:
506
541
  cls._spawn_signature_ = inspect.Signature(
507
542
  [inspect.Parameter(name, inspect.Parameter.POSITIONAL_OR_KEYWORD) for name in cls._memory_fields_]
508
543
  )
509
- cls._callbacks_ = []
510
- for name in cls._supported_callbacks_:
511
- cb = getattr(cls, name)
512
- if cb in cls._default_callbacks_:
513
- continue
514
- cls._callbacks_.append(cb)
515
544
 
516
545
 
517
546
  class PlayArchetype(_BaseArchetype):
@@ -796,20 +825,6 @@ class WatchArchetype(_BaseArchetype):
796
825
  case _:
797
826
  raise RuntimeError("Result is only accessible from the entity itself")
798
827
 
799
- @property
800
- def target_time(self) -> float:
801
- """The target time of this entity.
802
-
803
- Only meaningful for scored entities. Determines when combo and score are updated.
804
-
805
- Alias of `result.target_time`.
806
- """
807
- return self.result.target_time
808
-
809
- @target_time.setter
810
- def target_time(self, value: float):
811
- self.result.target_time = value
812
-
813
828
 
814
829
  class PreviewArchetype(_BaseArchetype):
815
830
  """Base class for preview mode archetypes.
@@ -967,10 +982,16 @@ class EntityRef[A: _BaseArchetype](Record):
967
982
  def archetype(cls) -> type[A]:
968
983
  return cls.type_var_value(A)
969
984
 
985
+ def with_archetype(self, archetype: type[A]) -> EntityRef[A]:
986
+ return EntityRef[archetype](index=self.index)
987
+
970
988
  def get(self) -> A:
971
989
  return self.archetype().at(self.index)
972
990
 
973
- def _to_list_(self, level_refs: dict[Any, int] | None = None) -> list[float | BlockPlace]:
991
+ def is_valid(self) -> bool:
992
+ return self.index >= 0 and self.archetype().is_at(self.index)
993
+
994
+ def _to_list_(self, level_refs: dict[Any, str] | None = None) -> list[float | str | BlockPlace]:
974
995
  ref = getattr(self, "_ref_", None)
975
996
  if ref is None:
976
997
  return [self.index]
@@ -979,6 +1000,19 @@ class EntityRef[A: _BaseArchetype](Record):
979
1000
  raise KeyError("Reference to entity not in level data")
980
1001
  return [level_refs[ref]]
981
1002
 
1003
+ @classmethod
1004
+ def _accepts_(cls, value: Any) -> bool:
1005
+ return super()._accepts_(value) or (cls._type_args_ and cls.archetype() is Any and isinstance(value, EntityRef))
1006
+
1007
+ @classmethod
1008
+ def _accept_(cls, value: Any) -> Self:
1009
+ if not cls._accepts_(value):
1010
+ raise TypeError(f"Expected {cls}, got {type(value)}")
1011
+ result = value.with_archetype(cls.archetype())
1012
+ if hasattr(value, "_ref_"):
1013
+ result._ref_ = value._ref_
1014
+ return result
1015
+
982
1016
 
983
1017
  class StandardArchetypeName(StrEnum):
984
1018
  """Standard archetype names."""
sonolus/script/array.py CHANGED
@@ -111,7 +111,7 @@ class Array[T, Size](GenericValue, ArrayLike[T]):
111
111
  iterator = iter(values)
112
112
  return cls(*(cls.element_type()._from_list_(iterator) for _ in range(cls.size())))
113
113
 
114
- def _to_list_(self, level_refs: dict[Any, int] | None = None) -> list[float | BlockPlace]:
114
+ def _to_list_(self, level_refs: dict[Any, str] | None = None) -> list[float | str | BlockPlace]:
115
115
  match self._value:
116
116
  case list():
117
117
  return [entry for value in self._value for entry in value._to_list_(level_refs)]
sonolus/script/bucket.py CHANGED
@@ -80,6 +80,24 @@ class JudgmentWindow(Record):
80
80
  self.good * other,
81
81
  )
82
82
 
83
+ def __add__(self, other: float | int) -> JudgmentWindow:
84
+ """Add a scalar to the intervals."""
85
+ return JudgmentWindow(
86
+ self.perfect + other,
87
+ self.great + other,
88
+ self.good + other,
89
+ )
90
+
91
+ @property
92
+ def start(self) -> float:
93
+ """The start time of the good interval."""
94
+ return self.good.start
95
+
96
+ @property
97
+ def end(self) -> float:
98
+ """The end time of the good interval."""
99
+ return self.good.end
100
+
83
101
 
84
102
  class Judgment(IntEnum):
85
103
  """The judgment of a hit."""
@@ -147,10 +165,10 @@ class Bucket(Record):
147
165
  class _BucketSprite:
148
166
  id: int
149
167
  fallback_id: int | None
150
- x: int
151
- y: int
152
- w: int
153
- h: int
168
+ x: float
169
+ y: float
170
+ w: float
171
+ h: float
154
172
  rotation: float
155
173
 
156
174
  def to_dict(self):
@@ -185,10 +203,10 @@ def bucket_sprite(
185
203
  *,
186
204
  sprite: Sprite,
187
205
  fallback_sprite: Sprite | None = None,
188
- x: int,
189
- y: int,
190
- w: int,
191
- h: int,
206
+ x: float,
207
+ y: float,
208
+ w: float,
209
+ h: float,
192
210
  rotation: float = 0,
193
211
  ) -> _BucketSprite:
194
212
  """Define a sprite for a bucket."""
@@ -97,7 +97,7 @@ class ConstantValue(Value):
97
97
  def _from_list_(cls, values: Iterable[float | BlockPlace]) -> Self:
98
98
  return cls()
99
99
 
100
- def _to_list_(self, level_refs: dict[Any, int] | None = None) -> list[float | BlockPlace]:
100
+ def _to_list_(self, level_refs: dict[Any, str] | None = None) -> list[float | str | BlockPlace]:
101
101
  return []
102
102
 
103
103
  @classmethod
@@ -12,6 +12,13 @@ def get_field_specifiers(cls, *, skip: set[str] = frozenset(), globals=None, loc
12
12
  if class_value is not _missing and key not in skip:
13
13
  results[key] = Annotated[value, class_value]
14
14
  for key, value in cls.__dict__.items():
15
- if key not in results and key not in skip and not key.startswith("__") and not callable(value):
15
+ if (
16
+ key not in results
17
+ and key not in skip
18
+ and not key.startswith("__")
19
+ and not callable(value)
20
+ and not hasattr(value, "__func__")
21
+ and not isinstance(value, property)
22
+ ):
16
23
  raise ValueError(f"Missing annotation for {cls.__name__}.{key}")
17
24
  return results
@@ -26,7 +26,7 @@ class TransientValue(Value):
26
26
  def _from_list_(cls, values: Iterable[float | BlockPlace]) -> Self:
27
27
  raise TypeError(f"{cls.__name__} cannot be constructed from list")
28
28
 
29
- def _to_list_(self, level_refs: dict[Any, int] | None = None) -> list[float | BlockPlace]:
29
+ def _to_list_(self, level_refs: dict[Any, str] | None = None) -> list[float | str | BlockPlace]:
30
30
  raise TypeError(f"{type(self).__name__} cannot be deconstructed to list")
31
31
 
32
32
  @classmethod
@@ -66,7 +66,7 @@ class Value:
66
66
  raise NotImplementedError
67
67
 
68
68
  @abstractmethod
69
- def _to_list_(self, level_refs: dict[Any, int] | None = None) -> list[float | BlockPlace]:
69
+ def _to_list_(self, level_refs: dict[Any, str] | None = None) -> list[float | str | BlockPlace]:
70
70
  """Converts this value to a list of floats."""
71
71
  raise NotImplementedError
72
72
 
@@ -76,7 +76,9 @@ class Value:
76
76
  """Returns the keys to a flat representation of this value."""
77
77
  raise NotImplementedError
78
78
 
79
- def _to_flat_dict_(self, prefix: str, level_refs: dict[Any, int] | None = None) -> dict[str, float | BlockPlace]:
79
+ def _to_flat_dict_(
80
+ self, prefix: str, level_refs: dict[Any, str] | None = None
81
+ ) -> dict[str, float | str | BlockPlace]:
80
82
  """Converts this value to a flat dictionary."""
81
83
  return dict(zip(self._flat_keys_(prefix), self._to_list_(level_refs), strict=False))
82
84
 
sonolus/script/level.py CHANGED
@@ -42,6 +42,25 @@ class Level:
42
42
  self.data = data
43
43
 
44
44
 
45
+ type EntityListArg = list[PlayArchetype | EntityListArg]
46
+
47
+
48
+ def flatten_entities(entities: EntityListArg):
49
+ """Flatten a list of entities.
50
+
51
+ Args:
52
+ entities: The list of entities.
53
+
54
+ Returns:
55
+ The flattened list of entities.
56
+ """
57
+ if isinstance(entities, list):
58
+ for entity in entities:
59
+ yield from flatten_entities(entity)
60
+ else:
61
+ yield entities
62
+
63
+
45
64
  class LevelData:
46
65
  """The data of a Sonolus level.
47
66
 
@@ -55,7 +74,7 @@ class LevelData:
55
74
 
56
75
  def __init__(self, bgm_offset: float, entities: list[PlayArchetype]) -> None:
57
76
  self.bgm_offset = bgm_offset
58
- self.entities = entities
77
+ self.entities = [*flatten_entities(entities)]
59
78
 
60
79
 
61
80
  class BpmChange(PlayArchetype):
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, final, runtime_checkable, TypeGuard
6
+ from typing import TYPE_CHECKING, Any, Self, TypeGuard, final, runtime_checkable
7
7
 
8
8
  from sonolus.backend.ir import IRConst, IRGet, IRPureInstr, IRSet
9
9
  from sonolus.backend.ops import Op
@@ -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, level_refs: dict[Any, int] | None = None) -> list[float | BlockPlace]:
95
+ def _to_list_(self, level_refs: dict[Any, str] | None = None) -> list[float | str | BlockPlace]:
96
96
  return [self.data]
97
97
 
98
98
  @classmethod
sonolus/script/record.py CHANGED
@@ -186,7 +186,7 @@ class Record(GenericValue):
186
186
  iterator = iter(values)
187
187
  return cls(**{field.name: field.type._from_list_(iterator) for field in cls._fields})
188
188
 
189
- def _to_list_(self, level_refs: dict[Any, int] | None = None) -> list[float | BlockPlace]:
189
+ def _to_list_(self, level_refs: dict[Any, str] | None = None) -> list[float | str | BlockPlace]:
190
190
  result = []
191
191
  for field in self._fields:
192
192
  result.extend(self._value[field.name]._to_list_(level_refs))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: sonolus.py
3
- Version: 0.1.8
3
+ Version: 0.1.9
4
4
  Summary: Sonolus engine development in Python
5
5
  Requires-Python: >=3.12
6
6
  Description-Content-Type: text/markdown
@@ -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=pqI9gtPBh0mlTgMNqul8bEVO1ARzKb8pNE9EN_CyDpk,994
6
- sonolus/backend/finalize.py,sha256=XjFeJgpKLI5_vU-okhSXRVTv31BZrUGbnBG_ITr3wrU,3963
6
+ sonolus/backend/finalize.py,sha256=vNUGLCUDxNqXGxweNRA1NpRvtij7Tks9to1V_JTs7Jo,4020
7
7
  sonolus/backend/interpret.py,sha256=B0jqlLmEGoyO2mxpcvwRwV17Tq_gOE9wLNt26Q5QOfs,14306
8
8
  sonolus/backend/ir.py,sha256=TCDLMvlX2S8emFDQwFVeD2OUC4fnhbrMObgYtoa_7PQ,2845
9
9
  sonolus/backend/mode.py,sha256=NkcPZJm8dn83LX35uP24MtQOCnfRDFZ280dHeEEfauE,613
@@ -11,11 +11,11 @@ sonolus/backend/node.py,sha256=H8qgnNyIseR-DhfgtcbDX03SUmhAJSSrYAlUEJTkkUo,999
11
11
  sonolus/backend/ops.py,sha256=ekkHSdgRubIYLSYFk0wTUuBvyf3TKdApM4AyR_koTQ8,10122
12
12
  sonolus/backend/place.py,sha256=Z3yFx-Ki2z32MXsVb6TkZ_D95RyZCu8iJPQRXNiyiNg,2364
13
13
  sonolus/backend/utils.py,sha256=9-mmCUwGlNdjp51jKrNBN2dGxCAXVV2PdJn031kaXHM,1717
14
- sonolus/backend/visitor.py,sha256=a7cRdiM9g1fLuR8_BxOwRTDvtq3JNfE4k1JqZioiQyU,45756
14
+ sonolus/backend/visitor.py,sha256=PRsF02Y664XrnBV_USQjtQ3ihqEeQR6zAcIRBTnhu18,46490
15
15
  sonolus/backend/optimize/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  sonolus/backend/optimize/allocate.py,sha256=LCqxvT8YsVGTaVAu58fb6lrrytVLWx1LNbcOfx8CqL8,5671
17
17
  sonolus/backend/optimize/constant_evaluation.py,sha256=ty3vNey7I44GK17lQA-3whkioFQGleYKD3P5a22foj0,15997
18
- sonolus/backend/optimize/copy_coalesce.py,sha256=vKeq1UYxA7cJq5HgP8HdsIACFPjNyK4m_asakm1SOZ4,3966
18
+ sonolus/backend/optimize/copy_coalesce.py,sha256=4vUe-y2w8sGyrguSlp8O_p0uy9rEUu5M-smI0F5UMQw,4404
19
19
  sonolus/backend/optimize/dead_code.py,sha256=qYmUqBmAp-O5mUpNusOoMEJVkbc9YIHx6Ynrg6dyNGY,8077
20
20
  sonolus/backend/optimize/dominance.py,sha256=oTFUqN8twrw6lTzqr1nlYs-Gk1NzIa-4qGdEQvDGzlM,3217
21
21
  sonolus/backend/optimize/flow.py,sha256=mMf5Um2uxwF65nw13UiIv7dFMHZZHnyWv2WaOVnGw2c,4266
@@ -28,16 +28,16 @@ sonolus/backend/optimize/ssa.py,sha256=D3CQm3s3gcuU0_k_0pXVrwirm4xjAZsX6corrTDS1
28
28
  sonolus/build/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
29
  sonolus/build/cli.py,sha256=12sFalCUJmn0Dg3f8ipNIkPmZ_djG15gldqWzDG7AYo,6241
30
30
  sonolus/build/collection.py,sha256=IsDgedsAJ-foHzQ4LnQ9zSVXSz5wVVt4sgqiUICBvCU,10573
31
- sonolus/build/compile.py,sha256=wBiRX6rnq8Op4_vVXJ-bPLtffgV4ppNBa9M9hIe9twI,3579
31
+ sonolus/build/compile.py,sha256=WhMwamVSi64gxrbj2tBdznHCT9pVLdR5lZS9WDapzg4,3521
32
32
  sonolus/build/engine.py,sha256=TAJCdSWOsEcTq9o6jfR3A2JZ8gOoc9YQx6FC_qW-dFw,6766
33
- sonolus/build/level.py,sha256=3sdGPvIZ4a15u3-JdITnB6rznp6a2E3k6A0gB8A15JA,610
33
+ sonolus/build/level.py,sha256=AjvK4725nqDcg7oGn5kWocBdG-AcirXpku74T7c2epA,673
34
34
  sonolus/build/node.py,sha256=jwsVWt6Brh4M9MypUt3Nqnxfm7fXrCMRWYQGwBTAszI,1162
35
35
  sonolus/build/project.py,sha256=QukkCVQBGxnp1F2jQjaAkTg3TutwhWqKGXAfQZDMk1c,5162
36
36
  sonolus/script/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
- sonolus/script/archetype.py,sha256=cQDoNVO7dUHYQ7RlAHiyoEnUYt0seCnFPD_bPzo0BNE,34114
38
- sonolus/script/array.py,sha256=rPAK3kdeL6A_a82DSnxDe6Cl99vjS2UVU97n1r8arsA,9341
37
+ sonolus/script/archetype.py,sha256=LGECC__TXb5km5UVk64fQr8AqduxmADIcKOmx1Z4qAY,35340
38
+ sonolus/script/array.py,sha256=C_LP-bgYfpd43pm_nFlG0x9ojov1qV9JCVJmKnUiqdo,9347
39
39
  sonolus/script/array_like.py,sha256=OVOLMadS-Jj941S-EgoxlFPdaQLT6ZrHzaMnKtB6PfU,8346
40
- sonolus/script/bucket.py,sha256=ZNlNeBZ1FzRLQ49bTuuJDmnYZ-_sjQEvosySx3ESxQc,6944
40
+ sonolus/script/bucket.py,sha256=oaaB7OXtBWzr8sLzPOpm8-GMhs7FzEhYrI1uVcM0DHM,7453
41
41
  sonolus/script/containers.py,sha256=tf0-UUSq8NH6k9jIKq6qgXRxanFQ0f5olH6uHghTynk,13171
42
42
  sonolus/script/debug.py,sha256=ua8FM7h563ZMQp7oyjJRGzjjF0zi4xcnFhI3RgIdOSw,2443
43
43
  sonolus/script/easing.py,sha256=7zaDKIfM_whUpb4FBz1DAF4NNG2vk_nDjl8kL2Y90aU,11396
@@ -47,15 +47,15 @@ sonolus/script/globals.py,sha256=Z8RfLkgDuXPIKiq-aOqblP0s__ALGmvcKdlyWZH21EM,916
47
47
  sonolus/script/instruction.py,sha256=PNfxC1dhT_hB0BxhDV3KXMn_kKxfI0t1iZmg8m6ddMU,6725
48
48
  sonolus/script/interval.py,sha256=3wMy7YlL6XV0g7w3eIDQDXl1WfTjW4NunKtwRxRMnDQ,9004
49
49
  sonolus/script/iterator.py,sha256=ZErUmpRrXISe1xiT3VOjHzcqqLhpfT9FI7Kz2s2vUpk,4163
50
- sonolus/script/level.py,sha256=NuXr8SalXn4eMm00OOYfWPQ-EXhJIKVCtbiIKX2SGag,1872
51
- sonolus/script/num.py,sha256=70dFsC5mcELiQoZk1Da1h1sHZ0Ed1D8oZzgX_hlPq9s,13917
50
+ sonolus/script/level.py,sha256=BIkhNC6gOpXfIeScXhY_OQV6q7ivnHsUoOiW1Ot-Ec8,2297
51
+ sonolus/script/num.py,sha256=4o0SQ9CpGpn5qddkVSwnJy6s5JHWW646BVNBWp2LMb0,13923
52
52
  sonolus/script/options.py,sha256=nTOuoRC2p_qoMx4ngOVDY2WZDooTxwwGTGKyb994v2A,7516
53
53
  sonolus/script/particle.py,sha256=K06ArT9tstRNdbuGIviDmDDWcK3-ieA53LHg0Xvizow,8304
54
54
  sonolus/script/pointer.py,sha256=pOh5vCSl6xR7mDm5PMOhBc_wf4O-b938DE0LtZWBmPc,1119
55
55
  sonolus/script/print.py,sha256=mNYu9QWiacBBGZrnePZQMVwbbguoelUps9GiOK_aVRU,2096
56
56
  sonolus/script/project.py,sha256=DhmBuH0CkFKmF27o1V9XhIOsywXDi57i-Wpwyd-70LM,2040
57
57
  sonolus/script/quad.py,sha256=e2kXKSp9K46Q9qstLsGLFPxaW7Z2kfVfignA8Ka2-Pw,8375
58
- sonolus/script/record.py,sha256=rOVlo-eUUvFG_Ee-wKrgX_ZwOqWKWtS7s8m-juM70yE,11216
58
+ sonolus/script/record.py,sha256=lIptvCrX0mTFMNZBOXyimO3OXMBPEBf6H0urh0eeMlE,11222
59
59
  sonolus/script/runtime.py,sha256=xeiLJFeqkCev1x6pBiM5afyvi3GWdpLJ5OYRg9M9nwo,18562
60
60
  sonolus/script/sprite.py,sha256=FOozsPtaQnInnm-QshtYznnC66_8jb1D2sHmo7nFEsY,15718
61
61
  sonolus/script/text.py,sha256=IsoINZJXefjReYDjJFwVaFsUCdgeQvPBDeywljM2dWo,13025
@@ -67,23 +67,23 @@ sonolus/script/vec.py,sha256=looCsmYpt6jlasdBqddtkC0hA1exZ3lxPP3_BL8cPXw,6148
67
67
  sonolus/script/internal/__init__.py,sha256=T6rzLoiOUaiSQtaHMZ88SNO-ijSjSSv33TKtUwu-Ms8,136
68
68
  sonolus/script/internal/builtin_impls.py,sha256=w27aKMhLX4Ivd7uKz1ZgVy1lC5scSSJ23-VfsbCfIb0,7731
69
69
  sonolus/script/internal/callbacks.py,sha256=vWzJG8uiJoEtsNnbeZPqOHogCwoLpz2D1MnHY2wVV8s,2801
70
- sonolus/script/internal/constant.py,sha256=lIBBR84Rfw0rBSZU2reCrUnB3yEMEdOX6A7_LgptYz8,3776
70
+ sonolus/script/internal/constant.py,sha256=VblCGm61J7PCnErom8L9-WHisD6-C09_yeuiMxQog14,3782
71
71
  sonolus/script/internal/context.py,sha256=I9X89aTWgoY-_jgnJHEnzzVLAvILACtPfgdE4ipxjOc,13930
72
72
  sonolus/script/internal/descriptor.py,sha256=XRFey-EjiAm_--KsNl-8N0Mi_iyQwlPh68gDp0pKf3E,392
73
73
  sonolus/script/internal/dict_impl.py,sha256=alu_wKGSk1kZajNf64qbe7t71shEzD4N5xNIATH8Swo,1885
74
74
  sonolus/script/internal/error.py,sha256=ZNnsvQVQAnFKzcvsm6-sste2lo-tP5pPI8sD7XlAZWc,490
75
75
  sonolus/script/internal/generic.py,sha256=YU1hUJoBcGc0OSrFStK5JI6CikOwSmd_IR20pCuT82k,7310
76
76
  sonolus/script/internal/impl.py,sha256=HKQVoHknw5t43Wmj_G1vFjGSmnFpOj1FUYnhbUM3rHc,2969
77
- sonolus/script/internal/introspection.py,sha256=A0P2R2pNQTyj4N6-v-bCzuyIi7F-ST3qzQ3AM5l9P58,819
77
+ sonolus/script/internal/introspection.py,sha256=SL2zaYjid0kkcj6ZbFLIwhgh7WKZBaAHhlbSJGr6PWs,974
78
78
  sonolus/script/internal/math_impls.py,sha256=7L450U7gW-jUkTWcQ1AMg9IX0yhu4G2WUsJ5xMZ8r3o,2306
79
79
  sonolus/script/internal/native.py,sha256=XKlNnWSJ-lxbwVGWhGj_CSSoWsVN18imqT5sAsDJT1w,1551
80
80
  sonolus/script/internal/random.py,sha256=6Ku5edRcDUh7rtqEEYCJz0BQavw69RALsVHS25z50pI,1695
81
81
  sonolus/script/internal/range.py,sha256=lrTanQFHU7RuQxSSPwDdoC30Y8FnHGxcP1Ahditu3zU,2297
82
- sonolus/script/internal/transient.py,sha256=pSDFGu0m26zVsp6owmNTeSPue-osDd1JahjJSijW8t0,1520
82
+ sonolus/script/internal/transient.py,sha256=s-8284jDw1xZorOvLw9mG-ADhZqSWmzUgfL3AO5QcKE,1526
83
83
  sonolus/script/internal/tuple_impl.py,sha256=vjXmScLVdeTkDn3t9fgIRqtW31iwngnaP2rmA6nlsLw,3431
84
- sonolus/script/internal/value.py,sha256=ik9sMKl0TbsH_C6QNxD4WfpAnmBFISgmmlazWwh3kY0,4308
85
- sonolus_py-0.1.8.dist-info/METADATA,sha256=cfD6gibjNFF16Xw5L4tIe_cUX5WYG_HFt4Tl8fVGkK8,216
86
- sonolus_py-0.1.8.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
87
- sonolus_py-0.1.8.dist-info/entry_points.txt,sha256=oTYspY_b7SA8TptEMTDxh4-Aj-ZVPnYC9f1lqH6s9G4,54
88
- sonolus_py-0.1.8.dist-info/licenses/LICENSE,sha256=JEKpqVhQYfEc7zg3Mj462sKbKYmO1K7WmvX1qvg9IJk,1067
89
- sonolus_py-0.1.8.dist-info/RECORD,,
84
+ sonolus/script/internal/value.py,sha256=QcX-Ppv5IHQvJEupqAXCmXpaWao5_0XDvYvNk9J2PQU,4334
85
+ sonolus_py-0.1.9.dist-info/METADATA,sha256=bqFPKVEV8CRv--1dBl6wh4WiOiX67OIet3NRKZO7WoE,216
86
+ sonolus_py-0.1.9.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
87
+ sonolus_py-0.1.9.dist-info/entry_points.txt,sha256=oTYspY_b7SA8TptEMTDxh4-Aj-ZVPnYC9f1lqH6s9G4,54
88
+ sonolus_py-0.1.9.dist-info/licenses/LICENSE,sha256=JEKpqVhQYfEc7zg3Mj462sKbKYmO1K7WmvX1qvg9IJk,1067
89
+ sonolus_py-0.1.9.dist-info/RECORD,,