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.
- package/README.md +34 -6
- package/bin/zexus +12 -2
- package/bin/zpics +12 -2
- package/bin/zpm +12 -2
- package/bin/zx +12 -2
- package/bin/zx-deploy +12 -2
- package/bin/zx-dev +12 -2
- package/bin/zx-run +12 -2
- package/package.json +2 -1
- package/rust_core/Cargo.lock +603 -0
- package/rust_core/Cargo.toml +26 -0
- package/rust_core/README.md +15 -0
- package/rust_core/pyproject.toml +25 -0
- package/rust_core/src/binary_bytecode.rs +543 -0
- package/rust_core/src/contract_vm.rs +643 -0
- package/rust_core/src/executor.rs +847 -0
- package/rust_core/src/hasher.rs +90 -0
- package/rust_core/src/lib.rs +71 -0
- package/rust_core/src/merkle.rs +128 -0
- package/rust_core/src/rust_vm.rs +2313 -0
- package/rust_core/src/signature.rs +79 -0
- package/rust_core/src/state_adapter.rs +281 -0
- package/rust_core/src/validator.rs +116 -0
- package/scripts/postinstall.js +204 -21
- package/src/zexus/__init__.py +1 -1
- package/src/zexus/cli/main.py +1 -1
- package/src/zexus/cli/zpm.py +1 -1
- package/src/zexus/evaluator/bytecode_compiler.py +150 -52
- package/src/zexus/evaluator/core.py +151 -809
- package/src/zexus/evaluator/expressions.py +27 -22
- package/src/zexus/evaluator/functions.py +171 -126
- package/src/zexus/evaluator/statements.py +55 -112
- package/src/zexus/module_cache.py +20 -9
- package/src/zexus/object.py +330 -38
- package/src/zexus/parser/parser.py +103 -23
- package/src/zexus/parser/strategy_context.py +318 -6
- package/src/zexus/parser/strategy_structural.py +2 -2
- package/src/zexus/persistence.py +46 -17
- package/src/zexus/security.py +140 -234
- package/src/zexus/type_checker.py +44 -5
- package/src/zexus/vm/binary_bytecode.py +7 -3
- package/src/zexus/vm/bytecode.py +6 -0
- package/src/zexus/vm/cache.py +24 -46
- package/src/zexus/vm/compiler.py +549 -68
- package/src/zexus/vm/memory_pool.py +21 -9
- package/src/zexus/vm/vm.py +609 -95
- package/src/zexus/zpm/package_manager.py +1 -1
- package/src/zexus.egg-info/PKG-INFO +56 -12
- package/src/zexus.egg-info/SOURCES.txt +14 -0
- package/src/zexus.egg-info/entry_points.txt +5 -1
- 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
|
-
"""
|
|
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
|
|
104
|
-
|
|
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
|
-
|
|
135
|
+
return
|
|
107
136
|
|
|
108
137
|
def _initialize_dispatch_table(self):
|
|
109
|
-
"""Precompute handlers for
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
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
|
|
463
|
+
if handler is None:
|
|
464
|
+
return EvaluationError(f"Unsupported AST node type: {node_type.__name__}")
|
|
497
465
|
|
|
498
466
|
try:
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
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
|
-
|
|
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(
|
|
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:
|