jaclang 0.7.23__py3-none-any.whl → 0.7.26__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.

Files changed (68) hide show
  1. jaclang/cli/cli.py +46 -29
  2. jaclang/compiler/__init__.py +2 -2
  3. jaclang/compiler/absyntree.py +114 -66
  4. jaclang/compiler/codeloc.py +7 -2
  5. jaclang/compiler/compile.py +10 -3
  6. jaclang/compiler/jac.lark +4 -1
  7. jaclang/compiler/parser.py +63 -43
  8. jaclang/compiler/passes/ir_pass.py +2 -2
  9. jaclang/compiler/passes/main/def_impl_match_pass.py +83 -0
  10. jaclang/compiler/passes/main/def_use_pass.py +1 -2
  11. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +146 -123
  12. jaclang/compiler/passes/main/import_pass.py +6 -2
  13. jaclang/compiler/passes/main/pyast_gen_pass.py +46 -20
  14. jaclang/compiler/passes/main/pyast_load_pass.py +56 -41
  15. jaclang/compiler/passes/main/pyjac_ast_link_pass.py +7 -7
  16. jaclang/compiler/passes/main/registry_pass.py +3 -12
  17. jaclang/compiler/passes/main/sym_tab_build_pass.py +1 -2
  18. jaclang/compiler/passes/main/tests/fixtures/defn_decl_mismatch.jac +19 -0
  19. jaclang/compiler/passes/main/tests/fixtures/fstrings.jac +2 -0
  20. jaclang/compiler/passes/main/tests/fixtures/uninitialized_hasvars.jac +26 -0
  21. jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +66 -0
  22. jaclang/compiler/passes/main/tests/test_def_use_pass.py +3 -3
  23. jaclang/compiler/passes/main/tests/test_registry_pass.py +2 -10
  24. jaclang/compiler/passes/main/tests/test_type_check_pass.py +1 -1
  25. jaclang/compiler/passes/tool/jac_formatter_pass.py +2 -2
  26. jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +3 -3
  27. jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +3 -3
  28. jaclang/compiler/passes/transform.py +27 -3
  29. jaclang/compiler/passes/utils/mypy_ast_build.py +246 -26
  30. jaclang/compiler/symtable.py +6 -0
  31. jaclang/compiler/tests/test_importer.py +2 -2
  32. jaclang/compiler/tests/test_parser.py +7 -1
  33. jaclang/langserve/engine.py +14 -12
  34. jaclang/langserve/server.py +7 -2
  35. jaclang/langserve/tests/test_server.py +1 -1
  36. jaclang/langserve/utils.py +17 -3
  37. jaclang/plugin/default.py +80 -43
  38. jaclang/plugin/feature.py +12 -2
  39. jaclang/plugin/plugin.md +471 -0
  40. jaclang/plugin/spec.py +14 -1
  41. jaclang/plugin/tests/fixtures/graph_purger.jac +101 -0
  42. jaclang/plugin/tests/fixtures/other_root_access.jac +9 -0
  43. jaclang/plugin/tests/test_jaseci.py +126 -6
  44. jaclang/runtimelib/architype.py +12 -1
  45. jaclang/runtimelib/context.py +2 -0
  46. jaclang/runtimelib/importer.py +7 -2
  47. jaclang/runtimelib/machine.py +21 -6
  48. jaclang/runtimelib/memory.py +5 -1
  49. jaclang/settings.py +3 -0
  50. jaclang/tests/fixtures/architype_def_bug.jac +17 -0
  51. jaclang/tests/fixtures/builtin_dotgen.jac +6 -6
  52. jaclang/tests/fixtures/decl_defn_param_name.jac +19 -0
  53. jaclang/tests/fixtures/enum_inside_archtype.jac +16 -11
  54. jaclang/tests/fixtures/expr_type.jac +54 -0
  55. jaclang/tests/fixtures/glob_multivar_statement.jac +15 -0
  56. jaclang/tests/fixtures/multi_dim_array_split.jac +19 -0
  57. jaclang/tests/fixtures/registry.jac +20 -8
  58. jaclang/tests/foo/__init__.jac +0 -0
  59. jaclang/tests/main.jac +2 -0
  60. jaclang/tests/test_cli.py +86 -4
  61. jaclang/tests/test_language.py +104 -27
  62. jaclang/utils/helpers.py +92 -14
  63. jaclang/utils/lang_tools.py +6 -2
  64. jaclang/utils/treeprinter.py +4 -2
  65. {jaclang-0.7.23.dist-info → jaclang-0.7.26.dist-info}/METADATA +2 -1
  66. {jaclang-0.7.23.dist-info → jaclang-0.7.26.dist-info}/RECORD +68 -57
  67. {jaclang-0.7.23.dist-info → jaclang-0.7.26.dist-info}/WHEEL +1 -1
  68. {jaclang-0.7.23.dist-info → jaclang-0.7.26.dist-info}/entry_points.txt +0 -0
jaclang/plugin/default.py CHANGED
@@ -6,13 +6,12 @@ import ast as ast3
6
6
  import fnmatch
7
7
  import html
8
8
  import os
9
- import pickle
10
9
  import types
11
10
  from collections import OrderedDict
12
11
  from dataclasses import field
13
12
  from functools import wraps
14
13
  from logging import getLogger
15
- from typing import Any, Callable, Mapping, Optional, Sequence, Type, Union
14
+ from typing import Any, Callable, Mapping, Optional, Sequence, Type, Union, cast
16
15
  from uuid import UUID
17
16
 
18
17
  from jaclang.compiler.constant import colors
@@ -42,6 +41,7 @@ from jaclang.runtimelib.constructs import (
42
41
  )
43
42
  from jaclang.runtimelib.importer import ImportPathSpec, JacImporter, PythonImporter
44
43
  from jaclang.runtimelib.machine import JacMachine, JacProgram
44
+ from jaclang.runtimelib.memory import Shelf, ShelfStorage
45
45
  from jaclang.runtimelib.utils import collect_node_connections, traverse_graph
46
46
 
47
47
 
@@ -54,6 +54,13 @@ logger = getLogger(__name__)
54
54
  class JacAccessValidationImpl:
55
55
  """Jac Access Validation Implementations."""
56
56
 
57
+ @staticmethod
58
+ @hookimpl
59
+ def elevate_root() -> None:
60
+ """Elevate context root to system_root."""
61
+ jctx = Jac.get_context()
62
+ jctx.root = jctx.system_root
63
+
57
64
  @staticmethod
58
65
  @hookimpl
59
66
  def allow_root(
@@ -380,7 +387,8 @@ class JacWalkerImpl:
380
387
  if walker.next:
381
388
  current_node = walker.next[-1].architype
382
389
  for i in warch._jac_entry_funcs_:
383
- if not i.trigger:
390
+ trigger = i.get_funcparam_annotations(i.func)
391
+ if not trigger:
384
392
  if i.func:
385
393
  i.func(warch, current_node)
386
394
  else:
@@ -388,7 +396,8 @@ class JacWalkerImpl:
388
396
  while len(walker.next):
389
397
  if current_node := walker.next.pop(0).architype:
390
398
  for i in current_node._jac_entry_funcs_:
391
- if not i.trigger or isinstance(warch, i.trigger):
399
+ trigger = i.get_funcparam_annotations(i.func)
400
+ if not trigger or isinstance(warch, trigger):
392
401
  if i.func:
393
402
  i.func(current_node, warch)
394
403
  else:
@@ -396,27 +405,30 @@ class JacWalkerImpl:
396
405
  if walker.disengaged:
397
406
  return warch
398
407
  for i in warch._jac_entry_funcs_:
399
- if not i.trigger or isinstance(current_node, i.trigger):
400
- if i.func and i.trigger:
408
+ trigger = i.get_funcparam_annotations(i.func)
409
+ if not trigger or isinstance(current_node, trigger):
410
+ if i.func and trigger:
401
411
  i.func(warch, current_node)
402
- elif not i.trigger:
412
+ elif not trigger:
403
413
  continue
404
414
  else:
405
415
  raise ValueError(f"No function {i.name} to call.")
406
416
  if walker.disengaged:
407
417
  return warch
408
418
  for i in warch._jac_exit_funcs_:
409
- if not i.trigger or isinstance(current_node, i.trigger):
410
- if i.func and i.trigger:
419
+ trigger = i.get_funcparam_annotations(i.func)
420
+ if not trigger or isinstance(current_node, trigger):
421
+ if i.func and trigger:
411
422
  i.func(warch, current_node)
412
- elif not i.trigger:
423
+ elif not trigger:
413
424
  continue
414
425
  else:
415
426
  raise ValueError(f"No function {i.name} to call.")
416
427
  if walker.disengaged:
417
428
  return warch
418
429
  for i in current_node._jac_exit_funcs_:
419
- if not i.trigger or isinstance(warch, i.trigger):
430
+ trigger = i.get_funcparam_annotations(i.func)
431
+ if not trigger or isinstance(warch, trigger):
420
432
  if i.func:
421
433
  i.func(current_node, warch)
422
434
  else:
@@ -424,7 +436,8 @@ class JacWalkerImpl:
424
436
  if walker.disengaged:
425
437
  return warch
426
438
  for i in warch._jac_exit_funcs_:
427
- if not i.trigger:
439
+ trigger = i.get_funcparam_annotations(i.func)
440
+ if not trigger:
428
441
  if i.func:
429
442
  i.func(warch, current_node)
430
443
  else:
@@ -510,9 +523,10 @@ class JacBuiltinImpl:
510
523
  'fillcolor="invis", fontcolor="black"];\n'
511
524
  )
512
525
  for source, target, edge in connections:
526
+ edge_label = html.escape(str(edge.__jac__.architype))
513
527
  dot_content += (
514
528
  f"{visited_nodes.index(source)} -> {visited_nodes.index(target)} "
515
- f' [label="{html.escape(str(edge.__jac__.architype))} "];\n'
529
+ f' [label="{edge_label if "GenericEdge" not in edge_label else ""}"];\n'
516
530
  )
517
531
  for node_ in visited_nodes:
518
532
  color = (
@@ -560,6 +574,29 @@ class JacFeatureImpl(
560
574
  """Get current execution context."""
561
575
  return ExecutionContext.get()
562
576
 
577
+ @staticmethod
578
+ @hookimpl
579
+ def reset_graph(root: Optional[Root] = None) -> int:
580
+ """Purge current or target graph."""
581
+ ctx = Jac.get_context()
582
+ mem = cast(ShelfStorage, ctx.mem)
583
+ ranchor = root.__jac__ if root else ctx.root
584
+
585
+ deleted_count = 0
586
+ for anchor in (
587
+ anchors.values()
588
+ if isinstance(anchors := mem.__shelf__, Shelf)
589
+ else mem.__mem__.values()
590
+ ):
591
+ if anchor == ranchor or anchor.root != ranchor.id:
592
+ continue
593
+
594
+ if loaded_anchor := mem.find_by_id(anchor.id):
595
+ deleted_count += 1
596
+ Jac.destroy(loaded_anchor)
597
+
598
+ return deleted_count
599
+
563
600
  @staticmethod
564
601
  @hookimpl
565
602
  def get_object(id: str) -> Architype | None:
@@ -751,7 +788,9 @@ class JacFeatureImpl(
751
788
 
752
789
  jac_machine = JacMachine.get(base_path)
753
790
  if not jac_machine.jac_program:
754
- jac_machine.attach_program(JacProgram(mod_bundle=None, bytecode=None))
791
+ jac_machine.attach_program(
792
+ JacProgram(mod_bundle=None, bytecode=None, sem_ir=None)
793
+ )
755
794
 
756
795
  if lng == "py":
757
796
  import_result = PythonImporter(JacMachine.get()).run_import(spec)
@@ -800,7 +839,7 @@ class JacFeatureImpl(
800
839
  if mod_name.endswith(".test"):
801
840
  mod_name = mod_name[:-5]
802
841
  JacTestCheck.reset()
803
- Jac.jac_import(target=mod_name, base_path=base)
842
+ Jac.jac_import(target=mod_name, base_path=base, cachable=False)
804
843
  JacTestCheck.run_test(xit, maxfail, verbose)
805
844
  ret_count = JacTestCheck.failcount
806
845
  else:
@@ -854,8 +893,13 @@ class JacFeatureImpl(
854
893
 
855
894
  @staticmethod
856
895
  @hookimpl
857
- def report(expr: Any) -> Any: # noqa: ANN401
896
+ def report(expr: Any, custom: bool) -> None: # noqa: ANN401
858
897
  """Jac's report stmt feature."""
898
+ ctx = Jac.get_context()
899
+ if custom:
900
+ ctx.custom = expr
901
+ else:
902
+ ctx.reports.append(expr)
859
903
 
860
904
  @staticmethod
861
905
  @hookimpl
@@ -1059,16 +1103,14 @@ class JacFeatureImpl(
1059
1103
  file_loc: str, scope: str, attr: str, return_semstr: bool
1060
1104
  ) -> Optional[str]:
1061
1105
  """Jac's get_semstr_type feature."""
1106
+ from jaclang.compiler.semtable import SemInfo, SemScope, SemRegistry
1107
+ from jaclang.runtimelib.machine import JacMachine
1108
+
1062
1109
  _scope = SemScope.get_scope_from_str(scope)
1063
- with open(
1064
- os.path.join(
1065
- os.path.dirname(file_loc),
1066
- "__jac_gen__",
1067
- os.path.basename(file_loc).replace(".jac", ".registry.pkl"),
1068
- ),
1069
- "rb",
1070
- ) as f:
1071
- mod_registry: SemRegistry = pickle.load(f)
1110
+ jac_program = JacMachine.get().jac_program
1111
+ mod_registry: SemRegistry = (
1112
+ jac_program.sem_ir if jac_program is not None else SemRegistry()
1113
+ )
1072
1114
  _, attr_seminfo = mod_registry.lookup(_scope, attr)
1073
1115
  if attr_seminfo and isinstance(attr_seminfo, SemInfo):
1074
1116
  return attr_seminfo.semstr if return_semstr else attr_seminfo.type
@@ -1078,15 +1120,12 @@ class JacFeatureImpl(
1078
1120
  @hookimpl
1079
1121
  def obj_scope(file_loc: str, attr: str) -> str:
1080
1122
  """Jac's gather_scope feature."""
1081
- with open(
1082
- os.path.join(
1083
- os.path.dirname(file_loc),
1084
- "__jac_gen__",
1085
- os.path.basename(file_loc).replace(".jac", ".registry.pkl"),
1086
- ),
1087
- "rb",
1088
- ) as f:
1089
- mod_registry: SemRegistry = pickle.load(f)
1123
+ from jaclang.runtimelib.machine import JacMachine
1124
+
1125
+ jac_program = JacMachine.get().jac_program
1126
+ mod_registry: SemRegistry = (
1127
+ jac_program.sem_ir if jac_program is not None else SemRegistry()
1128
+ )
1090
1129
 
1091
1130
  attr_scope = None
1092
1131
  for x in attr.split("."):
@@ -1119,15 +1158,13 @@ class JacFeatureImpl(
1119
1158
  @hookimpl
1120
1159
  def get_sem_type(file_loc: str, attr: str) -> tuple[str | None, str | None]:
1121
1160
  """Jac's get_semstr_type implementation."""
1122
- with open(
1123
- os.path.join(
1124
- os.path.dirname(file_loc),
1125
- "__jac_gen__",
1126
- os.path.basename(file_loc).replace(".jac", ".registry.pkl"),
1127
- ),
1128
- "rb",
1129
- ) as f:
1130
- mod_registry: SemRegistry = pickle.load(f)
1161
+ from jaclang.runtimelib.machine import JacMachine
1162
+ from jaclang.compiler.semtable import SemInfo, SemScope
1163
+
1164
+ jac_program = JacMachine.get().jac_program
1165
+ mod_registry: SemRegistry = (
1166
+ jac_program.sem_ir if jac_program is not None else SemRegistry()
1167
+ )
1131
1168
 
1132
1169
  attr_scope = None
1133
1170
  for x in attr.split("."):
jaclang/plugin/feature.py CHANGED
@@ -41,6 +41,11 @@ from jaclang.plugin.spec import (
41
41
  class JacAccessValidation:
42
42
  """Jac Access Validation Specs."""
43
43
 
44
+ @staticmethod
45
+ def elevate_root() -> None:
46
+ """Elevate context root to system_root."""
47
+ plugin_manager.hook.elevate_root()
48
+
44
49
  @staticmethod
45
50
  def allow_root(
46
51
  architype: Architype,
@@ -254,6 +259,11 @@ class JacFeature(
254
259
  """Get current execution context."""
255
260
  return plugin_manager.hook.get_context()
256
261
 
262
+ @staticmethod
263
+ def reset_graph(root: Optional[Root] = None) -> int:
264
+ """Purge current or target graph."""
265
+ return plugin_manager.hook.reset_graph(root=root)
266
+
257
267
  @staticmethod
258
268
  def get_object(id: str) -> Architype | None:
259
269
  """Get object given id."""
@@ -371,9 +381,9 @@ class JacFeature(
371
381
  return plugin_manager.hook.has_instance_default(gen_func=gen_func)
372
382
 
373
383
  @staticmethod
374
- def report(expr: Any) -> Any: # noqa: ANN401
384
+ def report(expr: Any, custom: bool = False) -> None: # noqa: ANN401
375
385
  """Jac's report stmt feature."""
376
- return plugin_manager.hook.report(expr=expr)
386
+ plugin_manager.hook.report(expr=expr, custom=custom)
377
387
 
378
388
  @staticmethod
379
389
  def edge_ref(