sonolus.py 0.1.4__py3-none-any.whl → 0.1.6__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 +18 -10
- sonolus/backend/interpret.py +7 -7
- sonolus/backend/ir.py +24 -0
- sonolus/backend/optimize/__init__.py +0 -0
- sonolus/backend/{allocate.py → optimize/allocate.py} +4 -3
- sonolus/backend/{constant_evaluation.py → optimize/constant_evaluation.py} +7 -7
- sonolus/backend/{coalesce.py → optimize/copy_coalesce.py} +3 -3
- sonolus/backend/optimize/dead_code.py +185 -0
- sonolus/backend/{dominance.py → optimize/dominance.py} +2 -17
- sonolus/backend/{flow.py → optimize/flow.py} +6 -5
- sonolus/backend/{inlining.py → optimize/inlining.py} +4 -17
- sonolus/backend/{liveness.py → optimize/liveness.py} +69 -65
- sonolus/backend/optimize/optimize.py +44 -0
- sonolus/backend/{passes.py → optimize/passes.py} +1 -1
- sonolus/backend/optimize/simplify.py +191 -0
- sonolus/backend/{ssa.py → optimize/ssa.py} +31 -18
- sonolus/backend/place.py +17 -25
- sonolus/backend/utils.py +10 -0
- sonolus/backend/visitor.py +360 -101
- sonolus/build/cli.py +14 -3
- sonolus/build/compile.py +8 -8
- sonolus/build/engine.py +10 -5
- sonolus/build/project.py +30 -1
- sonolus/script/archetype.py +429 -138
- sonolus/script/array.py +25 -8
- sonolus/script/array_like.py +297 -0
- sonolus/script/bucket.py +73 -11
- sonolus/script/containers.py +234 -51
- sonolus/script/debug.py +8 -8
- sonolus/script/easing.py +147 -105
- sonolus/script/effect.py +60 -0
- sonolus/script/engine.py +71 -4
- sonolus/script/globals.py +66 -32
- sonolus/script/instruction.py +79 -25
- sonolus/script/internal/builtin_impls.py +138 -27
- sonolus/script/internal/constant.py +139 -0
- sonolus/script/internal/context.py +14 -5
- 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 +5 -2
- sonolus/script/{math.py → internal/math_impls.py} +28 -28
- sonolus/script/internal/native.py +3 -3
- 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/interval.py +234 -16
- sonolus/script/iterator.py +120 -167
- sonolus/script/level.py +24 -0
- sonolus/script/num.py +79 -47
- sonolus/script/options.py +78 -12
- sonolus/script/particle.py +37 -4
- sonolus/script/pointer.py +4 -4
- sonolus/script/print.py +22 -1
- sonolus/script/project.py +59 -0
- sonolus/script/{graphics.py → quad.py} +75 -12
- sonolus/script/record.py +44 -13
- sonolus/script/runtime.py +50 -1
- sonolus/script/sprite.py +198 -115
- sonolus/script/text.py +2 -0
- sonolus/script/timing.py +72 -0
- sonolus/script/transform.py +296 -66
- sonolus/script/ui.py +134 -78
- sonolus/script/values.py +6 -13
- sonolus/script/vec.py +118 -3
- {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.6.dist-info}/METADATA +1 -1
- sonolus_py-0.1.6.dist-info/RECORD +89 -0
- sonolus/backend/dead_code.py +0 -80
- sonolus/backend/optimize.py +0 -37
- sonolus/backend/simplify.py +0 -47
- sonolus/script/comptime.py +0 -160
- sonolus/script/random.py +0 -14
- sonolus/script/range.py +0 -58
- sonolus_py-0.1.4.dist-info/RECORD +0 -84
- /sonolus/script/{callbacks.py → internal/callbacks.py} +0 -0
- {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.6.dist-info}/WHEEL +0 -0
- {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.6.dist-info}/entry_points.txt +0 -0
- {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.6.dist-info}/licenses/LICENSE +0 -0
sonolus/script/ui.py
CHANGED
|
@@ -1,81 +1,102 @@
|
|
|
1
1
|
from dataclasses import dataclass, field
|
|
2
|
-
from
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
|
|
2
|
+
from enum import StrEnum
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class UiMetric(StrEnum):
|
|
6
|
+
"""A metric to display on the UI."""
|
|
7
|
+
|
|
8
|
+
ARCADE = "arcade"
|
|
9
|
+
ARCADE_PERCENTAGE = "arcadePercentage"
|
|
10
|
+
ACCURACY = "accuracy"
|
|
11
|
+
ACCURACY_PERCENTAGE = "accuracyPercentage"
|
|
12
|
+
LIFE = "life"
|
|
13
|
+
PERFECT = "perfect"
|
|
14
|
+
PERFECT_PERCENTAGE = "perfectPercentage"
|
|
15
|
+
GREAT_GOOD_MISS = "greatGoodMiss"
|
|
16
|
+
GREAT_GOOD_MISS_PERCENTAGE = "greatGoodMissPercentage"
|
|
17
|
+
MISS = "miss"
|
|
18
|
+
MISS_PERCENTAGE = "missPercentage"
|
|
19
|
+
ERROR_HEATMAP = "errorHeatmap"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class UiJudgmentErrorStyle(StrEnum):
|
|
23
|
+
"""The style of the judgment error."""
|
|
24
|
+
|
|
25
|
+
NONE = "none"
|
|
26
|
+
PLUS = "plus"
|
|
27
|
+
MINUS = "minus"
|
|
28
|
+
ARROW_UP = "arrowUp"
|
|
29
|
+
ARROW_DOWN = "arrowDown"
|
|
30
|
+
ARROW_LEFT = "arrowLeft"
|
|
31
|
+
ARROW_RIGHT = "arrowRight"
|
|
32
|
+
TRIANGLE_UP = "triangleUp"
|
|
33
|
+
TRIANGLE_DOWN = "triangleDown"
|
|
34
|
+
TRIANGLE_LEFT = "triangleLeft"
|
|
35
|
+
TRIANGLE_RIGHT = "triangleRight"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class UiJudgmentErrorPlacement(StrEnum):
|
|
39
|
+
"""The placement of the judgment error."""
|
|
40
|
+
|
|
41
|
+
BOTH = "both"
|
|
42
|
+
LEFT = "left"
|
|
43
|
+
RIGHT = "right"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class EaseType(StrEnum):
|
|
47
|
+
"""The easing function to use."""
|
|
48
|
+
|
|
49
|
+
LINEAR = "linear"
|
|
50
|
+
NONE = "none"
|
|
51
|
+
IN_SINE = "inSine"
|
|
52
|
+
IN_QUAD = "inQuad"
|
|
53
|
+
IN_CUBIC = "inCubic"
|
|
54
|
+
IN_QUART = "inQuart"
|
|
55
|
+
IN_QUINT = "inQuint"
|
|
56
|
+
IN_EXPO = "inExpo"
|
|
57
|
+
IN_CIRC = "inCirc"
|
|
58
|
+
IN_BACK = "inBack"
|
|
59
|
+
IN_ELASTIC = "inElastic"
|
|
60
|
+
OUT_SINE = "outSine"
|
|
61
|
+
OUT_QUAD = "outQuad"
|
|
62
|
+
OUT_CUBIC = "outCubic"
|
|
63
|
+
OUT_QUART = "outQuart"
|
|
64
|
+
OUT_QUINT = "outQuint"
|
|
65
|
+
OUT_EXPO = "outExpo"
|
|
66
|
+
OUT_CIRC = "outCirc"
|
|
67
|
+
OUT_BACK = "outBack"
|
|
68
|
+
OUT_ELASTIC = "outElastic"
|
|
69
|
+
IN_OUT_SINE = "inOutSine"
|
|
70
|
+
IN_OUT_QUAD = "inOutQuad"
|
|
71
|
+
IN_OUT_CUBIC = "inOutCubic"
|
|
72
|
+
IN_OUT_QUART = "inOutQuart"
|
|
73
|
+
IN_OUT_QUINT = "inOutQuint"
|
|
74
|
+
IN_OUT_EXPO = "inOutExpo"
|
|
75
|
+
IN_OUT_CIRC = "inOutCirc"
|
|
76
|
+
IN_OUT_BACK = "inOutBack"
|
|
77
|
+
IN_OUT_ELASTIC = "inOutElastic"
|
|
78
|
+
OUT_IN_SINE = "outInSine"
|
|
79
|
+
OUT_IN_QUAD = "outInQuad"
|
|
80
|
+
OUT_IN_CUBIC = "outInCubic"
|
|
81
|
+
OUT_IN_QUART = "outInQuart"
|
|
82
|
+
OUT_IN_QUINT = "outInQuint"
|
|
83
|
+
OUT_IN_EXPO = "outInExpo"
|
|
84
|
+
OUT_IN_CIRC = "outInCirc"
|
|
85
|
+
OUT_IN_BACK = "outInBack"
|
|
86
|
+
OUT_IN_ELASTIC = "outInElastic"
|
|
75
87
|
|
|
76
88
|
|
|
77
89
|
@dataclass
|
|
78
90
|
class UiAnimationTween:
|
|
91
|
+
"""Tween animation configuration for UI elements.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
start: The initial value.
|
|
95
|
+
end: The final value.
|
|
96
|
+
duration: The duration of the animation.
|
|
97
|
+
ease: The easing function to use.
|
|
98
|
+
"""
|
|
99
|
+
|
|
79
100
|
start: float
|
|
80
101
|
end: float
|
|
81
102
|
duration: float
|
|
@@ -92,6 +113,13 @@ class UiAnimationTween:
|
|
|
92
113
|
|
|
93
114
|
@dataclass
|
|
94
115
|
class UiAnimation:
|
|
116
|
+
"""Animation configuration for UI elements.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
scale: The animation applied to scale.
|
|
120
|
+
alpha: The animation applied to alpha.
|
|
121
|
+
"""
|
|
122
|
+
|
|
95
123
|
scale: UiAnimationTween = field(default_factory=lambda: UiAnimationTween(1, 1, 0, "none"))
|
|
96
124
|
alpha: UiAnimationTween = field(default_factory=lambda: UiAnimationTween(1, 0, 0.2, "outCubic"))
|
|
97
125
|
|
|
@@ -104,6 +132,13 @@ class UiAnimation:
|
|
|
104
132
|
|
|
105
133
|
@dataclass
|
|
106
134
|
class UiVisibility:
|
|
135
|
+
"""Visibility configuration for UI elements.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
scale: The scale of the element.
|
|
139
|
+
alpha: The alpha of the element.
|
|
140
|
+
"""
|
|
141
|
+
|
|
107
142
|
scale: float = 1.0
|
|
108
143
|
alpha: float = 1.0
|
|
109
144
|
|
|
@@ -116,9 +151,30 @@ class UiVisibility:
|
|
|
116
151
|
|
|
117
152
|
@dataclass
|
|
118
153
|
class UiConfig:
|
|
154
|
+
"""Configuration for UI elements.
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
scope: The scope of the configuration.
|
|
158
|
+
primary_metric: The primary metric to display.
|
|
159
|
+
secondary_metric: The secondary metric to display.
|
|
160
|
+
menu_visibility: The visibility configuration for the menu.
|
|
161
|
+
judgment_visibility: The visibility configuration for judgments.
|
|
162
|
+
combo_visibility: The visibility configuration for the combo.
|
|
163
|
+
primary_metric_visibility: The visibility configuration for the primary metric.
|
|
164
|
+
secondary_metric_visibility: The visibility configuration for the secondary metric.
|
|
165
|
+
progress_visibility: The visibility configuration for progress.
|
|
166
|
+
tutorial_navigation_visibility: The visibility configuration for tutorial navigation.
|
|
167
|
+
tutorial_instruction_visibility: The visibility configuration for tutorial instructions.
|
|
168
|
+
judgment_animation: The animation configuration for judgments.
|
|
169
|
+
combo_animation: The animation configuration for the combo.
|
|
170
|
+
judgment_error_style: The style of the judgment error.
|
|
171
|
+
judgment_error_placement: The placement of the judgment error.
|
|
172
|
+
judgment_error_min: The minimum judgment error.
|
|
173
|
+
"""
|
|
174
|
+
|
|
119
175
|
scope: str | None = None
|
|
120
|
-
primary_metric: UiMetric =
|
|
121
|
-
secondary_metric: UiMetric =
|
|
176
|
+
primary_metric: UiMetric = UiMetric.ARCADE
|
|
177
|
+
secondary_metric: UiMetric = UiMetric.LIFE
|
|
122
178
|
menu_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
123
179
|
judgment_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
124
180
|
combo_visibility: UiVisibility = field(default_factory=UiVisibility)
|
|
@@ -130,11 +186,11 @@ class UiConfig:
|
|
|
130
186
|
judgment_animation: UiAnimation = field(default_factory=UiAnimation)
|
|
131
187
|
combo_animation: UiAnimation = field(
|
|
132
188
|
default_factory=lambda: UiAnimation(
|
|
133
|
-
scale=UiAnimationTween(1.2, 1, 0.2,
|
|
189
|
+
scale=UiAnimationTween(1.2, 1, 0.2, EaseType.IN_CUBIC), alpha=UiAnimationTween(1, 1, 0, EaseType.NONE)
|
|
134
190
|
)
|
|
135
191
|
)
|
|
136
|
-
judgment_error_style: UiJudgmentErrorStyle =
|
|
137
|
-
judgment_error_placement: UiJudgmentErrorPlacement =
|
|
192
|
+
judgment_error_style: UiJudgmentErrorStyle = UiJudgmentErrorStyle.NONE
|
|
193
|
+
judgment_error_placement: UiJudgmentErrorPlacement = UiJudgmentErrorPlacement.BOTH
|
|
138
194
|
judgment_error_min: float = 0.0
|
|
139
195
|
|
|
140
196
|
def to_dict(self):
|
sonolus/script/values.py
CHANGED
|
@@ -5,7 +5,10 @@ from sonolus.script.internal.impl import meta_fn, validate_value
|
|
|
5
5
|
|
|
6
6
|
@meta_fn
|
|
7
7
|
def alloc[T](type_: type[T]) -> T:
|
|
8
|
-
"""
|
|
8
|
+
"""Return an uninitialized instance of the given type.
|
|
9
|
+
|
|
10
|
+
Use this carefully as reading from uninitialized memory can lead to unexpected behavior.
|
|
11
|
+
"""
|
|
9
12
|
type_ = validate_concrete_type(type_)
|
|
10
13
|
if ctx():
|
|
11
14
|
return type_._alloc_()
|
|
@@ -15,7 +18,7 @@ def alloc[T](type_: type[T]) -> T:
|
|
|
15
18
|
|
|
16
19
|
@meta_fn
|
|
17
20
|
def zeros[T](type_: type[T]) -> T:
|
|
18
|
-
"""
|
|
21
|
+
"""Make a new instance of the given type initialized with zeros."""
|
|
19
22
|
type_ = validate_concrete_type(type_)
|
|
20
23
|
if ctx():
|
|
21
24
|
return copy(type_._from_list_([0] * type_._size_()))
|
|
@@ -25,19 +28,9 @@ def zeros[T](type_: type[T]) -> T:
|
|
|
25
28
|
|
|
26
29
|
@meta_fn
|
|
27
30
|
def copy[T](value: T) -> T:
|
|
28
|
-
"""
|
|
31
|
+
"""Make a deep copy of the given value."""
|
|
29
32
|
value = validate_value(value)
|
|
30
33
|
if ctx():
|
|
31
34
|
return value._copy_()
|
|
32
35
|
else:
|
|
33
36
|
return value._copy_()._as_py_()
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
@meta_fn
|
|
37
|
-
def with_default[T](value: T, default: T) -> T:
|
|
38
|
-
"""Returns the given value if it's not None, otherwise the default value."""
|
|
39
|
-
value = validate_value(value)
|
|
40
|
-
default = validate_value(default)
|
|
41
|
-
if value._is_py_() and value._as_py_() is None:
|
|
42
|
-
return default
|
|
43
|
-
return value
|
sonolus/script/vec.py
CHANGED
|
@@ -1,81 +1,196 @@
|
|
|
1
|
+
from math import atan2, cos, sin
|
|
1
2
|
from typing import Self
|
|
2
3
|
|
|
3
|
-
from sonolus.script.math import atan2, cos, sin
|
|
4
4
|
from sonolus.script.num import Num
|
|
5
5
|
from sonolus.script.record import Record
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class Vec2(Record):
|
|
9
|
+
"""A 2D vector.
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
```python
|
|
13
|
+
Vec2(x: float, y: float)
|
|
14
|
+
```
|
|
15
|
+
"""
|
|
16
|
+
|
|
9
17
|
x: float
|
|
10
18
|
y: float
|
|
11
19
|
|
|
12
20
|
@classmethod
|
|
13
21
|
def zero(cls) -> Self:
|
|
22
|
+
"""Return a vector with x and y set to 0.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
A new vector with x=0 and y=0.
|
|
26
|
+
"""
|
|
14
27
|
return cls(x=0, y=0)
|
|
15
28
|
|
|
16
29
|
@classmethod
|
|
17
30
|
def one(cls) -> Self:
|
|
31
|
+
"""Return a vector with x and y set to 1.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
A new vector with x=1 and y=1.
|
|
35
|
+
"""
|
|
18
36
|
return cls(x=1, y=1)
|
|
19
37
|
|
|
20
38
|
@classmethod
|
|
21
39
|
def up(cls) -> Self:
|
|
40
|
+
"""Return a vector pointing upwards (x=0, y=1).
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
A new vector pointing upwards.
|
|
44
|
+
"""
|
|
22
45
|
return cls(x=0, y=1)
|
|
23
46
|
|
|
24
47
|
@classmethod
|
|
25
48
|
def down(cls) -> Self:
|
|
49
|
+
"""Return a vector pointing downwards (x=0, y=-1).
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
A new vector pointing downwards.
|
|
53
|
+
"""
|
|
26
54
|
return cls(x=0, y=-1)
|
|
27
55
|
|
|
28
56
|
@classmethod
|
|
29
57
|
def left(cls) -> Self:
|
|
58
|
+
"""Return a vector pointing to the left (x=-1, y=0).
|
|
59
|
+
|
|
60
|
+
Returns:
|
|
61
|
+
A new vector pointing to the left.
|
|
62
|
+
"""
|
|
30
63
|
return cls(x=-1, y=0)
|
|
31
64
|
|
|
32
65
|
@classmethod
|
|
33
66
|
def right(cls) -> Self:
|
|
67
|
+
"""Return a vector pointing to the right (x=1, y=0).
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
A new vector pointing to the right.
|
|
71
|
+
"""
|
|
34
72
|
return cls(x=1, y=0)
|
|
35
73
|
|
|
36
74
|
@property
|
|
37
75
|
def magnitude(self) -> Num:
|
|
76
|
+
"""Calculate the magnitude (length) of the vector.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
The magnitude of the vector.
|
|
80
|
+
"""
|
|
38
81
|
return (self.x**2 + self.y**2) ** 0.5
|
|
39
82
|
|
|
40
83
|
@property
|
|
41
84
|
def angle(self) -> Num:
|
|
85
|
+
"""Calculate the angle of the vector in radians from the positive x-axis.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
The angle of the vector in radians.
|
|
89
|
+
"""
|
|
42
90
|
return atan2(self.y, self.x)
|
|
43
91
|
|
|
44
92
|
def dot(self, other: Self) -> Num:
|
|
93
|
+
"""Calculate the dot product of this vector with another vector.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
other: The other vector to calculate the dot product with.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
The dot product of the two vectors.
|
|
100
|
+
"""
|
|
45
101
|
return self.x * other.x + self.y * other.y
|
|
46
102
|
|
|
47
103
|
def rotate(self, angle: Num) -> Self:
|
|
104
|
+
"""Rotate the vector by a given angle in radians and return a new vector.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
angle: The angle to rotate the vector by, in radians.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
A new vector rotated by the given angle.
|
|
111
|
+
"""
|
|
48
112
|
return Vec2(
|
|
49
113
|
x=self.x * cos(angle) - self.y * sin(angle),
|
|
50
114
|
y=self.x * sin(angle) + self.y * cos(angle),
|
|
51
115
|
)
|
|
52
116
|
|
|
53
117
|
def rotate_about(self, angle: Num, pivot: Self) -> Self:
|
|
118
|
+
"""Rotate the vector about a pivot by a given angle in radians and return a new vector.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
angle: The angle to rotate the vector by, in radians.
|
|
122
|
+
pivot: The pivot point to rotate about.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
A new vector rotated about the pivot by the given angle.
|
|
126
|
+
"""
|
|
54
127
|
return (self - pivot).rotate(angle) + pivot
|
|
55
128
|
|
|
56
129
|
@property
|
|
57
130
|
def tuple(self) -> tuple[float, float]:
|
|
131
|
+
"""Return the vector as a tuple (x, y).
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
A tuple representation of the vector.
|
|
135
|
+
"""
|
|
58
136
|
return self.x, self.y
|
|
59
137
|
|
|
60
138
|
def __add__(self, other: Self) -> Self:
|
|
139
|
+
"""Add this vector to another vector and return a new vector.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
other: The vector to add.
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
A new vector resulting from the addition.
|
|
146
|
+
"""
|
|
61
147
|
return Vec2(x=self.x + other.x, y=self.y + other.y)
|
|
62
148
|
|
|
63
149
|
def __sub__(self, other: Self) -> Self:
|
|
150
|
+
"""Subtract another vector from this vector and return a new vector.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
other: The vector to subtract.
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
A new vector resulting from the subtraction.
|
|
157
|
+
"""
|
|
64
158
|
return Vec2(x=self.x - other.x, y=self.y - other.y)
|
|
65
159
|
|
|
66
160
|
def __mul__(self, other: Self | float) -> Self:
|
|
161
|
+
"""Multiply this vector by another vector or a scalar and return a new vector.
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
other: The vector or scalar to multiply by.
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
A new vector resulting from the multiplication.
|
|
168
|
+
"""
|
|
67
169
|
match other:
|
|
68
170
|
case Vec2(x, y):
|
|
69
171
|
return Vec2(x=self.x * x, y=self.y * y)
|
|
70
|
-
case
|
|
172
|
+
case Num(factor):
|
|
71
173
|
return Vec2(x=self.x * factor, y=self.y * factor)
|
|
72
174
|
|
|
73
175
|
def __truediv__(self, other: Self | float) -> Self:
|
|
176
|
+
"""Divide this vector by another vector or a scalar and return a new vector.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
other: The vector or scalar to divide by.
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
A new vector resulting from the division.
|
|
183
|
+
"""
|
|
74
184
|
match other:
|
|
75
185
|
case Vec2(x, y):
|
|
76
186
|
return Vec2(x=self.x / x, y=self.y / y)
|
|
77
|
-
case
|
|
187
|
+
case Num(factor):
|
|
78
188
|
return Vec2(x=self.x / factor, y=self.y / factor)
|
|
79
189
|
|
|
80
190
|
def __neg__(self) -> Self:
|
|
191
|
+
"""Negate the vector (invert the direction) and return a new vector.
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
A new vector with inverted direction.
|
|
195
|
+
"""
|
|
81
196
|
return Vec2(x=-self.x, y=-self.y)
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
sonolus/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
sonolus/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
sonolus/backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
sonolus/backend/blocks.py,sha256=3peyb9eYBy0s53xNVJ1KmK4IgoyVkkwG-lqDQ_VZTHc,18531
|
|
5
|
+
sonolus/backend/excepthook.py,sha256=pqI9gtPBh0mlTgMNqul8bEVO1ARzKb8pNE9EN_CyDpk,994
|
|
6
|
+
sonolus/backend/finalize.py,sha256=XjFeJgpKLI5_vU-okhSXRVTv31BZrUGbnBG_ITr3wrU,3963
|
|
7
|
+
sonolus/backend/interpret.py,sha256=B0jqlLmEGoyO2mxpcvwRwV17Tq_gOE9wLNt26Q5QOfs,14306
|
|
8
|
+
sonolus/backend/ir.py,sha256=TCDLMvlX2S8emFDQwFVeD2OUC4fnhbrMObgYtoa_7PQ,2845
|
|
9
|
+
sonolus/backend/mode.py,sha256=NkcPZJm8dn83LX35uP24MtQOCnfRDFZ280dHeEEfauE,613
|
|
10
|
+
sonolus/backend/node.py,sha256=H8qgnNyIseR-DhfgtcbDX03SUmhAJSSrYAlUEJTkkUo,999
|
|
11
|
+
sonolus/backend/ops.py,sha256=ekkHSdgRubIYLSYFk0wTUuBvyf3TKdApM4AyR_koTQ8,10122
|
|
12
|
+
sonolus/backend/place.py,sha256=Z3yFx-Ki2z32MXsVb6TkZ_D95RyZCu8iJPQRXNiyiNg,2364
|
|
13
|
+
sonolus/backend/utils.py,sha256=9-mmCUwGlNdjp51jKrNBN2dGxCAXVV2PdJn031kaXHM,1717
|
|
14
|
+
sonolus/backend/visitor.py,sha256=a7cRdiM9g1fLuR8_BxOwRTDvtq3JNfE4k1JqZioiQyU,45756
|
|
15
|
+
sonolus/backend/optimize/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
+
sonolus/backend/optimize/allocate.py,sha256=LCqxvT8YsVGTaVAu58fb6lrrytVLWx1LNbcOfx8CqL8,5671
|
|
17
|
+
sonolus/backend/optimize/constant_evaluation.py,sha256=ty3vNey7I44GK17lQA-3whkioFQGleYKD3P5a22foj0,15997
|
|
18
|
+
sonolus/backend/optimize/copy_coalesce.py,sha256=vKeq1UYxA7cJq5HgP8HdsIACFPjNyK4m_asakm1SOZ4,3966
|
|
19
|
+
sonolus/backend/optimize/dead_code.py,sha256=qYmUqBmAp-O5mUpNusOoMEJVkbc9YIHx6Ynrg6dyNGY,8077
|
|
20
|
+
sonolus/backend/optimize/dominance.py,sha256=oTFUqN8twrw6lTzqr1nlYs-Gk1NzIa-4qGdEQvDGzlM,3217
|
|
21
|
+
sonolus/backend/optimize/flow.py,sha256=mMf5Um2uxwF65nw13UiIv7dFMHZZHnyWv2WaOVnGw2c,4266
|
|
22
|
+
sonolus/backend/optimize/inlining.py,sha256=jwTiuHivSq9bB7FfVbD9Wd_Ztaz8ml_5CRnikr2d6yU,5719
|
|
23
|
+
sonolus/backend/optimize/liveness.py,sha256=c0ejVf1LNcYBlByf3rxkNs18IoXmiOdCFwEk3Afv8DE,7121
|
|
24
|
+
sonolus/backend/optimize/optimize.py,sha256=oGPmsDD0FFNihhrpV9uSybkGHP3C_EU0Rpw6x7kvf8c,1329
|
|
25
|
+
sonolus/backend/optimize/passes.py,sha256=OPzcpFUU7qbQFSrgr84UuzDg_vB1GYkZj2K2aqGkkag,1643
|
|
26
|
+
sonolus/backend/optimize/simplify.py,sha256=Tz4RftjH5TpIxoIOwiZuLchsrwzI9GaS_exdjAW6HKk,7927
|
|
27
|
+
sonolus/backend/optimize/ssa.py,sha256=D3CQm3s3gcuU0_k_0pXVrwirm4xjAZsX6corrTDS1Co,9013
|
|
28
|
+
sonolus/build/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
|
+
sonolus/build/cli.py,sha256=12sFalCUJmn0Dg3f8ipNIkPmZ_djG15gldqWzDG7AYo,6241
|
|
30
|
+
sonolus/build/collection.py,sha256=IsDgedsAJ-foHzQ4LnQ9zSVXSz5wVVt4sgqiUICBvCU,10573
|
|
31
|
+
sonolus/build/compile.py,sha256=wBiRX6rnq8Op4_vVXJ-bPLtffgV4ppNBa9M9hIe9twI,3579
|
|
32
|
+
sonolus/build/engine.py,sha256=TAJCdSWOsEcTq9o6jfR3A2JZ8gOoc9YQx6FC_qW-dFw,6766
|
|
33
|
+
sonolus/build/level.py,sha256=3sdGPvIZ4a15u3-JdITnB6rznp6a2E3k6A0gB8A15JA,610
|
|
34
|
+
sonolus/build/node.py,sha256=jwsVWt6Brh4M9MypUt3Nqnxfm7fXrCMRWYQGwBTAszI,1162
|
|
35
|
+
sonolus/build/project.py,sha256=QukkCVQBGxnp1F2jQjaAkTg3TutwhWqKGXAfQZDMk1c,5162
|
|
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=KJxyL4I7A-CNFQW1RbZYQGVI527XZmoesDR-q6BurB8,9339
|
|
39
|
+
sonolus/script/array_like.py,sha256=OVOLMadS-Jj941S-EgoxlFPdaQLT6ZrHzaMnKtB6PfU,8346
|
|
40
|
+
sonolus/script/bucket.py,sha256=ZNlNeBZ1FzRLQ49bTuuJDmnYZ-_sjQEvosySx3ESxQc,6944
|
|
41
|
+
sonolus/script/containers.py,sha256=tf0-UUSq8NH6k9jIKq6qgXRxanFQ0f5olH6uHghTynk,13171
|
|
42
|
+
sonolus/script/debug.py,sha256=ua8FM7h563ZMQp7oyjJRGzjjF0zi4xcnFhI3RgIdOSw,2443
|
|
43
|
+
sonolus/script/easing.py,sha256=7zaDKIfM_whUpb4FBz1DAF4NNG2vk_nDjl8kL2Y90aU,11396
|
|
44
|
+
sonolus/script/effect.py,sha256=kFshJhpVh5XiRPYms30vhry7_P6bQMVEkZ1K90jprgk,5830
|
|
45
|
+
sonolus/script/engine.py,sha256=WUCENp-G_12jN_QW-w1RJCJQrkyRbsVtB1z7OeNV2mQ,6975
|
|
46
|
+
sonolus/script/globals.py,sha256=Z8RfLkgDuXPIKiq-aOqblP0s__ALGmvcKdlyWZH21EM,9166
|
|
47
|
+
sonolus/script/instruction.py,sha256=PNfxC1dhT_hB0BxhDV3KXMn_kKxfI0t1iZmg8m6ddMU,6725
|
|
48
|
+
sonolus/script/interval.py,sha256=3wMy7YlL6XV0g7w3eIDQDXl1WfTjW4NunKtwRxRMnDQ,9004
|
|
49
|
+
sonolus/script/iterator.py,sha256=ZErUmpRrXISe1xiT3VOjHzcqqLhpfT9FI7Kz2s2vUpk,4163
|
|
50
|
+
sonolus/script/level.py,sha256=NuXr8SalXn4eMm00OOYfWPQ-EXhJIKVCtbiIKX2SGag,1872
|
|
51
|
+
sonolus/script/num.py,sha256=-u1wwFkPJYrJCjD8yE2DArrH3SMVKqQaHQhgVpd8EeA,13911
|
|
52
|
+
sonolus/script/options.py,sha256=nTOuoRC2p_qoMx4ngOVDY2WZDooTxwwGTGKyb994v2A,7516
|
|
53
|
+
sonolus/script/particle.py,sha256=K06ArT9tstRNdbuGIviDmDDWcK3-ieA53LHg0Xvizow,8304
|
|
54
|
+
sonolus/script/pointer.py,sha256=pOh5vCSl6xR7mDm5PMOhBc_wf4O-b938DE0LtZWBmPc,1119
|
|
55
|
+
sonolus/script/print.py,sha256=mNYu9QWiacBBGZrnePZQMVwbbguoelUps9GiOK_aVRU,2096
|
|
56
|
+
sonolus/script/project.py,sha256=DhmBuH0CkFKmF27o1V9XhIOsywXDi57i-Wpwyd-70LM,2040
|
|
57
|
+
sonolus/script/quad.py,sha256=SVMcfRYx8Bv5t7A2vhus9QUiw-1V-qtRhldr3DnnNWw,7693
|
|
58
|
+
sonolus/script/record.py,sha256=rOVlo-eUUvFG_Ee-wKrgX_ZwOqWKWtS7s8m-juM70yE,11216
|
|
59
|
+
sonolus/script/runtime.py,sha256=xeiLJFeqkCev1x6pBiM5afyvi3GWdpLJ5OYRg9M9nwo,18562
|
|
60
|
+
sonolus/script/sprite.py,sha256=FOozsPtaQnInnm-QshtYznnC66_8jb1D2sHmo7nFEsY,15718
|
|
61
|
+
sonolus/script/text.py,sha256=IsoINZJXefjReYDjJFwVaFsUCdgeQvPBDeywljM2dWo,13025
|
|
62
|
+
sonolus/script/timing.py,sha256=ZR0ypV2PIoDCMHHGOMfCeezStCsBQdzomdqaz5VKex0,2981
|
|
63
|
+
sonolus/script/transform.py,sha256=hH6KSRQC8vV-Z10CRCrGewMYqQwUMH3mQIEmniuC2Zw,10760
|
|
64
|
+
sonolus/script/ui.py,sha256=kyuP88sLRJPT-Yx-7fx8Xu9Wdegyw_CJNslcP4WnDUs,7268
|
|
65
|
+
sonolus/script/values.py,sha256=JuvJknskuY6FPprUp9R-6Gj2TDJLu4ppbVcYedG5dG0,1049
|
|
66
|
+
sonolus/script/vec.py,sha256=Uph6Z9xofwbKGZu0H7rl6fzlO4bj5i0cnWu4LQeIL4I,5270
|
|
67
|
+
sonolus/script/internal/__init__.py,sha256=T6rzLoiOUaiSQtaHMZ88SNO-ijSjSSv33TKtUwu-Ms8,136
|
|
68
|
+
sonolus/script/internal/builtin_impls.py,sha256=w27aKMhLX4Ivd7uKz1ZgVy1lC5scSSJ23-VfsbCfIb0,7731
|
|
69
|
+
sonolus/script/internal/callbacks.py,sha256=vWzJG8uiJoEtsNnbeZPqOHogCwoLpz2D1MnHY2wVV8s,2801
|
|
70
|
+
sonolus/script/internal/constant.py,sha256=lIBBR84Rfw0rBSZU2reCrUnB3yEMEdOX6A7_LgptYz8,3776
|
|
71
|
+
sonolus/script/internal/context.py,sha256=evLOXcOqskK5Gh5Je86ghKlMaon-Opi7dDoMtkCjEh8,13533
|
|
72
|
+
sonolus/script/internal/descriptor.py,sha256=XRFey-EjiAm_--KsNl-8N0Mi_iyQwlPh68gDp0pKf3E,392
|
|
73
|
+
sonolus/script/internal/dict_impl.py,sha256=alu_wKGSk1kZajNf64qbe7t71shEzD4N5xNIATH8Swo,1885
|
|
74
|
+
sonolus/script/internal/error.py,sha256=ZNnsvQVQAnFKzcvsm6-sste2lo-tP5pPI8sD7XlAZWc,490
|
|
75
|
+
sonolus/script/internal/generic.py,sha256=YU1hUJoBcGc0OSrFStK5JI6CikOwSmd_IR20pCuT82k,7310
|
|
76
|
+
sonolus/script/internal/impl.py,sha256=HKQVoHknw5t43Wmj_G1vFjGSmnFpOj1FUYnhbUM3rHc,2969
|
|
77
|
+
sonolus/script/internal/introspection.py,sha256=A0P2R2pNQTyj4N6-v-bCzuyIi7F-ST3qzQ3AM5l9P58,819
|
|
78
|
+
sonolus/script/internal/math_impls.py,sha256=7L450U7gW-jUkTWcQ1AMg9IX0yhu4G2WUsJ5xMZ8r3o,2306
|
|
79
|
+
sonolus/script/internal/native.py,sha256=XKlNnWSJ-lxbwVGWhGj_CSSoWsVN18imqT5sAsDJT1w,1551
|
|
80
|
+
sonolus/script/internal/random.py,sha256=6Ku5edRcDUh7rtqEEYCJz0BQavw69RALsVHS25z50pI,1695
|
|
81
|
+
sonolus/script/internal/range.py,sha256=lrTanQFHU7RuQxSSPwDdoC30Y8FnHGxcP1Ahditu3zU,2297
|
|
82
|
+
sonolus/script/internal/transient.py,sha256=pSDFGu0m26zVsp6owmNTeSPue-osDd1JahjJSijW8t0,1520
|
|
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.6.dist-info/METADATA,sha256=FBVX2Rg8O7Z0tikPOsj5wEziwbk4MSLsRxxBhJeTDrY,216
|
|
86
|
+
sonolus_py-0.1.6.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
|
87
|
+
sonolus_py-0.1.6.dist-info/entry_points.txt,sha256=oTYspY_b7SA8TptEMTDxh4-Aj-ZVPnYC9f1lqH6s9G4,54
|
|
88
|
+
sonolus_py-0.1.6.dist-info/licenses/LICENSE,sha256=JEKpqVhQYfEc7zg3Mj462sKbKYmO1K7WmvX1qvg9IJk,1067
|
|
89
|
+
sonolus_py-0.1.6.dist-info/RECORD,,
|
sonolus/backend/dead_code.py
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
from sonolus.backend.flow import BasicBlock, traverse_cfg_preorder
|
|
2
|
-
from sonolus.backend.ir import IRConst, IRGet, IRInstr, IRSet
|
|
3
|
-
from sonolus.backend.liveness import LivenessAnalysis, get_live, get_live_phi_targets
|
|
4
|
-
from sonolus.backend.passes import CompilerPass
|
|
5
|
-
from sonolus.backend.place import BlockPlace, SSAPlace, TempBlock
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class UnreachableCodeElimination(CompilerPass):
|
|
9
|
-
def run(self, entry: BasicBlock) -> BasicBlock:
|
|
10
|
-
original_blocks = [*traverse_cfg_preorder(entry)]
|
|
11
|
-
worklist = {entry}
|
|
12
|
-
visited = set()
|
|
13
|
-
while worklist:
|
|
14
|
-
block = worklist.pop()
|
|
15
|
-
if block in visited:
|
|
16
|
-
continue
|
|
17
|
-
visited.add(block)
|
|
18
|
-
match block.test:
|
|
19
|
-
case IRConst(value=value):
|
|
20
|
-
block.test = IRConst(0)
|
|
21
|
-
taken_edge = next(
|
|
22
|
-
(edge for edge in block.outgoing if edge.cond == value),
|
|
23
|
-
None,
|
|
24
|
-
) or next((edge for edge in block.outgoing if edge.cond is None), None)
|
|
25
|
-
assert not block.outgoing or taken_edge
|
|
26
|
-
for edge in [*block.outgoing]:
|
|
27
|
-
if edge is not taken_edge:
|
|
28
|
-
edge.dst.incoming.remove(edge)
|
|
29
|
-
block.outgoing.remove(edge)
|
|
30
|
-
if taken_edge:
|
|
31
|
-
taken_edge.cond = None
|
|
32
|
-
block.outgoing.add(taken_edge)
|
|
33
|
-
worklist.add(taken_edge.dst)
|
|
34
|
-
case _:
|
|
35
|
-
worklist.update(edge.dst for edge in block.outgoing)
|
|
36
|
-
for block in original_blocks:
|
|
37
|
-
if block not in visited:
|
|
38
|
-
for edge in block.outgoing:
|
|
39
|
-
edge.dst.incoming.remove(edge)
|
|
40
|
-
else:
|
|
41
|
-
for args in block.phis.values():
|
|
42
|
-
for src_block in [*args]:
|
|
43
|
-
if src_block not in visited:
|
|
44
|
-
args.pop(src_block)
|
|
45
|
-
return entry
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
class DeadCodeElimination(CompilerPass):
|
|
49
|
-
def requires(self) -> set[CompilerPass]:
|
|
50
|
-
return {LivenessAnalysis()}
|
|
51
|
-
|
|
52
|
-
def preserves(self) -> set[CompilerPass] | None:
|
|
53
|
-
return {LivenessAnalysis()}
|
|
54
|
-
|
|
55
|
-
def run(self, entry: BasicBlock) -> BasicBlock:
|
|
56
|
-
for block in traverse_cfg_preorder(entry):
|
|
57
|
-
live_stmts = []
|
|
58
|
-
for statement in block.statements:
|
|
59
|
-
live = get_live(statement)
|
|
60
|
-
match statement:
|
|
61
|
-
case IRSet(place=place, value=value):
|
|
62
|
-
is_live = not (
|
|
63
|
-
(isinstance(place, SSAPlace) and place not in live)
|
|
64
|
-
or (
|
|
65
|
-
isinstance(place, BlockPlace)
|
|
66
|
-
and isinstance(place.block, TempBlock)
|
|
67
|
-
and place.block not in live
|
|
68
|
-
)
|
|
69
|
-
or (isinstance(value, IRGet) and place == value.place)
|
|
70
|
-
)
|
|
71
|
-
if is_live:
|
|
72
|
-
live_stmts.append(statement)
|
|
73
|
-
elif isinstance(value, IRInstr) and value.op.side_effects:
|
|
74
|
-
live_stmts.append(value)
|
|
75
|
-
value.live = live
|
|
76
|
-
case other:
|
|
77
|
-
live_stmts.append(other)
|
|
78
|
-
block.statements = live_stmts
|
|
79
|
-
block.phis = {place: phi for place, phi in block.phis.items() if place in get_live_phi_targets(block)}
|
|
80
|
-
return entry
|