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.
- package/README.md +3 -3
- package/package.json +1 -1
- package/src/__init__.py +7 -0
- package/src/zexus/__init__.py +1 -1
- package/src/zexus/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/capability_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/debug_sanitizer.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/environment.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/error_reporter.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/input_validation.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/lexer.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/module_cache.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/module_manager.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/object.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/security.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/security_enforcement.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/syntax_validator.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/zexus_ast.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/zexus_token.cpython-312.pyc +0 -0
- package/src/zexus/access_control_system/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/access_control_system/__pycache__/access_control.cpython-312.pyc +0 -0
- package/src/zexus/advanced_types.py +17 -2
- package/src/zexus/blockchain/__init__.py +411 -0
- package/src/zexus/blockchain/accelerator.py +1160 -0
- package/src/zexus/blockchain/chain.py +660 -0
- package/src/zexus/blockchain/consensus.py +821 -0
- package/src/zexus/blockchain/contract_vm.py +1019 -0
- package/src/zexus/blockchain/crypto.py +79 -14
- package/src/zexus/blockchain/events.py +526 -0
- package/src/zexus/blockchain/loadtest.py +721 -0
- package/src/zexus/blockchain/monitoring.py +350 -0
- package/src/zexus/blockchain/mpt.py +716 -0
- package/src/zexus/blockchain/multichain.py +951 -0
- package/src/zexus/blockchain/multiprocess_executor.py +338 -0
- package/src/zexus/blockchain/network.py +886 -0
- package/src/zexus/blockchain/node.py +666 -0
- package/src/zexus/blockchain/rpc.py +1203 -0
- package/src/zexus/blockchain/rust_bridge.py +421 -0
- package/src/zexus/blockchain/storage.py +423 -0
- package/src/zexus/blockchain/tokens.py +750 -0
- package/src/zexus/blockchain/upgradeable.py +1004 -0
- package/src/zexus/blockchain/verification.py +1602 -0
- package/src/zexus/blockchain/wallet.py +621 -0
- package/src/zexus/cli/__pycache__/main.cpython-312.pyc +0 -0
- package/src/zexus/cli/main.py +300 -20
- package/src/zexus/cli/zpm.py +1 -1
- package/src/zexus/compiler/__pycache__/bytecode.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/lexer.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/parser.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/semantic.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/zexus_ast.cpython-312.pyc +0 -0
- package/src/zexus/compiler/lexer.py +10 -5
- package/src/zexus/concurrency_system.py +79 -0
- package/src/zexus/config.py +54 -0
- package/src/zexus/crypto_bridge.py +244 -8
- package/src/zexus/dap/__init__.py +10 -0
- package/src/zexus/dap/__main__.py +4 -0
- package/src/zexus/dap/dap_server.py +391 -0
- package/src/zexus/dap/debug_engine.py +298 -0
- package/src/zexus/environment.py +10 -1
- package/src/zexus/evaluator/__pycache__/bytecode_compiler.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/core.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/expressions.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/functions.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/resource_limiter.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/statements.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/unified_execution.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/utils.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/bytecode_compiler.py +441 -37
- package/src/zexus/evaluator/core.py +560 -49
- package/src/zexus/evaluator/expressions.py +122 -49
- package/src/zexus/evaluator/functions.py +417 -16
- package/src/zexus/evaluator/statements.py +521 -118
- package/src/zexus/evaluator/unified_execution.py +573 -72
- package/src/zexus/evaluator/utils.py +14 -2
- package/src/zexus/event_loop.py +186 -0
- package/src/zexus/lexer.py +742 -486
- package/src/zexus/lsp/__init__.py +1 -1
- package/src/zexus/lsp/definition_provider.py +163 -9
- package/src/zexus/lsp/server.py +22 -8
- package/src/zexus/lsp/symbol_provider.py +182 -9
- package/src/zexus/module_cache.py +237 -9
- package/src/zexus/object.py +64 -6
- package/src/zexus/parser/__pycache__/parser.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/strategy_context.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/strategy_structural.cpython-312.pyc +0 -0
- package/src/zexus/parser/parser.py +786 -285
- package/src/zexus/parser/strategy_context.py +407 -66
- package/src/zexus/parser/strategy_structural.py +117 -19
- package/src/zexus/persistence.py +15 -1
- package/src/zexus/renderer/__init__.py +15 -0
- package/src/zexus/renderer/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/renderer/__pycache__/backend.cpython-312.pyc +0 -0
- package/src/zexus/renderer/__pycache__/canvas.cpython-312.pyc +0 -0
- package/src/zexus/renderer/__pycache__/color_system.cpython-312.pyc +0 -0
- package/src/zexus/renderer/__pycache__/layout.cpython-312.pyc +0 -0
- package/src/zexus/renderer/__pycache__/main_renderer.cpython-312.pyc +0 -0
- package/src/zexus/renderer/__pycache__/painter.cpython-312.pyc +0 -0
- package/src/zexus/renderer/tk_backend.py +208 -0
- package/src/zexus/renderer/web_backend.py +260 -0
- package/src/zexus/runtime/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/runtime/__pycache__/async_runtime.cpython-312.pyc +0 -0
- package/src/zexus/runtime/__pycache__/load_manager.cpython-312.pyc +0 -0
- package/src/zexus/runtime/file_flags.py +137 -0
- package/src/zexus/safety/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/safety/__pycache__/memory_safety.cpython-312.pyc +0 -0
- package/src/zexus/security.py +424 -34
- package/src/zexus/stdlib/fs.py +23 -18
- package/src/zexus/stdlib/http.py +289 -186
- package/src/zexus/stdlib/sockets.py +207 -163
- package/src/zexus/stdlib/websockets.py +282 -0
- package/src/zexus/stdlib_integration.py +369 -2
- package/src/zexus/strategy_recovery.py +6 -3
- package/src/zexus/type_checker.py +423 -0
- package/src/zexus/virtual_filesystem.py +189 -2
- package/src/zexus/vm/__init__.py +113 -3
- package/src/zexus/vm/__pycache__/async_optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/bytecode.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/bytecode_converter.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/cache.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/compiler.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/gas_metering.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/jit.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/parallel_vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/async_optimizer.py +14 -1
- package/src/zexus/vm/binary_bytecode.py +659 -0
- package/src/zexus/vm/bytecode.py +28 -1
- package/src/zexus/vm/bytecode_converter.py +26 -12
- package/src/zexus/vm/cabi.c +1985 -0
- package/src/zexus/vm/cabi.cpython-312-x86_64-linux-gnu.so +0 -0
- package/src/zexus/vm/cabi.h +127 -0
- package/src/zexus/vm/cache.py +557 -17
- package/src/zexus/vm/compiler.py +703 -5
- package/src/zexus/vm/fastops.c +15743 -0
- package/src/zexus/vm/fastops.cpython-312-x86_64-linux-gnu.so +0 -0
- package/src/zexus/vm/fastops.pyx +288 -0
- package/src/zexus/vm/gas_metering.py +50 -9
- package/src/zexus/vm/jit.py +83 -2
- package/src/zexus/vm/native_jit_backend.py +1816 -0
- package/src/zexus/vm/native_runtime.cpp +1388 -0
- package/src/zexus/vm/native_runtime.cpython-312-x86_64-linux-gnu.so +0 -0
- package/src/zexus/vm/optimizer.py +161 -11
- package/src/zexus/vm/parallel_vm.py +118 -42
- package/src/zexus/vm/peephole_optimizer.py +82 -4
- package/src/zexus/vm/profiler.py +38 -18
- package/src/zexus/vm/register_allocator.py +16 -5
- package/src/zexus/vm/register_vm.py +8 -5
- package/src/zexus/vm/vm.py +3411 -573
- package/src/zexus/vm/wasm_compiler.py +658 -0
- package/src/zexus/zexus_ast.py +63 -11
- package/src/zexus/zexus_token.py +13 -5
- package/src/zexus/zpm/installer.py +55 -15
- package/src/zexus/zpm/package_manager.py +1 -1
- package/src/zexus/zpm/registry.py +257 -28
- package/src/zexus.egg-info/PKG-INFO +7 -4
- package/src/zexus.egg-info/SOURCES.txt +116 -9
- package/src/zexus.egg-info/entry_points.txt +1 -0
- 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
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|
|
Binary file
|
|
Binary file
|