jaclang 0.7.14__py3-none-any.whl → 0.7.17__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 (131) hide show
  1. jaclang/cli/cli.py +147 -77
  2. jaclang/cli/cmdreg.py +9 -12
  3. jaclang/compiler/__init__.py +19 -53
  4. jaclang/compiler/absyntree.py +94 -16
  5. jaclang/compiler/constant.py +8 -8
  6. jaclang/compiler/jac.lark +4 -3
  7. jaclang/compiler/parser.py +41 -25
  8. jaclang/compiler/passes/ir_pass.py +4 -13
  9. jaclang/compiler/passes/main/__init__.py +1 -1
  10. jaclang/compiler/passes/main/access_modifier_pass.py +96 -147
  11. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +155 -54
  12. jaclang/compiler/passes/main/import_pass.py +99 -75
  13. jaclang/compiler/passes/main/py_collect_dep_pass.py +70 -0
  14. jaclang/compiler/passes/main/pyast_gen_pass.py +328 -565
  15. jaclang/compiler/passes/main/pyast_load_pass.py +33 -6
  16. jaclang/compiler/passes/main/pyjac_ast_link_pass.py +7 -0
  17. jaclang/compiler/passes/main/registry_pass.py +37 -3
  18. jaclang/compiler/passes/main/schedules.py +9 -2
  19. jaclang/compiler/passes/main/sym_tab_build_pass.py +10 -6
  20. jaclang/compiler/passes/main/tests/__init__.py +1 -1
  21. jaclang/compiler/passes/main/tests/fixtures/autoimpl.empty.impl.jac +0 -0
  22. jaclang/compiler/passes/main/tests/fixtures/autoimpl.jac +1 -1
  23. jaclang/compiler/passes/main/tests/fixtures/py_imp_test.jac +29 -0
  24. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/__init__.py +3 -0
  25. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/color.py +3 -0
  26. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/constants.py +5 -0
  27. jaclang/compiler/passes/main/tests/fixtures/pygame_mock/display.py +2 -0
  28. jaclang/compiler/passes/main/tests/test_import_pass.py +72 -13
  29. jaclang/compiler/passes/main/type_check_pass.py +22 -5
  30. jaclang/compiler/passes/tool/jac_formatter_pass.py +135 -89
  31. jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +37 -41
  32. jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +37 -42
  33. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/access_mod_check.jac +27 -0
  34. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/architype_test.jac +13 -0
  35. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/comment_alignment.jac +11 -0
  36. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/comments.jac +13 -0
  37. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/decorator_stack.jac +37 -0
  38. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/esc_keywords.jac +5 -0
  39. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/long_names.jac +19 -0
  40. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +6 -0
  41. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +11 -0
  42. jaclang/compiler/passes/tool/tests/test_unparse_validate.py +33 -39
  43. jaclang/compiler/passes/transform.py +4 -0
  44. jaclang/compiler/passes/utils/mypy_ast_build.py +45 -0
  45. jaclang/compiler/semtable.py +31 -7
  46. jaclang/compiler/symtable.py +16 -11
  47. jaclang/compiler/tests/test_importer.py +25 -10
  48. jaclang/langserve/engine.py +104 -118
  49. jaclang/langserve/sem_manager.py +379 -0
  50. jaclang/langserve/server.py +24 -11
  51. jaclang/langserve/tests/fixtures/base_module_structure.jac +27 -6
  52. jaclang/langserve/tests/fixtures/circle.jac +3 -3
  53. jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
  54. jaclang/langserve/tests/fixtures/circle_pure.test.jac +3 -3
  55. jaclang/langserve/tests/fixtures/import_include_statements.jac +1 -1
  56. jaclang/langserve/tests/fixtures/rename.jac +30 -0
  57. jaclang/langserve/tests/test_sem_tokens.py +277 -0
  58. jaclang/langserve/tests/test_server.py +287 -17
  59. jaclang/langserve/utils.py +184 -98
  60. jaclang/plugin/builtin.py +1 -1
  61. jaclang/plugin/default.py +288 -92
  62. jaclang/plugin/feature.py +65 -27
  63. jaclang/plugin/spec.py +62 -23
  64. jaclang/plugin/tests/fixtures/other_root_access.jac +82 -0
  65. jaclang/plugin/tests/test_jaseci.py +414 -42
  66. jaclang/runtimelib/architype.py +650 -0
  67. jaclang/{core → runtimelib}/constructs.py +5 -8
  68. jaclang/{core → runtimelib}/context.py +86 -59
  69. jaclang/runtimelib/importer.py +361 -0
  70. jaclang/runtimelib/machine.py +158 -0
  71. jaclang/runtimelib/memory.py +158 -0
  72. jaclang/{core → runtimelib}/utils.py +30 -15
  73. jaclang/settings.py +5 -4
  74. jaclang/tests/fixtures/abc.jac +3 -3
  75. jaclang/tests/fixtures/access_checker.jac +12 -17
  76. jaclang/tests/fixtures/access_modifier.jac +88 -33
  77. jaclang/tests/fixtures/baddy.jac +3 -0
  78. jaclang/tests/fixtures/baddy.test.jac +3 -0
  79. jaclang/tests/fixtures/bar.jac +34 -0
  80. jaclang/tests/fixtures/byllmissue.jac +1 -5
  81. jaclang/tests/fixtures/chandra_bugs2.jac +11 -10
  82. jaclang/tests/fixtures/cls_method.jac +41 -0
  83. jaclang/tests/fixtures/dblhello.jac +6 -0
  84. jaclang/tests/fixtures/deep/one_lev.jac +3 -3
  85. jaclang/tests/fixtures/deep/one_lev_dup.jac +2 -3
  86. jaclang/tests/fixtures/deep_import_mods.jac +13 -0
  87. jaclang/tests/fixtures/edge_node_walk.jac +1 -1
  88. jaclang/tests/fixtures/edge_ops.jac +1 -1
  89. jaclang/tests/fixtures/edges_walk.jac +1 -1
  90. jaclang/tests/fixtures/err.impl.jac +3 -0
  91. jaclang/tests/fixtures/err.jac +4 -2
  92. jaclang/tests/fixtures/err_runtime.jac +15 -0
  93. jaclang/tests/fixtures/foo.jac +43 -0
  94. jaclang/tests/fixtures/gendot_bubble_sort.jac +1 -1
  95. jaclang/tests/fixtures/hello.jac +4 -0
  96. jaclang/tests/fixtures/impl_grab.impl.jac +2 -1
  97. jaclang/tests/fixtures/impl_grab.jac +4 -1
  98. jaclang/tests/fixtures/import.jac +9 -0
  99. jaclang/tests/fixtures/index_slice.jac +30 -0
  100. jaclang/tests/fixtures/jp_importer_auto.jac +14 -0
  101. jaclang/tests/fixtures/maxfail_run_test.jac +4 -4
  102. jaclang/tests/fixtures/needs_import.jac +2 -2
  103. jaclang/tests/fixtures/pyfunc_1.py +1 -1
  104. jaclang/tests/fixtures/pyfunc_2.py +5 -2
  105. jaclang/tests/fixtures/pygame_mock/__init__.py +3 -0
  106. jaclang/tests/fixtures/pygame_mock/color.py +3 -0
  107. jaclang/tests/fixtures/pygame_mock/constants.py +5 -0
  108. jaclang/tests/fixtures/pygame_mock/display.py +2 -0
  109. jaclang/tests/fixtures/pygame_mock/inner/__init__.py +0 -0
  110. jaclang/tests/fixtures/pygame_mock/inner/iner_mod.py +2 -0
  111. jaclang/tests/fixtures/registry.jac +9 -0
  112. jaclang/tests/fixtures/run_test.jac +4 -4
  113. jaclang/tests/fixtures/semstr.jac +1 -4
  114. jaclang/tests/fixtures/simple_archs.jac +1 -1
  115. jaclang/tests/test_cli.py +109 -3
  116. jaclang/tests/test_language.py +170 -68
  117. jaclang/tests/test_reference.py +2 -3
  118. jaclang/utils/helpers.py +45 -21
  119. jaclang/utils/test.py +9 -0
  120. jaclang/utils/treeprinter.py +30 -7
  121. {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/METADATA +3 -2
  122. {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/RECORD +126 -90
  123. jaclang/core/architype.py +0 -502
  124. jaclang/core/importer.py +0 -344
  125. jaclang/core/memory.py +0 -99
  126. jaclang/tests/fixtures/aott_raise.jac +0 -25
  127. jaclang/tests/fixtures/package_import.jac +0 -6
  128. /jaclang/{core → runtimelib}/__init__.py +0 -0
  129. /jaclang/{core → runtimelib}/test.py +0 -0
  130. {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/WHEEL +0 -0
  131. {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/entry_points.txt +0 -0
@@ -10,6 +10,7 @@ import jaclang.compiler.absyntree as ast
10
10
  from jaclang.compiler.absyntree import AstNode
11
11
  from jaclang.compiler.constant import Tokens as Tok
12
12
  from jaclang.compiler.passes import Pass
13
+ from jaclang.settings import settings
13
14
 
14
15
 
15
16
  class JacFormatPass(Pass):
@@ -20,7 +21,7 @@ class JacFormatPass(Pass):
20
21
  self.comments: list[ast.CommentToken] = []
21
22
  self.indent_size = 4
22
23
  self.indent_level = 0
23
- self.MAX_LINE_LENGTH = 44
24
+ self.MAX_LINE_LENGTH = int(float(settings.max_line_length) / 2)
24
25
 
25
26
  def enter_node(self, node: ast.AstNode) -> None:
26
27
  """Enter node."""
@@ -49,7 +50,8 @@ class JacFormatPass(Pass):
49
50
 
50
51
  def emit(self, node: ast.AstNode, s: str, strip_mode: bool = True) -> None:
51
52
  """Emit code to node."""
52
- node.gen.jac += self.indent_str() + s.replace("\n", "\n" + self.indent_str())
53
+ indented_str = re.sub(r"\n(?!\n)", f"\n{self.indent_str()}", s)
54
+ node.gen.jac += self.indent_str() + indented_str
53
55
  if "\n" in node.gen.jac:
54
56
  if strip_mode:
55
57
  node.gen.jac = node.gen.jac.rstrip(" ")
@@ -129,9 +131,15 @@ class JacFormatPass(Pass):
129
131
  else:
130
132
  if isinstance(last_element, ast.Import):
131
133
  self.emit_ln(node, "")
132
- self.emit_ln(node, i.gen.jac)
133
- if not node.gen.jac.endswith("\n"):
134
+ if last_element and (
135
+ isinstance(i, ast.Architype)
136
+ and isinstance(last_element, ast.Architype)
137
+ and i.loc.first_line - last_element.loc.last_line == 2
138
+ and not node.gen.jac.endswith("\n\n")
139
+ ):
134
140
  self.emit_ln(node, "")
141
+ self.emit_ln(node, i.gen.jac)
142
+
135
143
  if counter <= len(node.body) - 1:
136
144
  if (
137
145
  isinstance(i, ast.Ability)
@@ -142,6 +150,7 @@ class JacFormatPass(Pass):
142
150
  and len(node.body[counter].kid[-1].kid) == 2
143
151
  and len(node.body[counter - 1].kid[-1].kid) == 2
144
152
  )
153
+ and node.gen.jac.endswith("\n")
145
154
  ):
146
155
  self.emit(node, "")
147
156
  else:
@@ -212,7 +221,7 @@ class JacFormatPass(Pass):
212
221
  items: list[T],
213
222
  """
214
223
  prev_token = None
215
- for i, stmt in enumerate(node.kid):
224
+ for stmt in node.kid:
216
225
  if isinstance(node.parent, (ast.EnumDef, ast.Enum)) and stmt.gen.jac == ",":
217
226
  self.indent_level -= 1
218
227
  self.emit_ln(node, f"{stmt.gen.jac}")
@@ -238,42 +247,18 @@ class JacFormatPass(Pass):
238
247
  if stmt.name == Tok.LBRACE:
239
248
  self.emit(node, f" {stmt.value}")
240
249
  elif stmt.name == Tok.RBRACE:
241
- if self.indent_level > 0:
242
- self.indent_level -= 1
243
- if (stmt.parent and stmt.parent.gen.jac.strip() == "{") or (
244
- stmt.parent
245
- and stmt.parent.parent
246
- and isinstance(
247
- stmt.parent.parent,
248
- (ast.ElseIf, ast.IfStmt, ast.IterForStmt, ast.TryStmt),
249
- )
250
- ):
250
+ self.indent_level = max(0, self.indent_level - 1)
251
+ if stmt.parent and stmt.parent.gen.jac.strip() == "{":
251
252
  self.emit(node, f"{stmt.value}")
252
253
  else:
253
- next_kid = (
254
- node.kid[i + 1]
255
- if i < (len(node.kid) - 1)
256
- else ast.EmptyToken()
257
- )
258
- if (
259
- isinstance(next_kid, ast.CommentToken)
260
- and next_kid.is_inline
261
- ):
262
- self.emit(node, f" {stmt.value}")
263
- elif not (node.gen.jac).endswith("\n"):
254
+ if not node.gen.jac.endswith("\n"):
264
255
  self.emit_ln(node, "")
265
- self.emit(node, f"{stmt.value}")
266
- else:
267
- self.emit(node, f"{stmt.value}")
256
+ self.emit(node, f"{stmt.value}")
268
257
  elif isinstance(stmt, ast.CommentToken):
269
258
  if stmt.is_inline:
270
259
  if isinstance(prev_token, ast.Semi) or (
271
260
  isinstance(prev_token, ast.Token)
272
- and prev_token.name
273
- in [
274
- Tok.LBRACE,
275
- Tok.RBRACE,
276
- ]
261
+ and prev_token.name in [Tok.LBRACE, Tok.RBRACE]
277
262
  ):
278
263
  self.indent_level -= 1
279
264
  self.emit(node, f" {stmt.gen.jac}")
@@ -297,48 +282,33 @@ class JacFormatPass(Pass):
297
282
  self.emit(node, stmt.gen.jac)
298
283
  if not stmt.gen.jac.endswith("postinit;"):
299
284
  self.indent_level -= 1
285
+ self.emit_ln(stmt, "")
300
286
  self.emit_ln(node, "")
301
287
  self.indent_level += 1
302
288
  elif stmt.gen.jac == ",":
303
289
  self.emit(node, f"{stmt.value} ")
304
290
  elif stmt.value == "=":
305
291
  self.emit(node, f" {stmt.value} ")
292
+ elif prev_token and prev_token.gen.jac.strip() == "@":
293
+ self.emit_ln(node, stmt.value)
306
294
  else:
307
- self.emit(node, f"{stmt.value}")
295
+ self.emit(node, f"{stmt.gen.jac}")
308
296
  prev_token = stmt
309
297
  continue
310
298
  elif isinstance(stmt, ast.Semi):
311
299
  self.emit(node, stmt.gen.jac)
312
- elif isinstance(prev_token, (ast.HasVar, ast.ArchHas)) and not isinstance(
313
- stmt, (ast.HasVar, ast.ArchHas)
300
+ elif (
301
+ isinstance(prev_token, (ast.HasVar, ast.ArchHas))
302
+ and not isinstance(stmt, (ast.HasVar, ast.ArchHas))
303
+ ) or (
304
+ isinstance(prev_token, ast.Ability)
305
+ and isinstance(stmt, (ast.Ability, ast.AbilityDef))
314
306
  ):
315
307
  if not isinstance(prev_token.kid[-1], ast.CommentToken):
316
308
  self.indent_level -= 1
317
309
  self.emit_ln(node, "")
318
310
  self.indent_level += 1
319
311
  self.emit(node, stmt.gen.jac)
320
- elif isinstance(prev_token, ast.Ability) and isinstance(
321
- stmt, (ast.Ability, ast.AbilityDef)
322
- ):
323
- if not isinstance(prev_token.kid[-1], ast.CommentToken) and (
324
- stmt.body and not isinstance(stmt.body, ast.FuncCall)
325
- ):
326
- self.indent_level -= 1
327
- self.emit_ln(node, "")
328
- self.indent_level += 1
329
- self.emit(node, f"{stmt.gen.jac}")
330
- elif stmt.body and isinstance(
331
- stmt.body, (ast.FuncCall, ast.EventSignature)
332
- ):
333
- self.indent_level -= 1
334
- self.emit_ln(node, "")
335
- self.indent_level += 1
336
- self.emit(node, stmt.gen.jac)
337
- else:
338
- self.indent_level -= 1
339
- self.emit_ln(node, "")
340
- self.indent_level += 1
341
- self.emit(node, f"{stmt.gen.jac}")
342
312
  else:
343
313
  if prev_token and prev_token.gen.jac.strip() == "{":
344
314
  self.emit_ln(node, "")
@@ -352,6 +322,7 @@ class JacFormatPass(Pass):
352
322
  tag: T,
353
323
  """
354
324
  start = True
325
+ prev_token = None
355
326
  for i in node.kid:
356
327
  if isinstance(i, ast.CommentToken):
357
328
  if i.is_inline:
@@ -366,8 +337,13 @@ class JacFormatPass(Pass):
366
337
  elif i.gen.jac == ",":
367
338
  self.emit(node, f"{i.gen.jac} ")
368
339
  else:
369
- if start:
370
- self.emit(node, i.gen.jac)
340
+ if isinstance(i, ast.Token) and not isinstance(i, ast.BuiltinType):
341
+ try:
342
+ prev_token = self.token_before(i)
343
+ except Exception:
344
+ prev_token = None
345
+ if start or (prev_token and prev_token.gen.jac.strip() == ":"):
346
+ self.emit(node, i.gen.jac.strip())
371
347
  start = False
372
348
  else:
373
349
  self.emit(node, f" {i.gen.jac}")
@@ -469,7 +445,7 @@ class JacFormatPass(Pass):
469
445
  path: list[Token],
470
446
  alias: Optional[Name],
471
447
  """
472
- self.emit(node, node.path_str)
448
+ self.emit(node, node.dot_path_str)
473
449
  if node.alias:
474
450
  self.emit(node, " as " + node.alias.gen.jac)
475
451
 
@@ -681,6 +657,8 @@ class JacFormatPass(Pass):
681
657
  self.emit(node, i.gen.jac)
682
658
  elif isinstance(i, ast.SubNodeList) and i.gen.jac.startswith("@"):
683
659
  self.emit_ln(node, i.gen.jac)
660
+ elif isinstance(i, ast.SubTag):
661
+ self.emit(node, i.gen.jac)
684
662
  else:
685
663
  if start:
686
664
  self.emit(node, i.gen.jac)
@@ -763,7 +741,7 @@ class JacFormatPass(Pass):
763
741
  self.indent_level += indent_val
764
742
  indented = True
765
743
  else:
766
- self.emit(node, f"{j.gen.jac.strip()}")
744
+ self.emit(node, j.gen.jac.lstrip())
767
745
  if indented:
768
746
  self.indent_level -= indent_val
769
747
  else:
@@ -929,6 +907,8 @@ class JacFormatPass(Pass):
929
907
  """Check if the length of the current generated code exceeds the max line length."""
930
908
  if max_line_length == 0:
931
909
  max_line_length = self.MAX_LINE_LENGTH
910
+ # print(content)
911
+ # print(len(content))
932
912
  return len(content) > max_line_length
933
913
 
934
914
  def exit_binary_expr(self, node: ast.BinaryExpr) -> None:
@@ -978,6 +958,7 @@ class JacFormatPass(Pass):
978
958
  self.error(
979
959
  f"Binary operator {node.op.value} not supported in bootstrap Jac"
980
960
  )
961
+ # print(node.gen)
981
962
  if isinstance(
982
963
  node.kid[-1], (ast.Semi, ast.CommentToken)
983
964
  ) and not node.gen.jac.endswith("\n"):
@@ -1110,6 +1091,9 @@ class JacFormatPass(Pass):
1110
1091
  if isinstance(i, ast.CommentToken):
1111
1092
  if i.is_inline:
1112
1093
  self.emit(node, f" {i.gen.jac}")
1094
+ elif (tok := self.token_before(i)) and (i.line_no - tok.line_no == 1):
1095
+ self.emit_ln(node, "")
1096
+ self.emit(node, i.gen.jac)
1113
1097
  else:
1114
1098
  self.emit_ln(node, "")
1115
1099
  self.emit_ln(node, "")
@@ -1340,38 +1324,96 @@ class JacFormatPass(Pass):
1340
1324
  if isinstance(node.kid[-1], (ast.Semi, ast.CommentToken)):
1341
1325
  self.emit_ln(node, "")
1342
1326
 
1327
+ def handle_long_assignment(self, node: ast.Assignment, kid: ast.AstNode) -> None:
1328
+ """Handle long assignment lines."""
1329
+ parts = re.split(r"(=)", kid.gen.jac)
1330
+ first_part = parts.pop(0).strip()
1331
+ self.emit_ln(
1332
+ node, f"{first_part} {parts.pop(0).strip()} {parts.pop(0).strip()}"
1333
+ )
1334
+ for j in range(0, len(parts) - 1, 2):
1335
+ op = parts[j]
1336
+ var = parts[j + 1].strip() if j + 1 < len(parts) else ""
1337
+ if var:
1338
+ self.indent_level += 1
1339
+ self.emit(node, f"{op} {var}")
1340
+ self.indent_level -= 1
1341
+ self.emit_ln(node, "")
1342
+ else:
1343
+ self.indent_level += 1
1344
+ self.emit(node, op)
1345
+ self.indent_level -= 1
1346
+
1347
+ def handle_long_expression(self, node: ast.AstNode, kid: ast.AstNode) -> None:
1348
+ """Handle long expressions with multiple operators."""
1349
+ parts = re.split(r"(\+|\-|\*|\/)", kid.gen.jac)
1350
+ self.emit_ln(node, f"{parts.pop(0).strip()}")
1351
+ for j in range(0, len(parts) - 1, 2):
1352
+ op = parts[j]
1353
+ var = parts[j + 1].strip() if j + 1 < len(parts) else ""
1354
+ if j < len(parts) - 2:
1355
+ self.indent_level += 1
1356
+ self.emit(node, f"{op} {var}")
1357
+ self.indent_level -= 1
1358
+ self.emit_ln(node, "")
1359
+ else:
1360
+ self.indent_level += 1
1361
+ self.emit(node, f"{op} {var}")
1362
+ self.indent_level -= 1
1363
+
1343
1364
  def exit_assignment(self, node: ast.Assignment) -> None:
1344
1365
  """Sub objects.
1345
1366
 
1346
- target: SubNodeList[AtomType],
1347
- value: Optional[ExprType | YieldStmt],
1348
- type_tag: Optional[SubTag[ExprType]],
1367
+ target: SubNodeList[Expr],
1368
+ value: Optional[Expr | YieldExpr],
1369
+ type_tag: Optional[SubTag[Expr]],
1349
1370
  mutable: bool = True,
1350
- aug_op: Optional[Token] = None
1371
+ aug_op: Optional[Token] = None,
1372
+ semstr: Optional[String] = None,
1373
+ is_enum_stmt: bool = False,
1351
1374
  """
1352
- for i in node.kid:
1353
- if isinstance(i, ast.CommentToken):
1354
- if i.is_inline:
1355
- self.emit(node, i.gen.jac)
1375
+ prev_token = None
1376
+ for kid in node.kid:
1377
+ if isinstance(kid, ast.CommentToken):
1378
+ if kid.is_inline:
1379
+ self.emit(node, kid.gen.jac)
1356
1380
  else:
1357
- if i.gen.jac not in [
1381
+ if kid.gen.jac not in [
1358
1382
  "# Update any new user level buddy schedule",
1359
1383
  "# Construct prompt here",
1360
1384
  ]:
1361
1385
  self.emit_ln(node, "")
1362
1386
  self.emit_ln(node, "")
1363
- self.emit_ln(node, i.gen.jac)
1387
+ self.emit_ln(node, kid.gen.jac)
1364
1388
  else:
1365
1389
  self.emit_ln(node, "")
1366
- self.emit(node, i.gen.jac)
1367
- elif isinstance(i, ast.Token) and (
1368
- i.name == Tok.KW_LET or i.gen.jac == ":"
1390
+ self.emit(node, kid.gen.jac)
1391
+ elif isinstance(kid, ast.Token) and (
1392
+ kid.name == Tok.KW_LET or kid.gen.jac == ":"
1369
1393
  ):
1370
- self.emit(node, f"{i.gen.jac} ")
1371
- elif isinstance(i, ast.Token) and "=" in i.gen.jac:
1372
- self.emit(node, f" {i.gen.jac} ")
1394
+ self.emit(node, f"{kid.gen.jac} ")
1395
+ elif isinstance(kid, ast.Token) and "=" in kid.gen.jac:
1396
+ self.emit(node, f" {kid.gen.jac} ")
1397
+ elif (
1398
+ "=" in kid.gen.jac
1399
+ and self.is_line_break_needed(
1400
+ kid.gen.jac, max_line_length=self.MAX_LINE_LENGTH * 2
1401
+ )
1402
+ and "\n" not in kid.gen.jac
1403
+ ):
1404
+ self.handle_long_assignment(node, kid)
1405
+ elif (
1406
+ prev_token
1407
+ and "=" in prev_token.gen.jac
1408
+ and self.is_line_break_needed(
1409
+ kid.gen.jac, max_line_length=self.MAX_LINE_LENGTH * 2
1410
+ )
1411
+ and "\n" not in kid.gen.jac
1412
+ ):
1413
+ self.handle_long_expression(node, kid)
1373
1414
  else:
1374
- self.emit(node, i.gen.jac)
1415
+ self.emit(node, kid.gen.jac)
1416
+ prev_token = kid
1375
1417
  if isinstance(
1376
1418
  node.kid[-1], (ast.Semi, ast.CommentToken)
1377
1419
  ) and not node.gen.jac.endswith("\n"):
@@ -2386,7 +2428,7 @@ class JacFormatPass(Pass):
2386
2428
  """
2387
2429
  self.emit(node, f"<>{node.value}" if node.is_kwesc else node.value)
2388
2430
 
2389
- def enter_float(self, node: ast.Float) -> None:
2431
+ def exit_float(self, node: ast.Float) -> None:
2390
2432
  """Sub objects.
2391
2433
 
2392
2434
  name: str,
@@ -2399,7 +2441,7 @@ class JacFormatPass(Pass):
2399
2441
  """
2400
2442
  self.emit(node, node.value)
2401
2443
 
2402
- def enter_int(self, node: ast.Int) -> None:
2444
+ def exit_int(self, node: ast.Int) -> None:
2403
2445
  """Sub objects.
2404
2446
 
2405
2447
  name: str,
@@ -2412,7 +2454,7 @@ class JacFormatPass(Pass):
2412
2454
  """
2413
2455
  self.emit(node, node.value)
2414
2456
 
2415
- def enter_string(self, node: ast.String) -> None:
2457
+ def exit_string(self, node: ast.String) -> None:
2416
2458
  """Sub objects.
2417
2459
 
2418
2460
  name: str,
@@ -2424,7 +2466,11 @@ class JacFormatPass(Pass):
2424
2466
  pos_end: int,
2425
2467
  """
2426
2468
  # if string is in docstring format and spans multiple lines turn into the multiple single quoted strings
2427
- if "\n" in node.value and node.parent and isinstance(node.parent, ast.Expr):
2469
+ if "\n" in node.value and (
2470
+ node.parent
2471
+ and isinstance(node.parent, ast.Expr)
2472
+ and not isinstance(node.parent, ast.MultiString)
2473
+ ):
2428
2474
  string_type = node.value[0:3]
2429
2475
  pure_string = node.value[3:-3]
2430
2476
  lines = pure_string.split("\n")
@@ -2442,14 +2488,14 @@ class JacFormatPass(Pass):
2442
2488
  string_type = node.value[0:3]
2443
2489
  pure_string = node.value[3:-3]
2444
2490
  lines = pure_string.split("\n")
2445
- self.emit(node, string_type)
2446
- for line in lines[:-1]:
2447
- self.emit_ln(node, line)
2448
- self.emit_ln(node, f"{lines[-1]}{string_type}")
2491
+ self.emit_ln(node, f"{string_type}{lines[0].lstrip()}")
2492
+ for line in lines[1:-1]:
2493
+ self.emit_ln(node, line.lstrip())
2494
+ self.emit(node, f"{lines[-1].lstrip()}{string_type}")
2449
2495
  else:
2450
2496
  self.emit(node, node.value)
2451
2497
 
2452
- def enter_bool(self, node: ast.Bool) -> None:
2498
+ def exit_bool(self, node: ast.Bool) -> None:
2453
2499
  """Sub objects.
2454
2500
 
2455
2501
  name: str,
@@ -32,7 +32,7 @@ obj ExecutionContext {
32
32
  "Global Execution Context, should be monkey patched by the user."
33
33
  glob exec_ctx = ExecutionContext();
34
34
 
35
- obj ElementAnchor {
35
+ obj Anchor :ArchitypeProtocol: {
36
36
  has ob: object,
37
37
  jid: UUID = :> uuid4,
38
38
  timestamp: datetime = :> datetime.now,
@@ -41,8 +41,12 @@ obj ElementAnchor {
41
41
  rw_access: set = :> set,
42
42
  ro_access: set = :> set,
43
43
  owner_id: UUID = exec_ctx.master,
44
- mem: Memory = exec_ctx.memory;
44
+ mem: Memory = exec_ctx.memory,
45
+ ds_entry_funcs: list[DSFunc],
46
+ ds_exit_funcs: list[DSFunc];
45
47
 
48
+ static can on_entry(cls: type, triggers: list[type]);
49
+ static can on_exit(cls: type, triggers: list[type]);
46
50
  can make_public_ro;
47
51
  can make_public_rw;
48
52
  can make_private;
@@ -55,15 +59,7 @@ obj ElementAnchor {
55
59
  can revoke_access(caller_id: UUID);
56
60
  }
57
61
 
58
- obj ObjectAnchor :ElementAnchor, ArchitypeProtocol: {
59
- has ds_entry_funcs: list[DSFunc],
60
- ds_exit_funcs: list[DSFunc];
61
-
62
- static can on_entry(cls: type, triggers: list[type]);
63
- static can on_exit(cls: type, triggers: list[type]);
64
- }
65
-
66
- obj NodeAnchor :ObjectAnchor: {
62
+ obj NodeAnchor :Anchor: {
67
63
  has edges: dict[EdgeDir, list[Edge]] = {EdgeDir.IN: [], EdgeDir.OUT: []};
68
64
 
69
65
  can connect_node(nd: Node, edg: Edge) -> Node;
@@ -71,7 +67,7 @@ obj NodeAnchor :ObjectAnchor: {
71
67
  can __call__(walk: Walker);
72
68
  }
73
69
 
74
- obj EdgeAnchor :ObjectAnchor: {
70
+ obj EdgeAnchor :Anchor: {
75
71
  has source: Node = None,
76
72
  target: Node = None,
77
73
  dir: EdgeDir = None;
@@ -81,7 +77,7 @@ obj EdgeAnchor :ObjectAnchor: {
81
77
  can __call__(walk: Walker);
82
78
  }
83
79
 
84
- obj WalkerAnchor :ObjectAnchor: {
80
+ obj WalkerAnchor :Anchor: {
85
81
  has path: list[Node] = [],
86
82
  next: list[Node] = [],
87
83
  ignores: list[Node] = [],
@@ -94,27 +90,27 @@ obj WalkerAnchor :ObjectAnchor: {
94
90
  }
95
91
 
96
92
  obj Root :AbsRootHook: {
97
- has _jac_: NodeAnchor | None = None;
93
+ has __jac__: NodeAnchor | None = None;
98
94
 
99
95
  can postinit {
100
- self._jac_ = NodeAnchor(self, ds_entry_funcs=[], ds_exit_funcs=[]);
96
+ self.__jac__ = NodeAnchor(self, ds_entry_funcs=[], ds_exit_funcs=[]);
101
97
  }
102
98
  }
103
99
 
104
100
  obj GenericEdge :ArchitypeProtocol: {
105
- has _jac_: EdgeAnchor | None = None;
101
+ has __jac__: EdgeAnchor | None = None;
106
102
 
107
103
  can postinit {
108
- self._jac_ = EdgeAnchor(self, ds_entry_funcs=[], ds_exit_funcs=[]);
104
+ self.__jac__ = EdgeAnchor(self, ds_entry_funcs=[], ds_exit_funcs=[]);
109
105
  }
110
106
  }
111
107
 
112
108
  obj Master {
113
- has _jac_: ElementAnchor | None = None;
109
+ has __jac__: Anchor | None = None;
114
110
  has root_node: Root = Root(Root);
115
111
 
116
112
  can postinit {
117
- self._jac_ = ElementAnchor(self);
113
+ self.__jac__ = Anchor(self);
118
114
  }
119
115
  }
120
116
 
@@ -204,31 +200,31 @@ obj JacPlugin {
204
200
  PRIVATE
205
201
  }
206
202
 
207
- :obj:ElementAnchor:can:make_public_ro {
203
+ :obj:Anchor:can:make_public_ro {
208
204
  self.__jinfo.access_mode = AccessMode.READ_ONLY;
209
205
  }
210
206
 
211
- :obj:ElementAnchor:can:make_public_rw {
207
+ :obj:Anchor:can:make_public_rw {
212
208
  self.__jinfo.access_mode = AccessMode.READ_WRITE;
213
209
  }
214
210
 
215
- :obj:ElementAnchor:can:make_private {
211
+ :obj:Anchor:can:make_private {
216
212
  self.__jinfo.access_mode = AccessMode.PRIVATE;
217
213
  }
218
214
 
219
- :obj:ElementAnchor:can:is_public_ro -> bool {
215
+ :obj:Anchor:can:is_public_ro -> bool {
220
216
  return self.__jinfo.access_mode == AccessMode.READ_ONLY;
221
217
  }
222
218
 
223
- :obj:ElementAnchor:can:is_public_rw -> bool {
219
+ :obj:Anchor:can:is_public_rw -> bool {
224
220
  return self.__jinfo.access_mode == AccessMode.READ_WRITE;
225
221
  }
226
222
 
227
- :obj:ElementAnchor:can:is_private -> bool {
223
+ :obj:Anchor:can:is_private -> bool {
228
224
  return self.__jinfo.access_mode == AccessMode.PRIVATE;
229
225
  }
230
226
 
231
- :obj:ElementAnchor:can:is_readable
227
+ :obj:Anchor:can:is_readable
232
228
  (caller_id: UUID) -> bool {
233
229
  return (caller_id == self.owner_id
234
230
  or |> self.is_public_read
@@ -236,14 +232,14 @@ obj JacPlugin {
236
232
  or caller_id in self.rw_access);
237
233
  }
238
234
 
239
- :obj:ElementAnchor:can:is_writable
235
+ :obj:Anchor:can:is_writable
240
236
  (caller_id: UUID) -> bool {
241
237
  return (caller_id == self.owner_id
242
238
  or |> self.is_public_write
243
239
  or caller_id in self.rw_access);
244
240
  }
245
241
 
246
- :obj:ElementAnchor:can:give_access
242
+ :obj:Anchor:can:give_access
247
243
  (caller_id: UUID, read_write: bool=False) {
248
244
  if read_write {
249
245
  caller_id |> self.rw_access.add;
@@ -252,13 +248,13 @@ obj JacPlugin {
252
248
  }
253
249
  }
254
250
 
255
- :obj:ElementAnchor:can:revoke_access
251
+ :obj:Anchor:can:revoke_access
256
252
  (caller_id: UUID) {
257
253
  caller_id |> self.ro_access.discard;
258
254
  caller_id |> self.rw_access.discard;
259
255
  }
260
256
 
261
- :obj:ObjectAnchor:can:on_entry
257
+ :obj:Anchor:can:on_entry
262
258
  (cls: type, triggers: list) {
263
259
  can decorator(func: callable) -> callable {
264
260
  cls.ds_entry_funcs.append(
@@ -272,7 +268,7 @@ obj JacPlugin {
272
268
  return decorator;
273
269
  }
274
270
 
275
- :obj:ObjectAnchor:can:on_exit
271
+ :obj:Anchor:can:on_exit
276
272
  (cls: type, triggers: list) {
277
273
  can decorator(func: callable) -> callable {
278
274
  cls.ds_exit_funcs.append(
@@ -361,7 +357,7 @@ obj JacPlugin {
361
357
 
362
358
  :obj:NodeAnchor:can:__call__
363
359
  (walk: object) {
364
- if not isinstance(walk._jac_, WalkerAnchor) {
360
+ if not isinstance(walk.__jac__, WalkerAnchor) {
365
361
  raise TypeError("Argument must be a Walker instance");
366
362
  }
367
363
  walk(self);
@@ -369,10 +365,10 @@ obj JacPlugin {
369
365
 
370
366
  :obj:EdgeAnchor:can:__call__
371
367
  (walk: EdgeInterface) {
372
- if not isinstance(walk._jac_, WalkerAnchor) {
368
+ if not isinstance(walk.__jac__, WalkerAnchor) {
373
369
  raise TypeError("Argument must be a Walker instance");
374
370
  }
375
- walk(self._jac_.target);
371
+ walk(self.__jac__.target);
376
372
  }
377
373
 
378
374
  :obj:WalkerAnchor:can:__call__
@@ -423,25 +419,25 @@ obj JacPlugin {
423
419
  (arch: AT, arch_type: str, on_entry: list[DSFunc], on_exit: list[DSFunc]) -> bool {
424
420
  match arch_type {
425
421
  case 'obj':
426
- arch._jac_ = ObjectAnchor(
422
+ arch.__jac__ = Anchor(
427
423
  ob=arch,
428
424
  ds_entry_funcs=on_entry,
429
425
  ds_exit_funcs=on_exit
430
426
  );
431
427
  case 'node':
432
- arch._jac_ = NodeAnchor(
428
+ arch.__jac__ = NodeAnchor(
433
429
  ob=arch,
434
430
  ds_entry_funcs=on_entry,
435
431
  ds_exit_funcs=on_exit
436
432
  );
437
433
  case 'edge':
438
- arch._jac_ = EdgeAnchor(
434
+ arch.__jac__ = EdgeAnchor(
439
435
  ob=arch,
440
436
  ds_entry_funcs=on_entry,
441
437
  ds_exit_funcs=on_exit
442
438
  );
443
439
  case 'walker':
444
- arch._jac_ = WalkerAnchor(
440
+ arch.__jac__ = WalkerAnchor(
445
441
  ob=arch,
446
442
  ds_entry_funcs=on_entry,
447
443
  ds_exit_funcs=on_exit
@@ -464,19 +460,19 @@ obj JacPlugin {
464
460
  edg_type = edge_spec[1];
465
461
  }
466
462
  edg = edg_type(*(edge_spec[2])) if edge_spec[2] else edg_type();
467
- edg._jac_.apply_dir(edge_spec[0]);
463
+ edg.__jac__.apply_dir(edge_spec[0]);
468
464
  return edg;
469
465
  }
470
466
 
471
467
  :obj:JacPlugin:can:connect
472
468
  (left: T, right: T, edge_spec: tuple[int, Optional[type], Optional[tuple]]) -> Architype {
473
469
  edg = JacPlugin.build_edge(edge_spec);
474
- left.connect_node(right._jac_, edg._jac_);
470
+ left.connect_node(right.__jac__, edg.__jac__);
475
471
  }
476
472
 
477
473
  :obj:JacPlugin:can:visit_node
478
474
  (walker_obj: Any, expr: Any) -> bool {
479
- return walker_obj._jac_.visit_node(expr);
475
+ return walker_obj.__jac__.visit_node(expr);
480
476
  }
481
477
 
482
478
  glob expected_area = 78.53981633974483;