jaclang 0.7.23__py3-none-any.whl → 0.7.25__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/cli/cli.py +46 -29
- jaclang/compiler/__init__.py +2 -2
- jaclang/compiler/absyntree.py +87 -48
- jaclang/compiler/codeloc.py +7 -2
- jaclang/compiler/compile.py +10 -3
- jaclang/compiler/parser.py +26 -23
- jaclang/compiler/passes/ir_pass.py +2 -2
- jaclang/compiler/passes/main/def_impl_match_pass.py +46 -0
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +146 -123
- jaclang/compiler/passes/main/import_pass.py +6 -2
- jaclang/compiler/passes/main/pyast_load_pass.py +36 -35
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +7 -7
- jaclang/compiler/passes/main/registry_pass.py +3 -12
- jaclang/compiler/passes/main/tests/fixtures/defn_decl_mismatch.jac +19 -0
- jaclang/compiler/passes/main/tests/fixtures/fstrings.jac +2 -0
- jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +59 -0
- jaclang/compiler/passes/main/tests/test_registry_pass.py +2 -10
- jaclang/compiler/passes/main/tests/test_type_check_pass.py +1 -1
- jaclang/compiler/passes/transform.py +27 -3
- jaclang/compiler/passes/utils/mypy_ast_build.py +246 -26
- jaclang/compiler/symtable.py +6 -0
- jaclang/compiler/tests/test_importer.py +2 -2
- jaclang/langserve/engine.py +14 -12
- jaclang/langserve/server.py +7 -2
- jaclang/langserve/tests/test_server.py +1 -1
- jaclang/langserve/utils.py +17 -3
- jaclang/plugin/default.py +32 -32
- jaclang/plugin/feature.py +2 -2
- jaclang/plugin/plugin.md +471 -0
- jaclang/plugin/spec.py +2 -1
- jaclang/runtimelib/context.py +2 -0
- jaclang/runtimelib/importer.py +7 -2
- jaclang/runtimelib/machine.py +21 -6
- jaclang/settings.py +3 -0
- jaclang/tests/fixtures/builtin_dotgen.jac +6 -6
- jaclang/tests/fixtures/enum_inside_archtype.jac +16 -11
- jaclang/tests/fixtures/expr_type.jac +54 -0
- jaclang/tests/fixtures/glob_multivar_statement.jac +15 -0
- jaclang/tests/fixtures/registry.jac +20 -8
- jaclang/tests/foo/__init__.jac +0 -0
- jaclang/tests/main.jac +2 -0
- jaclang/tests/test_cli.py +68 -4
- jaclang/tests/test_language.py +60 -27
- jaclang/utils/helpers.py +92 -14
- jaclang/utils/lang_tools.py +6 -2
- jaclang/utils/treeprinter.py +4 -2
- {jaclang-0.7.23.dist-info → jaclang-0.7.25.dist-info}/METADATA +2 -1
- {jaclang-0.7.23.dist-info → jaclang-0.7.25.dist-info}/RECORD +50 -44
- {jaclang-0.7.23.dist-info → jaclang-0.7.25.dist-info}/WHEEL +1 -1
- {jaclang-0.7.23.dist-info → jaclang-0.7.25.dist-info}/entry_points.txt +0 -0
jaclang/compiler/codeloc.py
CHANGED
|
@@ -9,7 +9,7 @@ from typing import Optional, TYPE_CHECKING
|
|
|
9
9
|
from jaclang.vendor.mypy.nodes import Node as MypyNode
|
|
10
10
|
|
|
11
11
|
if TYPE_CHECKING:
|
|
12
|
-
from jaclang.compiler.absyntree import Token
|
|
12
|
+
from jaclang.compiler.absyntree import JacSource, Token
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
@dataclass
|
|
@@ -42,10 +42,15 @@ class CodeLocInfo:
|
|
|
42
42
|
self.first_tok = first_tok
|
|
43
43
|
self.last_tok = last_tok
|
|
44
44
|
|
|
45
|
+
@property
|
|
46
|
+
def orig_src(self) -> JacSource:
|
|
47
|
+
"""Get file source."""
|
|
48
|
+
return self.first_tok.orig_src
|
|
49
|
+
|
|
45
50
|
@property
|
|
46
51
|
def mod_path(self) -> str:
|
|
47
52
|
"""Get line number."""
|
|
48
|
-
return self.first_tok.file_path
|
|
53
|
+
return self.first_tok.orig_src.file_path
|
|
49
54
|
|
|
50
55
|
@property
|
|
51
56
|
def first_line(self) -> int:
|
jaclang/compiler/compile.py
CHANGED
|
@@ -16,11 +16,13 @@ def compile_jac(file_path: str, cache_result: bool = False) -> Pass:
|
|
|
16
16
|
file_path=file_path,
|
|
17
17
|
schedule=pass_schedule,
|
|
18
18
|
)
|
|
19
|
-
|
|
19
|
+
# If there is syntax error, the code will be an instance of JacParser as there is
|
|
20
|
+
# no more passes were processed, in that case we can ignore it.
|
|
21
|
+
had_syntax_error = isinstance(code, JacParser) and len(code.errors_had) != 0
|
|
22
|
+
if cache_result and (not had_syntax_error) and isinstance(code.ir, ast.Module):
|
|
20
23
|
print_pass = PyOutPass(input_ir=code.ir, prior=code)
|
|
21
24
|
return print_pass
|
|
22
|
-
|
|
23
|
-
return code
|
|
25
|
+
return code
|
|
24
26
|
|
|
25
27
|
|
|
26
28
|
def jac_file_to_pass(
|
|
@@ -49,6 +51,11 @@ def jac_str_to_pass(
|
|
|
49
51
|
target = schedule[-1] if schedule else None
|
|
50
52
|
source = ast.JacSource(jac_str, mod_path=file_path)
|
|
51
53
|
ast_ret: Pass = JacParser(input_ir=source)
|
|
54
|
+
|
|
55
|
+
# If there is syntax error, no point in processing in further passes.
|
|
56
|
+
if len(ast_ret.errors_had) != 0:
|
|
57
|
+
return ast_ret
|
|
58
|
+
|
|
52
59
|
for i in schedule:
|
|
53
60
|
if i == target:
|
|
54
61
|
break
|
jaclang/compiler/parser.py
CHANGED
|
@@ -43,14 +43,22 @@ class JacParser(Pass):
|
|
|
43
43
|
raise self.ice()
|
|
44
44
|
except jl.UnexpectedInput as e:
|
|
45
45
|
catch_error = ast.EmptyToken()
|
|
46
|
-
catch_error.
|
|
46
|
+
catch_error.orig_src = self.source
|
|
47
47
|
catch_error.line_no = e.line
|
|
48
48
|
catch_error.end_line = e.line
|
|
49
49
|
catch_error.c_start = e.column
|
|
50
50
|
catch_error.c_end = e.column + 1
|
|
51
|
-
|
|
51
|
+
catch_error.pos_start = e.pos_in_stream or 0
|
|
52
|
+
catch_error.pos_end = catch_error.pos_start + 1
|
|
53
|
+
|
|
54
|
+
error_msg = "Syntax Error"
|
|
55
|
+
if len(e.args) >= 1 and isinstance(e.args[0], str):
|
|
56
|
+
error_msg += e.args[0]
|
|
57
|
+
self.error(error_msg, node_override=catch_error)
|
|
58
|
+
|
|
52
59
|
except Exception as e:
|
|
53
60
|
self.error(f"Internal Error: {e}")
|
|
61
|
+
|
|
54
62
|
return ast.Module(
|
|
55
63
|
name="",
|
|
56
64
|
source=self.source,
|
|
@@ -65,7 +73,7 @@ class JacParser(Pass):
|
|
|
65
73
|
def proc_comment(token: jl.Token, mod: ast.AstNode) -> ast.CommentToken:
|
|
66
74
|
"""Process comment."""
|
|
67
75
|
return ast.CommentToken(
|
|
68
|
-
|
|
76
|
+
orig_src=mod.loc.orig_src,
|
|
69
77
|
name=token.type,
|
|
70
78
|
value=token.value,
|
|
71
79
|
line=token.line if token.line is not None else 0,
|
|
@@ -166,7 +174,7 @@ class JacParser(Pass):
|
|
|
166
174
|
kid=(
|
|
167
175
|
kid
|
|
168
176
|
if len(kid)
|
|
169
|
-
else [ast.EmptyToken(
|
|
177
|
+
else [ast.EmptyToken(ast.JacSource("", self.parse_ref.mod_path))]
|
|
170
178
|
),
|
|
171
179
|
)
|
|
172
180
|
return self.nu(mod)
|
|
@@ -706,10 +714,12 @@ class JacParser(Pass):
|
|
|
706
714
|
| NAME (COLON STRING)?
|
|
707
715
|
| py_code_block
|
|
708
716
|
| free_code
|
|
717
|
+
| abstract_ability
|
|
718
|
+
| ability
|
|
709
719
|
"""
|
|
710
|
-
if isinstance(kid[0], ast.PyInlineCode):
|
|
720
|
+
if isinstance(kid[0], (ast.PyInlineCode, ast.Ability)):
|
|
711
721
|
return self.nu(kid[0])
|
|
712
|
-
|
|
722
|
+
elif isinstance(kid[0], (ast.Name)):
|
|
713
723
|
if (
|
|
714
724
|
len(kid) >= 3
|
|
715
725
|
and isinstance(kid[-1], ast.Expr)
|
|
@@ -1010,7 +1020,11 @@ class JacParser(Pass):
|
|
|
1010
1020
|
kid=(
|
|
1011
1021
|
kid
|
|
1012
1022
|
if len(kid)
|
|
1013
|
-
else [
|
|
1023
|
+
else [
|
|
1024
|
+
ast.EmptyToken(
|
|
1025
|
+
ast.JacSource("", self.parse_ref.mod_path)
|
|
1026
|
+
)
|
|
1027
|
+
]
|
|
1014
1028
|
),
|
|
1015
1029
|
)
|
|
1016
1030
|
)
|
|
@@ -1228,7 +1242,7 @@ class JacParser(Pass):
|
|
|
1228
1242
|
return self.nu(
|
|
1229
1243
|
ast.BuiltinType(
|
|
1230
1244
|
name=kid[0].name,
|
|
1231
|
-
|
|
1245
|
+
orig_src=self.parse_ref.source,
|
|
1232
1246
|
value=kid[0].value,
|
|
1233
1247
|
line=kid[0].loc.first_line,
|
|
1234
1248
|
end_line=kid[0].loc.last_line,
|
|
@@ -2786,25 +2800,14 @@ class JacParser(Pass):
|
|
|
2786
2800
|
def name_list(self, kid: list[ast.AstNode]) -> ast.SubNodeList[ast.Name]:
|
|
2787
2801
|
"""Grammar rule.
|
|
2788
2802
|
|
|
2789
|
-
name_list: (
|
|
2803
|
+
name_list: (named_ref COMMA)* named_ref
|
|
2790
2804
|
"""
|
|
2791
|
-
|
|
2792
|
-
name = None
|
|
2793
|
-
comma = None
|
|
2794
|
-
if isinstance(kid[0], ast.SubNodeList):
|
|
2795
|
-
consume = kid[0]
|
|
2796
|
-
comma = kid[1]
|
|
2797
|
-
name = kid[2]
|
|
2798
|
-
new_kid = [*consume.kid, comma, name]
|
|
2799
|
-
else:
|
|
2800
|
-
name = kid[0]
|
|
2801
|
-
new_kid = [name]
|
|
2802
|
-
valid_kid = [i for i in new_kid if isinstance(i, ast.Name)]
|
|
2805
|
+
valid_kid = [i for i in kid if isinstance(i, ast.Name)]
|
|
2803
2806
|
return self.nu(
|
|
2804
2807
|
ast.SubNodeList[ast.Name](
|
|
2805
2808
|
items=valid_kid,
|
|
2806
2809
|
delim=Tok.COMMA,
|
|
2807
|
-
kid=
|
|
2810
|
+
kid=kid,
|
|
2808
2811
|
)
|
|
2809
2812
|
)
|
|
2810
2813
|
|
|
@@ -3996,7 +3999,7 @@ class JacParser(Pass):
|
|
|
3996
3999
|
elif token.type == Tok.PYNLINE and isinstance(token.value, str):
|
|
3997
4000
|
token.value = token.value.replace("::py::", "")
|
|
3998
4001
|
ret = ret_type(
|
|
3999
|
-
|
|
4002
|
+
orig_src=self.parse_ref.source,
|
|
4000
4003
|
name=token.type,
|
|
4001
4004
|
value=token.value[2:] if token.type == Tok.KWESC_NAME else token.value,
|
|
4002
4005
|
line=token.line if token.line is not None else 0,
|
|
@@ -140,11 +140,11 @@ class Pass(Transform[T]):
|
|
|
140
140
|
|
|
141
141
|
def error(self, msg: str, node_override: Optional[ast.AstNode] = None) -> None:
|
|
142
142
|
"""Pass Error."""
|
|
143
|
-
self.log_error(
|
|
143
|
+
self.log_error(msg, node_override=node_override)
|
|
144
144
|
|
|
145
145
|
def warning(self, msg: str, node_override: Optional[ast.AstNode] = None) -> None:
|
|
146
146
|
"""Pass Error."""
|
|
147
|
-
self.log_warning(
|
|
147
|
+
self.log_warning(msg, node_override=node_override)
|
|
148
148
|
|
|
149
149
|
def ice(self, msg: str = "Something went horribly wrong!") -> RuntimeError:
|
|
150
150
|
"""Pass Error."""
|
|
@@ -90,6 +90,10 @@ class DeclImplMatchPass(Pass):
|
|
|
90
90
|
raise self.ice(
|
|
91
91
|
f"Expected AstImplNeedingNode, got {valid_decl.__class__.__name__}. Not possible."
|
|
92
92
|
)
|
|
93
|
+
|
|
94
|
+
# Ensure if it's an ability def impl, the parameters are matched.
|
|
95
|
+
self.validate_params_match(sym, decl_node.name_of)
|
|
96
|
+
|
|
93
97
|
valid_decl.body = sym.decl.name_of
|
|
94
98
|
sym.decl.name_of.decl_link = valid_decl
|
|
95
99
|
for idx, a in enumerate(sym.decl.name_of.target.archs):
|
|
@@ -97,5 +101,47 @@ class DeclImplMatchPass(Pass):
|
|
|
97
101
|
a.name_spec.sym = name_of_links[idx].sym
|
|
98
102
|
sym.decl.name_of.sym_tab.tab.update(valid_decl.sym_tab.tab)
|
|
99
103
|
valid_decl.sym_tab.tab = sym.decl.name_of.sym_tab.tab
|
|
104
|
+
|
|
100
105
|
for i in sym_tab.kid:
|
|
101
106
|
self.connect_def_impl(i)
|
|
107
|
+
|
|
108
|
+
def validate_params_match(self, sym: Symbol, valid_decl: ast.AstSymbolNode) -> None:
|
|
109
|
+
"""Validate if the parameters match."""
|
|
110
|
+
if (
|
|
111
|
+
isinstance(valid_decl, ast.Ability)
|
|
112
|
+
and isinstance(sym.decl.name_of, ast.AbilityDef)
|
|
113
|
+
and isinstance(valid_decl.signature, ast.FuncSignature)
|
|
114
|
+
and isinstance(sym.decl.name_of.signature, ast.FuncSignature)
|
|
115
|
+
):
|
|
116
|
+
|
|
117
|
+
params_decl = valid_decl.signature.params
|
|
118
|
+
params_defn = sym.decl.name_of.signature.params
|
|
119
|
+
|
|
120
|
+
if params_decl and params_defn:
|
|
121
|
+
# Check if the parameter count is matched.
|
|
122
|
+
if len(params_defn.items) != len(params_decl.items):
|
|
123
|
+
self.error(
|
|
124
|
+
f"Parameter count mismatch for ability {sym.sym_name}.",
|
|
125
|
+
sym.decl.name_of.name_spec,
|
|
126
|
+
)
|
|
127
|
+
self.error(
|
|
128
|
+
f"From the declaration of {valid_decl.name_spec.sym_name}.",
|
|
129
|
+
valid_decl.name_spec,
|
|
130
|
+
)
|
|
131
|
+
else:
|
|
132
|
+
for idx in range(len(params_defn.items)):
|
|
133
|
+
# Check if all the parameter names are matched.
|
|
134
|
+
# TODO: This shouldn't be an issue however if the names are not matched, it doesn't
|
|
135
|
+
# work as expected like in C++, for now I'm adding this validation, however this
|
|
136
|
+
# needs to be fixed to have a C++ style.
|
|
137
|
+
param_name_decl = params_decl.items[idx].name.value
|
|
138
|
+
param_name_defn = params_defn.items[idx].name.value
|
|
139
|
+
if param_name_defn != param_name_decl:
|
|
140
|
+
self.error(
|
|
141
|
+
f"Parameter name mismatch for ability {sym.sym_name}.",
|
|
142
|
+
params_defn.items[idx].name,
|
|
143
|
+
)
|
|
144
|
+
self.error(
|
|
145
|
+
f"From the declaration of {valid_decl.name_spec.sym_name}.",
|
|
146
|
+
params_decl.items[idx].name,
|
|
147
|
+
)
|