jaclang 0.5.18__py3-none-any.whl → 0.6.0__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 (47) hide show
  1. jaclang/cli/cli.py +4 -2
  2. jaclang/compiler/__init__.py +12 -5
  3. jaclang/compiler/absyntree.py +3 -3
  4. jaclang/compiler/generated/jac_parser.py +2 -2
  5. jaclang/compiler/jac.lark +2 -2
  6. jaclang/compiler/parser.py +47 -7
  7. jaclang/compiler/passes/main/__init__.py +3 -2
  8. jaclang/compiler/passes/main/access_modifier_pass.py +173 -0
  9. jaclang/compiler/passes/main/import_pass.py +32 -19
  10. jaclang/compiler/passes/main/pyast_gen_pass.py +41 -26
  11. jaclang/compiler/passes/main/pyast_load_pass.py +136 -73
  12. jaclang/compiler/passes/main/pyout_pass.py +14 -13
  13. jaclang/compiler/passes/main/registry_pass.py +8 -3
  14. jaclang/compiler/passes/main/schedules.py +5 -3
  15. jaclang/compiler/passes/main/sym_tab_build_pass.py +23 -26
  16. jaclang/compiler/passes/main/tests/test_import_pass.py +2 -2
  17. jaclang/compiler/passes/tool/jac_formatter_pass.py +83 -21
  18. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +11 -4
  19. jaclang/compiler/passes/transform.py +2 -0
  20. jaclang/compiler/symtable.py +10 -3
  21. jaclang/compiler/tests/test_importer.py +9 -0
  22. jaclang/compiler/workspace.py +17 -5
  23. jaclang/core/aott.py +34 -63
  24. jaclang/core/importer.py +73 -65
  25. jaclang/core/llms/__init__.py +20 -0
  26. jaclang/core/llms/anthropic.py +61 -0
  27. jaclang/core/llms/base.py +206 -0
  28. jaclang/core/llms/groq.py +67 -0
  29. jaclang/core/llms/huggingface.py +73 -0
  30. jaclang/core/llms/ollama.py +78 -0
  31. jaclang/core/llms/openai.py +61 -0
  32. jaclang/core/llms/togetherai.py +60 -0
  33. jaclang/core/llms/utils.py +9 -0
  34. jaclang/core/utils.py +16 -1
  35. jaclang/plugin/default.py +37 -14
  36. jaclang/plugin/feature.py +9 -6
  37. jaclang/plugin/spec.py +8 -1
  38. jaclang/settings.py +1 -1
  39. jaclang/utils/helpers.py +6 -2
  40. jaclang/utils/treeprinter.py +9 -6
  41. jaclang-0.6.0.dist-info/METADATA +17 -0
  42. {jaclang-0.5.18.dist-info → jaclang-0.6.0.dist-info}/RECORD +45 -36
  43. jaclang/core/llms.py +0 -111
  44. jaclang-0.5.18.dist-info/METADATA +0 -7
  45. {jaclang-0.5.18.dist-info → jaclang-0.6.0.dist-info}/WHEEL +0 -0
  46. {jaclang-0.5.18.dist-info → jaclang-0.6.0.dist-info}/entry_points.txt +0 -0
  47. {jaclang-0.5.18.dist-info → jaclang-0.6.0.dist-info}/top_level.txt +0 -0
jaclang/compiler/jac.lark CHANGED
@@ -195,8 +195,8 @@ list_inner_pattern: (pattern_seq | STAR_MUL NAME)
195
195
  dict_inner_pattern: (literal_pattern COLON pattern_seq | STAR_POW NAME)
196
196
 
197
197
  // Match class patterns
198
- class_pattern: NAME LPAREN kw_pattern_list? RPAREN
199
- | NAME LPAREN pattern_list (COMMA kw_pattern_list)? RPAREN
198
+ class_pattern: NAME (DOT NAME)* LPAREN kw_pattern_list? RPAREN
199
+ | NAME (DOT NAME)* LPAREN pattern_list (COMMA kw_pattern_list)? RPAREN
200
200
 
201
201
  pattern_list: (pattern_list COMMA)? pattern_seq
202
202
  kw_pattern_list: (kw_pattern_list COMMA)? named_ref EQ pattern_seq
@@ -3739,12 +3739,43 @@ class JacParser(Pass):
3739
3739
  def class_pattern(self, kid: list[ast.AstNode]) -> ast.MatchArch:
3740
3740
  """Grammar rule.
3741
3741
 
3742
- class_pattern: NAME LPAREN kw_pattern_list? RPAREN
3743
- | NAME LPAREN pattern_list (COMMA kw_pattern_list)? RPAREN
3742
+ class_pattern: NAME (DOT NAME)* LPAREN kw_pattern_list? RPAREN
3743
+ | NAME (DOT NAME)* LPAREN pattern_list (COMMA kw_pattern_list)? RPAREN
3744
3744
  """
3745
- name = kid[0]
3746
- first = kid[2]
3747
- second = kid[4] if len(kid) > 4 else None
3745
+ chomp = [*kid]
3746
+ cur_element = chomp[0]
3747
+ chomp = chomp[1:]
3748
+ while not (isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.LPAREN):
3749
+ if isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.DOT:
3750
+ target_ = cur_element
3751
+ right_ = chomp[1]
3752
+ if isinstance(right_, (ast.Expr, ast.AtomExpr)) and isinstance(
3753
+ target_, ast.Expr
3754
+ ):
3755
+ cur_element = ast.AtomTrailer(
3756
+ target=target_,
3757
+ right=right_,
3758
+ is_attr=True,
3759
+ is_null_ok=False,
3760
+ kid=[target_, chomp[0], right_],
3761
+ )
3762
+ chomp = chomp[2:]
3763
+ else:
3764
+ raise self.ice()
3765
+ elif isinstance(cur_element, ast.NameSpec):
3766
+ chomp = chomp[1:]
3767
+ else:
3768
+ break
3769
+ name = cur_element
3770
+ lparen = chomp[0]
3771
+ rapren = chomp[-1]
3772
+ first = chomp[1]
3773
+ if len(chomp) > 4:
3774
+ second = chomp[3]
3775
+ comma = chomp[2]
3776
+ else:
3777
+ second = None
3778
+ comma = None
3748
3779
  arg = (
3749
3780
  first
3750
3781
  if isinstance(first, ast.SubNodeList)
@@ -3762,13 +3793,22 @@ class JacParser(Pass):
3762
3793
  else None
3763
3794
  )
3764
3795
  )
3765
- if isinstance(name, ast.NameSpec):
3796
+ if isinstance(name, (ast.NameSpec, ast.AtomTrailer)):
3797
+ kid_nodes = [name, lparen]
3798
+ if arg:
3799
+ kid_nodes.append(arg)
3800
+ if kw:
3801
+ kid_nodes.extend([comma, kw]) if comma else kid_nodes.append(kw)
3802
+ elif kw:
3803
+ kid_nodes.append(kw)
3804
+ kid_nodes.append(rapren)
3805
+
3766
3806
  return self.nu(
3767
3807
  ast.MatchArch(
3768
3808
  name=name,
3769
3809
  arg_patterns=arg,
3770
3810
  kw_patterns=kw,
3771
- kid=kid,
3811
+ kid=kid_nodes,
3772
3812
  )
3773
3813
  )
3774
3814
  else:
@@ -1,7 +1,7 @@
1
1
  """Collection of passes for Jac IR."""
2
2
 
3
3
  from .sub_node_tab_pass import SubNodeTabPass
4
- from .import_pass import ImportPass # noqa: I100
4
+ from .import_pass import JacImportPass, PyImportPass # noqa: I100
5
5
  from .sym_tab_build_pass import SymTabBuildPass # noqa: I100
6
6
  from .def_impl_match_pass import DeclDefMatchPass # noqa: I100
7
7
  from .def_use_pass import DefUsePass # noqa: I100
@@ -17,7 +17,8 @@ pass_schedule = py_code_gen
17
17
 
18
18
  __all__ = [
19
19
  "SubNodeTabPass",
20
- "ImportPass",
20
+ "JacImportPass",
21
+ "PyImportPass",
21
22
  "SymTabBuildPass",
22
23
  "DeclDefMatchPass",
23
24
  "DefUsePass",
@@ -0,0 +1,173 @@
1
+ """Access check pass for the Jac compiler.
2
+
3
+ This pass checks for access to attributes in the Jac language.
4
+ """
5
+
6
+ import os
7
+ from typing import Optional
8
+
9
+ import jaclang.compiler.absyntree as ast
10
+ from jaclang.compiler.passes.main.sym_tab_build_pass import SymTabPass, SymbolAccess
11
+
12
+
13
+ class AccessCheckPass(SymTabPass):
14
+ """Jac Ast Access Check pass."""
15
+
16
+ def after_pass(self) -> None:
17
+ """After pass."""
18
+ pass
19
+
20
+ def access_check(self, node: ast.Name) -> None:
21
+ """Access check."""
22
+ node_info = (
23
+ node.sym_tab.lookup(node.sym_name)
24
+ if isinstance(node.sym_tab, ast.SymbolTable)
25
+ else None
26
+ )
27
+
28
+ if node.sym_link:
29
+ decl_package_path = os.path.dirname(
30
+ os.path.abspath(node.sym_link.defn[-1].loc.mod_path)
31
+ )
32
+ use_package_path = os.path.dirname(os.path.abspath(node.loc.mod_path))
33
+ else:
34
+ decl_package_path = use_package_path = ""
35
+
36
+ if (
37
+ node_info
38
+ and node.sym_link
39
+ and node_info.access == SymbolAccess.PROTECTED
40
+ and decl_package_path != use_package_path
41
+ ):
42
+ return self.error(
43
+ f'Can not access protected variable "{node.sym_name}" from {decl_package_path}'
44
+ f" to {use_package_path}."
45
+ )
46
+
47
+ if (
48
+ node_info
49
+ and node.sym_link
50
+ and node_info.access == SymbolAccess.PRIVATE
51
+ and node.sym_link.defn[-1].loc.mod_path != node.loc.mod_path
52
+ ):
53
+ return self.error(
54
+ f'Can not access private variable "{node.sym_name}" from {node.sym_link.defn[-1].loc.mod_path}'
55
+ f" to {node.loc.mod_path}."
56
+ )
57
+
58
+ def access_register(
59
+ self, node: ast.AstSymbolNode, acc_tag: Optional[SymbolAccess] = None
60
+ ) -> None:
61
+ """Access register."""
62
+ node.sym_info.acc_tag = acc_tag
63
+
64
+ def enter_global_vars(self, node: ast.GlobalVars) -> None:
65
+ """Sub objects.
66
+
67
+ access: Optional[SubTag[Token]],
68
+ assignments: SubNodeList[Assignment],
69
+ is_frozen: bool,
70
+ """
71
+ pass
72
+
73
+ def enter_module(self, node: ast.Module) -> None:
74
+ """Sub objects.
75
+
76
+ name: str,
77
+ doc: Token,
78
+ body: Optional['Elements'],
79
+ mod_path: str,
80
+ is_imported: bool,
81
+ """
82
+
83
+ def enter_architype(self, node: ast.Architype) -> None:
84
+ """Sub objects.
85
+
86
+ name: Name,
87
+ arch_type: Token,
88
+ access: Optional[SubTag[Token]],
89
+ base_classes: Optional[SubNodeList[Expr]],
90
+ body: Optional[SubNodeList[ArchBlockStmt] | ArchDef],
91
+ decorators: Optional[SubNodeList[Expr]] = None,
92
+ """
93
+ pass
94
+
95
+ def enter_enum(self, node: ast.Enum) -> None:
96
+ """Sub objects.
97
+
98
+ name: Name,
99
+ access: Optional[SubTag[Token]],
100
+ base_classes: Optional[SubNodeList[Expr]],
101
+ body: Optional[SubNodeList[EnumBlockStmt] | EnumDef],
102
+ decorators: Optional[SubNodeList[Expr]] = None,
103
+ """
104
+ pass
105
+
106
+ def enter_ability(self, node: ast.Ability) -> None:
107
+ """Sub objects.
108
+
109
+ name_ref: NameSpec,
110
+ is_func: bool,
111
+ is_async: bool,
112
+ is_override: bool,
113
+ is_static: bool,
114
+ is_abstract: bool,
115
+ access: Optional[SubTag[Token]],
116
+ signature: Optional[FuncSignature | EventSignature],
117
+ body: Optional[SubNodeList[CodeBlockStmt] | AbilityDef],
118
+ decorators: Optional[SubNodeList[Expr]] = None,
119
+ """
120
+ pass
121
+
122
+ def enter_sub_node_list(self, node: ast.SubNodeList) -> None:
123
+ """Sub objects.
124
+
125
+ items: list[T]
126
+ """
127
+
128
+ def enter_arch_has(self, node: ast.ArchHas) -> None:
129
+ """Sub objects.
130
+
131
+ is_static: bool,
132
+ access: Optional[SubTag[Token]],
133
+ vars: SubNodeList[HasVar],
134
+ is_frozen: bool,
135
+ """
136
+ pass
137
+
138
+ def enter_atom_trailer(self, node: ast.AtomTrailer) -> None:
139
+ """Sub objects.
140
+
141
+ access: Optional[SubTag[Token]],
142
+ """
143
+ pass
144
+
145
+ def enter_func_call(self, node: ast.FuncCall) -> None:
146
+ """Sub objects.
147
+
148
+ target: Expr,
149
+ params: Optional[SubNodeList[Expr | KWPair]],
150
+ genai_call: Optional[FuncCall],
151
+ kid: Sequence[AstNode],
152
+ """
153
+ pass
154
+
155
+ def enter_name(self, node: ast.Name) -> None:
156
+ """Sub objects.
157
+
158
+ name: str,
159
+ value: str,
160
+ col_start: int,
161
+ col_end: int,
162
+ pos_start: int,
163
+ pos_end: int,
164
+ """
165
+ from jaclang.compiler.passes import Pass
166
+
167
+ if isinstance(node.parent, ast.FuncCall):
168
+ self.access_check(node)
169
+
170
+ if node.sym_link and Pass.has_parent_of_type(
171
+ node=node.sym_link.defn[-1], typ=ast.GlobalVars
172
+ ):
173
+ self.access_check(node)
@@ -19,8 +19,8 @@ from jaclang.settings import settings
19
19
  from jaclang.utils.helpers import import_target_to_relative_path
20
20
 
21
21
 
22
- class ImportPass(Pass):
23
- """Jac statically imports all modules."""
22
+ class JacImportPass(Pass):
23
+ """Jac statically imports Jac modules."""
24
24
 
25
25
  def before_pass(self) -> None:
26
26
  """Run once before pass."""
@@ -29,6 +29,7 @@ class ImportPass(Pass):
29
29
  def enter_module(self, node: ast.Module) -> None:
30
30
  """Run Importer."""
31
31
  self.cur_node = node
32
+ self.import_table[node.loc.mod_path] = node
32
33
  self.annex_impl(node)
33
34
  self.terminate() # Turns off auto traversal for deliberate traversal
34
35
  self.run_again = True
@@ -36,28 +37,26 @@ class ImportPass(Pass):
36
37
  self.run_again = False
37
38
  all_imports = self.get_all_sub_nodes(node, ast.ModulePath)
38
39
  for i in all_imports:
39
- lang = i.parent_of_type(ast.Import).hint.tag.value
40
- if lang == "jac" and not i.sub_module:
41
- self.run_again = True
42
- mod = self.import_module(
43
- node=i,
44
- mod_path=node.loc.mod_path,
45
- )
46
- if not mod:
47
- self.run_again = False
48
- continue
49
- self.annex_impl(mod)
50
- i.sub_module = mod
51
- i.add_kids_right([mod], pos_update=False)
52
- elif lang == "py" and settings.jac_proc_debug:
53
- mod = self.import_py_module(node=i, mod_path=node.loc.mod_path)
54
- i.sub_module = mod
55
- i.add_kids_right([mod], pos_update=False)
40
+ self.process_import(node, i)
56
41
  self.enter_module_path(i)
57
42
  SubNodeTabPass(prior=self, input_ir=node)
58
43
  self.annex_impl(node)
59
44
  node.mod_deps = self.import_table
60
45
 
46
+ def process_import(self, node: ast.Module, i: ast.ModulePath) -> None:
47
+ """Process an import."""
48
+ lang = i.parent_of_type(ast.Import).hint.tag.value
49
+ if lang == "jac" and not i.sub_module:
50
+ mod = self.import_module(
51
+ node=i,
52
+ mod_path=node.loc.mod_path,
53
+ )
54
+ if mod:
55
+ self.run_again = True
56
+ self.annex_impl(mod)
57
+ i.sub_module = mod
58
+ i.add_kids_right([mod], pos_update=False)
59
+
61
60
  def annex_impl(self, node: ast.Module) -> None:
62
61
  """Annex impl and test modules."""
63
62
  if not node.loc.mod_path:
@@ -165,3 +164,17 @@ class ImportPass(Pass):
165
164
  )
166
165
  raise e
167
166
  return None
167
+
168
+
169
+ class PyImportPass(JacImportPass):
170
+ """Jac statically imports Python modules."""
171
+
172
+ def process_import(self, node: ast.Module, i: ast.ModulePath) -> None:
173
+ """Process an import."""
174
+ lang = i.parent_of_type(ast.Import).hint.tag.value
175
+ if lang == "py" and not i.sub_module and settings.py_raise:
176
+ mod = self.import_py_module(node=i, mod_path=node.loc.mod_path)
177
+ if mod:
178
+ # self.run_again = True
179
+ i.sub_module = mod
180
+ i.add_kids_right([mod], pos_update=False)
@@ -611,9 +611,10 @@ class PyastGenPass(Pass):
611
611
  )
612
612
  )
613
613
  if node.items:
614
- self.warning(
615
- "Includes import * in target module into current namespace."
616
- )
614
+ pass
615
+ # self.warning(
616
+ # "Includes import * in target module into current namespace."
617
+ # )
617
618
  if not node.from_loc:
618
619
  py_nodes.append(self.sync(ast3.Import(names=node.items.gen.py_ast)))
619
620
  else:
@@ -676,8 +677,6 @@ class PyastGenPass(Pass):
676
677
  doc: Optional[String],
677
678
  decorators: Optional[SubNodeList[ExprType]],
678
679
  """
679
- self.needs_jac_feature()
680
- self.needs_dataclass()
681
680
  body = self.resolve_stmt_block(
682
681
  node.body.body if isinstance(node.body, ast.ArchDef) else node.body,
683
682
  doc=node.doc,
@@ -689,6 +688,8 @@ class PyastGenPass(Pass):
689
688
  )
690
689
  ds_on_entry, ds_on_exit = self.collect_events(node)
691
690
  if node.arch_type.name != Tok.KW_CLASS:
691
+ self.needs_jac_feature()
692
+ self.needs_dataclass()
692
693
  decorators.append(
693
694
  self.sync(
694
695
  ast3.Call(
@@ -723,24 +724,26 @@ class PyastGenPass(Pass):
723
724
  )
724
725
  )
725
726
  )
726
- decorators.append(
727
- self.sync(
728
- ast3.Call(
729
- func=self.sync(ast3.Name(id="__jac_dataclass__", ctx=ast3.Load())),
730
- args=[],
731
- keywords=[
732
- self.sync(
733
- ast3.keyword(
734
- arg="eq",
735
- value=self.sync(
736
- ast3.Constant(value=False),
737
- ),
727
+ decorators.append(
728
+ self.sync(
729
+ ast3.Call(
730
+ func=self.sync(
731
+ ast3.Name(id="__jac_dataclass__", ctx=ast3.Load())
732
+ ),
733
+ args=[],
734
+ keywords=[
735
+ self.sync(
736
+ ast3.keyword(
737
+ arg="eq",
738
+ value=self.sync(
739
+ ast3.Constant(value=False),
740
+ ),
741
+ )
738
742
  )
739
- )
740
- ],
743
+ ],
744
+ )
741
745
  )
742
746
  )
743
- )
744
747
  base_classes = node.base_classes.gen.py_ast if node.base_classes else []
745
748
  if node.is_abstract:
746
749
  self.needs_jac_feature()
@@ -1065,7 +1068,11 @@ class PyastGenPass(Pass):
1065
1068
  if isinstance(node.signature, ast.FuncSignature)
1066
1069
  else []
1067
1070
  )
1068
- action = node.semstr.gen.py_ast[0] if node.semstr else None
1071
+ action = (
1072
+ node.semstr.gen.py_ast[0]
1073
+ if node.semstr
1074
+ else self.sync(ast3.Constant(value=None))
1075
+ )
1069
1076
  return [
1070
1077
  self.sync(
1071
1078
  ast3.Assign(
@@ -1385,12 +1392,20 @@ class PyastGenPass(Pass):
1385
1392
  ):
1386
1393
  node.gen.py_ast = [
1387
1394
  self.sync(
1388
- ast3.Attribute(
1389
- value=self.sync(
1390
- ast3.Name(id=Con.JAC_FEATURE.value, ctx=ast3.Load())
1395
+ ast3.Call(
1396
+ func=self.sync(
1397
+ ast3.Attribute(
1398
+ value=self.sync(
1399
+ ast3.Name(
1400
+ id=Con.JAC_FEATURE.value, ctx=ast3.Load()
1401
+ )
1402
+ ),
1403
+ attr="get_root_type",
1404
+ ctx=ast3.Load(),
1405
+ )
1391
1406
  ),
1392
- attr="RootType",
1393
- ctx=ast3.Load(),
1407
+ args=[],
1408
+ keywords=[],
1394
1409
  )
1395
1410
  )
1396
1411
  ]