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,520 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Register-Based Virtual Machine for Zexus
|
|
3
|
+
|
|
4
|
+
A register-based VM that provides 1.5-3x faster arithmetic operations
|
|
5
|
+
compared to the stack-based VM. Uses virtual registers for intermediate
|
|
6
|
+
values, reducing memory access and stack manipulation overhead.
|
|
7
|
+
|
|
8
|
+
Architecture:
|
|
9
|
+
- 16 virtual registers (r0-r15)
|
|
10
|
+
- Register allocation for variables and temporaries
|
|
11
|
+
- Hybrid mode: registers for arithmetic, stack for complex operations
|
|
12
|
+
- Automatic spilling when registers are exhausted
|
|
13
|
+
|
|
14
|
+
Performance:
|
|
15
|
+
- Target: 1.5-3x speedup for arithmetic-heavy code
|
|
16
|
+
- Best for: loops, mathematical computations, nested expressions
|
|
17
|
+
- Compatible with existing stack-based bytecode via converter
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
21
|
+
from .bytecode import Opcode, Bytecode
|
|
22
|
+
from enum import IntEnum
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class RegisterOpcode(IntEnum):
|
|
26
|
+
"""Register-based opcodes (200-299 range to avoid conflicts)"""
|
|
27
|
+
# Register load/store
|
|
28
|
+
LOAD_REG = 200 # Load constant to register: LOAD_REG r1, 42
|
|
29
|
+
LOAD_VAR_REG = 201 # Load variable to register: LOAD_VAR_REG r1, "x"
|
|
30
|
+
STORE_REG = 202 # Store register to variable: STORE_REG r1, "x"
|
|
31
|
+
MOV_REG = 203 # Move between registers: MOV_REG r2, r1
|
|
32
|
+
|
|
33
|
+
# Register arithmetic (3-address code: dest, src1, src2)
|
|
34
|
+
ADD_REG = 210 # r3 = r1 + r2
|
|
35
|
+
SUB_REG = 211 # r3 = r1 - r2
|
|
36
|
+
MUL_REG = 212 # r3 = r1 * r2
|
|
37
|
+
DIV_REG = 213 # r3 = r1 / r2
|
|
38
|
+
MOD_REG = 214 # r3 = r1 % r2
|
|
39
|
+
POW_REG = 215 # r3 = r1 ** r2
|
|
40
|
+
NEG_REG = 216 # r2 = -r1 (unary)
|
|
41
|
+
|
|
42
|
+
# Register comparisons
|
|
43
|
+
EQ_REG = 220 # r3 = (r1 == r2)
|
|
44
|
+
NEQ_REG = 221 # r3 = (r1 != r2)
|
|
45
|
+
LT_REG = 222 # r3 = (r1 < r2)
|
|
46
|
+
GT_REG = 223 # r3 = (r1 > r2)
|
|
47
|
+
LTE_REG = 224 # r3 = (r1 <= r2)
|
|
48
|
+
GTE_REG = 225 # r3 = (r1 >= r2)
|
|
49
|
+
|
|
50
|
+
# Register logical operations
|
|
51
|
+
AND_REG = 230 # r3 = r1 && r2
|
|
52
|
+
OR_REG = 231 # r3 = r1 || r2
|
|
53
|
+
NOT_REG = 232 # r2 = !r1
|
|
54
|
+
|
|
55
|
+
# Stack interop (for hybrid mode)
|
|
56
|
+
PUSH_REG = 240 # Push register value to stack
|
|
57
|
+
POP_REG = 241 # Pop stack value to register
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class RegisterFile:
|
|
61
|
+
"""
|
|
62
|
+
Virtual register file with 16 general-purpose registers.
|
|
63
|
+
|
|
64
|
+
Registers r0-r15:
|
|
65
|
+
- r0-r7: General purpose temporaries
|
|
66
|
+
- r8-r11: Function argument passing
|
|
67
|
+
- r12-r14: Saved registers (callee-saved)
|
|
68
|
+
- r15: Special purpose (return value)
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
def __init__(self, num_registers: int = 16):
|
|
72
|
+
self.num_registers = num_registers
|
|
73
|
+
self.registers: List[Any] = [None] * num_registers
|
|
74
|
+
self.dirty: List[bool] = [False] * num_registers # Track modified registers
|
|
75
|
+
|
|
76
|
+
def read(self, reg_num: int) -> Any:
|
|
77
|
+
"""Read value from register"""
|
|
78
|
+
if not (0 <= reg_num < self.num_registers):
|
|
79
|
+
raise ValueError(f"Invalid register number: r{reg_num}")
|
|
80
|
+
return self.registers[reg_num]
|
|
81
|
+
|
|
82
|
+
def write(self, reg_num: int, value: Any) -> None:
|
|
83
|
+
"""Write value to register"""
|
|
84
|
+
if not (0 <= reg_num < self.num_registers):
|
|
85
|
+
raise ValueError(f"Invalid register number: r{reg_num}")
|
|
86
|
+
self.registers[reg_num] = value
|
|
87
|
+
self.dirty[reg_num] = True
|
|
88
|
+
|
|
89
|
+
def clear(self, reg_num: int) -> None:
|
|
90
|
+
"""Clear register (set to None)"""
|
|
91
|
+
self.registers[reg_num] = None
|
|
92
|
+
self.dirty[reg_num] = False
|
|
93
|
+
|
|
94
|
+
def clear_all(self) -> None:
|
|
95
|
+
"""Clear all registers"""
|
|
96
|
+
self.registers = [None] * self.num_registers
|
|
97
|
+
self.dirty = [False] * self.num_registers
|
|
98
|
+
|
|
99
|
+
def is_dirty(self, reg_num: int) -> bool:
|
|
100
|
+
"""Check if register has been modified"""
|
|
101
|
+
return self.dirty[reg_num]
|
|
102
|
+
|
|
103
|
+
def get_free_register(self) -> Optional[int]:
|
|
104
|
+
"""Find first available (clean, None) register"""
|
|
105
|
+
for i in range(self.num_registers):
|
|
106
|
+
if self.registers[i] is None and not self.dirty[i]:
|
|
107
|
+
return i
|
|
108
|
+
return None
|
|
109
|
+
|
|
110
|
+
def __repr__(self) -> str:
|
|
111
|
+
active = [f"r{i}={v}" for i, v in enumerate(self.registers) if v is not None]
|
|
112
|
+
return f"<RegisterFile [{', '.join(active)}]>"
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class RegisterAllocator:
|
|
116
|
+
"""
|
|
117
|
+
Register allocation strategy for mapping variables to registers.
|
|
118
|
+
|
|
119
|
+
Strategies:
|
|
120
|
+
1. Linear scan allocation (simple, fast)
|
|
121
|
+
2. Graph coloring (optimal, slower)
|
|
122
|
+
3. Live range splitting for spilling
|
|
123
|
+
|
|
124
|
+
When all registers are full, spills to memory (stack/variables).
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
def __init__(self, num_registers: int = 16, reserved: int = 2):
|
|
128
|
+
"""
|
|
129
|
+
Initialize register allocator
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
num_registers: Total registers available
|
|
133
|
+
reserved: Number of reserved registers (e.g., r15 for return)
|
|
134
|
+
"""
|
|
135
|
+
self.num_registers = num_registers
|
|
136
|
+
self.reserved = reserved
|
|
137
|
+
self.available = num_registers - reserved
|
|
138
|
+
|
|
139
|
+
# Variable → register mapping
|
|
140
|
+
self.var_to_reg: Dict[str, int] = {}
|
|
141
|
+
|
|
142
|
+
# Register → variable mapping (reverse lookup)
|
|
143
|
+
self.reg_to_var: Dict[int, str] = {}
|
|
144
|
+
|
|
145
|
+
# Track register usage
|
|
146
|
+
self.allocated_regs: set = set()
|
|
147
|
+
|
|
148
|
+
# Spilled variables (couldn't fit in registers)
|
|
149
|
+
self.spilled_vars: set = set()
|
|
150
|
+
|
|
151
|
+
def allocate(self, var_name: str) -> int:
|
|
152
|
+
"""
|
|
153
|
+
Allocate a register for variable.
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
Register number, or -1 if must spill
|
|
157
|
+
"""
|
|
158
|
+
# Check if already allocated
|
|
159
|
+
if var_name in self.var_to_reg:
|
|
160
|
+
return self.var_to_reg[var_name]
|
|
161
|
+
|
|
162
|
+
# Find free register
|
|
163
|
+
for reg in range(self.available):
|
|
164
|
+
if reg not in self.allocated_regs:
|
|
165
|
+
self.var_to_reg[var_name] = reg
|
|
166
|
+
self.reg_to_var[reg] = var_name
|
|
167
|
+
self.allocated_regs.add(reg)
|
|
168
|
+
return reg
|
|
169
|
+
|
|
170
|
+
# No free registers - must spill
|
|
171
|
+
self.spilled_vars.add(var_name)
|
|
172
|
+
return -1
|
|
173
|
+
|
|
174
|
+
def free(self, var_name: str) -> None:
|
|
175
|
+
"""Free register allocated to variable"""
|
|
176
|
+
if var_name in self.var_to_reg:
|
|
177
|
+
reg = self.var_to_reg[var_name]
|
|
178
|
+
del self.var_to_reg[var_name]
|
|
179
|
+
del self.reg_to_var[reg]
|
|
180
|
+
self.allocated_regs.discard(reg)
|
|
181
|
+
|
|
182
|
+
def get_register(self, var_name: str) -> Optional[int]:
|
|
183
|
+
"""Get register allocated to variable (None if not allocated)"""
|
|
184
|
+
return self.var_to_reg.get(var_name)
|
|
185
|
+
|
|
186
|
+
def get_variable(self, reg_num: int) -> Optional[str]:
|
|
187
|
+
"""Get variable allocated to register (None if not allocated)"""
|
|
188
|
+
return self.reg_to_var.get(reg_num)
|
|
189
|
+
|
|
190
|
+
def clear(self) -> None:
|
|
191
|
+
"""Reset allocator state"""
|
|
192
|
+
self.var_to_reg.clear()
|
|
193
|
+
self.reg_to_var.clear()
|
|
194
|
+
self.allocated_regs.clear()
|
|
195
|
+
self.spilled_vars.clear()
|
|
196
|
+
|
|
197
|
+
def __repr__(self) -> str:
|
|
198
|
+
allocs = [f"{var}→r{reg}" for var, reg in self.var_to_reg.items()]
|
|
199
|
+
return f"<RegisterAllocator [{', '.join(allocs)}] spilled={len(self.spilled_vars)}>"
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
class RegisterVM:
|
|
203
|
+
"""
|
|
204
|
+
Register-based Virtual Machine for Zexus.
|
|
205
|
+
|
|
206
|
+
Features:
|
|
207
|
+
- 16 virtual registers (r0-r15)
|
|
208
|
+
- Register-based arithmetic (1.5-3x faster)
|
|
209
|
+
- Hybrid execution (registers + stack)
|
|
210
|
+
- Automatic register allocation
|
|
211
|
+
- Register spilling when needed
|
|
212
|
+
|
|
213
|
+
Usage:
|
|
214
|
+
vm = RegisterVM()
|
|
215
|
+
result = vm.execute(bytecode)
|
|
216
|
+
|
|
217
|
+
Performance:
|
|
218
|
+
Best for: arithmetic loops, mathematical computations
|
|
219
|
+
Speedup: 1.5-3x vs stack-based VM
|
|
220
|
+
"""
|
|
221
|
+
|
|
222
|
+
def __init__(
|
|
223
|
+
self,
|
|
224
|
+
num_registers: int = 16,
|
|
225
|
+
use_allocator: bool = True,
|
|
226
|
+
hybrid_mode: bool = True,
|
|
227
|
+
debug: bool = False
|
|
228
|
+
):
|
|
229
|
+
"""
|
|
230
|
+
Initialize Register VM
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
num_registers: Number of virtual registers (default 16)
|
|
234
|
+
use_allocator: Use automatic register allocation
|
|
235
|
+
hybrid_mode: Use hybrid stack+register execution
|
|
236
|
+
debug: Enable debug output
|
|
237
|
+
"""
|
|
238
|
+
self.registers = RegisterFile(num_registers)
|
|
239
|
+
self.allocator = RegisterAllocator(num_registers) if use_allocator else None
|
|
240
|
+
self.hybrid_mode = hybrid_mode
|
|
241
|
+
self.debug = debug
|
|
242
|
+
|
|
243
|
+
# Stack for hybrid mode and complex operations
|
|
244
|
+
self.stack: List[Any] = []
|
|
245
|
+
|
|
246
|
+
# Environment for variables
|
|
247
|
+
self.env: Dict[str, Any] = {}
|
|
248
|
+
|
|
249
|
+
# Constants table
|
|
250
|
+
self.constants: List[Any] = []
|
|
251
|
+
|
|
252
|
+
# Execution stats
|
|
253
|
+
self.stats = {
|
|
254
|
+
'instructions_executed': 0,
|
|
255
|
+
'register_ops': 0,
|
|
256
|
+
'stack_ops': 0,
|
|
257
|
+
'spills': 0,
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
def execute(self, bytecode: Union[Bytecode, List[Tuple]]) -> Any:
|
|
261
|
+
"""
|
|
262
|
+
Execute register-based or hybrid bytecode.
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
bytecode: Bytecode object or instruction list
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
Execution result (typically top of stack or r15 register)
|
|
269
|
+
"""
|
|
270
|
+
# Extract instructions and constants
|
|
271
|
+
if isinstance(bytecode, Bytecode):
|
|
272
|
+
instructions = bytecode.instructions
|
|
273
|
+
self.constants = bytecode.constants
|
|
274
|
+
else:
|
|
275
|
+
instructions = bytecode
|
|
276
|
+
self.constants = []
|
|
277
|
+
|
|
278
|
+
# Reset state
|
|
279
|
+
self.registers.clear_all()
|
|
280
|
+
self.stack.clear()
|
|
281
|
+
if self.allocator:
|
|
282
|
+
self.allocator.clear()
|
|
283
|
+
|
|
284
|
+
# Execute instruction stream
|
|
285
|
+
pc = 0 # Program counter
|
|
286
|
+
while pc < len(instructions):
|
|
287
|
+
inst = instructions[pc]
|
|
288
|
+
opcode = inst[0] if isinstance(inst, tuple) else inst
|
|
289
|
+
|
|
290
|
+
# Dispatch to handler
|
|
291
|
+
if opcode in RegisterOpcode.__members__.values():
|
|
292
|
+
pc = self._execute_register_instruction(inst, pc)
|
|
293
|
+
elif self.hybrid_mode:
|
|
294
|
+
pc = self._execute_stack_instruction(inst, pc)
|
|
295
|
+
else:
|
|
296
|
+
raise ValueError(f"Stack opcode {opcode} in register-only mode")
|
|
297
|
+
|
|
298
|
+
self.stats['instructions_executed'] += 1
|
|
299
|
+
pc += 1
|
|
300
|
+
|
|
301
|
+
# Return result (r15 or top of stack)
|
|
302
|
+
if self.registers.read(15) is not None:
|
|
303
|
+
return self.registers.read(15)
|
|
304
|
+
elif self.stack:
|
|
305
|
+
return self.stack[-1]
|
|
306
|
+
return None
|
|
307
|
+
|
|
308
|
+
def _execute_register_instruction(self, inst: Tuple, pc: int) -> int:
|
|
309
|
+
"""Execute register-based instruction"""
|
|
310
|
+
opcode = inst[0]
|
|
311
|
+
self.stats['register_ops'] += 1
|
|
312
|
+
|
|
313
|
+
# LOAD_REG r1, const_idx
|
|
314
|
+
if opcode == RegisterOpcode.LOAD_REG:
|
|
315
|
+
reg, const_idx = inst[1], inst[2]
|
|
316
|
+
value = self.constants[const_idx]
|
|
317
|
+
self.registers.write(reg, value)
|
|
318
|
+
if self.debug:
|
|
319
|
+
print(f" LOAD_REG r{reg}, {value}")
|
|
320
|
+
|
|
321
|
+
# LOAD_VAR_REG r1, "x"
|
|
322
|
+
elif opcode == RegisterOpcode.LOAD_VAR_REG:
|
|
323
|
+
reg, var_name = inst[1], inst[2]
|
|
324
|
+
value = self.env.get(var_name)
|
|
325
|
+
self.registers.write(reg, value)
|
|
326
|
+
if self.debug:
|
|
327
|
+
print(f" LOAD_VAR_REG r{reg}, {var_name} ({value})")
|
|
328
|
+
|
|
329
|
+
# STORE_REG r1, "x"
|
|
330
|
+
elif opcode == RegisterOpcode.STORE_REG:
|
|
331
|
+
reg, var_name = inst[1], inst[2]
|
|
332
|
+
value = self.registers.read(reg)
|
|
333
|
+
self.env[var_name] = value
|
|
334
|
+
if self.debug:
|
|
335
|
+
print(f" STORE_REG r{reg}, {var_name} ({value})")
|
|
336
|
+
|
|
337
|
+
# MOV_REG r2, r1
|
|
338
|
+
elif opcode == RegisterOpcode.MOV_REG:
|
|
339
|
+
dest, src = inst[1], inst[2]
|
|
340
|
+
value = self.registers.read(src)
|
|
341
|
+
self.registers.write(dest, value)
|
|
342
|
+
if self.debug:
|
|
343
|
+
print(f" MOV_REG r{dest}, r{src} ({value})")
|
|
344
|
+
|
|
345
|
+
# Arithmetic: ADD_REG r3, r1, r2
|
|
346
|
+
elif opcode == RegisterOpcode.ADD_REG:
|
|
347
|
+
dest, src1, src2 = inst[1], inst[2], inst[3]
|
|
348
|
+
v1, v2 = self.registers.read(src1), self.registers.read(src2)
|
|
349
|
+
self.registers.write(dest, v1 + v2)
|
|
350
|
+
if self.debug:
|
|
351
|
+
print(f" ADD_REG r{dest}, r{src1}, r{src2} ({v1} + {v2} = {v1+v2})")
|
|
352
|
+
|
|
353
|
+
elif opcode == RegisterOpcode.SUB_REG:
|
|
354
|
+
dest, src1, src2 = inst[1], inst[2], inst[3]
|
|
355
|
+
v1, v2 = self.registers.read(src1), self.registers.read(src2)
|
|
356
|
+
self.registers.write(dest, v1 - v2)
|
|
357
|
+
if self.debug:
|
|
358
|
+
print(f" SUB_REG r{dest}, r{src1}, r{src2} ({v1} - {v2} = {v1-v2})")
|
|
359
|
+
|
|
360
|
+
elif opcode == RegisterOpcode.MUL_REG:
|
|
361
|
+
dest, src1, src2 = inst[1], inst[2], inst[3]
|
|
362
|
+
v1, v2 = self.registers.read(src1), self.registers.read(src2)
|
|
363
|
+
self.registers.write(dest, v1 * v2)
|
|
364
|
+
if self.debug:
|
|
365
|
+
print(f" MUL_REG r{dest}, r{src1}, r{src2} ({v1} * {v2} = {v1*v2})")
|
|
366
|
+
|
|
367
|
+
elif opcode == RegisterOpcode.DIV_REG:
|
|
368
|
+
dest, src1, src2 = inst[1], inst[2], inst[3]
|
|
369
|
+
v1, v2 = self.registers.read(src1), self.registers.read(src2)
|
|
370
|
+
self.registers.write(dest, v1 / v2)
|
|
371
|
+
if self.debug:
|
|
372
|
+
print(f" DIV_REG r{dest}, r{src1}, r{src2} ({v1} / {v2} = {v1/v2})")
|
|
373
|
+
|
|
374
|
+
elif opcode == RegisterOpcode.MOD_REG:
|
|
375
|
+
dest, src1, src2 = inst[1], inst[2], inst[3]
|
|
376
|
+
v1, v2 = self.registers.read(src1), self.registers.read(src2)
|
|
377
|
+
self.registers.write(dest, v1 % v2)
|
|
378
|
+
|
|
379
|
+
elif opcode == RegisterOpcode.POW_REG:
|
|
380
|
+
dest, src1, src2 = inst[1], inst[2], inst[3]
|
|
381
|
+
v1, v2 = self.registers.read(src1), self.registers.read(src2)
|
|
382
|
+
self.registers.write(dest, v1 ** v2)
|
|
383
|
+
|
|
384
|
+
elif opcode == RegisterOpcode.NEG_REG:
|
|
385
|
+
dest, src = inst[1], inst[2]
|
|
386
|
+
value = self.registers.read(src)
|
|
387
|
+
self.registers.write(dest, -value)
|
|
388
|
+
|
|
389
|
+
# Comparisons
|
|
390
|
+
elif opcode == RegisterOpcode.EQ_REG:
|
|
391
|
+
dest, src1, src2 = inst[1], inst[2], inst[3]
|
|
392
|
+
v1, v2 = self.registers.read(src1), self.registers.read(src2)
|
|
393
|
+
self.registers.write(dest, v1 == v2)
|
|
394
|
+
|
|
395
|
+
elif opcode == RegisterOpcode.NEQ_REG:
|
|
396
|
+
dest, src1, src2 = inst[1], inst[2], inst[3]
|
|
397
|
+
v1, v2 = self.registers.read(src1), self.registers.read(src2)
|
|
398
|
+
self.registers.write(dest, v1 != v2)
|
|
399
|
+
|
|
400
|
+
elif opcode == RegisterOpcode.LT_REG:
|
|
401
|
+
dest, src1, src2 = inst[1], inst[2], inst[3]
|
|
402
|
+
v1, v2 = self.registers.read(src1), self.registers.read(src2)
|
|
403
|
+
self.registers.write(dest, v1 < v2)
|
|
404
|
+
|
|
405
|
+
elif opcode == RegisterOpcode.GT_REG:
|
|
406
|
+
dest, src1, src2 = inst[1], inst[2], inst[3]
|
|
407
|
+
v1, v2 = self.registers.read(src1), self.registers.read(src2)
|
|
408
|
+
self.registers.write(dest, v1 > v2)
|
|
409
|
+
|
|
410
|
+
elif opcode == RegisterOpcode.LTE_REG:
|
|
411
|
+
dest, src1, src2 = inst[1], inst[2], inst[3]
|
|
412
|
+
v1, v2 = self.registers.read(src1), self.registers.read(src2)
|
|
413
|
+
self.registers.write(dest, v1 <= v2)
|
|
414
|
+
|
|
415
|
+
elif opcode == RegisterOpcode.GTE_REG:
|
|
416
|
+
dest, src1, src2 = inst[1], inst[2], inst[3]
|
|
417
|
+
v1, v2 = self.registers.read(src1), self.registers.read(src2)
|
|
418
|
+
self.registers.write(dest, v1 >= v2)
|
|
419
|
+
|
|
420
|
+
# Logical operations
|
|
421
|
+
elif opcode == RegisterOpcode.AND_REG:
|
|
422
|
+
dest, src1, src2 = inst[1], inst[2], inst[3]
|
|
423
|
+
v1, v2 = self.registers.read(src1), self.registers.read(src2)
|
|
424
|
+
self.registers.write(dest, v1 and v2)
|
|
425
|
+
|
|
426
|
+
elif opcode == RegisterOpcode.OR_REG:
|
|
427
|
+
dest, src1, src2 = inst[1], inst[2], inst[3]
|
|
428
|
+
v1, v2 = self.registers.read(src1), self.registers.read(src2)
|
|
429
|
+
self.registers.write(dest, v1 or v2)
|
|
430
|
+
|
|
431
|
+
elif opcode == RegisterOpcode.NOT_REG:
|
|
432
|
+
dest, src = inst[1], inst[2]
|
|
433
|
+
value = self.registers.read(src)
|
|
434
|
+
self.registers.write(dest, not value)
|
|
435
|
+
|
|
436
|
+
# Stack interop (hybrid mode)
|
|
437
|
+
elif opcode == RegisterOpcode.PUSH_REG:
|
|
438
|
+
reg = inst[1]
|
|
439
|
+
value = self.registers.read(reg)
|
|
440
|
+
self.stack.append(value)
|
|
441
|
+
if self.debug:
|
|
442
|
+
print(f" PUSH_REG r{reg} ({value})")
|
|
443
|
+
|
|
444
|
+
elif opcode == RegisterOpcode.POP_REG:
|
|
445
|
+
reg = inst[1]
|
|
446
|
+
value = self.stack.pop()
|
|
447
|
+
self.registers.write(reg, value)
|
|
448
|
+
if self.debug:
|
|
449
|
+
print(f" POP_REG r{reg} ({value})")
|
|
450
|
+
|
|
451
|
+
else:
|
|
452
|
+
raise ValueError(f"Unknown register opcode: {opcode}")
|
|
453
|
+
|
|
454
|
+
return pc
|
|
455
|
+
|
|
456
|
+
def _execute_stack_instruction(self, inst: Tuple, pc: int) -> int:
|
|
457
|
+
"""Execute stack-based instruction (hybrid mode)"""
|
|
458
|
+
opcode = inst[0]
|
|
459
|
+
self.stats['stack_ops'] += 1
|
|
460
|
+
|
|
461
|
+
# Implement minimal stack operations for hybrid mode
|
|
462
|
+
if opcode == "LOAD_CONST" or opcode == Opcode.LOAD_CONST:
|
|
463
|
+
const_idx = inst[1]
|
|
464
|
+
self.stack.append(self.constants[const_idx])
|
|
465
|
+
|
|
466
|
+
elif opcode == "STORE_NAME" or opcode == Opcode.STORE_NAME:
|
|
467
|
+
var_name = inst[1]
|
|
468
|
+
value = self.stack.pop()
|
|
469
|
+
self.env[var_name] = value
|
|
470
|
+
|
|
471
|
+
elif opcode == "LOAD_NAME" or opcode == Opcode.LOAD_NAME:
|
|
472
|
+
var_name = inst[1]
|
|
473
|
+
self.stack.append(self.env.get(var_name))
|
|
474
|
+
|
|
475
|
+
elif opcode == "ADD" or opcode == Opcode.ADD:
|
|
476
|
+
b, a = self.stack.pop(), self.stack.pop()
|
|
477
|
+
self.stack.append(a + b)
|
|
478
|
+
|
|
479
|
+
elif opcode == "SUB" or opcode == Opcode.SUB:
|
|
480
|
+
b, a = self.stack.pop(), self.stack.pop()
|
|
481
|
+
self.stack.append(a - b)
|
|
482
|
+
|
|
483
|
+
elif opcode == "MUL" or opcode == Opcode.MUL:
|
|
484
|
+
b, a = self.stack.pop(), self.stack.pop()
|
|
485
|
+
self.stack.append(a * b)
|
|
486
|
+
|
|
487
|
+
elif opcode == "DIV" or opcode == Opcode.DIV:
|
|
488
|
+
b, a = self.stack.pop(), self.stack.pop()
|
|
489
|
+
self.stack.append(a / b)
|
|
490
|
+
|
|
491
|
+
elif opcode == "PRINT" or opcode == Opcode.PRINT:
|
|
492
|
+
value = self.stack.pop() if self.stack else None
|
|
493
|
+
print(value)
|
|
494
|
+
|
|
495
|
+
elif opcode == "RETURN" or opcode == Opcode.RETURN:
|
|
496
|
+
# Store return value in r15 for consistency
|
|
497
|
+
if self.stack:
|
|
498
|
+
self.registers.write(15, self.stack.pop())
|
|
499
|
+
|
|
500
|
+
else:
|
|
501
|
+
if self.debug:
|
|
502
|
+
print(f" Unimplemented stack opcode: {opcode}")
|
|
503
|
+
|
|
504
|
+
return pc
|
|
505
|
+
|
|
506
|
+
def get_stats(self) -> Dict[str, int]:
|
|
507
|
+
"""Get execution statistics"""
|
|
508
|
+
total = self.stats['register_ops'] + self.stats['stack_ops']
|
|
509
|
+
if total > 0:
|
|
510
|
+
register_pct = (self.stats['register_ops'] / total) * 100
|
|
511
|
+
else:
|
|
512
|
+
register_pct = 0
|
|
513
|
+
|
|
514
|
+
return {
|
|
515
|
+
**self.stats,
|
|
516
|
+
'register_percentage': register_pct,
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
def __repr__(self) -> str:
|
|
520
|
+
return f"<RegisterVM regs={self.registers.num_registers} stack={len(self.stack)}>"
|