sonolus.py 0.1.0__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/__init__.py +0 -0
- sonolus/backend/__init__.py +0 -0
- sonolus/backend/allocate.py +51 -0
- sonolus/backend/blocks.py +756 -0
- sonolus/backend/excepthook.py +37 -0
- sonolus/backend/finalize.py +69 -0
- sonolus/backend/flow.py +92 -0
- sonolus/backend/interpret.py +333 -0
- sonolus/backend/ir.py +89 -0
- sonolus/backend/mode.py +24 -0
- sonolus/backend/node.py +40 -0
- sonolus/backend/ops.py +197 -0
- sonolus/backend/optimize.py +9 -0
- sonolus/backend/passes.py +6 -0
- sonolus/backend/place.py +90 -0
- sonolus/backend/simplify.py +30 -0
- sonolus/backend/utils.py +48 -0
- sonolus/backend/visitor.py +880 -0
- sonolus/build/__init__.py +0 -0
- sonolus/build/cli.py +170 -0
- sonolus/build/collection.py +293 -0
- sonolus/build/compile.py +90 -0
- sonolus/build/defaults.py +32 -0
- sonolus/build/engine.py +149 -0
- sonolus/build/level.py +23 -0
- sonolus/build/node.py +43 -0
- sonolus/build/project.py +94 -0
- sonolus/py.typed +0 -0
- sonolus/script/__init__.py +0 -0
- sonolus/script/archetype.py +651 -0
- sonolus/script/array.py +241 -0
- sonolus/script/bucket.py +192 -0
- sonolus/script/callbacks.py +105 -0
- sonolus/script/comptime.py +146 -0
- sonolus/script/containers.py +247 -0
- sonolus/script/debug.py +70 -0
- sonolus/script/effect.py +132 -0
- sonolus/script/engine.py +101 -0
- sonolus/script/globals.py +234 -0
- sonolus/script/graphics.py +141 -0
- sonolus/script/icon.py +73 -0
- sonolus/script/internal/__init__.py +5 -0
- sonolus/script/internal/builtin_impls.py +144 -0
- sonolus/script/internal/context.py +365 -0
- sonolus/script/internal/descriptor.py +17 -0
- sonolus/script/internal/error.py +15 -0
- sonolus/script/internal/generic.py +197 -0
- sonolus/script/internal/impl.py +69 -0
- sonolus/script/internal/introspection.py +14 -0
- sonolus/script/internal/native.py +38 -0
- sonolus/script/internal/value.py +144 -0
- sonolus/script/interval.py +98 -0
- sonolus/script/iterator.py +211 -0
- sonolus/script/level.py +52 -0
- sonolus/script/math.py +92 -0
- sonolus/script/num.py +382 -0
- sonolus/script/options.py +194 -0
- sonolus/script/particle.py +158 -0
- sonolus/script/pointer.py +30 -0
- sonolus/script/project.py +17 -0
- sonolus/script/range.py +58 -0
- sonolus/script/record.py +293 -0
- sonolus/script/runtime.py +526 -0
- sonolus/script/sprite.py +332 -0
- sonolus/script/text.py +404 -0
- sonolus/script/timing.py +42 -0
- sonolus/script/transform.py +118 -0
- sonolus/script/ui.py +160 -0
- sonolus/script/values.py +43 -0
- sonolus/script/vec.py +48 -0
- sonolus_py-0.1.0.dist-info/METADATA +10 -0
- sonolus_py-0.1.0.dist-info/RECORD +75 -0
- sonolus_py-0.1.0.dist-info/WHEEL +4 -0
- sonolus_py-0.1.0.dist-info/entry_points.txt +2 -0
- sonolus_py-0.1.0.dist-info/licenses/LICENSE +21 -0
sonolus/backend/ops.py
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
from enum import StrEnum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Op(StrEnum):
|
|
5
|
+
def __new__(cls, name: str, side_effects: bool, pure: bool, control_flow: bool):
|
|
6
|
+
obj = str.__new__(cls, name)
|
|
7
|
+
obj._value_ = name
|
|
8
|
+
obj.side_effects = side_effects
|
|
9
|
+
obj.pure = pure
|
|
10
|
+
obj.control_flow = control_flow
|
|
11
|
+
return obj
|
|
12
|
+
|
|
13
|
+
Abs = ("Abs", False, True, False)
|
|
14
|
+
Add = ("Add", False, True, False)
|
|
15
|
+
And = ("And", False, True, True)
|
|
16
|
+
Arccos = ("Arccos", False, True, False)
|
|
17
|
+
Arcsin = ("Arcsin", False, True, False)
|
|
18
|
+
Arctan = ("Arctan", False, True, False)
|
|
19
|
+
Arctan2 = ("Arctan2", False, True, False)
|
|
20
|
+
BeatToBPM = ("BeatToBPM", False, True, False)
|
|
21
|
+
BeatToStartingBeat = ("BeatToStartingBeat", False, True, False)
|
|
22
|
+
BeatToStartingTime = ("BeatToStartingTime", False, True, False)
|
|
23
|
+
BeatToTime = ("BeatToTime", False, True, False)
|
|
24
|
+
Block = ("Block", False, True, True)
|
|
25
|
+
Break = ("Break", True, False, True)
|
|
26
|
+
Ceil = ("Ceil", False, True, False)
|
|
27
|
+
Clamp = ("Clamp", False, True, False)
|
|
28
|
+
Copy = ("Copy", True, False, False)
|
|
29
|
+
Cos = ("Cos", False, True, False)
|
|
30
|
+
Cosh = ("Cosh", False, True, False)
|
|
31
|
+
DebugLog = ("DebugLog", True, False, False)
|
|
32
|
+
DebugPause = ("DebugPause", True, False, False)
|
|
33
|
+
DecrementPost = ("DecrementPost", True, False, False)
|
|
34
|
+
DecrementPostPointed = ("DecrementPostPointed", True, False, False)
|
|
35
|
+
DecrementPostShifted = ("DecrementPostShifted", True, False, False)
|
|
36
|
+
DecrementPre = ("DecrementPre", True, False, False)
|
|
37
|
+
DecrementPrePointed = ("DecrementPrePointed", True, False, False)
|
|
38
|
+
DecrementPreShifted = ("DecrementPreShifted", True, False, False)
|
|
39
|
+
Degree = ("Degree", False, True, False)
|
|
40
|
+
DestroyParticleEffect = ("DestroyParticleEffect", True, False, False)
|
|
41
|
+
Divide = ("Divide", False, True, False)
|
|
42
|
+
DoWhile = ("DoWhile", False, True, True)
|
|
43
|
+
Draw = ("Draw", True, False, False)
|
|
44
|
+
DrawCurvedB = ("DrawCurvedB", True, False, False)
|
|
45
|
+
DrawCurvedBT = ("DrawCurvedBT", True, False, False)
|
|
46
|
+
DrawCurvedL = ("DrawCurvedL", True, False, False)
|
|
47
|
+
DrawCurvedLR = ("DrawCurvedLR", True, False, False)
|
|
48
|
+
DrawCurvedR = ("DrawCurvedR", True, False, False)
|
|
49
|
+
DrawCurvedT = ("DrawCurvedT", True, False, False)
|
|
50
|
+
EaseInBack = ("EaseInBack", False, True, False)
|
|
51
|
+
EaseInCirc = ("EaseInCirc", False, True, False)
|
|
52
|
+
EaseInCubic = ("EaseInCubic", False, True, False)
|
|
53
|
+
EaseInElastic = ("EaseInElastic", False, True, False)
|
|
54
|
+
EaseInExpo = ("EaseInExpo", False, True, False)
|
|
55
|
+
EaseInOutBack = ("EaseInOutBack", False, True, False)
|
|
56
|
+
EaseInOutCirc = ("EaseInOutCirc", False, True, False)
|
|
57
|
+
EaseInOutCubic = ("EaseInOutCubic", False, True, False)
|
|
58
|
+
EaseInOutElastic = ("EaseInOutElastic", False, True, False)
|
|
59
|
+
EaseInOutExpo = ("EaseInOutExpo", False, True, False)
|
|
60
|
+
EaseInOutQuad = ("EaseInOutQuad", False, True, False)
|
|
61
|
+
EaseInOutQuart = ("EaseInOutQuart", False, True, False)
|
|
62
|
+
EaseInOutQuint = ("EaseInOutQuint", False, True, False)
|
|
63
|
+
EaseInOutSine = ("EaseInOutSine", False, True, False)
|
|
64
|
+
EaseInQuad = ("EaseInQuad", False, True, False)
|
|
65
|
+
EaseInQuart = ("EaseInQuart", False, True, False)
|
|
66
|
+
EaseInQuint = ("EaseInQuint", False, True, False)
|
|
67
|
+
EaseInSine = ("EaseInSine", False, True, False)
|
|
68
|
+
EaseOutBack = ("EaseOutBack", False, True, False)
|
|
69
|
+
EaseOutCirc = ("EaseOutCirc", False, True, False)
|
|
70
|
+
EaseOutCubic = ("EaseOutCubic", False, True, False)
|
|
71
|
+
EaseOutElastic = ("EaseOutElastic", False, True, False)
|
|
72
|
+
EaseOutExpo = ("EaseOutExpo", False, True, False)
|
|
73
|
+
EaseOutInBack = ("EaseOutInBack", False, True, False)
|
|
74
|
+
EaseOutInCirc = ("EaseOutInCirc", False, True, False)
|
|
75
|
+
EaseOutInCubic = ("EaseOutInCubic", False, True, False)
|
|
76
|
+
EaseOutInElastic = ("EaseOutInElastic", False, True, False)
|
|
77
|
+
EaseOutInExpo = ("EaseOutInExpo", False, True, False)
|
|
78
|
+
EaseOutInQuad = ("EaseOutInQuad", False, True, False)
|
|
79
|
+
EaseOutInQuart = ("EaseOutInQuart", False, True, False)
|
|
80
|
+
EaseOutInQuint = ("EaseOutInQuint", False, True, False)
|
|
81
|
+
EaseOutInSine = ("EaseOutInSine", False, True, False)
|
|
82
|
+
EaseOutQuad = ("EaseOutQuad", False, True, False)
|
|
83
|
+
EaseOutQuart = ("EaseOutQuart", False, True, False)
|
|
84
|
+
EaseOutQuint = ("EaseOutQuint", False, True, False)
|
|
85
|
+
EaseOutSine = ("EaseOutSine", False, True, False)
|
|
86
|
+
Equal = ("Equal", False, True, False)
|
|
87
|
+
Execute = ("Execute", False, True, False)
|
|
88
|
+
Execute0 = ("Execute0", False, True, False)
|
|
89
|
+
ExportValue = ("ExportValue", True, False, False)
|
|
90
|
+
Floor = ("Floor", False, True, False)
|
|
91
|
+
Frac = ("Frac", False, True, False)
|
|
92
|
+
Get = ("Get", False, False, False)
|
|
93
|
+
GetPointed = ("GetPointed", False, False, False)
|
|
94
|
+
GetShifted = ("GetShifted", False, False, False)
|
|
95
|
+
Greater = ("Greater", False, True, False)
|
|
96
|
+
GreaterOr = ("GreaterOr", False, True, False)
|
|
97
|
+
HasEffectClip = ("HasEffectClip", False, True, False)
|
|
98
|
+
HasParticleEffect = ("HasParticleEffect", False, True, False)
|
|
99
|
+
HasSkinSprite = ("HasSkinSprite", False, True, False)
|
|
100
|
+
If = ("If", False, True, True)
|
|
101
|
+
IncrementPost = ("IncrementPost", True, False, False)
|
|
102
|
+
IncrementPostPointed = ("IncrementPostPointed", True, False, False)
|
|
103
|
+
IncrementPostShifted = ("IncrementPostShifted", True, False, False)
|
|
104
|
+
IncrementPre = ("IncrementPre", True, False, False)
|
|
105
|
+
IncrementPrePointed = ("IncrementPrePointed", True, False, False)
|
|
106
|
+
IncrementPreShifted = ("IncrementPreShifted", True, False, False)
|
|
107
|
+
Judge = ("Judge", False, True, False)
|
|
108
|
+
JudgeSimple = ("JudgeSimple", False, True, False)
|
|
109
|
+
JumpLoop = ("JumpLoop", False, True, True)
|
|
110
|
+
Lerp = ("Lerp", False, True, False)
|
|
111
|
+
LerpClamped = ("LerpClamped", False, True, False)
|
|
112
|
+
Less = ("Less", False, True, False)
|
|
113
|
+
LessOr = ("LessOr", False, True, False)
|
|
114
|
+
Log = ("Log", False, True, False)
|
|
115
|
+
Max = ("Max", False, True, False)
|
|
116
|
+
Min = ("Min", False, True, False)
|
|
117
|
+
Mod = ("Mod", False, True, False)
|
|
118
|
+
MoveParticleEffect = ("MoveParticleEffect", True, False, False)
|
|
119
|
+
Multiply = ("Multiply", False, True, False)
|
|
120
|
+
Negate = ("Negate", False, True, False)
|
|
121
|
+
Not = ("Not", False, True, False)
|
|
122
|
+
NotEqual = ("NotEqual", False, True, False)
|
|
123
|
+
Or = ("Or", False, True, True)
|
|
124
|
+
Paint = ("Paint", True, False, False)
|
|
125
|
+
Play = ("Play", True, False, False)
|
|
126
|
+
PlayLooped = ("PlayLooped", True, False, False)
|
|
127
|
+
PlayLoopedScheduled = ("PlayLoopedScheduled", True, False, False)
|
|
128
|
+
PlayScheduled = ("PlayScheduled", True, False, False)
|
|
129
|
+
Power = ("Power", False, True, False)
|
|
130
|
+
Print = ("Print", True, False, False)
|
|
131
|
+
Radian = ("Radian", False, True, False)
|
|
132
|
+
Random = ("Random", False, False, False)
|
|
133
|
+
RandomInteger = ("RandomInteger", False, False, False)
|
|
134
|
+
Rem = ("Rem", False, True, False)
|
|
135
|
+
Remap = ("Remap", False, True, False)
|
|
136
|
+
RemapClamped = ("RemapClamped", False, True, False)
|
|
137
|
+
Round = ("Round", False, True, False)
|
|
138
|
+
Set = ("Set", True, False, False)
|
|
139
|
+
SetAdd = ("SetAdd", True, False, False)
|
|
140
|
+
SetAddPointed = ("SetAddPointed", True, False, False)
|
|
141
|
+
SetAddShifted = ("SetAddShifted", True, False, False)
|
|
142
|
+
SetDivide = ("SetDivide", True, False, False)
|
|
143
|
+
SetDividePointed = ("SetDividePointed", True, False, False)
|
|
144
|
+
SetDivideShifted = ("SetDivideShifted", True, False, False)
|
|
145
|
+
SetMod = ("SetMod", True, False, False)
|
|
146
|
+
SetModPointed = ("SetModPointed", True, False, False)
|
|
147
|
+
SetModShifted = ("SetModShifted", True, False, False)
|
|
148
|
+
SetMultiply = ("SetMultiply", True, False, False)
|
|
149
|
+
SetMultiplyPointed = ("SetMultiplyPointed", True, False, False)
|
|
150
|
+
SetMultiplyShifted = ("SetMultiplyShifted", True, False, False)
|
|
151
|
+
SetPointed = ("SetPointed", True, False, False)
|
|
152
|
+
SetPower = ("SetPower", True, False, False)
|
|
153
|
+
SetPowerPointed = ("SetPowerPointed", True, False, False)
|
|
154
|
+
SetPowerShifted = ("SetPowerShifted", True, False, False)
|
|
155
|
+
SetRem = ("SetRem", True, False, False)
|
|
156
|
+
SetRemPointed = ("SetRemPointed", True, False, False)
|
|
157
|
+
SetRemShifted = ("SetRemShifted", True, False, False)
|
|
158
|
+
SetShifted = ("SetShifted", True, False, False)
|
|
159
|
+
SetSubtract = ("SetSubtract", True, False, False)
|
|
160
|
+
SetSubtractPointed = ("SetSubtractPointed", True, False, False)
|
|
161
|
+
SetSubtractShifted = ("SetSubtractShifted", True, False, False)
|
|
162
|
+
Sign = ("Sign", False, True, False)
|
|
163
|
+
Sin = ("Sin", False, True, False)
|
|
164
|
+
Sinh = ("Sinh", False, True, False)
|
|
165
|
+
Spawn = ("Spawn", True, False, False)
|
|
166
|
+
SpawnParticleEffect = ("SpawnParticleEffect", True, False, False)
|
|
167
|
+
StackEnter = ("StackEnter", True, False, False)
|
|
168
|
+
StackGet = ("StackGet", False, False, False)
|
|
169
|
+
StackGetFrame = ("StackGetFrame", False, False, False)
|
|
170
|
+
StackGetFramePointer = ("StackGetFramePointer", False, False, False)
|
|
171
|
+
StackGetPointer = ("StackGetPointer", False, False, False)
|
|
172
|
+
StackGrow = ("StackGrow", True, False, False)
|
|
173
|
+
StackInit = ("StackInit", True, False, False)
|
|
174
|
+
StackLeave = ("StackLeave", True, False, False)
|
|
175
|
+
StackPop = ("StackPop", True, False, False)
|
|
176
|
+
StackPush = ("StackPush", True, False, False)
|
|
177
|
+
StackSet = ("StackSet", True, False, False)
|
|
178
|
+
StackSetFrame = ("StackSetFrame", True, False, False)
|
|
179
|
+
StackSetFramePointer = ("StackSetFramePointer", True, False, False)
|
|
180
|
+
StackSetPointer = ("StackSetPointer", True, False, False)
|
|
181
|
+
StopLooped = ("StopLooped", True, False, False)
|
|
182
|
+
StopLoopedScheduled = ("StopLoopedScheduled", True, False, False)
|
|
183
|
+
Subtract = ("Subtract", False, True, False)
|
|
184
|
+
Switch = ("Switch", False, True, True)
|
|
185
|
+
SwitchInteger = ("SwitchInteger", False, True, True)
|
|
186
|
+
SwitchIntegerWithDefault = ("SwitchIntegerWithDefault", False, True, True)
|
|
187
|
+
SwitchWithDefault = ("SwitchWithDefault", False, True, True)
|
|
188
|
+
Tan = ("Tan", False, True, False)
|
|
189
|
+
Tanh = ("Tanh", False, True, False)
|
|
190
|
+
TimeToScaledTime = ("TimeToScaledTime", False, True, False)
|
|
191
|
+
TimeToStartingScaledTime = ("TimeToStartingScaledTime", False, True, False)
|
|
192
|
+
TimeToStartingTime = ("TimeToStartingTime", False, True, False)
|
|
193
|
+
TimeToTimeScale = ("TimeToTimeScale", False, True, False)
|
|
194
|
+
Trunc = ("Trunc", False, True, False)
|
|
195
|
+
Unlerp = ("Unlerp", False, True, False)
|
|
196
|
+
UnlerpClamped = ("UnlerpClamped", False, True, False)
|
|
197
|
+
While = ("While", False, True, True)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from sonolus.backend.allocate import AllocateBasic
|
|
2
|
+
from sonolus.backend.flow import BasicBlock
|
|
3
|
+
from sonolus.backend.simplify import CoalesceFlow
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def optimize_and_allocate(cfg: BasicBlock):
|
|
7
|
+
cfg = CoalesceFlow().run(cfg)
|
|
8
|
+
cfg = AllocateBasic().run(cfg)
|
|
9
|
+
return cfg
|
sonolus/backend/place.py
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
from collections.abc import Iterator
|
|
2
|
+
from typing import Self
|
|
3
|
+
|
|
4
|
+
from sonolus.backend.blocks import Block
|
|
5
|
+
|
|
6
|
+
type Place = BlockPlace | SSAPlace
|
|
7
|
+
type BlockValue = Block | int | TempBlock | Place
|
|
8
|
+
type IndexValue = int | Place
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TempBlock:
|
|
12
|
+
name: str
|
|
13
|
+
size: int
|
|
14
|
+
|
|
15
|
+
def __init__(self, name: str, size: int = 1):
|
|
16
|
+
self.name = name
|
|
17
|
+
self.size = size
|
|
18
|
+
|
|
19
|
+
def __repr__(self):
|
|
20
|
+
return f"TempBlock(name={self.name!r}, size={self.size!r})"
|
|
21
|
+
|
|
22
|
+
def __str__(self):
|
|
23
|
+
return f"{self.name}"
|
|
24
|
+
|
|
25
|
+
def __getitem__(self, item) -> "BlockPlace":
|
|
26
|
+
return BlockPlace(self, item)
|
|
27
|
+
|
|
28
|
+
def __iter__(self) -> "Iterator[BlockPlace]":
|
|
29
|
+
for i in range(self.size):
|
|
30
|
+
yield self[i]
|
|
31
|
+
|
|
32
|
+
def __eq__(self, other):
|
|
33
|
+
return isinstance(other, TempBlock) and self.name == other.name and self.size == other.size
|
|
34
|
+
|
|
35
|
+
def __hash__(self):
|
|
36
|
+
return hash((self.name, self.size))
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class BlockPlace:
|
|
40
|
+
block: BlockValue
|
|
41
|
+
index: IndexValue
|
|
42
|
+
offset: int = 0
|
|
43
|
+
|
|
44
|
+
def __init__(self, block: BlockValue, index: IndexValue = 0, offset: int = 0):
|
|
45
|
+
self.block = block
|
|
46
|
+
self.index = index
|
|
47
|
+
self.offset = offset
|
|
48
|
+
|
|
49
|
+
def __repr__(self):
|
|
50
|
+
return f"BlockPlace(block={self.block!r}, index={self.index!r}, offset={self.offset!r})"
|
|
51
|
+
|
|
52
|
+
def __str__(self):
|
|
53
|
+
if isinstance(self.block, TempBlock) and self.block.size == 1 and self.index == 0 and self.offset == 0:
|
|
54
|
+
return f"{self.block}"
|
|
55
|
+
elif isinstance(self.index, int):
|
|
56
|
+
return f"{self.block}[{self.index + self.offset}]"
|
|
57
|
+
elif self.offset == 0:
|
|
58
|
+
return f"{self.block}[{self.index}]"
|
|
59
|
+
else:
|
|
60
|
+
return f"{self.block}[{self.index} + {self.offset}]"
|
|
61
|
+
|
|
62
|
+
def __eq__(self, other):
|
|
63
|
+
return isinstance(other, BlockPlace) and self.block == other.block and self.index == other.index
|
|
64
|
+
|
|
65
|
+
def __hash__(self):
|
|
66
|
+
return hash((self.block, self.index))
|
|
67
|
+
|
|
68
|
+
def add_offset(self, offset: int) -> Self:
|
|
69
|
+
return BlockPlace(self.block, self.index, self.offset + offset)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class SSAPlace:
|
|
73
|
+
name: str
|
|
74
|
+
num: int
|
|
75
|
+
|
|
76
|
+
def __init__(self, name: str, num: int):
|
|
77
|
+
self.name = name
|
|
78
|
+
self.num = num
|
|
79
|
+
|
|
80
|
+
def __repr__(self):
|
|
81
|
+
return f"SSAPlace(name={self.name!r}, num={self.num!r})"
|
|
82
|
+
|
|
83
|
+
def __str__(self):
|
|
84
|
+
return f"{self.name}.{self.num}"
|
|
85
|
+
|
|
86
|
+
def __eq__(self, other):
|
|
87
|
+
return isinstance(other, SSAPlace) and self.name == other.name and self.num == other.num
|
|
88
|
+
|
|
89
|
+
def __hash__(self):
|
|
90
|
+
return hash((self.name, self.num))
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from sonolus.backend.flow import BasicBlock
|
|
2
|
+
from sonolus.backend.passes import CompilerPass
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class CoalesceFlow(CompilerPass):
|
|
6
|
+
def run(self, entry: BasicBlock) -> BasicBlock:
|
|
7
|
+
queue = [entry]
|
|
8
|
+
processed = set()
|
|
9
|
+
while queue:
|
|
10
|
+
block = queue.pop()
|
|
11
|
+
if block in processed:
|
|
12
|
+
continue
|
|
13
|
+
processed.add(block)
|
|
14
|
+
if len(block.outgoing) != 1:
|
|
15
|
+
queue.extend(edge.dst for edge in block.outgoing)
|
|
16
|
+
continue
|
|
17
|
+
next_block = next(iter(block.outgoing)).dst
|
|
18
|
+
if len(next_block.incoming) != 1:
|
|
19
|
+
queue.append(next_block)
|
|
20
|
+
continue
|
|
21
|
+
block.statements.extend(next_block.statements)
|
|
22
|
+
block.test = next_block.test
|
|
23
|
+
for edge in next_block.outgoing:
|
|
24
|
+
edge.src = block
|
|
25
|
+
block.outgoing = next_block.outgoing
|
|
26
|
+
processed.add(next_block)
|
|
27
|
+
queue.extend(edge.dst for edge in block.outgoing)
|
|
28
|
+
processed.remove(block)
|
|
29
|
+
queue.append(block)
|
|
30
|
+
return entry
|
sonolus/backend/utils.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# ruff: noqa: N802
|
|
2
|
+
import ast
|
|
3
|
+
import inspect
|
|
4
|
+
from collections.abc import Callable
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_function(fn: Callable) -> tuple[str, ast.FunctionDef]:
|
|
9
|
+
# This preserves both line number and column number in the returned node
|
|
10
|
+
source_file = inspect.getsourcefile(fn)
|
|
11
|
+
_, start_line = inspect.getsourcelines(fn)
|
|
12
|
+
base_tree = ast.parse(Path(source_file).read_text(encoding="utf-8"))
|
|
13
|
+
return source_file, find_function(base_tree, start_line)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class FindFunction(ast.NodeVisitor):
|
|
17
|
+
def __init__(self, line):
|
|
18
|
+
self.line = line
|
|
19
|
+
self.node: ast.FunctionDef | None = None
|
|
20
|
+
|
|
21
|
+
def visit_FunctionDef(self, node: ast.FunctionDef):
|
|
22
|
+
if node.lineno == self.line or (
|
|
23
|
+
node.decorator_list and (node.decorator_list[-1].end_lineno <= self.line <= node.lineno)
|
|
24
|
+
):
|
|
25
|
+
self.node = node
|
|
26
|
+
else:
|
|
27
|
+
self.generic_visit(node)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def find_function(tree: ast.Module, line: int):
|
|
31
|
+
visitor = FindFunction(line)
|
|
32
|
+
visitor.visit(tree)
|
|
33
|
+
return visitor.node
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ScanWrites(ast.NodeVisitor):
|
|
37
|
+
def __init__(self):
|
|
38
|
+
self.writes = []
|
|
39
|
+
|
|
40
|
+
def visit_Name(self, node):
|
|
41
|
+
if isinstance(node.ctx, ast.Store | ast.Delete):
|
|
42
|
+
self.writes.append(node.id)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def scan_writes(node: ast.AST) -> set[str]:
|
|
46
|
+
visitor = ScanWrites()
|
|
47
|
+
visitor.visit(node)
|
|
48
|
+
return set(visitor.writes)
|