jaclang 0.7.29__py3-none-any.whl → 0.7.31__py3-none-any.whl
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.
Potentially problematic release.
This version of jaclang might be problematic. Click here for more details.
- jaclang/__init__.py +419 -3
- jaclang/compiler/__init__.py +1 -1
- jaclang/compiler/absyntree.py +15 -5
- jaclang/compiler/compile.py +1 -1
- jaclang/compiler/constant.py +4 -5
- jaclang/compiler/jac.lark +227 -180
- jaclang/compiler/parser.py +1335 -1826
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +2 -2
- jaclang/compiler/passes/main/import_pass.py +3 -2
- jaclang/compiler/passes/main/pyast_gen_pass.py +570 -747
- jaclang/compiler/passes/main/tests/test_import_pass.py +4 -1
- jaclang/compiler/passes/main/tests/test_type_check_pass.py +6 -3
- jaclang/compiler/passes/tool/jac_formatter_pass.py +0 -1
- jaclang/compiler/tests/test_importer.py +45 -1
- jaclang/compiler/tests/test_parser.py +13 -5
- jaclang/plugin/builtin.py +11 -0
- jaclang/plugin/default.py +55 -20
- jaclang/plugin/feature.py +14 -5
- jaclang/plugin/spec.py +16 -6
- jaclang/plugin/tests/fixtures/graph_purger.jac +2 -0
- jaclang/plugin/tests/fixtures/other_root_access.jac +1 -0
- jaclang/plugin/tests/fixtures/savable_object.jac +2 -0
- jaclang/plugin/tests/test_jaseci.py +1 -1
- jaclang/runtimelib/architype.py +11 -21
- jaclang/runtimelib/context.py +25 -9
- jaclang/runtimelib/importer.py +26 -3
- jaclang/runtimelib/machine.py +2 -2
- jaclang/settings.py +2 -0
- jaclang/tests/fixtures/create_dynamic_architype.jac +1 -1
- jaclang/tests/fixtures/nested_impls.jac +55 -0
- jaclang/tests/test_cli.py +1 -1
- jaclang/tests/test_language.py +27 -13
- jaclang/tests/test_reference.py +2 -2
- jaclang/utils/helpers.py +4 -3
- jaclang/utils/test.py +2 -2
- jaclang/utils/tests/test_lang_tools.py +4 -2
- {jaclang-0.7.29.dist-info → jaclang-0.7.31.dist-info}/METADATA +2 -2
- {jaclang-0.7.29.dist-info → jaclang-0.7.31.dist-info}/RECORD +40 -39
- {jaclang-0.7.29.dist-info → jaclang-0.7.31.dist-info}/WHEEL +1 -1
- {jaclang-0.7.29.dist-info → jaclang-0.7.31.dist-info}/entry_points.txt +0 -0
jaclang/__init__.py
CHANGED
|
@@ -1,12 +1,428 @@
|
|
|
1
1
|
"""The Jac Programming Language."""
|
|
2
2
|
|
|
3
|
+
import inspect
|
|
4
|
+
import os
|
|
5
|
+
from abc import ABCMeta, abstractmethod as abstract
|
|
6
|
+
from dataclasses import dataclass, field as dc_field
|
|
7
|
+
from types import ModuleType
|
|
8
|
+
from typing import (
|
|
9
|
+
Any,
|
|
10
|
+
Callable,
|
|
11
|
+
ClassVar,
|
|
12
|
+
Dict,
|
|
13
|
+
Generic,
|
|
14
|
+
Tuple,
|
|
15
|
+
Type,
|
|
16
|
+
TypeGuard,
|
|
17
|
+
TypeVar,
|
|
18
|
+
cast,
|
|
19
|
+
override,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
from jaclang.plugin.builtin import dotgen, jid, jobj # noqa: F401
|
|
3
23
|
from jaclang.plugin.default import JacFeatureImpl
|
|
4
|
-
from jaclang.plugin.feature import JacFeature, plugin_manager
|
|
24
|
+
from jaclang.plugin.feature import JacFeature as Jac, plugin_manager
|
|
25
|
+
from jaclang.plugin.spec import EdgeDir
|
|
26
|
+
from jaclang.runtimelib.context import ExecutionContext
|
|
27
|
+
|
|
28
|
+
__all__ = [
|
|
29
|
+
# Jac types.
|
|
30
|
+
"Obj",
|
|
31
|
+
"Walker",
|
|
32
|
+
"Node",
|
|
33
|
+
"Edge",
|
|
34
|
+
"JacList",
|
|
35
|
+
"EdgeDir",
|
|
36
|
+
"Root",
|
|
37
|
+
# Decorators.
|
|
38
|
+
"with_entry",
|
|
39
|
+
"with_exit",
|
|
40
|
+
"jac_test",
|
|
41
|
+
"abstract",
|
|
42
|
+
"override",
|
|
43
|
+
# Functions.
|
|
44
|
+
"jac_import",
|
|
45
|
+
"field",
|
|
46
|
+
# Builtin.
|
|
47
|
+
"Jac",
|
|
48
|
+
"root",
|
|
49
|
+
"static",
|
|
50
|
+
"dotgen",
|
|
51
|
+
"jid",
|
|
52
|
+
"jobj",
|
|
53
|
+
]
|
|
5
54
|
|
|
6
|
-
jac_import = JacFeature.jac_import
|
|
7
55
|
|
|
56
|
+
# ----------------------------------------------------------------------------
|
|
57
|
+
# Plugin Initialization.
|
|
58
|
+
# ----------------------------------------------------------------------------
|
|
8
59
|
|
|
9
60
|
plugin_manager.register(JacFeatureImpl)
|
|
10
61
|
plugin_manager.load_setuptools_entrypoints("jac")
|
|
11
62
|
|
|
12
|
-
|
|
63
|
+
T = TypeVar("T")
|
|
64
|
+
S = TypeVar("S") # S is a subtype of T.
|
|
65
|
+
|
|
66
|
+
# ----------------------------------------------------------------------------
|
|
67
|
+
# Meta classes.
|
|
68
|
+
# ----------------------------------------------------------------------------
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# Since the meta class of the architypes are changine the base class to it's
|
|
72
|
+
# suitable archi type, If a class doesn't have a parent class (ie. by default
|
|
73
|
+
# inherit from object) __bases__ will be immutable. So we need to use a dummy
|
|
74
|
+
# parent class to make it mutable.
|
|
75
|
+
#
|
|
76
|
+
# Reference: https://stackoverflow.com/a/9639512/10846399
|
|
77
|
+
#
|
|
78
|
+
class _ArchiTypeBase:
|
|
79
|
+
|
|
80
|
+
def __init__(self, *args, **kwargs) -> None: # noqa: ANN002, ANN003
|
|
81
|
+
"""Initialize Jac architype base."""
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class JacMeta(ABCMeta):
|
|
85
|
+
"""Common metaclass for Jac types."""
|
|
86
|
+
|
|
87
|
+
def __new__( # noqa: D102
|
|
88
|
+
cls,
|
|
89
|
+
name: str,
|
|
90
|
+
bases: Tuple[Type, ...],
|
|
91
|
+
dct: Dict[str, Any],
|
|
92
|
+
) -> "JacMeta":
|
|
93
|
+
|
|
94
|
+
# We have added this "__init__" to the jac base class just to make the type checkers happy.
|
|
95
|
+
# Actually the dataclass decorator will create an __init__ function and assign it here bellow.
|
|
96
|
+
if bases == (_ArchiTypeBase,) and "__init__" in dct:
|
|
97
|
+
del dct["__init__"]
|
|
98
|
+
|
|
99
|
+
on_entry, on_exit = [], []
|
|
100
|
+
for func in dct.values():
|
|
101
|
+
if hasattr(func, "__jac_entry"):
|
|
102
|
+
on_entry.append(Jac.DSFunc(func.__name__, func))
|
|
103
|
+
if hasattr(func, "__jac_exit"):
|
|
104
|
+
on_exit.append(Jac.DSFunc(func.__name__, func))
|
|
105
|
+
|
|
106
|
+
inst = super().__new__(cls, name, bases, dct)
|
|
107
|
+
inst = dataclass(eq=False)(inst) # type: ignore [arg-type, assignment]
|
|
108
|
+
inst = inst._MAKE_FN(on_entry, on_exit)(inst) # type: ignore [assignment, attr-defined]
|
|
109
|
+
return inst
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
# ----------------------------------------------------------------------------
|
|
113
|
+
# Base classes.
|
|
114
|
+
# ----------------------------------------------------------------------------
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class Obj(_ArchiTypeBase, metaclass=JacMeta):
|
|
118
|
+
"""Base class for all the jac object types."""
|
|
119
|
+
|
|
120
|
+
_MAKE_FN = Jac.make_obj
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class Walker(_ArchiTypeBase, metaclass=JacMeta):
|
|
124
|
+
"""Base class for all the jac walker types."""
|
|
125
|
+
|
|
126
|
+
_MAKE_FN = Jac.make_walker
|
|
127
|
+
|
|
128
|
+
def spawn(self, node: "Node | Root") -> "Walker":
|
|
129
|
+
"""Spawn a new node from the walker."""
|
|
130
|
+
return Jac.spawn_call(self, node) # type: ignore [arg-type, return-value]
|
|
131
|
+
|
|
132
|
+
def ignore(
|
|
133
|
+
self,
|
|
134
|
+
expr: """(
|
|
135
|
+
Root
|
|
136
|
+
| Node
|
|
137
|
+
| Edge
|
|
138
|
+
| list[Node | Root | Edge]
|
|
139
|
+
| JacList[Node | Root | Edge]
|
|
140
|
+
)""",
|
|
141
|
+
) -> bool:
|
|
142
|
+
"""Ignore statement."""
|
|
143
|
+
return Jac.ignore(self, expr) # type: ignore [arg-type]
|
|
144
|
+
|
|
145
|
+
def visit(
|
|
146
|
+
self,
|
|
147
|
+
expr: """(
|
|
148
|
+
Root
|
|
149
|
+
| Node
|
|
150
|
+
| Edge
|
|
151
|
+
| list[Node | Root | Edge]
|
|
152
|
+
| JacList[Node | Root | Edge]
|
|
153
|
+
)""",
|
|
154
|
+
) -> bool:
|
|
155
|
+
"""Visit statement."""
|
|
156
|
+
return Jac.visit_node(self, expr) # type: ignore [arg-type]
|
|
157
|
+
|
|
158
|
+
def disengage(self) -> None:
|
|
159
|
+
"""Disengage statement."""
|
|
160
|
+
Jac.disengage(self) # type: ignore [arg-type]
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class Node(_ArchiTypeBase, metaclass=JacMeta):
|
|
164
|
+
"""Base class for all the jac node types."""
|
|
165
|
+
|
|
166
|
+
_MAKE_FN = Jac.make_node
|
|
167
|
+
|
|
168
|
+
def spawn(self, archi: Walker) -> "Walker":
|
|
169
|
+
"""Spawn a new node from the walker."""
|
|
170
|
+
return Jac.spawn_call(self, archi) # type: ignore [arg-type, return-value]
|
|
171
|
+
|
|
172
|
+
def connect(
|
|
173
|
+
self,
|
|
174
|
+
node: "Node | Root | JacList[Node | Root]",
|
|
175
|
+
edge: "type[Edge] | Edge | None" = None,
|
|
176
|
+
unidir: bool = False,
|
|
177
|
+
conn_assign: tuple[tuple, tuple] | None = None,
|
|
178
|
+
edges_only: bool = False,
|
|
179
|
+
) -> "JacList[Node | Root| Edge]":
|
|
180
|
+
"""Connect the current node to another node."""
|
|
181
|
+
# TODO: The above edge type should be reviewed, as the bellow can also take None, Edge, type[Edge].
|
|
182
|
+
ret = Jac.connect(
|
|
183
|
+
left=self, # type: ignore [arg-type]
|
|
184
|
+
right=node, # type: ignore [arg-type]
|
|
185
|
+
edge_spec=Jac.build_edge(
|
|
186
|
+
is_undirected=unidir, conn_type=edge, conn_assign=conn_assign # type: ignore [arg-type]
|
|
187
|
+
),
|
|
188
|
+
edges_only=edges_only,
|
|
189
|
+
)
|
|
190
|
+
return JacList(ret) # type: ignore [arg-type]
|
|
191
|
+
|
|
192
|
+
def disconnect(
|
|
193
|
+
self,
|
|
194
|
+
node: "Node | Root | JacList[Node | Root]",
|
|
195
|
+
edge: "type[Edge] | None" = None,
|
|
196
|
+
dir: EdgeDir = EdgeDir.OUT,
|
|
197
|
+
) -> bool:
|
|
198
|
+
"""Disconnect the current node from the graph."""
|
|
199
|
+
filter_func = None
|
|
200
|
+
if edge:
|
|
201
|
+
filter_func = lambda edges: [ # noqa: E731
|
|
202
|
+
ed for ed in edges if isinstance(ed, edge)
|
|
203
|
+
]
|
|
204
|
+
return Jac.disconnect(self, node, dir=dir, filter_func=filter_func) # type: ignore [arg-type]
|
|
205
|
+
|
|
206
|
+
def refs(
|
|
207
|
+
self,
|
|
208
|
+
edge: "type[Edge] | None" = None,
|
|
209
|
+
cond: "Callable[[Edge], bool] | None" = None,
|
|
210
|
+
target: "Node | Root | JacList[Node|Root] | None" = None,
|
|
211
|
+
dir: EdgeDir = EdgeDir.OUT,
|
|
212
|
+
edges_only: bool = False,
|
|
213
|
+
) -> "JacList[Node | Root | Edge]":
|
|
214
|
+
"""Return all the connected nodes / edges."""
|
|
215
|
+
filter_func = (
|
|
216
|
+
(
|
|
217
|
+
lambda edges: ( # noqa: E731
|
|
218
|
+
[ed for ed in edges if isinstance(ed, edge) if not cond or cond(ed)]
|
|
219
|
+
)
|
|
220
|
+
)
|
|
221
|
+
if edge
|
|
222
|
+
else None
|
|
223
|
+
)
|
|
224
|
+
ret = plugin_manager.hook.edge_ref(
|
|
225
|
+
node_obj=self,
|
|
226
|
+
target_obj=target,
|
|
227
|
+
dir=dir,
|
|
228
|
+
filter_func=filter_func,
|
|
229
|
+
edges_only=edges_only,
|
|
230
|
+
)
|
|
231
|
+
return JacList(ret)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class Root(_ArchiTypeBase, metaclass=JacMeta):
|
|
235
|
+
"""Base class for jac root type."""
|
|
236
|
+
|
|
237
|
+
_MAKE_FN = Jac.make_root
|
|
238
|
+
|
|
239
|
+
def spawn(self, archi: Walker) -> "Walker":
|
|
240
|
+
"""Spawn a new node from the walker."""
|
|
241
|
+
return Jac.spawn_call(self, archi) # type: ignore [arg-type, return-value]
|
|
242
|
+
|
|
243
|
+
def connect(
|
|
244
|
+
self,
|
|
245
|
+
node: "Node | Root | JacList[Node | Root]",
|
|
246
|
+
edge: "type[Edge] | Edge | None" = None,
|
|
247
|
+
unidir: bool = False,
|
|
248
|
+
conn_assign: tuple[tuple, tuple] | None = None,
|
|
249
|
+
edges_only: bool = False,
|
|
250
|
+
) -> "JacList[Node | Root| Edge]":
|
|
251
|
+
"""Connect the current node to another node."""
|
|
252
|
+
# TODO: The above edge type should be reviewed, as the bellow can also take None, Edge, type[Edge].
|
|
253
|
+
ret = Jac.connect(
|
|
254
|
+
left=self, # type: ignore [arg-type]
|
|
255
|
+
right=node, # type: ignore [arg-type]
|
|
256
|
+
edge_spec=Jac.build_edge(
|
|
257
|
+
is_undirected=unidir, conn_type=edge, conn_assign=conn_assign # type: ignore [arg-type]
|
|
258
|
+
),
|
|
259
|
+
edges_only=edges_only,
|
|
260
|
+
)
|
|
261
|
+
return JacList(ret) # type: ignore [arg-type]
|
|
262
|
+
|
|
263
|
+
def disconnect(
|
|
264
|
+
self,
|
|
265
|
+
node: "Node | Root | JacList[Node | Root]",
|
|
266
|
+
edge: "type[Edge] | None" = None,
|
|
267
|
+
dir: EdgeDir = EdgeDir.OUT,
|
|
268
|
+
) -> bool:
|
|
269
|
+
"""Disconnect the current node from the graph."""
|
|
270
|
+
filter_func = None
|
|
271
|
+
if edge:
|
|
272
|
+
filter_func = lambda edges: [ # noqa: E731
|
|
273
|
+
ed for ed in edges if isinstance(ed, edge)
|
|
274
|
+
]
|
|
275
|
+
return Jac.disconnect(self, node, dir=dir, filter_func=filter_func) # type: ignore [arg-type]
|
|
276
|
+
|
|
277
|
+
def refs(
|
|
278
|
+
self,
|
|
279
|
+
edge: "type[Edge] | None" = None,
|
|
280
|
+
cond: "Callable[[Edge], bool] | None" = None,
|
|
281
|
+
target: "Node | Root | JacList[Node|Root] | None" = None,
|
|
282
|
+
dir: EdgeDir = EdgeDir.OUT,
|
|
283
|
+
edges_only: bool = False,
|
|
284
|
+
) -> "JacList[Node | Root | Edge]":
|
|
285
|
+
"""Return all the connected nodes / edges."""
|
|
286
|
+
filter_func = (
|
|
287
|
+
(
|
|
288
|
+
lambda edges: ( # noqa: E731
|
|
289
|
+
[ed for ed in edges if isinstance(ed, edge) if not cond or cond(ed)]
|
|
290
|
+
)
|
|
291
|
+
)
|
|
292
|
+
if edge
|
|
293
|
+
else None
|
|
294
|
+
)
|
|
295
|
+
ret = plugin_manager.hook.edge_ref(
|
|
296
|
+
node_obj=self,
|
|
297
|
+
target_obj=target,
|
|
298
|
+
dir=dir,
|
|
299
|
+
filter_func=filter_func,
|
|
300
|
+
edges_only=edges_only,
|
|
301
|
+
)
|
|
302
|
+
return JacList(ret)
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
class Edge(_ArchiTypeBase, metaclass=JacMeta):
|
|
306
|
+
"""Base class for all the jac edge types."""
|
|
307
|
+
|
|
308
|
+
_MAKE_FN = Jac.make_edge
|
|
309
|
+
|
|
310
|
+
def spawn(self, archi: Walker) -> "Walker":
|
|
311
|
+
"""Spawn a new node from the walker."""
|
|
312
|
+
return Jac.spawn_call(self, archi) # type: ignore [arg-type, return-value]
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
class GenericEdge(_ArchiTypeBase, metaclass=JacMeta):
|
|
316
|
+
"""Base class for jac root type."""
|
|
317
|
+
|
|
318
|
+
_MAKE_FN = Jac.make_generic_edge
|
|
319
|
+
|
|
320
|
+
def spawn(self, archi: Walker) -> "Walker":
|
|
321
|
+
"""Spawn a new node from the walker."""
|
|
322
|
+
return Jac.spawn_call(self, archi) # type: ignore [arg-type, return-value]
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
class JacList(Generic[T], list[T]):
|
|
326
|
+
"""List with jac methods."""
|
|
327
|
+
|
|
328
|
+
# Reuse the methods.
|
|
329
|
+
connect = Node.connect
|
|
330
|
+
disconnect = Node.disconnect
|
|
331
|
+
refs = Node.refs
|
|
332
|
+
|
|
333
|
+
def filter(
|
|
334
|
+
self,
|
|
335
|
+
ty: Type[S] | None = None,
|
|
336
|
+
fn: Callable[[T | S], TypeGuard[S]] | None = None,
|
|
337
|
+
) -> "JacList[S]":
|
|
338
|
+
"""Filter comprehension."""
|
|
339
|
+
if ty and fn:
|
|
340
|
+
return JacList([item for item in self if isinstance(item, ty) and fn(item)])
|
|
341
|
+
if ty:
|
|
342
|
+
return JacList([item for item in self if isinstance(item, ty)])
|
|
343
|
+
if fn:
|
|
344
|
+
return JacList(list(filter(fn, self)))
|
|
345
|
+
return cast(JacList[S], self)
|
|
346
|
+
|
|
347
|
+
def assign(self, attrs: tuple[str], values: tuple[Any]) -> "JacList[T]":
|
|
348
|
+
"""Assign Comprehension."""
|
|
349
|
+
return JacList(Jac.assign_compr(self, (attrs, values)))
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
# ----------------------------------------------------------------------------
|
|
353
|
+
# Decorators.
|
|
354
|
+
# ----------------------------------------------------------------------------
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
def with_entry(func: Callable) -> Callable:
|
|
358
|
+
"""Mark a method as jac entry with this decorator."""
|
|
359
|
+
setattr(func, "__jac_entry", True) # noqa: B010
|
|
360
|
+
return func
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def with_exit(func: Callable) -> Callable:
|
|
364
|
+
"""Mark a method as jac exit with this decorator."""
|
|
365
|
+
setattr(func, "__jac_exit", True) # noqa: B010
|
|
366
|
+
return func
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
# ----------------------------------------------------------------------------
|
|
370
|
+
# Functions.
|
|
371
|
+
# ----------------------------------------------------------------------------
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def jac_import(
|
|
375
|
+
target: str,
|
|
376
|
+
lng: str | None = "jac",
|
|
377
|
+
base_path: str | None = None,
|
|
378
|
+
absorb: bool = False,
|
|
379
|
+
cachable: bool = True,
|
|
380
|
+
alias: str | None = None,
|
|
381
|
+
override_name: str | None = None,
|
|
382
|
+
items: dict[str, str | None] | None = None,
|
|
383
|
+
reload_module: bool | None = False,
|
|
384
|
+
) -> tuple[ModuleType, ...]:
|
|
385
|
+
"""Import a module."""
|
|
386
|
+
base_path = base_path or os.path.dirname(inspect.stack()[1].filename)
|
|
387
|
+
return Jac.jac_import(
|
|
388
|
+
target=target,
|
|
389
|
+
lng=lng,
|
|
390
|
+
base_path=base_path,
|
|
391
|
+
absorb=absorb,
|
|
392
|
+
cachable=cachable,
|
|
393
|
+
mdl_alias=alias,
|
|
394
|
+
override_name=override_name,
|
|
395
|
+
items=items,
|
|
396
|
+
reload_module=reload_module,
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
def field(
|
|
401
|
+
value: T = None, # type: ignore [assignment]
|
|
402
|
+
gen: Callable[[], T] | None = None,
|
|
403
|
+
postinit: bool = False,
|
|
404
|
+
) -> T:
|
|
405
|
+
"""Set the default value to jac architype dataclass."""
|
|
406
|
+
if postinit:
|
|
407
|
+
return dc_field(init=False)
|
|
408
|
+
gen = gen or (lambda: value) # noqa: E731
|
|
409
|
+
return Jac.has_instance_default(gen_func=gen) # type: ignore
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
# ----------------------------------------------------------------------------
|
|
413
|
+
# Builtin.
|
|
414
|
+
# ----------------------------------------------------------------------------
|
|
415
|
+
|
|
416
|
+
jac_test = Jac.create_test
|
|
417
|
+
static = ClassVar
|
|
418
|
+
|
|
419
|
+
root = cast(Root, Jac.get_root())
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
# Listen to context change and update the above global root here.
|
|
423
|
+
def _update_root() -> None:
|
|
424
|
+
global root
|
|
425
|
+
root = cast(Root, ExecutionContext.get_root())
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
ExecutionContext.on_ctx_change.append(lambda ctx: _update_root())
|
jaclang/compiler/__init__.py
CHANGED
|
@@ -55,7 +55,7 @@ TOKEN_MAP.update(
|
|
|
55
55
|
"CARROW_L": "<++", "CARROW_R": "++>", "GLOBAL_OP": ":global:",
|
|
56
56
|
"NONLOCAL_OP": ":nonlocal:", "WALKER_OP": ":walker:", "NODE_OP": ":node:",
|
|
57
57
|
"EDGE_OP": ":edge:", "CLASS_OP": ":class:", "OBJECT_OP": ":obj:",
|
|
58
|
-
"TYPE_OP": "`", "ABILITY_OP": ":can:", "
|
|
58
|
+
"TYPE_OP": "`", "ABILITY_OP": ":can:", "NULL_OK": "?",
|
|
59
59
|
"KW_OR": "|", "ARROW_BI": "<-->", "ARROW_L": "<--",
|
|
60
60
|
"ARROW_R": "-->", "ARROW_L_P1": "<-:", "ARROW_R_P2": ":->",
|
|
61
61
|
"ARROW_L_P2": ":-", "ARROW_R_P1": "-:", "CARROW_BI": "<++>",
|
jaclang/compiler/absyntree.py
CHANGED
|
@@ -462,7 +462,7 @@ class NameAtom(AtomExpr, EnumBlockStmt):
|
|
|
462
462
|
self._sym: Optional[Symbol] = None
|
|
463
463
|
self._sym_name: str = ""
|
|
464
464
|
self._sym_category: SymbolType = SymbolType.UNKNOWN
|
|
465
|
-
self._py_ctx_func: Type[ast3.
|
|
465
|
+
self._py_ctx_func: Type[ast3.expr_context] = ast3.Load
|
|
466
466
|
AtomExpr.__init__(self)
|
|
467
467
|
|
|
468
468
|
@property
|
|
@@ -492,12 +492,12 @@ class NameAtom(AtomExpr, EnumBlockStmt):
|
|
|
492
492
|
return ret_type
|
|
493
493
|
|
|
494
494
|
@property
|
|
495
|
-
def py_ctx_func(self) -> Type[ast3.
|
|
495
|
+
def py_ctx_func(self) -> Type[ast3.expr_context]:
|
|
496
496
|
"""Get python context function."""
|
|
497
497
|
return self._py_ctx_func
|
|
498
498
|
|
|
499
499
|
@py_ctx_func.setter
|
|
500
|
-
def py_ctx_func(self, py_ctx_func: Type[ast3.
|
|
500
|
+
def py_ctx_func(self, py_ctx_func: Type[ast3.expr_context]) -> None:
|
|
501
501
|
"""Set python context function."""
|
|
502
502
|
self._py_ctx_func = py_ctx_func
|
|
503
503
|
|
|
@@ -1013,8 +1013,9 @@ class ModulePath(AstSymbolNode):
|
|
|
1013
1013
|
target = self.dot_path_str
|
|
1014
1014
|
if target_item:
|
|
1015
1015
|
target += f".{target_item}"
|
|
1016
|
-
base_path =
|
|
1017
|
-
|
|
1016
|
+
base_path = (
|
|
1017
|
+
os.getenv("JACPATH") or os.path.dirname(self.loc.mod_path) or os.getcwd()
|
|
1018
|
+
)
|
|
1018
1019
|
parts = target.split(".")
|
|
1019
1020
|
traversal_levels = self.level - 1 if self.level > 0 else 0
|
|
1020
1021
|
actual_parts = parts[traversal_levels:]
|
|
@@ -1026,6 +1027,15 @@ class ModulePath(AstSymbolNode):
|
|
|
1026
1027
|
if os.path.exists(relative_path + ".jac")
|
|
1027
1028
|
else relative_path
|
|
1028
1029
|
)
|
|
1030
|
+
jacpath = os.getenv("JACPATH")
|
|
1031
|
+
if not os.path.exists(relative_path) and jacpath:
|
|
1032
|
+
name_to_find = actual_parts[-1] + ".jac"
|
|
1033
|
+
|
|
1034
|
+
# Walk through the single path in JACPATH
|
|
1035
|
+
for root, _, files in os.walk(jacpath):
|
|
1036
|
+
if name_to_find in files:
|
|
1037
|
+
relative_path = os.path.join(root, name_to_find)
|
|
1038
|
+
break
|
|
1029
1039
|
return relative_path
|
|
1030
1040
|
|
|
1031
1041
|
def normalize(self, deep: bool = False) -> bool:
|
jaclang/compiler/compile.py
CHANGED
|
@@ -31,7 +31,7 @@ def jac_file_to_pass(
|
|
|
31
31
|
schedule: list[Type[Pass]] = pass_schedule,
|
|
32
32
|
) -> Pass:
|
|
33
33
|
"""Convert a Jac file to an AST."""
|
|
34
|
-
with open(file_path) as file:
|
|
34
|
+
with open(file_path, "r", encoding="utf-8") as file:
|
|
35
35
|
return jac_str_to_pass(
|
|
36
36
|
jac_str=file.read(),
|
|
37
37
|
file_path=file_path,
|
jaclang/compiler/constant.py
CHANGED
|
@@ -91,8 +91,9 @@ class Constants(StrEnum):
|
|
|
91
91
|
"""Token constants for Jac."""
|
|
92
92
|
|
|
93
93
|
JAC_LANG_IMP = "jac"
|
|
94
|
-
HERE = "_jac_here_"
|
|
95
|
-
|
|
94
|
+
HERE = "here" # "_jac_here_"
|
|
95
|
+
JAC_CHECK = "_check"
|
|
96
|
+
JAC_FEATURE = "Jac" # "_Jac"
|
|
96
97
|
ROOT = f"{JAC_FEATURE}.get_root()"
|
|
97
98
|
EDGES_TO_NODE = "__jac__.edges_to_nodes"
|
|
98
99
|
EDGE_REF = "__jac__.edge_ref"
|
|
@@ -152,7 +153,6 @@ class Tokens(str, Enum):
|
|
|
152
153
|
|
|
153
154
|
FLOAT = "FLOAT"
|
|
154
155
|
STRING = "STRING"
|
|
155
|
-
DOC_STRING = "DOC_STRING"
|
|
156
156
|
PYNLINE = "PYNLINE"
|
|
157
157
|
BOOL = "BOOL"
|
|
158
158
|
INT = "INT"
|
|
@@ -315,7 +315,6 @@ class Tokens(str, Enum):
|
|
|
315
315
|
ABILITY_OP = "ABILITY_OP"
|
|
316
316
|
A_PIPE_FWD = "A_PIPE_FWD"
|
|
317
317
|
A_PIPE_BKWD = "A_PIPE_BKWD"
|
|
318
|
-
ELVIS_OP = "ELVIS_OP"
|
|
319
318
|
RETURN_HINT = "RETURN_HINT"
|
|
320
319
|
NULL_OK = "NULL_OK"
|
|
321
320
|
DECOR_OP = "DECOR_OP"
|
|
@@ -356,7 +355,7 @@ colors = [
|
|
|
356
355
|
"#F0FFF0",
|
|
357
356
|
"#F5E5FF",
|
|
358
357
|
"#FFFFE0",
|
|
359
|
-
"#D2FEFF
|
|
358
|
+
"#D2FEFF",
|
|
360
359
|
"#E8FFD7",
|
|
361
360
|
"#FFDEAD",
|
|
362
361
|
"#FFF0F5",
|