zexus 1.6.8 → 1.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -5
- package/package.json +1 -1
- package/src/__init__.py +7 -0
- package/src/zexus/__init__.py +1 -1
- package/src/zexus/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/capability_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/debug_sanitizer.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/environment.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/error_reporter.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/input_validation.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/lexer.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/module_cache.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/module_manager.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/object.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/security.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/security_enforcement.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/syntax_validator.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/zexus_ast.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/zexus_token.cpython-312.pyc +0 -0
- package/src/zexus/access_control_system/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/access_control_system/__pycache__/access_control.cpython-312.pyc +0 -0
- package/src/zexus/advanced_types.py +17 -2
- package/src/zexus/blockchain/__init__.py +411 -0
- package/src/zexus/blockchain/accelerator.py +1160 -0
- package/src/zexus/blockchain/chain.py +660 -0
- package/src/zexus/blockchain/consensus.py +821 -0
- package/src/zexus/blockchain/contract_vm.py +1019 -0
- package/src/zexus/blockchain/crypto.py +79 -14
- package/src/zexus/blockchain/events.py +526 -0
- package/src/zexus/blockchain/loadtest.py +721 -0
- package/src/zexus/blockchain/monitoring.py +350 -0
- package/src/zexus/blockchain/mpt.py +716 -0
- package/src/zexus/blockchain/multichain.py +951 -0
- package/src/zexus/blockchain/multiprocess_executor.py +338 -0
- package/src/zexus/blockchain/network.py +886 -0
- package/src/zexus/blockchain/node.py +666 -0
- package/src/zexus/blockchain/rpc.py +1203 -0
- package/src/zexus/blockchain/rust_bridge.py +421 -0
- package/src/zexus/blockchain/storage.py +423 -0
- package/src/zexus/blockchain/tokens.py +750 -0
- package/src/zexus/blockchain/upgradeable.py +1004 -0
- package/src/zexus/blockchain/verification.py +1602 -0
- package/src/zexus/blockchain/wallet.py +621 -0
- package/src/zexus/capability_system.py +184 -9
- package/src/zexus/cli/__pycache__/main.cpython-312.pyc +0 -0
- package/src/zexus/cli/main.py +383 -34
- package/src/zexus/cli/zpm.py +1 -1
- package/src/zexus/compiler/__pycache__/bytecode.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/lexer.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/parser.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/semantic.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/zexus_ast.cpython-312.pyc +0 -0
- package/src/zexus/compiler/bytecode.py +124 -7
- package/src/zexus/compiler/compat_runtime.py +6 -2
- package/src/zexus/compiler/lexer.py +16 -5
- package/src/zexus/compiler/parser.py +108 -7
- package/src/zexus/compiler/semantic.py +18 -19
- package/src/zexus/compiler/zexus_ast.py +26 -1
- package/src/zexus/concurrency_system.py +79 -0
- package/src/zexus/config.py +54 -0
- package/src/zexus/crypto_bridge.py +244 -8
- package/src/zexus/dap/__init__.py +10 -0
- package/src/zexus/dap/__main__.py +4 -0
- package/src/zexus/dap/dap_server.py +391 -0
- package/src/zexus/dap/debug_engine.py +298 -0
- package/src/zexus/environment.py +112 -9
- package/src/zexus/evaluator/__pycache__/bytecode_compiler.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/core.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/expressions.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/functions.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/resource_limiter.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/statements.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/unified_execution.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/utils.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/bytecode_compiler.py +457 -37
- package/src/zexus/evaluator/core.py +644 -50
- package/src/zexus/evaluator/expressions.py +358 -62
- package/src/zexus/evaluator/functions.py +458 -20
- package/src/zexus/evaluator/resource_limiter.py +4 -4
- package/src/zexus/evaluator/statements.py +774 -122
- package/src/zexus/evaluator/unified_execution.py +573 -72
- package/src/zexus/evaluator/utils.py +14 -2
- package/src/zexus/evaluator_original.py +1 -1
- package/src/zexus/event_loop.py +186 -0
- package/src/zexus/lexer.py +742 -458
- package/src/zexus/lsp/__init__.py +1 -1
- package/src/zexus/lsp/definition_provider.py +163 -9
- package/src/zexus/lsp/server.py +22 -8
- package/src/zexus/lsp/symbol_provider.py +182 -9
- package/src/zexus/module_cache.py +239 -9
- package/src/zexus/module_manager.py +129 -1
- package/src/zexus/object.py +76 -6
- package/src/zexus/parser/__pycache__/parser.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/strategy_context.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/strategy_structural.cpython-312.pyc +0 -0
- package/src/zexus/parser/parser.py +1349 -408
- package/src/zexus/parser/strategy_context.py +755 -58
- package/src/zexus/parser/strategy_structural.py +121 -21
- package/src/zexus/persistence.py +15 -1
- package/src/zexus/renderer/__init__.py +61 -0
- package/src/zexus/renderer/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/renderer/__pycache__/backend.cpython-312.pyc +0 -0
- package/src/zexus/renderer/__pycache__/canvas.cpython-312.pyc +0 -0
- package/src/zexus/renderer/__pycache__/color_system.cpython-312.pyc +0 -0
- package/src/zexus/renderer/__pycache__/layout.cpython-312.pyc +0 -0
- package/src/zexus/renderer/__pycache__/main_renderer.cpython-312.pyc +0 -0
- package/src/zexus/renderer/__pycache__/painter.cpython-312.pyc +0 -0
- package/src/zexus/renderer/backend.py +261 -0
- package/src/zexus/renderer/canvas.py +78 -0
- package/src/zexus/renderer/color_system.py +201 -0
- package/src/zexus/renderer/graphics.py +31 -0
- package/src/zexus/renderer/layout.py +222 -0
- package/src/zexus/renderer/main_renderer.py +66 -0
- package/src/zexus/renderer/painter.py +30 -0
- package/src/zexus/renderer/tk_backend.py +208 -0
- package/src/zexus/renderer/web_backend.py +260 -0
- package/src/zexus/runtime/__init__.py +10 -2
- package/src/zexus/runtime/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/runtime/__pycache__/async_runtime.cpython-312.pyc +0 -0
- package/src/zexus/runtime/__pycache__/load_manager.cpython-312.pyc +0 -0
- package/src/zexus/runtime/file_flags.py +137 -0
- package/src/zexus/runtime/load_manager.py +368 -0
- package/src/zexus/safety/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/safety/__pycache__/memory_safety.cpython-312.pyc +0 -0
- package/src/zexus/security.py +424 -34
- package/src/zexus/stdlib/fs.py +23 -18
- package/src/zexus/stdlib/http.py +289 -186
- package/src/zexus/stdlib/sockets.py +207 -163
- package/src/zexus/stdlib/websockets.py +282 -0
- package/src/zexus/stdlib_integration.py +369 -2
- package/src/zexus/strategy_recovery.py +6 -3
- package/src/zexus/type_checker.py +423 -0
- package/src/zexus/virtual_filesystem.py +189 -2
- package/src/zexus/vm/__init__.py +113 -3
- package/src/zexus/vm/__pycache__/async_optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/bytecode.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/bytecode_converter.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/cache.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/compiler.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/gas_metering.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/jit.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/parallel_vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/async_optimizer.py +80 -6
- package/src/zexus/vm/binary_bytecode.py +659 -0
- package/src/zexus/vm/bytecode.py +59 -11
- package/src/zexus/vm/bytecode_converter.py +26 -12
- package/src/zexus/vm/cabi.c +1985 -0
- package/src/zexus/vm/cabi.cpython-312-x86_64-linux-gnu.so +0 -0
- package/src/zexus/vm/cabi.h +127 -0
- package/src/zexus/vm/cache.py +561 -17
- package/src/zexus/vm/compiler.py +818 -51
- package/src/zexus/vm/fastops.c +15743 -0
- package/src/zexus/vm/fastops.cpython-312-x86_64-linux-gnu.so +0 -0
- package/src/zexus/vm/fastops.pyx +288 -0
- package/src/zexus/vm/gas_metering.py +50 -9
- package/src/zexus/vm/jit.py +364 -20
- package/src/zexus/vm/native_jit_backend.py +1816 -0
- package/src/zexus/vm/native_runtime.cpp +1388 -0
- package/src/zexus/vm/native_runtime.cpython-312-x86_64-linux-gnu.so +0 -0
- package/src/zexus/vm/optimizer.py +161 -11
- package/src/zexus/vm/parallel_vm.py +140 -45
- package/src/zexus/vm/peephole_optimizer.py +82 -4
- package/src/zexus/vm/profiler.py +38 -18
- package/src/zexus/vm/register_allocator.py +16 -5
- package/src/zexus/vm/register_vm.py +8 -5
- package/src/zexus/vm/vm.py +3581 -531
- package/src/zexus/vm/wasm_compiler.py +658 -0
- package/src/zexus/zexus_ast.py +137 -11
- package/src/zexus/zexus_token.py +16 -5
- package/src/zexus/zpm/installer.py +55 -15
- package/src/zexus/zpm/package_manager.py +1 -1
- package/src/zexus/zpm/registry.py +257 -28
- package/src/zexus.egg-info/PKG-INFO +16 -6
- package/src/zexus.egg-info/SOURCES.txt +129 -17
- package/src/zexus.egg-info/entry_points.txt +1 -0
- package/src/zexus.egg-info/requires.txt +4 -0
|
Binary file
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
# cython: language_level=3
|
|
2
|
+
# cython: boundscheck=False
|
|
3
|
+
# cython: wraparound=False
|
|
4
|
+
# cython: cdivision=True
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
Cython-accelerated hot-path VM execution.
|
|
8
|
+
|
|
9
|
+
Implements a fast dispatch loop for common bytecode ops used in benchmarks.
|
|
10
|
+
Falls back to Python execution for unsupported ops by raising NotImplementedError.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from zexus.object import List as ZList
|
|
14
|
+
from zexus.object import Map as ZMap
|
|
15
|
+
from zexus.object import String as ZString
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _resolve(name, dict env, dict closure_cells):
|
|
19
|
+
if name in env:
|
|
20
|
+
val = env[name]
|
|
21
|
+
if hasattr(val, "value"):
|
|
22
|
+
return val.value
|
|
23
|
+
return val
|
|
24
|
+
if closure_cells is not None and name in closure_cells:
|
|
25
|
+
cell = closure_cells[name]
|
|
26
|
+
if hasattr(cell, "value"):
|
|
27
|
+
return cell.value
|
|
28
|
+
return cell
|
|
29
|
+
return None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _store(name, value, dict env, dict closure_cells):
|
|
33
|
+
if name in env:
|
|
34
|
+
current = env[name]
|
|
35
|
+
if hasattr(current, "value"):
|
|
36
|
+
current.value = value
|
|
37
|
+
return
|
|
38
|
+
env[name] = value
|
|
39
|
+
return
|
|
40
|
+
if closure_cells is not None and name in closure_cells:
|
|
41
|
+
cell = closure_cells[name]
|
|
42
|
+
if hasattr(cell, "value"):
|
|
43
|
+
cell.value = value
|
|
44
|
+
return
|
|
45
|
+
closure_cells[name] = value
|
|
46
|
+
return
|
|
47
|
+
env[name] = value
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _call_method(target, method_name, args):
|
|
51
|
+
if target is None:
|
|
52
|
+
return None
|
|
53
|
+
try:
|
|
54
|
+
if method_name == "set":
|
|
55
|
+
if isinstance(target, ZMap) and len(args) >= 2:
|
|
56
|
+
key = args[0]
|
|
57
|
+
if isinstance(key, str):
|
|
58
|
+
key = ZString(key)
|
|
59
|
+
return target.set(key, args[1])
|
|
60
|
+
if isinstance(target, ZList) and len(args) >= 2:
|
|
61
|
+
return target.set(args[0], args[1])
|
|
62
|
+
if isinstance(target, (dict, list)) and len(args) >= 2:
|
|
63
|
+
target[args[0]] = args[1]
|
|
64
|
+
return args[1]
|
|
65
|
+
if hasattr(target, "call_method"):
|
|
66
|
+
return target.call_method(method_name, args)
|
|
67
|
+
attr = getattr(target, method_name, None)
|
|
68
|
+
if callable(attr):
|
|
69
|
+
return attr(*args)
|
|
70
|
+
if isinstance(target, dict) and method_name in target:
|
|
71
|
+
candidate = target[method_name]
|
|
72
|
+
return candidate(*args) if callable(candidate) else candidate
|
|
73
|
+
return attr
|
|
74
|
+
except Exception:
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _call_top(fn_obj, args):
|
|
79
|
+
if fn_obj is None:
|
|
80
|
+
return None
|
|
81
|
+
if isinstance(fn_obj, dict) and "bytecode" in fn_obj:
|
|
82
|
+
raise NotImplementedError("CALL_TOP requires VM execution")
|
|
83
|
+
try:
|
|
84
|
+
if callable(fn_obj):
|
|
85
|
+
return fn_obj(*args)
|
|
86
|
+
return None
|
|
87
|
+
except Exception:
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def execute(list instrs, list consts, dict env, dict builtins, dict closure_cells=None):
|
|
92
|
+
cdef Py_ssize_t ip = 0
|
|
93
|
+
cdef Py_ssize_t instr_count = len(instrs)
|
|
94
|
+
cdef list stack = []
|
|
95
|
+
cdef object op_name
|
|
96
|
+
cdef object operand
|
|
97
|
+
|
|
98
|
+
while ip < instr_count:
|
|
99
|
+
op_name, operand = instrs[ip]
|
|
100
|
+
ip += 1
|
|
101
|
+
|
|
102
|
+
if op_name == "LOAD_CONST":
|
|
103
|
+
if isinstance(operand, int) and 0 <= operand < len(consts):
|
|
104
|
+
stack.append(consts[operand])
|
|
105
|
+
else:
|
|
106
|
+
stack.append(operand)
|
|
107
|
+
elif op_name == "LOAD_NAME":
|
|
108
|
+
name = consts[operand] if isinstance(operand, int) and 0 <= operand < len(consts) else operand
|
|
109
|
+
stack.append(_resolve(name, env, closure_cells))
|
|
110
|
+
elif op_name == "STORE_NAME":
|
|
111
|
+
name = consts[operand] if isinstance(operand, int) and 0 <= operand < len(consts) else operand
|
|
112
|
+
val = stack.pop() if stack else None
|
|
113
|
+
_store(name, val, env, closure_cells)
|
|
114
|
+
elif op_name == "POP":
|
|
115
|
+
if stack:
|
|
116
|
+
stack.pop()
|
|
117
|
+
elif op_name == "DUP":
|
|
118
|
+
if stack:
|
|
119
|
+
stack.append(stack[-1])
|
|
120
|
+
elif op_name == "ADD":
|
|
121
|
+
b = stack.pop() if stack else 0
|
|
122
|
+
a = stack.pop() if stack else 0
|
|
123
|
+
if hasattr(a, "value"):
|
|
124
|
+
a = a.value
|
|
125
|
+
if hasattr(b, "value"):
|
|
126
|
+
b = b.value
|
|
127
|
+
stack.append(a + b)
|
|
128
|
+
elif op_name == "SUB":
|
|
129
|
+
b = stack.pop() if stack else 0
|
|
130
|
+
a = stack.pop() if stack else 0
|
|
131
|
+
if hasattr(a, "value"):
|
|
132
|
+
a = a.value
|
|
133
|
+
if hasattr(b, "value"):
|
|
134
|
+
b = b.value
|
|
135
|
+
stack.append(a - b)
|
|
136
|
+
elif op_name == "MUL":
|
|
137
|
+
b = stack.pop() if stack else 0
|
|
138
|
+
a = stack.pop() if stack else 0
|
|
139
|
+
if hasattr(a, "value"):
|
|
140
|
+
a = a.value
|
|
141
|
+
if hasattr(b, "value"):
|
|
142
|
+
b = b.value
|
|
143
|
+
stack.append(a * b)
|
|
144
|
+
elif op_name == "DIV":
|
|
145
|
+
b = stack.pop() if stack else 1
|
|
146
|
+
a = stack.pop() if stack else 0
|
|
147
|
+
if hasattr(a, "value"):
|
|
148
|
+
a = a.value
|
|
149
|
+
if hasattr(b, "value"):
|
|
150
|
+
b = b.value
|
|
151
|
+
stack.append(a / b if b != 0 else 0)
|
|
152
|
+
elif op_name == "MOD":
|
|
153
|
+
b = stack.pop() if stack else 1
|
|
154
|
+
a = stack.pop() if stack else 0
|
|
155
|
+
stack.append(a % b if b != 0 else 0)
|
|
156
|
+
elif op_name == "EQ":
|
|
157
|
+
b = stack.pop() if stack else None
|
|
158
|
+
a = stack.pop() if stack else None
|
|
159
|
+
stack.append(a == b)
|
|
160
|
+
elif op_name == "NEQ":
|
|
161
|
+
b = stack.pop() if stack else None
|
|
162
|
+
a = stack.pop() if stack else None
|
|
163
|
+
stack.append(a != b)
|
|
164
|
+
elif op_name == "LT":
|
|
165
|
+
b = stack.pop() if stack else 0
|
|
166
|
+
a = stack.pop() if stack else 0
|
|
167
|
+
stack.append(a < b)
|
|
168
|
+
elif op_name == "GT":
|
|
169
|
+
b = stack.pop() if stack else 0
|
|
170
|
+
a = stack.pop() if stack else 0
|
|
171
|
+
stack.append(a > b)
|
|
172
|
+
elif op_name == "LTE":
|
|
173
|
+
b = stack.pop() if stack else 0
|
|
174
|
+
a = stack.pop() if stack else 0
|
|
175
|
+
stack.append(a <= b)
|
|
176
|
+
elif op_name == "GTE":
|
|
177
|
+
b = stack.pop() if stack else 0
|
|
178
|
+
a = stack.pop() if stack else 0
|
|
179
|
+
stack.append(a >= b)
|
|
180
|
+
elif op_name == "NOT":
|
|
181
|
+
a = stack.pop() if stack else False
|
|
182
|
+
stack.append(not a)
|
|
183
|
+
elif op_name == "NEG":
|
|
184
|
+
a = stack.pop() if stack else 0
|
|
185
|
+
stack.append(-a)
|
|
186
|
+
elif op_name == "JUMP":
|
|
187
|
+
ip = operand
|
|
188
|
+
elif op_name == "JUMP_IF_FALSE":
|
|
189
|
+
cond = stack.pop() if stack else None
|
|
190
|
+
if not cond:
|
|
191
|
+
ip = operand
|
|
192
|
+
elif op_name == "RETURN":
|
|
193
|
+
return stack.pop() if stack else None
|
|
194
|
+
elif op_name == "BUILD_LIST":
|
|
195
|
+
count = operand if operand is not None else 0
|
|
196
|
+
elements = [stack.pop() for _ in range(count)][::-1]
|
|
197
|
+
stack.append(elements)
|
|
198
|
+
elif op_name == "BUILD_MAP":
|
|
199
|
+
count = operand if operand is not None else 0
|
|
200
|
+
result = {}
|
|
201
|
+
for _ in range(count):
|
|
202
|
+
val = stack.pop(); key = stack.pop()
|
|
203
|
+
result[key] = val
|
|
204
|
+
stack.append(result)
|
|
205
|
+
elif op_name == "BUILD_SET":
|
|
206
|
+
count = operand if operand is not None else 0
|
|
207
|
+
elements = [stack.pop() for _ in range(count)][::-1]
|
|
208
|
+
stack.append(set(elements))
|
|
209
|
+
elif op_name == "INDEX":
|
|
210
|
+
idx = stack.pop()
|
|
211
|
+
obj = stack.pop()
|
|
212
|
+
try:
|
|
213
|
+
if isinstance(obj, ZList):
|
|
214
|
+
stack.append(obj.get(idx))
|
|
215
|
+
elif isinstance(obj, ZMap):
|
|
216
|
+
stack.append(obj.get(idx))
|
|
217
|
+
else:
|
|
218
|
+
stack.append(obj[idx] if obj is not None else None)
|
|
219
|
+
except Exception:
|
|
220
|
+
stack.append(None)
|
|
221
|
+
elif op_name == "SLICE":
|
|
222
|
+
end = stack.pop() if stack else None
|
|
223
|
+
start = stack.pop() if stack else None
|
|
224
|
+
obj = stack.pop() if stack else None
|
|
225
|
+
if hasattr(start, "value"):
|
|
226
|
+
start = start.value
|
|
227
|
+
if hasattr(end, "value"):
|
|
228
|
+
end = end.value
|
|
229
|
+
try:
|
|
230
|
+
if isinstance(obj, ZList):
|
|
231
|
+
stack.append(ZList(obj.elements[start:end]))
|
|
232
|
+
elif isinstance(obj, ZString):
|
|
233
|
+
stack.append(ZString(obj.value[start:end]))
|
|
234
|
+
else:
|
|
235
|
+
stack.append(obj[start:end] if obj is not None else None)
|
|
236
|
+
except Exception:
|
|
237
|
+
stack.append(None)
|
|
238
|
+
elif op_name == "GET_LENGTH":
|
|
239
|
+
obj = stack.pop() if stack else None
|
|
240
|
+
try:
|
|
241
|
+
if obj is None:
|
|
242
|
+
stack.append(0)
|
|
243
|
+
elif isinstance(obj, ZList):
|
|
244
|
+
stack.append(len(obj.elements))
|
|
245
|
+
elif isinstance(obj, ZMap):
|
|
246
|
+
stack.append(len(obj.pairs))
|
|
247
|
+
elif isinstance(obj, ZString):
|
|
248
|
+
stack.append(len(obj.value))
|
|
249
|
+
else:
|
|
250
|
+
stack.append(len(obj))
|
|
251
|
+
except Exception:
|
|
252
|
+
stack.append(0)
|
|
253
|
+
elif op_name == "CALL_NAME":
|
|
254
|
+
name_idx, arg_count = operand
|
|
255
|
+
func_name = consts[name_idx] if isinstance(name_idx, int) and 0 <= name_idx < len(consts) else name_idx
|
|
256
|
+
args = [stack.pop() for _ in range(arg_count)][::-1] if arg_count else []
|
|
257
|
+
fn = _resolve(func_name, env, closure_cells) or builtins.get(func_name)
|
|
258
|
+
if fn is None:
|
|
259
|
+
stack.append(None)
|
|
260
|
+
else:
|
|
261
|
+
stack.append(fn(*args))
|
|
262
|
+
elif op_name == "CALL_BUILTIN":
|
|
263
|
+
name_idx, arg_count = operand
|
|
264
|
+
func_name = consts[name_idx] if isinstance(name_idx, int) and 0 <= name_idx < len(consts) else name_idx
|
|
265
|
+
args = [stack.pop() for _ in range(arg_count)][::-1] if arg_count else []
|
|
266
|
+
fn = builtins.get(func_name)
|
|
267
|
+
if fn is None:
|
|
268
|
+
stack.append(None)
|
|
269
|
+
else:
|
|
270
|
+
try:
|
|
271
|
+
stack.append(fn(*args))
|
|
272
|
+
except Exception:
|
|
273
|
+
stack.append(None)
|
|
274
|
+
elif op_name == "CALL_METHOD":
|
|
275
|
+
method_idx, arg_count = operand
|
|
276
|
+
args = [stack.pop() for _ in range(arg_count)][::-1] if arg_count else []
|
|
277
|
+
target = stack.pop() if stack else None
|
|
278
|
+
method_name = consts[method_idx] if isinstance(method_idx, int) and 0 <= method_idx < len(consts) else method_idx
|
|
279
|
+
stack.append(_call_method(target, method_name, args))
|
|
280
|
+
elif op_name == "CALL_TOP":
|
|
281
|
+
arg_count = operand
|
|
282
|
+
args = [stack.pop() for _ in range(arg_count)][::-1] if arg_count else []
|
|
283
|
+
fn_obj = stack.pop() if stack else None
|
|
284
|
+
stack.append(_call_top(fn_obj, args))
|
|
285
|
+
else:
|
|
286
|
+
raise NotImplementedError(f"opcode not supported: {op_name}")
|
|
287
|
+
|
|
288
|
+
return stack.pop() if stack else None
|
|
@@ -57,6 +57,8 @@ class GasCost(IntEnum):
|
|
|
57
57
|
# Function operations
|
|
58
58
|
CALL_NAME = 10 # Base cost for function call
|
|
59
59
|
CALL_TOP = 10
|
|
60
|
+
CALL_METHOD = 10
|
|
61
|
+
CALL_BUILTIN = 8
|
|
60
62
|
STORE_FUNC = 5
|
|
61
63
|
BUILD_LAMBDA = 5
|
|
62
64
|
|
|
@@ -74,6 +76,22 @@ class GasCost(IntEnum):
|
|
|
74
76
|
TX_COMMIT = 30
|
|
75
77
|
TX_REVERT = 20
|
|
76
78
|
LEDGER_APPEND = 40
|
|
79
|
+
GAS_CHARGE = 2 # Overhead of the charge itself
|
|
80
|
+
REQUIRE = 5
|
|
81
|
+
AUDIT_LOG = 15
|
|
82
|
+
RESTRICT_ACCESS = 5
|
|
83
|
+
DEFINE_CONTRACT = 50
|
|
84
|
+
EMIT_EVENT = 10
|
|
85
|
+
|
|
86
|
+
# Error handling
|
|
87
|
+
SETUP_TRY = 3
|
|
88
|
+
POP_TRY = 2
|
|
89
|
+
THROW = 5
|
|
90
|
+
ENABLE_ERROR_MODE = 2
|
|
91
|
+
|
|
92
|
+
# Parallel operations
|
|
93
|
+
PARALLEL_START = 15
|
|
94
|
+
PARALLEL_END = 10
|
|
77
95
|
|
|
78
96
|
# I/O operations
|
|
79
97
|
PRINT = 10
|
|
@@ -90,16 +108,19 @@ class GasMetering:
|
|
|
90
108
|
gas_limit: Maximum gas allowed (None = unlimited)
|
|
91
109
|
enable_timeout: Enable execution timeout mechanism
|
|
92
110
|
"""
|
|
93
|
-
self.gas_limit = gas_limit if gas_limit is not None else
|
|
111
|
+
self.gas_limit = gas_limit if gas_limit is not None else 100_000_000
|
|
94
112
|
self.gas_used = 0
|
|
95
113
|
self.enable_timeout = enable_timeout
|
|
96
114
|
self.operation_count = 0
|
|
97
|
-
self.max_operations =
|
|
115
|
+
self.max_operations = 100_000_000 # Safety limit for operations with generous default
|
|
98
116
|
|
|
99
117
|
# Track gas usage by operation type for profiling
|
|
100
118
|
self.gas_by_operation: Dict[str, int] = {}
|
|
101
119
|
self.operation_counts: Dict[str, int] = {}
|
|
102
120
|
|
|
121
|
+
# OPTIMIZATION: Cache for operation costs to avoid repeated enum lookups
|
|
122
|
+
self._cost_cache: Dict[str, int] = {}
|
|
123
|
+
|
|
103
124
|
def consume(self, operation: str, amount: Optional[int] = None, **kwargs) -> bool:
|
|
104
125
|
"""
|
|
105
126
|
Consume gas for an operation
|
|
@@ -112,6 +133,11 @@ class GasMetering:
|
|
|
112
133
|
Returns:
|
|
113
134
|
True if enough gas available, False if out of gas
|
|
114
135
|
"""
|
|
136
|
+
# OPTIMIZATION: Fast path for operation count check (most common failure)
|
|
137
|
+
self.operation_count += 1
|
|
138
|
+
if self.operation_count > self.max_operations:
|
|
139
|
+
return False
|
|
140
|
+
|
|
115
141
|
# Calculate gas cost
|
|
116
142
|
if amount is not None:
|
|
117
143
|
cost = amount
|
|
@@ -124,16 +150,23 @@ class GasMetering:
|
|
|
124
150
|
|
|
125
151
|
# Consume gas
|
|
126
152
|
self.gas_used += cost
|
|
127
|
-
self.operation_count += 1
|
|
128
153
|
|
|
129
|
-
# Track for profiling
|
|
130
|
-
self.gas_by_operation
|
|
131
|
-
|
|
154
|
+
# Track for profiling (only if needed)
|
|
155
|
+
if self.gas_by_operation is not None: # Allow disabling profiling
|
|
156
|
+
self.gas_by_operation[operation] = self.gas_by_operation.get(operation, 0) + cost
|
|
157
|
+
self.operation_counts[operation] = self.operation_counts.get(operation, 0) + 1
|
|
132
158
|
|
|
133
|
-
|
|
159
|
+
return True
|
|
160
|
+
|
|
161
|
+
def consume_light(self, amount: int = 1) -> bool:
|
|
162
|
+
"""Lightweight gas accounting: only counts operations with a fixed cost."""
|
|
163
|
+
self.operation_count += 1
|
|
134
164
|
if self.operation_count > self.max_operations:
|
|
135
165
|
return False
|
|
136
|
-
|
|
166
|
+
if self.gas_limit is not None:
|
|
167
|
+
self.gas_used += amount
|
|
168
|
+
if self.gas_used > self.gas_limit:
|
|
169
|
+
return False
|
|
137
170
|
return True
|
|
138
171
|
|
|
139
172
|
def _get_operation_cost(self, operation: str, **kwargs) -> int:
|
|
@@ -147,6 +180,10 @@ class GasMetering:
|
|
|
147
180
|
Returns:
|
|
148
181
|
Gas cost for the operation
|
|
149
182
|
"""
|
|
183
|
+
# OPTIMIZATION: Check cache first for static costs (no kwargs)
|
|
184
|
+
if not kwargs and operation in self._cost_cache:
|
|
185
|
+
return self._cost_cache[operation]
|
|
186
|
+
|
|
150
187
|
# Try to get cost from GasCost enum
|
|
151
188
|
try:
|
|
152
189
|
base_cost = GasCost[operation].value
|
|
@@ -170,11 +207,15 @@ class GasMetering:
|
|
|
170
207
|
leaf_count = kwargs.get('leaf_count', 0)
|
|
171
208
|
return base_cost + (leaf_count * 5)
|
|
172
209
|
|
|
173
|
-
elif operation in ("CALL_NAME", "CALL_TOP"):
|
|
210
|
+
elif operation in ("CALL_NAME", "CALL_TOP", "CALL_METHOD", "CALL_BUILTIN"):
|
|
174
211
|
# Cost scales with number of arguments
|
|
175
212
|
arg_count = kwargs.get('arg_count', 0)
|
|
176
213
|
return base_cost + (arg_count * 2)
|
|
177
214
|
|
|
215
|
+
# Cache static costs
|
|
216
|
+
if not kwargs:
|
|
217
|
+
self._cost_cache[operation] = base_cost
|
|
218
|
+
|
|
178
219
|
return base_cost
|
|
179
220
|
|
|
180
221
|
def check_limit(self) -> bool:
|