sonolus.py 0.11.0__py3-none-any.whl → 0.12.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.
- sonolus/backend/finalize.py +30 -32
- sonolus/backend/interpret.py +3 -3
- sonolus/backend/node.py +6 -28
- sonolus/backend/visitor.py +2 -0
- sonolus/build/cli.py +7 -0
- sonolus/build/compile.py +17 -3
- sonolus/build/dev_server.py +7 -1
- sonolus/build/node.py +6 -8
- sonolus/script/archetype.py +182 -44
- sonolus/script/containers.py +6 -5
- sonolus/script/debug.py +18 -2
- sonolus/script/engine.py +48 -0
- sonolus/script/internal/builtin_impls.py +82 -3
- sonolus/script/internal/context.py +46 -5
- sonolus/script/internal/generic.py +34 -7
- sonolus/script/internal/impl.py +6 -0
- sonolus/script/internal/introspection.py +10 -1
- sonolus/script/project.py +2 -0
- sonolus/script/record.py +34 -20
- sonolus/script/stream.py +28 -21
- sonolus/script/values.py +1 -6
- {sonolus_py-0.11.0.dist-info → sonolus_py-0.12.5.dist-info}/METADATA +2 -2
- {sonolus_py-0.11.0.dist-info → sonolus_py-0.12.5.dist-info}/RECORD +26 -26
- {sonolus_py-0.11.0.dist-info → sonolus_py-0.12.5.dist-info}/WHEEL +0 -0
- {sonolus_py-0.11.0.dist-info → sonolus_py-0.12.5.dist-info}/entry_points.txt +0 -0
- {sonolus_py-0.11.0.dist-info → sonolus_py-0.12.5.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from types import FunctionType
|
|
2
|
+
from typing import Any, Never, assert_never
|
|
2
3
|
|
|
3
4
|
from sonolus.backend.ops import Op
|
|
4
5
|
from sonolus.script.array import Array
|
|
@@ -389,10 +390,85 @@ def _super(*args):
|
|
|
389
390
|
return super(*(arg._as_py_() if arg._is_py_() else arg for arg in args))
|
|
390
391
|
|
|
391
392
|
|
|
393
|
+
@meta_fn
|
|
394
|
+
def _hasattr(obj: Any, name: str) -> bool:
|
|
395
|
+
from sonolus.script.internal.constant import ConstantValue
|
|
396
|
+
from sonolus.script.internal.descriptor import SonolusDescriptor
|
|
397
|
+
|
|
398
|
+
name = validate_value(name)._as_py_()
|
|
399
|
+
if isinstance(obj, ConstantValue):
|
|
400
|
+
# Unwrap so we can access fields
|
|
401
|
+
obj = obj._as_py_()
|
|
402
|
+
descriptor = None
|
|
403
|
+
for cls in type.mro(type(obj)):
|
|
404
|
+
descriptor = cls.__dict__.get(name, None)
|
|
405
|
+
if descriptor is not None:
|
|
406
|
+
break
|
|
407
|
+
# We want to mirror what getattr supports and fail fast if a future getattr would fail.
|
|
408
|
+
match descriptor:
|
|
409
|
+
case None:
|
|
410
|
+
return hasattr(obj, name)
|
|
411
|
+
case property() | SonolusDescriptor() | FunctionType() | classmethod() | staticmethod():
|
|
412
|
+
return True
|
|
413
|
+
case non_descriptor if not hasattr(non_descriptor, "__get__"):
|
|
414
|
+
return True
|
|
415
|
+
case _:
|
|
416
|
+
raise TypeError(f"Unsupported field or descriptor {name}")
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
@meta_fn
|
|
420
|
+
def _getattr(obj: Any, name: str, default=_empty) -> Any:
|
|
421
|
+
from sonolus.backend.visitor import compile_and_call
|
|
422
|
+
from sonolus.script.internal.constant import ConstantValue
|
|
423
|
+
from sonolus.script.internal.descriptor import SonolusDescriptor
|
|
424
|
+
|
|
425
|
+
name = validate_value(name)._as_py_()
|
|
426
|
+
if isinstance(obj, ConstantValue):
|
|
427
|
+
# Unwrap so we can access fields
|
|
428
|
+
obj = obj._as_py_()
|
|
429
|
+
descriptor = None
|
|
430
|
+
for cls in type.mro(type(obj)):
|
|
431
|
+
descriptor = cls.__dict__.get(name, None)
|
|
432
|
+
if descriptor is not None:
|
|
433
|
+
break
|
|
434
|
+
match descriptor:
|
|
435
|
+
case property(fget=getter):
|
|
436
|
+
return compile_and_call(getter, obj)
|
|
437
|
+
case SonolusDescriptor() | FunctionType() | classmethod() | staticmethod() | None:
|
|
438
|
+
return validate_value(getattr(obj, name) if default is _empty else getattr(obj, name, default))
|
|
439
|
+
case non_descriptor if not hasattr(non_descriptor, "__get__"):
|
|
440
|
+
return validate_value(getattr(obj, name) if default is _empty else getattr(obj, name, default))
|
|
441
|
+
case _:
|
|
442
|
+
raise TypeError(f"Unsupported field or descriptor {name}")
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
@meta_fn
|
|
446
|
+
def _setattr(obj: Any, name: str, value: Any):
|
|
447
|
+
from sonolus.backend.visitor import compile_and_call
|
|
448
|
+
from sonolus.script.internal.descriptor import SonolusDescriptor
|
|
449
|
+
|
|
450
|
+
name = validate_value(name)._as_py_()
|
|
451
|
+
if obj._is_py_():
|
|
452
|
+
obj = obj._as_py_()
|
|
453
|
+
descriptor = getattr(type(obj), name, None)
|
|
454
|
+
match descriptor:
|
|
455
|
+
case property(fset=setter):
|
|
456
|
+
if setter is None:
|
|
457
|
+
raise AttributeError(f"Cannot set attribute {name} because property has no setter")
|
|
458
|
+
compile_and_call(setter, obj, value)
|
|
459
|
+
case SonolusDescriptor():
|
|
460
|
+
setattr(obj, name, value)
|
|
461
|
+
case _:
|
|
462
|
+
raise TypeError(f"Unsupported field or descriptor {name}")
|
|
463
|
+
|
|
464
|
+
|
|
392
465
|
class _Type(Record):
|
|
393
466
|
@meta_fn
|
|
394
467
|
def __call__(self, value, /):
|
|
395
|
-
|
|
468
|
+
value = validate_value(value)
|
|
469
|
+
if value._is_py_():
|
|
470
|
+
value = value._as_py_()
|
|
471
|
+
return validate_value(type(value))
|
|
396
472
|
|
|
397
473
|
def __getitem__(self, item):
|
|
398
474
|
return self
|
|
@@ -412,12 +488,13 @@ BUILTIN_IMPLS = {
|
|
|
412
488
|
id(abs): _abs,
|
|
413
489
|
id(all): _all,
|
|
414
490
|
id(any): _any,
|
|
415
|
-
id(sum): _sum,
|
|
416
491
|
id(bool): _bool,
|
|
417
492
|
id(callable): _callable,
|
|
418
493
|
id(enumerate): _enumerate,
|
|
419
494
|
id(filter): _filter,
|
|
420
495
|
id(float): _float,
|
|
496
|
+
id(getattr): _getattr,
|
|
497
|
+
id(hasattr): _hasattr,
|
|
421
498
|
id(int): _int,
|
|
422
499
|
id(isinstance): _isinstance,
|
|
423
500
|
id(iter): _iter,
|
|
@@ -428,6 +505,8 @@ BUILTIN_IMPLS = {
|
|
|
428
505
|
id(next): _next,
|
|
429
506
|
id(range): Range,
|
|
430
507
|
id(reversed): _reversed,
|
|
508
|
+
id(setattr): _setattr,
|
|
509
|
+
id(sum): _sum,
|
|
431
510
|
id(super): _super,
|
|
432
511
|
id(type): _type,
|
|
433
512
|
id(zip): _zip,
|
|
@@ -94,25 +94,36 @@ class ProjectContextState:
|
|
|
94
94
|
|
|
95
95
|
class ModeContextState:
|
|
96
96
|
archetypes: dict[type, int]
|
|
97
|
+
compile_time_only_archetypes: set[type]
|
|
97
98
|
archetypes_by_name: dict[str, type]
|
|
98
99
|
keys_by_archetype_id: Sequence[int]
|
|
99
100
|
is_scored_by_archetype_id: Sequence[bool]
|
|
101
|
+
archetype_mro_id_array_rom_indexes: Sequence[int] | None = None
|
|
100
102
|
environment_mappings: dict[_GlobalInfo, int]
|
|
101
103
|
environment_offsets: dict[Block, int]
|
|
102
104
|
mode: Mode
|
|
103
105
|
lock: Lock
|
|
104
106
|
|
|
105
|
-
def __init__(self, mode: Mode, archetypes:
|
|
107
|
+
def __init__(self, mode: Mode, archetypes: list[type] | None = None):
|
|
106
108
|
from sonolus.script.array import Array
|
|
107
109
|
|
|
108
|
-
|
|
110
|
+
archetypes = [*archetypes] if archetypes is not None else []
|
|
111
|
+
seen_archetypes = {*archetypes}
|
|
112
|
+
compile_time_only_archetypes = set()
|
|
113
|
+
for type_ in [*archetypes]:
|
|
114
|
+
for entry in type_.mro():
|
|
115
|
+
if getattr(entry, "_is_concrete_archetype_", False) and entry not in seen_archetypes:
|
|
116
|
+
archetypes.append(entry)
|
|
117
|
+
seen_archetypes.add(entry)
|
|
118
|
+
compile_time_only_archetypes.add(entry)
|
|
119
|
+
self.archetypes = {type_: idx for idx, type_ in enumerate(archetypes)}
|
|
120
|
+
self.compile_time_only_archetypes = compile_time_only_archetypes
|
|
109
121
|
self.archetypes_by_name = {type_.name: type_ for type_, _ in self.archetypes.items()} # type: ignore
|
|
110
|
-
ordered_archetypes = sorted(self.archetypes, key=lambda a: self.archetypes[a])
|
|
111
122
|
self.keys_by_archetype_id = (
|
|
112
|
-
Array(*((getattr(a, "_key_", -1)) for a in
|
|
123
|
+
Array(*((getattr(a, "_key_", -1)) for a in archetypes)) if archetypes else Array[int, Literal[0]]()
|
|
113
124
|
)
|
|
114
125
|
self.is_scored_by_archetype_id = (
|
|
115
|
-
Array(*((getattr(a, "_is_scored_", False)) for a in
|
|
126
|
+
Array(*((getattr(a, "_is_scored_", False)) for a in archetypes))
|
|
116
127
|
if archetypes
|
|
117
128
|
else Array[bool, Literal[0]]()
|
|
118
129
|
)
|
|
@@ -121,6 +132,27 @@ class ModeContextState:
|
|
|
121
132
|
self.mode = mode
|
|
122
133
|
self.lock = Lock()
|
|
123
134
|
|
|
135
|
+
def _init_archetype_mro_info(self, rom: ReadOnlyMemory):
|
|
136
|
+
from sonolus.script.array import Array
|
|
137
|
+
from sonolus.script.num import Num
|
|
138
|
+
|
|
139
|
+
with self.lock:
|
|
140
|
+
if self.archetype_mro_id_array_rom_indexes is not None:
|
|
141
|
+
return
|
|
142
|
+
archetype_mro_id_values = []
|
|
143
|
+
archetype_mro_id_offsets = []
|
|
144
|
+
for type_ in self.archetypes:
|
|
145
|
+
mro_ids = [self.archetypes[entry] for entry in type_.mro() if entry in self.archetypes]
|
|
146
|
+
archetype_mro_id_offsets.append(len(archetype_mro_id_values))
|
|
147
|
+
archetype_mro_id_values.append(len(mro_ids))
|
|
148
|
+
archetype_mro_id_values.extend(mro_ids)
|
|
149
|
+
archetype_mro_id_array_place = rom[tuple(archetype_mro_id_values)]
|
|
150
|
+
|
|
151
|
+
archetype_mro_id_rom_indexes = Array[int, len(archetype_mro_id_offsets)]._with_value(
|
|
152
|
+
[Num._accept_(offset + archetype_mro_id_array_place.index) for offset in archetype_mro_id_offsets]
|
|
153
|
+
)
|
|
154
|
+
self.archetype_mro_id_array_rom_indexes = archetype_mro_id_rom_indexes
|
|
155
|
+
|
|
124
156
|
|
|
125
157
|
class CallbackContextState:
|
|
126
158
|
callback: str
|
|
@@ -371,6 +403,15 @@ class Context:
|
|
|
371
403
|
self.mode_state.archetypes[type_] = len(self.mode_state.archetypes)
|
|
372
404
|
return self.mode_state.archetypes[type_]
|
|
373
405
|
|
|
406
|
+
def get_archetype_mro_id_array(self, archetype_id: int) -> Sequence[int]:
|
|
407
|
+
from sonolus.script.containers import ArrayPointer
|
|
408
|
+
from sonolus.script.num import Num
|
|
409
|
+
from sonolus.script.pointer import _deref
|
|
410
|
+
|
|
411
|
+
self.mode_state._init_archetype_mro_info(self.rom)
|
|
412
|
+
rom_index = self.mode_state.archetype_mro_id_array_rom_indexes[archetype_id]
|
|
413
|
+
return ArrayPointer[int](_deref(self.blocks.EngineRom, rom_index, Num), self.blocks.EngineRom, rom_index + 1)
|
|
414
|
+
|
|
374
415
|
|
|
375
416
|
def ctx() -> Context | Any: # Using Any to silence type checker warnings if it's None
|
|
376
417
|
return context_var.get()
|
|
@@ -37,6 +37,11 @@ def validate_type_spec(spec: Any) -> PartialGeneric | TypeVar | type[Value]:
|
|
|
37
37
|
validated_args = {validate_type_arg(arg) for arg in args}
|
|
38
38
|
if len(validated_args) == 1:
|
|
39
39
|
return validated_args.pop()
|
|
40
|
+
|
|
41
|
+
from sonolus.script.archetype import _BaseArchetype
|
|
42
|
+
|
|
43
|
+
if isinstance(spec, type) and issubclass(spec, _BaseArchetype):
|
|
44
|
+
raise TypeError(f"Expected a concrete type, got {spec}. Did you mean to write EntityRef[{spec.__name__}]?")
|
|
40
45
|
raise TypeError(f"Invalid type spec: {spec}")
|
|
41
46
|
|
|
42
47
|
|
|
@@ -44,15 +49,18 @@ def validate_concrete_type(spec: Any) -> type[Value]:
|
|
|
44
49
|
spec = validate_type_spec(spec)
|
|
45
50
|
if isinstance(spec, type) and issubclass(spec, Value) and spec._is_concrete_():
|
|
46
51
|
return spec
|
|
52
|
+
if (
|
|
53
|
+
isinstance(spec, type)
|
|
54
|
+
and issubclass(spec, Value)
|
|
55
|
+
and not spec._is_concrete_()
|
|
56
|
+
and issubclass(spec, GenericValue)
|
|
57
|
+
):
|
|
58
|
+
raise TypeError(f"Expected a concrete type, got {spec}. Are there missing type arguments?")
|
|
59
|
+
if isinstance(spec, PartialGeneric):
|
|
60
|
+
raise TypeError(f"Expected a concrete type, got {spec}. Invalid use of a type parameter as a type argument?")
|
|
47
61
|
raise TypeError(f"Expected a concrete type, got {spec}")
|
|
48
62
|
|
|
49
63
|
|
|
50
|
-
def validate_type_args(args) -> tuple[Any, ...]:
|
|
51
|
-
if not isinstance(args, tuple):
|
|
52
|
-
args = (args,)
|
|
53
|
-
return tuple(validate_type_arg(arg) for arg in args)
|
|
54
|
-
|
|
55
|
-
|
|
56
64
|
def contains_incomplete_type(args) -> bool:
|
|
57
65
|
if not isinstance(args, tuple):
|
|
58
66
|
args = (args,)
|
|
@@ -102,7 +110,26 @@ class GenericValue(Value):
|
|
|
102
110
|
def __class_getitem__(cls, args: Any) -> type[Self]:
|
|
103
111
|
if cls._type_args_ is not None:
|
|
104
112
|
raise TypeError(f"Type {cls.__name__} is already parameterized")
|
|
105
|
-
|
|
113
|
+
if not isinstance(args, tuple):
|
|
114
|
+
args = (args,)
|
|
115
|
+
validated_args = []
|
|
116
|
+
for i, arg in enumerate(args):
|
|
117
|
+
if i < len(cls.__type_params__):
|
|
118
|
+
type_param = cls.__type_params__[i]
|
|
119
|
+
else:
|
|
120
|
+
type_param = None
|
|
121
|
+
try:
|
|
122
|
+
validated_args.append(validate_type_arg(arg))
|
|
123
|
+
except TypeError as e:
|
|
124
|
+
if type_param is not None:
|
|
125
|
+
type_param_body = ", ".join(str(tp) for tp in cls.__type_params__)
|
|
126
|
+
raise TypeError(
|
|
127
|
+
f"Invalid type argument for type parameter {type_param} of "
|
|
128
|
+
f"class {cls.__name__}[{type_param_body}]: {e}"
|
|
129
|
+
) from e
|
|
130
|
+
else:
|
|
131
|
+
raise TypeError(f"Invalid type argument at position {i} of class {cls.__name__}: {e}") from e
|
|
132
|
+
args = tuple(validated_args)
|
|
106
133
|
args = cls._validate_type_args_(args)
|
|
107
134
|
if contains_incomplete_type(args):
|
|
108
135
|
return PartialGeneric(cls, args)
|
sonolus/script/internal/impl.py
CHANGED
|
@@ -62,6 +62,12 @@ def try_validate_value(value: Any) -> Value | None:
|
|
|
62
62
|
except ImportError:
|
|
63
63
|
pass
|
|
64
64
|
|
|
65
|
+
if hasattr(value, "_init_") and callable(value._init_):
|
|
66
|
+
try:
|
|
67
|
+
value._init_()
|
|
68
|
+
except Exception as e:
|
|
69
|
+
raise RuntimeError(f"Error initializing value {value}: {e}") from e
|
|
70
|
+
|
|
65
71
|
match value:
|
|
66
72
|
case Value():
|
|
67
73
|
return value
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import inspect
|
|
2
|
+
from abc import ABC
|
|
3
|
+
from collections.abc import Sequence
|
|
2
4
|
from typing import Annotated
|
|
3
5
|
|
|
4
6
|
_missing = object()
|
|
@@ -11,9 +13,15 @@ def get_field_specifiers(
|
|
|
11
13
|
globals=None, # noqa: A002
|
|
12
14
|
locals=None, # noqa: A002
|
|
13
15
|
eval_str=True,
|
|
16
|
+
included_classes: Sequence[type] | None = None,
|
|
14
17
|
):
|
|
15
18
|
"""Like inspect.get_annotations, but also turns class attributes into Annotated."""
|
|
16
|
-
|
|
19
|
+
if included_classes is not None:
|
|
20
|
+
results = {}
|
|
21
|
+
for entry in reversed(included_classes):
|
|
22
|
+
results.update(inspect.get_annotations(entry, eval_str=eval_str))
|
|
23
|
+
else:
|
|
24
|
+
results = inspect.get_annotations(cls, globals=globals, locals=locals, eval_str=eval_str)
|
|
17
25
|
for key, value in results.items():
|
|
18
26
|
class_value = getattr(cls, key, _missing)
|
|
19
27
|
if class_value is not _missing and key not in skip:
|
|
@@ -26,6 +34,7 @@ def get_field_specifiers(
|
|
|
26
34
|
and not callable(value)
|
|
27
35
|
and not hasattr(value, "__func__")
|
|
28
36
|
and not isinstance(value, property)
|
|
37
|
+
and not (issubclass(cls, ABC) and (hasattr(ABC, key)))
|
|
29
38
|
):
|
|
30
39
|
raise ValueError(f"Missing annotation for {cls.__name__}.{key}")
|
|
31
40
|
for skipped_key in skip:
|
sonolus/script/project.py
CHANGED
sonolus/script/record.py
CHANGED
|
@@ -4,7 +4,7 @@ import inspect
|
|
|
4
4
|
from abc import ABCMeta
|
|
5
5
|
from collections.abc import Iterable
|
|
6
6
|
from inspect import getmro
|
|
7
|
-
from typing import Any, ClassVar, Self, TypeVar, dataclass_transform, get_origin
|
|
7
|
+
from typing import Any, ClassVar, Protocol, Self, TypeVar, dataclass_transform, get_origin
|
|
8
8
|
|
|
9
9
|
from sonolus.backend.place import BlockPlace
|
|
10
10
|
from sonolus.script.internal.context import ctx
|
|
@@ -21,7 +21,8 @@ from sonolus.script.internal.value import BackingSource, DataValue, Value
|
|
|
21
21
|
from sonolus.script.num import Num
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
# Protocol metaclass is a subclass of ABCMeta, but let's make ABCMeta explicit for clarity
|
|
25
|
+
class RecordMeta(type(Protocol), ABCMeta):
|
|
25
26
|
@meta_fn
|
|
26
27
|
def __pos__[T](cls: type[T]) -> T:
|
|
27
28
|
"""Create a zero-initialized record instance."""
|
|
@@ -103,25 +104,28 @@ class Record(GenericValue, metaclass=RecordMeta):
|
|
|
103
104
|
index = 0
|
|
104
105
|
offset = 0
|
|
105
106
|
for name, hint in hints.items():
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
107
|
+
try:
|
|
108
|
+
if name not in cls.__annotations__:
|
|
109
|
+
continue
|
|
110
|
+
if hint is ClassVar or get_origin(hint) is ClassVar:
|
|
111
|
+
continue
|
|
112
|
+
if hasattr(cls, name):
|
|
113
|
+
raise TypeError("Default values are not supported for Record fields")
|
|
114
|
+
type_ = validate_type_spec(hint)
|
|
115
|
+
fields.append(_RecordField(name, type_, index, offset))
|
|
116
|
+
if isinstance(type_, type) and issubclass(type_, Value) and type_._is_concrete_():
|
|
117
|
+
offset += type_._size_()
|
|
118
|
+
setattr(cls, name, fields[-1])
|
|
119
|
+
index += 1
|
|
120
|
+
params.append(
|
|
121
|
+
inspect.Parameter(
|
|
122
|
+
name,
|
|
123
|
+
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
124
|
+
annotation=type_,
|
|
125
|
+
)
|
|
123
126
|
)
|
|
124
|
-
|
|
127
|
+
except Exception as e:
|
|
128
|
+
raise TypeError(f"Error processing field '{name}' of Record {cls.__name__}: {e}") from e
|
|
125
129
|
|
|
126
130
|
cls._parameterized_ = {}
|
|
127
131
|
cls._fields_ = fields
|
|
@@ -320,6 +324,16 @@ class Record(GenericValue, metaclass=RecordMeta):
|
|
|
320
324
|
"""
|
|
321
325
|
return super().type_var_value(var)
|
|
322
326
|
|
|
327
|
+
@classmethod
|
|
328
|
+
def _validate_parameterized_(cls):
|
|
329
|
+
pass
|
|
330
|
+
|
|
331
|
+
@classmethod
|
|
332
|
+
def _get_parameterized(cls, args: tuple[Any, ...]) -> type[Self]:
|
|
333
|
+
result = super()._get_parameterized(args)
|
|
334
|
+
result._validate_parameterized_()
|
|
335
|
+
return result
|
|
336
|
+
|
|
323
337
|
|
|
324
338
|
class _RecordField(SonolusDescriptor):
|
|
325
339
|
def __init__(self, name: str, type_: type[Value] | Any, index: int, offset: int):
|
sonolus/script/stream.py
CHANGED
|
@@ -94,27 +94,34 @@ def streams[T](cls: type[T]) -> T:
|
|
|
94
94
|
"""
|
|
95
95
|
if len(cls.__bases__) != 1:
|
|
96
96
|
raise ValueError("Options class must not inherit from any class (except object)")
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
97
|
+
|
|
98
|
+
@classmethod
|
|
99
|
+
def _init_(cls):
|
|
100
|
+
if getattr(cls, "_init_done_", False):
|
|
101
|
+
return
|
|
102
|
+
entries = []
|
|
103
|
+
# Offset 0 is unused so we can tell when a stream object is uninitialized since it'll have offset 0.
|
|
104
|
+
offset = 1
|
|
105
|
+
for name, annotation in get_field_specifiers(cls, skip={"_init_done_"}).items():
|
|
106
|
+
if issubclass(annotation, Stream | StreamGroup):
|
|
107
|
+
annotation = cast(type[Stream | StreamGroup], annotation)
|
|
108
|
+
if annotation is Stream or annotation is StreamGroup:
|
|
109
|
+
raise TypeError(f"Invalid annotation for streams: {annotation}. Must have type arguments.")
|
|
110
|
+
setattr(cls, name, _StreamField(offset, annotation))
|
|
111
|
+
# Streams store their data across several backing streams
|
|
112
|
+
entries.append((name, offset, annotation))
|
|
113
|
+
offset += annotation.backing_size()
|
|
114
|
+
elif issubclass(annotation, Value) and annotation._is_concrete_():
|
|
115
|
+
setattr(cls, name, _StreamDataField(offset, annotation))
|
|
116
|
+
# Data fields store their data in a single backing stream at different offsets in the same stream
|
|
117
|
+
entries.append((name, offset, annotation))
|
|
118
|
+
offset += 1
|
|
119
|
+
cls._streams_ = entries
|
|
120
|
+
cls._is_comptime_value_ = True
|
|
121
|
+
cls._init_done_ = True
|
|
122
|
+
|
|
123
|
+
cls._init_ = _init_
|
|
124
|
+
return cls()
|
|
118
125
|
|
|
119
126
|
|
|
120
127
|
@meta_fn
|
sonolus/script/values.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from sonolus.script.internal.context import ctx
|
|
2
2
|
from sonolus.script.internal.generic import validate_concrete_type
|
|
3
3
|
from sonolus.script.internal.impl import meta_fn, validate_value
|
|
4
|
-
from sonolus.script.num import Num
|
|
5
4
|
|
|
6
5
|
|
|
7
6
|
@meta_fn
|
|
@@ -49,8 +48,4 @@ def swap[T](a: T, b: T):
|
|
|
49
48
|
@meta_fn
|
|
50
49
|
def sizeof(type_: type, /) -> int:
|
|
51
50
|
"""Return the size of the given type."""
|
|
52
|
-
|
|
53
|
-
if ctx():
|
|
54
|
-
return Num(type_._size_())
|
|
55
|
-
else:
|
|
56
|
-
return type_._size_()
|
|
51
|
+
return validate_concrete_type(type_)._size_()
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sonolus.py
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.5
|
|
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
|
|
7
7
|
Project-URL: Issues, https://github.com/qwewqa/sonolus.py/issues
|
|
8
8
|
Project-URL: Changelog, https://sonolus.py.qwewqa.xyz/changelog/
|
|
9
9
|
License-File: LICENSE
|
|
10
|
-
Requires-Python: >=3.12
|
|
10
|
+
Requires-Python: >=3.12.5
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
|
|
13
13
|
# 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=
|
|
7
|
-
sonolus/backend/interpret.py,sha256=
|
|
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=
|
|
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=
|
|
14
|
+
sonolus/backend/visitor.py,sha256=0EO5EgACDHpbITvKMbdP4EmoIbBDmZtZjnup9jksf_E,64590
|
|
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
|
|
@@ -26,24 +26,24 @@ sonolus/backend/optimize/passes.py,sha256=YyFKy6qCwcR_Ua2_SXpcBODfvBbm_ygVYcqloO
|
|
|
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=
|
|
29
|
+
sonolus/build/cli.py,sha256=kjLyKkO0OAZbK-7yg6AWz6uwYo_i7GGGQg8Kr7wcmAA,10830
|
|
30
30
|
sonolus/build/collection.py,sha256=6hniAzriPWBKUeGDkXabNXpbdHiHnqiK9shs6U1OExM,12748
|
|
31
|
-
sonolus/build/compile.py,sha256=
|
|
32
|
-
sonolus/build/dev_server.py,sha256=
|
|
31
|
+
sonolus/build/compile.py,sha256=m4v4wYWnI6ebot4-fJi9a7eoF0WIo3uPOPy0_NpLgK0,8855
|
|
32
|
+
sonolus/build/dev_server.py,sha256=l0Ld8cJIMRS3Y_RWKVGUAqlBg2p2hevClenV9E9SBFg,10896
|
|
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=
|
|
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=
|
|
38
|
+
sonolus/script/archetype.py,sha256=m1FSzrJ6J1_Evw-afGTVEJ7PkzfLNnn0-s82XnBki0I,56042
|
|
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=
|
|
43
|
-
sonolus/script/debug.py,sha256=
|
|
42
|
+
sonolus/script/containers.py,sha256=KKySXTh_ON9hut1ScMS31ewRNnVd4t7OwpIZg2bPhno,28676
|
|
43
|
+
sonolus/script/debug.py,sha256=FRKNwigMh8tzZ_OC6chGNYYQGoYImNvky0FTDeLziAI,8289
|
|
44
44
|
sonolus/script/easing.py,sha256=2FUJI_nfp990P_armCcRqHm2329O985glJAhSC6tnxs,11379
|
|
45
45
|
sonolus/script/effect.py,sha256=SfJxSNF3RlPCRXnkt62ZlWhCXw3mmmRCsoMsvTErUP0,7960
|
|
46
|
-
sonolus/script/engine.py,sha256=
|
|
46
|
+
sonolus/script/engine.py,sha256=0pSzgSUX8CLXb6l-8kNlHWclj2_NSfn1ddq2vo3ZY2E,12234
|
|
47
47
|
sonolus/script/globals.py,sha256=nlXSNS4NRXsgQU2AJImVIs752h1WqsMnShSKgU011c4,10270
|
|
48
48
|
sonolus/script/instruction.py,sha256=Dd-14D5Amo8nhPBr6DNyg2lpYw_rqZkT8Kix3HkfE7k,6793
|
|
49
49
|
sonolus/script/interval.py,sha256=-1pnvRmkeBFL4qUvAKzza6h29Hce2oD2GNSUKhoP4QQ,11956
|
|
@@ -56,29 +56,29 @@ sonolus/script/options.py,sha256=05y_4j2kr8fzct5FLqmSp5ZAjnq6-slmNgtsh4fVEpg,945
|
|
|
56
56
|
sonolus/script/particle.py,sha256=3HbxehuW7Fdri3s8NenGxiwxVU7tVDH8SQ4VyCc0wMk,10498
|
|
57
57
|
sonolus/script/pointer.py,sha256=FoOfyD93r0G5d_2BaKfeOT9SqkOP3hq6sqtOs_Rb0c8,1511
|
|
58
58
|
sonolus/script/printing.py,sha256=mNYu9QWiacBBGZrnePZQMVwbbguoelUps9GiOK_aVRU,2096
|
|
59
|
-
sonolus/script/project.py,sha256=
|
|
59
|
+
sonolus/script/project.py,sha256=hAt2YLfpOPDSphnZDA0QmZbRCY4y5guuUYoj-HHQaFw,4858
|
|
60
60
|
sonolus/script/quad.py,sha256=8lZ_5-eWeqePldNGBkNZTuOgS_IRb41URgGwSW4h2T0,14445
|
|
61
|
-
sonolus/script/record.py,sha256=
|
|
61
|
+
sonolus/script/record.py,sha256=1YiGvX58gC07jsF8GIHDIZCE5kxQ92D8cwEinjBvxDk,13780
|
|
62
62
|
sonolus/script/runtime.py,sha256=IFNHmExpavyXy5Y_X1pfvulsM-VzdcI9domvuj9sunM,33325
|
|
63
63
|
sonolus/script/sprite.py,sha256=KhQNnq0wKm1tDMQTrlZIr0mL0jPCfojTORzsCK5qO1o,18448
|
|
64
|
-
sonolus/script/stream.py,sha256=
|
|
64
|
+
sonolus/script/stream.py,sha256=RoL6ntK7DCiLKb8Tw8lvtLJDZqHS525fS0NgWwQGlGU,25104
|
|
65
65
|
sonolus/script/text.py,sha256=wxujIgKYcCfl2AD2_Im8g3vh0lDEHYwTSRZg9wsBPEU,13402
|
|
66
66
|
sonolus/script/timing.py,sha256=DklMvuxcFg3MzXsecUo6Yhdk7pScOJ7STwXvAiTvLKM,3067
|
|
67
67
|
sonolus/script/transform.py,sha256=CnSQWTZxHve5CklH6VGM9CB9fJibdh0FNgJdDCsMABk,21419
|
|
68
68
|
sonolus/script/ui.py,sha256=DYPGWIjHj1IFPxW1zaEuIUQx0b32FJPXtiwCvrtJ6oo,7528
|
|
69
|
-
sonolus/script/values.py,sha256=
|
|
69
|
+
sonolus/script/values.py,sha256=dfsXfwdc_Apwka8MNDu6Gy497iduPpU3OpZYqV4tehQ,1513
|
|
70
70
|
sonolus/script/vec.py,sha256=f7keqogIQiRpuQ0dULOFCxFlmvkykoFZMFwYw9P39Kk,9319
|
|
71
71
|
sonolus/script/internal/__init__.py,sha256=T6rzLoiOUaiSQtaHMZ88SNO-ijSjSSv33TKtUwu-Ms8,136
|
|
72
|
-
sonolus/script/internal/builtin_impls.py,sha256=
|
|
72
|
+
sonolus/script/internal/builtin_impls.py,sha256=nAMHdKVSkDG_MlLk1lFgiFq66pv8RQaI_UpYOfss5ik,16674
|
|
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=
|
|
75
|
+
sonolus/script/internal/context.py,sha256=dhWQS7fFPMhb0FJyw3y--0HlBtwuYANdIYiv7u_96jk,22023
|
|
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
|
-
sonolus/script/internal/generic.py,sha256=
|
|
80
|
-
sonolus/script/internal/impl.py,sha256=
|
|
81
|
-
sonolus/script/internal/introspection.py,sha256=
|
|
79
|
+
sonolus/script/internal/generic.py,sha256=37bwcKR5xMFQnSy6fzoS8UKkwbE8Rx7tzBuC4p9T2GM,8931
|
|
80
|
+
sonolus/script/internal/impl.py,sha256=Yp4cyIRy_KWvW2VJbiLKejcQbDBoJZ7jzgEoC92lUCA,3715
|
|
81
|
+
sonolus/script/internal/introspection.py,sha256=OP1eCtchdw_nBjUhVBaO2tDj9-stjhwnAvHZpoHCxFk,1508
|
|
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
|
|
84
84
|
sonolus/script/internal/random.py,sha256=6Ku5edRcDUh7rtqEEYCJz0BQavw69RALsVHS25z50pI,1695
|
|
@@ -87,8 +87,8 @@ sonolus/script/internal/simulation_context.py,sha256=LGxLTvxbqBIhoe1R-SfwGajNIDw
|
|
|
87
87
|
sonolus/script/internal/transient.py,sha256=y2AWABqF1aoaP6H4_2u4MMpNioC4OsZQCtPyNI0txqo,1634
|
|
88
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.
|
|
91
|
-
sonolus_py-0.
|
|
92
|
-
sonolus_py-0.
|
|
93
|
-
sonolus_py-0.
|
|
94
|
-
sonolus_py-0.
|
|
90
|
+
sonolus_py-0.12.5.dist-info/METADATA,sha256=jvZNhekacnG-TeRXmA4mjV1fewfG0bsNyHGIhRoZLQw,556
|
|
91
|
+
sonolus_py-0.12.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
92
|
+
sonolus_py-0.12.5.dist-info/entry_points.txt,sha256=oTYspY_b7SA8TptEMTDxh4-Aj-ZVPnYC9f1lqH6s9G4,54
|
|
93
|
+
sonolus_py-0.12.5.dist-info/licenses/LICENSE,sha256=JEKpqVhQYfEc7zg3Mj462sKbKYmO1K7WmvX1qvg9IJk,1067
|
|
94
|
+
sonolus_py-0.12.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|