zexus 1.7.1 → 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 +3 -3
- 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/cli/__pycache__/main.cpython-312.pyc +0 -0
- package/src/zexus/cli/main.py +300 -20
- 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/lexer.py +10 -5
- 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 +10 -1
- 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 +441 -37
- package/src/zexus/evaluator/core.py +560 -49
- package/src/zexus/evaluator/expressions.py +122 -49
- package/src/zexus/evaluator/functions.py +417 -16
- package/src/zexus/evaluator/statements.py +521 -118
- package/src/zexus/evaluator/unified_execution.py +573 -72
- package/src/zexus/evaluator/utils.py +14 -2
- package/src/zexus/event_loop.py +186 -0
- package/src/zexus/lexer.py +742 -486
- 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 +237 -9
- package/src/zexus/object.py +64 -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 +786 -285
- package/src/zexus/parser/strategy_context.py +407 -66
- package/src/zexus/parser/strategy_structural.py +117 -19
- package/src/zexus/persistence.py +15 -1
- package/src/zexus/renderer/__init__.py +15 -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/tk_backend.py +208 -0
- package/src/zexus/renderer/web_backend.py +260 -0
- 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/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 +14 -1
- package/src/zexus/vm/binary_bytecode.py +659 -0
- package/src/zexus/vm/bytecode.py +28 -1
- 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 +557 -17
- package/src/zexus/vm/compiler.py +703 -5
- 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 +83 -2
- 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 +118 -42
- 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 +3411 -573
- package/src/zexus/vm/wasm_compiler.py +658 -0
- package/src/zexus/zexus_ast.py +63 -11
- package/src/zexus/zexus_token.py +13 -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 +7 -4
- package/src/zexus.egg-info/SOURCES.txt +116 -9
- package/src/zexus.egg-info/entry_points.txt +1 -0
- package/src/zexus.egg-info/requires.txt +4 -0
package/src/zexus/cli/main.py
CHANGED
|
@@ -68,12 +68,13 @@ except ModuleNotFoundError: # Fallback to minimal console utilities when rich i
|
|
|
68
68
|
from ..lexer import Lexer
|
|
69
69
|
from ..parser import Parser
|
|
70
70
|
# UPDATED: Import evaluate from evaluator package
|
|
71
|
-
from ..evaluator import evaluate
|
|
71
|
+
from ..evaluator import evaluate, Evaluator
|
|
72
72
|
# UPDATED: Import Environment and String from object module
|
|
73
73
|
from ..object import Environment, String
|
|
74
74
|
from ..syntax_validator import SyntaxValidator
|
|
75
75
|
from ..hybrid_orchestrator import orchestrator
|
|
76
76
|
from ..config import config
|
|
77
|
+
from ..runtime.file_flags import parse_file_flags, apply_vm_config
|
|
77
78
|
# Import error handling
|
|
78
79
|
from ..error_reporter import get_error_reporter, ZexusError, print_error
|
|
79
80
|
# VM and Compiler for high-performance execution
|
|
@@ -92,6 +93,7 @@ def show_all_commands():
|
|
|
92
93
|
|
|
93
94
|
commands = [
|
|
94
95
|
("zx run <file>", "Execute a Zexus program"),
|
|
96
|
+
("zx -r \"<code>\"", "Run inline Zexus code (like python -c)"),
|
|
95
97
|
("zx run --zexus", "Show this command list"),
|
|
96
98
|
("zx check <file>", "Check syntax with detailed validation"),
|
|
97
99
|
("zx validate <file>", "Validate and auto-fix syntax errors"),
|
|
@@ -106,7 +108,9 @@ def show_all_commands():
|
|
|
106
108
|
("--syntax-style=<style>", "universal, tolerable, or auto (default)"),
|
|
107
109
|
("--execution-mode=<mode>", "interpreter, compiler, or auto (default)"),
|
|
108
110
|
("--advanced-parsing", "Enable multi-strategy parsing (default: on)"),
|
|
109
|
-
("--debug", "Enable debug output"),
|
|
111
|
+
("--debug <on|off|minimal|full>", "Enable/disable debug output"),
|
|
112
|
+
("--no-debug", "Disable debug output"),
|
|
113
|
+
("--no-vm", "Disable VM execution for run"),
|
|
110
114
|
("--version", "Show Zexus version"),
|
|
111
115
|
("--help", "Show detailed help"),
|
|
112
116
|
("", ""),
|
|
@@ -122,6 +126,8 @@ def show_all_commands():
|
|
|
122
126
|
("zx check --debug program.zx", "Check syntax with debug info"),
|
|
123
127
|
("zx profile myapp.zx", "Profile with memory tracking"),
|
|
124
128
|
("zx profile --no-memory --top 10 app.zx", "Profile without memory, show top 10"),
|
|
129
|
+
("zx -r \"print(42)\"", "Execute inline code directly"),
|
|
130
|
+
("zx -r \"let x = 10; print(x * 2)\"", "Run multi-statement inline code"),
|
|
125
131
|
("", ""),
|
|
126
132
|
("[bold]Built-in Functions:[/bold]", "100+ functions available"),
|
|
127
133
|
("", "Memory: persist_set, persist_get, track_memory"),
|
|
@@ -150,54 +156,189 @@ def show_all_commands():
|
|
|
150
156
|
console.print("\n[bold green]💡 Tip:[/bold green] Use 'zx <command> --help' for detailed command options\n")
|
|
151
157
|
|
|
152
158
|
@click.group(invoke_without_command=True)
|
|
153
|
-
@click.version_option(version="1.7.
|
|
159
|
+
@click.version_option(version="1.7.2", prog_name="Zexus")
|
|
154
160
|
@click.option('--syntax-style', type=click.Choice(['universal', 'tolerable', 'auto']),
|
|
155
161
|
default='auto', help='Syntax style to use (universal=strict, tolerable=flexible)')
|
|
156
162
|
@click.option('--advanced-parsing', is_flag=True, default=True,
|
|
157
163
|
help='Enable advanced multi-strategy parsing (recommended)')
|
|
158
164
|
@click.option('--execution-mode', type=click.Choice(['interpreter', 'compiler', 'auto']),
|
|
159
165
|
default='auto', help='Execution engine to use')
|
|
160
|
-
@click.option('--debug',
|
|
166
|
+
@click.option('--debug', type=click.Choice(['on', 'off', 'minimal', 'full', 'none']),
|
|
167
|
+
help='Enable/disable debug logging (on/off/minimal/full)')
|
|
168
|
+
@click.option('--no-debug', is_flag=True, help='Disable debug logging')
|
|
161
169
|
@click.option('--zexus', is_flag=True, help='Show all available Zexus commands')
|
|
170
|
+
@click.option('-r', '--run-code', type=str, default=None,
|
|
171
|
+
help='Execute inline Zexus code (like python -c)')
|
|
162
172
|
@click.pass_context
|
|
163
|
-
def cli(ctx, syntax_style, advanced_parsing, execution_mode, debug, zexus):
|
|
173
|
+
def cli(ctx, syntax_style, advanced_parsing, execution_mode, debug, no_debug, zexus, run_code):
|
|
164
174
|
"""Zexus Programming Language - Hybrid Interpreter/Compiler
|
|
165
175
|
|
|
166
176
|
Use 'zx run --zexus' or 'zx --zexus' to see all available commands.
|
|
177
|
+
Use 'zx -r "<code>"' to execute inline Zexus code.
|
|
167
178
|
"""
|
|
168
179
|
|
|
169
180
|
if zexus:
|
|
170
181
|
show_all_commands()
|
|
171
182
|
sys.exit(0)
|
|
172
183
|
|
|
173
|
-
# If no command provided, show help
|
|
174
|
-
if ctx.invoked_subcommand is None:
|
|
175
|
-
click.echo(ctx.get_help())
|
|
176
|
-
return
|
|
177
|
-
|
|
178
184
|
ctx.ensure_object(dict)
|
|
179
185
|
ctx.obj['SYNTAX_STYLE'] = syntax_style
|
|
180
186
|
ctx.obj['ADVANCED_PARSING'] = advanced_parsing
|
|
181
187
|
ctx.obj['EXECUTION_MODE'] = execution_mode
|
|
182
|
-
ctx.obj['DEBUG'] =
|
|
188
|
+
ctx.obj['DEBUG'] = False
|
|
183
189
|
|
|
184
190
|
# Update config based on CLI flags
|
|
185
|
-
if debug:
|
|
191
|
+
if no_debug or debug in ('off', 'none'):
|
|
192
|
+
config.disable_debug()
|
|
193
|
+
config.enable_debug_logs = False
|
|
194
|
+
ctx.obj['DEBUG'] = False
|
|
195
|
+
elif debug in ('on', 'full'):
|
|
196
|
+
config.enable_debug('full')
|
|
197
|
+
config.enable_debug_logs = True
|
|
198
|
+
ctx.obj['DEBUG'] = True
|
|
199
|
+
elif debug == 'minimal':
|
|
200
|
+
config.enable_debug('minimal')
|
|
186
201
|
config.enable_debug_logs = True
|
|
202
|
+
ctx.obj['DEBUG'] = True
|
|
203
|
+
|
|
204
|
+
# Handle inline code execution: zx -r "<code>"
|
|
205
|
+
if run_code is not None:
|
|
206
|
+
_execute_inline_code(ctx, run_code)
|
|
207
|
+
return
|
|
208
|
+
|
|
209
|
+
# If no command provided, show help
|
|
210
|
+
if ctx.invoked_subcommand is None:
|
|
211
|
+
click.echo(ctx.get_help())
|
|
212
|
+
return
|
|
187
213
|
if execution_mode == 'compiler':
|
|
188
214
|
config.use_hybrid_compiler = True
|
|
189
215
|
elif execution_mode == 'interpreter':
|
|
190
216
|
config.use_hybrid_compiler = False
|
|
191
217
|
|
|
218
|
+
|
|
219
|
+
def _execute_inline_code(ctx, source_code):
|
|
220
|
+
"""Execute inline Zexus code passed via -r flag.
|
|
221
|
+
|
|
222
|
+
Examples:
|
|
223
|
+
zx -r "print(42)"
|
|
224
|
+
zx -r "let x = 10; print(x * 2)"
|
|
225
|
+
zx -r "action greet(name) { print(\"Hello \" + name) }; greet(\"World\")"
|
|
226
|
+
"""
|
|
227
|
+
error_reporter = get_error_reporter()
|
|
228
|
+
|
|
229
|
+
try:
|
|
230
|
+
# Register source for error reporting
|
|
231
|
+
error_reporter.register_source("<inline>", source_code)
|
|
232
|
+
|
|
233
|
+
syntax_style = ctx.obj['SYNTAX_STYLE']
|
|
234
|
+
advanced_parsing = ctx.obj['ADVANCED_PARSING']
|
|
235
|
+
debug_mode = ctx.obj.get('DEBUG', False)
|
|
236
|
+
validator = SyntaxValidator()
|
|
237
|
+
|
|
238
|
+
# Auto-detect syntax style if needed
|
|
239
|
+
if syntax_style == 'auto':
|
|
240
|
+
syntax_style = validator.suggest_syntax_style(source_code)
|
|
241
|
+
|
|
242
|
+
# Parse the program
|
|
243
|
+
lexer = Lexer(source_code, filename="<inline>")
|
|
244
|
+
parser = Parser(lexer, syntax_style, enable_advanced_strategies=advanced_parsing)
|
|
245
|
+
program = parser.parse_program()
|
|
246
|
+
|
|
247
|
+
if parser.errors and any("critical" in e.lower() for e in parser.errors):
|
|
248
|
+
console.print("[bold red]❌ Parse error in inline code:[/bold red]")
|
|
249
|
+
for error in parser.errors:
|
|
250
|
+
console.print(f" ❌ {error}")
|
|
251
|
+
sys.exit(1)
|
|
252
|
+
|
|
253
|
+
# Set up environment
|
|
254
|
+
env = Environment()
|
|
255
|
+
env.set("__file__", String("<inline>"))
|
|
256
|
+
env.set("__FILE__", String("<inline>"))
|
|
257
|
+
env.set("__MODULE__", String("__main__"))
|
|
258
|
+
env.set("__DIR__", String(os.getcwd()))
|
|
259
|
+
|
|
260
|
+
from ..object import List as ZList
|
|
261
|
+
env.set("__ARGS__", ZList([]))
|
|
262
|
+
env.set("__ARGV__", ZList([]))
|
|
263
|
+
env.set("__PACKAGE__", String(""))
|
|
264
|
+
|
|
265
|
+
# Attempt VM execution first, fall back to interpreter
|
|
266
|
+
bytecode = None
|
|
267
|
+
fallback_reason = None
|
|
268
|
+
|
|
269
|
+
try:
|
|
270
|
+
bytecode = compile_ast_to_bytecode(program, optimize=True)
|
|
271
|
+
except UnsupportedNodeError as e:
|
|
272
|
+
fallback_reason = str(e)
|
|
273
|
+
except Exception as e:
|
|
274
|
+
fallback_reason = str(e)
|
|
275
|
+
|
|
276
|
+
if bytecode is not None and fallback_reason is None:
|
|
277
|
+
vm = VM(
|
|
278
|
+
mode=VMMode.AUTO,
|
|
279
|
+
use_jit=True,
|
|
280
|
+
max_heap_mb=512,
|
|
281
|
+
debug=debug_mode,
|
|
282
|
+
gas_limit=10000000
|
|
283
|
+
)
|
|
284
|
+
# Load builtins into VM
|
|
285
|
+
try:
|
|
286
|
+
builtin_evaluator = Evaluator(use_vm=False)
|
|
287
|
+
vm.builtins.update(dict(builtin_evaluator.builtins))
|
|
288
|
+
except Exception:
|
|
289
|
+
pass
|
|
290
|
+
|
|
291
|
+
vm.env["__file__"] = "<inline>"
|
|
292
|
+
vm.env["__FILE__"] = "<inline>"
|
|
293
|
+
vm.env["__MODULE__"] = "__main__"
|
|
294
|
+
vm.env["__DIR__"] = os.getcwd()
|
|
295
|
+
vm.env["__ARGS__"] = ()
|
|
296
|
+
vm.env["__ARGV__"] = ()
|
|
297
|
+
vm.env["__PACKAGE__"] = ""
|
|
298
|
+
|
|
299
|
+
try:
|
|
300
|
+
result = vm.execute(bytecode, debug=debug_mode)
|
|
301
|
+
except Exception as e:
|
|
302
|
+
if debug_mode:
|
|
303
|
+
import traceback
|
|
304
|
+
traceback.print_exc()
|
|
305
|
+
fallback_reason = str(e)
|
|
306
|
+
|
|
307
|
+
if fallback_reason is not None:
|
|
308
|
+
result = evaluate(program, env, debug_mode=debug_mode, use_vm=False)
|
|
309
|
+
elif bytecode is None:
|
|
310
|
+
result = evaluate(program, env, debug_mode=debug_mode, use_vm=False)
|
|
311
|
+
|
|
312
|
+
# Print result if meaningful
|
|
313
|
+
if result and hasattr(result, 'inspect') and result.inspect() != 'null':
|
|
314
|
+
console.print(result.inspect())
|
|
315
|
+
elif isinstance(result, str) and result:
|
|
316
|
+
console.print(result)
|
|
317
|
+
elif hasattr(result, 'value') and result.value is not None:
|
|
318
|
+
console.print(str(result.value))
|
|
319
|
+
|
|
320
|
+
except ZexusError as e:
|
|
321
|
+
print_error(e)
|
|
322
|
+
sys.exit(1)
|
|
323
|
+
except Exception as e:
|
|
324
|
+
console.print(f"[bold red]Error:[/bold red] {str(e)}")
|
|
325
|
+
if ctx.obj.get('DEBUG'):
|
|
326
|
+
import traceback
|
|
327
|
+
traceback.print_exc()
|
|
328
|
+
sys.exit(1)
|
|
329
|
+
|
|
330
|
+
|
|
192
331
|
@cli.command()
|
|
193
332
|
@click.argument('file', type=click.Path(exists=True))
|
|
194
333
|
@click.argument('args', nargs=-1) # Accept any number of additional arguments
|
|
195
|
-
@click.option('--use-vm',
|
|
334
|
+
@click.option('--use-vm/--no-vm', default=True, help='Use VM for execution (default: enabled for performance)')
|
|
196
335
|
@click.option('--vm-mode', type=click.Choice(['auto', 'stack', 'register', 'parallel']),
|
|
197
336
|
default='auto', help='VM execution mode (auto=best performance)')
|
|
198
337
|
@click.option('--no-optimize', is_flag=True, default=False, help='Disable bytecode optimizations')
|
|
338
|
+
@click.option('--precompile-modules', is_flag=True, default=False,
|
|
339
|
+
help='Pre-parse and cache all imported modules before execution')
|
|
199
340
|
@click.pass_context
|
|
200
|
-
def run(ctx, file, args, use_vm, vm_mode, no_optimize):
|
|
341
|
+
def run(ctx, file, args, use_vm, vm_mode, no_optimize, precompile_modules):
|
|
201
342
|
"""Run a Zexus program with hybrid execution"""
|
|
202
343
|
# Register source for error reporting
|
|
203
344
|
error_reporter = get_error_reporter()
|
|
@@ -208,6 +349,37 @@ def run(ctx, file, args, use_vm, vm_mode, no_optimize):
|
|
|
208
349
|
|
|
209
350
|
# Register source with error reporter
|
|
210
351
|
error_reporter.register_source(file, source_code)
|
|
352
|
+
|
|
353
|
+
# Apply in-file execution flags (if any)
|
|
354
|
+
file_flags = parse_file_flags(source_code)
|
|
355
|
+
vm_config = {}
|
|
356
|
+
if file_flags:
|
|
357
|
+
if 'use_vm' in file_flags:
|
|
358
|
+
use_vm = bool(file_flags.get('use_vm'))
|
|
359
|
+
if 'vm_mode' in file_flags:
|
|
360
|
+
vm_mode = str(file_flags.get('vm_mode')).lower()
|
|
361
|
+
if 'no_optimize' in file_flags:
|
|
362
|
+
no_optimize = bool(file_flags.get('no_optimize'))
|
|
363
|
+
if 'precompile_modules' in file_flags:
|
|
364
|
+
precompile_modules = bool(file_flags.get('precompile_modules'))
|
|
365
|
+
if 'syntax_style' in file_flags:
|
|
366
|
+
ctx.obj['SYNTAX_STYLE'] = str(file_flags.get('syntax_style'))
|
|
367
|
+
if 'advanced_parsing' in file_flags:
|
|
368
|
+
ctx.obj['ADVANCED_PARSING'] = bool(file_flags.get('advanced_parsing'))
|
|
369
|
+
if 'execution_mode' in file_flags:
|
|
370
|
+
ctx.obj['EXECUTION_MODE'] = str(file_flags.get('execution_mode'))
|
|
371
|
+
if 'debug' in file_flags:
|
|
372
|
+
dbg = file_flags.get('debug')
|
|
373
|
+
if isinstance(dbg, str):
|
|
374
|
+
config.debug_level = dbg
|
|
375
|
+
ctx.obj['DEBUG'] = dbg != 'none'
|
|
376
|
+
else:
|
|
377
|
+
ctx.obj['DEBUG'] = bool(dbg)
|
|
378
|
+
config.enable_debug_logs = ctx.obj['DEBUG']
|
|
379
|
+
if 'vm_config' in file_flags and isinstance(file_flags.get('vm_config'), dict):
|
|
380
|
+
vm_config = dict(file_flags.get('vm_config'))
|
|
381
|
+
|
|
382
|
+
console.print("[dim]Applied file flags (@zexus) overrides[/dim]")
|
|
211
383
|
|
|
212
384
|
syntax_style = ctx.obj['SYNTAX_STYLE']
|
|
213
385
|
advanced_parsing = ctx.obj['ADVANCED_PARSING']
|
|
@@ -256,7 +428,36 @@ def run(ctx, file, args, use_vm, vm_mode, no_optimize):
|
|
|
256
428
|
for error in parser.errors:
|
|
257
429
|
console.print(f" ❌ {error}")
|
|
258
430
|
sys.exit(1)
|
|
259
|
-
|
|
431
|
+
|
|
432
|
+
# Pre-compile imported modules (parse + optional bytecode) before execution
|
|
433
|
+
if precompile_modules:
|
|
434
|
+
console.print("[dim]Pre-compiling imported modules...[/dim]", end="")
|
|
435
|
+
try:
|
|
436
|
+
from ..module_cache import precompile_modules as _precompile
|
|
437
|
+
import os as _os
|
|
438
|
+
_abs = _os.path.abspath(file)
|
|
439
|
+
precompiled = _precompile(program, _abs, compile_bytecode=use_vm)
|
|
440
|
+
if precompiled:
|
|
441
|
+
console.print(f" [green]done[/green] ({len(precompiled)} module(s) cached)")
|
|
442
|
+
else:
|
|
443
|
+
console.print(" [green]done[/green] (no external modules)")
|
|
444
|
+
except Exception as e:
|
|
445
|
+
console.print(f" [yellow]warning:[/yellow] {e}")
|
|
446
|
+
|
|
447
|
+
# Static type checking pass
|
|
448
|
+
try:
|
|
449
|
+
from ..type_checker import StaticTypeChecker
|
|
450
|
+
_tc = StaticTypeChecker()
|
|
451
|
+
_type_diags = _tc.check(program)
|
|
452
|
+
if _type_diags:
|
|
453
|
+
for _d in _type_diags:
|
|
454
|
+
if _d.level == "error":
|
|
455
|
+
console.print(f" [bold red]✗ {_d}[/bold red]")
|
|
456
|
+
else:
|
|
457
|
+
console.print(f" [yellow]⚠ {_d}[/yellow]")
|
|
458
|
+
except Exception:
|
|
459
|
+
pass # type checker should never block execution
|
|
460
|
+
|
|
260
461
|
# Use the evaluator package
|
|
261
462
|
env = Environment()
|
|
262
463
|
|
|
@@ -287,6 +488,11 @@ def run(ctx, file, args, use_vm, vm_mode, no_optimize):
|
|
|
287
488
|
env.set("__PACKAGE__", package_name)
|
|
288
489
|
|
|
289
490
|
# Execute based on mode
|
|
491
|
+
if not use_vm:
|
|
492
|
+
try:
|
|
493
|
+
env.disable_vm = True
|
|
494
|
+
except Exception:
|
|
495
|
+
pass
|
|
290
496
|
bytecode = None
|
|
291
497
|
fallback_reason = None
|
|
292
498
|
|
|
@@ -313,20 +519,41 @@ def run(ctx, file, args, use_vm, vm_mode, no_optimize):
|
|
|
313
519
|
fallback_reason = str(e)
|
|
314
520
|
|
|
315
521
|
if bytecode is not None and fallback_reason is None:
|
|
316
|
-
|
|
522
|
+
vm_mode_map = {
|
|
317
523
|
'auto': VMMode.AUTO,
|
|
318
524
|
'stack': VMMode.STACK,
|
|
319
525
|
'register': VMMode.REGISTER,
|
|
320
526
|
'parallel': VMMode.PARALLEL
|
|
321
|
-
}
|
|
527
|
+
}
|
|
528
|
+
vm_mode_value = vm_mode if vm_mode in vm_mode_map else 'auto'
|
|
529
|
+
vm_mode_enum = vm_mode_map[vm_mode_value]
|
|
530
|
+
|
|
531
|
+
vm_builtins = {}
|
|
532
|
+
try:
|
|
533
|
+
builtin_evaluator = Evaluator(use_vm=False)
|
|
534
|
+
vm_builtins = dict(builtin_evaluator.builtins)
|
|
535
|
+
except Exception:
|
|
536
|
+
vm_builtins = {}
|
|
322
537
|
|
|
323
538
|
console.print(f"[dim]Initializing VM ({vm_mode} mode)...[/dim]", end="")
|
|
324
539
|
vm = VM(
|
|
325
540
|
mode=vm_mode_enum,
|
|
326
541
|
use_jit=not no_optimize,
|
|
327
542
|
max_heap_mb=1000, # 1GB heap limit
|
|
328
|
-
debug=ctx.obj.get('DEBUG', False)
|
|
543
|
+
debug=ctx.obj.get('DEBUG', False),
|
|
544
|
+
gas_limit=100000000 # 100M instructions for heavy checks
|
|
329
545
|
)
|
|
546
|
+
if vm_builtins:
|
|
547
|
+
vm.builtins.update(vm_builtins)
|
|
548
|
+
apply_vm_config(vm, vm_config)
|
|
549
|
+
# Mirror interpreter module context for relative imports in VM
|
|
550
|
+
vm.env["__file__"] = abs_file
|
|
551
|
+
vm.env["__FILE__"] = abs_file
|
|
552
|
+
vm.env["__MODULE__"] = "__main__"
|
|
553
|
+
vm.env["__DIR__"] = os.path.dirname(abs_file)
|
|
554
|
+
vm.env["__ARGS__"] = args
|
|
555
|
+
vm.env["__ARGV__"] = args
|
|
556
|
+
vm.env["__PACKAGE__"] = package_name.value if hasattr(package_name, "value") else package_name
|
|
330
557
|
console.print(" [green]done[/green]")
|
|
331
558
|
|
|
332
559
|
console.print("[dim]Executing on VM...[/dim]")
|
|
@@ -341,10 +568,10 @@ def run(ctx, file, args, use_vm, vm_mode, no_optimize):
|
|
|
341
568
|
|
|
342
569
|
if fallback_reason is not None:
|
|
343
570
|
console.print("[bold yellow]🔄 Falling back to interpreter execution...[/bold yellow]")
|
|
344
|
-
result = evaluate(program, env, debug_mode=ctx.obj['DEBUG'])
|
|
571
|
+
result = evaluate(program, env, debug_mode=ctx.obj['DEBUG'], use_vm=False)
|
|
345
572
|
elif bytecode is None:
|
|
346
573
|
# No bytecode generated but VM not requested or compile skipped
|
|
347
|
-
result = evaluate(program, env, debug_mode=ctx.obj['DEBUG'])
|
|
574
|
+
result = evaluate(program, env, debug_mode=ctx.obj['DEBUG'], use_vm=False)
|
|
348
575
|
|
|
349
576
|
if result and hasattr(result, 'inspect') and result.inspect() != 'null':
|
|
350
577
|
console.print(f"\n✅ [bold green]Result:[/bold green] {result.inspect()}")
|
|
@@ -428,6 +655,59 @@ def check(ctx, file):
|
|
|
428
655
|
console.print(f"[bold red]Error:[/bold red] {str(e)}")
|
|
429
656
|
sys.exit(1)
|
|
430
657
|
|
|
658
|
+
|
|
659
|
+
@cli.command()
|
|
660
|
+
@click.argument('file', type=click.Path(exists=True))
|
|
661
|
+
@click.option('--target', '-t', type=click.Choice(['wasm']), default='wasm',
|
|
662
|
+
help='Compilation target (default: wasm)')
|
|
663
|
+
@click.option('-o', '--output', type=click.Path(), default=None,
|
|
664
|
+
help='Output file path (default: <input>.wasm)')
|
|
665
|
+
@click.pass_context
|
|
666
|
+
def compile(ctx, file, target, output):
|
|
667
|
+
"""Compile a Zexus file to a target format (e.g. WebAssembly)."""
|
|
668
|
+
import os
|
|
669
|
+
try:
|
|
670
|
+
with open(file, 'r') as f:
|
|
671
|
+
source_code = f.read()
|
|
672
|
+
|
|
673
|
+
syntax_style = ctx.obj['SYNTAX_STYLE']
|
|
674
|
+
advanced_parsing = ctx.obj['ADVANCED_PARSING']
|
|
675
|
+
|
|
676
|
+
lexer = Lexer(source_code)
|
|
677
|
+
parser = Parser(lexer, syntax_style, enable_advanced_strategies=advanced_parsing)
|
|
678
|
+
program = parser.parse_program()
|
|
679
|
+
|
|
680
|
+
if parser.errors:
|
|
681
|
+
console.print("[bold red]❌ Parse errors — cannot compile:[/bold red]")
|
|
682
|
+
for err in parser.errors:
|
|
683
|
+
console.print(f" 🚫 {err}")
|
|
684
|
+
sys.exit(1)
|
|
685
|
+
|
|
686
|
+
# Compile AST → bytecode
|
|
687
|
+
from ..vm.compiler import BytecodeCompiler as BCCompiler
|
|
688
|
+
bc_compiler = BCCompiler()
|
|
689
|
+
bytecode = bc_compiler.compile(program)
|
|
690
|
+
|
|
691
|
+
if target == 'wasm':
|
|
692
|
+
from ..vm.wasm_compiler import WasmCompiler
|
|
693
|
+
wasm = WasmCompiler().compile(bytecode)
|
|
694
|
+
|
|
695
|
+
out_path = output or os.path.splitext(file)[0] + '.wasm'
|
|
696
|
+
with open(out_path, 'wb') as wf:
|
|
697
|
+
wf.write(wasm)
|
|
698
|
+
|
|
699
|
+
console.print(f"[bold green]✅ Compiled to WASM:[/bold green] {out_path} ({len(wasm)} bytes)")
|
|
700
|
+
else:
|
|
701
|
+
console.print(f"[bold red]Unknown target: {target}[/bold red]")
|
|
702
|
+
sys.exit(1)
|
|
703
|
+
|
|
704
|
+
except Exception as e:
|
|
705
|
+
console.print(f"[bold red]Compile error:[/bold red] {str(e)}")
|
|
706
|
+
import traceback
|
|
707
|
+
traceback.print_exc()
|
|
708
|
+
sys.exit(1)
|
|
709
|
+
|
|
710
|
+
|
|
431
711
|
@cli.command()
|
|
432
712
|
@click.argument('file', type=click.Path(exists=True))
|
|
433
713
|
@click.pass_context
|
package/src/zexus/cli/zpm.py
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -39,12 +39,17 @@ class Lexer:
|
|
|
39
39
|
return self.input[self.read_position]
|
|
40
40
|
|
|
41
41
|
def next_token(self):
|
|
42
|
-
|
|
42
|
+
# Avoid recursion: long files can contain thousands of consecutive
|
|
43
|
+
# comments/blank lines.
|
|
44
|
+
while True:
|
|
45
|
+
self.skip_whitespace()
|
|
46
|
+
|
|
47
|
+
# Skip single line comments
|
|
48
|
+
if self.ch == '#' and self.peek_char() != '{':
|
|
49
|
+
self.skip_comment()
|
|
50
|
+
continue
|
|
43
51
|
|
|
44
|
-
|
|
45
|
-
if self.ch == '#' and self.peek_char() != '{':
|
|
46
|
-
self.skip_comment()
|
|
47
|
-
return self.next_token()
|
|
52
|
+
break
|
|
48
53
|
|
|
49
54
|
tok = None
|
|
50
55
|
current_line = self.line
|
|
@@ -468,6 +468,85 @@ class ConcurrencyManager:
|
|
|
468
468
|
f"tasks={stats['tasks_completed']}/{stats['tasks_total']})")
|
|
469
469
|
|
|
470
470
|
|
|
471
|
+
# ---------------------------------------------------------------------------
|
|
472
|
+
# AsyncChannel — asyncio-native channel for the shared event loop
|
|
473
|
+
# ---------------------------------------------------------------------------
|
|
474
|
+
|
|
475
|
+
class AsyncChannel:
|
|
476
|
+
"""
|
|
477
|
+
Async-native channel backed by :class:`asyncio.Queue`.
|
|
478
|
+
|
|
479
|
+
Unlike :class:`Channel` (which uses ``threading`` primitives), this
|
|
480
|
+
channel is designed to be used inside coroutines running on the shared
|
|
481
|
+
Zexus event loop. ``send`` and ``receive`` are ``async`` methods.
|
|
482
|
+
|
|
483
|
+
Example (inside a Zexus ``async action``)::
|
|
484
|
+
|
|
485
|
+
ch = AsyncChannel("numbers", capacity=10)
|
|
486
|
+
await ch.send(42)
|
|
487
|
+
val = await ch.receive() # 42
|
|
488
|
+
ch.close()
|
|
489
|
+
"""
|
|
490
|
+
|
|
491
|
+
def __init__(self, name: str, element_type: Optional[str] = None,
|
|
492
|
+
capacity: int = 0):
|
|
493
|
+
self.name = name
|
|
494
|
+
self.element_type = element_type
|
|
495
|
+
self.capacity = capacity
|
|
496
|
+
self._closed = False
|
|
497
|
+
|
|
498
|
+
import asyncio as _asyncio
|
|
499
|
+
if capacity > 0:
|
|
500
|
+
self._queue: _asyncio.Queue = _asyncio.Queue(maxsize=capacity)
|
|
501
|
+
else:
|
|
502
|
+
self._queue = _asyncio.Queue()
|
|
503
|
+
|
|
504
|
+
@property
|
|
505
|
+
def is_open(self) -> bool:
|
|
506
|
+
return not self._closed
|
|
507
|
+
|
|
508
|
+
async def send(self, value, *, timeout: Optional[float] = None):
|
|
509
|
+
"""Send *value* into the channel (async, may block if full)."""
|
|
510
|
+
if self._closed:
|
|
511
|
+
raise RuntimeError(f"Cannot send on closed async channel '{self.name}'")
|
|
512
|
+
import asyncio as _asyncio
|
|
513
|
+
if timeout is not None:
|
|
514
|
+
await _asyncio.wait_for(self._queue.put(value), timeout=timeout)
|
|
515
|
+
else:
|
|
516
|
+
await self._queue.put(value)
|
|
517
|
+
|
|
518
|
+
async def receive(self, *, timeout: Optional[float] = None):
|
|
519
|
+
"""Receive a value from the channel (async, may block if empty)."""
|
|
520
|
+
if self._closed and self._queue.empty():
|
|
521
|
+
return None
|
|
522
|
+
import asyncio as _asyncio
|
|
523
|
+
try:
|
|
524
|
+
if timeout is not None:
|
|
525
|
+
value = await _asyncio.wait_for(self._queue.get(), timeout=timeout)
|
|
526
|
+
else:
|
|
527
|
+
value = await self._queue.get()
|
|
528
|
+
if isinstance(value, _ChannelClosedSentinel):
|
|
529
|
+
return None
|
|
530
|
+
return value
|
|
531
|
+
except _asyncio.TimeoutError:
|
|
532
|
+
if self._closed:
|
|
533
|
+
return None
|
|
534
|
+
raise RuntimeError(f"Timeout receiving from async channel '{self.name}'")
|
|
535
|
+
|
|
536
|
+
def close(self):
|
|
537
|
+
"""Close the channel. Pending receivers will get ``None``."""
|
|
538
|
+
self._closed = True
|
|
539
|
+
try:
|
|
540
|
+
self._queue.put_nowait(_CHANNEL_CLOSED_SENTINEL)
|
|
541
|
+
except Exception:
|
|
542
|
+
pass
|
|
543
|
+
|
|
544
|
+
def __repr__(self) -> str:
|
|
545
|
+
mode = f"buffered({self.capacity})" if self.capacity > 0 else "unbuffered"
|
|
546
|
+
status = "closed" if self._closed else "open"
|
|
547
|
+
return f"AsyncChannel<{self.element_type}>({self.name}, {mode}, {status})"
|
|
548
|
+
|
|
549
|
+
|
|
471
550
|
# Global singleton instance
|
|
472
551
|
_concurrency_manager: Optional[ConcurrencyManager] = None
|
|
473
552
|
|
package/src/zexus/config.py
CHANGED
|
@@ -28,6 +28,11 @@ DEFAULT_RUNTIME = {
|
|
|
28
28
|
'enable_advanced_parsing': True,
|
|
29
29
|
'enable_debug_logs': False,
|
|
30
30
|
'enable_parser_debug': False, # OPTIMIZATION: Disable parser debug output for speed
|
|
31
|
+
# Large-file stability: advanced parsing does extra analysis and can be
|
|
32
|
+
# significantly heavier on very large sources. For big files, we prefer the
|
|
33
|
+
# traditional streaming parser for stability.
|
|
34
|
+
'advanced_parsing_max_lines': 2000,
|
|
35
|
+
'advanced_parsing_max_tokens': 50000,
|
|
31
36
|
# Legacy runtime flags expected by older modules
|
|
32
37
|
'use_hybrid_compiler': True,
|
|
33
38
|
'fallback_to_interpreter': True,
|
|
@@ -40,8 +45,15 @@ class Config:
|
|
|
40
45
|
def __init__(self):
|
|
41
46
|
self.config_dir = Path.home() / ".zexus"
|
|
42
47
|
self.config_file = self.config_dir / "config.json"
|
|
48
|
+
|
|
49
|
+
# Fast caching attribute for hot paths
|
|
50
|
+
self.fast_debug_enabled = False
|
|
51
|
+
|
|
43
52
|
self._data = DEFAULT_CONFIG.copy()
|
|
44
53
|
self._ensure_loaded()
|
|
54
|
+
|
|
55
|
+
# Update cache from initial loaded data
|
|
56
|
+
self.fast_debug_enabled = (self.debug_level != 'none')
|
|
45
57
|
|
|
46
58
|
# ensure runtime defaults exist for backward compatibility
|
|
47
59
|
self._data.setdefault('runtime', {})
|
|
@@ -93,6 +105,7 @@ class Config:
|
|
|
93
105
|
raise ValueError('Invalid debug level')
|
|
94
106
|
self._data.setdefault('debug', {})['level'] = value
|
|
95
107
|
self._data['debug']['enabled'] = (value != 'none')
|
|
108
|
+
self.fast_debug_enabled = (value != 'none')
|
|
96
109
|
self._write()
|
|
97
110
|
|
|
98
111
|
def enable_debug(self, level='full'):
|
|
@@ -143,6 +156,47 @@ class Config:
|
|
|
143
156
|
self.debug_level = 'none'
|
|
144
157
|
|
|
145
158
|
# Legacy runtime properties
|
|
159
|
+
@property
|
|
160
|
+
def enable_parser_debug(self):
|
|
161
|
+
return bool(self._data.get('runtime', {}).get('enable_parser_debug', False))
|
|
162
|
+
|
|
163
|
+
@enable_parser_debug.setter
|
|
164
|
+
def enable_parser_debug(self, value):
|
|
165
|
+
self._data.setdefault('runtime', {})['enable_parser_debug'] = bool(value)
|
|
166
|
+
self._write()
|
|
167
|
+
|
|
168
|
+
@property
|
|
169
|
+
def advanced_parsing_max_lines(self):
|
|
170
|
+
try:
|
|
171
|
+
return int(self._data.get('runtime', {}).get('advanced_parsing_max_lines', 2000))
|
|
172
|
+
except Exception:
|
|
173
|
+
return 2000
|
|
174
|
+
|
|
175
|
+
@advanced_parsing_max_lines.setter
|
|
176
|
+
def advanced_parsing_max_lines(self, value):
|
|
177
|
+
try:
|
|
178
|
+
v = int(value)
|
|
179
|
+
except Exception:
|
|
180
|
+
v = 2000
|
|
181
|
+
self._data.setdefault('runtime', {})['advanced_parsing_max_lines'] = v
|
|
182
|
+
self._write()
|
|
183
|
+
|
|
184
|
+
@property
|
|
185
|
+
def advanced_parsing_max_tokens(self):
|
|
186
|
+
try:
|
|
187
|
+
return int(self._data.get('runtime', {}).get('advanced_parsing_max_tokens', 50000))
|
|
188
|
+
except Exception:
|
|
189
|
+
return 50000
|
|
190
|
+
|
|
191
|
+
@advanced_parsing_max_tokens.setter
|
|
192
|
+
def advanced_parsing_max_tokens(self, value):
|
|
193
|
+
try:
|
|
194
|
+
v = int(value)
|
|
195
|
+
except Exception:
|
|
196
|
+
v = 50000
|
|
197
|
+
self._data.setdefault('runtime', {})['advanced_parsing_max_tokens'] = v
|
|
198
|
+
self._write()
|
|
199
|
+
|
|
146
200
|
@property
|
|
147
201
|
def use_hybrid_compiler(self):
|
|
148
202
|
return self._data.get('runtime', {}).get('use_hybrid_compiler', True)
|