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,298 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Debug Engine — breakpoint / stepping state machine.
|
|
3
|
+
|
|
4
|
+
The engine is attached to the evaluator and consulted before every AST
|
|
5
|
+
node is dispatched. When a stop condition is met the engine parks the
|
|
6
|
+
execution thread on an ``Event`` and waits for the DAP front-end to
|
|
7
|
+
resume it.
|
|
8
|
+
|
|
9
|
+
Thread model
|
|
10
|
+
~~~~~~~~~~~~
|
|
11
|
+
* **Execution thread** — runs the Zexus program via the evaluator.
|
|
12
|
+
Calls ``DebugEngine.check()`` before each node.
|
|
13
|
+
* **DAP I/O thread** — reads DAP JSON messages, mutates engine state,
|
|
14
|
+
and signals the execution thread to continue.
|
|
15
|
+
|
|
16
|
+
Locking: a single ``threading.Condition`` guards all mutable state.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import threading
|
|
22
|
+
from dataclasses import dataclass, field
|
|
23
|
+
from enum import Enum, auto
|
|
24
|
+
from typing import Any, Callable, Dict, List, Optional, Set, Tuple
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# ---------------------------------------------------------------------------
|
|
28
|
+
# Public types
|
|
29
|
+
# ---------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
class StopReason(Enum):
|
|
32
|
+
BREAKPOINT = auto()
|
|
33
|
+
STEP = auto()
|
|
34
|
+
PAUSE = auto()
|
|
35
|
+
ENTRY = auto()
|
|
36
|
+
EXCEPTION = auto()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class StepMode(Enum):
|
|
40
|
+
CONTINUE = auto()
|
|
41
|
+
STEP_OVER = auto()
|
|
42
|
+
STEP_INTO = auto()
|
|
43
|
+
STEP_OUT = auto()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass
|
|
47
|
+
class Breakpoint:
|
|
48
|
+
id: int
|
|
49
|
+
file: str
|
|
50
|
+
line: int
|
|
51
|
+
condition: Optional[str] = None
|
|
52
|
+
hit_count: int = 0
|
|
53
|
+
enabled: bool = True
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass
|
|
57
|
+
class StackFrame:
|
|
58
|
+
id: int
|
|
59
|
+
name: str
|
|
60
|
+
file: str
|
|
61
|
+
line: int
|
|
62
|
+
column: int = 0
|
|
63
|
+
variables: Dict[str, Any] = field(default_factory=dict)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# ---------------------------------------------------------------------------
|
|
67
|
+
# Engine
|
|
68
|
+
# ---------------------------------------------------------------------------
|
|
69
|
+
|
|
70
|
+
class DebugEngine:
|
|
71
|
+
"""Breakpoint / stepping state machine consulted by the evaluator."""
|
|
72
|
+
|
|
73
|
+
def __init__(self) -> None:
|
|
74
|
+
self._lock = threading.Condition()
|
|
75
|
+
self._paused = False
|
|
76
|
+
self._stop_reason: Optional[StopReason] = None
|
|
77
|
+
self._step_mode: StepMode = StepMode.CONTINUE
|
|
78
|
+
self._step_depth: int = 0 # call depth at step start
|
|
79
|
+
self._stop_on_entry: bool = False
|
|
80
|
+
|
|
81
|
+
# Breakpoints: file -> {line -> Breakpoint}
|
|
82
|
+
self._breakpoints: Dict[str, Dict[int, Breakpoint]] = {}
|
|
83
|
+
self._bp_id_counter: int = 0
|
|
84
|
+
|
|
85
|
+
# Current execution state (updated by evaluator hook)
|
|
86
|
+
self._current_file: str = ""
|
|
87
|
+
self._current_line: int = 0
|
|
88
|
+
self._call_depth: int = 0
|
|
89
|
+
self._call_stack: List[StackFrame] = []
|
|
90
|
+
self._frame_id_counter: int = 0
|
|
91
|
+
|
|
92
|
+
# Callback fired when execution stops (DAP server sends stopped event)
|
|
93
|
+
self.on_stopped: Optional[Callable[[StopReason, str], None]] = None
|
|
94
|
+
# Callback fired when execution completes
|
|
95
|
+
self.on_terminated: Optional[Callable[[], None]] = None
|
|
96
|
+
|
|
97
|
+
self._terminated = False
|
|
98
|
+
|
|
99
|
+
# -- Evaluator hook (called from eval_node) ----------------------------
|
|
100
|
+
|
|
101
|
+
def check(self, file: str, line: int, env: Any = None) -> None:
|
|
102
|
+
"""Called by the evaluator **before** dispatching each AST node.
|
|
103
|
+
|
|
104
|
+
If a stop condition is met the calling thread parks here until the
|
|
105
|
+
DAP server calls ``continue_execution()`` or a step variant.
|
|
106
|
+
"""
|
|
107
|
+
if self._terminated:
|
|
108
|
+
return
|
|
109
|
+
|
|
110
|
+
with self._lock:
|
|
111
|
+
self._current_file = file
|
|
112
|
+
self._current_line = line
|
|
113
|
+
|
|
114
|
+
# Update top frame
|
|
115
|
+
if self._call_stack:
|
|
116
|
+
self._call_stack[-1].line = line
|
|
117
|
+
if env:
|
|
118
|
+
self._call_stack[-1].variables = self._extract_vars(env)
|
|
119
|
+
|
|
120
|
+
reason = self._should_stop(file, line)
|
|
121
|
+
if reason is None:
|
|
122
|
+
return
|
|
123
|
+
|
|
124
|
+
self._paused = True
|
|
125
|
+
self._stop_reason = reason
|
|
126
|
+
|
|
127
|
+
# Notify DAP server (outside lock)
|
|
128
|
+
if self.on_stopped:
|
|
129
|
+
self.on_stopped(reason, f"{file}:{line}")
|
|
130
|
+
|
|
131
|
+
# Park execution thread
|
|
132
|
+
with self._lock:
|
|
133
|
+
while self._paused and not self._terminated:
|
|
134
|
+
self._lock.wait(timeout=0.5)
|
|
135
|
+
|
|
136
|
+
def notify_call(self, name: str, file: str, line: int, env: Any = None):
|
|
137
|
+
"""Push a new frame when entering a function/action."""
|
|
138
|
+
with self._lock:
|
|
139
|
+
self._call_depth += 1
|
|
140
|
+
self._frame_id_counter += 1
|
|
141
|
+
frame = StackFrame(
|
|
142
|
+
id=self._frame_id_counter,
|
|
143
|
+
name=name,
|
|
144
|
+
file=file,
|
|
145
|
+
line=line,
|
|
146
|
+
variables=self._extract_vars(env) if env else {},
|
|
147
|
+
)
|
|
148
|
+
self._call_stack.append(frame)
|
|
149
|
+
|
|
150
|
+
def notify_return(self):
|
|
151
|
+
"""Pop a frame when leaving a function/action."""
|
|
152
|
+
with self._lock:
|
|
153
|
+
self._call_depth -= 1
|
|
154
|
+
if self._call_stack:
|
|
155
|
+
self._call_stack.pop()
|
|
156
|
+
|
|
157
|
+
def notify_terminated(self):
|
|
158
|
+
"""Signal that program execution finished."""
|
|
159
|
+
with self._lock:
|
|
160
|
+
self._terminated = True
|
|
161
|
+
self._paused = False
|
|
162
|
+
self._lock.notify_all()
|
|
163
|
+
if self.on_terminated:
|
|
164
|
+
self.on_terminated()
|
|
165
|
+
|
|
166
|
+
# -- DAP server control (called from I/O thread) -----------------------
|
|
167
|
+
|
|
168
|
+
def continue_execution(self):
|
|
169
|
+
with self._lock:
|
|
170
|
+
self._step_mode = StepMode.CONTINUE
|
|
171
|
+
self._paused = False
|
|
172
|
+
self._lock.notify_all()
|
|
173
|
+
|
|
174
|
+
def step_over(self):
|
|
175
|
+
with self._lock:
|
|
176
|
+
self._step_mode = StepMode.STEP_OVER
|
|
177
|
+
self._step_depth = self._call_depth
|
|
178
|
+
self._paused = False
|
|
179
|
+
self._lock.notify_all()
|
|
180
|
+
|
|
181
|
+
def step_into(self):
|
|
182
|
+
with self._lock:
|
|
183
|
+
self._step_mode = StepMode.STEP_INTO
|
|
184
|
+
self._paused = False
|
|
185
|
+
self._lock.notify_all()
|
|
186
|
+
|
|
187
|
+
def step_out(self):
|
|
188
|
+
with self._lock:
|
|
189
|
+
self._step_mode = StepMode.STEP_OUT
|
|
190
|
+
self._step_depth = self._call_depth
|
|
191
|
+
self._paused = False
|
|
192
|
+
self._lock.notify_all()
|
|
193
|
+
|
|
194
|
+
def pause(self):
|
|
195
|
+
"""Request the execution to pause at the next node."""
|
|
196
|
+
with self._lock:
|
|
197
|
+
self._step_mode = StepMode.STEP_INTO # stop on next node
|
|
198
|
+
|
|
199
|
+
def terminate(self):
|
|
200
|
+
with self._lock:
|
|
201
|
+
self._terminated = True
|
|
202
|
+
self._paused = False
|
|
203
|
+
self._lock.notify_all()
|
|
204
|
+
|
|
205
|
+
# -- Breakpoint management ---------------------------------------------
|
|
206
|
+
|
|
207
|
+
def set_breakpoints(self, file: str, lines: List[int]) -> List[Breakpoint]:
|
|
208
|
+
"""Replace breakpoints for *file* with the given *lines*."""
|
|
209
|
+
bps: Dict[int, Breakpoint] = {}
|
|
210
|
+
result = []
|
|
211
|
+
for ln in lines:
|
|
212
|
+
self._bp_id_counter += 1
|
|
213
|
+
bp = Breakpoint(id=self._bp_id_counter, file=file, line=ln)
|
|
214
|
+
bps[ln] = bp
|
|
215
|
+
result.append(bp)
|
|
216
|
+
with self._lock:
|
|
217
|
+
self._breakpoints[file] = bps
|
|
218
|
+
return result
|
|
219
|
+
|
|
220
|
+
def clear_breakpoints(self, file: str):
|
|
221
|
+
with self._lock:
|
|
222
|
+
self._breakpoints.pop(file, None)
|
|
223
|
+
|
|
224
|
+
# -- Inspection --------------------------------------------------------
|
|
225
|
+
|
|
226
|
+
@property
|
|
227
|
+
def is_paused(self) -> bool:
|
|
228
|
+
return self._paused
|
|
229
|
+
|
|
230
|
+
def get_stack_trace(self) -> List[StackFrame]:
|
|
231
|
+
with self._lock:
|
|
232
|
+
return list(reversed(self._call_stack))
|
|
233
|
+
|
|
234
|
+
def get_variables(self, frame_id: int) -> Dict[str, Any]:
|
|
235
|
+
with self._lock:
|
|
236
|
+
for f in self._call_stack:
|
|
237
|
+
if f.id == frame_id:
|
|
238
|
+
return dict(f.variables)
|
|
239
|
+
return {}
|
|
240
|
+
|
|
241
|
+
def set_stop_on_entry(self, stop: bool):
|
|
242
|
+
self._stop_on_entry = stop
|
|
243
|
+
|
|
244
|
+
# -- Internal ----------------------------------------------------------
|
|
245
|
+
|
|
246
|
+
def _should_stop(self, file: str, line: int) -> Optional[StopReason]:
|
|
247
|
+
"""Determine if execution should stop at this location.
|
|
248
|
+
|
|
249
|
+
Called with ``_lock`` held.
|
|
250
|
+
"""
|
|
251
|
+
# Stop on entry (first node)
|
|
252
|
+
if self._stop_on_entry:
|
|
253
|
+
self._stop_on_entry = False
|
|
254
|
+
return StopReason.ENTRY
|
|
255
|
+
|
|
256
|
+
# Breakpoint hit
|
|
257
|
+
file_bps = self._breakpoints.get(file)
|
|
258
|
+
if file_bps:
|
|
259
|
+
bp = file_bps.get(line)
|
|
260
|
+
if bp and bp.enabled:
|
|
261
|
+
bp.hit_count += 1
|
|
262
|
+
return StopReason.BREAKPOINT
|
|
263
|
+
|
|
264
|
+
# Stepping logic
|
|
265
|
+
if self._step_mode == StepMode.STEP_INTO:
|
|
266
|
+
return StopReason.STEP
|
|
267
|
+
if self._step_mode == StepMode.STEP_OVER:
|
|
268
|
+
if self._call_depth <= self._step_depth:
|
|
269
|
+
return StopReason.STEP
|
|
270
|
+
if self._step_mode == StepMode.STEP_OUT:
|
|
271
|
+
if self._call_depth < self._step_depth:
|
|
272
|
+
return StopReason.STEP
|
|
273
|
+
|
|
274
|
+
return None
|
|
275
|
+
|
|
276
|
+
@staticmethod
|
|
277
|
+
def _extract_vars(env: Any) -> Dict[str, Any]:
|
|
278
|
+
"""Pull variable names from a Zexus Environment."""
|
|
279
|
+
result: Dict[str, Any] = {}
|
|
280
|
+
store = getattr(env, "store", None) or getattr(env, "_store", None)
|
|
281
|
+
if isinstance(store, dict):
|
|
282
|
+
for k, v in store.items():
|
|
283
|
+
try:
|
|
284
|
+
result[k] = _format_value(v)
|
|
285
|
+
except Exception:
|
|
286
|
+
result[k] = str(v)
|
|
287
|
+
return result
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def _format_value(v: Any) -> str:
|
|
291
|
+
"""Format a Zexus runtime value for display in the debugger."""
|
|
292
|
+
if v is None:
|
|
293
|
+
return "null"
|
|
294
|
+
if hasattr(v, "inspect"):
|
|
295
|
+
return v.inspect()
|
|
296
|
+
if hasattr(v, "value"):
|
|
297
|
+
return str(v.value)
|
|
298
|
+
return str(v)
|
package/src/zexus/environment.py
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"""Environment helpers with export-aware values access."""
|
|
2
2
|
|
|
3
|
+
from .config import config as zexus_config
|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
class _EnvironmentValuesProxy:
|
|
5
7
|
"""Proxy that behaves like both callable view and export lookup."""
|
|
@@ -114,7 +116,10 @@ class Environment:
|
|
|
114
116
|
if self.outer:
|
|
115
117
|
getter = getattr(self.outer, 'get', None)
|
|
116
118
|
if callable(getter):
|
|
117
|
-
|
|
119
|
+
try:
|
|
120
|
+
return getter(name, default)
|
|
121
|
+
except TypeError:
|
|
122
|
+
return getter(name)
|
|
118
123
|
try:
|
|
119
124
|
return self.outer[name]
|
|
120
125
|
except (KeyError, TypeError, AttributeError):
|
|
@@ -135,6 +140,8 @@ class Environment:
|
|
|
135
140
|
module.set(var_name, value)
|
|
136
141
|
self.modules[module_name] = module
|
|
137
142
|
else:
|
|
143
|
+
if name == 'tx' and zexus_config.should_log('debug'):
|
|
144
|
+
print(f"DEBUG env.set tx -> {value}")
|
|
138
145
|
self.store[name] = value
|
|
139
146
|
|
|
140
147
|
def assign(self, name, value):
|
|
@@ -146,6 +153,8 @@ class Environment:
|
|
|
146
153
|
"""
|
|
147
154
|
# Check if variable exists in current scope
|
|
148
155
|
if name in self.store:
|
|
156
|
+
if name == 'tx' and zexus_config.should_log('debug'):
|
|
157
|
+
print(f"DEBUG env.assign tx -> {value}")
|
|
149
158
|
self.store[name] = value
|
|
150
159
|
return
|
|
151
160
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|