jaclang 0.7.25__py3-none-any.whl → 0.7.27__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/compiler/absyntree.py +27 -18
- jaclang/compiler/jac.lark +4 -1
- jaclang/compiler/parser.py +37 -20
- jaclang/compiler/passes/main/def_impl_match_pass.py +50 -13
- jaclang/compiler/passes/main/def_use_pass.py +1 -2
- jaclang/compiler/passes/main/pyast_gen_pass.py +46 -20
- jaclang/compiler/passes/main/pyast_load_pass.py +20 -6
- jaclang/compiler/passes/main/sym_tab_build_pass.py +1 -2
- jaclang/compiler/passes/main/tests/fixtures/uninitialized_hasvars.jac +26 -0
- jaclang/compiler/passes/main/tests/test_decl_def_match_pass.py +36 -29
- jaclang/compiler/passes/main/tests/test_def_use_pass.py +3 -3
- 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/tests/test_parser.py +7 -1
- jaclang/plugin/default.py +64 -18
- jaclang/plugin/feature.py +16 -1
- jaclang/plugin/spec.py +14 -2
- jaclang/plugin/tests/fixtures/graph_purger.jac +101 -0
- jaclang/plugin/tests/fixtures/other_root_access.jac +19 -0
- jaclang/plugin/tests/fixtures/savable_object.jac +84 -0
- jaclang/plugin/tests/test_jaseci.py +214 -6
- jaclang/runtimelib/architype.py +29 -1
- jaclang/runtimelib/memory.py +27 -8
- jaclang/runtimelib/utils.py +16 -0
- jaclang/tests/fixtures/architype_def_bug.jac +17 -0
- jaclang/tests/fixtures/decl_defn_param_name.jac +19 -0
- jaclang/tests/fixtures/multi_dim_array_split.jac +19 -0
- jaclang/tests/test_cli.py +18 -0
- jaclang/tests/test_language.py +43 -0
- {jaclang-0.7.25.dist-info → jaclang-0.7.27.dist-info}/METADATA +1 -1
- {jaclang-0.7.25.dist-info → jaclang-0.7.27.dist-info}/RECORD +34 -28
- {jaclang-0.7.25.dist-info → jaclang-0.7.27.dist-info}/WHEEL +0 -0
- {jaclang-0.7.25.dist-info → jaclang-0.7.27.dist-info}/entry_points.txt +0 -0
jaclang/compiler/absyntree.py
CHANGED
|
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import ast as ast3
|
|
6
6
|
import builtins
|
|
7
7
|
import os
|
|
8
|
+
from dataclasses import dataclass
|
|
8
9
|
from hashlib import md5
|
|
9
10
|
from types import EllipsisType
|
|
10
11
|
from typing import (
|
|
@@ -3401,18 +3402,22 @@ class FuncCall(Expr):
|
|
|
3401
3402
|
class IndexSlice(AtomExpr):
|
|
3402
3403
|
"""IndexSlice node type for Jac Ast."""
|
|
3403
3404
|
|
|
3405
|
+
@dataclass
|
|
3406
|
+
class Slice:
|
|
3407
|
+
"""Slice node for index slice."""
|
|
3408
|
+
|
|
3409
|
+
start: Optional[Expr]
|
|
3410
|
+
stop: Optional[Expr]
|
|
3411
|
+
step: Optional[Expr]
|
|
3412
|
+
|
|
3404
3413
|
def __init__(
|
|
3405
3414
|
self,
|
|
3406
|
-
|
|
3407
|
-
stop: Optional[Expr],
|
|
3408
|
-
step: Optional[Expr],
|
|
3415
|
+
slices: list[Slice],
|
|
3409
3416
|
is_range: bool,
|
|
3410
3417
|
kid: Sequence[AstNode],
|
|
3411
3418
|
) -> None:
|
|
3412
3419
|
"""Initialize index slice expression node."""
|
|
3413
|
-
self.
|
|
3414
|
-
self.stop = stop
|
|
3415
|
-
self.step = step
|
|
3420
|
+
self.slices = slices
|
|
3416
3421
|
self.is_range = is_range
|
|
3417
3422
|
AstNode.__init__(self, kid=kid)
|
|
3418
3423
|
Expr.__init__(self)
|
|
@@ -3422,22 +3427,26 @@ class IndexSlice(AtomExpr):
|
|
|
3422
3427
|
"""Normalize ast node."""
|
|
3423
3428
|
res = True
|
|
3424
3429
|
if deep:
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3430
|
+
for slice in self.slices:
|
|
3431
|
+
res = slice.start.normalize(deep) if slice.start else res
|
|
3432
|
+
res = res and slice.stop.normalize(deep) if slice.stop else res
|
|
3433
|
+
res = res and slice.step.normalize(deep) if slice.step else res
|
|
3428
3434
|
new_kid: list[AstNode] = []
|
|
3429
3435
|
new_kid.append(self.gen_token(Tok.LSQUARE))
|
|
3430
3436
|
if self.is_range:
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3437
|
+
for i, slice in enumerate(self.slices):
|
|
3438
|
+
if i > 0:
|
|
3439
|
+
new_kid.append(self.gen_token(Tok.COMMA))
|
|
3440
|
+
if slice.start:
|
|
3441
|
+
new_kid.append(slice.start)
|
|
3434
3442
|
new_kid.append(self.gen_token(Tok.COLON))
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3443
|
+
if slice.stop:
|
|
3444
|
+
new_kid.append(slice.stop)
|
|
3445
|
+
if slice.step:
|
|
3446
|
+
new_kid.append(self.gen_token(Tok.COLON))
|
|
3447
|
+
new_kid.append(slice.step)
|
|
3448
|
+
elif len(self.slices) == 1 and self.slices[0].start:
|
|
3449
|
+
new_kid.append(self.slices[0].start)
|
|
3441
3450
|
else:
|
|
3442
3451
|
res = False
|
|
3443
3452
|
new_kid.append(self.gen_token(Tok.RSQUARE))
|
jaclang/compiler/jac.lark
CHANGED
|
@@ -358,7 +358,10 @@ atomic_chain: atomic_chain NULL_OK? (filter_compr | assign_compr | index_slice)
|
|
|
358
358
|
| atomic_chain NULL_OK? (DOT_BKWD | DOT_FWD | DOT) named_ref
|
|
359
359
|
| (atomic_call | atom | edge_ref_chain)
|
|
360
360
|
|
|
361
|
-
index_slice: LSQUARE
|
|
361
|
+
index_slice: LSQUARE \
|
|
362
|
+
expression? COLON expression? (COLON expression?)? \
|
|
363
|
+
(COMMA expression? COLON expression? (COLON expression?)?)* \
|
|
364
|
+
RSQUARE
|
|
362
365
|
| list_val
|
|
363
366
|
|
|
364
367
|
// Function calls
|
jaclang/compiler/parser.py
CHANGED
|
@@ -2436,8 +2436,11 @@ class JacParser(Pass):
|
|
|
2436
2436
|
def index_slice(self, kid: list[ast.AstNode]) -> ast.IndexSlice:
|
|
2437
2437
|
"""Grammar rule.
|
|
2438
2438
|
|
|
2439
|
-
index_slice: LSQUARE
|
|
2440
|
-
|
|
2439
|
+
index_slice: LSQUARE \
|
|
2440
|
+
expression? COLON expression? (COLON expression?)? \
|
|
2441
|
+
(COMMA expression? COLON expression? (COLON expression?)?)* \
|
|
2442
|
+
RSQUARE
|
|
2443
|
+
| list_val
|
|
2441
2444
|
"""
|
|
2442
2445
|
if len(kid) == 1:
|
|
2443
2446
|
index = kid[0]
|
|
@@ -2454,9 +2457,9 @@ class JacParser(Pass):
|
|
|
2454
2457
|
kid = [expr]
|
|
2455
2458
|
return self.nu(
|
|
2456
2459
|
ast.IndexSlice(
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
+
slices=[
|
|
2461
|
+
ast.IndexSlice.Slice(start=expr, stop=None, step=None)
|
|
2462
|
+
],
|
|
2460
2463
|
is_range=False,
|
|
2461
2464
|
kid=kid,
|
|
2462
2465
|
)
|
|
@@ -2464,25 +2467,39 @@ class JacParser(Pass):
|
|
|
2464
2467
|
else:
|
|
2465
2468
|
raise self.ice()
|
|
2466
2469
|
else:
|
|
2467
|
-
|
|
2470
|
+
slices: list[ast.IndexSlice.Slice] = []
|
|
2468
2471
|
chomp = kid[1:]
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
chomp
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
chomp = chomp[1:]
|
|
2476
|
-
if isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.COLON:
|
|
2477
|
-
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
|
+
|
|
2478
2478
|
if isinstance(chomp[0], ast.Expr):
|
|
2479
|
-
|
|
2480
|
-
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
|
+
|
|
2481
2500
|
return self.nu(
|
|
2482
2501
|
ast.IndexSlice(
|
|
2483
|
-
|
|
2484
|
-
stop=expr2,
|
|
2485
|
-
step=expr3,
|
|
2502
|
+
slices=slices,
|
|
2486
2503
|
is_range=True,
|
|
2487
2504
|
kid=kid,
|
|
2488
2505
|
)
|
|
@@ -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
|
|
@@ -129,19 +130,55 @@ class DeclImplMatchPass(Pass):
|
|
|
129
130
|
valid_decl.name_spec,
|
|
130
131
|
)
|
|
131
132
|
else:
|
|
133
|
+
# Copy the parameter names from the declaration to the definition.
|
|
132
134
|
for idx in range(len(params_defn.items)):
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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:
|
|
144
154
|
self.error(
|
|
145
|
-
f"
|
|
146
|
-
|
|
155
|
+
f"Non default attribute '{var.name.value}' follows default attribute",
|
|
156
|
+
node_override=var.name,
|
|
147
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.
|
|
@@ -1055,14 +1055,7 @@ class PyastGenPass(Pass):
|
|
|
1055
1055
|
ctx=ast3.Load(),
|
|
1056
1056
|
)
|
|
1057
1057
|
),
|
|
1058
|
-
args=[
|
|
1059
|
-
self.sync(ast3.Constant(value=i.sym_name)),
|
|
1060
|
-
(
|
|
1061
|
-
i.signature.arch_tag_info.gen.py_ast[0]
|
|
1062
|
-
if i.signature.arch_tag_info
|
|
1063
|
-
else self.sync(ast3.Constant(value=None))
|
|
1064
|
-
),
|
|
1065
|
-
],
|
|
1058
|
+
args=[self.sync(ast3.Constant(value=i.sym_name))],
|
|
1066
1059
|
keywords=[],
|
|
1067
1060
|
)
|
|
1068
1061
|
)
|
|
@@ -3081,23 +3074,56 @@ class PyastGenPass(Pass):
|
|
|
3081
3074
|
def exit_index_slice(self, node: ast.IndexSlice) -> None:
|
|
3082
3075
|
"""Sub objects.
|
|
3083
3076
|
|
|
3084
|
-
|
|
3085
|
-
stop: Optional[ExprType],
|
|
3086
|
-
step: Optional[ExprType],
|
|
3077
|
+
slices: list[IndexSlice.Slice],
|
|
3087
3078
|
is_range: bool,
|
|
3088
3079
|
"""
|
|
3089
3080
|
if node.is_range:
|
|
3090
|
-
node.
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3081
|
+
if len(node.slices) > 1: # Multiple slices. Example arr[a:b, c:d]
|
|
3082
|
+
node.gen.py_ast = [
|
|
3083
|
+
self.sync(
|
|
3084
|
+
ast3.Tuple(
|
|
3085
|
+
elts=[
|
|
3086
|
+
self.sync(
|
|
3087
|
+
ast3.Slice(
|
|
3088
|
+
lower=(
|
|
3089
|
+
slice.start.gen.py_ast[0]
|
|
3090
|
+
if slice.start
|
|
3091
|
+
else None
|
|
3092
|
+
),
|
|
3093
|
+
upper=(
|
|
3094
|
+
slice.stop.gen.py_ast[0]
|
|
3095
|
+
if slice.stop
|
|
3096
|
+
else None
|
|
3097
|
+
),
|
|
3098
|
+
step=(
|
|
3099
|
+
slice.step.gen.py_ast[0]
|
|
3100
|
+
if slice.step
|
|
3101
|
+
else None
|
|
3102
|
+
),
|
|
3103
|
+
)
|
|
3104
|
+
)
|
|
3105
|
+
for slice in node.slices
|
|
3106
|
+
],
|
|
3107
|
+
ctx=ast3.Load(),
|
|
3108
|
+
)
|
|
3096
3109
|
)
|
|
3097
|
-
|
|
3098
|
-
]
|
|
3110
|
+
]
|
|
3111
|
+
elif len(node.slices) == 1: # Single slice. Example arr[a]
|
|
3112
|
+
slice = node.slices[0]
|
|
3113
|
+
node.gen.py_ast = [
|
|
3114
|
+
self.sync(
|
|
3115
|
+
ast3.Slice(
|
|
3116
|
+
lower=slice.start.gen.py_ast[0] if slice.start else None,
|
|
3117
|
+
upper=slice.stop.gen.py_ast[0] if slice.stop else None,
|
|
3118
|
+
step=slice.step.gen.py_ast[0] if slice.step else None,
|
|
3119
|
+
)
|
|
3120
|
+
)
|
|
3121
|
+
]
|
|
3099
3122
|
else:
|
|
3100
|
-
node.
|
|
3123
|
+
if len(node.slices) > 0 and node.slices[0].start is not None:
|
|
3124
|
+
node.gen.py_ast = node.slices[0].start.gen.py_ast
|
|
3125
|
+
else:
|
|
3126
|
+
node.gen.py_ast = []
|
|
3101
3127
|
|
|
3102
3128
|
def exit_special_var_ref(self, node: ast.SpecialVarRef) -> None:
|
|
3103
3129
|
"""Sub objects.
|
|
@@ -2026,9 +2026,7 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
2026
2026
|
and (isinstance(step, ast.Expr) or step is None)
|
|
2027
2027
|
):
|
|
2028
2028
|
return ast.IndexSlice(
|
|
2029
|
-
|
|
2030
|
-
stop=upper,
|
|
2031
|
-
step=step,
|
|
2029
|
+
slices=[ast.IndexSlice.Slice(lower, upper, step)],
|
|
2032
2030
|
is_range=True,
|
|
2033
2031
|
kid=valid_kid,
|
|
2034
2032
|
)
|
|
@@ -2061,12 +2059,28 @@ class PyastBuildPass(Pass[ast.PythonModuleAst]):
|
|
|
2061
2059
|
slice = self.convert(node.slice)
|
|
2062
2060
|
if not isinstance(slice, ast.IndexSlice) and isinstance(slice, ast.Expr):
|
|
2063
2061
|
slice = ast.IndexSlice(
|
|
2064
|
-
|
|
2065
|
-
stop=None,
|
|
2066
|
-
step=None,
|
|
2062
|
+
slices=[ast.IndexSlice.Slice(slice, None, None)],
|
|
2067
2063
|
is_range=False,
|
|
2068
2064
|
kid=[slice],
|
|
2069
2065
|
)
|
|
2066
|
+
if (
|
|
2067
|
+
not isinstance(slice, ast.IndexSlice)
|
|
2068
|
+
and isinstance(slice, ast.TupleVal)
|
|
2069
|
+
and slice.values is not None
|
|
2070
|
+
):
|
|
2071
|
+
|
|
2072
|
+
slices: list[ast.IndexSlice.Slice] = []
|
|
2073
|
+
for index_slice in slice.values.items:
|
|
2074
|
+
if not isinstance(index_slice, ast.IndexSlice):
|
|
2075
|
+
raise self.ice()
|
|
2076
|
+
slices.append(index_slice.slices[0])
|
|
2077
|
+
|
|
2078
|
+
slice = ast.IndexSlice(
|
|
2079
|
+
slices=slices,
|
|
2080
|
+
is_range=True,
|
|
2081
|
+
kid=[slice],
|
|
2082
|
+
)
|
|
2083
|
+
|
|
2070
2084
|
if isinstance(value, ast.Expr) and isinstance(slice, ast.IndexSlice):
|
|
2071
2085
|
return ast.AtomTrailer(
|
|
2072
2086
|
target=value,
|
|
@@ -995,8 +995,7 @@ class SymTabBuildPass(Pass):
|
|
|
995
995
|
def enter_index_slice(self, node: ast.IndexSlice) -> None:
|
|
996
996
|
"""Sub objects.
|
|
997
997
|
|
|
998
|
-
|
|
999
|
-
stop: Optional[ExprType],
|
|
998
|
+
slices: list[Slice],
|
|
1000
999
|
is_range: bool,
|
|
1001
1000
|
"""
|
|
1002
1001
|
self.sync_node_to_scope(node)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
|
|
2
|
+
# 1. Test initialization order.
|
|
3
|
+
obj Test1 {
|
|
4
|
+
has var1: int;
|
|
5
|
+
has var2: int = 42;
|
|
6
|
+
has var3: int; # <-- This should be syntax error.
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# 2. Test if postinit is needed but not provided.
|
|
11
|
+
obj Test2 {
|
|
12
|
+
has var1: str;
|
|
13
|
+
has var2: int by postinit;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
# 3. Postinit should be considered as has default initialization.
|
|
17
|
+
obj Test3 {
|
|
18
|
+
has var1: int;
|
|
19
|
+
has var2: int = 42;
|
|
20
|
+
has var3: int by postinit; # <-- This is fine.
|
|
21
|
+
has var4: int; # <-- This should be syntax error.
|
|
22
|
+
|
|
23
|
+
can postinit() {
|
|
24
|
+
self.var3 = 3;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -43,35 +43,6 @@ class DeclImplMatchPassTests(TestCase):
|
|
|
43
43
|
for exp in expected_stdout_values:
|
|
44
44
|
self.assertIn(exp, errors_output)
|
|
45
45
|
|
|
46
|
-
def test_parameter_name_mismatch(self) -> None:
|
|
47
|
-
"""Basic test for pass."""
|
|
48
|
-
state = jac_file_to_pass(
|
|
49
|
-
self.fixture_abs_path("defn_decl_mismatch.jac"), DeclImplMatchPass
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
expected_stdout_values = (
|
|
53
|
-
"Parameter name mismatch for ability (o)SomeObj.(c)bar.",
|
|
54
|
-
" 14 |",
|
|
55
|
-
" 15 | # Mis matching parameter name.",
|
|
56
|
-
" 16 | :obj:SomeObj:can:bar(param1: str, praam2:int) -> str {",
|
|
57
|
-
" | ^^^^^^",
|
|
58
|
-
' 17 | return "bar";',
|
|
59
|
-
" 18 | }",
|
|
60
|
-
"From the declaration of bar.",
|
|
61
|
-
" 3 | obj SomeObj {",
|
|
62
|
-
" 4 | can foo(param1: str, param2:int) -> str;",
|
|
63
|
-
" 5 | can bar(param1: str, param2:int) -> str;",
|
|
64
|
-
" | ^^^^^^",
|
|
65
|
-
" 6 | }",
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
errors_output = ""
|
|
69
|
-
for error in state.errors_had:
|
|
70
|
-
errors_output += error.pretty_print() + "\n"
|
|
71
|
-
|
|
72
|
-
for exp in expected_stdout_values:
|
|
73
|
-
self.assertIn(exp, errors_output)
|
|
74
|
-
|
|
75
46
|
def test_ability_connected_to_decl(self) -> None:
|
|
76
47
|
"""Basic test for pass."""
|
|
77
48
|
state = jac_file_to_pass(self.fixture_abs_path("base.jac"), DeclImplMatchPass)
|
|
@@ -105,3 +76,39 @@ class DeclImplMatchPassTests(TestCase):
|
|
|
105
76
|
)
|
|
106
77
|
for i in state.ir.get_all_sub_nodes(ast.ArchRef):
|
|
107
78
|
self.assertIsNotNone(i.sym)
|
|
79
|
+
|
|
80
|
+
def test_obj_hasvar_initialization(self) -> None:
|
|
81
|
+
"""Basic test for pass."""
|
|
82
|
+
state = jac_file_to_pass(
|
|
83
|
+
self.fixture_abs_path("uninitialized_hasvars.jac"), DeclImplMatchPass
|
|
84
|
+
)
|
|
85
|
+
self.assertTrue(state.errors_had)
|
|
86
|
+
|
|
87
|
+
expected_stdout_values = (
|
|
88
|
+
"Non default attribute 'var3' follows default attribute",
|
|
89
|
+
" 4 | has var1: int;",
|
|
90
|
+
" 5 | has var2: int = 42;",
|
|
91
|
+
" 6 | has var3: int; # <-- This should be syntax error.",
|
|
92
|
+
" | ^^^^",
|
|
93
|
+
" 7 | }",
|
|
94
|
+
'Missing "postinit" method required by un initialized attribute(s).',
|
|
95
|
+
" 11 | obj Test2 {",
|
|
96
|
+
" 12 | has var1: str;",
|
|
97
|
+
" 13 | has var2: int by postinit;",
|
|
98
|
+
" | ^^^^",
|
|
99
|
+
" 14 | }",
|
|
100
|
+
"Non default attribute 'var4' follows default attribute",
|
|
101
|
+
" 19 | has var2: int = 42;",
|
|
102
|
+
" 20 | has var3: int by postinit; # <-- This is fine.",
|
|
103
|
+
" 21 | has var4: int; # <-- This should be syntax error.",
|
|
104
|
+
" | ^^^^",
|
|
105
|
+
" 22 |",
|
|
106
|
+
" 23 | can postinit() {",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
errors_output = ""
|
|
110
|
+
for error in state.errors_had:
|
|
111
|
+
errors_output += error.pretty_print() + "\n"
|
|
112
|
+
|
|
113
|
+
for exp in expected_stdout_values:
|
|
114
|
+
self.assertIn(exp, errors_output)
|
|
@@ -19,7 +19,7 @@ class DefUsePassTests(TestCase):
|
|
|
19
19
|
target=DefUsePass,
|
|
20
20
|
)
|
|
21
21
|
uses = [i.uses for i in state.ir.sym_tab.kid[0].tab.values()]
|
|
22
|
+
self.assertEqual(len(uses[0]), 1)
|
|
22
23
|
self.assertEqual(len(uses[1]), 1)
|
|
23
|
-
self.
|
|
24
|
-
self.assertIn("
|
|
25
|
-
self.assertIn("message", [uses[1][0].sym_name, uses[2][0].sym_name])
|
|
24
|
+
self.assertIn("output", [uses[0][0].sym_name, uses[1][0].sym_name])
|
|
25
|
+
self.assertIn("message", [uses[0][0].sym_name, uses[1][0].sym_name])
|
|
@@ -1640,8 +1640,8 @@ class JacFormatPass(Pass):
|
|
|
1640
1640
|
def exit_index_slice(self, node: ast.IndexSlice) -> None:
|
|
1641
1641
|
"""Sub objects.
|
|
1642
1642
|
|
|
1643
|
-
|
|
1644
|
-
|
|
1643
|
+
slices: list[Slice],
|
|
1644
|
+
is_range: bool,
|
|
1645
1645
|
"""
|
|
1646
1646
|
for i in node.kid:
|
|
1647
1647
|
self.emit(node, i.gen.jac)
|
|
@@ -34,6 +34,8 @@ glob exec_ctx = ExecutionContext();
|
|
|
34
34
|
|
|
35
35
|
obj Anchor :ArchitypeProtocol: {
|
|
36
36
|
has ob: object,
|
|
37
|
+
ds_entry_funcs: list[DSFunc],
|
|
38
|
+
ds_exit_funcs: list[DSFunc],
|
|
37
39
|
jid: UUID = :> uuid4,
|
|
38
40
|
timestamp: datetime = :> datetime.now,
|
|
39
41
|
persist: bool = False,
|
|
@@ -41,9 +43,7 @@ obj Anchor :ArchitypeProtocol: {
|
|
|
41
43
|
rw_access: set = :> set,
|
|
42
44
|
ro_access: set = :> set,
|
|
43
45
|
owner_id: UUID = exec_ctx.master,
|
|
44
|
-
mem: Memory = exec_ctx.memory
|
|
45
|
-
ds_entry_funcs: list[DSFunc],
|
|
46
|
-
ds_exit_funcs: list[DSFunc];
|
|
46
|
+
mem: Memory = exec_ctx.memory;
|
|
47
47
|
|
|
48
48
|
static can on_entry(cls: type, triggers: list[type]);
|
|
49
49
|
static can on_exit(cls: type, triggers: list[type]);
|
|
@@ -33,6 +33,8 @@ glob exec_ctx = ExecutionContext();
|
|
|
33
33
|
|
|
34
34
|
obj Anchor :ArchitypeProtocol: {
|
|
35
35
|
has ob: object,
|
|
36
|
+
ds_entry_funcs: list[DSFunc],
|
|
37
|
+
ds_exit_funcs: list[DSFunc],
|
|
36
38
|
jid: UUID = :> uuid4,
|
|
37
39
|
timestamp: datetime = :> datetime.now,
|
|
38
40
|
persist: bool = False,
|
|
@@ -40,9 +42,7 @@ obj Anchor :ArchitypeProtocol: {
|
|
|
40
42
|
rw_access: set = :> set,
|
|
41
43
|
ro_access: set = :> set,
|
|
42
44
|
owner_id: UUID = exec_ctx.master,
|
|
43
|
-
mem: Memory = exec_ctx.memory
|
|
44
|
-
ds_entry_funcs: list[DSFunc],
|
|
45
|
-
ds_exit_funcs: list[DSFunc];
|
|
45
|
+
mem: Memory = exec_ctx.memory;
|
|
46
46
|
|
|
47
47
|
static can on_entry(cls: type, triggers: list[type]);
|
|
48
48
|
static can on_exit(cls: type, triggers: list[type]);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Tests for Jac parser."""
|
|
2
2
|
|
|
3
3
|
import inspect
|
|
4
|
+
import os
|
|
4
5
|
|
|
5
6
|
from jaclang.compiler import jac_lark as jl
|
|
6
7
|
from jaclang.compiler.absyntree import JacSource
|
|
@@ -27,7 +28,12 @@ class TestLarkParser(TestCaseMicroSuite):
|
|
|
27
28
|
prse = JacParser(
|
|
28
29
|
input_ir=JacSource(self.file_to_str(filename), mod_path=filename),
|
|
29
30
|
)
|
|
30
|
-
|
|
31
|
+
# A list of files where the errors are expected.
|
|
32
|
+
files_expected_errors = [
|
|
33
|
+
"uninitialized_hasvars.jac",
|
|
34
|
+
]
|
|
35
|
+
if os.path.basename(filename) not in files_expected_errors:
|
|
36
|
+
self.assertFalse(prse.errors_had)
|
|
31
37
|
|
|
32
38
|
def test_parser_fam(self) -> None:
|
|
33
39
|
"""Parse micro jac file."""
|