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.

Files changed (79) hide show
  1. sonolus/backend/finalize.py +18 -10
  2. sonolus/backend/interpret.py +7 -7
  3. sonolus/backend/ir.py +24 -0
  4. sonolus/backend/optimize/__init__.py +0 -0
  5. sonolus/backend/{allocate.py → optimize/allocate.py} +4 -3
  6. sonolus/backend/{constant_evaluation.py → optimize/constant_evaluation.py} +7 -7
  7. sonolus/backend/{coalesce.py → optimize/copy_coalesce.py} +3 -3
  8. sonolus/backend/optimize/dead_code.py +185 -0
  9. sonolus/backend/{dominance.py → optimize/dominance.py} +2 -17
  10. sonolus/backend/{flow.py → optimize/flow.py} +6 -5
  11. sonolus/backend/{inlining.py → optimize/inlining.py} +4 -17
  12. sonolus/backend/{liveness.py → optimize/liveness.py} +69 -65
  13. sonolus/backend/optimize/optimize.py +44 -0
  14. sonolus/backend/{passes.py → optimize/passes.py} +1 -1
  15. sonolus/backend/optimize/simplify.py +191 -0
  16. sonolus/backend/{ssa.py → optimize/ssa.py} +31 -18
  17. sonolus/backend/place.py +17 -25
  18. sonolus/backend/utils.py +10 -0
  19. sonolus/backend/visitor.py +360 -101
  20. sonolus/build/cli.py +14 -3
  21. sonolus/build/compile.py +8 -8
  22. sonolus/build/engine.py +10 -5
  23. sonolus/build/project.py +30 -1
  24. sonolus/script/archetype.py +429 -138
  25. sonolus/script/array.py +25 -8
  26. sonolus/script/array_like.py +297 -0
  27. sonolus/script/bucket.py +73 -11
  28. sonolus/script/containers.py +234 -51
  29. sonolus/script/debug.py +8 -8
  30. sonolus/script/easing.py +147 -105
  31. sonolus/script/effect.py +60 -0
  32. sonolus/script/engine.py +71 -4
  33. sonolus/script/globals.py +66 -32
  34. sonolus/script/instruction.py +79 -25
  35. sonolus/script/internal/builtin_impls.py +138 -27
  36. sonolus/script/internal/constant.py +139 -0
  37. sonolus/script/internal/context.py +14 -5
  38. sonolus/script/internal/dict_impl.py +65 -0
  39. sonolus/script/internal/generic.py +6 -9
  40. sonolus/script/internal/impl.py +38 -13
  41. sonolus/script/internal/introspection.py +5 -2
  42. sonolus/script/{math.py → internal/math_impls.py} +28 -28
  43. sonolus/script/internal/native.py +3 -3
  44. sonolus/script/internal/random.py +67 -0
  45. sonolus/script/internal/range.py +81 -0
  46. sonolus/script/internal/transient.py +51 -0
  47. sonolus/script/internal/tuple_impl.py +113 -0
  48. sonolus/script/interval.py +234 -16
  49. sonolus/script/iterator.py +120 -167
  50. sonolus/script/level.py +24 -0
  51. sonolus/script/num.py +79 -47
  52. sonolus/script/options.py +78 -12
  53. sonolus/script/particle.py +37 -4
  54. sonolus/script/pointer.py +4 -4
  55. sonolus/script/print.py +22 -1
  56. sonolus/script/project.py +59 -0
  57. sonolus/script/{graphics.py → quad.py} +75 -12
  58. sonolus/script/record.py +44 -13
  59. sonolus/script/runtime.py +50 -1
  60. sonolus/script/sprite.py +198 -115
  61. sonolus/script/text.py +2 -0
  62. sonolus/script/timing.py +72 -0
  63. sonolus/script/transform.py +296 -66
  64. sonolus/script/ui.py +134 -78
  65. sonolus/script/values.py +6 -13
  66. sonolus/script/vec.py +118 -3
  67. {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.6.dist-info}/METADATA +1 -1
  68. sonolus_py-0.1.6.dist-info/RECORD +89 -0
  69. sonolus/backend/dead_code.py +0 -80
  70. sonolus/backend/optimize.py +0 -37
  71. sonolus/backend/simplify.py +0 -47
  72. sonolus/script/comptime.py +0 -160
  73. sonolus/script/random.py +0 -14
  74. sonolus/script/range.py +0 -58
  75. sonolus_py-0.1.4.dist-info/RECORD +0 -84
  76. /sonolus/script/{callbacks.py → internal/callbacks.py} +0 -0
  77. {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.6.dist-info}/WHEEL +0 -0
  78. {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.6.dist-info}/entry_points.txt +0 -0
  79. {sonolus_py-0.1.4.dist-info → sonolus_py-0.1.6.dist-info}/licenses/LICENSE +0 -0
sonolus/build/cli.py CHANGED
@@ -2,6 +2,7 @@ import argparse
2
2
  import contextlib
3
3
  import http.server
4
4
  import importlib
5
+ import json
5
6
  import shutil
6
7
  import socket
7
8
  import socketserver
@@ -11,7 +12,7 @@ from time import perf_counter
11
12
 
12
13
  from sonolus.build.engine import package_engine
13
14
  from sonolus.build.level import package_level_data
14
- from sonolus.build.project import build_project_to_collection
15
+ from sonolus.build.project import build_project_to_collection, get_project_schema
15
16
  from sonolus.script.project import Project
16
17
 
17
18
 
@@ -147,6 +148,14 @@ def main():
147
148
  dev_parser.add_argument("--build-dir", type=str, default="./build")
148
149
  dev_parser.add_argument("--port", type=int, default=8000)
149
150
 
151
+ schema_parser = subparsers.add_parser("schema")
152
+ schema_parser.add_argument(
153
+ "module",
154
+ type=str,
155
+ nargs="?",
156
+ help="Module path (e.g., 'module.name'). If omitted, will auto-detect if only one module exists.",
157
+ )
158
+
150
159
  args = parser.parse_args()
151
160
 
152
161
  if not args.module:
@@ -161,16 +170,18 @@ def main():
161
170
  if project is None:
162
171
  sys.exit(1)
163
172
 
164
- build_dir = Path(args.build_dir)
165
-
166
173
  if args.command == "build":
174
+ build_dir = Path(args.build_dir)
167
175
  start_time = perf_counter()
168
176
  build_project(project, build_dir)
169
177
  end_time = perf_counter()
170
178
  print(f"Project built successfully to '{build_dir.resolve()}' in {end_time - start_time:.2f}s")
171
179
  elif args.command == "dev":
180
+ build_dir = Path(args.build_dir)
172
181
  start_time = perf_counter()
173
182
  build_collection(project, build_dir)
174
183
  end_time = perf_counter()
175
184
  print(f"Build finished in {end_time - start_time:.2f}s")
176
185
  run_server(build_dir / "site", port=args.port)
186
+ elif args.command == "schema":
187
+ print(json.dumps(get_project_schema(project), indent=2))
sonolus/build/compile.py CHANGED
@@ -1,15 +1,15 @@
1
1
  from collections.abc import Callable
2
2
 
3
3
  from sonolus.backend.finalize import cfg_to_engine_node
4
- from sonolus.backend.flow import BasicBlock
5
4
  from sonolus.backend.ir import IRConst, IRInstr
6
5
  from sonolus.backend.mode import Mode
7
6
  from sonolus.backend.ops import Op
8
- from sonolus.backend.optimize import optimize_and_allocate
7
+ from sonolus.backend.optimize.flow import BasicBlock
8
+ from sonolus.backend.optimize.optimize import optimize_and_allocate
9
9
  from sonolus.backend.visitor import compile_and_call
10
10
  from sonolus.build.node import OutputNodeGenerator
11
- from sonolus.script.archetype import BaseArchetype
12
- from sonolus.script.callbacks import CallbackInfo
11
+ from sonolus.script.archetype import _BaseArchetype
12
+ from sonolus.script.internal.callbacks import CallbackInfo
13
13
  from sonolus.script.internal.context import (
14
14
  CallbackContextState,
15
15
  Context,
@@ -19,13 +19,13 @@ from sonolus.script.internal.context import (
19
19
  ctx,
20
20
  using_ctx,
21
21
  )
22
- from sonolus.script.num import is_num
22
+ from sonolus.script.num import _is_num
23
23
 
24
24
 
25
25
  def compile_mode(
26
26
  mode: Mode,
27
27
  rom: ReadOnlyMemory,
28
- archetypes: list[type[BaseArchetype]] | None,
28
+ archetypes: list[type[_BaseArchetype]] | None,
29
29
  global_callbacks: list[tuple[CallbackInfo, Callable]] | None,
30
30
  ) -> dict:
31
31
  global_state = GlobalContextState(
@@ -74,7 +74,7 @@ def compile_mode(
74
74
 
75
75
 
76
76
  def callback_to_cfg(
77
- global_state: GlobalContextState, callback: Callable, name: str, archetype: type[BaseArchetype] | None = None
77
+ global_state: GlobalContextState, callback: Callable, name: str, archetype: type[_BaseArchetype] | None = None
78
78
  ) -> BasicBlock:
79
79
  callback_state = CallbackContextState(name)
80
80
  context = Context(global_state, callback_state)
@@ -83,6 +83,6 @@ def callback_to_cfg(
83
83
  result = compile_and_call(callback, archetype._for_compilation())
84
84
  else:
85
85
  result = compile_and_call(callback)
86
- if is_num(result):
86
+ if _is_num(result):
87
87
  ctx().add_statements(IRInstr(Op.Break, [IRConst(1), result.ir()]))
88
88
  return context_to_cfg(context)
sonolus/build/engine.py CHANGED
@@ -7,15 +7,20 @@ from pathlib import Path
7
7
 
8
8
  from sonolus.backend.mode import Mode
9
9
  from sonolus.build.compile import compile_mode
10
- from sonolus.script.archetype import BaseArchetype
10
+ from sonolus.script.archetype import _BaseArchetype
11
11
  from sonolus.script.bucket import Buckets
12
- from sonolus.script.callbacks import navigate_callback, preprocess_callback, update_callback, update_spawn_callback
13
12
  from sonolus.script.effect import Effects
14
13
  from sonolus.script.engine import EngineData
15
14
  from sonolus.script.instruction import (
16
15
  TutorialInstructionIcons,
17
16
  TutorialInstructions,
18
17
  )
18
+ from sonolus.script.internal.callbacks import (
19
+ navigate_callback,
20
+ preprocess_callback,
21
+ update_callback,
22
+ update_spawn_callback,
23
+ )
19
24
  from sonolus.script.internal.context import ReadOnlyMemory
20
25
  from sonolus.script.options import Options
21
26
  from sonolus.script.particle import Particles
@@ -101,7 +106,7 @@ def build_engine_configuration(
101
106
 
102
107
 
103
108
  def build_play_mode(
104
- archetypes: list[type[BaseArchetype]],
109
+ archetypes: list[type[_BaseArchetype]],
105
110
  skin: Skin,
106
111
  effects: Effects,
107
112
  particles: Particles,
@@ -118,7 +123,7 @@ def build_play_mode(
118
123
 
119
124
 
120
125
  def build_watch_mode(
121
- archetypes: list[type[BaseArchetype]],
126
+ archetypes: list[type[_BaseArchetype]],
122
127
  skin: Skin,
123
128
  effects: Effects,
124
129
  particles: Particles,
@@ -138,7 +143,7 @@ def build_watch_mode(
138
143
 
139
144
 
140
145
  def build_preview_mode(
141
- archetypes: list[type[BaseArchetype]],
146
+ archetypes: list[type[_BaseArchetype]],
142
147
  skin: Skin,
143
148
  rom: ReadOnlyMemory,
144
149
  ):
sonolus/build/project.py CHANGED
@@ -5,7 +5,7 @@ from sonolus.build.engine import package_engine
5
5
  from sonolus.build.level import package_level_data
6
6
  from sonolus.script.engine import Engine
7
7
  from sonolus.script.level import Level
8
- from sonolus.script.project import Project
8
+ from sonolus.script.project import Project, ProjectSchema
9
9
 
10
10
  BLANK_PNG = (
11
11
  b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x01\x00\x00\x00\x007n\xf9$"
@@ -92,3 +92,32 @@ def load_resources_files_to_collection(base_path: Path) -> Collection:
92
92
  collection.load_from_scp(path)
93
93
  collection.load_from_source(base_path)
94
94
  return collection
95
+
96
+
97
+ def get_project_schema(project: Project) -> ProjectSchema:
98
+ by_archetype: dict[str, dict[str, bool]] = {}
99
+ for archetype in project.engine.data.play.archetypes:
100
+ fields = by_archetype.setdefault(archetype.name, {})
101
+ # If a field is exported, we should exclude it if it's imported in watch mode
102
+ for field in archetype._exported_keys_:
103
+ fields[field] = False
104
+ for field in archetype._imported_keys_:
105
+ fields[field] = True
106
+ for archetype in project.engine.data.watch.archetypes:
107
+ fields = by_archetype.setdefault(archetype.name, {})
108
+ for field in archetype._imported_keys_:
109
+ if field not in fields:
110
+ fields[field] = True
111
+ for archetype in project.engine.data.preview.archetypes:
112
+ fields = by_archetype.setdefault(archetype.name, {})
113
+ for field in archetype._imported_keys_:
114
+ fields[field] = True
115
+ return {
116
+ "archetypes": [
117
+ {
118
+ "name": name,
119
+ "fields": [*fields],
120
+ }
121
+ for name, fields in by_archetype.items()
122
+ ]
123
+ }