zexus 1.6.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/LICENSE +0 -0
- package/README.md +2513 -0
- package/bin/zexus +2 -0
- package/bin/zpics +2 -0
- package/bin/zpm +2 -0
- package/bin/zx +2 -0
- package/bin/zx-deploy +2 -0
- package/bin/zx-dev +2 -0
- package/bin/zx-run +2 -0
- package/package.json +66 -0
- package/scripts/README.md +24 -0
- package/scripts/postinstall.js +44 -0
- package/shared_config.json +24 -0
- package/src/README.md +1525 -0
- package/src/tests/run_zexus_tests.py +117 -0
- package/src/tests/test_all_phases.zx +346 -0
- package/src/tests/test_blockchain_features.zx +306 -0
- package/src/tests/test_complexity_features.zx +321 -0
- package/src/tests/test_core_integration.py +185 -0
- package/src/tests/test_phase10_ecosystem.zx +177 -0
- package/src/tests/test_phase1_modifiers.zx +87 -0
- package/src/tests/test_phase2_plugins.zx +80 -0
- package/src/tests/test_phase3_security.zx +97 -0
- package/src/tests/test_phase4_vfs.zx +116 -0
- package/src/tests/test_phase5_types.zx +117 -0
- package/src/tests/test_phase6_metaprogramming.zx +125 -0
- package/src/tests/test_phase7_optimization.zx +132 -0
- package/src/tests/test_phase9_advanced_types.zx +157 -0
- package/src/tests/test_security_features.py +419 -0
- package/src/tests/test_security_features.zx +276 -0
- package/src/tests/test_simple_zx.zx +1 -0
- package/src/tests/test_verification_simple.zx +69 -0
- package/src/zexus/__init__.py +28 -0
- package/src/zexus/__main__.py +5 -0
- package/src/zexus/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/advanced_types.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/builtin_modules.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/capability_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/complexity_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/concurrency_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/config.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/dependency_injection.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/ecosystem.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__/hybrid_orchestrator.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/lexer.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/metaprogramming.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/module_cache.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/object.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/optimization.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/plugin_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/policy_engine.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/security.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/stdlib_integration.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/strategy_recovery.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/syntax_validator.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/type_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/virtual_filesystem.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/advanced_types.py +401 -0
- package/src/zexus/blockchain/__init__.py +40 -0
- package/src/zexus/blockchain/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/crypto.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/ledger.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/transaction.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/crypto.py +463 -0
- package/src/zexus/blockchain/ledger.py +255 -0
- package/src/zexus/blockchain/transaction.py +267 -0
- package/src/zexus/builtin_modules.py +284 -0
- package/src/zexus/builtin_plugins.py +317 -0
- package/src/zexus/capability_system.py +372 -0
- package/src/zexus/cli/__init__.py +2 -0
- package/src/zexus/cli/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/cli/__pycache__/main.cpython-312.pyc +0 -0
- package/src/zexus/cli/main.py +707 -0
- package/src/zexus/cli/zpm.py +203 -0
- package/src/zexus/compare_interpreter_compiler.py +146 -0
- package/src/zexus/compiler/__init__.py +169 -0
- package/src/zexus/compiler/__pycache__/__init__.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__/zexus_ast.cpython-312.pyc +0 -0
- package/src/zexus/compiler/bytecode.py +266 -0
- package/src/zexus/compiler/compat_runtime.py +277 -0
- package/src/zexus/compiler/lexer.py +257 -0
- package/src/zexus/compiler/parser.py +779 -0
- package/src/zexus/compiler/semantic.py +118 -0
- package/src/zexus/compiler/zexus_ast.py +454 -0
- package/src/zexus/complexity_system.py +575 -0
- package/src/zexus/concurrency_system.py +493 -0
- package/src/zexus/config.py +201 -0
- package/src/zexus/crypto_bridge.py +19 -0
- package/src/zexus/dependency_injection.py +423 -0
- package/src/zexus/ecosystem.py +434 -0
- package/src/zexus/environment.py +101 -0
- package/src/zexus/environment_manager.py +119 -0
- package/src/zexus/error_reporter.py +314 -0
- package/src/zexus/evaluator/__init__.py +12 -0
- package/src/zexus/evaluator/__pycache__/__init__.cpython-312.pyc +0 -0
- 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__/integration.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/statements.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/utils.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/bytecode_compiler.py +700 -0
- package/src/zexus/evaluator/core.py +891 -0
- package/src/zexus/evaluator/expressions.py +827 -0
- package/src/zexus/evaluator/functions.py +3989 -0
- package/src/zexus/evaluator/integration.py +396 -0
- package/src/zexus/evaluator/statements.py +4303 -0
- package/src/zexus/evaluator/utils.py +126 -0
- package/src/zexus/evaluator_original.py +2041 -0
- package/src/zexus/external_bridge.py +16 -0
- package/src/zexus/find_affected_imports.sh +155 -0
- package/src/zexus/hybrid_orchestrator.py +152 -0
- package/src/zexus/input_validation.py +259 -0
- package/src/zexus/lexer.py +571 -0
- package/src/zexus/logging.py +89 -0
- package/src/zexus/lsp/__init__.py +9 -0
- package/src/zexus/lsp/completion_provider.py +207 -0
- package/src/zexus/lsp/definition_provider.py +22 -0
- package/src/zexus/lsp/hover_provider.py +71 -0
- package/src/zexus/lsp/server.py +269 -0
- package/src/zexus/lsp/symbol_provider.py +31 -0
- package/src/zexus/metaprogramming.py +321 -0
- package/src/zexus/module_cache.py +89 -0
- package/src/zexus/module_manager.py +107 -0
- package/src/zexus/object.py +973 -0
- package/src/zexus/optimization.py +424 -0
- package/src/zexus/parser/__init__.py +31 -0
- package/src/zexus/parser/__pycache__/__init__.cpython-312.pyc +0 -0
- 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/integration.py +86 -0
- package/src/zexus/parser/parser.py +3977 -0
- package/src/zexus/parser/strategy_context.py +7254 -0
- package/src/zexus/parser/strategy_structural.py +1033 -0
- package/src/zexus/persistence.py +391 -0
- package/src/zexus/plugin_system.py +290 -0
- package/src/zexus/policy_engine.py +365 -0
- package/src/zexus/profiler/__init__.py +5 -0
- package/src/zexus/profiler/profiler.py +233 -0
- package/src/zexus/purity_system.py +398 -0
- package/src/zexus/runtime/__init__.py +20 -0
- package/src/zexus/runtime/async_runtime.py +324 -0
- package/src/zexus/search_old_imports.sh +65 -0
- package/src/zexus/security.py +1407 -0
- package/src/zexus/stack_trace.py +233 -0
- package/src/zexus/stdlib/__init__.py +27 -0
- package/src/zexus/stdlib/blockchain.py +341 -0
- package/src/zexus/stdlib/compression.py +167 -0
- package/src/zexus/stdlib/crypto.py +124 -0
- package/src/zexus/stdlib/datetime.py +163 -0
- package/src/zexus/stdlib/db_mongo.py +199 -0
- package/src/zexus/stdlib/db_mysql.py +162 -0
- package/src/zexus/stdlib/db_postgres.py +163 -0
- package/src/zexus/stdlib/db_sqlite.py +133 -0
- package/src/zexus/stdlib/encoding.py +230 -0
- package/src/zexus/stdlib/fs.py +195 -0
- package/src/zexus/stdlib/http.py +219 -0
- package/src/zexus/stdlib/http_server.py +248 -0
- package/src/zexus/stdlib/json_module.py +61 -0
- package/src/zexus/stdlib/math.py +360 -0
- package/src/zexus/stdlib/os_module.py +265 -0
- package/src/zexus/stdlib/regex.py +148 -0
- package/src/zexus/stdlib/sockets.py +253 -0
- package/src/zexus/stdlib/test_framework.zx +208 -0
- package/src/zexus/stdlib/test_runner.zx +119 -0
- package/src/zexus/stdlib_integration.py +341 -0
- package/src/zexus/strategy_recovery.py +256 -0
- package/src/zexus/syntax_validator.py +356 -0
- package/src/zexus/testing/zpics.py +407 -0
- package/src/zexus/testing/zpics_runtime.py +369 -0
- package/src/zexus/type_system.py +374 -0
- package/src/zexus/validation_system.py +569 -0
- package/src/zexus/virtual_filesystem.py +355 -0
- package/src/zexus/vm/__init__.py +8 -0
- package/src/zexus/vm/__pycache__/__init__.cpython-312.pyc +0 -0
- 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__/cache.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/jit.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/memory_manager.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/memory_pool.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/parallel_vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/peephole_optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/profiler.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/register_allocator.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/register_vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/ssa_converter.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/async_optimizer.py +420 -0
- package/src/zexus/vm/bytecode.py +428 -0
- package/src/zexus/vm/bytecode_converter.py +297 -0
- package/src/zexus/vm/cache.py +532 -0
- package/src/zexus/vm/jit.py +720 -0
- package/src/zexus/vm/memory_manager.py +520 -0
- package/src/zexus/vm/memory_pool.py +511 -0
- package/src/zexus/vm/optimizer.py +478 -0
- package/src/zexus/vm/parallel_vm.py +899 -0
- package/src/zexus/vm/peephole_optimizer.py +452 -0
- package/src/zexus/vm/profiler.py +527 -0
- package/src/zexus/vm/register_allocator.py +462 -0
- package/src/zexus/vm/register_vm.py +520 -0
- package/src/zexus/vm/ssa_converter.py +757 -0
- package/src/zexus/vm/vm.py +1392 -0
- package/src/zexus/zexus_ast.py +1782 -0
- package/src/zexus/zexus_token.py +253 -0
- package/src/zexus/zpm/__init__.py +15 -0
- package/src/zexus/zpm/installer.py +116 -0
- package/src/zexus/zpm/package_manager.py +208 -0
- package/src/zexus/zpm/publisher.py +98 -0
- package/src/zexus/zpm/registry.py +110 -0
- package/src/zexus.egg-info/PKG-INFO +2235 -0
- package/src/zexus.egg-info/SOURCES.txt +876 -0
- package/src/zexus.egg-info/dependency_links.txt +1 -0
- package/src/zexus.egg-info/entry_points.txt +3 -0
- package/src/zexus.egg-info/not-zip-safe +1 -0
- package/src/zexus.egg-info/requires.txt +14 -0
- package/src/zexus.egg-info/top_level.txt +2 -0
- package/zexus.json +14 -0
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
# lexer.py (ENHANCED WITH PHASE 1 KEYWORDS)
|
|
2
|
+
from .zexus_token import *
|
|
3
|
+
from .error_reporter import get_error_reporter, SyntaxError as ZexusSyntaxError
|
|
4
|
+
|
|
5
|
+
class Lexer:
|
|
6
|
+
def __init__(self, source_code, filename="<stdin>"):
|
|
7
|
+
self.input = source_code
|
|
8
|
+
self.position = 0
|
|
9
|
+
self.read_position = 0
|
|
10
|
+
self.ch = ""
|
|
11
|
+
self.in_embedded_block = False
|
|
12
|
+
self.line = 1
|
|
13
|
+
self.column = 1
|
|
14
|
+
self.filename = filename
|
|
15
|
+
# Hint for parser: when '(' starts a lambda parameter list that is
|
|
16
|
+
# immediately followed by '=>', this flag will be set for the token
|
|
17
|
+
# produced for that '('. Parser can check and consume accordingly.
|
|
18
|
+
self._next_paren_has_lambda = False
|
|
19
|
+
|
|
20
|
+
# Register source with error reporter
|
|
21
|
+
self.error_reporter = get_error_reporter()
|
|
22
|
+
self.error_reporter.register_source(filename, source_code)
|
|
23
|
+
|
|
24
|
+
self.read_char()
|
|
25
|
+
|
|
26
|
+
def read_char(self):
|
|
27
|
+
if self.read_position >= len(self.input):
|
|
28
|
+
self.ch = ""
|
|
29
|
+
else:
|
|
30
|
+
self.ch = self.input[self.read_position]
|
|
31
|
+
|
|
32
|
+
# Update line and column tracking
|
|
33
|
+
if self.ch == '\n':
|
|
34
|
+
self.line += 1
|
|
35
|
+
self.column = 1
|
|
36
|
+
else:
|
|
37
|
+
self.column += 1
|
|
38
|
+
|
|
39
|
+
self.position = self.read_position
|
|
40
|
+
self.read_position += 1
|
|
41
|
+
|
|
42
|
+
def peek_char(self):
|
|
43
|
+
if self.read_position >= len(self.input):
|
|
44
|
+
return ""
|
|
45
|
+
else:
|
|
46
|
+
return self.input[self.read_position]
|
|
47
|
+
|
|
48
|
+
def next_token(self):
|
|
49
|
+
self.skip_whitespace()
|
|
50
|
+
|
|
51
|
+
# CRITICAL FIX: Skip single line comments (both # and // styles)
|
|
52
|
+
if self.ch == '#' and self.peek_char() != '{':
|
|
53
|
+
self.skip_comment()
|
|
54
|
+
return self.next_token()
|
|
55
|
+
|
|
56
|
+
# NEW: Handle // style comments
|
|
57
|
+
if self.ch == '/' and self.peek_char() == '/':
|
|
58
|
+
self.skip_double_slash_comment()
|
|
59
|
+
return self.next_token()
|
|
60
|
+
|
|
61
|
+
tok = None
|
|
62
|
+
current_line = self.line
|
|
63
|
+
current_column = self.column
|
|
64
|
+
|
|
65
|
+
if self.ch == '=':
|
|
66
|
+
# Equality '=='
|
|
67
|
+
if self.peek_char() == '=':
|
|
68
|
+
ch = self.ch
|
|
69
|
+
self.read_char()
|
|
70
|
+
literal = ch + self.ch
|
|
71
|
+
tok = Token(EQ, literal)
|
|
72
|
+
tok.line = current_line
|
|
73
|
+
tok.column = current_column
|
|
74
|
+
# Arrow '=>' (treat as lambda shorthand)
|
|
75
|
+
elif self.peek_char() == '>':
|
|
76
|
+
ch = self.ch
|
|
77
|
+
self.read_char()
|
|
78
|
+
literal = ch + self.ch
|
|
79
|
+
tok = Token(LAMBDA, literal)
|
|
80
|
+
tok.line = current_line
|
|
81
|
+
tok.column = current_column
|
|
82
|
+
else:
|
|
83
|
+
tok = Token(ASSIGN, self.ch)
|
|
84
|
+
tok.line = current_line
|
|
85
|
+
tok.column = current_column
|
|
86
|
+
elif self.ch == '!':
|
|
87
|
+
if self.peek_char() == '=':
|
|
88
|
+
ch = self.ch
|
|
89
|
+
self.read_char()
|
|
90
|
+
literal = ch + self.ch
|
|
91
|
+
tok = Token(NOT_EQ, literal)
|
|
92
|
+
tok.line = current_line
|
|
93
|
+
tok.column = current_column
|
|
94
|
+
else:
|
|
95
|
+
tok = Token(BANG, self.ch)
|
|
96
|
+
tok.line = current_line
|
|
97
|
+
tok.column = current_column
|
|
98
|
+
elif self.ch == '&':
|
|
99
|
+
if self.peek_char() == '&':
|
|
100
|
+
ch = self.ch
|
|
101
|
+
self.read_char()
|
|
102
|
+
literal = ch + self.ch
|
|
103
|
+
tok = Token(AND, literal)
|
|
104
|
+
tok.line = current_line
|
|
105
|
+
tok.column = current_column
|
|
106
|
+
else:
|
|
107
|
+
# Single '&' is not supported - suggest using '&&'
|
|
108
|
+
error = self.error_reporter.report_error(
|
|
109
|
+
ZexusSyntaxError,
|
|
110
|
+
f"Unexpected character '{self.ch}'",
|
|
111
|
+
line=current_line,
|
|
112
|
+
column=current_column,
|
|
113
|
+
filename=self.filename,
|
|
114
|
+
suggestion="Did you mean '&&' for logical AND?"
|
|
115
|
+
)
|
|
116
|
+
raise error
|
|
117
|
+
elif self.ch == '|':
|
|
118
|
+
if self.peek_char() == '|':
|
|
119
|
+
ch = self.ch
|
|
120
|
+
self.read_char()
|
|
121
|
+
literal = ch + self.ch
|
|
122
|
+
tok = Token(OR, literal)
|
|
123
|
+
tok.line = current_line
|
|
124
|
+
tok.column = current_column
|
|
125
|
+
else:
|
|
126
|
+
# Single '|' is not supported - suggest using '||'
|
|
127
|
+
error = self.error_reporter.report_error(
|
|
128
|
+
ZexusSyntaxError,
|
|
129
|
+
f"Unexpected character '{self.ch}'",
|
|
130
|
+
line=current_line,
|
|
131
|
+
column=current_column,
|
|
132
|
+
filename=self.filename,
|
|
133
|
+
suggestion="Did you mean '||' for logical OR?"
|
|
134
|
+
)
|
|
135
|
+
raise error
|
|
136
|
+
elif self.ch == '<':
|
|
137
|
+
if self.peek_char() == '=':
|
|
138
|
+
ch = self.ch
|
|
139
|
+
self.read_char()
|
|
140
|
+
literal = ch + self.ch
|
|
141
|
+
tok = Token(LTE, literal)
|
|
142
|
+
tok.line = current_line
|
|
143
|
+
tok.column = current_column
|
|
144
|
+
elif self.peek_char() == '<':
|
|
145
|
+
ch = self.ch
|
|
146
|
+
self.read_char()
|
|
147
|
+
literal = ch + self.ch
|
|
148
|
+
tok = Token(IMPORT_OP, literal)
|
|
149
|
+
tok.line = current_line
|
|
150
|
+
tok.column = current_column
|
|
151
|
+
else:
|
|
152
|
+
tok = Token(LT, self.ch)
|
|
153
|
+
tok.line = current_line
|
|
154
|
+
tok.column = current_column
|
|
155
|
+
elif self.ch == '>':
|
|
156
|
+
if self.peek_char() == '=':
|
|
157
|
+
ch = self.ch
|
|
158
|
+
self.read_char()
|
|
159
|
+
literal = ch + self.ch
|
|
160
|
+
tok = Token(GTE, literal)
|
|
161
|
+
tok.line = current_line
|
|
162
|
+
tok.column = current_column
|
|
163
|
+
elif self.peek_char() == '>':
|
|
164
|
+
ch = self.ch
|
|
165
|
+
self.read_char()
|
|
166
|
+
literal = ch + self.ch
|
|
167
|
+
tok = Token(APPEND, literal)
|
|
168
|
+
tok.line = current_line
|
|
169
|
+
tok.column = current_column
|
|
170
|
+
else:
|
|
171
|
+
tok = Token(GT, self.ch)
|
|
172
|
+
tok.line = current_line
|
|
173
|
+
tok.column = current_column
|
|
174
|
+
elif self.ch == '?':
|
|
175
|
+
# Check for nullish coalescing '??'
|
|
176
|
+
if self.peek_char() == '?':
|
|
177
|
+
ch = self.ch
|
|
178
|
+
self.read_char()
|
|
179
|
+
literal = ch + self.ch
|
|
180
|
+
tok = Token(NULLISH, literal)
|
|
181
|
+
tok.line = current_line
|
|
182
|
+
tok.column = current_column
|
|
183
|
+
else:
|
|
184
|
+
tok = Token(QUESTION, self.ch)
|
|
185
|
+
tok.line = current_line
|
|
186
|
+
tok.column = current_column
|
|
187
|
+
elif self.ch == '"':
|
|
188
|
+
string_literal = self.read_string()
|
|
189
|
+
tok = Token(STRING, string_literal)
|
|
190
|
+
tok.line = current_line
|
|
191
|
+
tok.column = current_column
|
|
192
|
+
elif self.ch == '[':
|
|
193
|
+
tok = Token(LBRACKET, self.ch)
|
|
194
|
+
tok.line = current_line
|
|
195
|
+
tok.column = current_column
|
|
196
|
+
elif self.ch == ']':
|
|
197
|
+
tok = Token(RBRACKET, self.ch)
|
|
198
|
+
tok.line = current_line
|
|
199
|
+
tok.column = current_column
|
|
200
|
+
elif self.ch == '@':
|
|
201
|
+
tok = Token(AT, self.ch)
|
|
202
|
+
tok.line = current_line
|
|
203
|
+
tok.column = current_column
|
|
204
|
+
elif self.ch == '(':
|
|
205
|
+
# Quick char-level scan: detect if this '(' pairs with a ')' that
|
|
206
|
+
# is followed by '=>' (arrow). If so, set a hint flag so parser
|
|
207
|
+
# can treat the parentheses as a lambda-parameter list.
|
|
208
|
+
try:
|
|
209
|
+
src = self.input
|
|
210
|
+
i = self.position
|
|
211
|
+
depth = 0
|
|
212
|
+
found = False
|
|
213
|
+
while i < len(src):
|
|
214
|
+
c = src[i]
|
|
215
|
+
if c == '(':
|
|
216
|
+
depth += 1
|
|
217
|
+
elif c == ')':
|
|
218
|
+
depth -= 1
|
|
219
|
+
if depth == 0:
|
|
220
|
+
# look ahead for '=>' skipping whitespace
|
|
221
|
+
j = i + 1
|
|
222
|
+
while j < len(src) and src[j].isspace():
|
|
223
|
+
j += 1
|
|
224
|
+
if j + 1 < len(src) and src[j] == '=' and src[j + 1] == '>':
|
|
225
|
+
found = True
|
|
226
|
+
break
|
|
227
|
+
i += 1
|
|
228
|
+
self._next_paren_has_lambda = found
|
|
229
|
+
except Exception:
|
|
230
|
+
self._next_paren_has_lambda = False
|
|
231
|
+
|
|
232
|
+
tok = Token(LPAREN, self.ch)
|
|
233
|
+
tok.line = current_line
|
|
234
|
+
tok.column = current_column
|
|
235
|
+
elif self.ch == ')':
|
|
236
|
+
tok = Token(RPAREN, self.ch)
|
|
237
|
+
tok.line = current_line
|
|
238
|
+
tok.column = current_column
|
|
239
|
+
elif self.ch == '{':
|
|
240
|
+
# Check if this might be start of embedded block
|
|
241
|
+
lookback = self.input[max(0, self.position-10):self.position]
|
|
242
|
+
if 'embedded' in lookback:
|
|
243
|
+
self.in_embedded_block = True
|
|
244
|
+
tok = Token(LBRACE, self.ch)
|
|
245
|
+
tok.line = current_line
|
|
246
|
+
tok.column = current_column
|
|
247
|
+
elif self.ch == '}':
|
|
248
|
+
if self.in_embedded_block:
|
|
249
|
+
self.in_embedded_block = False
|
|
250
|
+
tok = Token(RBRACE, self.ch)
|
|
251
|
+
tok.line = current_line
|
|
252
|
+
tok.column = current_column
|
|
253
|
+
elif self.ch == ',':
|
|
254
|
+
tok = Token(COMMA, self.ch)
|
|
255
|
+
tok.line = current_line
|
|
256
|
+
tok.column = current_column
|
|
257
|
+
elif self.ch == ';':
|
|
258
|
+
tok = Token(SEMICOLON, self.ch)
|
|
259
|
+
tok.line = current_line
|
|
260
|
+
tok.column = current_column
|
|
261
|
+
elif self.ch == ':':
|
|
262
|
+
tok = Token(COLON, self.ch)
|
|
263
|
+
tok.line = current_line
|
|
264
|
+
tok.column = current_column
|
|
265
|
+
elif self.ch == '+':
|
|
266
|
+
tok = Token(PLUS, self.ch)
|
|
267
|
+
tok.line = current_line
|
|
268
|
+
tok.column = current_column
|
|
269
|
+
elif self.ch == '-':
|
|
270
|
+
tok = Token(MINUS, self.ch)
|
|
271
|
+
tok.line = current_line
|
|
272
|
+
tok.column = current_column
|
|
273
|
+
elif self.ch == '*':
|
|
274
|
+
tok = Token(STAR, self.ch)
|
|
275
|
+
tok.line = current_line
|
|
276
|
+
tok.column = current_column
|
|
277
|
+
elif self.ch == '/':
|
|
278
|
+
# Check if this is division or comment
|
|
279
|
+
if self.peek_char() == '/':
|
|
280
|
+
# It's a // comment, handle above
|
|
281
|
+
self.skip_double_slash_comment()
|
|
282
|
+
return self.next_token()
|
|
283
|
+
else:
|
|
284
|
+
tok = Token(SLASH, self.ch)
|
|
285
|
+
tok.line = current_line
|
|
286
|
+
tok.column = current_column
|
|
287
|
+
elif self.ch == '%':
|
|
288
|
+
tok = Token(MOD, self.ch)
|
|
289
|
+
tok.line = current_line
|
|
290
|
+
tok.column = current_column
|
|
291
|
+
elif self.ch == '.':
|
|
292
|
+
tok = Token(DOT, self.ch)
|
|
293
|
+
tok.line = current_line
|
|
294
|
+
tok.column = current_column
|
|
295
|
+
elif self.ch == "":
|
|
296
|
+
tok = Token(EOF, "")
|
|
297
|
+
tok.line = current_line
|
|
298
|
+
tok.column = current_column
|
|
299
|
+
else:
|
|
300
|
+
if self.is_letter(self.ch):
|
|
301
|
+
literal = self.read_identifier()
|
|
302
|
+
|
|
303
|
+
if self.in_embedded_block:
|
|
304
|
+
token_type = IDENT
|
|
305
|
+
else:
|
|
306
|
+
token_type = self.lookup_ident(literal)
|
|
307
|
+
|
|
308
|
+
tok = Token(token_type, literal)
|
|
309
|
+
tok.line = current_line
|
|
310
|
+
tok.column = current_column
|
|
311
|
+
return tok
|
|
312
|
+
elif self.is_digit(self.ch):
|
|
313
|
+
num_literal = self.read_number()
|
|
314
|
+
if '.' in num_literal:
|
|
315
|
+
tok = Token(FLOAT, num_literal)
|
|
316
|
+
else:
|
|
317
|
+
tok = Token(INT, num_literal)
|
|
318
|
+
tok.line = current_line
|
|
319
|
+
tok.column = current_column
|
|
320
|
+
return tok
|
|
321
|
+
else:
|
|
322
|
+
if self.ch in ['\n', '\r']:
|
|
323
|
+
self.read_char()
|
|
324
|
+
return self.next_token()
|
|
325
|
+
# For embedded code, treat unknown printable chars as IDENT
|
|
326
|
+
if self.ch.isprintable():
|
|
327
|
+
literal = self.read_embedded_char()
|
|
328
|
+
tok = Token(IDENT, literal)
|
|
329
|
+
tok.line = current_line
|
|
330
|
+
tok.column = current_column
|
|
331
|
+
return tok
|
|
332
|
+
# Unknown character - report helpful error
|
|
333
|
+
char_desc = f"'{self.ch}'" if self.ch.isprintable() else f"'\\x{ord(self.ch):02x}'"
|
|
334
|
+
error = self.error_reporter.report_error(
|
|
335
|
+
ZexusSyntaxError,
|
|
336
|
+
f"Unexpected character {char_desc}",
|
|
337
|
+
line=current_line,
|
|
338
|
+
column=current_column,
|
|
339
|
+
filename=self.filename,
|
|
340
|
+
suggestion="Remove or replace this character with valid Zexus syntax."
|
|
341
|
+
)
|
|
342
|
+
raise error
|
|
343
|
+
|
|
344
|
+
self.read_char()
|
|
345
|
+
return tok
|
|
346
|
+
|
|
347
|
+
def read_embedded_char(self):
|
|
348
|
+
"""Read a single character as identifier for embedded code compatibility"""
|
|
349
|
+
char = self.ch
|
|
350
|
+
self.read_char()
|
|
351
|
+
return char
|
|
352
|
+
|
|
353
|
+
def skip_comment(self):
|
|
354
|
+
"""Skip # style comments"""
|
|
355
|
+
while self.ch != '\n' and self.ch != "":
|
|
356
|
+
self.read_char()
|
|
357
|
+
self.skip_whitespace()
|
|
358
|
+
|
|
359
|
+
def skip_double_slash_comment(self):
|
|
360
|
+
"""Skip // style comments"""
|
|
361
|
+
# Consume the first '/'
|
|
362
|
+
self.read_char()
|
|
363
|
+
# Consume the second '/'
|
|
364
|
+
self.read_char()
|
|
365
|
+
# Skip until end of line
|
|
366
|
+
while self.ch != '\n' and self.ch != "":
|
|
367
|
+
self.read_char()
|
|
368
|
+
self.skip_whitespace()
|
|
369
|
+
|
|
370
|
+
def read_string(self):
|
|
371
|
+
start_position = self.position + 1
|
|
372
|
+
start_line = self.line
|
|
373
|
+
start_column = self.column
|
|
374
|
+
result = []
|
|
375
|
+
while True:
|
|
376
|
+
self.read_char()
|
|
377
|
+
if self.ch == "":
|
|
378
|
+
# End of input - unclosed string
|
|
379
|
+
error = self.error_reporter.report_error(
|
|
380
|
+
ZexusSyntaxError,
|
|
381
|
+
"Unterminated string literal",
|
|
382
|
+
line=start_line,
|
|
383
|
+
column=start_column,
|
|
384
|
+
filename=self.filename,
|
|
385
|
+
suggestion="Add a closing quote \" to terminate the string."
|
|
386
|
+
)
|
|
387
|
+
raise error
|
|
388
|
+
elif self.ch == '\\':
|
|
389
|
+
# Escape sequence - read next character
|
|
390
|
+
self.read_char()
|
|
391
|
+
if self.ch == '':
|
|
392
|
+
error = self.error_reporter.report_error(
|
|
393
|
+
ZexusSyntaxError,
|
|
394
|
+
"Incomplete escape sequence at end of file",
|
|
395
|
+
line=self.line,
|
|
396
|
+
column=self.column,
|
|
397
|
+
filename=self.filename,
|
|
398
|
+
suggestion="Remove the backslash or complete the escape sequence."
|
|
399
|
+
)
|
|
400
|
+
raise error
|
|
401
|
+
# Map escape sequences to their actual characters
|
|
402
|
+
escape_map = {
|
|
403
|
+
'n': '\n',
|
|
404
|
+
't': '\t',
|
|
405
|
+
'r': '\r',
|
|
406
|
+
'\\': '\\',
|
|
407
|
+
'"': '"',
|
|
408
|
+
"'": "'"
|
|
409
|
+
}
|
|
410
|
+
result.append(escape_map.get(self.ch, self.ch))
|
|
411
|
+
elif self.ch == '"':
|
|
412
|
+
# End of string
|
|
413
|
+
break
|
|
414
|
+
else:
|
|
415
|
+
result.append(self.ch)
|
|
416
|
+
return ''.join(result)
|
|
417
|
+
|
|
418
|
+
def read_identifier(self):
|
|
419
|
+
start_position = self.position
|
|
420
|
+
while self.is_letter(self.ch) or self.is_digit(self.ch):
|
|
421
|
+
self.read_char()
|
|
422
|
+
return self.input[start_position:self.position]
|
|
423
|
+
|
|
424
|
+
def read_number(self):
|
|
425
|
+
start_position = self.position
|
|
426
|
+
is_float = False
|
|
427
|
+
|
|
428
|
+
# Read integer part
|
|
429
|
+
while self.is_digit(self.ch):
|
|
430
|
+
self.read_char()
|
|
431
|
+
|
|
432
|
+
# Check for decimal point
|
|
433
|
+
if self.ch == '.':
|
|
434
|
+
is_float = True
|
|
435
|
+
self.read_char()
|
|
436
|
+
# Read fractional part
|
|
437
|
+
while self.is_digit(self.ch):
|
|
438
|
+
self.read_char()
|
|
439
|
+
|
|
440
|
+
number_str = self.input[start_position:self.position]
|
|
441
|
+
return number_str
|
|
442
|
+
|
|
443
|
+
def lookup_ident(self, ident):
|
|
444
|
+
# keyword lookup mapping (string -> token constant)
|
|
445
|
+
keywords = {
|
|
446
|
+
"let": LET,
|
|
447
|
+
"const": CONST, # NEW: Const keyword for immutable variables
|
|
448
|
+
"data": DATA, # NEW: Data keyword for dataclass definitions
|
|
449
|
+
"print": PRINT,
|
|
450
|
+
"if": IF,
|
|
451
|
+
"then": THEN, # NEW: Then keyword for if-then-else expressions
|
|
452
|
+
"elif": ELIF, # NEW: Elif keyword for else-if conditionals
|
|
453
|
+
"else": ELSE,
|
|
454
|
+
"true": TRUE,
|
|
455
|
+
"false": FALSE,
|
|
456
|
+
"null": NULL,
|
|
457
|
+
"return": RETURN,
|
|
458
|
+
"for": FOR,
|
|
459
|
+
"each": EACH,
|
|
460
|
+
"in": IN,
|
|
461
|
+
"action": ACTION,
|
|
462
|
+
"function": FUNCTION,
|
|
463
|
+
"while": WHILE,
|
|
464
|
+
"use": USE,
|
|
465
|
+
"exactly": EXACTLY,
|
|
466
|
+
"embedded": EMBEDDED,
|
|
467
|
+
"export": EXPORT,
|
|
468
|
+
"lambda": LAMBDA,
|
|
469
|
+
"debug": DEBUG, # DUAL-MODE: Works as both statement (debug x;) and function (debug(x))
|
|
470
|
+
"try": TRY, # NEW: Try keyword
|
|
471
|
+
"catch": CATCH, # NEW: Catch keyword
|
|
472
|
+
"continue": CONTINUE, # NEW: Continue on error keyword
|
|
473
|
+
"break": BREAK, # NEW: Break loop keyword
|
|
474
|
+
"throw": THROW, # NEW: Throw error keyword
|
|
475
|
+
"external": EXTERNAL, # NEW: External keyword
|
|
476
|
+
"from": FROM, # NEW: From keyword
|
|
477
|
+
"screen": SCREEN, # NEW: renderer keyword
|
|
478
|
+
"component": COMPONENT, # NEW: renderer keyword
|
|
479
|
+
"theme": THEME, # NEW: renderer keyword
|
|
480
|
+
"canvas": CANVAS, # NEW (optional recognition)
|
|
481
|
+
"graphics": GRAPHICS, # NEW (optional recognition)
|
|
482
|
+
"animation": ANIMATION, # NEW (optional recognition)
|
|
483
|
+
"clock": CLOCK, # NEW (optional recognition)
|
|
484
|
+
"async": ASYNC,
|
|
485
|
+
"await": AWAIT,
|
|
486
|
+
"channel": CHANNEL, # NEW: Channel for concurrent communication
|
|
487
|
+
"send": SEND, # NEW: Send to channel
|
|
488
|
+
"receive": RECEIVE, # NEW: Receive from channel
|
|
489
|
+
"atomic": ATOMIC, # NEW: Atomic operations
|
|
490
|
+
"event": EVENT,
|
|
491
|
+
"emit": EMIT,
|
|
492
|
+
"enum": ENUM,
|
|
493
|
+
"protocol": PROTOCOL,
|
|
494
|
+
"import": IMPORT,
|
|
495
|
+
# Modifiers
|
|
496
|
+
"public": PUBLIC,
|
|
497
|
+
"private": PRIVATE,
|
|
498
|
+
"sealed": SEALED,
|
|
499
|
+
"secure": SECURE,
|
|
500
|
+
"pure": PURE,
|
|
501
|
+
"view": VIEW,
|
|
502
|
+
"payable": PAYABLE,
|
|
503
|
+
"modifier": MODIFIER,
|
|
504
|
+
# NEW: Entity, Verify, Contract, Protect
|
|
505
|
+
"entity": ENTITY,
|
|
506
|
+
"verify": VERIFY,
|
|
507
|
+
"contract": CONTRACT,
|
|
508
|
+
"protect": PROTECT,
|
|
509
|
+
"implements": IMPLEMENTS,
|
|
510
|
+
"this": THIS,
|
|
511
|
+
"interface": INTERFACE,
|
|
512
|
+
"capability": CAPABILITY, # NEW: Capability keyword for security
|
|
513
|
+
"grant": GRANT, # NEW: Grant keyword for capability grants
|
|
514
|
+
"revoke": REVOKE, # NEW: Revoke keyword for capability revocation
|
|
515
|
+
"module": MODULE, # NEW: Module keyword for code organization
|
|
516
|
+
"package": PACKAGE, # NEW: Package keyword for package definition
|
|
517
|
+
"using": USING, # NEW: Using keyword for resource management
|
|
518
|
+
"type_alias": TYPE_ALIAS, # NEW: Type alias keyword for type definitions
|
|
519
|
+
"seal": SEAL, # NEW: Seal keyword for immutable objects
|
|
520
|
+
"audit": AUDIT, # NEW: Audit keyword for compliance logging
|
|
521
|
+
"restrict": RESTRICT, # NEW: Restrict keyword for field-level access control
|
|
522
|
+
"sandbox": SANDBOX, # NEW: Sandbox keyword for isolated execution
|
|
523
|
+
"trail": TRAIL, # NEW: Trail keyword for real-time logging
|
|
524
|
+
# Advanced features
|
|
525
|
+
"middleware": MIDDLEWARE,
|
|
526
|
+
"auth": AUTH,
|
|
527
|
+
"throttle": THROTTLE,
|
|
528
|
+
"cache": CACHE,
|
|
529
|
+
# Blockchain & Smart Contract keywords
|
|
530
|
+
"ledger": LEDGER, # Immutable state ledger
|
|
531
|
+
"state": STATE, # State management
|
|
532
|
+
"revert": REVERT, # Revert transaction
|
|
533
|
+
# NOTE: "tx" removed as keyword - users can use it as variable name
|
|
534
|
+
# Only uppercase "TX" is reserved for transaction context
|
|
535
|
+
"limit": LIMIT, # Gas/resource limit
|
|
536
|
+
# NOTE: hash, signature, verify_sig, gas are BUILTINS, not keywords
|
|
537
|
+
# NEW: Persistent storage keywords
|
|
538
|
+
"persistent": PERSISTENT, # NEW: Persistent keyword
|
|
539
|
+
"storage": STORAGE, # NEW: Storage keyword
|
|
540
|
+
"require": REQUIRE, # Already defined in zexus_token.py
|
|
541
|
+
# Logical operators as keywords (alternative to && and ||)
|
|
542
|
+
"and": AND, # Logical AND (alternative to &&)
|
|
543
|
+
"or": OR, # Logical OR (alternative to ||)
|
|
544
|
+
# Performance optimization keywords
|
|
545
|
+
"native": NATIVE, # Performance: call C/C++ code
|
|
546
|
+
"gc": GC, # Performance: control garbage collection
|
|
547
|
+
"inline": INLINE, # Performance: function inlining
|
|
548
|
+
"buffer": BUFFER, # Performance: direct memory access
|
|
549
|
+
"simd": SIMD, # Performance: vector operations
|
|
550
|
+
"defer": DEFER, # Convenience: cleanup code execution
|
|
551
|
+
"pattern": PATTERN, # Convenience: pattern matching
|
|
552
|
+
"match": MATCH, # Match expression for pattern matching
|
|
553
|
+
"enum": ENUM, # Advanced: type-safe enumerations
|
|
554
|
+
"stream": STREAM, # Advanced: event streaming
|
|
555
|
+
"watch": WATCH, # Advanced: reactive state management
|
|
556
|
+
"log": LOG, # Output logging to file
|
|
557
|
+
"inject": INJECT, # Advanced: dependency injection
|
|
558
|
+
"validate": VALIDATE, # Data validation
|
|
559
|
+
"sanitize": SANITIZE, # Data sanitization
|
|
560
|
+
}
|
|
561
|
+
return keywords.get(ident, IDENT)
|
|
562
|
+
|
|
563
|
+
def is_letter(self, char):
|
|
564
|
+
return 'a' <= char <= 'z' or 'A' <= char <= 'Z' or char == '_'
|
|
565
|
+
|
|
566
|
+
def is_digit(self, char):
|
|
567
|
+
return '0' <= char <= '9'
|
|
568
|
+
|
|
569
|
+
def skip_whitespace(self):
|
|
570
|
+
while self.ch in [' ', '\t', '\n', '\r']:
|
|
571
|
+
self.read_char()
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Centralized logging for Zexus.
|
|
3
|
+
Provides consistent debug/info/warn/error logging with level control and formatting.
|
|
4
|
+
"""
|
|
5
|
+
import sys
|
|
6
|
+
from . import config
|
|
7
|
+
|
|
8
|
+
# ANSI color codes
|
|
9
|
+
COLORS = {
|
|
10
|
+
'reset': '\033[0m',
|
|
11
|
+
'red': '\033[31m',
|
|
12
|
+
'green': '\033[32m',
|
|
13
|
+
'yellow': '\033[33m',
|
|
14
|
+
'blue': '\033[34m',
|
|
15
|
+
'magenta': '\033[35m',
|
|
16
|
+
'cyan': '\033[36m'
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
# Icons for different log types
|
|
20
|
+
ICONS = {
|
|
21
|
+
'debug': 'đ',
|
|
22
|
+
'info': 'âšī¸ ',
|
|
23
|
+
'warn': 'â ī¸ ',
|
|
24
|
+
'error': 'â',
|
|
25
|
+
'success': 'â
',
|
|
26
|
+
'parser': 'đ§',
|
|
27
|
+
'eval': 'đ',
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
class Logger:
|
|
31
|
+
def __init__(self, module_name):
|
|
32
|
+
self.module_name = module_name
|
|
33
|
+
self.config = config.config # Use the singleton
|
|
34
|
+
|
|
35
|
+
def _should_log(self, level):
|
|
36
|
+
try:
|
|
37
|
+
return self.config.should_log(level)
|
|
38
|
+
except Exception:
|
|
39
|
+
# If config check fails, only allow errors
|
|
40
|
+
return level == 'error'
|
|
41
|
+
|
|
42
|
+
def _format(self, level, message, data=None, color=None):
|
|
43
|
+
icon = ICONS.get(level, '')
|
|
44
|
+
prefix = f"{icon} [{self.module_name.upper()}]"
|
|
45
|
+
if color and sys.stdout.isatty(): # Only use colors if terminal supports it
|
|
46
|
+
prefix = f"{COLORS[color]}{prefix}{COLORS['reset']}"
|
|
47
|
+
|
|
48
|
+
if data is not None:
|
|
49
|
+
if isinstance(data, (list, tuple)) and len(data) > 0:
|
|
50
|
+
# Format sequences nicely
|
|
51
|
+
items = [str(x) for x in data]
|
|
52
|
+
data_str = f"[{', '.join(items)}]"
|
|
53
|
+
else:
|
|
54
|
+
data_str = str(data)
|
|
55
|
+
return f"{prefix} {message}: {data_str}"
|
|
56
|
+
return f"{prefix} {message}"
|
|
57
|
+
|
|
58
|
+
def debug(self, message, data=None):
|
|
59
|
+
if self._should_log('debug'):
|
|
60
|
+
print(self._format('debug', message, data, color='cyan'))
|
|
61
|
+
|
|
62
|
+
def info(self, message, data=None):
|
|
63
|
+
if self._should_log('info'):
|
|
64
|
+
print(self._format('info', message, data, color='blue'))
|
|
65
|
+
|
|
66
|
+
def warn(self, message, data=None):
|
|
67
|
+
if self._should_log('warn'):
|
|
68
|
+
print(self._format('warn', message, data, color='yellow'))
|
|
69
|
+
|
|
70
|
+
def error(self, message, data=None):
|
|
71
|
+
if self._should_log('error'):
|
|
72
|
+
print(self._format('error', message, data, color='red'), file=sys.stderr)
|
|
73
|
+
|
|
74
|
+
def success(self, message, data=None):
|
|
75
|
+
if self._should_log('info'):
|
|
76
|
+
print(self._format('success', message, data, color='green'))
|
|
77
|
+
|
|
78
|
+
def parser(self, message, data=None):
|
|
79
|
+
if self._should_log('debug'):
|
|
80
|
+
print(self._format('parser', message, data, color='magenta'))
|
|
81
|
+
|
|
82
|
+
def eval(self, message, data=None):
|
|
83
|
+
if self._should_log('debug'):
|
|
84
|
+
print(self._format('eval', message, data, color='blue'))
|
|
85
|
+
|
|
86
|
+
# Pre-configured loggers for main subsystems
|
|
87
|
+
parser_log = Logger('parser')
|
|
88
|
+
eval_log = Logger('eval')
|
|
89
|
+
runtime_log = Logger('runtime')
|