sonolus.py 0.1.3__py3-none-any.whl → 0.1.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of sonolus.py might be problematic. Click here for more details.
- sonolus/backend/blocks.py +756 -756
- sonolus/backend/excepthook.py +37 -37
- sonolus/backend/finalize.py +77 -69
- sonolus/backend/interpret.py +7 -7
- sonolus/backend/ir.py +29 -3
- sonolus/backend/mode.py +24 -24
- sonolus/backend/node.py +40 -40
- sonolus/backend/ops.py +197 -197
- sonolus/backend/optimize/__init__.py +0 -0
- sonolus/backend/optimize/allocate.py +126 -0
- sonolus/backend/optimize/constant_evaluation.py +374 -0
- sonolus/backend/optimize/copy_coalesce.py +85 -0
- sonolus/backend/optimize/dead_code.py +185 -0
- sonolus/backend/optimize/dominance.py +96 -0
- sonolus/backend/{flow.py → optimize/flow.py} +122 -92
- sonolus/backend/optimize/inlining.py +137 -0
- sonolus/backend/optimize/liveness.py +177 -0
- sonolus/backend/optimize/optimize.py +44 -0
- sonolus/backend/optimize/passes.py +52 -0
- sonolus/backend/optimize/simplify.py +191 -0
- sonolus/backend/optimize/ssa.py +200 -0
- sonolus/backend/place.py +17 -25
- sonolus/backend/utils.py +58 -48
- sonolus/backend/visitor.py +1151 -882
- sonolus/build/cli.py +7 -1
- sonolus/build/compile.py +88 -90
- sonolus/build/engine.py +10 -5
- sonolus/build/level.py +24 -23
- sonolus/build/node.py +43 -43
- sonolus/script/archetype.py +438 -139
- sonolus/script/array.py +27 -10
- sonolus/script/array_like.py +297 -0
- sonolus/script/bucket.py +253 -191
- sonolus/script/containers.py +257 -51
- sonolus/script/debug.py +26 -10
- sonolus/script/easing.py +365 -0
- sonolus/script/effect.py +191 -131
- sonolus/script/engine.py +71 -4
- sonolus/script/globals.py +303 -269
- sonolus/script/instruction.py +205 -151
- sonolus/script/internal/__init__.py +5 -5
- sonolus/script/internal/builtin_impls.py +255 -144
- sonolus/script/{callbacks.py → internal/callbacks.py} +127 -127
- sonolus/script/internal/constant.py +139 -0
- sonolus/script/internal/context.py +26 -9
- sonolus/script/internal/descriptor.py +17 -17
- sonolus/script/internal/dict_impl.py +65 -0
- sonolus/script/internal/generic.py +6 -9
- sonolus/script/internal/impl.py +38 -13
- sonolus/script/internal/introspection.py +17 -14
- sonolus/script/internal/math_impls.py +121 -0
- sonolus/script/internal/native.py +40 -38
- sonolus/script/internal/random.py +67 -0
- sonolus/script/internal/range.py +81 -0
- sonolus/script/internal/transient.py +51 -0
- sonolus/script/internal/tuple_impl.py +113 -0
- sonolus/script/internal/value.py +3 -3
- sonolus/script/interval.py +338 -112
- sonolus/script/iterator.py +167 -214
- sonolus/script/level.py +24 -0
- sonolus/script/num.py +80 -48
- sonolus/script/options.py +257 -191
- sonolus/script/particle.py +190 -157
- sonolus/script/pointer.py +30 -30
- sonolus/script/print.py +102 -81
- sonolus/script/project.py +8 -0
- sonolus/script/quad.py +263 -0
- sonolus/script/record.py +47 -16
- sonolus/script/runtime.py +52 -1
- sonolus/script/sprite.py +418 -333
- sonolus/script/text.py +409 -407
- sonolus/script/timing.py +114 -42
- sonolus/script/transform.py +332 -48
- sonolus/script/ui.py +216 -160
- sonolus/script/values.py +6 -13
- sonolus/script/vec.py +196 -78
- {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.5.dist-info}/METADATA +1 -1
- sonolus_py-0.1.5.dist-info/RECORD +89 -0
- {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.5.dist-info}/WHEEL +1 -1
- {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.5.dist-info}/licenses/LICENSE +21 -21
- sonolus/backend/allocate.py +0 -51
- sonolus/backend/optimize.py +0 -9
- sonolus/backend/passes.py +0 -6
- sonolus/backend/simplify.py +0 -30
- sonolus/script/comptime.py +0 -160
- sonolus/script/graphics.py +0 -150
- sonolus/script/math.py +0 -92
- sonolus/script/range.py +0 -58
- sonolus_py-0.1.3.dist-info/RECORD +0 -75
- {sonolus_py-0.1.3.dist-info → sonolus_py-0.1.5.dist-info}/entry_points.txt +0 -0
sonolus/script/options.py
CHANGED
|
@@ -1,191 +1,257 @@
|
|
|
1
|
-
# ruff: noqa: A002
|
|
2
|
-
from dataclasses import dataclass
|
|
3
|
-
from typing import Annotated, Any, NewType, dataclass_transform, get_origin
|
|
4
|
-
|
|
5
|
-
from sonolus.backend.mode import Mode
|
|
6
|
-
from sonolus.backend.place import BlockPlace
|
|
7
|
-
from sonolus.script.debug import assert_unreachable
|
|
8
|
-
from sonolus.script.internal.context import ctx
|
|
9
|
-
from sonolus.script.internal.descriptor import SonolusDescriptor
|
|
10
|
-
from sonolus.script.internal.generic import validate_concrete_type
|
|
11
|
-
from sonolus.script.internal.introspection import get_field_specifiers
|
|
12
|
-
from sonolus.script.num import Num
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@dataclass
|
|
16
|
-
class
|
|
17
|
-
name: str | None
|
|
18
|
-
standard: bool
|
|
19
|
-
advanced: bool
|
|
20
|
-
scope: str | None
|
|
21
|
-
default: float
|
|
22
|
-
min: float
|
|
23
|
-
max: float
|
|
24
|
-
step: float
|
|
25
|
-
unit: str | None
|
|
26
|
-
|
|
27
|
-
def to_dict(self):
|
|
28
|
-
result = {
|
|
29
|
-
"type": "slider",
|
|
30
|
-
"name": self.name,
|
|
31
|
-
"standard": self.standard,
|
|
32
|
-
"advanced": self.advanced,
|
|
33
|
-
"def": self.default,
|
|
34
|
-
"min": self.min,
|
|
35
|
-
"max": self.max,
|
|
36
|
-
"step": self.step,
|
|
37
|
-
}
|
|
38
|
-
if self.scope is not None:
|
|
39
|
-
result["scope"] = self.scope
|
|
40
|
-
if self.unit is not None:
|
|
41
|
-
result["unit"] = self.unit
|
|
42
|
-
return result
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
@dataclass
|
|
46
|
-
class
|
|
47
|
-
name: str | None
|
|
48
|
-
standard: bool
|
|
49
|
-
advanced: bool
|
|
50
|
-
scope: str | None
|
|
51
|
-
default: bool
|
|
52
|
-
|
|
53
|
-
def to_dict(self):
|
|
54
|
-
result = {
|
|
55
|
-
"type": "toggle",
|
|
56
|
-
"name": self.name,
|
|
57
|
-
"standard": self.standard,
|
|
58
|
-
"advanced": self.advanced,
|
|
59
|
-
"def": int(self.default),
|
|
60
|
-
}
|
|
61
|
-
if self.scope is not None:
|
|
62
|
-
result["scope"] = self.scope
|
|
63
|
-
return result
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
@dataclass
|
|
67
|
-
class
|
|
68
|
-
name: str | None
|
|
69
|
-
standard: bool
|
|
70
|
-
advanced: bool
|
|
71
|
-
scope: str | None
|
|
72
|
-
default: str
|
|
73
|
-
values: list[str]
|
|
74
|
-
|
|
75
|
-
def to_dict(self):
|
|
76
|
-
result = {
|
|
77
|
-
"type": "select",
|
|
78
|
-
"name": self.name,
|
|
79
|
-
"standard": self.standard,
|
|
80
|
-
"advanced": self.advanced,
|
|
81
|
-
"def": self.values.index(self.default),
|
|
82
|
-
"values": self.values,
|
|
83
|
-
}
|
|
84
|
-
if self.scope is not None:
|
|
85
|
-
result["scope"] = self.scope
|
|
86
|
-
return result
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
def slider_option(
|
|
90
|
-
*,
|
|
91
|
-
name: str | None = None,
|
|
92
|
-
standard: bool = False,
|
|
93
|
-
advanced: bool = False,
|
|
94
|
-
default: float,
|
|
95
|
-
min: float,
|
|
96
|
-
max: float,
|
|
97
|
-
step: float,
|
|
98
|
-
unit: str | None = None,
|
|
99
|
-
scope: str | None = None,
|
|
100
|
-
) -> Any:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
1
|
+
# ruff: noqa: A002
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import Annotated, Any, NewType, dataclass_transform, get_origin
|
|
4
|
+
|
|
5
|
+
from sonolus.backend.mode import Mode
|
|
6
|
+
from sonolus.backend.place import BlockPlace
|
|
7
|
+
from sonolus.script.debug import assert_unreachable
|
|
8
|
+
from sonolus.script.internal.context import ctx
|
|
9
|
+
from sonolus.script.internal.descriptor import SonolusDescriptor
|
|
10
|
+
from sonolus.script.internal.generic import validate_concrete_type
|
|
11
|
+
from sonolus.script.internal.introspection import get_field_specifiers
|
|
12
|
+
from sonolus.script.num import Num
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class _SliderOption:
|
|
17
|
+
name: str | None
|
|
18
|
+
standard: bool
|
|
19
|
+
advanced: bool
|
|
20
|
+
scope: str | None
|
|
21
|
+
default: float
|
|
22
|
+
min: float
|
|
23
|
+
max: float
|
|
24
|
+
step: float
|
|
25
|
+
unit: str | None
|
|
26
|
+
|
|
27
|
+
def to_dict(self):
|
|
28
|
+
result = {
|
|
29
|
+
"type": "slider",
|
|
30
|
+
"name": self.name,
|
|
31
|
+
"standard": self.standard,
|
|
32
|
+
"advanced": self.advanced,
|
|
33
|
+
"def": self.default,
|
|
34
|
+
"min": self.min,
|
|
35
|
+
"max": self.max,
|
|
36
|
+
"step": self.step,
|
|
37
|
+
}
|
|
38
|
+
if self.scope is not None:
|
|
39
|
+
result["scope"] = self.scope
|
|
40
|
+
if self.unit is not None:
|
|
41
|
+
result["unit"] = self.unit
|
|
42
|
+
return result
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass
|
|
46
|
+
class _ToggleOption:
|
|
47
|
+
name: str | None
|
|
48
|
+
standard: bool
|
|
49
|
+
advanced: bool
|
|
50
|
+
scope: str | None
|
|
51
|
+
default: bool
|
|
52
|
+
|
|
53
|
+
def to_dict(self):
|
|
54
|
+
result = {
|
|
55
|
+
"type": "toggle",
|
|
56
|
+
"name": self.name,
|
|
57
|
+
"standard": self.standard,
|
|
58
|
+
"advanced": self.advanced,
|
|
59
|
+
"def": int(self.default),
|
|
60
|
+
}
|
|
61
|
+
if self.scope is not None:
|
|
62
|
+
result["scope"] = self.scope
|
|
63
|
+
return result
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dataclass
|
|
67
|
+
class _SelectOption:
|
|
68
|
+
name: str | None
|
|
69
|
+
standard: bool
|
|
70
|
+
advanced: bool
|
|
71
|
+
scope: str | None
|
|
72
|
+
default: str
|
|
73
|
+
values: list[str]
|
|
74
|
+
|
|
75
|
+
def to_dict(self):
|
|
76
|
+
result = {
|
|
77
|
+
"type": "select",
|
|
78
|
+
"name": self.name,
|
|
79
|
+
"standard": self.standard,
|
|
80
|
+
"advanced": self.advanced,
|
|
81
|
+
"def": self.values.index(self.default),
|
|
82
|
+
"values": self.values,
|
|
83
|
+
}
|
|
84
|
+
if self.scope is not None:
|
|
85
|
+
result["scope"] = self.scope
|
|
86
|
+
return result
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def slider_option(
|
|
90
|
+
*,
|
|
91
|
+
name: str | None = None,
|
|
92
|
+
standard: bool = False,
|
|
93
|
+
advanced: bool = False,
|
|
94
|
+
default: float,
|
|
95
|
+
min: float,
|
|
96
|
+
max: float,
|
|
97
|
+
step: float,
|
|
98
|
+
unit: str | None = None,
|
|
99
|
+
scope: str | None = None,
|
|
100
|
+
) -> Any:
|
|
101
|
+
"""Define a slider option.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
name: The name of the option.
|
|
105
|
+
standard: Whether the option is standard.
|
|
106
|
+
advanced: Whether the option is advanced.
|
|
107
|
+
default: The default value of the option.
|
|
108
|
+
min: The minimum value of the option.
|
|
109
|
+
max: The maximum value of the option.
|
|
110
|
+
step: The step value of the option.
|
|
111
|
+
unit: The unit of the option.
|
|
112
|
+
scope: The scope of the option.
|
|
113
|
+
"""
|
|
114
|
+
return _SliderOption(name, standard, advanced, scope, default, min, max, step, unit)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def toggle_option(
|
|
118
|
+
*,
|
|
119
|
+
name: str | None = None,
|
|
120
|
+
standard: bool = False,
|
|
121
|
+
advanced: bool = False,
|
|
122
|
+
default: bool,
|
|
123
|
+
scope: str | None = None,
|
|
124
|
+
) -> Any:
|
|
125
|
+
"""Define a toggle option.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
name: The name of the option.
|
|
129
|
+
standard: Whether the option is standard.
|
|
130
|
+
advanced: Whether the option is advanced.
|
|
131
|
+
default: The default value of the option.
|
|
132
|
+
scope: The scope of the option.
|
|
133
|
+
"""
|
|
134
|
+
return _ToggleOption(name, standard, advanced, scope, default)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def select_option(
|
|
138
|
+
*,
|
|
139
|
+
name: str | None = None,
|
|
140
|
+
standard: bool = False,
|
|
141
|
+
advanced: bool = False,
|
|
142
|
+
default: str,
|
|
143
|
+
values: list[str],
|
|
144
|
+
scope: str | None = None,
|
|
145
|
+
) -> Any:
|
|
146
|
+
"""Define a select option.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
name: The name of the option.
|
|
150
|
+
standard: Whether the option is standard.
|
|
151
|
+
advanced: Whether the option is advanced.
|
|
152
|
+
default: The default value of the option.
|
|
153
|
+
values: The values of the option.
|
|
154
|
+
scope: The scope of the option.
|
|
155
|
+
"""
|
|
156
|
+
return _SelectOption(name, standard, advanced, scope, default, values)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
type Options = NewType("Options", Any)
|
|
160
|
+
type _OptionInfo = _SliderOption | _ToggleOption | _SelectOption
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class _OptionField(SonolusDescriptor):
|
|
164
|
+
info: _OptionInfo
|
|
165
|
+
index: int
|
|
166
|
+
|
|
167
|
+
def __init__(self, info: _OptionInfo, index: int):
|
|
168
|
+
self.info = info
|
|
169
|
+
self.index = index
|
|
170
|
+
|
|
171
|
+
def __get__(self, instance, owner):
|
|
172
|
+
if ctx():
|
|
173
|
+
match ctx().global_state.mode:
|
|
174
|
+
case Mode.PLAY:
|
|
175
|
+
block = ctx().blocks.LevelOption
|
|
176
|
+
case Mode.WATCH:
|
|
177
|
+
block = ctx().blocks.LevelOption
|
|
178
|
+
case Mode.PREVIEW:
|
|
179
|
+
block = ctx().blocks.PreviewOption
|
|
180
|
+
case Mode.TUTORIAL:
|
|
181
|
+
block = None
|
|
182
|
+
case _:
|
|
183
|
+
assert_unreachable()
|
|
184
|
+
if block is not None:
|
|
185
|
+
return Num._from_place_(BlockPlace(block, self.index))
|
|
186
|
+
else:
|
|
187
|
+
return Num._accept_(self.info.default)
|
|
188
|
+
|
|
189
|
+
def __set__(self, instance, value):
|
|
190
|
+
raise AttributeError("Options are read-only")
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
@dataclass_transform()
|
|
194
|
+
def options[T](cls: type[T]) -> T | Options:
|
|
195
|
+
"""Decorator to define options.
|
|
196
|
+
|
|
197
|
+
Usage:
|
|
198
|
+
```python
|
|
199
|
+
@options
|
|
200
|
+
class Options:
|
|
201
|
+
slider_option: float = slider_option(
|
|
202
|
+
name='Slider Option',
|
|
203
|
+
standard=True,
|
|
204
|
+
advanced=False,
|
|
205
|
+
default=0.5,
|
|
206
|
+
min=0,
|
|
207
|
+
max=1,
|
|
208
|
+
step=0.1,
|
|
209
|
+
unit='unit',
|
|
210
|
+
scope='scope',
|
|
211
|
+
)
|
|
212
|
+
toggle_option: bool = toggle_option(
|
|
213
|
+
name='Toggle Option',
|
|
214
|
+
standard=True,
|
|
215
|
+
advanced=False,
|
|
216
|
+
default=True,
|
|
217
|
+
scope='scope',
|
|
218
|
+
)
|
|
219
|
+
select_option: int = select_option(
|
|
220
|
+
name='Select Option',
|
|
221
|
+
standard=True,
|
|
222
|
+
advanced=False,
|
|
223
|
+
default='value',
|
|
224
|
+
values=['value'],
|
|
225
|
+
scope='scope',
|
|
226
|
+
)
|
|
227
|
+
```
|
|
228
|
+
"""
|
|
229
|
+
if len(cls.__bases__) != 1:
|
|
230
|
+
raise ValueError("Options class must not inherit from any class (except object)")
|
|
231
|
+
instance = cls()
|
|
232
|
+
entries = []
|
|
233
|
+
for i, (name, annotation) in enumerate(get_field_specifiers(cls).items()):
|
|
234
|
+
if get_origin(annotation) is not Annotated:
|
|
235
|
+
raise TypeError(f"Invalid annotation for options: {annotation}")
|
|
236
|
+
annotation_type = annotation.__args__[0]
|
|
237
|
+
annotation_values = annotation.__metadata__
|
|
238
|
+
if len(annotation_values) != 1:
|
|
239
|
+
raise ValueError("Invalid annotation values for options")
|
|
240
|
+
annotation_type = validate_concrete_type(annotation_type)
|
|
241
|
+
if annotation_type is not Num:
|
|
242
|
+
raise TypeError(f"Invalid annotation type for options: {annotation_type}")
|
|
243
|
+
annotation_value = annotation_values[0]
|
|
244
|
+
if not isinstance(annotation_value, _SliderOption | _ToggleOption | _SelectOption):
|
|
245
|
+
raise TypeError(f"Invalid annotation value for options: {annotation_value}")
|
|
246
|
+
if annotation_value.name is None:
|
|
247
|
+
annotation_value.name = name
|
|
248
|
+
entries.append(annotation_value)
|
|
249
|
+
setattr(cls, name, _OptionField(annotation_value, i))
|
|
250
|
+
instance._options_ = entries
|
|
251
|
+
instance._is_comptime_value_ = True
|
|
252
|
+
return instance
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
@options
|
|
256
|
+
class EmptyOptions:
|
|
257
|
+
pass
|