zexus 1.6.8 → 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.
Files changed (177) hide show
  1. package/README.md +12 -5
  2. package/package.json +1 -1
  3. package/src/__init__.py +7 -0
  4. package/src/zexus/__init__.py +1 -1
  5. package/src/zexus/__pycache__/__init__.cpython-312.pyc +0 -0
  6. package/src/zexus/__pycache__/capability_system.cpython-312.pyc +0 -0
  7. package/src/zexus/__pycache__/debug_sanitizer.cpython-312.pyc +0 -0
  8. package/src/zexus/__pycache__/environment.cpython-312.pyc +0 -0
  9. package/src/zexus/__pycache__/error_reporter.cpython-312.pyc +0 -0
  10. package/src/zexus/__pycache__/input_validation.cpython-312.pyc +0 -0
  11. package/src/zexus/__pycache__/lexer.cpython-312.pyc +0 -0
  12. package/src/zexus/__pycache__/module_cache.cpython-312.pyc +0 -0
  13. package/src/zexus/__pycache__/module_manager.cpython-312.pyc +0 -0
  14. package/src/zexus/__pycache__/object.cpython-312.pyc +0 -0
  15. package/src/zexus/__pycache__/security.cpython-312.pyc +0 -0
  16. package/src/zexus/__pycache__/security_enforcement.cpython-312.pyc +0 -0
  17. package/src/zexus/__pycache__/syntax_validator.cpython-312.pyc +0 -0
  18. package/src/zexus/__pycache__/zexus_ast.cpython-312.pyc +0 -0
  19. package/src/zexus/__pycache__/zexus_token.cpython-312.pyc +0 -0
  20. package/src/zexus/access_control_system/__pycache__/__init__.cpython-312.pyc +0 -0
  21. package/src/zexus/access_control_system/__pycache__/access_control.cpython-312.pyc +0 -0
  22. package/src/zexus/advanced_types.py +17 -2
  23. package/src/zexus/blockchain/__init__.py +411 -0
  24. package/src/zexus/blockchain/accelerator.py +1160 -0
  25. package/src/zexus/blockchain/chain.py +660 -0
  26. package/src/zexus/blockchain/consensus.py +821 -0
  27. package/src/zexus/blockchain/contract_vm.py +1019 -0
  28. package/src/zexus/blockchain/crypto.py +79 -14
  29. package/src/zexus/blockchain/events.py +526 -0
  30. package/src/zexus/blockchain/loadtest.py +721 -0
  31. package/src/zexus/blockchain/monitoring.py +350 -0
  32. package/src/zexus/blockchain/mpt.py +716 -0
  33. package/src/zexus/blockchain/multichain.py +951 -0
  34. package/src/zexus/blockchain/multiprocess_executor.py +338 -0
  35. package/src/zexus/blockchain/network.py +886 -0
  36. package/src/zexus/blockchain/node.py +666 -0
  37. package/src/zexus/blockchain/rpc.py +1203 -0
  38. package/src/zexus/blockchain/rust_bridge.py +421 -0
  39. package/src/zexus/blockchain/storage.py +423 -0
  40. package/src/zexus/blockchain/tokens.py +750 -0
  41. package/src/zexus/blockchain/upgradeable.py +1004 -0
  42. package/src/zexus/blockchain/verification.py +1602 -0
  43. package/src/zexus/blockchain/wallet.py +621 -0
  44. package/src/zexus/capability_system.py +184 -9
  45. package/src/zexus/cli/__pycache__/main.cpython-312.pyc +0 -0
  46. package/src/zexus/cli/main.py +383 -34
  47. package/src/zexus/cli/zpm.py +1 -1
  48. package/src/zexus/compiler/__pycache__/bytecode.cpython-312.pyc +0 -0
  49. package/src/zexus/compiler/__pycache__/lexer.cpython-312.pyc +0 -0
  50. package/src/zexus/compiler/__pycache__/parser.cpython-312.pyc +0 -0
  51. package/src/zexus/compiler/__pycache__/semantic.cpython-312.pyc +0 -0
  52. package/src/zexus/compiler/__pycache__/zexus_ast.cpython-312.pyc +0 -0
  53. package/src/zexus/compiler/bytecode.py +124 -7
  54. package/src/zexus/compiler/compat_runtime.py +6 -2
  55. package/src/zexus/compiler/lexer.py +16 -5
  56. package/src/zexus/compiler/parser.py +108 -7
  57. package/src/zexus/compiler/semantic.py +18 -19
  58. package/src/zexus/compiler/zexus_ast.py +26 -1
  59. package/src/zexus/concurrency_system.py +79 -0
  60. package/src/zexus/config.py +54 -0
  61. package/src/zexus/crypto_bridge.py +244 -8
  62. package/src/zexus/dap/__init__.py +10 -0
  63. package/src/zexus/dap/__main__.py +4 -0
  64. package/src/zexus/dap/dap_server.py +391 -0
  65. package/src/zexus/dap/debug_engine.py +298 -0
  66. package/src/zexus/environment.py +112 -9
  67. package/src/zexus/evaluator/__pycache__/bytecode_compiler.cpython-312.pyc +0 -0
  68. package/src/zexus/evaluator/__pycache__/core.cpython-312.pyc +0 -0
  69. package/src/zexus/evaluator/__pycache__/expressions.cpython-312.pyc +0 -0
  70. package/src/zexus/evaluator/__pycache__/functions.cpython-312.pyc +0 -0
  71. package/src/zexus/evaluator/__pycache__/resource_limiter.cpython-312.pyc +0 -0
  72. package/src/zexus/evaluator/__pycache__/statements.cpython-312.pyc +0 -0
  73. package/src/zexus/evaluator/__pycache__/unified_execution.cpython-312.pyc +0 -0
  74. package/src/zexus/evaluator/__pycache__/utils.cpython-312.pyc +0 -0
  75. package/src/zexus/evaluator/bytecode_compiler.py +457 -37
  76. package/src/zexus/evaluator/core.py +644 -50
  77. package/src/zexus/evaluator/expressions.py +358 -62
  78. package/src/zexus/evaluator/functions.py +458 -20
  79. package/src/zexus/evaluator/resource_limiter.py +4 -4
  80. package/src/zexus/evaluator/statements.py +774 -122
  81. package/src/zexus/evaluator/unified_execution.py +573 -72
  82. package/src/zexus/evaluator/utils.py +14 -2
  83. package/src/zexus/evaluator_original.py +1 -1
  84. package/src/zexus/event_loop.py +186 -0
  85. package/src/zexus/lexer.py +742 -458
  86. package/src/zexus/lsp/__init__.py +1 -1
  87. package/src/zexus/lsp/definition_provider.py +163 -9
  88. package/src/zexus/lsp/server.py +22 -8
  89. package/src/zexus/lsp/symbol_provider.py +182 -9
  90. package/src/zexus/module_cache.py +239 -9
  91. package/src/zexus/module_manager.py +129 -1
  92. package/src/zexus/object.py +76 -6
  93. package/src/zexus/parser/__pycache__/parser.cpython-312.pyc +0 -0
  94. package/src/zexus/parser/__pycache__/strategy_context.cpython-312.pyc +0 -0
  95. package/src/zexus/parser/__pycache__/strategy_structural.cpython-312.pyc +0 -0
  96. package/src/zexus/parser/parser.py +1349 -408
  97. package/src/zexus/parser/strategy_context.py +755 -58
  98. package/src/zexus/parser/strategy_structural.py +121 -21
  99. package/src/zexus/persistence.py +15 -1
  100. package/src/zexus/renderer/__init__.py +61 -0
  101. package/src/zexus/renderer/__pycache__/__init__.cpython-312.pyc +0 -0
  102. package/src/zexus/renderer/__pycache__/backend.cpython-312.pyc +0 -0
  103. package/src/zexus/renderer/__pycache__/canvas.cpython-312.pyc +0 -0
  104. package/src/zexus/renderer/__pycache__/color_system.cpython-312.pyc +0 -0
  105. package/src/zexus/renderer/__pycache__/layout.cpython-312.pyc +0 -0
  106. package/src/zexus/renderer/__pycache__/main_renderer.cpython-312.pyc +0 -0
  107. package/src/zexus/renderer/__pycache__/painter.cpython-312.pyc +0 -0
  108. package/src/zexus/renderer/backend.py +261 -0
  109. package/src/zexus/renderer/canvas.py +78 -0
  110. package/src/zexus/renderer/color_system.py +201 -0
  111. package/src/zexus/renderer/graphics.py +31 -0
  112. package/src/zexus/renderer/layout.py +222 -0
  113. package/src/zexus/renderer/main_renderer.py +66 -0
  114. package/src/zexus/renderer/painter.py +30 -0
  115. package/src/zexus/renderer/tk_backend.py +208 -0
  116. package/src/zexus/renderer/web_backend.py +260 -0
  117. package/src/zexus/runtime/__init__.py +10 -2
  118. package/src/zexus/runtime/__pycache__/__init__.cpython-312.pyc +0 -0
  119. package/src/zexus/runtime/__pycache__/async_runtime.cpython-312.pyc +0 -0
  120. package/src/zexus/runtime/__pycache__/load_manager.cpython-312.pyc +0 -0
  121. package/src/zexus/runtime/file_flags.py +137 -0
  122. package/src/zexus/runtime/load_manager.py +368 -0
  123. package/src/zexus/safety/__pycache__/__init__.cpython-312.pyc +0 -0
  124. package/src/zexus/safety/__pycache__/memory_safety.cpython-312.pyc +0 -0
  125. package/src/zexus/security.py +424 -34
  126. package/src/zexus/stdlib/fs.py +23 -18
  127. package/src/zexus/stdlib/http.py +289 -186
  128. package/src/zexus/stdlib/sockets.py +207 -163
  129. package/src/zexus/stdlib/websockets.py +282 -0
  130. package/src/zexus/stdlib_integration.py +369 -2
  131. package/src/zexus/strategy_recovery.py +6 -3
  132. package/src/zexus/type_checker.py +423 -0
  133. package/src/zexus/virtual_filesystem.py +189 -2
  134. package/src/zexus/vm/__init__.py +113 -3
  135. package/src/zexus/vm/__pycache__/async_optimizer.cpython-312.pyc +0 -0
  136. package/src/zexus/vm/__pycache__/bytecode.cpython-312.pyc +0 -0
  137. package/src/zexus/vm/__pycache__/bytecode_converter.cpython-312.pyc +0 -0
  138. package/src/zexus/vm/__pycache__/cache.cpython-312.pyc +0 -0
  139. package/src/zexus/vm/__pycache__/compiler.cpython-312.pyc +0 -0
  140. package/src/zexus/vm/__pycache__/gas_metering.cpython-312.pyc +0 -0
  141. package/src/zexus/vm/__pycache__/jit.cpython-312.pyc +0 -0
  142. package/src/zexus/vm/__pycache__/parallel_vm.cpython-312.pyc +0 -0
  143. package/src/zexus/vm/__pycache__/vm.cpython-312.pyc +0 -0
  144. package/src/zexus/vm/async_optimizer.py +80 -6
  145. package/src/zexus/vm/binary_bytecode.py +659 -0
  146. package/src/zexus/vm/bytecode.py +59 -11
  147. package/src/zexus/vm/bytecode_converter.py +26 -12
  148. package/src/zexus/vm/cabi.c +1985 -0
  149. package/src/zexus/vm/cabi.cpython-312-x86_64-linux-gnu.so +0 -0
  150. package/src/zexus/vm/cabi.h +127 -0
  151. package/src/zexus/vm/cache.py +561 -17
  152. package/src/zexus/vm/compiler.py +818 -51
  153. package/src/zexus/vm/fastops.c +15743 -0
  154. package/src/zexus/vm/fastops.cpython-312-x86_64-linux-gnu.so +0 -0
  155. package/src/zexus/vm/fastops.pyx +288 -0
  156. package/src/zexus/vm/gas_metering.py +50 -9
  157. package/src/zexus/vm/jit.py +364 -20
  158. package/src/zexus/vm/native_jit_backend.py +1816 -0
  159. package/src/zexus/vm/native_runtime.cpp +1388 -0
  160. package/src/zexus/vm/native_runtime.cpython-312-x86_64-linux-gnu.so +0 -0
  161. package/src/zexus/vm/optimizer.py +161 -11
  162. package/src/zexus/vm/parallel_vm.py +140 -45
  163. package/src/zexus/vm/peephole_optimizer.py +82 -4
  164. package/src/zexus/vm/profiler.py +38 -18
  165. package/src/zexus/vm/register_allocator.py +16 -5
  166. package/src/zexus/vm/register_vm.py +8 -5
  167. package/src/zexus/vm/vm.py +3581 -531
  168. package/src/zexus/vm/wasm_compiler.py +658 -0
  169. package/src/zexus/zexus_ast.py +137 -11
  170. package/src/zexus/zexus_token.py +16 -5
  171. package/src/zexus/zpm/installer.py +55 -15
  172. package/src/zexus/zpm/package_manager.py +1 -1
  173. package/src/zexus/zpm/registry.py +257 -28
  174. package/src/zexus.egg-info/PKG-INFO +16 -6
  175. package/src/zexus.egg-info/SOURCES.txt +129 -17
  176. package/src/zexus.egg-info/entry_points.txt +1 -0
  177. package/src/zexus.egg-info/requires.txt +4 -0
@@ -18,6 +18,7 @@ Features:
18
18
  import hashlib
19
19
  import time
20
20
  import dis
21
+ import os
21
22
  from typing import Dict, Any, Optional, Tuple, Callable, List, Set
22
23
  from dataclasses import dataclass, field
23
24
  from enum import Enum
@@ -29,6 +30,19 @@ try:
29
30
  except ImportError:
30
31
  OPTIMIZER_AVAILABLE = False
31
32
 
33
+ try:
34
+ from .gas_metering import OutOfGasError, OperationLimitExceededError
35
+ except Exception:
36
+ OutOfGasError = None
37
+ OperationLimitExceededError = None
38
+
39
+ try:
40
+ from .native_jit_backend import NativeJITBackend
41
+ _NATIVE_JIT_AVAILABLE = True
42
+ except Exception:
43
+ _NATIVE_JIT_AVAILABLE = False
44
+ NativeJITBackend = None
45
+
32
46
 
33
47
  class ExecutionTier(Enum):
34
48
  """Execution tiers for tiered compilation"""
@@ -128,6 +142,28 @@ class JITCompiler:
128
142
  'RETURN', 'JUMP', 'JUMP_IF_FALSE',
129
143
  }
130
144
 
145
+ # Native JIT backend (optional)
146
+ self.native_backend = None
147
+ native_flag = os.environ.get("ZEXUS_NATIVE_JIT", "0")
148
+ if native_flag.lower() in ("1", "true", "yes"):
149
+ self.enable_native_backend()
150
+ if os.environ.get("ZEXUS_JIT_TRACE", "0") in ("1", "true", "yes"):
151
+ print(f"[JIT TRACE] native_backend={'on' if self.native_backend else 'off'}")
152
+
153
+ def enable_native_backend(self) -> bool:
154
+ if self.native_backend is not None:
155
+ return True
156
+ if not _NATIVE_JIT_AVAILABLE:
157
+ return False
158
+ try:
159
+ self.native_backend = NativeJITBackend(debug=self.debug)
160
+ if self.debug:
161
+ print("🔧 JIT: Native backend enabled")
162
+ return True
163
+ except Exception:
164
+ self.native_backend = None
165
+ return False
166
+
131
167
  def should_compile(self, bytecode_hash: str) -> bool:
132
168
  """
133
169
  Determine if bytecode should be JIT compiled
@@ -217,6 +253,33 @@ class JITCompiler:
217
253
 
218
254
  start_time = time.time()
219
255
 
256
+ # Native JIT path
257
+ if self.native_backend is not None:
258
+ try:
259
+ native_fn = self.native_backend.compile(bytecode)
260
+ if native_fn is not None:
261
+ self.compilation_cache[bytecode_hash] = native_fn
262
+ compilation_time = time.time() - start_time
263
+ self.stats.compilations += 1
264
+ self.stats.compilation_time += compilation_time
265
+ self.stats.average_compilation_time = (
266
+ self.stats.compilation_time / self.stats.compilations
267
+ )
268
+ self.stats.tier_promotions += 1
269
+
270
+ if bytecode_hash in self.hot_paths:
271
+ info = self.hot_paths[bytecode_hash]
272
+ info.compiled_version = native_fn
273
+ info.compilation_time = compilation_time
274
+ info.tier = ExecutionTier.JIT_NATIVE
275
+
276
+ if self.debug:
277
+ print(f"✅ JIT: Native compiled {bytecode_hash[:8]} in {compilation_time*1000:.2f}ms")
278
+ return native_fn
279
+ except Exception:
280
+ if self.debug:
281
+ print(f"⚠️ JIT: Native backend failed for {bytecode_hash[:8]}, falling back")
282
+
220
283
  try:
221
284
  # Step 1: Analyze stack behavior
222
285
  stack_frames = self._analyze_stack_behavior(bytecode)
@@ -242,18 +305,27 @@ class JITCompiler:
242
305
  compiled = compile(python_code, f'<jit:{bytecode_hash[:8]}>', 'exec')
243
306
 
244
307
  # Step 5: Create executable function
245
- namespace = {'__builtins__': {}}
308
+ namespace = {
309
+ '__builtins__': {},
310
+ 'OutOfGasError': OutOfGasError,
311
+ 'OperationLimitExceededError': OperationLimitExceededError,
312
+ }
246
313
  exec(compiled, namespace)
247
314
  jit_function = namespace.get('jit_execute')
248
315
 
249
316
  if jit_function:
250
- # Verify the compiled function works
251
317
  verification_result = self._verify_compilation(bytecode, jit_function)
252
318
  if not verification_result:
253
- if self.debug:
254
- print(f"❌ JIT: Verification failed for {bytecode_hash[:8]}")
255
- self.stats.compilation_failures += 1
256
- return None
319
+ fallback_fn = self._build_fallback_executor(optimized_instructions, updated_constants)
320
+ if fallback_fn and self._verify_compilation(bytecode, fallback_fn):
321
+ if self.debug:
322
+ print(f"♻️ JIT: Falling back to compatibility executor for {bytecode_hash[:8]}")
323
+ jit_function = fallback_fn
324
+ else:
325
+ if self.debug:
326
+ print(f"❌ JIT: Verification failed for {bytecode_hash[:8]}")
327
+ self.stats.compilation_failures += 1
328
+ return None
257
329
 
258
330
  # Cache the compiled function
259
331
  self.compilation_cache[bytecode_hash] = jit_function
@@ -372,6 +444,7 @@ class JITCompiler:
372
444
  instructions = bytecode.instructions if hasattr(bytecode, 'instructions') else bytecode
373
445
 
374
446
  for opcode, _ in instructions:
447
+ opcode = self._normalize_opcode(opcode)
375
448
  if opcode not in self.supported_opcodes:
376
449
  if self.debug:
377
450
  print(f"⚠️ JIT: Unsupported opcode: {opcode}")
@@ -385,8 +458,12 @@ class JITCompiler:
385
458
  Returns:
386
459
  List of StackFrame objects representing stack state at each instruction
387
460
  """
388
- instructions = bytecode.instructions if hasattr(bytecode, 'instructions') else bytecode
461
+ raw_instructions = bytecode.instructions if hasattr(bytecode, 'instructions') else bytecode
389
462
  constants = bytecode.constants if hasattr(bytecode, 'constants') else []
463
+ instructions = [
464
+ (self._normalize_opcode(opcode), operand)
465
+ for opcode, operand in raw_instructions
466
+ ]
390
467
 
391
468
  frames = []
392
469
  current_frame = StackFrame()
@@ -484,24 +561,32 @@ class JITCompiler:
484
561
  'OR': 'or',
485
562
  }.get(opcode, opcode)
486
563
 
564
+ def _normalize_opcode(self, opcode) -> str:
565
+ """Normalize opcode values from enums or raw strings."""
566
+ return opcode.name if hasattr(opcode, 'name') else opcode
567
+
487
568
  def _optimize_bytecode(self, bytecode) -> Tuple[List, List]:
488
569
  """
489
570
  Apply optimization passes to bytecode
490
571
 
491
572
  Returns: (optimized_instructions, updated_constants)
492
573
  """
493
- instructions = list(bytecode.instructions) if hasattr(bytecode, 'instructions') else list(bytecode)
574
+ raw_instructions = list(bytecode.instructions) if hasattr(bytecode, 'instructions') else list(bytecode)
494
575
  constants = list(bytecode.constants) if hasattr(bytecode, 'constants') else []
576
+ instructions = [
577
+ (self._normalize_opcode(opcode), operand)
578
+ for opcode, operand in raw_instructions
579
+ ]
495
580
 
496
581
  if self.optimizer:
497
582
  try:
498
- optimized, updated_constants = self.optimizer.optimize(instructions, constants)
583
+ optimized = self.optimizer.optimize(instructions, constants)
499
584
  if self.debug:
500
585
  stats = self.optimizer.get_stats()
501
586
  if stats['total_optimizations'] > 0:
502
587
  print(f"🔧 JIT Optimizer: {stats['original_size']} → {stats['optimized_size']} instructions "
503
- f"({stats['size_reduction_pct']:.1f}% reduction)")
504
- return optimized, updated_constants
588
+ f"({stats['size_reduction']:.1f}% reduction)")
589
+ return optimized, constants
505
590
  except Exception as e:
506
591
  if self.debug:
507
592
  print(f"⚠️ JIT: Optimizer failed: {e}")
@@ -538,6 +623,229 @@ class JITCompiler:
538
623
 
539
624
  return optimized
540
625
 
626
+ def _build_fallback_executor(self, instructions, constants):
627
+ """Construct a conservative executor for instructions when optimized code fails."""
628
+ normalized_instrs = [
629
+ (self._normalize_opcode(op), operand)
630
+ for op, operand in (instructions or [])
631
+ ]
632
+ consts = list(constants or [])
633
+
634
+ def _const(idx):
635
+ if isinstance(idx, int) and 0 <= idx < len(consts):
636
+ return consts[idx]
637
+ return idx
638
+
639
+ arithmetic_ops: Dict[str, Callable[[Any, Any], Any]] = {
640
+ 'ADD': lambda a, b: a + b,
641
+ 'SUB': lambda a, b: a - b,
642
+ 'MUL': lambda a, b: a * b,
643
+ 'DIV': lambda a, b: a / b if b not in (0, None) else None,
644
+ 'MOD': lambda a, b: a % b if b not in (0, None) else None,
645
+ 'POW': lambda a, b: a ** b,
646
+ }
647
+
648
+ compare_ops: Dict[str, Callable[[Any, Any], bool]] = {
649
+ 'EQ': lambda a, b: a == b,
650
+ 'NEQ': lambda a, b: a != b,
651
+ 'LT': lambda a, b: a < b,
652
+ 'GT': lambda a, b: a > b,
653
+ 'LTE': lambda a, b: a <= b,
654
+ 'GTE': lambda a, b: a >= b,
655
+ }
656
+
657
+ def jit_execute(vm, stack, env):
658
+ ip = 0
659
+ while ip < len(normalized_instrs):
660
+ op, operand = normalized_instrs[ip]
661
+
662
+ if op == 'LOAD_CONST':
663
+ stack.append(_const(operand))
664
+
665
+ elif op == 'LOAD_NAME':
666
+ name = _const(operand)
667
+ stack.append(env.get(name, None))
668
+
669
+ elif op == 'STORE_NAME':
670
+ name = _const(operand)
671
+ value = stack.pop() if stack else None
672
+ env[name] = value
673
+
674
+ elif op == 'STORE_CONST':
675
+ if isinstance(operand, (tuple, list)) and len(operand) == 2:
676
+ name = _const(operand[0])
677
+ value = _const(operand[1])
678
+ env[name] = value
679
+
680
+ elif op in arithmetic_ops:
681
+ b = stack.pop() if stack else None
682
+ a = stack.pop() if stack else None
683
+ try:
684
+ stack.append(arithmetic_ops[op](a, b))
685
+ except Exception:
686
+ stack.append(None)
687
+
688
+ elif op in compare_ops:
689
+ b = stack.pop() if stack else None
690
+ a = stack.pop() if stack else None
691
+ try:
692
+ stack.append(compare_ops[op](a, b))
693
+ except Exception:
694
+ stack.append(False)
695
+
696
+ elif op == 'NOT':
697
+ value = stack.pop() if stack else None
698
+ stack.append(not value)
699
+
700
+ elif op == 'AND':
701
+ b = stack.pop() if stack else None
702
+ a = stack.pop() if stack else None
703
+ stack.append(bool(a) and bool(b))
704
+
705
+ elif op == 'OR':
706
+ b = stack.pop() if stack else None
707
+ a = stack.pop() if stack else None
708
+ stack.append(bool(a) or bool(b))
709
+
710
+ elif op == 'POP':
711
+ if stack:
712
+ stack.pop()
713
+
714
+ elif op == 'JUMP':
715
+ ip = operand if isinstance(operand, int) else ip + 1
716
+ continue
717
+
718
+ elif op == 'JUMP_IF_FALSE':
719
+ condition = stack.pop() if stack else None
720
+ target = operand if isinstance(operand, int) else None
721
+ if not condition and target is not None:
722
+ ip = target
723
+ continue
724
+
725
+ elif op == 'RETURN':
726
+ return stack[-1] if stack else None
727
+
728
+ else:
729
+ # Unsupported opcode - bail out with None to keep semantics safe
730
+ return stack[-1] if stack else None
731
+
732
+ ip += 1
733
+
734
+ return stack[-1] if stack else None
735
+
736
+ return jit_execute if normalized_instrs else None
737
+
738
+ def _constant_folding(self, instructions, constants=None):
739
+ """Perform simple constant folding for common arithmetic patterns."""
740
+ instructions = [tuple(inst) for inst in instructions or []]
741
+ constants_list = list(constants) if constants is not None else None
742
+
743
+ if not instructions:
744
+ return []
745
+
746
+ # Without constants we cannot safely fold indexed operands.
747
+ if not constants_list:
748
+ return list(instructions)
749
+
750
+ def _op_name(op):
751
+ return op.name if hasattr(op, 'name') else op
752
+
753
+ result = []
754
+ i = 0
755
+ while i < len(instructions):
756
+ if i + 2 < len(instructions):
757
+ op1, operand1 = instructions[i]
758
+ op2, operand2 = instructions[i + 1]
759
+ op3, _ = instructions[i + 2]
760
+ if (_op_name(op1) == 'LOAD_CONST' and _op_name(op2) == 'LOAD_CONST' and
761
+ isinstance(operand1, int) and isinstance(operand2, int) and
762
+ 0 <= operand1 < len(constants_list) and 0 <= operand2 < len(constants_list) and
763
+ _op_name(op3) in {'ADD', 'SUB', 'MUL', 'DIV', 'MOD', 'POW'}):
764
+ a = constants_list[operand1]
765
+ b = constants_list[operand2]
766
+ try:
767
+ op3_name = _op_name(op3)
768
+ if op3_name == 'ADD':
769
+ value = a + b
770
+ elif op3_name == 'SUB':
771
+ value = a - b
772
+ elif op3_name == 'MUL':
773
+ value = a * b
774
+ elif op3_name == 'DIV':
775
+ value = a / b if b != 0 else 0
776
+ elif op3_name == 'MOD':
777
+ value = a % b if b != 0 else 0
778
+ else: # POW
779
+ value = a ** b
780
+ except Exception:
781
+ value = None
782
+
783
+ if value is not None:
784
+ const_idx = len(constants_list)
785
+ constants_list.append(value)
786
+ result.append(('LOAD_CONST', const_idx))
787
+ i += 3
788
+ continue
789
+ result.append(instructions[i])
790
+ i += 1
791
+ return result
792
+
793
+ def _dead_code_elimination(self, instructions):
794
+ """Remove unreachable instructions after terminal ops."""
795
+ instructions = [tuple(inst) for inst in instructions or []]
796
+ def _op_name(op):
797
+ return op.name if hasattr(op, 'name') else op
798
+ result = []
799
+ dead = False
800
+ for opcode, operand in instructions:
801
+ name = _op_name(opcode)
802
+ if dead and name not in {'LABEL', 'JUMP_TARGET'}:
803
+ continue
804
+ result.append((opcode, operand))
805
+ if name in {'RETURN', 'JUMP'}:
806
+ dead = True
807
+ return result
808
+
809
+ def _peephole_optimization(self, instructions):
810
+ """Eliminate short redundant instruction patterns."""
811
+ instructions = [tuple(inst) for inst in instructions or []]
812
+ def _op_name(op):
813
+ return op.name if hasattr(op, 'name') else op
814
+ result = []
815
+ i = 0
816
+ while i < len(instructions):
817
+ if i + 1 < len(instructions):
818
+ op1, operand1 = instructions[i]
819
+ op2, _ = instructions[i + 1]
820
+ if _op_name(op1) in {'LOAD_CONST', 'LOAD_NAME'} and _op_name(op2) == 'POP':
821
+ i += 2
822
+ continue
823
+ if _op_name(op1) == 'DUP' and _op_name(op2) == 'POP':
824
+ i += 2
825
+ continue
826
+ result.append(instructions[i])
827
+ i += 1
828
+ return result
829
+
830
+ def _instruction_combining(self, instructions):
831
+ """Combine simple instruction pairs into compact forms."""
832
+ instructions = [tuple(inst) for inst in instructions or []]
833
+ def _op_name(op):
834
+ return op.name if hasattr(op, 'name') else op
835
+ result = []
836
+ i = 0
837
+ while i < len(instructions):
838
+ if i + 1 < len(instructions):
839
+ (op1, operand1) = instructions[i]
840
+ (op2, operand2) = instructions[i + 1]
841
+ if _op_name(op1) == 'LOAD_CONST' and _op_name(op2) == 'STORE_NAME':
842
+ result.append(('STORE_CONST', (operand2, operand1)))
843
+ i += 2
844
+ continue
845
+ result.append(instructions[i])
846
+ i += 1
847
+ return result
848
+
541
849
  def _generate_efficient_python_code(self, instructions: List, constants: List, stack_frames: List[StackFrame]) -> str:
542
850
  """
543
851
  Generate efficient Python source code from optimized bytecode
@@ -546,6 +854,14 @@ class JITCompiler:
546
854
  lines = [
547
855
  "def jit_execute(vm, stack, env):",
548
856
  " # JIT-compiled native code",
857
+ " gas = getattr(vm, 'gas_metering', None)",
858
+ " def _gas(op, **kwargs):",
859
+ " if gas is None:",
860
+ " return",
861
+ " if not gas.consume(op, **kwargs):",
862
+ " if gas.operation_count > gas.max_operations:",
863
+ " raise OperationLimitExceededError(gas.operation_count, gas.max_operations)",
864
+ " raise OutOfGasError(gas.gas_used, gas.gas_limit, op)",
549
865
  ]
550
866
 
551
867
  # Track variable assignments for efficient code generation
@@ -559,6 +875,7 @@ class JITCompiler:
559
875
  frame = stack_frames[i]
560
876
 
561
877
  if opcode == 'LOAD_CONST':
878
+ lines.append(" _gas('LOAD_CONST')")
562
879
  if operand < len(constants):
563
880
  const_val = constants[operand]
564
881
  var_name = f"const_{operand}_{i}"
@@ -572,6 +889,7 @@ class JITCompiler:
572
889
  stack_height += 1
573
890
 
574
891
  elif opcode == 'LOAD_NAME':
892
+ lines.append(" _gas('LOAD_NAME')")
575
893
  if operand < len(constants):
576
894
  name = constants[operand]
577
895
  var_name = f"var_{operand}_{i}"
@@ -585,6 +903,7 @@ class JITCompiler:
585
903
  stack_height += 1
586
904
 
587
905
  elif opcode == 'STORE_NAME':
906
+ lines.append(" _gas('STORE_NAME')")
588
907
  if operand < len(constants):
589
908
  name = constants[operand]
590
909
  if stack_height > 0:
@@ -592,6 +911,7 @@ class JITCompiler:
592
911
  stack_height -= 1
593
912
 
594
913
  elif opcode == 'STORE_CONST':
914
+ lines.append(" _gas('STORE_NAME')")
595
915
  if isinstance(operand, tuple) and len(operand) == 2:
596
916
  name_idx, const_idx = operand
597
917
  if name_idx < len(constants) and const_idx < len(constants):
@@ -600,10 +920,12 @@ class JITCompiler:
600
920
  lines.append(f" env[{repr(name)}] = {repr(const_val)}")
601
921
 
602
922
  elif opcode in ['ADD', 'SUB', 'MUL', 'DIV', 'MOD', 'POW']:
923
+ lines.append(f" _gas('{opcode}')")
603
924
  if stack_height >= 2:
604
925
  # Generate efficient arithmetic
605
926
  operator = self._opcode_to_operator(opcode)
606
927
  result_var = f"result_{i}"
928
+ assigned = False
607
929
 
608
930
  # Try to use pre-computed values from stack analysis
609
931
  if i > 0 and i-1 < len(stack_frames):
@@ -619,28 +941,29 @@ class JITCompiler:
619
941
 
620
942
  # Check if we can compute at compile time
621
943
  try:
622
- if (a_expr.startswith('const_') and b_expr.startswith('const_')):
944
+ if (isinstance(a_expr, str) and isinstance(b_expr, str) and
945
+ a_expr.startswith('const_') and b_expr.startswith('const_')):
623
946
  # Already computed by optimizer
624
947
  computed = eval(f"{a_val} {operator} {b_val}")
625
948
  lines.append(f" {result_var} = {repr(computed)}")
626
949
  else:
627
950
  lines.append(f" {result_var} = {a_val} {operator} {b_val}")
628
- except (TypeError, ValueError, NameError, SyntaxError):
951
+ except (TypeError, ValueError, NameError, SyntaxError, AttributeError):
629
952
  lines.append(f" {result_var} = {a_val} {operator} {b_val}")
630
- else:
631
- lines.append(f" b = stack.pop()")
632
- lines.append(f" a = stack.pop()")
633
- lines.append(f" {result_var} = a {operator} b")
634
- else:
953
+ assigned = True
954
+
955
+ if not assigned:
635
956
  lines.append(f" b = stack.pop()")
636
957
  lines.append(f" a = stack.pop()")
637
958
  lines.append(f" {result_var} = a {operator} b")
959
+ assigned = True
638
960
 
639
961
  local_vars.add(result_var)
640
962
  lines.append(f" stack.append({result_var})")
641
963
  stack_height -= 1 # 2 popped, 1 pushed = net -1
642
964
 
643
965
  elif opcode == 'RETURN':
966
+ lines.append(" _gas('RETURN')")
644
967
  if stack_height > 0:
645
968
  lines.append(" return stack[-1]")
646
969
  else:
@@ -683,13 +1006,34 @@ class JITCompiler:
683
1006
  vm_bytecode = VM(use_jit=False)
684
1007
  vm_bytecode.env = env_dict.copy()
685
1008
  vm_bytecode.stack = stack.copy()
686
- bytecode_result = vm_bytecode.execute(original_bytecode)
1009
+ bytecode_exc = None
1010
+ try:
1011
+ bytecode_result = vm_bytecode.execute(original_bytecode)
1012
+ except Exception as e: # noqa: BLE001 - intentional verification comparison
1013
+ bytecode_exc = e
1014
+ bytecode_result = None
687
1015
 
688
1016
  # Run JIT version
689
1017
  vm_jit = VM(use_jit=False)
690
1018
  vm_jit.env = env_dict.copy()
691
1019
  vm_jit.stack = stack.copy()
692
- jit_result = jit_function(vm_jit, vm_jit.stack, vm_jit.env)
1020
+ jit_exc = None
1021
+ try:
1022
+ jit_result = jit_function(vm_jit, vm_jit.stack, vm_jit.env)
1023
+ except Exception as e: # noqa: BLE001 - intentional verification comparison
1024
+ jit_exc = e
1025
+ jit_result = None
1026
+
1027
+ # If both threw exceptions, ensure they match in type
1028
+ if bytecode_exc or jit_exc:
1029
+ if type(bytecode_exc) != type(jit_exc):
1030
+ if self.debug:
1031
+ print("❌ JIT Verification mismatch (exceptions):")
1032
+ print(f" Bytecode exception: {bytecode_exc!r}")
1033
+ print(f" JIT exception: {jit_exc!r}")
1034
+ print(f" Environment: {env_dict}")
1035
+ return False
1036
+ continue
693
1037
 
694
1038
  # Compare results
695
1039
  if bytecode_result != jit_result: