zexus 1.7.1 → 1.7.2

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.
Files changed (159) hide show
  1. package/README.md +3 -3
  2. package/package.json +1 -1
  3. package/src/__init__.py +7 -0
  4. package/src/zexus/__init__.py +1 -1
  5. package/src/zexus/__pycache__/__init__.cpython-312.pyc +0 -0
  6. package/src/zexus/__pycache__/capability_system.cpython-312.pyc +0 -0
  7. package/src/zexus/__pycache__/debug_sanitizer.cpython-312.pyc +0 -0
  8. package/src/zexus/__pycache__/environment.cpython-312.pyc +0 -0
  9. package/src/zexus/__pycache__/error_reporter.cpython-312.pyc +0 -0
  10. package/src/zexus/__pycache__/input_validation.cpython-312.pyc +0 -0
  11. package/src/zexus/__pycache__/lexer.cpython-312.pyc +0 -0
  12. package/src/zexus/__pycache__/module_cache.cpython-312.pyc +0 -0
  13. package/src/zexus/__pycache__/module_manager.cpython-312.pyc +0 -0
  14. package/src/zexus/__pycache__/object.cpython-312.pyc +0 -0
  15. package/src/zexus/__pycache__/security.cpython-312.pyc +0 -0
  16. package/src/zexus/__pycache__/security_enforcement.cpython-312.pyc +0 -0
  17. package/src/zexus/__pycache__/syntax_validator.cpython-312.pyc +0 -0
  18. package/src/zexus/__pycache__/zexus_ast.cpython-312.pyc +0 -0
  19. package/src/zexus/__pycache__/zexus_token.cpython-312.pyc +0 -0
  20. package/src/zexus/access_control_system/__pycache__/__init__.cpython-312.pyc +0 -0
  21. package/src/zexus/access_control_system/__pycache__/access_control.cpython-312.pyc +0 -0
  22. package/src/zexus/advanced_types.py +17 -2
  23. package/src/zexus/blockchain/__init__.py +411 -0
  24. package/src/zexus/blockchain/accelerator.py +1160 -0
  25. package/src/zexus/blockchain/chain.py +660 -0
  26. package/src/zexus/blockchain/consensus.py +821 -0
  27. package/src/zexus/blockchain/contract_vm.py +1019 -0
  28. package/src/zexus/blockchain/crypto.py +79 -14
  29. package/src/zexus/blockchain/events.py +526 -0
  30. package/src/zexus/blockchain/loadtest.py +721 -0
  31. package/src/zexus/blockchain/monitoring.py +350 -0
  32. package/src/zexus/blockchain/mpt.py +716 -0
  33. package/src/zexus/blockchain/multichain.py +951 -0
  34. package/src/zexus/blockchain/multiprocess_executor.py +338 -0
  35. package/src/zexus/blockchain/network.py +886 -0
  36. package/src/zexus/blockchain/node.py +666 -0
  37. package/src/zexus/blockchain/rpc.py +1203 -0
  38. package/src/zexus/blockchain/rust_bridge.py +421 -0
  39. package/src/zexus/blockchain/storage.py +423 -0
  40. package/src/zexus/blockchain/tokens.py +750 -0
  41. package/src/zexus/blockchain/upgradeable.py +1004 -0
  42. package/src/zexus/blockchain/verification.py +1602 -0
  43. package/src/zexus/blockchain/wallet.py +621 -0
  44. package/src/zexus/cli/__pycache__/main.cpython-312.pyc +0 -0
  45. package/src/zexus/cli/main.py +300 -20
  46. package/src/zexus/cli/zpm.py +1 -1
  47. package/src/zexus/compiler/__pycache__/bytecode.cpython-312.pyc +0 -0
  48. package/src/zexus/compiler/__pycache__/lexer.cpython-312.pyc +0 -0
  49. package/src/zexus/compiler/__pycache__/parser.cpython-312.pyc +0 -0
  50. package/src/zexus/compiler/__pycache__/semantic.cpython-312.pyc +0 -0
  51. package/src/zexus/compiler/__pycache__/zexus_ast.cpython-312.pyc +0 -0
  52. package/src/zexus/compiler/lexer.py +10 -5
  53. package/src/zexus/concurrency_system.py +79 -0
  54. package/src/zexus/config.py +54 -0
  55. package/src/zexus/crypto_bridge.py +244 -8
  56. package/src/zexus/dap/__init__.py +10 -0
  57. package/src/zexus/dap/__main__.py +4 -0
  58. package/src/zexus/dap/dap_server.py +391 -0
  59. package/src/zexus/dap/debug_engine.py +298 -0
  60. package/src/zexus/environment.py +10 -1
  61. package/src/zexus/evaluator/__pycache__/bytecode_compiler.cpython-312.pyc +0 -0
  62. package/src/zexus/evaluator/__pycache__/core.cpython-312.pyc +0 -0
  63. package/src/zexus/evaluator/__pycache__/expressions.cpython-312.pyc +0 -0
  64. package/src/zexus/evaluator/__pycache__/functions.cpython-312.pyc +0 -0
  65. package/src/zexus/evaluator/__pycache__/resource_limiter.cpython-312.pyc +0 -0
  66. package/src/zexus/evaluator/__pycache__/statements.cpython-312.pyc +0 -0
  67. package/src/zexus/evaluator/__pycache__/unified_execution.cpython-312.pyc +0 -0
  68. package/src/zexus/evaluator/__pycache__/utils.cpython-312.pyc +0 -0
  69. package/src/zexus/evaluator/bytecode_compiler.py +441 -37
  70. package/src/zexus/evaluator/core.py +560 -49
  71. package/src/zexus/evaluator/expressions.py +122 -49
  72. package/src/zexus/evaluator/functions.py +417 -16
  73. package/src/zexus/evaluator/statements.py +521 -118
  74. package/src/zexus/evaluator/unified_execution.py +573 -72
  75. package/src/zexus/evaluator/utils.py +14 -2
  76. package/src/zexus/event_loop.py +186 -0
  77. package/src/zexus/lexer.py +742 -486
  78. package/src/zexus/lsp/__init__.py +1 -1
  79. package/src/zexus/lsp/definition_provider.py +163 -9
  80. package/src/zexus/lsp/server.py +22 -8
  81. package/src/zexus/lsp/symbol_provider.py +182 -9
  82. package/src/zexus/module_cache.py +237 -9
  83. package/src/zexus/object.py +64 -6
  84. package/src/zexus/parser/__pycache__/parser.cpython-312.pyc +0 -0
  85. package/src/zexus/parser/__pycache__/strategy_context.cpython-312.pyc +0 -0
  86. package/src/zexus/parser/__pycache__/strategy_structural.cpython-312.pyc +0 -0
  87. package/src/zexus/parser/parser.py +786 -285
  88. package/src/zexus/parser/strategy_context.py +407 -66
  89. package/src/zexus/parser/strategy_structural.py +117 -19
  90. package/src/zexus/persistence.py +15 -1
  91. package/src/zexus/renderer/__init__.py +15 -0
  92. package/src/zexus/renderer/__pycache__/__init__.cpython-312.pyc +0 -0
  93. package/src/zexus/renderer/__pycache__/backend.cpython-312.pyc +0 -0
  94. package/src/zexus/renderer/__pycache__/canvas.cpython-312.pyc +0 -0
  95. package/src/zexus/renderer/__pycache__/color_system.cpython-312.pyc +0 -0
  96. package/src/zexus/renderer/__pycache__/layout.cpython-312.pyc +0 -0
  97. package/src/zexus/renderer/__pycache__/main_renderer.cpython-312.pyc +0 -0
  98. package/src/zexus/renderer/__pycache__/painter.cpython-312.pyc +0 -0
  99. package/src/zexus/renderer/tk_backend.py +208 -0
  100. package/src/zexus/renderer/web_backend.py +260 -0
  101. package/src/zexus/runtime/__pycache__/__init__.cpython-312.pyc +0 -0
  102. package/src/zexus/runtime/__pycache__/async_runtime.cpython-312.pyc +0 -0
  103. package/src/zexus/runtime/__pycache__/load_manager.cpython-312.pyc +0 -0
  104. package/src/zexus/runtime/file_flags.py +137 -0
  105. package/src/zexus/safety/__pycache__/__init__.cpython-312.pyc +0 -0
  106. package/src/zexus/safety/__pycache__/memory_safety.cpython-312.pyc +0 -0
  107. package/src/zexus/security.py +424 -34
  108. package/src/zexus/stdlib/fs.py +23 -18
  109. package/src/zexus/stdlib/http.py +289 -186
  110. package/src/zexus/stdlib/sockets.py +207 -163
  111. package/src/zexus/stdlib/websockets.py +282 -0
  112. package/src/zexus/stdlib_integration.py +369 -2
  113. package/src/zexus/strategy_recovery.py +6 -3
  114. package/src/zexus/type_checker.py +423 -0
  115. package/src/zexus/virtual_filesystem.py +189 -2
  116. package/src/zexus/vm/__init__.py +113 -3
  117. package/src/zexus/vm/__pycache__/async_optimizer.cpython-312.pyc +0 -0
  118. package/src/zexus/vm/__pycache__/bytecode.cpython-312.pyc +0 -0
  119. package/src/zexus/vm/__pycache__/bytecode_converter.cpython-312.pyc +0 -0
  120. package/src/zexus/vm/__pycache__/cache.cpython-312.pyc +0 -0
  121. package/src/zexus/vm/__pycache__/compiler.cpython-312.pyc +0 -0
  122. package/src/zexus/vm/__pycache__/gas_metering.cpython-312.pyc +0 -0
  123. package/src/zexus/vm/__pycache__/jit.cpython-312.pyc +0 -0
  124. package/src/zexus/vm/__pycache__/parallel_vm.cpython-312.pyc +0 -0
  125. package/src/zexus/vm/__pycache__/vm.cpython-312.pyc +0 -0
  126. package/src/zexus/vm/async_optimizer.py +14 -1
  127. package/src/zexus/vm/binary_bytecode.py +659 -0
  128. package/src/zexus/vm/bytecode.py +28 -1
  129. package/src/zexus/vm/bytecode_converter.py +26 -12
  130. package/src/zexus/vm/cabi.c +1985 -0
  131. package/src/zexus/vm/cabi.cpython-312-x86_64-linux-gnu.so +0 -0
  132. package/src/zexus/vm/cabi.h +127 -0
  133. package/src/zexus/vm/cache.py +557 -17
  134. package/src/zexus/vm/compiler.py +703 -5
  135. package/src/zexus/vm/fastops.c +15743 -0
  136. package/src/zexus/vm/fastops.cpython-312-x86_64-linux-gnu.so +0 -0
  137. package/src/zexus/vm/fastops.pyx +288 -0
  138. package/src/zexus/vm/gas_metering.py +50 -9
  139. package/src/zexus/vm/jit.py +83 -2
  140. package/src/zexus/vm/native_jit_backend.py +1816 -0
  141. package/src/zexus/vm/native_runtime.cpp +1388 -0
  142. package/src/zexus/vm/native_runtime.cpython-312-x86_64-linux-gnu.so +0 -0
  143. package/src/zexus/vm/optimizer.py +161 -11
  144. package/src/zexus/vm/parallel_vm.py +118 -42
  145. package/src/zexus/vm/peephole_optimizer.py +82 -4
  146. package/src/zexus/vm/profiler.py +38 -18
  147. package/src/zexus/vm/register_allocator.py +16 -5
  148. package/src/zexus/vm/register_vm.py +8 -5
  149. package/src/zexus/vm/vm.py +3411 -573
  150. package/src/zexus/vm/wasm_compiler.py +658 -0
  151. package/src/zexus/zexus_ast.py +63 -11
  152. package/src/zexus/zexus_token.py +13 -5
  153. package/src/zexus/zpm/installer.py +55 -15
  154. package/src/zexus/zpm/package_manager.py +1 -1
  155. package/src/zexus/zpm/registry.py +257 -28
  156. package/src/zexus.egg-info/PKG-INFO +7 -4
  157. package/src/zexus.egg-info/SOURCES.txt +116 -9
  158. package/src/zexus.egg-info/entry_points.txt +1 -0
  159. package/src/zexus.egg-info/requires.txt +4 -0
@@ -0,0 +1,260 @@
1
+ """
2
+ Web GUI Backend for the Zexus Renderer.
3
+
4
+ Serves the rendered UI as HTML over a local HTTP server. The evaluator
5
+ creates screens/components normally and then calls ``show_screen()`` which
6
+ opens a browser tab to ``http://localhost:<port>/``.
7
+
8
+ The server uses only the Python standard library (``http.server`` +
9
+ ``json``). No Flask/Django/etc. dependency.
10
+
11
+ Usage from Zexus::
12
+
13
+ @zexus gui_backend = "web"
14
+
15
+ screen dashboard {
16
+ title: "Dashboard"
17
+ width: 600
18
+ height: 400
19
+ }
20
+
21
+ component counter label {
22
+ text: "Count: 0"
23
+ x: 20
24
+ y: 30
25
+ }
26
+
27
+ add counter to dashboard
28
+ show dashboard
29
+ """
30
+
31
+ from __future__ import annotations
32
+
33
+ import json
34
+ import os
35
+ import socket
36
+ import threading
37
+ import webbrowser
38
+ from http.server import HTTPServer, BaseHTTPRequestHandler
39
+ from typing import Any, Dict, List, Optional
40
+
41
+ from .layout import Screen, ScreenComponent, ScreenRegistry, Button, Label, TextBox
42
+ from .canvas import Canvas, CanvasRegistry
43
+ from .color_system import RGBColor
44
+
45
+
46
+ # ---------------------------------------------------------------------------
47
+ # HTML generation
48
+ # ---------------------------------------------------------------------------
49
+
50
+ _HTML_TEMPLATE = """\
51
+ <!DOCTYPE html>
52
+ <html lang="en">
53
+ <head>
54
+ <meta charset="UTF-8">
55
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
56
+ <title>{title}</title>
57
+ <style>
58
+ * {{ margin: 0; padding: 0; box-sizing: border-box; }}
59
+ body {{ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
60
+ background: {bg}; }}
61
+ .zx-screen {{ position: relative; width: {width}px; height: {height}px;
62
+ margin: 20px auto; border: 1px solid #ddd; border-radius: 8px;
63
+ background: {bg}; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,.12); }}
64
+ .zx-label {{ position: absolute; }}
65
+ .zx-button {{ position: absolute; padding: 6px 16px; border: 1px solid #888;
66
+ border-radius: 4px; cursor: pointer; background: #f4f4f4; }}
67
+ .zx-button:hover {{ background: #e0e0e0; }}
68
+ .zx-textbox {{ position: absolute; padding: 4px 8px; border: 1px solid #aaa;
69
+ border-radius: 3px; }}
70
+ .zx-canvas {{ position: relative; }}
71
+ </style>
72
+ </head>
73
+ <body>
74
+ <div class="zx-screen">
75
+ {components}
76
+ </div>
77
+ {canvas_section}
78
+ <script>
79
+ // Event relay — POST click events back to /event
80
+ document.querySelectorAll('.zx-button').forEach(btn => {{
81
+ btn.addEventListener('click', () => {{
82
+ fetch('/event', {{
83
+ method: 'POST',
84
+ headers: {{'Content-Type': 'application/json'}},
85
+ body: JSON.stringify({{component: btn.dataset.name, event: 'click'}})
86
+ }});
87
+ }});
88
+ }});
89
+ </script>
90
+ </body>
91
+ </html>
92
+ """
93
+
94
+
95
+ def _component_html(comp: ScreenComponent) -> str:
96
+ x = int(comp.get("x", 10))
97
+ y = int(comp.get("y", 10))
98
+ color = comp.get("color", "black")
99
+ text = comp.get("text", comp.name)
100
+
101
+ if isinstance(comp, Button):
102
+ return (f'<button class="zx-button" data-name="{comp.name}" '
103
+ f'style="left:{x}px;top:{y}px;color:{color}">{text}</button>')
104
+ if isinstance(comp, TextBox):
105
+ w = int(comp.get("width", 20))
106
+ return (f'<input class="zx-textbox" '
107
+ f'style="left:{x}px;top:{y}px;width:{w*8}px;color:{color}" '
108
+ f'value="{text}" />')
109
+ # Default: Label
110
+ size = int(comp.get("fontSize", 14))
111
+ return (f'<span class="zx-label" '
112
+ f'style="left:{x}px;top:{y}px;font-size:{size}px;color:{color}">{text}</span>')
113
+
114
+
115
+ def _canvas_svg(canvas: Canvas) -> str:
116
+ """Render a ``Canvas`` as an inline SVG element."""
117
+ scale = 4
118
+ w, h = canvas.width * scale, canvas.height * scale
119
+ lines: List[str] = [f'<svg class="zx-canvas" width="{w}" height="{h}" '
120
+ f'style="margin:20px auto;display:block;border:1px solid #ddd">']
121
+ for op_type, args in canvas.operations:
122
+ if op_type == "line":
123
+ x1, y1, x2, y2 = args
124
+ lines.append(f'<line x1="{x1*scale}" y1="{y1*scale}" '
125
+ f'x2="{x2*scale}" y2="{y2*scale}" stroke="black" stroke-width="2"/>')
126
+ elif op_type == "text":
127
+ x, y, text = args
128
+ lines.append(f'<text x="{x*scale}" y="{y*scale+12}">{text}</text>')
129
+ lines.append("</svg>")
130
+ return "\n".join(lines)
131
+
132
+
133
+ def build_html(screen: Screen, canvases: Optional[Dict[str, Canvas]] = None) -> str:
134
+ title = str(screen.get("title", screen.name))
135
+ width = int(screen.get("width", 600))
136
+ height = int(screen.get("height", 400))
137
+ bg = str(screen.get("background", "#ffffff"))
138
+
139
+ components = "\n".join(_component_html(c) for c in screen.children)
140
+ canvas_section = ""
141
+ if canvases:
142
+ canvas_section = "\n".join(_canvas_svg(c) for c in canvases.values())
143
+
144
+ return _HTML_TEMPLATE.format(
145
+ title=title, width=width, height=height, bg=bg,
146
+ components=components, canvas_section=canvas_section,
147
+ )
148
+
149
+
150
+ # ---------------------------------------------------------------------------
151
+ # HTTP server
152
+ # ---------------------------------------------------------------------------
153
+
154
+ class _Handler(BaseHTTPRequestHandler):
155
+ """Serves the screen HTML and accepts event POSTs."""
156
+
157
+ backend: "WebBackend" # set on class before server starts
158
+
159
+ def do_GET(self):
160
+ html = self.backend._current_html or "<h1>No screen loaded</h1>"
161
+ self.send_response(200)
162
+ self.send_header("Content-Type", "text/html; charset=utf-8")
163
+ self.end_headers()
164
+ self.wfile.write(html.encode())
165
+
166
+ def do_POST(self):
167
+ length = int(self.headers.get("Content-Length", 0))
168
+ body = self.rfile.read(length)
169
+ try:
170
+ data = json.loads(body)
171
+ comp_name = data.get("component", "")
172
+ event = data.get("event", "")
173
+ handler = self.backend._event_handlers.get(f"{comp_name}:{event}")
174
+ if handler:
175
+ handler()
176
+ except Exception:
177
+ pass
178
+ self.send_response(200)
179
+ self.send_header("Content-Type", "application/json")
180
+ self.end_headers()
181
+ self.wfile.write(b'{"ok":true}')
182
+
183
+ def log_message(self, format, *args):
184
+ pass # silence request logs
185
+
186
+
187
+ # ---------------------------------------------------------------------------
188
+ # WebBackend
189
+ # ---------------------------------------------------------------------------
190
+
191
+ class WebBackend:
192
+ """Serves Zexus UI as HTML on a local HTTP port."""
193
+
194
+ def __init__(self, screen_registry: Optional[ScreenRegistry] = None,
195
+ canvas_registry: Optional[CanvasRegistry] = None,
196
+ port: int = 0) -> None:
197
+ self.screen_registry = screen_registry or ScreenRegistry()
198
+ self.canvas_registry = canvas_registry or CanvasRegistry()
199
+ self._port = port
200
+ self._server: Optional[HTTPServer] = None
201
+ self._thread: Optional[threading.Thread] = None
202
+ self._current_html: Optional[str] = None
203
+ self._event_handlers: Dict[str, Any] = {}
204
+
205
+ @property
206
+ def url(self) -> str:
207
+ if self._server:
208
+ return f"http://localhost:{self._server.server_address[1]}"
209
+ return ""
210
+
211
+ # -- Lifecycle ---------------------------------------------------------
212
+
213
+ def start(self) -> None:
214
+ handler_cls = type("H", (_Handler,), {"backend": self})
215
+ self._server = HTTPServer(("127.0.0.1", self._port), handler_cls)
216
+ self._port = self._server.server_address[1]
217
+ self._thread = threading.Thread(target=self._server.serve_forever, daemon=True)
218
+ self._thread.start()
219
+
220
+ def stop(self) -> None:
221
+ if self._server:
222
+ self._server.shutdown()
223
+
224
+ # -- Screen rendering --------------------------------------------------
225
+
226
+ def show_screen(self, name: str, open_browser: bool = True) -> str:
227
+ """Build HTML from a registered screen and serve it.
228
+
229
+ Returns the URL.
230
+ """
231
+ if self._server is None:
232
+ self.start()
233
+
234
+ screen = self.screen_registry.get_screen(name)
235
+ canvases = self.canvas_registry.snapshot() if self.canvas_registry else None
236
+ # Convert snapshot dicts back to Canvas objects for rendering
237
+ canvas_objs: Dict[str, Canvas] = {}
238
+ if self.canvas_registry:
239
+ canvas_objs = dict(self.canvas_registry.canvases)
240
+ self._current_html = build_html(screen, canvas_objs or None)
241
+
242
+ url = self.url
243
+ if open_browser:
244
+ webbrowser.open(url)
245
+ return url
246
+
247
+ # -- Event binding -----------------------------------------------------
248
+
249
+ def on(self, component_name: str, event: str, handler) -> None:
250
+ self._event_handlers[f"{component_name}:{event}"] = handler
251
+
252
+
253
+ # ---------------------------------------------------------------------------
254
+ # Factory
255
+ # ---------------------------------------------------------------------------
256
+
257
+ def create_web_backend(**kwargs) -> WebBackend:
258
+ backend = WebBackend(**kwargs)
259
+ backend.start()
260
+ return backend
@@ -0,0 +1,137 @@
1
+ """Parse and apply inline file flags for Zexus execution.
2
+
3
+ Supported directive formats (first 25 lines):
4
+ - // @zexus: {"use_vm": true, "vm_mode": "stack", "no_optimize": false}
5
+ - # @zexus: use_vm=true; vm_mode=auto; debug=full
6
+
7
+ Values accept booleans, ints, floats, or strings.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from typing import Any, Dict, Optional
13
+ import json
14
+ import re
15
+
16
+ _MAX_SCAN_LINES = 25
17
+
18
+
19
+ def parse_file_flags(source: str) -> Dict[str, Any]:
20
+ flags: Dict[str, Any] = {}
21
+ if not source:
22
+ return flags
23
+
24
+ lines = source.splitlines()[:_MAX_SCAN_LINES]
25
+ for line in lines:
26
+ stripped = line.strip()
27
+ if not stripped:
28
+ continue
29
+ if "@zexus" not in stripped:
30
+ continue
31
+
32
+ # Strip leading comment markers
33
+ directive = stripped
34
+ for prefix in ("//", "#", "/*", "*/"):
35
+ if directive.startswith(prefix):
36
+ directive = directive[len(prefix):].strip()
37
+ # Remove leading @zexus marker
38
+ if directive.lower().startswith("@zexus"):
39
+ directive = directive[len("@zexus"):].strip()
40
+ if directive.startswith(":"):
41
+ directive = directive[1:].strip()
42
+
43
+ # JSON object form
44
+ if "{" in directive:
45
+ json_part = directive[directive.find("{"):].strip()
46
+ try:
47
+ parsed = json.loads(json_part)
48
+ if isinstance(parsed, dict):
49
+ flags.update(parsed)
50
+ except Exception:
51
+ pass
52
+ continue
53
+
54
+ # key=value form (semicolon or comma separated)
55
+ for part in re.split(r"[;,]", directive):
56
+ part = part.strip()
57
+ if not part:
58
+ continue
59
+ if "=" not in part:
60
+ continue
61
+ key, raw_val = part.split("=", 1)
62
+ key = key.strip()
63
+ raw_val = raw_val.strip()
64
+ flags[key] = _parse_value(raw_val)
65
+
66
+ return flags
67
+
68
+
69
+ def _parse_value(raw: str) -> Any:
70
+ if not raw:
71
+ return raw
72
+ lowered = raw.lower()
73
+ if lowered in ("true", "yes", "on"):
74
+ return True
75
+ if lowered in ("false", "no", "off"):
76
+ return False
77
+ # numbers
78
+ try:
79
+ if "." in raw:
80
+ return float(raw)
81
+ return int(raw)
82
+ except Exception:
83
+ pass
84
+ # quoted string
85
+ if (raw.startswith("\"") and raw.endswith("\"")) or (raw.startswith("'") and raw.endswith("'")):
86
+ return raw[1:-1]
87
+ return raw
88
+
89
+
90
+ def apply_vm_config(vm, vm_config: Dict[str, Any]) -> None:
91
+ if not vm_config:
92
+ return
93
+
94
+ mode_value = vm_config.get("mode")
95
+ if isinstance(mode_value, str):
96
+ try:
97
+ from ..vm.vm import VMMode
98
+ vm.mode = VMMode(mode_value.lower())
99
+ except Exception:
100
+ pass
101
+
102
+ # Explicit gas metering disable
103
+ if vm_config.get("enable_gas_metering") is False:
104
+ try:
105
+ vm.enable_gas_metering = False
106
+ vm.gas_metering = None
107
+ except Exception:
108
+ pass
109
+
110
+ # perf fast dispatch
111
+ if vm_config.get("perf_fast_dispatch") is True:
112
+ try:
113
+ vm._perf_fast_dispatch = True
114
+ except Exception:
115
+ pass
116
+
117
+ if vm_config.get("prefer_register") is True:
118
+ try:
119
+ vm.prefer_register = True
120
+ except Exception:
121
+ pass
122
+
123
+ if vm_config.get("prefer_parallel") is True:
124
+ try:
125
+ vm.prefer_parallel = True
126
+ except Exception:
127
+ pass
128
+
129
+ # generic attribute setters
130
+ for key, value in vm_config.items():
131
+ if key == "mode":
132
+ continue
133
+ if hasattr(vm, key):
134
+ try:
135
+ setattr(vm, key, value)
136
+ except Exception:
137
+ continue