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.
- jaclang/cli/cli.py +46 -29
- jaclang/compiler/__init__.py +2 -2
- jaclang/compiler/absyntree.py +114 -66
- jaclang/compiler/codeloc.py +7 -2
- jaclang/compiler/compile.py +10 -3
- jaclang/compiler/jac.lark +4 -1
- jaclang/compiler/parser.py +63 -43
- jaclang/compiler/passes/ir_pass.py +2 -2
- jaclang/compiler/passes/main/def_impl_match_pass.py +83 -0
- jaclang/compiler/passes/main/def_use_pass.py +1 -2
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +146 -123
- jaclang/compiler/passes/main/import_pass.py +6 -2
- jaclang/compiler/passes/main/pyast_gen_pass.py +46 -20
- jaclang/compiler/passes/main/pyast_load_pass.py +56 -41
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +7 -7
- jaclang/compiler/passes/main/registry_pass.py +3 -12
- jaclang/compiler/passes/main/sym_tab_build_pass.py +1 -2
- 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/fixtures/uninitialized_hasvars.jac +26 -0
- jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +66 -0
- jaclang/compiler/passes/main/tests/test_def_use_pass.py +3 -3
- 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/tool/jac_formatter_pass.py +2 -2
- jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +3 -3
- jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +3 -3
- 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/compiler/tests/test_parser.py +7 -1
- 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 +80 -43
- jaclang/plugin/feature.py +12 -2
- jaclang/plugin/plugin.md +471 -0
- jaclang/plugin/spec.py +14 -1
- jaclang/plugin/tests/fixtures/graph_purger.jac +101 -0
- jaclang/plugin/tests/fixtures/other_root_access.jac +9 -0
- jaclang/plugin/tests/test_jaseci.py +126 -6
- jaclang/runtimelib/architype.py +12 -1
- jaclang/runtimelib/context.py +2 -0
- jaclang/runtimelib/importer.py +7 -2
- jaclang/runtimelib/machine.py +21 -6
- jaclang/runtimelib/memory.py +5 -1
- jaclang/settings.py +3 -0
- jaclang/tests/fixtures/architype_def_bug.jac +17 -0
- jaclang/tests/fixtures/builtin_dotgen.jac +6 -6
- jaclang/tests/fixtures/decl_defn_param_name.jac +19 -0
- 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/multi_dim_array_split.jac +19 -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 +86 -4
- jaclang/tests/test_language.py +104 -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.26.dist-info}/METADATA +2 -1
- {jaclang-0.7.23.dist-info → jaclang-0.7.26.dist-info}/RECORD +68 -57
- {jaclang-0.7.23.dist-info → jaclang-0.7.26.dist-info}/WHEEL +1 -1
- {jaclang-0.7.23.dist-info → jaclang-0.7.26.dist-info}/entry_points.txt +0 -0
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,
|
|
@@ -2422,8 +2436,11 @@ class JacParser(Pass):
|
|
|
2422
2436
|
def index_slice(self, kid: list[ast.AstNode]) -> ast.IndexSlice:
|
|
2423
2437
|
"""Grammar rule.
|
|
2424
2438
|
|
|
2425
|
-
index_slice: LSQUARE
|
|
2426
|
-
|
|
2439
|
+
index_slice: LSQUARE \
|
|
2440
|
+
expression? COLON expression? (COLON expression?)? \
|
|
2441
|
+
(COMMA expression? COLON expression? (COLON expression?)?)* \
|
|
2442
|
+
RSQUARE
|
|
2443
|
+
| list_val
|
|
2427
2444
|
"""
|
|
2428
2445
|
if len(kid) == 1:
|
|
2429
2446
|
index = kid[0]
|
|
@@ -2440,9 +2457,9 @@ class JacParser(Pass):
|
|
|
2440
2457
|
kid = [expr]
|
|
2441
2458
|
return self.nu(
|
|
2442
2459
|
ast.IndexSlice(
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2460
|
+
slices=[
|
|
2461
|
+
ast.IndexSlice.Slice(start=expr, stop=None, step=None)
|
|
2462
|
+
],
|
|
2446
2463
|
is_range=False,
|
|
2447
2464
|
kid=kid,
|
|
2448
2465
|
)
|
|
@@ -2450,25 +2467,39 @@ class JacParser(Pass):
|
|
|
2450
2467
|
else:
|
|
2451
2468
|
raise self.ice()
|
|
2452
2469
|
else:
|
|
2453
|
-
|
|
2470
|
+
slices: list[ast.IndexSlice.Slice] = []
|
|
2454
2471
|
chomp = kid[1:]
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
chomp
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
chomp = chomp[1:]
|
|
2462
|
-
if isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.COLON:
|
|
2463
|
-
chomp = chomp[1:]
|
|
2472
|
+
|
|
2473
|
+
while not (
|
|
2474
|
+
isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.RSQUARE
|
|
2475
|
+
):
|
|
2476
|
+
expr1 = expr2 = expr3 = None
|
|
2477
|
+
|
|
2464
2478
|
if isinstance(chomp[0], ast.Expr):
|
|
2465
|
-
|
|
2466
|
-
chomp
|
|
2479
|
+
expr1 = chomp[0]
|
|
2480
|
+
chomp.pop(0)
|
|
2481
|
+
chomp.pop(0)
|
|
2482
|
+
|
|
2483
|
+
if isinstance(chomp[0], ast.Expr):
|
|
2484
|
+
expr2 = chomp[0]
|
|
2485
|
+
chomp.pop(0)
|
|
2486
|
+
|
|
2487
|
+
if isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.COLON:
|
|
2488
|
+
chomp.pop(0)
|
|
2489
|
+
if isinstance(chomp[0], ast.Expr):
|
|
2490
|
+
expr3 = chomp[0]
|
|
2491
|
+
chomp.pop(0)
|
|
2492
|
+
|
|
2493
|
+
if isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.COMMA:
|
|
2494
|
+
chomp.pop(0)
|
|
2495
|
+
|
|
2496
|
+
slices.append(
|
|
2497
|
+
ast.IndexSlice.Slice(start=expr1, stop=expr2, step=expr3)
|
|
2498
|
+
)
|
|
2499
|
+
|
|
2467
2500
|
return self.nu(
|
|
2468
2501
|
ast.IndexSlice(
|
|
2469
|
-
|
|
2470
|
-
stop=expr2,
|
|
2471
|
-
step=expr3,
|
|
2502
|
+
slices=slices,
|
|
2472
2503
|
is_range=True,
|
|
2473
2504
|
kid=kid,
|
|
2474
2505
|
)
|
|
@@ -2786,25 +2817,14 @@ class JacParser(Pass):
|
|
|
2786
2817
|
def name_list(self, kid: list[ast.AstNode]) -> ast.SubNodeList[ast.Name]:
|
|
2787
2818
|
"""Grammar rule.
|
|
2788
2819
|
|
|
2789
|
-
name_list: (
|
|
2820
|
+
name_list: (named_ref COMMA)* named_ref
|
|
2790
2821
|
"""
|
|
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)]
|
|
2822
|
+
valid_kid = [i for i in kid if isinstance(i, ast.Name)]
|
|
2803
2823
|
return self.nu(
|
|
2804
2824
|
ast.SubNodeList[ast.Name](
|
|
2805
2825
|
items=valid_kid,
|
|
2806
2826
|
delim=Tok.COMMA,
|
|
2807
|
-
kid=
|
|
2827
|
+
kid=kid,
|
|
2808
2828
|
)
|
|
2809
2829
|
)
|
|
2810
2830
|
|
|
@@ -3996,7 +4016,7 @@ class JacParser(Pass):
|
|
|
3996
4016
|
elif token.type == Tok.PYNLINE and isinstance(token.value, str):
|
|
3997
4017
|
token.value = token.value.replace("::py::", "")
|
|
3998
4018
|
ret = ret_type(
|
|
3999
|
-
|
|
4019
|
+
orig_src=self.parse_ref.source,
|
|
4000
4020
|
name=token.type,
|
|
4001
4021
|
value=token.value[2:] if token.type == Tok.KWESC_NAME else token.value,
|
|
4002
4022
|
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."""
|
|
@@ -7,6 +7,7 @@ body field.
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
import jaclang.compiler.absyntree as ast
|
|
10
|
+
from jaclang.compiler.constant import Tokens as Tok
|
|
10
11
|
from jaclang.compiler.passes import Pass
|
|
11
12
|
from jaclang.compiler.passes.main import SubNodeTabPass
|
|
12
13
|
from jaclang.compiler.symtable import Symbol, SymbolTable
|
|
@@ -90,6 +91,10 @@ class DeclImplMatchPass(Pass):
|
|
|
90
91
|
raise self.ice(
|
|
91
92
|
f"Expected AstImplNeedingNode, got {valid_decl.__class__.__name__}. Not possible."
|
|
92
93
|
)
|
|
94
|
+
|
|
95
|
+
# Ensure if it's an ability def impl, the parameters are matched.
|
|
96
|
+
self.validate_params_match(sym, decl_node.name_of)
|
|
97
|
+
|
|
93
98
|
valid_decl.body = sym.decl.name_of
|
|
94
99
|
sym.decl.name_of.decl_link = valid_decl
|
|
95
100
|
for idx, a in enumerate(sym.decl.name_of.target.archs):
|
|
@@ -97,5 +102,83 @@ class DeclImplMatchPass(Pass):
|
|
|
97
102
|
a.name_spec.sym = name_of_links[idx].sym
|
|
98
103
|
sym.decl.name_of.sym_tab.tab.update(valid_decl.sym_tab.tab)
|
|
99
104
|
valid_decl.sym_tab.tab = sym.decl.name_of.sym_tab.tab
|
|
105
|
+
|
|
100
106
|
for i in sym_tab.kid:
|
|
101
107
|
self.connect_def_impl(i)
|
|
108
|
+
|
|
109
|
+
def validate_params_match(self, sym: Symbol, valid_decl: ast.AstSymbolNode) -> None:
|
|
110
|
+
"""Validate if the parameters match."""
|
|
111
|
+
if (
|
|
112
|
+
isinstance(valid_decl, ast.Ability)
|
|
113
|
+
and isinstance(sym.decl.name_of, ast.AbilityDef)
|
|
114
|
+
and isinstance(valid_decl.signature, ast.FuncSignature)
|
|
115
|
+
and isinstance(sym.decl.name_of.signature, ast.FuncSignature)
|
|
116
|
+
):
|
|
117
|
+
|
|
118
|
+
params_decl = valid_decl.signature.params
|
|
119
|
+
params_defn = sym.decl.name_of.signature.params
|
|
120
|
+
|
|
121
|
+
if params_decl and params_defn:
|
|
122
|
+
# Check if the parameter count is matched.
|
|
123
|
+
if len(params_defn.items) != len(params_decl.items):
|
|
124
|
+
self.error(
|
|
125
|
+
f"Parameter count mismatch for ability {sym.sym_name}.",
|
|
126
|
+
sym.decl.name_of.name_spec,
|
|
127
|
+
)
|
|
128
|
+
self.error(
|
|
129
|
+
f"From the declaration of {valid_decl.name_spec.sym_name}.",
|
|
130
|
+
valid_decl.name_spec,
|
|
131
|
+
)
|
|
132
|
+
else:
|
|
133
|
+
# Copy the parameter names from the declaration to the definition.
|
|
134
|
+
for idx in range(len(params_defn.items)):
|
|
135
|
+
params_decl.items[idx] = params_defn.items[idx]
|
|
136
|
+
for idx in range(len(params_defn.kid)):
|
|
137
|
+
params_decl.kid[idx] = params_defn.kid[idx]
|
|
138
|
+
|
|
139
|
+
def exit_architype(self, node: ast.Architype) -> None:
|
|
140
|
+
"""Exit Architype."""
|
|
141
|
+
if node.arch_type.name == Tok.KW_OBJECT and isinstance(
|
|
142
|
+
node.body, ast.SubNodeList
|
|
143
|
+
):
|
|
144
|
+
|
|
145
|
+
found_default_init = False
|
|
146
|
+
for stmnt in node.body.items:
|
|
147
|
+
if not isinstance(stmnt, ast.ArchHas):
|
|
148
|
+
continue
|
|
149
|
+
for var in stmnt.vars.items:
|
|
150
|
+
if (var.value is not None) or (var.defer):
|
|
151
|
+
found_default_init = True
|
|
152
|
+
else:
|
|
153
|
+
if found_default_init:
|
|
154
|
+
self.error(
|
|
155
|
+
f"Non default attribute '{var.name.value}' follows default attribute",
|
|
156
|
+
node_override=var.name,
|
|
157
|
+
)
|
|
158
|
+
break
|
|
159
|
+
|
|
160
|
+
post_init_vars: list[ast.HasVar] = []
|
|
161
|
+
postinit_method: ast.Ability | None = None
|
|
162
|
+
|
|
163
|
+
for item in node.body.items:
|
|
164
|
+
|
|
165
|
+
if isinstance(item, ast.ArchHas):
|
|
166
|
+
for var in item.vars.items:
|
|
167
|
+
if var.defer:
|
|
168
|
+
post_init_vars.append(var)
|
|
169
|
+
|
|
170
|
+
elif isinstance(item, ast.Ability):
|
|
171
|
+
if item.is_abstract:
|
|
172
|
+
continue
|
|
173
|
+
if (
|
|
174
|
+
isinstance(item.name_ref, ast.SpecialVarRef)
|
|
175
|
+
and item.name_ref.name == "KW_POST_INIT"
|
|
176
|
+
):
|
|
177
|
+
postinit_method = item
|
|
178
|
+
|
|
179
|
+
# Check if postinit needed and not provided.
|
|
180
|
+
if len(post_init_vars) != 0 and (postinit_method is None):
|
|
181
|
+
self.error(
|
|
182
|
+
'Missing "postinit" method required by un initialized attribute(s).',
|
|
183
|
+
node_override=post_init_vars[0].name_spec,
|
|
184
|
+
) # We show the error on the first uninitialized var.
|