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
|
@@ -3,18 +3,54 @@ Bytecode Compiler for Evaluator
|
|
|
3
3
|
|
|
4
4
|
This module allows the evaluator to compile AST nodes to bytecode
|
|
5
5
|
for VM execution when performance is critical.
|
|
6
|
+
|
|
7
|
+
Features:
|
|
8
|
+
- AST to bytecode compilation
|
|
9
|
+
- File-based persistent caching (faster repeat runs)
|
|
10
|
+
- Pattern-based caching (similar code reuse)
|
|
11
|
+
- Multi-pass optimization (peephole, constant folding)
|
|
12
|
+
- Seamless integration with UnifiedExecutor
|
|
6
13
|
"""
|
|
7
14
|
import os
|
|
8
15
|
from typing import Dict, List, Optional
|
|
9
16
|
from .. import zexus_ast
|
|
10
17
|
from ..vm.bytecode import Bytecode, BytecodeBuilder
|
|
11
18
|
|
|
12
|
-
#
|
|
19
|
+
# Import cache (always available now)
|
|
20
|
+
from ..vm.cache import BytecodeCache
|
|
21
|
+
|
|
22
|
+
# Import optimizers (standard, not optional)
|
|
23
|
+
try:
|
|
24
|
+
from ..vm.optimizer import BytecodeOptimizer
|
|
25
|
+
OPTIMIZER_AVAILABLE = True
|
|
26
|
+
except ImportError:
|
|
27
|
+
BytecodeOptimizer = None
|
|
28
|
+
OPTIMIZER_AVAILABLE = False
|
|
29
|
+
|
|
13
30
|
try:
|
|
14
|
-
from ..vm.
|
|
15
|
-
|
|
31
|
+
from ..vm.peephole_optimizer import PeepholeOptimizer, OptimizationLevel
|
|
32
|
+
PEEPHOLE_AVAILABLE = True
|
|
16
33
|
except ImportError:
|
|
17
|
-
|
|
34
|
+
PeepholeOptimizer = None
|
|
35
|
+
OptimizationLevel = None
|
|
36
|
+
PEEPHOLE_AVAILABLE = False
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# Global shared cache for cross-compiler persistence
|
|
40
|
+
_SHARED_CACHE: Optional[BytecodeCache] = None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def get_shared_cache() -> BytecodeCache:
|
|
44
|
+
"""Get the global shared bytecode cache (persistent across runs)"""
|
|
45
|
+
global _SHARED_CACHE
|
|
46
|
+
if _SHARED_CACHE is None:
|
|
47
|
+
_SHARED_CACHE = BytecodeCache(
|
|
48
|
+
max_size=2000,
|
|
49
|
+
max_memory_mb=100,
|
|
50
|
+
persistent=True, # Enable disk persistence
|
|
51
|
+
debug=False
|
|
52
|
+
)
|
|
53
|
+
return _SHARED_CACHE
|
|
18
54
|
|
|
19
55
|
|
|
20
56
|
class EvaluatorBytecodeCompiler:
|
|
@@ -24,8 +60,9 @@ class EvaluatorBytecodeCompiler:
|
|
|
24
60
|
|
|
25
61
|
Features:
|
|
26
62
|
- AST to bytecode compilation
|
|
27
|
-
-
|
|
28
|
-
-
|
|
63
|
+
- File-based caching for repeat runs
|
|
64
|
+
- Pattern caching for similar code
|
|
65
|
+
- Multi-pass optimization
|
|
29
66
|
- Error tracking
|
|
30
67
|
"""
|
|
31
68
|
|
|
@@ -35,31 +72,81 @@ class EvaluatorBytecodeCompiler:
|
|
|
35
72
|
|
|
36
73
|
Args:
|
|
37
74
|
use_cache: Enable bytecode caching
|
|
38
|
-
cache_size: Maximum cache entries
|
|
75
|
+
cache_size: Maximum cache entries (ignored if using shared cache)
|
|
39
76
|
"""
|
|
40
77
|
self.builder: Optional[BytecodeBuilder] = None
|
|
41
78
|
self.errors: List[str] = []
|
|
42
79
|
self._loop_stack: List[Dict[str, str]] = [] # Stack of loop labels
|
|
43
80
|
|
|
44
|
-
#
|
|
81
|
+
# Use shared persistent cache
|
|
45
82
|
self.cache: Optional[BytecodeCache] = None
|
|
46
|
-
if use_cache
|
|
47
|
-
self.cache =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
83
|
+
if use_cache:
|
|
84
|
+
self.cache = get_shared_cache()
|
|
85
|
+
self._cache_stats_baseline = self._snapshot_cache_stats()
|
|
86
|
+
|
|
87
|
+
# Initialize optimizers (standard, not optional)
|
|
88
|
+
self.bytecode_optimizer = None
|
|
89
|
+
self.peephole_optimizer = None
|
|
90
|
+
|
|
91
|
+
if OPTIMIZER_AVAILABLE:
|
|
92
|
+
self.bytecode_optimizer = BytecodeOptimizer(level=2, debug=False)
|
|
93
|
+
|
|
94
|
+
if PEEPHOLE_AVAILABLE:
|
|
95
|
+
self.peephole_optimizer = PeepholeOptimizer(
|
|
96
|
+
level=OptimizationLevel.MODERATE
|
|
52
97
|
)
|
|
98
|
+
if not use_cache or self.cache is None:
|
|
99
|
+
self._cache_stats_baseline = {"hits": 0, "misses": 0, "pattern_hits": 0}
|
|
100
|
+
|
|
101
|
+
def compile_file(self, file_path: str, ast_root, optimize: bool = True) -> Optional[List[Bytecode]]:
|
|
102
|
+
"""
|
|
103
|
+
Compile an entire file's AST with file-based caching.
|
|
104
|
+
|
|
105
|
+
This enables faster repeat runs - if the file hasn't changed,
|
|
106
|
+
we skip compilation entirely and return cached bytecode.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
file_path: Path to source file
|
|
110
|
+
ast_root: Parsed AST root
|
|
111
|
+
optimize: Whether to apply optimizations
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
List of bytecode objects or None if cached invalid
|
|
115
|
+
"""
|
|
116
|
+
if self.cache:
|
|
117
|
+
# Check file-based cache first
|
|
118
|
+
cached = self.cache.get_by_file(file_path)
|
|
119
|
+
if cached:
|
|
120
|
+
return cached
|
|
121
|
+
|
|
122
|
+
# Cache miss - compile
|
|
123
|
+
bytecodes = []
|
|
124
|
+
if hasattr(ast_root, 'statements'):
|
|
125
|
+
for stmt in ast_root.statements:
|
|
126
|
+
bc = self.compile(stmt, optimize=optimize, use_cache=False)
|
|
127
|
+
if bc:
|
|
128
|
+
bytecodes.append(bc)
|
|
129
|
+
else:
|
|
130
|
+
bc = self.compile(ast_root, optimize=optimize, use_cache=False)
|
|
131
|
+
if bc:
|
|
132
|
+
bytecodes.append(bc)
|
|
133
|
+
|
|
134
|
+
# Store in file cache
|
|
135
|
+
if self.cache and bytecodes:
|
|
136
|
+
self.cache.put_by_file(file_path, bytecodes)
|
|
137
|
+
|
|
138
|
+
return bytecodes if bytecodes else None
|
|
53
139
|
|
|
54
140
|
def compile(self, node, optimize: bool = True, use_cache: bool = True) -> Optional[Bytecode]:
|
|
55
141
|
"""
|
|
56
142
|
Compile an AST node to bytecode.
|
|
57
143
|
|
|
58
144
|
Process:
|
|
59
|
-
1. Check cache for existing bytecode
|
|
60
|
-
2.
|
|
61
|
-
3.
|
|
62
|
-
4.
|
|
145
|
+
1. Check AST cache for existing bytecode
|
|
146
|
+
2. Check pattern cache for similar code
|
|
147
|
+
3. If cache miss, compile AST to bytecode
|
|
148
|
+
4. Apply multi-pass optimizations
|
|
149
|
+
5. Store in caches for future use
|
|
63
150
|
|
|
64
151
|
Args:
|
|
65
152
|
node: AST node to compile
|
|
@@ -69,11 +156,16 @@ class EvaluatorBytecodeCompiler:
|
|
|
69
156
|
Returns:
|
|
70
157
|
Bytecode object or None if compilation failed
|
|
71
158
|
"""
|
|
72
|
-
# Check cache first
|
|
159
|
+
# Check AST cache first
|
|
73
160
|
if use_cache and self.cache:
|
|
74
161
|
cached = self.cache.get(node)
|
|
75
162
|
if cached:
|
|
76
163
|
return cached
|
|
164
|
+
|
|
165
|
+
# Check pattern cache (similar code structure)
|
|
166
|
+
pattern_cached = self.cache.get_by_pattern(node)
|
|
167
|
+
if pattern_cached:
|
|
168
|
+
return pattern_cached
|
|
77
169
|
|
|
78
170
|
# Cache miss - compile
|
|
79
171
|
self.builder = BytecodeBuilder()
|
|
@@ -92,9 +184,10 @@ class EvaluatorBytecodeCompiler:
|
|
|
92
184
|
|
|
93
185
|
bytecode.set_metadata('created_by', 'evaluator')
|
|
94
186
|
|
|
95
|
-
# Store in
|
|
187
|
+
# Store in caches
|
|
96
188
|
if use_cache and self.cache:
|
|
97
189
|
self.cache.put(node, bytecode)
|
|
190
|
+
self.cache.put_by_pattern(node, bytecode)
|
|
98
191
|
|
|
99
192
|
return bytecode
|
|
100
193
|
|
|
@@ -124,6 +217,31 @@ class EvaluatorBytecodeCompiler:
|
|
|
124
217
|
error_msg = f"Unsupported node type for bytecode: {node_type}"
|
|
125
218
|
self.errors.append(error_msg)
|
|
126
219
|
self.builder.emit_constant(None)
|
|
220
|
+
|
|
221
|
+
def _coerce_string(self, candidate) -> str:
|
|
222
|
+
"""Convert literal or identifier nodes into raw string values."""
|
|
223
|
+
if candidate is None:
|
|
224
|
+
return ""
|
|
225
|
+
if hasattr(candidate, 'value'):
|
|
226
|
+
return str(candidate.value)
|
|
227
|
+
return str(candidate)
|
|
228
|
+
|
|
229
|
+
def _coerce_identifier(self, candidate) -> str:
|
|
230
|
+
"""Extract identifier name as string, handling AST nodes and raw strings."""
|
|
231
|
+
if candidate is None:
|
|
232
|
+
return ""
|
|
233
|
+
if hasattr(candidate, 'value'):
|
|
234
|
+
return str(candidate.value)
|
|
235
|
+
return str(candidate)
|
|
236
|
+
|
|
237
|
+
def _emit_vm_builtin_call(self, builtin_name: str, payload, discard_result: bool = True):
|
|
238
|
+
"""Helper to push a payload and invoke a VM builtin handler."""
|
|
239
|
+
if self.builder is None:
|
|
240
|
+
return
|
|
241
|
+
self.builder.emit_constant(payload)
|
|
242
|
+
self.builder.emit_call(builtin_name, 1)
|
|
243
|
+
if discard_result:
|
|
244
|
+
self.builder.emit("POP")
|
|
127
245
|
|
|
128
246
|
# === Statement Compilation ===
|
|
129
247
|
|
|
@@ -139,7 +257,7 @@ class EvaluatorBytecodeCompiler:
|
|
|
139
257
|
"""Compile expression statement"""
|
|
140
258
|
self._compile_node(node.expression)
|
|
141
259
|
# Pop result unless it's the last statement
|
|
142
|
-
|
|
260
|
+
self.builder.emit("POP")
|
|
143
261
|
|
|
144
262
|
def _compile_LetStatement(self, node: zexus_ast.LetStatement):
|
|
145
263
|
"""Compile let statement"""
|
|
@@ -169,6 +287,19 @@ class EvaluatorBytecodeCompiler:
|
|
|
169
287
|
# Emit a special instruction or constant to signal continue mode
|
|
170
288
|
# For now, emit a CONTINUE instruction that the VM can handle
|
|
171
289
|
self.builder.emit("CONTINUE")
|
|
290
|
+
|
|
291
|
+
def _compile_BreakStatement(self, node: zexus_ast.BreakStatement):
|
|
292
|
+
"""Compile break statement by jumping to loop end label"""
|
|
293
|
+
if not self._loop_stack:
|
|
294
|
+
self.errors.append("Break statement outside loop")
|
|
295
|
+
self.builder.emit_constant(None)
|
|
296
|
+
return
|
|
297
|
+
end_label = self._loop_stack[-1].get('end')
|
|
298
|
+
if not end_label:
|
|
299
|
+
self.errors.append("Break statement missing loop end label")
|
|
300
|
+
self.builder.emit_constant(None)
|
|
301
|
+
return
|
|
302
|
+
self.builder.emit_jump(end_label)
|
|
172
303
|
|
|
173
304
|
def _compile_IfStatement(self, node: zexus_ast.IfStatement):
|
|
174
305
|
"""Compile if statement with elif and else branches"""
|
|
@@ -336,6 +467,86 @@ class EvaluatorBytecodeCompiler:
|
|
|
336
467
|
|
|
337
468
|
# Emit PRINT opcode
|
|
338
469
|
self.builder.emit("PRINT")
|
|
470
|
+
|
|
471
|
+
def _compile_UseStatement(self, node: zexus_ast.UseStatement):
|
|
472
|
+
"""Compile module use/import statement for VM execution."""
|
|
473
|
+
module_path = self._coerce_string(getattr(node, 'file_path', None))
|
|
474
|
+
alias_name = self._coerce_identifier(getattr(node, 'alias', None)) if getattr(node, 'alias', None) else ""
|
|
475
|
+
|
|
476
|
+
names_list = []
|
|
477
|
+
if getattr(node, 'names', None):
|
|
478
|
+
for entry in node.names:
|
|
479
|
+
names_list.append(self._coerce_identifier(entry))
|
|
480
|
+
|
|
481
|
+
spec = {
|
|
482
|
+
"file": module_path,
|
|
483
|
+
"alias": alias_name,
|
|
484
|
+
"names": names_list,
|
|
485
|
+
"is_named": bool(getattr(node, 'is_named_import', False)) and len(names_list) > 0,
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
spec_idx = self.builder.bytecode.add_constant(spec)
|
|
489
|
+
self.builder.emit("LOAD_CONST", spec_idx)
|
|
490
|
+
name_idx = self.builder.bytecode.add_constant("__vm_use_module__")
|
|
491
|
+
self.builder.emit("CALL_NAME", (name_idx, 1))
|
|
492
|
+
self.builder.emit("POP")
|
|
493
|
+
|
|
494
|
+
def _compile_FromStatement(self, node: zexus_ast.FromStatement):
|
|
495
|
+
"""Compile from-import statements into VM-friendly builtin calls."""
|
|
496
|
+
module_path = self._coerce_string(getattr(node, 'file_path', None))
|
|
497
|
+
entries = []
|
|
498
|
+
|
|
499
|
+
for entry in getattr(node, 'imports', []) or []:
|
|
500
|
+
if isinstance(entry, (list, tuple)):
|
|
501
|
+
base = entry[0] if len(entry) > 0 else None
|
|
502
|
+
alias = entry[1] if len(entry) > 1 else None
|
|
503
|
+
else:
|
|
504
|
+
base = entry
|
|
505
|
+
alias = None
|
|
506
|
+
|
|
507
|
+
entries.append({
|
|
508
|
+
"name": self._coerce_identifier(base),
|
|
509
|
+
"alias": self._coerce_identifier(alias) if alias else "",
|
|
510
|
+
})
|
|
511
|
+
|
|
512
|
+
spec = {
|
|
513
|
+
"file": module_path,
|
|
514
|
+
"imports": entries,
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
spec_idx = self.builder.bytecode.add_constant(spec)
|
|
518
|
+
self.builder.emit("LOAD_CONST", spec_idx)
|
|
519
|
+
name_idx = self.builder.bytecode.add_constant("__vm_from_module__")
|
|
520
|
+
self.builder.emit("CALL_NAME", (name_idx, 1))
|
|
521
|
+
self.builder.emit("POP")
|
|
522
|
+
|
|
523
|
+
def _compile_NativeStatement(self, node: zexus_ast.NativeStatement):
|
|
524
|
+
"""Compile native performance statements via VM builtins."""
|
|
525
|
+
self._emit_vm_builtin_call("__vm_native_statement__", node, discard_result=False)
|
|
526
|
+
|
|
527
|
+
def _compile_GCStatement(self, node: zexus_ast.GCStatement):
|
|
528
|
+
"""Compile garbage collection directives into VM builtins."""
|
|
529
|
+
self._emit_vm_builtin_call("__vm_gc_statement__", node, discard_result=False)
|
|
530
|
+
|
|
531
|
+
def _compile_InlineStatement(self, node: zexus_ast.InlineStatement):
|
|
532
|
+
"""Compile inline optimization directives into VM builtins."""
|
|
533
|
+
self._emit_vm_builtin_call("__vm_inline_statement__", node, discard_result=False)
|
|
534
|
+
|
|
535
|
+
def _compile_BufferStatement(self, node: zexus_ast.BufferStatement):
|
|
536
|
+
"""Compile buffer directives to VM builtins."""
|
|
537
|
+
self._emit_vm_builtin_call("__vm_buffer_statement__", node, discard_result=False)
|
|
538
|
+
|
|
539
|
+
def _compile_SIMDStatement(self, node: zexus_ast.SIMDStatement):
|
|
540
|
+
"""Compile SIMD directives to VM builtins."""
|
|
541
|
+
self._emit_vm_builtin_call("__vm_simd_statement__", node, discard_result=False)
|
|
542
|
+
|
|
543
|
+
def _compile_DeferStatement(self, node: zexus_ast.DeferStatement):
|
|
544
|
+
"""Compile defer cleanup directives to VM builtins."""
|
|
545
|
+
self._emit_vm_builtin_call("__vm_defer_statement__", node, discard_result=False)
|
|
546
|
+
|
|
547
|
+
def _compile_PatternStatement(self, node: zexus_ast.PatternStatement):
|
|
548
|
+
"""Compile pattern matching directives to VM builtins."""
|
|
549
|
+
self._emit_vm_builtin_call("__vm_pattern_statement__", node, discard_result=False)
|
|
339
550
|
|
|
340
551
|
# === Blockchain Statement Compilation ===
|
|
341
552
|
|
|
@@ -485,7 +696,36 @@ class EvaluatorBytecodeCompiler:
|
|
|
485
696
|
self._compile_node(value_expr)
|
|
486
697
|
# Build map from stack
|
|
487
698
|
self.builder.emit("BUILD_MAP", len(node.pairs))
|
|
488
|
-
|
|
699
|
+
|
|
700
|
+
def _compile_PropertyAccessExpression(self, node: zexus_ast.PropertyAccessExpression):
|
|
701
|
+
"""Compile property access"""
|
|
702
|
+
if self.builder is None:
|
|
703
|
+
return
|
|
704
|
+
|
|
705
|
+
# Compile object
|
|
706
|
+
self._compile_node(node.object)
|
|
707
|
+
|
|
708
|
+
if node.computed:
|
|
709
|
+
# Bracket notation: obj[expr]
|
|
710
|
+
self._compile_node(node.property)
|
|
711
|
+
self._builder_emit("INDEX")
|
|
712
|
+
else:
|
|
713
|
+
# Dot notation: obj.prop
|
|
714
|
+
if hasattr(node.property, 'value'):
|
|
715
|
+
name = node.property.value
|
|
716
|
+
else:
|
|
717
|
+
name = str(node.property)
|
|
718
|
+
|
|
719
|
+
# Push property name as constant
|
|
720
|
+
self.builder.emit_constant(name)
|
|
721
|
+
self._builder_emit("GET_ATTR")
|
|
722
|
+
|
|
723
|
+
def _builder_emit(self, opcode):
|
|
724
|
+
"""Helper to emit opcode string or enum"""
|
|
725
|
+
# If builder has emit, use it. Some builders might use emit(opcode, operand).
|
|
726
|
+
# Wrapper to handle potential string usage if enum not fully refreshed
|
|
727
|
+
self.builder.emit(opcode)
|
|
728
|
+
|
|
489
729
|
def _compile_InfixExpression(self, node: zexus_ast.InfixExpression):
|
|
490
730
|
"""Compile infix expression"""
|
|
491
731
|
if self.builder is None:
|
|
@@ -523,6 +763,26 @@ class EvaluatorBytecodeCompiler:
|
|
|
523
763
|
|
|
524
764
|
def _compile_CallExpression(self, node: zexus_ast.CallExpression):
|
|
525
765
|
"""Compile function call"""
|
|
766
|
+
# Method call on property access (obj.method(...))
|
|
767
|
+
if isinstance(node.function, zexus_ast.PropertyAccessExpression):
|
|
768
|
+
# Only handle non-computed property names here
|
|
769
|
+
if hasattr(node.function, 'computed') and node.function.computed:
|
|
770
|
+
pass
|
|
771
|
+
else:
|
|
772
|
+
method_name = None
|
|
773
|
+
if hasattr(node.function.property, 'value'):
|
|
774
|
+
method_name = node.function.property.value
|
|
775
|
+
elif isinstance(node.function.property, str):
|
|
776
|
+
method_name = node.function.property
|
|
777
|
+
|
|
778
|
+
if method_name is not None:
|
|
779
|
+
# Load object first, then args, then CALL_METHOD
|
|
780
|
+
self._compile_node(node.function.object)
|
|
781
|
+
for arg in node.arguments:
|
|
782
|
+
self._compile_node(arg)
|
|
783
|
+
self.builder.emit_call_method(method_name, len(node.arguments))
|
|
784
|
+
return
|
|
785
|
+
|
|
526
786
|
# Check for blockchain-specific function calls that have dedicated opcodes
|
|
527
787
|
if isinstance(node.function, zexus_ast.Identifier):
|
|
528
788
|
func_name = node.function.value
|
|
@@ -594,16 +854,57 @@ class EvaluatorBytecodeCompiler:
|
|
|
594
854
|
|
|
595
855
|
def _compile_AssignmentExpression(self, node: zexus_ast.AssignmentExpression):
|
|
596
856
|
"""Compile assignment expression"""
|
|
597
|
-
# Compile the value
|
|
598
|
-
self._compile_node(node.value)
|
|
599
857
|
# Store to name
|
|
600
858
|
if isinstance(node.name, zexus_ast.Identifier):
|
|
859
|
+
# Compile the value
|
|
860
|
+
self._compile_node(node.value)
|
|
601
861
|
self.builder.emit("DUP") # Keep value on stack
|
|
602
862
|
name = str(node.name.value).strip()
|
|
603
863
|
self.builder.emit_store(name)
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
864
|
+
return
|
|
865
|
+
|
|
866
|
+
# Property/index assignment (obj.prop = value / obj[expr] = value)
|
|
867
|
+
if isinstance(node.name, zexus_ast.PropertyAccessExpression):
|
|
868
|
+
tmp_name = "__assign_tmp"
|
|
869
|
+
# Evaluate value first and stash it
|
|
870
|
+
self._compile_node(node.value)
|
|
871
|
+
self.builder.emit_store(tmp_name)
|
|
872
|
+
|
|
873
|
+
# Compile object
|
|
874
|
+
self._compile_node(node.name.object)
|
|
875
|
+
|
|
876
|
+
# Compile property key
|
|
877
|
+
if hasattr(node.name, 'computed') and node.name.computed:
|
|
878
|
+
self._compile_node(node.name.property)
|
|
879
|
+
else:
|
|
880
|
+
if hasattr(node.name.property, 'value'):
|
|
881
|
+
prop_name = node.name.property.value
|
|
882
|
+
self.builder.emit_constant(prop_name)
|
|
883
|
+
else:
|
|
884
|
+
self._compile_node(node.name.property)
|
|
885
|
+
|
|
886
|
+
# Push value and call set
|
|
887
|
+
self.builder.emit_load(tmp_name)
|
|
888
|
+
self.builder.emit_call_method("set", 2)
|
|
889
|
+
|
|
890
|
+
# Return assigned value
|
|
891
|
+
self.builder.emit_load(tmp_name)
|
|
892
|
+
return
|
|
893
|
+
|
|
894
|
+
if isinstance(node.name, zexus_ast.IndexExpression):
|
|
895
|
+
tmp_name = "__assign_tmp"
|
|
896
|
+
self._compile_node(node.value)
|
|
897
|
+
self.builder.emit_store(tmp_name)
|
|
898
|
+
|
|
899
|
+
self._compile_node(node.name.left)
|
|
900
|
+
self._compile_node(node.name.index)
|
|
901
|
+
self.builder.emit_load(tmp_name)
|
|
902
|
+
self.builder.emit_call_method("set", 2)
|
|
903
|
+
self.builder.emit_load(tmp_name)
|
|
904
|
+
return
|
|
905
|
+
|
|
906
|
+
self.errors.append(
|
|
907
|
+
"Complex assignment targets not yet supported in bytecode")
|
|
607
908
|
|
|
608
909
|
def _compile_IndexExpression(self, node):
|
|
609
910
|
"""Compile index expression"""
|
|
@@ -613,6 +914,42 @@ class EvaluatorBytecodeCompiler:
|
|
|
613
914
|
self._compile_node(node.index)
|
|
614
915
|
# Emit index operation
|
|
615
916
|
self.builder.emit("INDEX")
|
|
917
|
+
|
|
918
|
+
def _compile_SliceExpression(self, node):
|
|
919
|
+
"""Compile slice expression"""
|
|
920
|
+
self._compile_node(node.object)
|
|
921
|
+
|
|
922
|
+
if node.start is not None:
|
|
923
|
+
self._compile_node(node.start)
|
|
924
|
+
else:
|
|
925
|
+
self.builder.emit_constant(None)
|
|
926
|
+
|
|
927
|
+
if node.end is not None:
|
|
928
|
+
self._compile_node(node.end)
|
|
929
|
+
else:
|
|
930
|
+
self.builder.emit_constant(None)
|
|
931
|
+
|
|
932
|
+
self.builder.emit("SLICE")
|
|
933
|
+
|
|
934
|
+
def _compile_ThisExpression(self, node):
|
|
935
|
+
"""Compile 'this' expression"""
|
|
936
|
+
self.builder.emit_load("this")
|
|
937
|
+
|
|
938
|
+
def _compile_TernaryExpression(self, node: zexus_ast.TernaryExpression):
|
|
939
|
+
"""Compile ternary expression: condition ? true_value : false_value"""
|
|
940
|
+
else_label = f"ternary_else_{id(node)}"
|
|
941
|
+
end_label = f"ternary_end_{id(node)}"
|
|
942
|
+
|
|
943
|
+
self._compile_node(node.condition)
|
|
944
|
+
self.builder.emit_jump_if_false(else_label)
|
|
945
|
+
|
|
946
|
+
self._compile_node(node.true_value)
|
|
947
|
+
self.builder.emit_jump(end_label)
|
|
948
|
+
|
|
949
|
+
self.builder.mark_label(else_label)
|
|
950
|
+
self._compile_node(node.false_value)
|
|
951
|
+
|
|
952
|
+
self.builder.mark_label(end_label)
|
|
616
953
|
|
|
617
954
|
def _compile_PropertyAccessExpression(self, node):
|
|
618
955
|
"""Compile property access (obj.property or obj[property])"""
|
|
@@ -680,13 +1017,19 @@ class EvaluatorBytecodeCompiler:
|
|
|
680
1017
|
|
|
681
1018
|
def _optimize(self, bytecode: Bytecode) -> Bytecode:
|
|
682
1019
|
"""
|
|
683
|
-
Apply
|
|
1020
|
+
Apply multi-pass optimizations to bytecode.
|
|
1021
|
+
|
|
1022
|
+
Optimization pipeline:
|
|
1023
|
+
1. BytecodeOptimizer (if available) - advanced passes
|
|
1024
|
+
2. PeepholeOptimizer (if available) - local patterns
|
|
1025
|
+
3. Built-in optimizations - fallback
|
|
684
1026
|
|
|
685
|
-
Optimizations:
|
|
686
|
-
- Remove unnecessary POP instructions
|
|
1027
|
+
Optimizations include:
|
|
687
1028
|
- Constant folding (compile-time evaluation)
|
|
688
|
-
- Dead code elimination
|
|
689
|
-
-
|
|
1029
|
+
- Dead code elimination
|
|
1030
|
+
- Strength reduction
|
|
1031
|
+
- Instruction fusion
|
|
1032
|
+
- Jump threading
|
|
690
1033
|
- Redundant operation removal
|
|
691
1034
|
"""
|
|
692
1035
|
from zexus.vm.bytecode import Bytecode, Opcode
|
|
@@ -695,8 +1038,33 @@ class EvaluatorBytecodeCompiler:
|
|
|
695
1038
|
if not instructions:
|
|
696
1039
|
return bytecode
|
|
697
1040
|
|
|
698
|
-
# Multiple optimization passes for better results
|
|
699
1041
|
optimized = instructions
|
|
1042
|
+
|
|
1043
|
+
# Pass 1: BytecodeOptimizer (advanced optimizations)
|
|
1044
|
+
if self.bytecode_optimizer:
|
|
1045
|
+
try:
|
|
1046
|
+
optimized = self.bytecode_optimizer.optimize(
|
|
1047
|
+
optimized,
|
|
1048
|
+
bytecode.constants
|
|
1049
|
+
)
|
|
1050
|
+
except Exception:
|
|
1051
|
+
pass # Fall through to other optimizers
|
|
1052
|
+
|
|
1053
|
+
# Pass 2: PeepholeOptimizer (local patterns)
|
|
1054
|
+
if self.peephole_optimizer:
|
|
1055
|
+
try:
|
|
1056
|
+
# Convert to format peephole expects
|
|
1057
|
+
from ..vm.peephole_optimizer import Instruction
|
|
1058
|
+
peep_insts = [
|
|
1059
|
+
Instruction(opcode=inst[0], arg=inst[1] if len(inst) > 1 else None)
|
|
1060
|
+
for inst in optimized
|
|
1061
|
+
]
|
|
1062
|
+
peep_result = self.peephole_optimizer.optimize(peep_insts)
|
|
1063
|
+
optimized = [(inst.opcode, inst.arg) for inst in peep_result]
|
|
1064
|
+
except Exception:
|
|
1065
|
+
pass # Fall through to built-in
|
|
1066
|
+
|
|
1067
|
+
# Pass 3: Built-in optimizations (always available)
|
|
700
1068
|
optimized = self._constant_folding(optimized, bytecode.constants)
|
|
701
1069
|
optimized = self._dead_code_elimination(optimized)
|
|
702
1070
|
optimized = self._peephole_patterns(optimized)
|
|
@@ -916,8 +1284,12 @@ class EvaluatorBytecodeCompiler:
|
|
|
916
1284
|
'StringLiteral', 'Boolean', 'ListLiteral', 'MapLiteral', 'NullLiteral',
|
|
917
1285
|
'InfixExpression', 'PrefixExpression', 'CallExpression',
|
|
918
1286
|
'AwaitExpression', 'SpawnExpression', 'AssignmentExpression', 'IndexExpression',
|
|
919
|
-
'PropertyAccessExpression', 'LambdaExpression',
|
|
1287
|
+
'PropertyAccessExpression', 'SliceExpression', 'LambdaExpression',
|
|
1288
|
+
'ThisExpression', 'TernaryExpression',
|
|
920
1289
|
'FindExpression', 'LoadExpression',
|
|
1290
|
+
'UseStatement', 'FromStatement',
|
|
1291
|
+
'NativeStatement', 'GCStatement', 'InlineStatement',
|
|
1292
|
+
'BufferStatement', 'SIMDStatement', 'DeferStatement', 'PatternStatement',
|
|
921
1293
|
# Blockchain nodes
|
|
922
1294
|
'TxStatement', 'RevertStatement', 'RequireStatement',
|
|
923
1295
|
'StateAccessExpression', 'LedgerAppendStatement', 'GasChargeStatement'
|
|
@@ -927,6 +1299,17 @@ class EvaluatorBytecodeCompiler:
|
|
|
927
1299
|
|
|
928
1300
|
# ==================== Cache Management ====================
|
|
929
1301
|
|
|
1302
|
+
def _snapshot_cache_stats(self) -> Dict[str, int]:
|
|
1303
|
+
"""Capture current cache stats to use as a baseline."""
|
|
1304
|
+
if not self.cache:
|
|
1305
|
+
return {"hits": 0, "misses": 0, "pattern_hits": 0}
|
|
1306
|
+
stats = self.cache.get_stats() or {}
|
|
1307
|
+
return {
|
|
1308
|
+
"hits": int(stats.get("hits", 0)),
|
|
1309
|
+
"misses": int(stats.get("misses", 0)),
|
|
1310
|
+
"pattern_hits": int(stats.get("pattern_hits", 0)),
|
|
1311
|
+
}
|
|
1312
|
+
|
|
930
1313
|
def get_cache_stats(self) -> Optional[Dict]:
|
|
931
1314
|
"""
|
|
932
1315
|
Get cache statistics
|
|
@@ -934,14 +1317,34 @@ class EvaluatorBytecodeCompiler:
|
|
|
934
1317
|
Returns:
|
|
935
1318
|
Dictionary with cache stats or None if cache disabled
|
|
936
1319
|
"""
|
|
937
|
-
if self.cache:
|
|
938
|
-
return
|
|
939
|
-
|
|
1320
|
+
if not self.cache:
|
|
1321
|
+
return None
|
|
1322
|
+
|
|
1323
|
+
stats = self.cache.get_stats() or {}
|
|
1324
|
+
baseline = getattr(self, "_cache_stats_baseline", {"hits": 0, "misses": 0, "pattern_hits": 0})
|
|
1325
|
+
|
|
1326
|
+
hits = max(0, int(stats.get("hits", 0)) - baseline.get("hits", 0))
|
|
1327
|
+
misses = max(0, int(stats.get("misses", 0)) - baseline.get("misses", 0))
|
|
1328
|
+
pattern_hits = max(0, int(stats.get("pattern_hits", 0)) - baseline.get("pattern_hits", 0))
|
|
1329
|
+
|
|
1330
|
+
total = hits + misses
|
|
1331
|
+
hit_rate = (hits / total * 100.0) if total else 0.0
|
|
1332
|
+
|
|
1333
|
+
adjusted_stats = dict(stats)
|
|
1334
|
+
adjusted_stats.update({
|
|
1335
|
+
"hits": hits,
|
|
1336
|
+
"misses": misses,
|
|
1337
|
+
"pattern_hits": pattern_hits,
|
|
1338
|
+
"total": total,
|
|
1339
|
+
"hit_rate": hit_rate,
|
|
1340
|
+
})
|
|
1341
|
+
return adjusted_stats
|
|
940
1342
|
|
|
941
1343
|
def clear_cache(self):
|
|
942
1344
|
"""Clear bytecode cache"""
|
|
943
1345
|
if self.cache:
|
|
944
1346
|
self.cache.clear()
|
|
1347
|
+
self._cache_stats_baseline = {"hits": 0, "misses": 0, "pattern_hits": 0}
|
|
945
1348
|
|
|
946
1349
|
def invalidate_cache(self, node):
|
|
947
1350
|
"""Invalidate cached bytecode for a node"""
|
|
@@ -952,6 +1355,7 @@ class EvaluatorBytecodeCompiler:
|
|
|
952
1355
|
"""Reset cache statistics"""
|
|
953
1356
|
if self.cache:
|
|
954
1357
|
self.cache.reset_stats()
|
|
1358
|
+
self._cache_stats_baseline = self._snapshot_cache_stats()
|
|
955
1359
|
|
|
956
1360
|
def cache_size(self) -> int:
|
|
957
1361
|
"""Get current cache size"""
|