zexus 1.8.0 → 1.8.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 (51) hide show
  1. package/README.md +34 -6
  2. package/bin/zexus +12 -2
  3. package/bin/zpics +12 -2
  4. package/bin/zpm +12 -2
  5. package/bin/zx +12 -2
  6. package/bin/zx-deploy +12 -2
  7. package/bin/zx-dev +12 -2
  8. package/bin/zx-run +12 -2
  9. package/package.json +2 -1
  10. package/rust_core/Cargo.lock +603 -0
  11. package/rust_core/Cargo.toml +26 -0
  12. package/rust_core/README.md +15 -0
  13. package/rust_core/pyproject.toml +25 -0
  14. package/rust_core/src/binary_bytecode.rs +543 -0
  15. package/rust_core/src/contract_vm.rs +643 -0
  16. package/rust_core/src/executor.rs +847 -0
  17. package/rust_core/src/hasher.rs +90 -0
  18. package/rust_core/src/lib.rs +71 -0
  19. package/rust_core/src/merkle.rs +128 -0
  20. package/rust_core/src/rust_vm.rs +2313 -0
  21. package/rust_core/src/signature.rs +79 -0
  22. package/rust_core/src/state_adapter.rs +281 -0
  23. package/rust_core/src/validator.rs +116 -0
  24. package/scripts/postinstall.js +204 -21
  25. package/src/zexus/__init__.py +1 -1
  26. package/src/zexus/cli/main.py +1 -1
  27. package/src/zexus/cli/zpm.py +1 -1
  28. package/src/zexus/evaluator/bytecode_compiler.py +150 -52
  29. package/src/zexus/evaluator/core.py +151 -809
  30. package/src/zexus/evaluator/expressions.py +27 -22
  31. package/src/zexus/evaluator/functions.py +171 -126
  32. package/src/zexus/evaluator/statements.py +55 -112
  33. package/src/zexus/module_cache.py +20 -9
  34. package/src/zexus/object.py +330 -38
  35. package/src/zexus/parser/parser.py +103 -23
  36. package/src/zexus/parser/strategy_context.py +318 -6
  37. package/src/zexus/parser/strategy_structural.py +2 -2
  38. package/src/zexus/persistence.py +46 -17
  39. package/src/zexus/security.py +140 -234
  40. package/src/zexus/type_checker.py +44 -5
  41. package/src/zexus/vm/binary_bytecode.py +7 -3
  42. package/src/zexus/vm/bytecode.py +6 -0
  43. package/src/zexus/vm/cache.py +24 -46
  44. package/src/zexus/vm/compiler.py +549 -68
  45. package/src/zexus/vm/memory_pool.py +21 -9
  46. package/src/zexus/vm/vm.py +609 -95
  47. package/src/zexus/zpm/package_manager.py +1 -1
  48. package/src/zexus.egg-info/PKG-INFO +56 -12
  49. package/src/zexus.egg-info/SOURCES.txt +14 -0
  50. package/src/zexus.egg-info/entry_points.txt +5 -1
  51. package/src/zexus.egg-info/requires.txt +26 -0
@@ -2,6 +2,7 @@
2
2
  import traceback
3
3
  import asyncio
4
4
  import os
5
+ import re
5
6
  import sys
6
7
  from .. import zexus_ast
7
8
  from ..object import Environment, EvaluationError, Null, Boolean as BooleanObj, Map, EmbeddedCode, List, Action, LambdaFunction, String, ReturnValue, Builtin, Integer, Float
@@ -97,160 +98,127 @@ class Evaluator(ExpressionEvaluatorMixin, StatementEvaluatorMixin, FunctionEvalu
97
98
  self.use_vm = previous_use_vm
98
99
 
99
100
  def _ensure_recursion_headroom(self, minimum: int = 5000):
100
- """Ensure Python's recursion limit can accommodate deep language recursion."""
101
+ """(M8) Keep recursion usable, but avoid an unbounded recursion-limit jump.
102
+
103
+ The interpreter's evaluation strategy uses Python recursion for AST
104
+ traversal and function calls. With the default Python recursion limit,
105
+ relatively small program recursion (e.g., factorial(100)) can trigger
106
+ `RecursionError`.
107
+
108
+ Default behavior:
109
+ - Raise the recursion limit to a conservative target (3000) if the
110
+ current limit is lower.
111
+ - Never raise above `minimum`.
112
+
113
+ Opt-in override:
114
+ - Set `ZEXUS_PYTHON_RECURSION_LIMIT=<int>` to request a specific limit.
115
+
116
+ Opt-out:
117
+ - Set `ZEXUS_DISABLE_RECURSION_LIMIT_RAISE=1` to disable any adjustment.
118
+ """
119
+ if os.getenv("ZEXUS_DISABLE_RECURSION_LIMIT_RAISE") == "1":
120
+ return
121
+
122
+ requested = os.getenv("ZEXUS_PYTHON_RECURSION_LIMIT")
123
+ default_target = 3000
124
+
101
125
  try:
102
126
  current = sys.getrecursionlimit()
103
- if current < minimum:
104
- sys.setrecursionlimit(minimum)
127
+ requested_limit = int(requested) if requested else default_target
128
+ if requested_limit <= 0:
129
+ return
130
+
131
+ target = min(max(current, requested_limit), minimum)
132
+ if target > current:
133
+ sys.setrecursionlimit(target)
105
134
  except Exception:
106
- pass
135
+ return
107
136
 
108
137
  def _initialize_dispatch_table(self):
109
- """Precompute handlers for ALL node types to eliminate isinstance overhead.
110
-
111
- Every AST node type gets an O(1) dict lookup instead of walking
112
- a ~117-branch isinstance chain. This yields ~28%+ faster evaluation
113
- on typical programs.
138
+ """Precompute handlers for AST node types to eliminate isinstance overhead.
139
+
140
+ (M4) This table is the single dispatch source of truth.
114
141
  """
115
- try:
116
- # Core hot-path nodes with dedicated handler methods
117
- self._node_handlers = {
118
- zexus_ast.Program: self._handle_program_node,
119
- zexus_ast.ExpressionStatement: self._handle_expression_statement,
120
- zexus_ast.BlockStatement: self._handle_block_statement,
121
- zexus_ast.ReturnStatement: self._handle_return_statement,
122
- zexus_ast.LetStatement: self._handle_let_statement,
123
- zexus_ast.ConstStatement: self._handle_const_statement,
124
- zexus_ast.AssignmentExpression: self._handle_assignment_expression,
125
- zexus_ast.IfStatement: self._handle_if_statement,
126
- zexus_ast.WhileStatement: self._handle_while_statement,
127
- zexus_ast.ActionStatement: self._handle_action_statement,
128
- zexus_ast.FunctionStatement: self._handle_function_statement,
129
- zexus_ast.Identifier: self._handle_identifier,
130
- zexus_ast.IntegerLiteral: self._handle_integer_literal,
131
- zexus_ast.Boolean: self._handle_boolean_literal,
132
- zexus_ast.NullLiteral: self._handle_null_literal,
133
- zexus_ast.ThisExpression: self._handle_this_expression,
134
- zexus_ast.InfixExpression: self._handle_infix_expression,
135
- zexus_ast.PrefixExpression: self._handle_prefix_expression,
136
- zexus_ast.CallExpression: self._handle_call_expression,
137
- zexus_ast.PropertyAccessExpression: self._handle_property_access_expression,
138
- zexus_ast.MethodCallExpression: self._handle_method_call_expression,
139
- zexus_ast.ListLiteral: self._handle_list_literal,
140
- zexus_ast.StringLiteral: self._handle_string_literal,
141
- zexus_ast.StringInterpolationExpression: self._handle_string_interpolation,
142
- zexus_ast.FloatLiteral: self._handle_float_literal,
143
- zexus_ast.MapLiteral: self._handle_map_literal,
144
- zexus_ast.LambdaExpression: self._handle_lambda_expression,
145
- zexus_ast.ActionLiteral: self._handle_action_literal,
146
- zexus_ast.ForEachStatement: self._handle_foreach_statement,
147
- zexus_ast.PrintStatement: self._handle_print_statement,
148
- zexus_ast.DataStatement: self._handle_data_statement,
149
- zexus_ast.TryCatchStatement: self._handle_try_catch_statement,
150
- zexus_ast.ThrowStatement: self._handle_throw_statement,
151
- zexus_ast.ContractStatement: self._handle_contract_statement,
152
- zexus_ast.ExportStatement: self._handle_export_statement,
153
- zexus_ast.UseStatement: self._handle_use_statement,
154
- zexus_ast.FromStatement: self._handle_from_statement,
155
- zexus_ast.IfExpression: self._handle_if_expression,
156
- zexus_ast.TernaryExpression: self._handle_ternary_expression,
157
- zexus_ast.ContinueStatement: self._handle_continue_statement,
158
- zexus_ast.BreakStatement: self._handle_break_statement,
159
- }
160
-
161
- # Extend with ALL remaining node types — each delegates to its
162
- # corresponding eval_* method, eliminating the isinstance fallback.
163
- _extended_dispatch = {
164
- # Security statements
165
- zexus_ast.SealStatement: 'eval_seal_statement',
166
- zexus_ast.RestrictStatement: 'eval_restrict_statement',
167
- zexus_ast.SandboxStatement: 'eval_sandbox_statement',
168
- zexus_ast.TrailStatement: 'eval_trail_statement',
169
- zexus_ast.CapabilityStatement: 'eval_capability_statement',
170
- zexus_ast.GrantStatement: 'eval_grant_statement',
171
- zexus_ast.RevokeStatement: 'eval_revoke_statement',
172
- zexus_ast.ValidateStatement: 'eval_validate_statement',
173
- zexus_ast.SanitizeStatement: 'eval_sanitize_statement',
174
- zexus_ast.InjectStatement: 'eval_inject_statement',
175
- zexus_ast.ImmutableStatement: 'eval_immutable_statement',
176
- zexus_ast.ProtectStatement: 'eval_protect_statement',
177
- zexus_ast.VerifyStatement: 'eval_verify_statement',
178
- # Blockchain / state
179
- zexus_ast.TxStatement: 'eval_tx_statement',
180
- zexus_ast.EntityStatement: 'eval_entity_statement',
181
- zexus_ast.LedgerStatement: 'eval_ledger_statement',
182
- zexus_ast.StateStatement: 'eval_state_statement',
183
- zexus_ast.RequireStatement: 'eval_require_statement',
184
- zexus_ast.RevertStatement: 'eval_revert_statement',
185
- zexus_ast.LimitStatement: 'eval_limit_statement',
186
- zexus_ast.ProtocolStatement: 'eval_protocol_statement',
187
- zexus_ast.PersistentStatement: 'eval_persistent_statement',
188
- zexus_ast.EmitStatement: 'eval_emit_statement',
189
- zexus_ast.ModifierDeclaration: 'eval_modifier_declaration',
190
- # UI
191
- zexus_ast.ScreenStatement: 'eval_screen_statement',
192
- zexus_ast.ColorStatement: 'eval_color_statement',
193
- zexus_ast.CanvasStatement: 'eval_canvas_statement',
194
- zexus_ast.GraphicsStatement: 'eval_graphics_statement',
195
- zexus_ast.AnimationStatement: 'eval_animation_statement',
196
- zexus_ast.ClockStatement: 'eval_clock_statement',
197
- zexus_ast.ComponentStatement: 'eval_component_statement',
198
- zexus_ast.ThemeStatement: 'eval_theme_statement',
199
- # Concurrency
200
- zexus_ast.ChannelStatement: 'eval_channel_statement',
201
- zexus_ast.SendStatement: 'eval_send_statement',
202
- zexus_ast.ReceiveStatement: 'eval_receive_statement',
203
- zexus_ast.AtomicStatement: 'eval_atomic_statement',
204
- # Language features
205
- zexus_ast.WatchStatement: 'eval_watch_statement',
206
- zexus_ast.DeferStatement: 'eval_defer_statement',
207
- zexus_ast.PatternStatement: 'eval_pattern_statement',
208
- zexus_ast.EnumStatement: 'eval_enum_statement',
209
- zexus_ast.StreamStatement: 'eval_stream_statement',
210
- zexus_ast.DebugStatement: 'eval_debug_statement',
211
- zexus_ast.LogStatement: 'eval_log_statement',
212
- zexus_ast.ImportLogStatement: 'eval_import_log_statement',
213
- zexus_ast.ExternalDeclaration: 'eval_external_declaration',
214
- zexus_ast.ExactlyStatement: 'eval_exactly_statement',
215
- zexus_ast.NativeStatement: 'eval_native_statement',
216
- zexus_ast.GCStatement: 'eval_gc_statement',
217
- zexus_ast.InlineStatement: 'eval_inline_statement',
218
- zexus_ast.BufferStatement: 'eval_buffer_statement',
219
- zexus_ast.SIMDStatement: 'eval_simd_statement',
220
- zexus_ast.EmbeddedCodeStatement: 'eval_embedded_code_statement',
221
- zexus_ast.MiddlewareStatement: 'eval_middleware_statement',
222
- zexus_ast.AuthStatement: 'eval_auth_statement',
223
- zexus_ast.ThrottleStatement: 'eval_throttle_statement',
224
- zexus_ast.CacheStatement: 'eval_cache_statement',
225
- zexus_ast.InterfaceStatement: 'eval_interface_statement',
226
- zexus_ast.TypeAliasStatement: 'eval_type_alias_statement',
227
- zexus_ast.ModuleStatement: 'eval_module_statement',
228
- zexus_ast.PackageStatement: 'eval_package_statement',
229
- zexus_ast.UsingStatement: 'eval_using_statement',
230
- # Expressions
231
- zexus_ast.MatchExpression: 'eval_match_expression',
232
- zexus_ast.AwaitExpression: 'eval_await_expression',
233
- zexus_ast.AsyncExpression: 'eval_async_expression',
234
- zexus_ast.FindExpression: 'eval_find_expression',
235
- zexus_ast.LoadExpression: 'eval_load_expression',
236
- zexus_ast.FileImportExpression: 'eval_file_import_expression',
237
- zexus_ast.NullishExpression: 'eval_nullish_expression',
238
- zexus_ast.SliceExpression: 'eval_slice_expression',
239
- zexus_ast.EmbeddedLiteral: 'eval_embedded_literal',
240
- zexus_ast.TXExpression: 'eval_tx_expression',
241
- zexus_ast.HashExpression: 'eval_hash_expression',
242
- zexus_ast.SignatureExpression: 'eval_signature_expression',
243
- zexus_ast.VerifySignatureExpression: 'eval_verify_signature_expression',
244
- zexus_ast.GasExpression: 'eval_gas_expression',
245
- }
246
- for ast_type, method_name in _extended_dispatch.items():
247
- method = getattr(self, method_name, None)
248
- if method:
249
- self._node_handlers[ast_type] = lambda node, env, st, m=method: m(node, env, st)
250
-
251
- except AttributeError:
252
- # AST variants may omit certain nodes; keep table empty in that case
253
- self._node_handlers = {}
142
+
143
+ def _camel_to_snake(name: str) -> str:
144
+ # Handles acronyms reasonably (e.g., TXExpression -> tx_expression)
145
+ s1 = re.sub(r"(.)([A-Z][a-z]+)", r"\1_\2", name)
146
+ return re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", s1).lower()
147
+
148
+ def _ast(name: str):
149
+ return getattr(zexus_ast, name, None)
150
+
151
+ self._node_handlers = {}
152
+
153
+ # Core hot-path nodes with dedicated handler methods
154
+ _core = {
155
+ "Program": self._handle_program_node,
156
+ "ExpressionStatement": self._handle_expression_statement,
157
+ "BlockStatement": self._handle_block_statement,
158
+ "ReturnStatement": self._handle_return_statement,
159
+ "LetStatement": self._handle_let_statement,
160
+ "ConstStatement": self._handle_const_statement,
161
+ "AssignmentExpression": self._handle_assignment_expression,
162
+ "IfStatement": self._handle_if_statement,
163
+ "WhileStatement": self._handle_while_statement,
164
+ "ActionStatement": self._handle_action_statement,
165
+ "FunctionStatement": self._handle_function_statement,
166
+ "Identifier": self._handle_identifier,
167
+ "IntegerLiteral": self._handle_integer_literal,
168
+ "Boolean": self._handle_boolean_literal,
169
+ "NullLiteral": self._handle_null_literal,
170
+ "ThisExpression": self._handle_this_expression,
171
+ "InfixExpression": self._handle_infix_expression,
172
+ "PrefixExpression": self._handle_prefix_expression,
173
+ "CallExpression": self._handle_call_expression,
174
+ "PropertyAccessExpression": self._handle_property_access_expression,
175
+ "MethodCallExpression": self._handle_method_call_expression,
176
+ "ListLiteral": self._handle_list_literal,
177
+ "StringLiteral": self._handle_string_literal,
178
+ "StringInterpolationExpression": self._handle_string_interpolation,
179
+ "FloatLiteral": self._handle_float_literal,
180
+ "MapLiteral": self._handle_map_literal,
181
+ "LambdaExpression": self._handle_lambda_expression,
182
+ "ActionLiteral": self._handle_action_literal,
183
+ "ForEachStatement": self._handle_foreach_statement,
184
+ "PrintStatement": self._handle_print_statement,
185
+ "DataStatement": self._handle_data_statement,
186
+ "TryCatchStatement": self._handle_try_catch_statement,
187
+ "ThrowStatement": self._handle_throw_statement,
188
+ "ContractStatement": self._handle_contract_statement,
189
+ "ExportStatement": self._handle_export_statement,
190
+ "UseStatement": self._handle_use_statement,
191
+ "FromStatement": self._handle_from_statement,
192
+ "IfExpression": self._handle_if_expression,
193
+ "TernaryExpression": self._handle_ternary_expression,
194
+ "ContinueStatement": self._handle_continue_statement,
195
+ "BreakStatement": self._handle_break_statement,
196
+ }
197
+ for ast_name, handler in _core.items():
198
+ ast_type = _ast(ast_name)
199
+ if ast_type is not None:
200
+ self._node_handlers[ast_type] = handler
201
+
202
+ # Auto-register remaining node classes that follow the eval_<snake_case> convention.
203
+ base_node = getattr(zexus_ast, "Node", None)
204
+ for ast_name, ast_type in vars(zexus_ast).items():
205
+ if not isinstance(ast_type, type):
206
+ continue
207
+ if ast_type in self._node_handlers:
208
+ continue
209
+ if base_node is not None and ast_type is base_node:
210
+ continue
211
+
212
+ try:
213
+ if base_node is not None and not issubclass(ast_type, base_node):
214
+ continue
215
+ except Exception:
216
+ continue
217
+
218
+ method_name = f"eval_{_camel_to_snake(ast_name)}"
219
+ method = getattr(self, method_name, None)
220
+ if callable(method):
221
+ self._node_handlers[ast_type] = lambda node, env, st, m=method: m(node, env, st)
254
222
 
255
223
  def _handle_program_node(self, node, env, stack_trace):
256
224
  debug_log(" Program node", f"{len(node.statements)} statements")
@@ -492,670 +460,23 @@ class Evaluator(ExpressionEvaluatorMixin, StatementEvaluatorMixin, FunctionEvalu
492
460
  node_type = type(node)
493
461
 
494
462
  handler = self._node_handlers.get(node_type)
495
- if handler:
496
- return handler(node, env, stack_trace)
463
+ if handler is None:
464
+ return EvaluationError(f"Unsupported AST node type: {node_type.__name__}")
497
465
 
498
466
  try:
499
- # === STATEMENTS ===
500
- if isinstance(node, zexus_ast.Program):
501
- debug_log(" Program node", f"{len(node.statements)} statements")
502
- return self.ceval_program(node.statements, env)
503
-
504
- elif isinstance(node, zexus_ast.ExpressionStatement):
505
- debug_log(" ExpressionStatement node")
506
- return self.eval_node(node.expression, env, stack_trace)
507
-
508
- elif isinstance(node, zexus_ast.BlockStatement):
509
- debug_log(" BlockStatement node", f"{len(node.statements)} statements")
510
- return self.eval_block_statement(node, env, stack_trace)
511
-
512
- elif isinstance(node, zexus_ast.ReturnStatement):
513
- debug_log(" ReturnStatement node")
514
- return self.eval_return_statement(node, env, stack_trace)
515
-
516
- elif isinstance(node, zexus_ast.ContinueStatement):
517
- debug_log(" ContinueStatement node")
518
- return self.eval_continue_statement(node, env, stack_trace)
519
-
520
- elif isinstance(node, zexus_ast.BreakStatement):
521
- debug_log(" BreakStatement node")
522
- return self.eval_break_statement(node, env, stack_trace)
523
-
524
- elif isinstance(node, zexus_ast.LetStatement):
525
- return self.eval_let_statement(node, env, stack_trace)
526
-
527
- elif isinstance(node, zexus_ast.ConstStatement):
528
- return self.eval_const_statement(node, env, stack_trace)
529
-
530
- elif isinstance(node, zexus_ast.DataStatement):
531
- return self.eval_data_statement(node, env, stack_trace)
532
-
533
- elif isinstance(node, zexus_ast.AssignmentExpression):
534
- debug_log(" AssignmentExpression node")
535
- return self.eval_assignment_expression(node, env, stack_trace)
536
-
537
- elif isinstance(node, zexus_ast.TryCatchStatement):
538
- return self.eval_try_catch_statement(node, env, stack_trace)
539
-
540
- elif isinstance(node, zexus_ast.ThrowStatement):
541
- debug_log(" ThrowStatement node")
542
- return self.eval_throw_statement(node, env, stack_trace)
543
-
544
- elif isinstance(node, zexus_ast.IfStatement):
545
- debug_log(" IfStatement node")
546
- return self.eval_if_statement(node, env, stack_trace)
547
-
548
- elif isinstance(node, zexus_ast.WhileStatement):
549
- debug_log(" WhileStatement node")
550
- return self.eval_while_statement(node, env, stack_trace)
551
-
552
- elif isinstance(node, zexus_ast.ForEachStatement):
553
- debug_log(" ForEachStatement node", f"for each {node.item.value}")
554
- return self.eval_foreach_statement(node, env, stack_trace)
555
-
556
- elif isinstance(node, zexus_ast.WatchStatement):
557
- debug_log(" WatchStatement node")
558
- return self.eval_watch_statement(node, env, stack_trace)
559
-
560
- elif isinstance(node, zexus_ast.SealStatement):
561
- return self.eval_seal_statement(node, env, stack_trace)
562
-
563
- elif isinstance(node, zexus_ast.RestrictStatement):
564
- return self.eval_restrict_statement(node, env, stack_trace)
565
-
566
- elif isinstance(node, zexus_ast.SandboxStatement):
567
- return self.eval_sandbox_statement(node, env, stack_trace)
568
-
569
- elif isinstance(node, zexus_ast.TrailStatement):
570
- return self.eval_trail_statement(node, env, stack_trace)
571
-
572
- elif isinstance(node, zexus_ast.TxStatement):
573
- return self.eval_tx_statement(node, env, stack_trace)
574
-
575
- elif isinstance(node, zexus_ast.EntityStatement):
576
- return self.eval_entity_statement(node, env, stack_trace)
577
-
578
- elif isinstance(node, zexus_ast.ContractStatement):
579
- return self.eval_contract_statement(node, env, stack_trace)
580
-
581
- elif isinstance(node, zexus_ast.ExportStatement):
582
- return self.eval_export_statement(node, env, stack_trace)
583
-
584
- elif isinstance(node, zexus_ast.UseStatement):
585
- debug_log(" UseStatement node", node.file_path)
586
- return self.eval_use_statement(node, env, stack_trace)
587
-
588
- elif isinstance(node, zexus_ast.FromStatement):
589
- debug_log(" FromStatement node", node.file_path)
590
- return self.eval_from_statement(node, env, stack_trace)
591
-
592
- elif isinstance(node, zexus_ast.VerifyStatement):
593
- return self.eval_verify_statement(node, env, stack_trace)
594
-
595
- elif isinstance(node, zexus_ast.ProtectStatement):
596
- return self.eval_protect_statement(node, env, stack_trace)
597
-
598
- elif isinstance(node, zexus_ast.MiddlewareStatement):
599
- return self.eval_middleware_statement(node, env, stack_trace)
600
-
601
- elif isinstance(node, zexus_ast.AuthStatement):
602
- return self.eval_auth_statement(node, env, stack_trace)
603
-
604
- elif isinstance(node, zexus_ast.ThrottleStatement):
605
- return self.eval_throttle_statement(node, env, stack_trace)
606
-
607
- elif isinstance(node, zexus_ast.CacheStatement):
608
- return self.eval_cache_statement(node, env, stack_trace)
609
-
610
- elif isinstance(node, zexus_ast.PrintStatement):
611
- debug_log(" PrintStatement node")
612
- return self.eval_print_statement(node, env, stack_trace)
613
-
614
- elif isinstance(node, zexus_ast.ScreenStatement):
615
- debug_log(" ScreenStatement node", node.name.value)
616
- return self.eval_screen_statement(node, env, stack_trace)
617
-
618
- elif isinstance(node, zexus_ast.EmbeddedCodeStatement):
619
- debug_log(" EmbeddedCodeStatement node", node.name.value)
620
- return self.eval_embedded_code_statement(node, env, stack_trace)
621
-
622
- elif isinstance(node, zexus_ast.ColorStatement):
623
- debug_log(" ColorStatement node", node.name.value)
624
- return self.eval_color_statement(node, env, stack_trace)
625
-
626
- elif isinstance(node, zexus_ast.CanvasStatement):
627
- debug_log(" CanvasStatement node", node.name.value)
628
- return self.eval_canvas_statement(node, env, stack_trace)
629
-
630
- elif isinstance(node, zexus_ast.GraphicsStatement):
631
- debug_log(" GraphicsStatement node", node.name.value)
632
- return self.eval_graphics_statement(node, env, stack_trace)
633
-
634
- elif isinstance(node, zexus_ast.AnimationStatement):
635
- debug_log(" AnimationStatement node", node.name.value)
636
- return self.eval_animation_statement(node, env, stack_trace)
637
-
638
- elif isinstance(node, zexus_ast.ClockStatement):
639
- debug_log(" ClockStatement node", node.name.value)
640
- return self.eval_clock_statement(node, env, stack_trace)
641
-
642
- elif isinstance(node, zexus_ast.ComponentStatement):
643
- debug_log(" ComponentStatement node", node.name.value)
644
- return self.eval_component_statement(node, env, stack_trace)
645
-
646
- elif isinstance(node, zexus_ast.ThemeStatement):
647
- debug_log(" ThemeStatement node", node.name.value)
648
- return self.eval_theme_statement(node, env, stack_trace)
649
-
650
- elif isinstance(node, zexus_ast.DebugStatement):
651
- debug_log(" DebugStatement node")
652
- return self.eval_debug_statement(node, env, stack_trace)
653
-
654
- elif isinstance(node, zexus_ast.ExternalDeclaration):
655
- debug_log(" ExternalDeclaration node", node.name.value)
656
- return self.eval_external_declaration(node, env, stack_trace)
657
-
658
- elif isinstance(node, zexus_ast.ExactlyStatement):
659
- debug_log(" ExactlyStatement node")
660
- return self.eval_exactly_statement(node, env, stack_trace)
661
-
662
- elif isinstance(node, zexus_ast.ActionStatement):
663
- debug_log(" ActionStatement node", f"action {node.name.value}")
664
- return self.eval_action_statement(node, env, stack_trace)
665
-
666
- elif isinstance(node, zexus_ast.FunctionStatement):
667
- debug_log(" FunctionStatement node", f"function {node.name.value}")
668
- debug_log(" FunctionStatement evaluate", f"{node.name.value} modifiers={getattr(node, 'modifiers', [])}")
669
- return self.eval_function_statement(node, env, stack_trace)
670
-
671
- elif isinstance(node, zexus_ast.NativeStatement):
672
- debug_log(" NativeStatement node", f"native {node.function_name}")
673
- return self.eval_native_statement(node, env, stack_trace)
674
-
675
- elif isinstance(node, zexus_ast.GCStatement):
676
- debug_log(" GCStatement node", f"gc {node.action}")
677
- return self.eval_gc_statement(node, env, stack_trace)
678
-
679
- elif isinstance(node, zexus_ast.InlineStatement):
680
- debug_log(" InlineStatement node", f"inline {node.function_name}")
681
- return self.eval_inline_statement(node, env, stack_trace)
682
-
683
- elif isinstance(node, zexus_ast.BufferStatement):
684
- debug_log(" BufferStatement node", f"buffer {node.buffer_name}")
685
- return self.eval_buffer_statement(node, env, stack_trace)
686
-
687
- elif isinstance(node, zexus_ast.SIMDStatement):
688
- debug_log(" SIMDStatement node")
689
- return self.eval_simd_statement(node, env, stack_trace)
690
-
691
- elif isinstance(node, zexus_ast.DeferStatement):
692
- debug_log(" DeferStatement node")
693
- return self.eval_defer_statement(node, env, stack_trace)
694
-
695
- elif isinstance(node, zexus_ast.PatternStatement):
696
- debug_log(" PatternStatement node")
697
- return self.eval_pattern_statement(node, env, stack_trace)
698
-
699
- elif isinstance(node, zexus_ast.EnumStatement):
700
- debug_log(" EnumStatement node", f"enum {node.name}")
701
- return self.eval_enum_statement(node, env, stack_trace)
702
-
703
- elif isinstance(node, zexus_ast.StreamStatement):
704
- debug_log(" StreamStatement node", f"stream {node.stream_name}")
705
- return self.eval_stream_statement(node, env, stack_trace)
706
-
707
- elif isinstance(node, zexus_ast.WatchStatement):
708
- debug_log(" WatchStatement node")
709
- return self.eval_watch_statement(node, env, stack_trace)
710
-
711
- elif isinstance(node, zexus_ast.LogStatement):
712
- debug_log(" LogStatement node")
713
- return self.eval_log_statement(node, env, stack_trace)
714
-
715
- elif isinstance(node, zexus_ast.ImportLogStatement):
716
- debug_log(" ImportLogStatement node", "log <<")
717
- return self.eval_import_log_statement(node, env, stack_trace)
718
-
719
- # === NEW SECURITY STATEMENTS ===
720
- elif isinstance(node, zexus_ast.CapabilityStatement):
721
- debug_log(" CapabilityStatement node", f"capability {node.name}")
722
- return self.eval_capability_statement(node, env, stack_trace)
723
-
724
- elif isinstance(node, zexus_ast.GrantStatement):
725
- debug_log(" GrantStatement node", f"grant {node.entity_name}")
726
- return self.eval_grant_statement(node, env, stack_trace)
727
-
728
- elif isinstance(node, zexus_ast.RevokeStatement):
729
- debug_log(" RevokeStatement node", f"revoke {node.entity_name}")
730
- return self.eval_revoke_statement(node, env, stack_trace)
731
-
732
- elif isinstance(node, zexus_ast.ValidateStatement):
733
- debug_log(" ValidateStatement node")
734
- return self.eval_validate_statement(node, env, stack_trace)
735
-
736
- elif isinstance(node, zexus_ast.SanitizeStatement):
737
- debug_log(" SanitizeStatement node")
738
- return self.eval_sanitize_statement(node, env, stack_trace)
739
-
740
- elif isinstance(node, zexus_ast.InjectStatement):
741
- debug_log(" InjectStatement node")
742
- return self.eval_inject_statement(node, env, stack_trace)
743
-
744
- elif isinstance(node, zexus_ast.ImmutableStatement):
745
- debug_log(" ImmutableStatement node", f"immutable {node.target}")
746
- return self.eval_immutable_statement(node, env, stack_trace)
747
-
748
- # === COMPLEXITY & LARGE PROJECT MANAGEMENT STATEMENTS ===
749
- elif isinstance(node, zexus_ast.InterfaceStatement):
750
- debug_log(" InterfaceStatement node", f"interface {node.name.value}")
751
- return self.eval_interface_statement(node, env, stack_trace)
752
-
753
- elif isinstance(node, zexus_ast.TypeAliasStatement):
754
- debug_log(" TypeAliasStatement node", f"type_alias {node.name.value}")
755
- return self.eval_type_alias_statement(node, env, stack_trace)
756
-
757
- elif isinstance(node, zexus_ast.ModuleStatement):
758
- debug_log(" ModuleStatement node", f"module {node.name.value}")
759
- return self.eval_module_statement(node, env, stack_trace)
760
-
761
- elif isinstance(node, zexus_ast.PackageStatement):
762
- debug_log(" PackageStatement node", f"package {node.name.value}")
763
- return self.eval_package_statement(node, env, stack_trace)
764
-
765
- elif isinstance(node, zexus_ast.UsingStatement):
766
- debug_log(" UsingStatement node", f"using {node.resource_name.value}")
767
- return self.eval_using_statement(node, env, stack_trace)
768
-
769
- # === EXPRESSIONS ===
770
- # === CONCURRENCY & PERFORMANCE STATEMENTS ===
771
- elif isinstance(node, zexus_ast.ChannelStatement):
772
- debug_log(" ChannelStatement node", f"channel {node.name.value}")
773
- return self.eval_channel_statement(node, env, stack_trace)
774
-
775
- elif isinstance(node, zexus_ast.SendStatement):
776
- debug_log(" SendStatement node", "send to channel")
777
- return self.eval_send_statement(node, env, stack_trace)
778
-
779
- elif isinstance(node, zexus_ast.ReceiveStatement):
780
- debug_log(" ReceiveStatement node", "receive from channel")
781
- return self.eval_receive_statement(node, env, stack_trace)
782
-
783
- elif isinstance(node, zexus_ast.AtomicStatement):
784
- debug_log(" AtomicStatement node", "atomic operation")
785
- return self.eval_atomic_statement(node, env, stack_trace)
786
-
787
- # === BLOCKCHAIN STATEMENTS ===
788
- elif isinstance(node, zexus_ast.LedgerStatement):
789
- debug_log(" LedgerStatement node", f"ledger {node.name.value}")
790
- return self.eval_ledger_statement(node, env, stack_trace)
791
-
792
- elif isinstance(node, zexus_ast.StateStatement):
793
- debug_log(" StateStatement node", f"state {node.name.value}")
794
- return self.eval_state_statement(node, env, stack_trace)
795
-
796
- elif isinstance(node, zexus_ast.RequireStatement):
797
- debug_log(" RequireStatement node", "require condition")
798
- return self.eval_require_statement(node, env, stack_trace)
799
-
800
- elif isinstance(node, zexus_ast.RevertStatement):
801
- debug_log(" RevertStatement node", "revert transaction")
802
- return self.eval_revert_statement(node, env, stack_trace)
803
-
804
- elif isinstance(node, zexus_ast.LimitStatement):
805
- debug_log(" LimitStatement node", "set gas limit")
806
- return self.eval_limit_statement(node, env, stack_trace)
807
-
808
- elif isinstance(node, zexus_ast.ProtocolStatement):
809
- debug_log(" ProtocolStatement node", f"protocol {node.name}")
810
- return self.eval_protocol_statement(node, env, stack_trace)
811
-
812
- elif isinstance(node, zexus_ast.PersistentStatement):
813
- debug_log(" PersistentStatement node", f"persistent {node.name}")
814
- return self.eval_persistent_statement(node, env, stack_trace)
815
-
816
- elif isinstance(node, zexus_ast.EmitStatement):
817
- debug_log(" EmitStatement node", f"emit {node.event_name}")
818
- return self.eval_emit_statement(node, env, stack_trace)
819
-
820
- elif isinstance(node, zexus_ast.ModifierDeclaration):
821
- debug_log(" ModifierDeclaration node", f"modifier {node.name}")
822
- return self.eval_modifier_declaration(node, env, stack_trace)
823
-
824
- # === EXPRESSIONS ===
825
- elif isinstance(node, zexus_ast.Identifier):
826
- debug_log(" Identifier node", node.value)
827
- return self.eval_identifier(node, env)
828
-
829
- elif isinstance(node, zexus_ast.IntegerLiteral):
830
- debug_log(" IntegerLiteral node", node.value)
831
- return Integer(node.value)
832
-
833
- elif node_type == zexus_ast.FloatLiteral or isinstance(node, zexus_ast.FloatLiteral):
834
- debug_log(" FloatLiteral node", getattr(node, 'value', 'unknown'))
835
- try:
836
- val = getattr(node, 'value', None)
837
- return Float(val)
838
- except Exception:
839
- return EvaluationError(f"Invalid float literal: {getattr(node, 'value', None)}")
840
-
841
- elif isinstance(node, zexus_ast.StringLiteral):
842
- debug_log(" StringLiteral node", node.value)
843
- # Process escape sequences in the string
844
- value = node.value
845
- value = value.replace('\\n', '\n')
846
- value = value.replace('\\t', '\t')
847
- value = value.replace('\\r', '\r')
848
- value = value.replace('\\\\', '\\')
849
- value = value.replace('\\"', '"')
850
- value = value.replace("\\'", "'")
851
- # String literals are trusted (not from external input)
852
- return String(value, is_trusted=True)
853
-
854
- elif isinstance(node, zexus_ast.StringInterpolationExpression):
855
- return self._handle_string_interpolation(node, env, stack_trace)
856
-
857
- elif isinstance(node, zexus_ast.Boolean):
858
- debug_log(" Boolean node", f"value: {node.value}")
859
- return BooleanObj(node.value)
860
-
861
- elif isinstance(node, zexus_ast.NullLiteral):
862
- debug_log(" NullLiteral node")
863
- return NULL
864
-
865
- elif isinstance(node, zexus_ast.ThisExpression):
866
- debug_log(" ThisExpression node")
867
- return self.eval_this_expression(node, env, stack_trace)
868
-
869
- elif isinstance(node, zexus_ast.InfixExpression):
870
- debug_log(" InfixExpression node", f"{node.left} {node.operator} {node.right}")
871
- return self.eval_infix_expression(node, env, stack_trace)
872
-
873
- elif isinstance(node, zexus_ast.PrefixExpression):
874
- debug_log(" PrefixExpression node", f"{node.operator} {node.right}")
875
- return self.eval_prefix_expression(node, env, stack_trace)
876
-
877
- elif isinstance(node, zexus_ast.IfExpression):
878
- debug_log(" IfExpression node")
879
- return self.eval_if_expression(node, env, stack_trace)
880
-
881
- elif isinstance(node, zexus_ast.TernaryExpression):
882
- debug_log(" TernaryExpression node")
883
- return self.eval_ternary_expression(node, env, stack_trace)
884
-
885
- elif isinstance(node, zexus_ast.NullishExpression):
886
- debug_log(" NullishExpression node")
887
- return self.eval_nullish_expression(node, env, stack_trace)
888
-
889
- elif isinstance(node, zexus_ast.AwaitExpression):
890
- debug_log(" AwaitExpression node")
891
- return self.eval_await_expression(node, env, stack_trace)
892
-
893
- elif isinstance(node, zexus_ast.FindExpression):
894
- debug_log(" FindExpression node")
895
- return self.eval_find_expression(node, env, stack_trace)
896
-
897
- elif isinstance(node, zexus_ast.LoadExpression):
898
- debug_log(" LoadExpression node")
899
- return self.eval_load_expression(node, env, stack_trace)
900
-
901
- elif isinstance(node, zexus_ast.FileImportExpression):
902
- debug_log(" FileImportExpression node", "<< file import")
903
- return self.eval_file_import_expression(node, env, stack_trace)
904
-
905
- elif isinstance(node, zexus_ast.MethodCallExpression):
906
- debug_log(" MethodCallExpression node", f"{node.object}.{node.method}")
907
- return self.eval_method_call_expression(node, env, stack_trace)
908
-
909
- elif isinstance(node, zexus_ast.CallExpression):
910
- debug_log("🚀 CallExpression node", f"Calling {node.function}")
911
- return self.eval_call_expression(node, env, stack_trace)
912
-
913
- elif isinstance(node, zexus_ast.AsyncExpression):
914
- debug_log("⚡ AsyncExpression node", f"Async execution of {node.expression}")
915
- return self.eval_async_expression(node, env, stack_trace)
916
-
917
- elif isinstance(node, zexus_ast.MatchExpression):
918
- debug_log("🎯 MatchExpression node", "Pattern matching")
919
- return self.eval_match_expression(node, env, stack_trace)
920
-
921
- elif isinstance(node, zexus_ast.ListLiteral):
922
- debug_log(" ListLiteral node", f"{len(node.elements)} elements")
923
- elems = self.eval_expressions(node.elements, env)
924
- if is_error(elems):
925
- return elems
926
- return List(elems)
927
-
928
- elif isinstance(node, zexus_ast.MapLiteral):
929
- debug_log(" MapLiteral node", f"{len(node.pairs)} pairs")
930
- pairs = {}
931
- for k, v in node.pairs:
932
- # If the key is a bare identifier (e.g. io.read) treat it as a string key
933
- if isinstance(k, zexus_ast.Identifier):
934
- key_str = k.value
935
- else:
936
- key = self.eval_node(k, env, stack_trace)
937
- if is_error(key):
938
- return key
939
- key_str = key.inspect()
940
-
941
- val = self.eval_node(v, env, stack_trace)
942
- if is_error(val):
943
- return val
944
- pairs[key_str] = val
945
- return Map(pairs)
946
-
947
- elif isinstance(node, zexus_ast.ActionLiteral):
948
- debug_log(" ActionLiteral node")
949
- return Action(node.parameters, node.body, env)
950
-
951
- elif isinstance(node, zexus_ast.LambdaExpression):
952
- debug_log(" LambdaExpression node")
953
- return LambdaFunction(node.parameters, node.body, env)
954
-
955
- elif isinstance(node, zexus_ast.EmbeddedLiteral):
956
- debug_log(" EmbeddedLiteral node")
957
- return EmbeddedCode("embedded_block", node.language, node.code)
958
-
959
- elif isinstance(node, zexus_ast.PropertyAccessExpression):
960
- debug_log(" PropertyAccessExpression node", f"{node.object}.{node.property}")
961
- obj = self.eval_node(node.object, env, stack_trace)
962
- if is_error(obj):
963
- return obj
964
-
965
- # Unwrap ReturnValue if present
966
- if isinstance(obj, ReturnValue):
967
- obj = obj.value
968
-
969
- # Determine property name based on whether it's computed (obj[expr]) or literal (obj.prop)
970
- if hasattr(node, 'computed') and node.computed:
971
- # Computed property (obj[expr]) - always evaluate the expression
972
- prop_result = self.eval_node(node.property, env, stack_trace)
973
- if is_error(prop_result):
974
- return prop_result
975
- property_name = prop_result.value if hasattr(prop_result, 'value') else str(prop_result)
976
- elif isinstance(node.property, zexus_ast.Identifier):
977
- # Literal property (obj.prop) - use the identifier name directly
978
- property_name = node.property.value
979
- elif isinstance(node.property, zexus_ast.IntegerLiteral):
980
- # Direct integer index like arr[0] (for backwards compatibility)
981
- property_name = node.property.value
982
- else:
983
- # Fallback: evaluate the property expression
984
- prop_result = self.eval_node(node.property, env, stack_trace)
985
- if is_error(prop_result):
986
- return prop_result
987
- property_name = prop_result.value if hasattr(prop_result, 'value') else str(prop_result)
988
-
989
- if isinstance(obj, EmbeddedCode):
990
- if property_name == "code":
991
- return String(obj.code)
992
- elif property_name == "language":
993
- return String(obj.language)
994
-
995
- # Enforcement: consult security restrictions before returning
996
- try:
997
- from ..security import get_security_context
998
- ctx = get_security_context()
999
- target = f"{getattr(node.object, 'value', str(node.object))}.{property_name}"
1000
- restriction = ctx.get_restriction(target)
1001
- except Exception:
1002
- restriction = None
1003
-
1004
- # Handle Builtin objects (for static methods like TypeName.default())
1005
- if isinstance(obj, Builtin):
1006
- if hasattr(obj, 'static_methods') and property_name in obj.static_methods:
1007
- return obj.static_methods[property_name]
1008
- return NULL
1009
-
1010
- # Handle Module objects
1011
- try:
1012
- from ..complexity_system import Module as _Module
1013
- except ImportError:
1014
- _Module = None
1015
- if _Module is not None and isinstance(obj, _Module):
1016
- val = obj.get(property_name)
1017
- if val is None:
1018
- return NULL
1019
- if restriction:
1020
- rule = restriction.get('restriction')
1021
- if rule == 'redact':
1022
- return String('***REDACTED***')
1023
- if rule == 'admin-only':
1024
- is_admin = bool(env.get('__is_admin__')) if env and hasattr(env, 'get') else False
1025
- if not is_admin:
1026
- return EvaluationError('Access denied: admin required')
1027
- return val
1028
-
1029
- # Handle Map objects
1030
- if isinstance(obj, Map):
1031
- # Try string key first
1032
- val = obj.pairs.get(property_name, NULL)
1033
- if val == NULL:
1034
- # Try with String object key (for dataclasses and other String-keyed maps)
1035
- str_key = String(property_name)
1036
- val = obj.pairs.get(str_key, NULL)
1037
-
1038
- # Check if this is a computed property
1039
- computed_props = obj.pairs.get(String("__computed__"))
1040
- if computed_props and isinstance(computed_props, dict) and property_name in computed_props:
1041
- # Evaluate computed property
1042
- computed_expr = computed_props[property_name]
1043
-
1044
- # Create environment with all field values in scope
1045
- from ..environment import Environment
1046
- compute_env = Environment(outer=env)
1047
- compute_env.set('this', obj)
1048
-
1049
- # Add all regular fields to environment
1050
- for key, value in obj.pairs.items():
1051
- if isinstance(key, String) and not key.value.startswith('__'):
1052
- compute_env.set(key.value, value)
1053
-
1054
- # Evaluate the computed expression
1055
- result = self.eval_node(computed_expr, compute_env, stack_trace)
1056
- return result if not is_error(result) else NULL
1057
-
1058
- # apply restriction if present
1059
- if restriction:
1060
- rule = restriction.get('restriction')
1061
- if rule == 'redact':
1062
- return String('***REDACTED***')
1063
- if rule == 'admin-only':
1064
- # check environment flag for admin
1065
- is_admin = bool(env.get('__is_admin__')) if env and hasattr(env, 'get') else False
1066
- if not is_admin:
1067
- return EvaluationError('Access denied: admin required')
1068
- return val
1069
-
1070
- # Check for objects with get_attr method (e.g., ContractReference)
1071
- if hasattr(obj, 'get_attr') and callable(obj.get_attr):
1072
- val = obj.get_attr(property_name)
1073
- if is_error(val):
1074
- return val
1075
- if restriction:
1076
- rule = restriction.get('restriction')
1077
- if rule == 'redact':
1078
- return String('***REDACTED***')
1079
- if rule == 'admin-only':
1080
- is_admin = bool(env.get('__is_admin__')) if env and hasattr(env, 'get') else False
1081
- if not is_admin:
1082
- return EvaluationError('Access denied: admin required')
1083
- return val
1084
-
1085
- if hasattr(obj, 'get') and callable(obj.get):
1086
- val = obj.get(property_name)
1087
- if restriction:
1088
- rule = restriction.get('restriction')
1089
- if rule == 'redact':
1090
- return String('***REDACTED***')
1091
- if rule == 'admin-only':
1092
- is_admin = bool(env.get('__is_admin__')) if env and hasattr(env, 'get') else False
1093
- if not is_admin:
1094
- return EvaluationError('Access denied: admin required')
1095
- return val
1096
-
1097
- elif isinstance(node, zexus_ast.SliceExpression):
1098
- debug_log(" SliceExpression node", f"{node.object}[{node.start}:{node.end}]")
1099
- obj = self.eval_node(node.object, env, stack_trace)
1100
- if is_error(obj):
1101
- return obj
1102
-
1103
- start_val = None
1104
- end_val = None
1105
- if node.start is not None:
1106
- start_val = self.eval_node(node.start, env, stack_trace)
1107
- if is_error(start_val):
1108
- return start_val
1109
- start_val = start_val.value if hasattr(start_val, 'value') else start_val
1110
- if node.end is not None:
1111
- end_val = self.eval_node(node.end, env, stack_trace)
1112
- if is_error(end_val):
1113
- return end_val
1114
- end_val = end_val.value if hasattr(end_val, 'value') else end_val
1115
-
1116
- if isinstance(obj, List):
1117
- return List(obj.elements[start_val:end_val])
1118
- if isinstance(obj, String):
1119
- return String(obj.value[start_val:end_val])
1120
- if isinstance(obj, list):
1121
- return obj[start_val:end_val]
1122
- if isinstance(obj, str):
1123
- return obj[start_val:end_val]
1124
- return NULL
1125
-
1126
- return NULL
1127
-
1128
- # === BLOCKCHAIN EXPRESSIONS ===
1129
- elif isinstance(node, zexus_ast.TXExpression):
1130
- debug_log(" TXExpression node", f"tx.{node.property_name}")
1131
- return self.eval_tx_expression(node, env, stack_trace)
1132
-
1133
- elif isinstance(node, zexus_ast.HashExpression):
1134
- debug_log(" HashExpression node", "hash()")
1135
- return self.eval_hash_expression(node, env, stack_trace)
1136
-
1137
- elif isinstance(node, zexus_ast.SignatureExpression):
1138
- debug_log(" SignatureExpression node", "signature()")
1139
- return self.eval_signature_expression(node, env, stack_trace)
1140
-
1141
- elif isinstance(node, zexus_ast.VerifySignatureExpression):
1142
- debug_log(" VerifySignatureExpression node", "verify_sig()")
1143
- return self.eval_verify_signature_expression(node, env, stack_trace)
1144
-
1145
- elif isinstance(node, zexus_ast.GasExpression):
1146
- debug_log(" GasExpression node", f"gas.{node.property_name}")
1147
- return self.eval_gas_expression(node, env, stack_trace)
1148
-
1149
- # Fallback
1150
- debug_log(" Unknown node type", node_type)
1151
- return EvaluationError(f"Unknown node type: {node_type}", stack_trace=stack_trace)
1152
-
467
+ return handler(node, env, stack_trace)
468
+ except RecursionError:
469
+ return EvaluationError(
470
+ "Maximum recursion depth exceeded while evaluating AST (Python recursion limit). "
471
+ "Consider simplifying deeply nested expressions or enabling the VM.",
472
+ stack_trace=stack_trace,
473
+ )
1153
474
  except Exception as e:
1154
- # Enhanced error with stack trace
1155
475
  error_msg = f"Internal error: {str(e)}"
1156
476
  debug_log(" Exception in eval_node", error_msg)
1157
477
  traceback.print_exc()
1158
- return EvaluationError(error_msg, stack_trace=stack_trace[-5:]) # Last 5 frames
478
+ trimmed_trace = stack_trace[-5:] if isinstance(stack_trace, list) else stack_trace
479
+ return EvaluationError(error_msg, stack_trace=trimmed_trace)
1159
480
 
1160
481
  # Additional VM-related methods
1161
482
  def _initialize_vm(self):
@@ -1465,11 +786,27 @@ class Evaluator(ExpressionEvaluatorMixin, StatementEvaluatorMixin, FunctionEvalu
1465
786
  "__vm_pattern_statement__": Builtin(_vm_pattern_statement, "__vm_pattern_statement__"),
1466
787
  }
1467
788
 
1468
- def _env_to_dict(self, env):
1469
- """Convert Environment object to dict for VM"""
789
+ def _env_to_dict(self, env, *, _depth: int = 0, _max_depth: int = 64, _seen=None):
790
+ """Convert Environment object to dict for VM.
791
+
792
+ LI7: Guard against cycles and unbounded `outer` chains.
793
+ """
1470
794
  result = {}
1471
795
  try:
1472
796
  from ..object import String, Integer, Float, Boolean, List, Map, NULL
797
+
798
+ if env is None:
799
+ return result
800
+
801
+ if _seen is None:
802
+ _seen = set()
803
+ env_id = id(env)
804
+ if env_id in _seen:
805
+ return result
806
+ _seen.add(env_id)
807
+
808
+ if _depth >= _max_depth:
809
+ return result
1473
810
 
1474
811
  def to_python(obj):
1475
812
  """Convert evaluator object to Python primitive"""
@@ -1492,7 +829,12 @@ class Evaluator(ExpressionEvaluatorMixin, StatementEvaluatorMixin, FunctionEvalu
1492
829
 
1493
830
  # Get outer environment if available
1494
831
  if hasattr(env, 'outer') and env.outer:
1495
- outer_dict = self._env_to_dict(env.outer)
832
+ outer_dict = self._env_to_dict(
833
+ env.outer,
834
+ _depth=_depth + 1,
835
+ _max_depth=_max_depth,
836
+ _seen=_seen,
837
+ )
1496
838
  # Don't overwrite inner scope
1497
839
  for k, v in outer_dict.items():
1498
840
  if k not in result: