jaclang 0.8.1__py3-none-any.whl → 0.8.3__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 (84) hide show
  1. jaclang/__init__.py +6 -0
  2. jaclang/cli/cli.py +21 -50
  3. jaclang/compiler/codeinfo.py +0 -1
  4. jaclang/compiler/constant.py +2 -0
  5. jaclang/compiler/jac.lark +17 -10
  6. jaclang/compiler/larkparse/jac_parser.py +2 -2
  7. jaclang/compiler/parser.py +34 -10
  8. jaclang/compiler/passes/main/__init__.py +2 -14
  9. jaclang/compiler/passes/main/annex_pass.py +2 -8
  10. jaclang/compiler/passes/main/cfg_build_pass.py +38 -12
  11. jaclang/compiler/passes/main/import_pass.py +3 -11
  12. jaclang/compiler/passes/main/pyast_gen_pass.py +246 -592
  13. jaclang/compiler/passes/main/sem_def_match_pass.py +67 -0
  14. jaclang/compiler/passes/main/sym_tab_build_pass.py +8 -0
  15. jaclang/compiler/passes/main/sym_tab_link_pass.py +2 -5
  16. jaclang/compiler/passes/main/tests/fixtures/sem_def_match.impl.jac +12 -0
  17. jaclang/compiler/passes/main/tests/fixtures/sem_def_match.jac +31 -0
  18. jaclang/compiler/passes/main/tests/test_cfg_build_pass.py +2 -8
  19. jaclang/compiler/passes/main/tests/test_decl_impl_match_pass.py +7 -8
  20. jaclang/compiler/passes/main/tests/test_import_pass.py +5 -18
  21. jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +2 -6
  22. jaclang/compiler/passes/main/tests/test_sem_def_match_pass.py +38 -0
  23. jaclang/compiler/passes/main/tests/test_sub_node_pass.py +1 -3
  24. jaclang/compiler/passes/main/tests/test_sym_tab_link_pass.py +20 -17
  25. jaclang/compiler/passes/tool/doc_ir_gen_pass.py +259 -106
  26. jaclang/compiler/passes/tool/jac_formatter_pass.py +2 -0
  27. jaclang/compiler/passes/tool/tests/fixtures/archetype_frmt.jac +14 -0
  28. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +5 -4
  29. jaclang/compiler/passes/tool/tests/fixtures/has_frmt.jac +13 -0
  30. jaclang/compiler/passes/tool/tests/fixtures/import_fmt.jac +6 -0
  31. jaclang/compiler/passes/tool/tests/fixtures/simple_walk_fmt.jac +3 -3
  32. jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +9 -0
  33. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +25 -3
  34. jaclang/compiler/passes/tool/tests/test_unparse_validate.py +2 -2
  35. jaclang/compiler/program.py +23 -60
  36. jaclang/compiler/tests/fixtures/pkg_import_lib_py/__init__.py +2 -8
  37. jaclang/compiler/tests/fixtures/pkg_import_lib_py/sub/__init__.py +1 -5
  38. jaclang/compiler/tests/test_importer.py +10 -13
  39. jaclang/compiler/unitree.py +88 -16
  40. jaclang/langserve/__init__.jac +1 -1
  41. jaclang/langserve/engine.jac +113 -108
  42. jaclang/langserve/server.jac +17 -2
  43. jaclang/langserve/tests/server_test/test_lang_serve.py +138 -46
  44. jaclang/langserve/tests/server_test/utils.py +35 -9
  45. jaclang/langserve/tests/test_sem_tokens.py +1 -1
  46. jaclang/langserve/tests/test_server.py +3 -7
  47. jaclang/runtimelib/archetype.py +127 -5
  48. jaclang/runtimelib/importer.py +51 -94
  49. jaclang/runtimelib/machine.py +391 -268
  50. jaclang/runtimelib/meta_importer.py +86 -0
  51. jaclang/runtimelib/tests/fixtures/graph_purger.jac +24 -26
  52. jaclang/runtimelib/tests/fixtures/other_root_access.jac +25 -16
  53. jaclang/runtimelib/tests/test_jaseci.py +3 -1
  54. jaclang/tests/fixtures/arch_rel_import_creation.jac +23 -23
  55. jaclang/tests/fixtures/async_ability.jac +43 -10
  56. jaclang/tests/fixtures/async_function.jac +18 -0
  57. jaclang/tests/fixtures/async_walker.jac +17 -12
  58. jaclang/tests/fixtures/create_dynamic_archetype.jac +25 -28
  59. jaclang/tests/fixtures/deep/deeper/deep_outer_import.jac +7 -4
  60. jaclang/tests/fixtures/deep/deeper/snd_lev.jac +2 -2
  61. jaclang/tests/fixtures/deep/deeper/snd_lev_dup.jac +6 -0
  62. jaclang/tests/fixtures/deep/one_lev.jac +2 -2
  63. jaclang/tests/fixtures/deep/one_lev_dup.jac +4 -3
  64. jaclang/tests/fixtures/dynamic_archetype.jac +19 -12
  65. jaclang/tests/fixtures/foo.jac +14 -22
  66. jaclang/tests/fixtures/jac_from_py.py +1 -1
  67. jaclang/tests/fixtures/jp_importer.jac +6 -6
  68. jaclang/tests/fixtures/jp_importer_auto.jac +5 -3
  69. jaclang/tests/fixtures/unicode_strings.jac +24 -0
  70. jaclang/tests/fixtures/walker_update.jac +5 -7
  71. jaclang/tests/test_language.py +138 -140
  72. jaclang/tests/test_reference.py +9 -4
  73. jaclang/tests/test_typecheck.py +13 -26
  74. jaclang/utils/lang_tools.py +7 -5
  75. jaclang/utils/module_resolver.py +23 -0
  76. {jaclang-0.8.1.dist-info → jaclang-0.8.3.dist-info}/METADATA +1 -1
  77. {jaclang-0.8.1.dist-info → jaclang-0.8.3.dist-info}/RECORD +79 -72
  78. jaclang/compiler/passes/main/tests/fixtures/main_err.jac +0 -6
  79. jaclang/compiler/passes/main/tests/fixtures/second_err.jac +0 -4
  80. jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +0 -644
  81. jaclang/compiler/passes/tool/tests/test_doc_ir_gen_pass.py +0 -29
  82. jaclang/tests/fixtures/deep/deeper/__init__.jac +0 -1
  83. {jaclang-0.8.1.dist-info → jaclang-0.8.3.dist-info}/WHEEL +0 -0
  84. {jaclang-0.8.1.dist-info → jaclang-0.8.3.dist-info}/entry_points.txt +0 -0
@@ -94,6 +94,8 @@ class JacFormatPass(Transform[uni.Module, uni.Module]):
94
94
  part_str = self.format_doc_ir(
95
95
  part, indent_level, current_line_budget, is_broken
96
96
  )
97
+ if part_str.startswith("\n"):
98
+ result = result.rstrip(" ")
97
99
  result += part_str
98
100
 
99
101
  if "\n" in part_str:
@@ -0,0 +1,14 @@
1
+ obj Anchor(ArchetypeProtocol) {
2
+ static def on_entry(cls: type, triggers: list[type]);
3
+ static def on_exit(cls: type, triggers: list[type]);
4
+ def make_public_ro;
5
+ def make_public_rw;
6
+ def make_private;
7
+ def is_public_ro -> bool;
8
+ def is_public_rw -> bool;
9
+ def is_private -> bool;
10
+ def is_readable(caller_id: UUID) -> bool;
11
+ def is_writable(caller_id: UUID) -> bool;
12
+ def give_access(caller_id: UUID, read_write: bool = False);
13
+ def revoke_access(caller_id: UUID);
14
+ }
@@ -1,6 +1,7 @@
1
1
  with entry {
2
- triple_quoted_string = """This is a triple quoted string.
3
- It can span multiple lines.
4
- It can contain any number of quotes or apostrophes.
5
- """;
2
+ triple_quoted_string =
3
+ """This is a triple quoted string.
4
+ It can span multiple lines.
5
+ It can contain any number of quotes or apostrophes.
6
+ """;
6
7
  }
@@ -0,0 +1,13 @@
1
+ obj Anchor(ArchetypeProtocol) {
2
+ has ob: object,
3
+ ds_entry_funcs: list[DSFunc],
4
+ ds_exit_funcs: list[DSFunc],
5
+ jid: UUID = :> uuid4(),
6
+ timestamp: datetime = :> datetime.now,
7
+ persist: bool = False,
8
+ access_mode: AccessMode = AccessMode.PRIVATE,
9
+ rw_access: set = :> set(),
10
+ ro_access: set = :> set(),
11
+ owner_id: UUID = exec_ctx.master,
12
+ mem: Memory = exec_ctx.memory;
13
+ }
@@ -0,0 +1,6 @@
1
+ import from datetime { datetime }
2
+ import from uuid { UUID, uuid4 }
3
+ import from jaclang.compiler.constant { EdgeDir }
4
+ import from jaclang.plugin { Archetype, ArchetypeProtocol, DSFunc, AbsRootHook, hookimpl }
5
+ import math;
6
+ import numpy as np;
@@ -10,7 +10,7 @@ edge Checking {}
10
10
 
11
11
  walker Creator {
12
12
  has count: int = 0;
13
-
13
+
14
14
  can create with `root | Item entry {
15
15
  here ++> Item();
16
16
  self.count += 1;
@@ -24,11 +24,11 @@ walker Creator {
24
24
  walker Walk {
25
25
  has count: int = 0;
26
26
  has value: int = 0;
27
-
27
+
28
28
  can skip_root with `root entry {
29
29
  visit [-->];
30
30
  }
31
-
31
+
32
32
  can step with Item entry {
33
33
  here.value = self.count;
34
34
  self.count += 1;
@@ -0,0 +1,9 @@
1
+ class SemTokManager {
2
+ """Initialize semantic token manager."""
3
+ def init(self: SemTokManager, ir: uni.Module) -> None {
4
+ self.sem_tokens: List[int] = self.gen_sem_tokens(ir);
5
+ self.aaaaastatic_sem_tokens:
6
+ List[Tuple[lspt.Position, int, int, uni.AstSymbolNode]] =
7
+ self.gen_sem_tok_node(ir);
8
+ }
9
+ }
@@ -51,6 +51,30 @@ class JacFormatPassTests(TestCaseMicroSuite):
51
51
  os.path.join(self.fixture_abs_path(""), "simple_walk_fmt.jac"),
52
52
  )
53
53
 
54
+ def test_tagbreak(self) -> None:
55
+ """Tests if the file matches a particular format."""
56
+ self.compare_files(
57
+ os.path.join(self.fixture_abs_path(""), "tagbreak.jac"),
58
+ )
59
+
60
+ def test_has_fmt(self) -> None:
61
+ """Tests if the file matches a particular format."""
62
+ self.compare_files(
63
+ os.path.join(self.fixture_abs_path(""), "has_frmt.jac"),
64
+ )
65
+
66
+ def test_import_fmt(self) -> None:
67
+ """Tests if the file matches a particular format."""
68
+ self.compare_files(
69
+ os.path.join(self.fixture_abs_path(""), "import_fmt.jac"),
70
+ )
71
+
72
+ def test_archetype(self) -> None:
73
+ """Tests if the file matches a particular format."""
74
+ self.compare_files(
75
+ os.path.join(self.fixture_abs_path(""), "archetype_frmt.jac"),
76
+ )
77
+
54
78
  # def test_corelib_fmt(self) -> None:
55
79
  # """Tests if the file matches a particular format."""
56
80
  # self.compare_files(
@@ -99,9 +123,7 @@ class JacFormatPassTests(TestCaseMicroSuite):
99
123
  """
100
124
  code_gen_pure = JacProgram().compile(self.fixture_abs_path(filename))
101
125
  code_gen_format = JacProgram.jac_file_formatter(self.fixture_abs_path(filename))
102
- code_gen_jac = JacProgram().compile_from_str(
103
- source_str=code_gen_format, file_path=filename
104
- )
126
+ code_gen_jac = JacProgram().compile(use_str=code_gen_format, file_path=filename)
105
127
  if "circle_clean_tests.jac" in filename:
106
128
  tokens = code_gen_format.split()
107
129
  num_test = 0
@@ -34,8 +34,8 @@ class JacUnparseTests(TestCaseMicroSuite):
34
34
  )
35
35
  before = ast3.dump(code_gen_pure.gen.py_ast[0], indent=2)
36
36
  x = code_gen_pure.unparse()
37
- code_gen_jac = JacProgram().compile_from_str(
38
- source_str=x,
37
+ code_gen_jac = JacProgram().compile(
38
+ use_str=x,
39
39
  file_path=filename,
40
40
  )
41
41
  after = ast3.dump(code_gen_jac.gen.py_ast[0], indent=2)
@@ -12,17 +12,16 @@ from jaclang.compiler.parser import JacParser
12
12
  from jaclang.compiler.passes.main import (
13
13
  Alert,
14
14
  CFGBuildPass,
15
- CompilerMode,
16
15
  DeclImplMatchPass,
17
16
  DefUsePass,
18
17
  InheritancePass,
19
18
  JacAnnexPass,
20
19
  JacImportDepsPass,
21
20
  PyBytecodeGenPass,
22
- PyImportDepsPass,
23
21
  PyJacAstLinkPass,
24
22
  PyastBuildPass,
25
23
  PyastGenPass,
24
+ SemDefMatchPass,
26
25
  SymTabBuildPass,
27
26
  SymTabLinkPass,
28
27
  Transform,
@@ -38,8 +37,10 @@ from jaclang.utils.log import logging
38
37
  logger = logging.getLogger(__name__)
39
38
 
40
39
  ir_gen_sched = [
40
+ SymTabBuildPass,
41
41
  DeclImplMatchPass,
42
42
  DefUsePass,
43
+ SemDefMatchPass,
43
44
  CFGBuildPass,
44
45
  InheritancePass,
45
46
  ]
@@ -63,29 +64,13 @@ class JacProgram:
63
64
 
64
65
  def get_bytecode(self, full_target: str) -> Optional[types.CodeType]:
65
66
  """Get the bytecode for a specific module."""
66
- if full_target in self.mod.hub:
67
+ if full_target in self.mod.hub and self.mod.hub[full_target].gen.py_bytecode:
67
68
  codeobj = self.mod.hub[full_target].gen.py_bytecode
68
69
  return marshal.loads(codeobj) if isinstance(codeobj, bytes) else None
69
- result = self.compile(file_path=full_target, mode=CompilerMode.COMPILE_SINGLE)
70
+ result = self.compile(file_path=full_target)
70
71
  return marshal.loads(result.gen.py_bytecode) if result.gen.py_bytecode else None
71
72
 
72
- def compile(
73
- self,
74
- file_path: str,
75
- mode: CompilerMode = CompilerMode.COMPILE,
76
- ) -> uni.Module:
77
- """Convert a Jac file to an AST."""
78
- with open(file_path, "r", encoding="utf-8") as file:
79
- return self.compile_from_str(
80
- source_str=file.read(), file_path=file_path, mode=mode
81
- )
82
-
83
- def compile_from_str(
84
- self,
85
- source_str: str,
86
- file_path: str,
87
- mode: CompilerMode = CompilerMode.COMPILE,
88
- ) -> uni.Module:
73
+ def parse_str(self, source_str: str, file_path: str) -> uni.Module:
89
74
  """Convert a Jac file to an AST."""
90
75
  had_error = False
91
76
  if file_path.endswith(".py"):
@@ -111,54 +96,32 @@ class JacProgram:
111
96
  if self.mod.main.stub_only:
112
97
  self.mod = uni.ProgramModule(mod)
113
98
  self.mod.hub[mod.loc.mod_path] = mod
114
- return self.run_pass_schedule(mod_targ=mod, mode=mode)
99
+ JacAnnexPass(ir_in=mod, prog=self)
100
+ return mod
115
101
 
116
- def run_pass_schedule(
117
- self,
118
- mod_targ: uni.Module,
119
- mode: CompilerMode = CompilerMode.COMPILE,
102
+ def compile(
103
+ self, file_path: str, use_str: str | None = None, no_cgen: bool = False
120
104
  ) -> uni.Module:
121
105
  """Convert a Jac file to an AST."""
122
- JacAnnexPass(ir_in=mod_targ, prog=self)
123
- SymTabBuildPass(ir_in=mod_targ, prog=self)
124
- if mode == CompilerMode.PARSE:
125
- return mod_targ
126
- elif mode in (CompilerMode.COMPILE_SINGLE, CompilerMode.NO_CGEN_SINGLE):
127
- self.schedule_runner(mod_targ, mode=mode)
128
- return mod_targ
106
+ if not use_str:
107
+ with open(file_path, "r", encoding="utf-8") as file:
108
+ use_str = file.read()
109
+ mod_targ = self.parse_str(use_str, file_path)
110
+ self.run_schedule(mod=mod_targ, passes=ir_gen_sched)
111
+ if not no_cgen:
112
+ self.run_schedule(mod=mod_targ, passes=py_code_gen)
113
+ return mod_targ
114
+
115
+ def build(self, file_path: str, use_str: str | None = None) -> uni.Module:
116
+ """Convert a Jac file to an AST."""
117
+ mod_targ = self.compile(file_path, use_str)
129
118
  JacImportDepsPass(ir_in=mod_targ, prog=self)
130
- if len(self.errors_had):
131
- return mod_targ
132
- SymTabLinkPass(ir_in=mod_targ, prog=self)
133
119
  for mod in self.mod.hub.values():
134
- self.schedule_runner(mod, mode=CompilerMode.COMPILE)
135
- if mode == CompilerMode.COMPILE:
136
- return mod_targ
137
- PyImportDepsPass(mod_targ, prog=self)
138
- SymTabLinkPass(ir_in=mod_targ, prog=self)
120
+ SymTabLinkPass(ir_in=mod, prog=self)
139
121
  for mod in self.mod.hub.values():
140
122
  DefUsePass(mod, prog=self)
141
- for mod in self.mod.hub.values():
142
- self.schedule_runner(mod, mode=CompilerMode.TYPECHECK)
143
123
  return mod_targ
144
124
 
145
- def schedule_runner(
146
- self,
147
- mod: uni.Module,
148
- mode: CompilerMode = CompilerMode.COMPILE,
149
- ) -> None:
150
- """Run premade passes on the module."""
151
- match mode:
152
- case CompilerMode.NO_CGEN | CompilerMode.NO_CGEN_SINGLE:
153
- passes = ir_gen_sched
154
- case CompilerMode.COMPILE | CompilerMode.COMPILE_SINGLE:
155
- passes = [*ir_gen_sched, *py_code_gen]
156
- case CompilerMode.TYPECHECK:
157
- passes = []
158
- case _:
159
- raise ValueError(f"Invalid mode: {mode}")
160
- self.run_schedule(mod, passes)
161
-
162
125
  def run_schedule(
163
126
  self,
164
127
  mod: uni.Module,
@@ -1,11 +1,5 @@
1
-
2
-
3
1
  from jaclang import JacMachineInterface as _
4
2
 
5
- (tool_func,) = _.py_jac_import(
6
- target="tools",
7
- base_path=__file__,
8
- items={"tool_func": None},
9
- )
3
+ from .tools import tool_func
10
4
 
11
- glob_var_lib = 'pkg_import_lib_py.glob_var_lib'
5
+ glob_var_lib = "pkg_import_lib_py.glob_var_lib"
@@ -1,7 +1,3 @@
1
1
  from jaclang import JacMachineInterface as _
2
2
 
3
- (help_func,) = _.py_jac_import(
4
- target=".helper",
5
- base_path=__file__,
6
- items={"help_func": None},
7
- )
3
+ from .helper import help_func
@@ -3,10 +3,10 @@
3
3
  import io
4
4
  import sys
5
5
 
6
- from jaclang import JacMachineInterface as Jac
6
+ from jaclang import JacMachine as Jac
7
7
  from jaclang.cli import cli
8
8
  from jaclang.compiler.program import JacProgram
9
- from jaclang.runtimelib.machine import JacMachineInterface, JacMachine
9
+ from jaclang.runtimelib.machine import JacMachineInterface
10
10
  from jaclang.utils.test import TestCase
11
11
 
12
12
 
@@ -15,29 +15,27 @@ class TestLoader(TestCase):
15
15
 
16
16
  def test_import_basic_python(self) -> None:
17
17
  """Test basic self loading."""
18
- mach = JacMachine(self.fixture_abs_path(__file__))
18
+ Jac.set_base_path(self.fixture_abs_path(__file__))
19
19
  JacMachineInterface.attach_program(
20
- mach,
21
20
  JacProgram(),
22
21
  )
23
- (h,) = Jac.jac_import(mach, "fixtures.hello_world", base_path=__file__)
22
+ (h,) = Jac.jac_import("fixtures.hello_world", base_path=__file__)
24
23
  self.assertEqual(h.hello(), "Hello World!") # type: ignore
25
24
 
26
25
  def test_modules_correct(self) -> None:
27
26
  """Test basic self loading."""
28
- mach = JacMachine(self.fixture_abs_path(__file__))
27
+ Jac.set_base_path(self.fixture_abs_path(__file__))
29
28
  JacMachineInterface.attach_program(
30
- mach,
31
29
  JacProgram(),
32
30
  )
33
- Jac.jac_import(mach, "fixtures.hello_world", base_path=__file__)
31
+ Jac.jac_import("fixtures.hello_world", base_path=__file__)
34
32
  self.assertIn(
35
33
  "module 'fixtures.hello_world'",
36
- str(mach.loaded_modules),
34
+ str(Jac.loaded_modules),
37
35
  )
38
36
  self.assertIn(
39
37
  "/tests/fixtures/hello_world.jac",
40
- str(mach.loaded_modules).replace("\\\\", "/"),
38
+ str(Jac.loaded_modules).replace("\\\\", "/"),
41
39
  )
42
40
 
43
41
  def test_jac_py_import(self) -> None:
@@ -92,12 +90,11 @@ class TestLoader(TestCase):
92
90
  sys.stdout = captured_output
93
91
 
94
92
  try:
95
- mach = JacMachine(self.fixture_abs_path(__file__))
93
+ Jac.set_base_path(self.fixture_abs_path(__file__))
96
94
  JacMachineInterface.attach_program(
97
- mach,
98
95
  JacProgram(),
99
96
  )
100
- Jac.jac_import(mach, module_name, base_path=__file__)
97
+ Jac.jac_import(module_name, base_path=__file__)
101
98
  cli.run(jac_file_path)
102
99
 
103
100
  # Reset stdout and get the output
@@ -548,6 +548,7 @@ class AstSymbolNode(UniNode):
548
548
  self.name_spec.name_of = self
549
549
  self.name_spec._sym_name = sym_name
550
550
  self.name_spec._sym_category = sym_category
551
+ self.semstr = ""
551
552
 
552
553
  @property
553
554
  def sym(self) -> Optional[Symbol]:
@@ -849,15 +850,15 @@ class NameAtom(AtomExpr, EnumBlockStmt):
849
850
  return None
850
851
 
851
852
 
852
- class ArchSpec(ElementStmt, CodeBlockStmt, AstSymbolNode, AstDocNode):
853
+ class ArchSpec(ElementStmt, CodeBlockStmt, AstSymbolNode, AstAsyncNode, AstDocNode):
853
854
  """ArchSpec node type for Jac Ast."""
854
855
 
855
856
  def __init__(
856
857
  self, decorators: Sequence[Expr] | None, is_async: bool = False
857
858
  ) -> None:
858
859
  self.decorators = decorators
859
- self.is_async = is_async
860
860
  CodeBlockStmt.__init__(self)
861
+ AstAsyncNode.__init__(self, is_async=is_async)
861
862
 
862
863
 
863
864
  class MatchPattern(UniNode):
@@ -1621,6 +1622,61 @@ class ImplDef(CodeBlockStmt, ElementStmt, ArchBlockStmt, AstSymbolNode, UniScope
1621
1622
  return res
1622
1623
 
1623
1624
 
1625
+ class SemDef(ElementStmt, AstSymbolNode, UniScopeNode):
1626
+ """SemDef node type for Jac Ast."""
1627
+
1628
+ def __init__(
1629
+ self,
1630
+ target: Sequence[NameAtom],
1631
+ value: String,
1632
+ kid: Sequence[UniNode],
1633
+ ) -> None:
1634
+ self.target = target
1635
+ self.value = value
1636
+ UniNode.__init__(self, kid=kid)
1637
+ AstSymbolNode.__init__(
1638
+ self,
1639
+ sym_name="sem." + ".".join([x.sym_name for x in self.target]),
1640
+ name_spec=self.create_sem_name_node(),
1641
+ sym_category=SymbolType.SEM,
1642
+ )
1643
+ UniScopeNode.__init__(self, name=self.sym_name)
1644
+
1645
+ def create_sem_name_node(self) -> Name:
1646
+ ret = Name(
1647
+ orig_src=self.target[-1].loc.orig_src,
1648
+ name=Tok.NAME.value,
1649
+ value="sem." + ".".join([x.sym_name for x in self.target]),
1650
+ col_start=self.target[0].loc.col_start,
1651
+ col_end=self.target[-1].loc.col_end,
1652
+ line=self.target[0].loc.first_line,
1653
+ end_line=self.target[-1].loc.last_line,
1654
+ pos_start=self.target[0].loc.pos_start,
1655
+ pos_end=self.target[-1].loc.pos_end,
1656
+ )
1657
+ ret.parent = self
1658
+ return ret
1659
+
1660
+ def normalize(self, deep: bool = False) -> bool:
1661
+ res = True
1662
+ if deep:
1663
+ for item in self.target:
1664
+ res = res and item.normalize(deep)
1665
+ res = res and self.value.normalize(deep)
1666
+ new_kid: list[UniNode] = [
1667
+ self.gen_token(Tok.KW_SEM),
1668
+ ]
1669
+ for idx, item in enumerate(self.target):
1670
+ new_kid.append(item)
1671
+ if idx < len(self.target) - 1:
1672
+ new_kid.append(self.gen_token(Tok.DOT))
1673
+ new_kid.append(self.gen_token(Tok.EQ))
1674
+ new_kid.append(self.value)
1675
+ new_kid.append(self.gen_token(Tok.SEMI))
1676
+ self.set_kids(nodes=new_kid)
1677
+ return res
1678
+
1679
+
1624
1680
  class Enum(ArchSpec, AstAccessNode, AstImplNeedingNode, ArchBlockStmt, UniScopeNode):
1625
1681
  """Enum node type for Jac Ast."""
1626
1682
 
@@ -1777,6 +1833,22 @@ class Ability(
1777
1833
  def is_genai_ability(self) -> bool:
1778
1834
  return isinstance(self.body, FuncCall)
1779
1835
 
1836
+ def get_pos_argc_range(self) -> tuple[int, int]:
1837
+ """Get the range of positional arguments for this ability.
1838
+
1839
+ Returns -1 for maximum number of arguments if there is an unpacked parameter (e.g., *args).
1840
+ """
1841
+ mn, mx = 0, 0
1842
+ if isinstance(self.signature, FuncSignature):
1843
+ for param in self.signature.params:
1844
+ if param.unpack:
1845
+ if param.unpack == Tok.STAR_MUL:
1846
+ mx = -1
1847
+ break
1848
+ mn += 1
1849
+ mx += 1
1850
+ return mn, mx
1851
+
1780
1852
  def py_resolve_name(self) -> str:
1781
1853
  if isinstance(self.name_ref, Name):
1782
1854
  return self.name_ref.value
@@ -1914,12 +1986,10 @@ class EventSignature(WalkerStmtOnlyNode):
1914
1986
  self,
1915
1987
  event: Token,
1916
1988
  arch_tag_info: Optional[Expr],
1917
- return_type: Optional[Expr],
1918
1989
  kid: Sequence[UniNode],
1919
1990
  ) -> None:
1920
1991
  self.event = event
1921
1992
  self.arch_tag_info = arch_tag_info
1922
- self.return_type = return_type
1923
1993
  UniNode.__init__(self, kid=kid)
1924
1994
  WalkerStmtOnlyNode.__init__(self)
1925
1995
 
@@ -1932,14 +2002,10 @@ class EventSignature(WalkerStmtOnlyNode):
1932
2002
  if self.arch_tag_info
1933
2003
  else res
1934
2004
  )
1935
- res = res and self.return_type.normalize(deep) if self.return_type else res
1936
2005
  new_kid: list[UniNode] = [self.gen_token(Tok.KW_WITH)]
1937
2006
  if self.arch_tag_info:
1938
2007
  new_kid.append(self.arch_tag_info)
1939
2008
  new_kid.append(self.event)
1940
- if self.return_type:
1941
- new_kid.append(self.gen_token(Tok.RETURN_HINT))
1942
- new_kid.append(self.return_type)
1943
2009
  self.set_kids(nodes=new_kid)
1944
2010
  return res
1945
2011
 
@@ -3659,10 +3725,12 @@ class FuncCall(Expr):
3659
3725
  params: Sequence[Expr | KWPair] | None,
3660
3726
  genai_call: Optional[FuncCall],
3661
3727
  kid: Sequence[UniNode],
3728
+ body_genai_call: Optional[FuncCall] = None,
3662
3729
  ) -> None:
3663
3730
  self.target = target
3664
3731
  self.params = list(params) if params else []
3665
3732
  self.genai_call = genai_call
3733
+ self.body_genai_call = body_genai_call
3666
3734
  UniNode.__init__(self, kid=kid)
3667
3735
  Expr.__init__(self)
3668
3736
 
@@ -4578,17 +4646,21 @@ class String(Literal):
4578
4646
  return eval(self.value)
4579
4647
 
4580
4648
  elif self.value.startswith(("'", '"')):
4581
- repr_str = self.value.encode().decode("unicode_escape")
4582
- if (
4583
- (self.value.startswith('"""') and self.value.endswith('"""'))
4584
- or (self.value.startswith("'''") and self.value.endswith("'''"))
4585
- ) and not self.find_parent_of_type(FString):
4586
- return repr_str[3:-3]
4587
4649
  if (not self.find_parent_of_type(FString)) or (
4588
4650
  not (self.parent and isinstance(self.parent, FString))
4589
4651
  ):
4590
- return repr_str[1:-1]
4591
- return repr_str
4652
+ try:
4653
+ return ast3.literal_eval(self.value)
4654
+ except (ValueError, SyntaxError):
4655
+ if (
4656
+ self.value.startswith('"""') and self.value.endswith('"""')
4657
+ ) or (self.value.startswith("'''") and self.value.endswith("'''")):
4658
+ return self.value[3:-3]
4659
+ return self.value[1:-1]
4660
+ try:
4661
+ return ast3.literal_eval(self.value)
4662
+ except (ValueError, SyntaxError):
4663
+ return self.value
4592
4664
  else:
4593
4665
  return self.value
4594
4666
 
@@ -1 +1 @@
1
- """Jac Language Server Protocol implementation."""
1
+ """Jaclang langserve package."""