jaclang 0.5.4__py3-none-any.whl → 0.5.6__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.

@@ -1300,7 +1300,7 @@ class BinaryExpr(Expr):
1300
1300
 
1301
1301
 
1302
1302
  class CompareExpr(Expr):
1303
- """ExprBinary node type for Jac Ast."""
1303
+ """CompareExpr node type for Jac Ast."""
1304
1304
 
1305
1305
  def __init__(
1306
1306
  self,
@@ -1316,6 +1316,21 @@ class CompareExpr(Expr):
1316
1316
  AstNode.__init__(self, kid=kid)
1317
1317
 
1318
1318
 
1319
+ class BoolExpr(Expr):
1320
+ """BoolExpr node type for Jac Ast."""
1321
+
1322
+ def __init__(
1323
+ self,
1324
+ op: Token,
1325
+ values: list[Expr],
1326
+ kid: Sequence[AstNode],
1327
+ ) -> None:
1328
+ """Initialize binary expression node."""
1329
+ self.values = values
1330
+ self.op = op
1331
+ AstNode.__init__(self, kid=kid)
1332
+
1333
+
1319
1334
  class LambdaExpr(Expr):
1320
1335
  """ExprLambda node type for Jac Ast."""
1321
1336
 
@@ -1764,13 +1779,11 @@ class EdgeOpRef(WalkerStmtOnlyNode, AtomExpr):
1764
1779
 
1765
1780
  def __init__(
1766
1781
  self,
1767
- filter_type: Optional[Expr],
1768
1782
  filter_cond: Optional[FilterCompr],
1769
1783
  edge_dir: EdgeDir,
1770
1784
  kid: Sequence[AstNode],
1771
1785
  ) -> None:
1772
1786
  """Initialize edge op reference expression node."""
1773
- self.filter_type = filter_type
1774
1787
  self.filter_cond = filter_cond
1775
1788
  self.edge_dir = edge_dir
1776
1789
  AstNode.__init__(self, kid=kid)
@@ -1819,10 +1832,12 @@ class FilterCompr(AtomExpr):
1819
1832
 
1820
1833
  def __init__(
1821
1834
  self,
1822
- compares: SubNodeList[CompareExpr],
1835
+ f_type: Optional[Expr],
1836
+ compares: Optional[SubNodeList[CompareExpr]],
1823
1837
  kid: Sequence[AstNode],
1824
1838
  ) -> None:
1825
1839
  """Initialize filter_cond context expression node."""
1840
+ self.f_type = f_type
1826
1841
  self.compares = compares
1827
1842
  AstNode.__init__(self, kid=kid)
1828
1843
  AstSymbolNode.__init__(
@@ -5,7 +5,7 @@ from __future__ import annotations
5
5
 
6
6
  import logging
7
7
  import os
8
- from typing import Callable, TypeAlias, cast
8
+ from typing import Callable, TypeAlias
9
9
 
10
10
 
11
11
  import jaclang.compiler.absyntree as ast
@@ -1915,16 +1915,48 @@ class JacParser(Pass):
1915
1915
  def logical_or(self, kid: list[ast.AstNode]) -> ast.Expr:
1916
1916
  """Grammar rule.
1917
1917
 
1918
- logical_or: (logical_or KW_OR)? logical_and
1918
+ logical_or: logical_and (KW_OR logical_and)*
1919
1919
  """
1920
- return self.binary_expr_unwind(kid)
1920
+ if len(kid) > 1:
1921
+ values = [i for i in kid if isinstance(i, ast.Expr)]
1922
+ ops = kid[1] if isinstance(kid[1], ast.Token) else None
1923
+ if not ops:
1924
+ raise self.ice()
1925
+ return self.nu(
1926
+ ast.BoolExpr(
1927
+ op=ops,
1928
+ values=values,
1929
+ kid=kid,
1930
+ )
1931
+ )
1932
+ elif isinstance(kid[0], ast.Expr):
1933
+ return self.nu(kid[0])
1934
+ else:
1935
+
1936
+ raise self.ice()
1921
1937
 
1922
1938
  def logical_and(self, kid: list[ast.AstNode]) -> ast.Expr:
1923
1939
  """Grammar rule.
1924
1940
 
1925
- logical_and: (logical_and KW_AND)? logical_not
1941
+ logical_and: logical_not (KW_AND logical_not)*
1926
1942
  """
1927
- return self.binary_expr_unwind(kid)
1943
+ if len(kid) > 1:
1944
+ values = [i for i in kid if isinstance(i, ast.Expr)]
1945
+ ops = kid[1] if isinstance(kid[1], ast.Token) else None
1946
+ if not ops:
1947
+ raise self.ice()
1948
+ return self.nu(
1949
+ ast.BoolExpr(
1950
+ op=ops,
1951
+ values=values,
1952
+ kid=kid,
1953
+ )
1954
+ )
1955
+ elif isinstance(kid[0], ast.Expr):
1956
+ return self.nu(kid[0])
1957
+ else:
1958
+
1959
+ raise self.ice()
1928
1960
 
1929
1961
  def logical_not(self, kid: list[ast.AstNode]) -> ast.Expr:
1930
1962
  """Grammar rule.
@@ -2224,76 +2256,51 @@ class JacParser(Pass):
2224
2256
  else:
2225
2257
  raise self.ice()
2226
2258
 
2227
- def index_slice(self, kid: list[ast.AstNode]) -> ast.IndexSlice | ast.ListVal:
2259
+ def index_slice(self, kid: list[ast.AstNode]) -> ast.IndexSlice:
2228
2260
  """Grammar rule.
2229
2261
 
2230
2262
  index_slice: LSQUARE expression? COLON expression? (COLON expression?)? RSQUARE
2231
- | list_val
2232
- """
2233
- if len(kid) == 1 and isinstance(kid[0], ast.ListVal):
2234
- expr = None
2235
- if not kid[0].values or len(kid[0].values.items) < 1:
2236
- self.parse_ref.error("Empty list slice not allowed", kid[0].values)
2237
- elif len(kid[0].values.items) == 1:
2238
- expr = kid[0].values.items[0] # TODO: Loses braces
2263
+ | list_val
2264
+ """
2265
+ if len(kid) == 1:
2266
+ index = kid[0]
2267
+ if isinstance(index, ast.ListVal):
2268
+ expr = index.values.items[0] if index.values else None
2269
+ return self.nu(
2270
+ ast.IndexSlice(
2271
+ start=expr,
2272
+ stop=None,
2273
+ step=None,
2274
+ is_range=False,
2275
+ kid=kid[0].kid,
2276
+ )
2277
+ )
2239
2278
  else:
2240
- vals = cast("ast.SubNodeList[ast.Expr|ast.KWPair]", kid[0].values)
2241
- expr = ast.TupleVal(values=vals, kid=kid[0].kid)
2242
- if expr is None:
2243
2279
  raise self.ice()
2244
- return self.nu(
2245
- ast.IndexSlice(
2246
- start=expr, stop=None, step=None, is_range=False, kid=[expr]
2247
- )
2248
- )
2249
- chomp = [*kid]
2250
- chomp = chomp[1:]
2251
- expr1 = chomp[0] if isinstance(chomp[0], ast.Expr) else None
2252
- expr2 = (
2253
- chomp[1]
2254
- if isinstance(chomp[0], ast.Token)
2255
- and chomp[0].name == Tok.COLON
2256
- and isinstance(chomp[1], ast.Expr)
2257
- else None
2258
- )
2259
- chomp = chomp[1:]
2260
- expr2 = (
2261
- chomp[1]
2262
- if isinstance(chomp[0], ast.Token)
2263
- and chomp[0].name == Tok.COLON
2264
- and len(chomp) > 1
2265
- and isinstance(chomp[1], ast.Expr)
2266
- else expr2
2267
- )
2268
- expr3 = None
2269
- if len(chomp) > 1:
2280
+ else:
2281
+ expr1 = expr2 = expr3 = None
2282
+ chomp = kid[1:]
2283
+ if isinstance(chomp[0], ast.Expr):
2284
+ expr1 = chomp[0]
2285
+ chomp = chomp[1:]
2270
2286
  chomp = chomp[1:]
2271
- expr3 = (
2272
- chomp[1]
2273
- if isinstance(chomp[0], ast.Token)
2274
- and chomp[0].name == Tok.COLON
2275
- and isinstance(chomp[1], ast.Expr)
2276
- else None
2277
- )
2278
- if len(chomp) > 1:
2287
+ if isinstance(chomp[0], ast.Expr):
2288
+ expr2 = chomp[0]
2289
+ chomp = chomp[1:]
2290
+ if isinstance(chomp[0], ast.Token) and chomp[0].name == Tok.COLON:
2279
2291
  chomp = chomp[1:]
2280
- expr3 = (
2281
- chomp[1]
2282
- if isinstance(chomp[0], ast.Token)
2283
- and chomp[0].name == Tok.COLON
2284
- and len(chomp) > 1
2285
- and isinstance(chomp[1], ast.Expr)
2286
- else expr3
2292
+ if isinstance(chomp[0], ast.Expr):
2293
+ expr3 = chomp[0]
2294
+ chomp = chomp[1:]
2295
+ return self.nu(
2296
+ ast.IndexSlice(
2297
+ start=expr1,
2298
+ stop=expr2,
2299
+ step=expr3,
2300
+ is_range=True,
2301
+ kid=kid,
2287
2302
  )
2288
- return self.nu(
2289
- ast.IndexSlice(
2290
- start=expr1,
2291
- stop=expr2,
2292
- step=expr3,
2293
- is_range=True,
2294
- kid=kid,
2295
2303
  )
2296
- )
2297
2304
 
2298
2305
  def atom(self, kid: list[ast.AstNode]) -> ast.Expr:
2299
2306
  """Grammar rule.
@@ -3128,24 +3135,13 @@ class JacParser(Pass):
3128
3135
  def edge_to(self, kid: list[ast.AstNode]) -> ast.EdgeOpRef:
3129
3136
  """Grammar rule.
3130
3137
 
3131
- edge_to: ARROW_R_P1 expression (COLON filter_compare_list)? ARROW_R_P2
3138
+ edge_to: ARROW_R_P1 typed_filter_compare_list ARROW_R_P2
3132
3139
  | ARROW_R
3133
3140
  """
3134
- ftype = kid[1] if len(kid) >= 3 else None
3135
- fcond = kid[3] if len(kid) >= 5 else None
3136
- if (isinstance(ftype, ast.Expr) or ftype is None) and (
3137
- isinstance(fcond, ast.SubNodeList) or fcond is None
3138
- ):
3139
- fcond = ast.FilterCompr(compares=fcond, kid=[fcond]) if fcond else None
3140
- if fcond:
3141
- kid[3] = fcond
3141
+ fcond = kid[1] if len(kid) > 1 else None
3142
+ if isinstance(fcond, ast.FilterCompr) or fcond is None:
3142
3143
  return self.nu(
3143
- ast.EdgeOpRef(
3144
- filter_type=ftype,
3145
- filter_cond=fcond,
3146
- edge_dir=EdgeDir.OUT,
3147
- kid=kid,
3148
- )
3144
+ ast.EdgeOpRef(filter_cond=fcond, edge_dir=EdgeDir.OUT, kid=kid)
3149
3145
  )
3150
3146
  else:
3151
3147
  raise self.ice()
@@ -3153,24 +3149,13 @@ class JacParser(Pass):
3153
3149
  def edge_from(self, kid: list[ast.AstNode]) -> ast.EdgeOpRef:
3154
3150
  """Grammar rule.
3155
3151
 
3156
- edge_from: ARROW_L_P1 expression (COLON filter_compare_list)? ARROW_L_P2
3152
+ edge_from: ARROW_L_P1 typed_filter_compare_list ARROW_L_P2
3157
3153
  | ARROW_L
3158
3154
  """
3159
- ftype = kid[1] if len(kid) >= 3 else None
3160
- fcond = kid[3] if len(kid) >= 5 else None
3161
- if (isinstance(ftype, ast.Expr) or ftype is None) and (
3162
- isinstance(fcond, ast.SubNodeList) or fcond is None
3163
- ):
3164
- fcond = ast.FilterCompr(compares=fcond, kid=[fcond]) if fcond else None
3165
- if fcond:
3166
- kid[3] = fcond
3155
+ fcond = kid[1] if len(kid) > 1 else None
3156
+ if isinstance(fcond, ast.FilterCompr) or fcond is None:
3167
3157
  return self.nu(
3168
- ast.EdgeOpRef(
3169
- filter_type=ftype,
3170
- filter_cond=fcond,
3171
- edge_dir=EdgeDir.IN,
3172
- kid=kid,
3173
- )
3158
+ ast.EdgeOpRef(filter_cond=fcond, edge_dir=EdgeDir.IN, kid=kid)
3174
3159
  )
3175
3160
  else:
3176
3161
  raise self.ice()
@@ -3178,24 +3163,13 @@ class JacParser(Pass):
3178
3163
  def edge_any(self, kid: list[ast.AstNode]) -> ast.EdgeOpRef:
3179
3164
  """Grammar rule.
3180
3165
 
3181
- edge_any: ARROW_L_P1 expression (COLON filter_compare_list)? ARROW_R_P2
3166
+ edge_any: ARROW_L_P1 typed_filter_compare_list ARROW_R_P2
3182
3167
  | ARROW_BI
3183
3168
  """
3184
- ftype = kid[1] if len(kid) >= 3 else None
3185
- fcond = kid[3] if len(kid) >= 5 else None
3186
- if (isinstance(ftype, ast.Expr) or ftype is None) and (
3187
- isinstance(fcond, ast.SubNodeList) or fcond is None
3188
- ):
3189
- fcond = ast.FilterCompr(compares=fcond, kid=[fcond]) if fcond else None
3190
- if fcond:
3191
- kid[3] = fcond
3169
+ fcond = kid[1] if len(kid) > 1 else None
3170
+ if isinstance(fcond, ast.FilterCompr) or fcond is None:
3192
3171
  return self.nu(
3193
- ast.EdgeOpRef(
3194
- filter_type=ftype,
3195
- filter_cond=fcond,
3196
- edge_dir=EdgeDir.ANY,
3197
- kid=kid,
3198
- )
3172
+ ast.EdgeOpRef(filter_cond=fcond, edge_dir=EdgeDir.ANY, kid=kid)
3199
3173
  )
3200
3174
  else:
3201
3175
  raise self.ice()
@@ -3314,15 +3288,15 @@ class JacParser(Pass):
3314
3288
  def filter_compr(self, kid: list[ast.AstNode]) -> ast.FilterCompr:
3315
3289
  """Grammar rule.
3316
3290
 
3317
- filter_compr: LPAREN EQ filter_compare_list RPAREN
3291
+ filter_compr: LPAREN NULL_OK filter_compare_list RPAREN
3292
+ | LPAREN TYPE_OP NULL_OK typed_filter_compare_list RPAREN
3318
3293
  """
3319
3294
  if isinstance(kid[2], ast.SubNodeList):
3320
- return self.nu(
3321
- ast.FilterCompr(
3322
- compares=kid[2],
3323
- kid=kid,
3324
- )
3325
- )
3295
+ return self.nu(ast.FilterCompr(compares=kid[2], f_type=None, kid=kid))
3296
+ elif isinstance(kid[3], ast.FilterCompr):
3297
+ kid[3].add_kids_left(kid[:3])
3298
+ kid[3].add_kids_right(kid[4:])
3299
+ return self.nu(kid[3])
3326
3300
  else:
3327
3301
  raise self.ice()
3328
3302
 
@@ -3352,6 +3326,28 @@ class JacParser(Pass):
3352
3326
  )
3353
3327
  )
3354
3328
 
3329
+ def typed_filter_compare_list(self, kid: list[ast.AstNode]) -> ast.FilterCompr:
3330
+ """Grammar rule.
3331
+
3332
+ typed_filter_compare_list: expression (COLON filter_compare_list)?
3333
+ """
3334
+ chomp = [*kid]
3335
+ expr = chomp[0]
3336
+ chomp = chomp[1:]
3337
+ compares = (
3338
+ chomp[1]
3339
+ if len(chomp)
3340
+ and isinstance(chomp[0], ast.Token)
3341
+ and chomp[0].name == Tok.COLON
3342
+ else None
3343
+ )
3344
+ if isinstance(expr, ast.Expr) and (
3345
+ (isinstance(compares, ast.SubNodeList)) or compares is None
3346
+ ):
3347
+ return self.nu(ast.FilterCompr(compares=compares, f_type=expr, kid=kid))
3348
+ else:
3349
+ raise self.ice()
3350
+
3355
3351
  def filter_compare_item(self, kid: list[ast.AstNode]) -> ast.CompareExpr:
3356
3352
  """Grammar rule.
3357
3353
 
@@ -1788,11 +1788,6 @@ class PyastGenPass(Pass):
1788
1788
  self.sync(
1789
1789
  ast3.Constant(value=node.op.edge_spec.edge_dir.name)
1790
1790
  ),
1791
- (
1792
- node.op.edge_spec.filter_type.gen.py_ast[0]
1793
- if node.op.edge_spec.filter_type is not None
1794
- else self.sync(ast3.Constant(value=None))
1795
- ),
1796
1791
  (
1797
1792
  node.op.edge_spec.filter_cond.gen.py_ast[0]
1798
1793
  if node.op.edge_spec.filter_cond is not None
@@ -1934,6 +1929,21 @@ class PyastGenPass(Pass):
1934
1929
  )
1935
1930
  ]
1936
1931
 
1932
+ def exit_bool_expr(self, node: ast.BoolExpr) -> None:
1933
+ """Sub objects.
1934
+
1935
+ op: Token,
1936
+ values: list[Expr],
1937
+ """
1938
+ node.gen.py_ast = [
1939
+ self.sync(
1940
+ ast3.BoolOp(
1941
+ op=node.op.gen.py_ast[0],
1942
+ values=[i.gen.py_ast[0] for i in node.values],
1943
+ )
1944
+ )
1945
+ ]
1946
+
1937
1947
  def exit_lambda_expr(self, node: ast.LambdaExpr) -> None:
1938
1948
  """Sub objects.
1939
1949
 
@@ -2405,9 +2415,9 @@ class PyastGenPass(Pass):
2405
2415
  node.gen.py_ast = [
2406
2416
  self.sync(
2407
2417
  ast3.Slice(
2408
- lower=node.start.gen.py_ast if node.start else None,
2409
- upper=node.stop.gen.py_ast if node.stop else None,
2410
- step=node.step.gen.py_ast if node.step else None,
2418
+ lower=node.start.gen.py_ast[0] if node.start else None,
2419
+ upper=node.stop.gen.py_ast[0] if node.stop else None,
2420
+ step=node.step.gen.py_ast[0] if node.step else None,
2411
2421
  )
2412
2422
  )
2413
2423
  ]
@@ -2535,16 +2545,6 @@ class PyastGenPass(Pass):
2535
2545
  ),
2536
2546
  )
2537
2547
  ),
2538
- self.sync(
2539
- ast3.keyword(
2540
- arg="filter_type",
2541
- value=self.sync(
2542
- node.filter_type.gen.py_ast[0]
2543
- if node.filter_type
2544
- else self.sync(ast3.Constant(value=None))
2545
- ),
2546
- )
2547
- ),
2548
2548
  self.sync(
2549
2549
  ast3.keyword(
2550
2550
  arg="filter_func",
@@ -2655,38 +2655,76 @@ class PyastGenPass(Pass):
2655
2655
  iter=self.sync(
2656
2656
  ast3.Name(id="x", ctx=ast3.Load())
2657
2657
  ),
2658
- ifs=[
2659
- self.sync(
2660
- ast3.Compare(
2661
- left=self.sync(
2662
- ast3.Attribute(
2663
- value=self.sync(
2658
+ ifs=(
2659
+ (
2660
+ [
2661
+ self.sync(
2662
+ ast3.Call(
2663
+ func=self.sync(
2664
2664
  ast3.Name(
2665
- id="i",
2665
+ id="isinstance",
2666
2666
  ctx=ast3.Load(),
2667
+ )
2668
+ ),
2669
+ args=[
2670
+ self.sync(
2671
+ ast3.Name(
2672
+ id="i",
2673
+ ctx=ast3.Load(),
2674
+ )
2675
+ ),
2676
+ self.sync(
2677
+ node.f_type.gen.py_ast[
2678
+ 0
2679
+ ]
2667
2680
  ),
2668
- jac_node=x,
2681
+ ],
2682
+ keywords=[],
2683
+ )
2684
+ )
2685
+ ]
2686
+ if node.f_type
2687
+ else []
2688
+ )
2689
+ + [
2690
+ self.sync(
2691
+ ast3.Compare(
2692
+ left=self.sync(
2693
+ ast3.Attribute(
2694
+ value=self.sync(
2695
+ ast3.Name(
2696
+ id="i",
2697
+ ctx=ast3.Load(),
2698
+ ),
2699
+ jac_node=x,
2700
+ ),
2701
+ attr=x.gen.py_ast[
2702
+ 0
2703
+ ].left.id,
2704
+ ctx=ast3.Load(),
2669
2705
  ),
2670
- attr=x.gen.py_ast[
2671
- 0
2672
- ].left.id,
2673
- ctx=ast3.Load(),
2706
+ jac_node=x,
2674
2707
  ),
2675
- jac_node=x,
2708
+ ops=x.gen.py_ast[0].ops,
2709
+ comparators=x.gen.py_ast[
2710
+ 0
2711
+ ].comparators,
2676
2712
  ),
2677
- ops=x.gen.py_ast[0].ops,
2678
- comparators=x.gen.py_ast[
2679
- 0
2680
- ].comparators,
2681
- ),
2682
- jac_node=x,
2683
- )
2684
- for x in node.compares.items
2685
- if isinstance(x.gen.py_ast[0], ast3.Compare)
2686
- and isinstance(
2687
- x.gen.py_ast[0].left, ast3.Name
2688
- )
2689
- ],
2713
+ jac_node=x,
2714
+ )
2715
+ for x in (
2716
+ node.compares.items
2717
+ if node.compares
2718
+ else []
2719
+ )
2720
+ if isinstance(
2721
+ x.gen.py_ast[0], ast3.Compare
2722
+ )
2723
+ and isinstance(
2724
+ x.gen.py_ast[0].left, ast3.Name
2725
+ )
2726
+ ]
2727
+ ),
2690
2728
  is_async=0,
2691
2729
  )
2692
2730
  )
@@ -1015,6 +1015,13 @@ class SymTabBuildPass(SymTabPass):
1015
1015
  """
1016
1016
  self.sync_node_to_scope(node)
1017
1017
 
1018
+ def enter_bool_expr(self, node: ast.BoolExpr) -> None:
1019
+ """Sub objects.
1020
+
1021
+ value: Token,
1022
+ """
1023
+ self.sync_node_to_scope(node)
1024
+
1018
1025
  def enter_lambda_expr(self, node: ast.LambdaExpr) -> None:
1019
1026
  """Sub objects.
1020
1027
 
@@ -24,11 +24,14 @@ class JacFormatPass(Pass):
24
24
  """Return string for indent."""
25
25
  return " " * self.indent_size * self.indent_level
26
26
 
27
- def emit(self, node: ast.AstNode, s: str) -> None:
27
+ def emit(self, node: ast.AstNode, s: str, strip_mode: bool = True) -> None:
28
28
  """Emit code to node."""
29
29
  node.gen.jac += self.indent_str() + s.replace("\n", "\n" + self.indent_str())
30
30
  if "\n" in node.gen.jac:
31
- node.gen.jac = node.gen.jac.rstrip(" ")
31
+ if strip_mode:
32
+ node.gen.jac = node.gen.jac.rstrip(" ")
33
+ else:
34
+ node.gen.jac = node.gen.jac
32
35
 
33
36
  def emit_ln(self, node: ast.AstNode, s: str) -> None:
34
37
  """Emit code to node."""
@@ -847,20 +850,11 @@ class JacFormatPass(Pass):
847
850
  and isinstance(node.right, ast.TupleVal)
848
851
  )
849
852
  ):
850
- # Check if line break is needed
851
- if node.op.value in ["and", "or"] and self.is_line_break_needed(
852
- f"{node.left.gen.jac} {node.op.value} {node.right.gen.jac}"
853
- ):
854
- self.emit_ln(node, f"{node.left.gen.jac}")
855
- self.emit(
856
- node,
857
- f" {node.op.value} {node.right.gen.jac}",
858
- )
859
- else:
860
- self.emit(
861
- node,
862
- f"{node.left.gen.jac} {node.op.value} {node.right.gen.jac}",
863
- )
853
+
854
+ self.emit(
855
+ node,
856
+ f"{node.left.gen.jac} {node.op.value} {node.right.gen.jac}",
857
+ )
864
858
  else:
865
859
  self.error(
866
860
  f"Binary operator {node.op.value} not supported in bootstrap Jac"
@@ -1332,6 +1326,35 @@ class JacFormatPass(Pass):
1332
1326
  f"Unable to find definition for {decl} declaration. Perhaps there's an `include` missing?" # noqa
1333
1327
  )
1334
1328
 
1329
+ def exit_bool_expr(self, node: ast.BoolExpr) -> None:
1330
+ """Sub objects.
1331
+
1332
+ op: Token,
1333
+ values: list[Expr],
1334
+ """
1335
+ end = node.values[-1]
1336
+ test_str = ""
1337
+ for i in node.values:
1338
+ test_str += f"{i.gen.jac}"
1339
+ if i != end:
1340
+ test_str += f" {node.op.value} "
1341
+
1342
+ # Check if line break is needed
1343
+ if self.is_line_break_needed(test_str):
1344
+ for i in node.values:
1345
+ if i != end:
1346
+ self.emit_ln(node, f"{i.gen.jac}")
1347
+ else:
1348
+ self.emit(node, f"{i.gen.jac}")
1349
+ if i != end:
1350
+ self.emit(
1351
+ node,
1352
+ " " * self.indent_size + f"{node.op.value} ",
1353
+ strip_mode=False,
1354
+ )
1355
+ else:
1356
+ self.emit(node, test_str)
1357
+
1335
1358
  def exit_lambda_expr(self, node: ast.LambdaExpr) -> None:
1336
1359
  """Sub objects.
1337
1360
 
@@ -1410,11 +1433,7 @@ class JacFormatPass(Pass):
1410
1433
  stop: Optional[ExprType],
1411
1434
  """
1412
1435
  for i in node.kid:
1413
- if not i.gen.jac.startswith("["):
1414
- self.emit(node, "[")
1415
1436
  self.emit(node, i.gen.jac)
1416
- if not i.gen.jac.endswith("]"):
1417
- self.emit(node, "]")
1418
1437
 
1419
1438
  def exit_list_val(self, node: ast.ListVal) -> None:
1420
1439
  """Sub objects.
@@ -0,0 +1,5 @@
1
+ """ Basic Hello World function """
2
+ from __future__ import annotations
3
+
4
+ def hello() -> None:
5
+ return 'Hello World!'