zexus 1.6.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/LICENSE +0 -0
- package/README.md +2513 -0
- package/bin/zexus +2 -0
- package/bin/zpics +2 -0
- package/bin/zpm +2 -0
- package/bin/zx +2 -0
- package/bin/zx-deploy +2 -0
- package/bin/zx-dev +2 -0
- package/bin/zx-run +2 -0
- package/package.json +66 -0
- package/scripts/README.md +24 -0
- package/scripts/postinstall.js +44 -0
- package/shared_config.json +24 -0
- package/src/README.md +1525 -0
- package/src/tests/run_zexus_tests.py +117 -0
- package/src/tests/test_all_phases.zx +346 -0
- package/src/tests/test_blockchain_features.zx +306 -0
- package/src/tests/test_complexity_features.zx +321 -0
- package/src/tests/test_core_integration.py +185 -0
- package/src/tests/test_phase10_ecosystem.zx +177 -0
- package/src/tests/test_phase1_modifiers.zx +87 -0
- package/src/tests/test_phase2_plugins.zx +80 -0
- package/src/tests/test_phase3_security.zx +97 -0
- package/src/tests/test_phase4_vfs.zx +116 -0
- package/src/tests/test_phase5_types.zx +117 -0
- package/src/tests/test_phase6_metaprogramming.zx +125 -0
- package/src/tests/test_phase7_optimization.zx +132 -0
- package/src/tests/test_phase9_advanced_types.zx +157 -0
- package/src/tests/test_security_features.py +419 -0
- package/src/tests/test_security_features.zx +276 -0
- package/src/tests/test_simple_zx.zx +1 -0
- package/src/tests/test_verification_simple.zx +69 -0
- package/src/zexus/__init__.py +28 -0
- package/src/zexus/__main__.py +5 -0
- package/src/zexus/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/advanced_types.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/builtin_modules.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/capability_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/complexity_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/concurrency_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/config.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/dependency_injection.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/ecosystem.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__/hybrid_orchestrator.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/lexer.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/metaprogramming.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/module_cache.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/object.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/optimization.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/plugin_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/policy_engine.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/security.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/stdlib_integration.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/strategy_recovery.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/syntax_validator.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/type_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/virtual_filesystem.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/advanced_types.py +401 -0
- package/src/zexus/blockchain/__init__.py +40 -0
- package/src/zexus/blockchain/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/crypto.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/ledger.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/transaction.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/crypto.py +463 -0
- package/src/zexus/blockchain/ledger.py +255 -0
- package/src/zexus/blockchain/transaction.py +267 -0
- package/src/zexus/builtin_modules.py +284 -0
- package/src/zexus/builtin_plugins.py +317 -0
- package/src/zexus/capability_system.py +372 -0
- package/src/zexus/cli/__init__.py +2 -0
- package/src/zexus/cli/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/cli/__pycache__/main.cpython-312.pyc +0 -0
- package/src/zexus/cli/main.py +707 -0
- package/src/zexus/cli/zpm.py +203 -0
- package/src/zexus/compare_interpreter_compiler.py +146 -0
- package/src/zexus/compiler/__init__.py +169 -0
- package/src/zexus/compiler/__pycache__/__init__.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__/zexus_ast.cpython-312.pyc +0 -0
- package/src/zexus/compiler/bytecode.py +266 -0
- package/src/zexus/compiler/compat_runtime.py +277 -0
- package/src/zexus/compiler/lexer.py +257 -0
- package/src/zexus/compiler/parser.py +779 -0
- package/src/zexus/compiler/semantic.py +118 -0
- package/src/zexus/compiler/zexus_ast.py +454 -0
- package/src/zexus/complexity_system.py +575 -0
- package/src/zexus/concurrency_system.py +493 -0
- package/src/zexus/config.py +201 -0
- package/src/zexus/crypto_bridge.py +19 -0
- package/src/zexus/dependency_injection.py +423 -0
- package/src/zexus/ecosystem.py +434 -0
- package/src/zexus/environment.py +101 -0
- package/src/zexus/environment_manager.py +119 -0
- package/src/zexus/error_reporter.py +314 -0
- package/src/zexus/evaluator/__init__.py +12 -0
- package/src/zexus/evaluator/__pycache__/__init__.cpython-312.pyc +0 -0
- 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__/integration.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/statements.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/utils.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/bytecode_compiler.py +700 -0
- package/src/zexus/evaluator/core.py +891 -0
- package/src/zexus/evaluator/expressions.py +827 -0
- package/src/zexus/evaluator/functions.py +3989 -0
- package/src/zexus/evaluator/integration.py +396 -0
- package/src/zexus/evaluator/statements.py +4303 -0
- package/src/zexus/evaluator/utils.py +126 -0
- package/src/zexus/evaluator_original.py +2041 -0
- package/src/zexus/external_bridge.py +16 -0
- package/src/zexus/find_affected_imports.sh +155 -0
- package/src/zexus/hybrid_orchestrator.py +152 -0
- package/src/zexus/input_validation.py +259 -0
- package/src/zexus/lexer.py +571 -0
- package/src/zexus/logging.py +89 -0
- package/src/zexus/lsp/__init__.py +9 -0
- package/src/zexus/lsp/completion_provider.py +207 -0
- package/src/zexus/lsp/definition_provider.py +22 -0
- package/src/zexus/lsp/hover_provider.py +71 -0
- package/src/zexus/lsp/server.py +269 -0
- package/src/zexus/lsp/symbol_provider.py +31 -0
- package/src/zexus/metaprogramming.py +321 -0
- package/src/zexus/module_cache.py +89 -0
- package/src/zexus/module_manager.py +107 -0
- package/src/zexus/object.py +973 -0
- package/src/zexus/optimization.py +424 -0
- package/src/zexus/parser/__init__.py +31 -0
- package/src/zexus/parser/__pycache__/__init__.cpython-312.pyc +0 -0
- 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/integration.py +86 -0
- package/src/zexus/parser/parser.py +3977 -0
- package/src/zexus/parser/strategy_context.py +7254 -0
- package/src/zexus/parser/strategy_structural.py +1033 -0
- package/src/zexus/persistence.py +391 -0
- package/src/zexus/plugin_system.py +290 -0
- package/src/zexus/policy_engine.py +365 -0
- package/src/zexus/profiler/__init__.py +5 -0
- package/src/zexus/profiler/profiler.py +233 -0
- package/src/zexus/purity_system.py +398 -0
- package/src/zexus/runtime/__init__.py +20 -0
- package/src/zexus/runtime/async_runtime.py +324 -0
- package/src/zexus/search_old_imports.sh +65 -0
- package/src/zexus/security.py +1407 -0
- package/src/zexus/stack_trace.py +233 -0
- package/src/zexus/stdlib/__init__.py +27 -0
- package/src/zexus/stdlib/blockchain.py +341 -0
- package/src/zexus/stdlib/compression.py +167 -0
- package/src/zexus/stdlib/crypto.py +124 -0
- package/src/zexus/stdlib/datetime.py +163 -0
- package/src/zexus/stdlib/db_mongo.py +199 -0
- package/src/zexus/stdlib/db_mysql.py +162 -0
- package/src/zexus/stdlib/db_postgres.py +163 -0
- package/src/zexus/stdlib/db_sqlite.py +133 -0
- package/src/zexus/stdlib/encoding.py +230 -0
- package/src/zexus/stdlib/fs.py +195 -0
- package/src/zexus/stdlib/http.py +219 -0
- package/src/zexus/stdlib/http_server.py +248 -0
- package/src/zexus/stdlib/json_module.py +61 -0
- package/src/zexus/stdlib/math.py +360 -0
- package/src/zexus/stdlib/os_module.py +265 -0
- package/src/zexus/stdlib/regex.py +148 -0
- package/src/zexus/stdlib/sockets.py +253 -0
- package/src/zexus/stdlib/test_framework.zx +208 -0
- package/src/zexus/stdlib/test_runner.zx +119 -0
- package/src/zexus/stdlib_integration.py +341 -0
- package/src/zexus/strategy_recovery.py +256 -0
- package/src/zexus/syntax_validator.py +356 -0
- package/src/zexus/testing/zpics.py +407 -0
- package/src/zexus/testing/zpics_runtime.py +369 -0
- package/src/zexus/type_system.py +374 -0
- package/src/zexus/validation_system.py +569 -0
- package/src/zexus/virtual_filesystem.py +355 -0
- package/src/zexus/vm/__init__.py +8 -0
- package/src/zexus/vm/__pycache__/__init__.cpython-312.pyc +0 -0
- 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__/cache.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/jit.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/memory_manager.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/memory_pool.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/parallel_vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/peephole_optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/profiler.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/register_allocator.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/register_vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/ssa_converter.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/async_optimizer.py +420 -0
- package/src/zexus/vm/bytecode.py +428 -0
- package/src/zexus/vm/bytecode_converter.py +297 -0
- package/src/zexus/vm/cache.py +532 -0
- package/src/zexus/vm/jit.py +720 -0
- package/src/zexus/vm/memory_manager.py +520 -0
- package/src/zexus/vm/memory_pool.py +511 -0
- package/src/zexus/vm/optimizer.py +478 -0
- package/src/zexus/vm/parallel_vm.py +899 -0
- package/src/zexus/vm/peephole_optimizer.py +452 -0
- package/src/zexus/vm/profiler.py +527 -0
- package/src/zexus/vm/register_allocator.py +462 -0
- package/src/zexus/vm/register_vm.py +520 -0
- package/src/zexus/vm/ssa_converter.py +757 -0
- package/src/zexus/vm/vm.py +1392 -0
- package/src/zexus/zexus_ast.py +1782 -0
- package/src/zexus/zexus_token.py +253 -0
- package/src/zexus/zpm/__init__.py +15 -0
- package/src/zexus/zpm/installer.py +116 -0
- package/src/zexus/zpm/package_manager.py +208 -0
- package/src/zexus/zpm/publisher.py +98 -0
- package/src/zexus/zpm/registry.py +110 -0
- package/src/zexus.egg-info/PKG-INFO +2235 -0
- package/src/zexus.egg-info/SOURCES.txt +876 -0
- package/src/zexus.egg-info/dependency_links.txt +1 -0
- package/src/zexus.egg-info/entry_points.txt +3 -0
- package/src/zexus.egg-info/not-zip-safe +1 -0
- package/src/zexus.egg-info/requires.txt +14 -0
- package/src/zexus.egg-info/top_level.txt +2 -0
- package/zexus.json +14 -0
|
@@ -0,0 +1,700 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Bytecode Compiler for Evaluator
|
|
3
|
+
|
|
4
|
+
This module allows the evaluator to compile AST nodes to bytecode
|
|
5
|
+
for VM execution when performance is critical.
|
|
6
|
+
"""
|
|
7
|
+
from typing import Dict, List, Optional
|
|
8
|
+
from .. import zexus_ast
|
|
9
|
+
from ..vm.bytecode import Bytecode, BytecodeBuilder
|
|
10
|
+
|
|
11
|
+
# Try to import cache (optional dependency)
|
|
12
|
+
try:
|
|
13
|
+
from ..vm.cache import BytecodeCache
|
|
14
|
+
CACHE_AVAILABLE = True
|
|
15
|
+
except ImportError:
|
|
16
|
+
CACHE_AVAILABLE = False
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class EvaluatorBytecodeCompiler:
|
|
20
|
+
"""
|
|
21
|
+
Compiles Zexus AST nodes to bytecode for VM execution.
|
|
22
|
+
Designed to work seamlessly with the evaluator's execution model.
|
|
23
|
+
|
|
24
|
+
Features:
|
|
25
|
+
- AST to bytecode compilation
|
|
26
|
+
- Bytecode caching for repeated code
|
|
27
|
+
- Optimization support
|
|
28
|
+
- Error tracking
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __init__(self, use_cache: bool = True, cache_size: int = 1000):
|
|
32
|
+
"""
|
|
33
|
+
Initialize bytecode compiler
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
use_cache: Enable bytecode caching
|
|
37
|
+
cache_size: Maximum cache entries
|
|
38
|
+
"""
|
|
39
|
+
self.builder: Optional[BytecodeBuilder] = None
|
|
40
|
+
self.errors: List[str] = []
|
|
41
|
+
self._loop_stack: List[Dict[str, str]] = [] # Stack of loop labels
|
|
42
|
+
|
|
43
|
+
# Bytecode cache
|
|
44
|
+
self.cache: Optional[BytecodeCache] = None
|
|
45
|
+
if use_cache and CACHE_AVAILABLE:
|
|
46
|
+
self.cache = BytecodeCache(
|
|
47
|
+
max_size=cache_size,
|
|
48
|
+
max_memory_mb=50,
|
|
49
|
+
persistent=False,
|
|
50
|
+
debug=False
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def compile(self, node, optimize: bool = True, use_cache: bool = True) -> Optional[Bytecode]:
|
|
54
|
+
"""
|
|
55
|
+
Compile an AST node to bytecode.
|
|
56
|
+
|
|
57
|
+
Process:
|
|
58
|
+
1. Check cache for existing bytecode
|
|
59
|
+
2. If cache miss, compile AST to bytecode
|
|
60
|
+
3. Apply optimizations if requested
|
|
61
|
+
4. Store in cache for future use
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
node: AST node to compile
|
|
65
|
+
optimize: Whether to apply optimizations
|
|
66
|
+
use_cache: Whether to use cache (default True)
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
Bytecode object or None if compilation failed
|
|
70
|
+
"""
|
|
71
|
+
# Check cache first
|
|
72
|
+
if use_cache and self.cache:
|
|
73
|
+
cached = self.cache.get(node)
|
|
74
|
+
if cached:
|
|
75
|
+
return cached
|
|
76
|
+
|
|
77
|
+
# Cache miss - compile
|
|
78
|
+
self.builder = BytecodeBuilder()
|
|
79
|
+
self.errors = []
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
self._compile_node(node)
|
|
83
|
+
|
|
84
|
+
if self.errors:
|
|
85
|
+
return None
|
|
86
|
+
|
|
87
|
+
bytecode = self.builder.build()
|
|
88
|
+
|
|
89
|
+
if optimize:
|
|
90
|
+
bytecode = self._optimize(bytecode)
|
|
91
|
+
|
|
92
|
+
bytecode.set_metadata('created_by', 'evaluator')
|
|
93
|
+
|
|
94
|
+
# Store in cache
|
|
95
|
+
if use_cache and self.cache:
|
|
96
|
+
self.cache.put(node, bytecode)
|
|
97
|
+
|
|
98
|
+
return bytecode
|
|
99
|
+
|
|
100
|
+
except Exception as e:
|
|
101
|
+
self.errors.append(f"Compilation error: {e}")
|
|
102
|
+
return None
|
|
103
|
+
|
|
104
|
+
def _compile_node(self, node):
|
|
105
|
+
"""Dispatch to appropriate compilation method based on node type"""
|
|
106
|
+
if self.builder is None:
|
|
107
|
+
self.errors.append("Bytecode builder not initialized")
|
|
108
|
+
return
|
|
109
|
+
|
|
110
|
+
if node is None:
|
|
111
|
+
self.builder.emit_constant(None)
|
|
112
|
+
return
|
|
113
|
+
|
|
114
|
+
node_type = type(node).__name__
|
|
115
|
+
|
|
116
|
+
# Dispatch to appropriate handler
|
|
117
|
+
method_name = f'_compile_{node_type}'
|
|
118
|
+
if hasattr(self, method_name):
|
|
119
|
+
method = getattr(self, method_name)
|
|
120
|
+
method(node)
|
|
121
|
+
else:
|
|
122
|
+
# Unsupported node type - emit error
|
|
123
|
+
error_msg = f"Unsupported node type for bytecode: {node_type}"
|
|
124
|
+
self.errors.append(error_msg)
|
|
125
|
+
self.builder.emit_constant(None)
|
|
126
|
+
|
|
127
|
+
# === Statement Compilation ===
|
|
128
|
+
|
|
129
|
+
def _compile_Program(self, node: zexus_ast.Program):
|
|
130
|
+
"""Compile a program (top-level)"""
|
|
131
|
+
for stmt in node.statements:
|
|
132
|
+
self._compile_node(stmt)
|
|
133
|
+
# Ensure we return something
|
|
134
|
+
if not node.statements:
|
|
135
|
+
self.builder.emit_constant(None)
|
|
136
|
+
|
|
137
|
+
def _compile_ExpressionStatement(self, node: zexus_ast.ExpressionStatement):
|
|
138
|
+
"""Compile expression statement"""
|
|
139
|
+
self._compile_node(node.expression)
|
|
140
|
+
# Pop result unless it's the last statement
|
|
141
|
+
# self.builder.emit("POP")
|
|
142
|
+
|
|
143
|
+
def _compile_LetStatement(self, node: zexus_ast.LetStatement):
|
|
144
|
+
"""Compile let statement"""
|
|
145
|
+
# Compile the value expression
|
|
146
|
+
self._compile_node(node.value)
|
|
147
|
+
# Store it
|
|
148
|
+
self.builder.emit_store(node.name.value)
|
|
149
|
+
|
|
150
|
+
def _compile_ConstStatement(self, node: zexus_ast.ConstStatement):
|
|
151
|
+
"""Compile const statement"""
|
|
152
|
+
# Similar to let for now
|
|
153
|
+
self._compile_node(node.value)
|
|
154
|
+
self.builder.emit_store(node.name.value)
|
|
155
|
+
|
|
156
|
+
def _compile_ReturnStatement(self, node: zexus_ast.ReturnStatement):
|
|
157
|
+
"""Compile return statement"""
|
|
158
|
+
if node.return_value:
|
|
159
|
+
self._compile_node(node.return_value)
|
|
160
|
+
else:
|
|
161
|
+
self.builder.emit_constant(None)
|
|
162
|
+
self.builder.emit("RETURN")
|
|
163
|
+
|
|
164
|
+
def _compile_ContinueStatement(self, node: zexus_ast.ContinueStatement):
|
|
165
|
+
"""Compile continue statement - enables error recovery mode"""
|
|
166
|
+
# Emit a special instruction or constant to signal continue mode
|
|
167
|
+
# For now, emit a CONTINUE instruction that the VM can handle
|
|
168
|
+
self.builder.emit("CONTINUE")
|
|
169
|
+
|
|
170
|
+
def _compile_IfStatement(self, node: zexus_ast.IfStatement):
|
|
171
|
+
"""Compile if statement with elif and else branches"""
|
|
172
|
+
else_label = f"else_{id(node)}"
|
|
173
|
+
end_label = f"end_if_{id(node)}"
|
|
174
|
+
|
|
175
|
+
# Compile condition
|
|
176
|
+
self._compile_node(node.condition)
|
|
177
|
+
self.builder.emit_jump_if_false(else_label)
|
|
178
|
+
|
|
179
|
+
# Compile consequence
|
|
180
|
+
self._compile_node(node.consequence)
|
|
181
|
+
self.builder.emit_jump(end_label)
|
|
182
|
+
|
|
183
|
+
# Compile alternative (elif/else)
|
|
184
|
+
self.builder.mark_label(else_label)
|
|
185
|
+
if node.alternative:
|
|
186
|
+
self._compile_node(node.alternative)
|
|
187
|
+
else:
|
|
188
|
+
self.builder.emit_constant(None)
|
|
189
|
+
|
|
190
|
+
self.builder.mark_label(end_label)
|
|
191
|
+
|
|
192
|
+
def _compile_WhileStatement(self, node: zexus_ast.WhileStatement):
|
|
193
|
+
"""Compile while loop"""
|
|
194
|
+
start_label = f"while_start_{id(node)}"
|
|
195
|
+
end_label = f"while_end_{id(node)}"
|
|
196
|
+
|
|
197
|
+
# Track loop labels for break/continue
|
|
198
|
+
self._loop_stack.append({'start': start_label, 'end': end_label})
|
|
199
|
+
|
|
200
|
+
# Loop start
|
|
201
|
+
self.builder.mark_label(start_label)
|
|
202
|
+
|
|
203
|
+
# Condition
|
|
204
|
+
self._compile_node(node.condition)
|
|
205
|
+
self.builder.emit_jump_if_false(end_label)
|
|
206
|
+
|
|
207
|
+
# Body
|
|
208
|
+
self._compile_node(node.body)
|
|
209
|
+
|
|
210
|
+
# Jump back to start
|
|
211
|
+
self.builder.emit_jump(start_label)
|
|
212
|
+
|
|
213
|
+
# Loop end
|
|
214
|
+
self.builder.mark_label(end_label)
|
|
215
|
+
self._loop_stack.pop()
|
|
216
|
+
|
|
217
|
+
# While statements don't return values by default
|
|
218
|
+
self.builder.emit_constant(None)
|
|
219
|
+
|
|
220
|
+
def _compile_ForEachStatement(self, node: zexus_ast.ForEachStatement):
|
|
221
|
+
"""Compile for-each loop"""
|
|
222
|
+
start_label = f"foreach_start_{id(node)}"
|
|
223
|
+
end_label = f"foreach_end_{id(node)}"
|
|
224
|
+
|
|
225
|
+
# Track loop labels for break/continue
|
|
226
|
+
self._loop_stack.append({'start': start_label, 'end': end_label})
|
|
227
|
+
|
|
228
|
+
# Compile the iterable
|
|
229
|
+
self._compile_node(node.iterable)
|
|
230
|
+
|
|
231
|
+
# Get iterator (for now, assume it's already iterable)
|
|
232
|
+
# Store iterator in a temp variable
|
|
233
|
+
iter_var = f"_iter_{id(node)}"
|
|
234
|
+
self.builder.emit_store(iter_var)
|
|
235
|
+
|
|
236
|
+
# Get length/count for iteration
|
|
237
|
+
self.builder.emit_load(iter_var)
|
|
238
|
+
self.builder.emit("GET_LENGTH") # Should push length onto stack
|
|
239
|
+
index_var = f"_index_{id(node)}"
|
|
240
|
+
self.builder.emit_constant(0)
|
|
241
|
+
self.builder.emit_store(index_var)
|
|
242
|
+
|
|
243
|
+
# Loop start
|
|
244
|
+
self.builder.mark_label(start_label)
|
|
245
|
+
|
|
246
|
+
# Check if index < length
|
|
247
|
+
self.builder.emit_load(index_var)
|
|
248
|
+
self.builder.emit_load(iter_var)
|
|
249
|
+
self.builder.emit("GET_LENGTH")
|
|
250
|
+
self.builder.emit("LT") # index < length
|
|
251
|
+
self.builder.emit_jump_if_false(end_label)
|
|
252
|
+
|
|
253
|
+
# Get current element
|
|
254
|
+
self.builder.emit_load(iter_var)
|
|
255
|
+
self.builder.emit_load(index_var)
|
|
256
|
+
self.builder.emit("INDEX") # Get element at index
|
|
257
|
+
|
|
258
|
+
# Store in loop variable
|
|
259
|
+
item_name = node.item.value if hasattr(node.item, 'value') else str(node.item)
|
|
260
|
+
self.builder.emit_store(item_name)
|
|
261
|
+
|
|
262
|
+
# Compile body
|
|
263
|
+
self._compile_node(node.body)
|
|
264
|
+
|
|
265
|
+
# Increment index
|
|
266
|
+
self.builder.emit_load(index_var)
|
|
267
|
+
self.builder.emit_constant(1)
|
|
268
|
+
self.builder.emit("ADD")
|
|
269
|
+
self.builder.emit_store(index_var)
|
|
270
|
+
|
|
271
|
+
# Jump back to start
|
|
272
|
+
self.builder.emit_jump(start_label)
|
|
273
|
+
|
|
274
|
+
# Loop end
|
|
275
|
+
self.builder.mark_label(end_label)
|
|
276
|
+
self._loop_stack.pop()
|
|
277
|
+
|
|
278
|
+
# For-each doesn't return a value
|
|
279
|
+
self.builder.emit_constant(None)
|
|
280
|
+
|
|
281
|
+
def _compile_BlockStatement(self, node: zexus_ast.BlockStatement):
|
|
282
|
+
"""Compile block statement"""
|
|
283
|
+
if not node.statements:
|
|
284
|
+
self.builder.emit_constant(None)
|
|
285
|
+
return
|
|
286
|
+
|
|
287
|
+
for i, stmt in enumerate(node.statements):
|
|
288
|
+
self._compile_node(stmt)
|
|
289
|
+
# Keep the last value on stack, pop others
|
|
290
|
+
if i < len(node.statements) - 1:
|
|
291
|
+
# Check if stmt has return - if so, don't pop
|
|
292
|
+
if type(stmt).__name__ != 'ReturnStatement':
|
|
293
|
+
# Only pop if not a declaration
|
|
294
|
+
if type(stmt).__name__ not in ['LetStatement', 'ConstStatement', 'ActionStatement']:
|
|
295
|
+
pass # Keep value for now
|
|
296
|
+
|
|
297
|
+
def _compile_ActionStatement(self, node: zexus_ast.ActionStatement):
|
|
298
|
+
"""Compile action definition"""
|
|
299
|
+
# Create nested bytecode for function body
|
|
300
|
+
inner_compiler = EvaluatorBytecodeCompiler()
|
|
301
|
+
func_bytecode = inner_compiler.compile(node.body, optimize=False)
|
|
302
|
+
|
|
303
|
+
if inner_compiler.errors:
|
|
304
|
+
self.errors.extend(inner_compiler.errors)
|
|
305
|
+
return
|
|
306
|
+
|
|
307
|
+
# Build function descriptor
|
|
308
|
+
params = [p.value for p in node.parameters] if hasattr(node, 'parameters') else []
|
|
309
|
+
func_desc = {
|
|
310
|
+
"bytecode": func_bytecode,
|
|
311
|
+
"params": params,
|
|
312
|
+
"is_async": getattr(node, "is_async", False)
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
# Store function descriptor
|
|
316
|
+
func_const_idx = self.builder.bytecode.add_constant(func_desc)
|
|
317
|
+
name_idx = self.builder.bytecode.add_constant(node.name.value)
|
|
318
|
+
self.builder.emit("STORE_FUNC", (name_idx, func_const_idx))
|
|
319
|
+
|
|
320
|
+
def _compile_FunctionStatement(self, node: zexus_ast.FunctionStatement):
|
|
321
|
+
"""Compile function definition (same as action)"""
|
|
322
|
+
# Reuse action compilation logic
|
|
323
|
+
self._compile_ActionStatement(node)
|
|
324
|
+
|
|
325
|
+
def _compile_PrintStatement(self, node: zexus_ast.PrintStatement):
|
|
326
|
+
"""Compile print statement"""
|
|
327
|
+
# Compile the value to print
|
|
328
|
+
if hasattr(node, 'value') and node.value:
|
|
329
|
+
self._compile_node(node.value)
|
|
330
|
+
else:
|
|
331
|
+
# Empty print
|
|
332
|
+
self.builder.emit_constant("")
|
|
333
|
+
|
|
334
|
+
# Emit PRINT opcode
|
|
335
|
+
self.builder.emit("PRINT")
|
|
336
|
+
|
|
337
|
+
# === Blockchain Statement Compilation ===
|
|
338
|
+
|
|
339
|
+
def _compile_TxStatement(self, node):
|
|
340
|
+
"""Compile TX statement (transaction block)"""
|
|
341
|
+
# Emit TX_BEGIN
|
|
342
|
+
self.builder.emit("TX_BEGIN")
|
|
343
|
+
|
|
344
|
+
# Compile transaction body
|
|
345
|
+
if hasattr(node, 'body'):
|
|
346
|
+
self._compile_node(node.body)
|
|
347
|
+
|
|
348
|
+
# Emit TX_COMMIT (success path)
|
|
349
|
+
self.builder.emit("TX_COMMIT")
|
|
350
|
+
|
|
351
|
+
def _compile_RevertStatement(self, node):
|
|
352
|
+
"""Compile REVERT statement"""
|
|
353
|
+
# If there's a reason/message, compile it
|
|
354
|
+
if hasattr(node, 'reason') and node.reason:
|
|
355
|
+
self._compile_node(node.reason)
|
|
356
|
+
# Get the reason from stack
|
|
357
|
+
reason_idx = self.builder.bytecode.add_constant("revert_reason")
|
|
358
|
+
self.builder.emit("STORE_NAME", reason_idx)
|
|
359
|
+
|
|
360
|
+
# Emit TX_REVERT
|
|
361
|
+
self.builder.emit("TX_REVERT")
|
|
362
|
+
|
|
363
|
+
def _compile_RequireStatement(self, node):
|
|
364
|
+
"""Compile REQUIRE statement - reverts if condition fails"""
|
|
365
|
+
# Compile condition
|
|
366
|
+
if hasattr(node, 'condition'):
|
|
367
|
+
self._compile_node(node.condition)
|
|
368
|
+
|
|
369
|
+
# Jump if true (condition passes)
|
|
370
|
+
pass_label = f"require_pass_{id(node)}"
|
|
371
|
+
self.builder.emit("JUMP_IF_TRUE", None)
|
|
372
|
+
|
|
373
|
+
# Condition failed - revert
|
|
374
|
+
if hasattr(node, 'message') and node.message:
|
|
375
|
+
# Compile error message
|
|
376
|
+
self._compile_node(node.message)
|
|
377
|
+
msg_idx = self.builder.bytecode.add_constant("require_msg")
|
|
378
|
+
self.builder.emit("STORE_NAME", msg_idx)
|
|
379
|
+
|
|
380
|
+
self.builder.emit("TX_REVERT")
|
|
381
|
+
|
|
382
|
+
# Pass label
|
|
383
|
+
self.builder.mark_label(pass_label)
|
|
384
|
+
|
|
385
|
+
def _compile_StateAccessExpression(self, node):
|
|
386
|
+
"""Compile STATE access expression"""
|
|
387
|
+
# Check if it's a read or write
|
|
388
|
+
if hasattr(node, 'key'):
|
|
389
|
+
key = node.key if isinstance(node.key, str) else str(node.key)
|
|
390
|
+
key_idx = self.builder.bytecode.add_constant(key)
|
|
391
|
+
|
|
392
|
+
if hasattr(node, 'is_write') and node.is_write:
|
|
393
|
+
# STATE_WRITE - expects value on stack
|
|
394
|
+
self.builder.emit("STATE_WRITE", key_idx)
|
|
395
|
+
else:
|
|
396
|
+
# STATE_READ
|
|
397
|
+
self.builder.emit("STATE_READ", key_idx)
|
|
398
|
+
|
|
399
|
+
def _compile_LedgerAppendStatement(self, node):
|
|
400
|
+
"""Compile LEDGER append statement"""
|
|
401
|
+
# Compile the entry to append
|
|
402
|
+
if hasattr(node, 'entry'):
|
|
403
|
+
self._compile_node(node.entry)
|
|
404
|
+
|
|
405
|
+
# Emit LEDGER_APPEND
|
|
406
|
+
self.builder.emit("LEDGER_APPEND")
|
|
407
|
+
|
|
408
|
+
def _compile_GasChargeStatement(self, node):
|
|
409
|
+
"""Compile GAS charge statement"""
|
|
410
|
+
# Get gas amount
|
|
411
|
+
if hasattr(node, 'amount'):
|
|
412
|
+
if isinstance(node.amount, int):
|
|
413
|
+
amount = node.amount
|
|
414
|
+
else:
|
|
415
|
+
# Compile expression for gas amount
|
|
416
|
+
self._compile_node(node.amount)
|
|
417
|
+
# For now, assume constant
|
|
418
|
+
amount = 1
|
|
419
|
+
else:
|
|
420
|
+
amount = 1
|
|
421
|
+
|
|
422
|
+
# Emit GAS_CHARGE
|
|
423
|
+
self.builder.emit("GAS_CHARGE", amount)
|
|
424
|
+
|
|
425
|
+
# === Expression Compilation ===
|
|
426
|
+
|
|
427
|
+
def _compile_Identifier(self, node: zexus_ast.Identifier):
|
|
428
|
+
"""Compile identifier (variable load)"""
|
|
429
|
+
self.builder.emit_load(node.value)
|
|
430
|
+
|
|
431
|
+
def _compile_IntegerLiteral(self, node: zexus_ast.IntegerLiteral):
|
|
432
|
+
"""Compile integer literal"""
|
|
433
|
+
if self.builder is None:
|
|
434
|
+
return
|
|
435
|
+
self.builder.emit_constant(node.value)
|
|
436
|
+
|
|
437
|
+
def _compile_FloatLiteral(self, node: zexus_ast.FloatLiteral):
|
|
438
|
+
"""Compile float literal"""
|
|
439
|
+
if self.builder is None:
|
|
440
|
+
return
|
|
441
|
+
self.builder.emit_constant(node.value)
|
|
442
|
+
|
|
443
|
+
def _compile_StringLiteral(self, node: zexus_ast.StringLiteral):
|
|
444
|
+
"""Compile string literal"""
|
|
445
|
+
if self.builder is None:
|
|
446
|
+
return
|
|
447
|
+
self.builder.emit_constant(node.value)
|
|
448
|
+
|
|
449
|
+
def _compile_Boolean(self, node: zexus_ast.Boolean):
|
|
450
|
+
"""Compile boolean literal"""
|
|
451
|
+
if self.builder is None:
|
|
452
|
+
return
|
|
453
|
+
self.builder.emit_constant(node.value)
|
|
454
|
+
|
|
455
|
+
def _compile_NullLiteral(self, node):
|
|
456
|
+
"""Compile null literal"""
|
|
457
|
+
if self.builder is None:
|
|
458
|
+
return
|
|
459
|
+
self.builder.emit_constant(None)
|
|
460
|
+
|
|
461
|
+
def _compile_ListLiteral(self, node: zexus_ast.ListLiteral):
|
|
462
|
+
"""Compile list literal"""
|
|
463
|
+
# Push each element
|
|
464
|
+
for element in node.elements:
|
|
465
|
+
self._compile_node(element)
|
|
466
|
+
# Build list from stack
|
|
467
|
+
self.builder.emit("BUILD_LIST", len(node.elements))
|
|
468
|
+
|
|
469
|
+
def _compile_MapLiteral(self, node: zexus_ast.MapLiteral):
|
|
470
|
+
"""Compile map/dictionary literal"""
|
|
471
|
+
# Push key-value pairs
|
|
472
|
+
for key_expr, value_expr in node.pairs:
|
|
473
|
+
self._compile_node(key_expr)
|
|
474
|
+
self._compile_node(value_expr)
|
|
475
|
+
# Build map from stack
|
|
476
|
+
self.builder.emit("BUILD_MAP", len(node.pairs))
|
|
477
|
+
|
|
478
|
+
def _compile_InfixExpression(self, node: zexus_ast.InfixExpression):
|
|
479
|
+
"""Compile infix expression"""
|
|
480
|
+
if self.builder is None:
|
|
481
|
+
return
|
|
482
|
+
# Compile operands
|
|
483
|
+
self._compile_node(node.left)
|
|
484
|
+
self._compile_node(node.right)
|
|
485
|
+
|
|
486
|
+
# Emit operator
|
|
487
|
+
op_map = {
|
|
488
|
+
'+': 'ADD', '-': 'SUB', '*': 'MUL', '/': 'DIV', '%': 'MOD',
|
|
489
|
+
'**': 'POW',
|
|
490
|
+
'==': 'EQ', '!=': 'NEQ', '<': 'LT', '>': 'GT',
|
|
491
|
+
'<=': 'LTE', '>=': 'GTE',
|
|
492
|
+
'&&': 'AND', '||': 'OR'
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
opcode = op_map.get(node.operator)
|
|
496
|
+
if opcode:
|
|
497
|
+
self.builder.emit(opcode)
|
|
498
|
+
else:
|
|
499
|
+
self.errors.append(f"Unsupported operator: {node.operator}")
|
|
500
|
+
self.builder.emit_constant(None)
|
|
501
|
+
|
|
502
|
+
def _compile_PrefixExpression(self, node: zexus_ast.PrefixExpression):
|
|
503
|
+
"""Compile prefix expression"""
|
|
504
|
+
self._compile_node(node.right)
|
|
505
|
+
|
|
506
|
+
if node.operator == '!':
|
|
507
|
+
self.builder.emit("NOT")
|
|
508
|
+
elif node.operator == '-':
|
|
509
|
+
self.builder.emit("NEG")
|
|
510
|
+
else:
|
|
511
|
+
self.errors.append(f"Unsupported prefix operator: {node.operator}")
|
|
512
|
+
|
|
513
|
+
def _compile_CallExpression(self, node: zexus_ast.CallExpression):
|
|
514
|
+
"""Compile function call"""
|
|
515
|
+
# Check for blockchain-specific function calls that have dedicated opcodes
|
|
516
|
+
if isinstance(node.function, zexus_ast.Identifier):
|
|
517
|
+
func_name = node.function.value
|
|
518
|
+
|
|
519
|
+
# HASH_BLOCK opcode - hash(block_data)
|
|
520
|
+
if func_name == "hash" and len(node.arguments) == 1:
|
|
521
|
+
self._compile_node(node.arguments[0])
|
|
522
|
+
self.builder.emit("HASH_BLOCK")
|
|
523
|
+
return
|
|
524
|
+
|
|
525
|
+
# VERIFY_SIGNATURE opcode - verify_sig(signature, message, public_key)
|
|
526
|
+
if func_name == "verify_sig" and len(node.arguments) == 3:
|
|
527
|
+
# Compile arguments in stack order: signature, message, public_key
|
|
528
|
+
for arg in node.arguments:
|
|
529
|
+
self._compile_node(arg)
|
|
530
|
+
self.builder.emit("VERIFY_SIGNATURE")
|
|
531
|
+
return
|
|
532
|
+
|
|
533
|
+
# MERKLE_ROOT opcode - merkle_root([leaves...])
|
|
534
|
+
if func_name == "merkle_root" and len(node.arguments) >= 1:
|
|
535
|
+
# If argument is a list literal, compile elements individually
|
|
536
|
+
if isinstance(node.arguments[0], zexus_ast.ListLiteral):
|
|
537
|
+
leaves = node.arguments[0].elements
|
|
538
|
+
for leaf in leaves:
|
|
539
|
+
self._compile_node(leaf)
|
|
540
|
+
self.builder.emit("MERKLE_ROOT", len(leaves))
|
|
541
|
+
return
|
|
542
|
+
|
|
543
|
+
# Compile arguments first (standard call path)
|
|
544
|
+
for arg in node.arguments:
|
|
545
|
+
self._compile_node(arg)
|
|
546
|
+
|
|
547
|
+
# Check if function is an identifier (direct call)
|
|
548
|
+
if isinstance(node.function, zexus_ast.Identifier):
|
|
549
|
+
self.builder.emit_call(node.function.value, len(node.arguments))
|
|
550
|
+
else:
|
|
551
|
+
# Function expression - evaluate and call
|
|
552
|
+
self._compile_node(node.function)
|
|
553
|
+
self.builder.emit("CALL_TOP", len(node.arguments))
|
|
554
|
+
|
|
555
|
+
def _compile_AwaitExpression(self, node):
|
|
556
|
+
"""Compile await expression"""
|
|
557
|
+
# Compile the inner expression
|
|
558
|
+
self._compile_node(node.expression)
|
|
559
|
+
# Emit await
|
|
560
|
+
self.builder.emit("AWAIT")
|
|
561
|
+
|
|
562
|
+
def _compile_SpawnExpression(self, node):
|
|
563
|
+
"""Compile spawn expression"""
|
|
564
|
+
# Compile the inner expression (should be a call)
|
|
565
|
+
self._compile_node(node.expression)
|
|
566
|
+
# Emit spawn
|
|
567
|
+
self.builder.emit("SPAWN")
|
|
568
|
+
|
|
569
|
+
def _compile_AssignmentExpression(self, node: zexus_ast.AssignmentExpression):
|
|
570
|
+
"""Compile assignment expression"""
|
|
571
|
+
# Compile the value
|
|
572
|
+
self._compile_node(node.value)
|
|
573
|
+
# Store to name
|
|
574
|
+
if isinstance(node.name, zexus_ast.Identifier):
|
|
575
|
+
self.builder.emit("DUP") # Keep value on stack
|
|
576
|
+
self.builder.emit_store(node.name.value)
|
|
577
|
+
else:
|
|
578
|
+
self.errors.append(
|
|
579
|
+
"Complex assignment targets not yet supported in bytecode")
|
|
580
|
+
|
|
581
|
+
def _compile_IndexExpression(self, node):
|
|
582
|
+
"""Compile index expression"""
|
|
583
|
+
# Compile the object
|
|
584
|
+
self._compile_node(node.left)
|
|
585
|
+
# Compile the index
|
|
586
|
+
self._compile_node(node.index)
|
|
587
|
+
# Emit index operation
|
|
588
|
+
self.builder.emit("INDEX")
|
|
589
|
+
|
|
590
|
+
# === Optimization ===
|
|
591
|
+
|
|
592
|
+
def _optimize(self, bytecode: Bytecode) -> Bytecode:
|
|
593
|
+
"""
|
|
594
|
+
Apply peephole optimizations to bytecode.
|
|
595
|
+
|
|
596
|
+
Optimizations:
|
|
597
|
+
- Remove unnecessary POP instructions
|
|
598
|
+
- Constant folding
|
|
599
|
+
- Dead code elimination
|
|
600
|
+
"""
|
|
601
|
+
# For now, return as-is
|
|
602
|
+
# Future: implement optimization passes
|
|
603
|
+
return bytecode
|
|
604
|
+
|
|
605
|
+
def can_compile(self, node) -> bool:
|
|
606
|
+
"""
|
|
607
|
+
Check if a node can be compiled to bytecode.
|
|
608
|
+
Some complex features may not be supported yet.
|
|
609
|
+
"""
|
|
610
|
+
if node is None:
|
|
611
|
+
return True
|
|
612
|
+
|
|
613
|
+
node_type = type(node).__name__
|
|
614
|
+
|
|
615
|
+
# List of supported node types
|
|
616
|
+
supported = {
|
|
617
|
+
'Program', 'ExpressionStatement', 'LetStatement', 'ConstStatement',
|
|
618
|
+
'ReturnStatement', 'ContinueStatement', 'IfStatement', 'WhileStatement', 'ForEachStatement',
|
|
619
|
+
'BlockStatement', 'ActionStatement', 'FunctionStatement', 'PrintStatement',
|
|
620
|
+
'Identifier', 'IntegerLiteral', 'FloatLiteral',
|
|
621
|
+
'StringLiteral', 'Boolean', 'ListLiteral', 'MapLiteral',
|
|
622
|
+
'InfixExpression', 'PrefixExpression', 'CallExpression',
|
|
623
|
+
'AwaitExpression', 'AssignmentExpression', 'IndexExpression'
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
return node_type in supported
|
|
627
|
+
|
|
628
|
+
# ==================== Cache Management ====================
|
|
629
|
+
|
|
630
|
+
def get_cache_stats(self) -> Optional[Dict]:
|
|
631
|
+
"""
|
|
632
|
+
Get cache statistics
|
|
633
|
+
|
|
634
|
+
Returns:
|
|
635
|
+
Dictionary with cache stats or None if cache disabled
|
|
636
|
+
"""
|
|
637
|
+
if self.cache:
|
|
638
|
+
return self.cache.get_stats()
|
|
639
|
+
return None
|
|
640
|
+
|
|
641
|
+
def clear_cache(self):
|
|
642
|
+
"""Clear bytecode cache"""
|
|
643
|
+
if self.cache:
|
|
644
|
+
self.cache.clear()
|
|
645
|
+
|
|
646
|
+
def invalidate_cache(self, node):
|
|
647
|
+
"""Invalidate cached bytecode for a node"""
|
|
648
|
+
if self.cache:
|
|
649
|
+
self.cache.invalidate(node)
|
|
650
|
+
|
|
651
|
+
def reset_cache_stats(self):
|
|
652
|
+
"""Reset cache statistics"""
|
|
653
|
+
if self.cache:
|
|
654
|
+
self.cache.reset_stats()
|
|
655
|
+
|
|
656
|
+
def cache_size(self) -> int:
|
|
657
|
+
"""Get current cache size"""
|
|
658
|
+
if self.cache:
|
|
659
|
+
return self.cache.size()
|
|
660
|
+
return 0
|
|
661
|
+
|
|
662
|
+
def cache_memory_usage(self) -> float:
|
|
663
|
+
"""Get cache memory usage in MB"""
|
|
664
|
+
if self.cache:
|
|
665
|
+
return self.cache.memory_usage_mb()
|
|
666
|
+
return 0.0
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
def should_use_vm_for_node(node) -> bool:
|
|
670
|
+
"""
|
|
671
|
+
Determine if a node should be compiled to bytecode and run in VM.
|
|
672
|
+
|
|
673
|
+
Heuristics:
|
|
674
|
+
- Large loops (optimization)
|
|
675
|
+
- Recursive functions (tail call optimization potential)
|
|
676
|
+
- Math-heavy computations
|
|
677
|
+
- Multiple function calls in sequence
|
|
678
|
+
"""
|
|
679
|
+
if node is None:
|
|
680
|
+
return False
|
|
681
|
+
|
|
682
|
+
node_type = type(node).__name__
|
|
683
|
+
|
|
684
|
+
# Always use VM for loops
|
|
685
|
+
if node_type in ['WhileStatement', 'ForEachStatement']:
|
|
686
|
+
return True
|
|
687
|
+
|
|
688
|
+
# Use VM for complex functions
|
|
689
|
+
if node_type == 'ActionStatement':
|
|
690
|
+
# Count statements in body
|
|
691
|
+
if hasattr(node, 'body') and hasattr(node.body, 'statements'):
|
|
692
|
+
if len(node.body.statements) > 5:
|
|
693
|
+
return True
|
|
694
|
+
|
|
695
|
+
# Use VM for programs with many statements
|
|
696
|
+
if node_type == 'Program':
|
|
697
|
+
if len(node.statements) > 10:
|
|
698
|
+
return True
|
|
699
|
+
|
|
700
|
+
return False
|