jaclang 0.8.7__py3-none-any.whl → 0.8.9__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 (99) hide show
  1. jaclang/cli/cli.py +77 -29
  2. jaclang/cli/cmdreg.py +44 -0
  3. jaclang/compiler/constant.py +6 -2
  4. jaclang/compiler/jac.lark +37 -47
  5. jaclang/compiler/larkparse/jac_parser.py +2 -2
  6. jaclang/compiler/parser.py +356 -61
  7. jaclang/compiler/passes/main/__init__.py +2 -4
  8. jaclang/compiler/passes/main/def_use_pass.py +1 -4
  9. jaclang/compiler/passes/main/predynamo_pass.py +221 -0
  10. jaclang/compiler/passes/main/pyast_gen_pass.py +221 -135
  11. jaclang/compiler/passes/main/pyast_load_pass.py +54 -20
  12. jaclang/compiler/passes/main/sym_tab_build_pass.py +1 -1
  13. jaclang/compiler/passes/main/tests/fixtures/checker/import_sym.jac +2 -0
  14. jaclang/compiler/passes/main/tests/fixtures/checker/import_sym_test.jac +6 -0
  15. jaclang/compiler/passes/main/tests/fixtures/checker/imported_sym.jac +5 -0
  16. jaclang/compiler/passes/main/tests/fixtures/checker_arg_param_match.jac +37 -0
  17. jaclang/compiler/passes/main/tests/fixtures/checker_arity.jac +18 -0
  18. jaclang/compiler/passes/main/tests/fixtures/checker_cat_is_animal.jac +18 -0
  19. jaclang/compiler/passes/main/tests/fixtures/checker_float.jac +7 -0
  20. jaclang/compiler/passes/main/tests/fixtures/checker_param_types.jac +11 -0
  21. jaclang/compiler/passes/main/tests/fixtures/checker_self_type.jac +9 -0
  22. jaclang/compiler/passes/main/tests/fixtures/checker_sym_inherit.jac +42 -0
  23. jaclang/compiler/passes/main/tests/fixtures/predynamo_fix3.jac +43 -0
  24. jaclang/compiler/passes/main/tests/fixtures/predynamo_where_assign.jac +13 -0
  25. jaclang/compiler/passes/main/tests/fixtures/predynamo_where_return.jac +11 -0
  26. jaclang/compiler/passes/main/tests/test_checker_pass.py +190 -0
  27. jaclang/compiler/passes/main/tests/test_predynamo_pass.py +56 -0
  28. jaclang/compiler/passes/main/type_checker_pass.py +29 -73
  29. jaclang/compiler/passes/tool/doc_ir_gen_pass.py +302 -58
  30. jaclang/compiler/passes/tool/jac_formatter_pass.py +119 -69
  31. jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +3 -3
  32. jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +4 -5
  33. jaclang/compiler/passes/tool/tests/fixtures/import_fmt.jac +7 -1
  34. jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +276 -10
  35. jaclang/compiler/passes/transform.py +12 -8
  36. jaclang/compiler/program.py +19 -7
  37. jaclang/compiler/tests/fixtures/jac_import_py_files.py +4 -0
  38. jaclang/compiler/tests/fixtures/jac_module.jac +3 -0
  39. jaclang/compiler/tests/fixtures/multiple_syntax_errors.jac +10 -0
  40. jaclang/compiler/tests/fixtures/python_module.py +1 -0
  41. jaclang/compiler/tests/test_importer.py +39 -0
  42. jaclang/compiler/tests/test_parser.py +49 -0
  43. jaclang/compiler/type_system/type_evaluator.jac +959 -0
  44. jaclang/compiler/type_system/type_utils.py +246 -0
  45. jaclang/compiler/type_system/types.py +58 -2
  46. jaclang/compiler/unitree.py +102 -107
  47. jaclang/langserve/engine.jac +138 -159
  48. jaclang/langserve/server.jac +25 -1
  49. jaclang/langserve/tests/fixtures/circle.jac +3 -3
  50. jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
  51. jaclang/langserve/tests/fixtures/circle_pure.test.jac +3 -3
  52. jaclang/langserve/tests/fixtures/completion_test_err.jac +10 -0
  53. jaclang/langserve/tests/server_test/circle_template.jac +80 -0
  54. jaclang/langserve/tests/server_test/glob_template.jac +4 -0
  55. jaclang/langserve/tests/server_test/test_lang_serve.py +154 -309
  56. jaclang/langserve/tests/server_test/utils.py +153 -116
  57. jaclang/langserve/tests/test_server.py +21 -84
  58. jaclang/langserve/utils.jac +12 -15
  59. jaclang/lib.py +17 -0
  60. jaclang/runtimelib/archetype.py +25 -25
  61. jaclang/runtimelib/constructs.py +2 -2
  62. jaclang/runtimelib/machine.py +63 -46
  63. jaclang/runtimelib/meta_importer.py +27 -1
  64. jaclang/runtimelib/tests/fixtures/custom_access_validation.jac +1 -1
  65. jaclang/runtimelib/tests/fixtures/savable_object.jac +2 -2
  66. jaclang/settings.py +19 -16
  67. jaclang/tests/fixtures/abc_check.jac +3 -3
  68. jaclang/tests/fixtures/arch_rel_import_creation.jac +12 -12
  69. jaclang/tests/fixtures/attr_pattern_case.jac +18 -0
  70. jaclang/tests/fixtures/chandra_bugs2.jac +3 -3
  71. jaclang/tests/fixtures/create_dynamic_archetype.jac +13 -13
  72. jaclang/tests/fixtures/funccall_genexpr.jac +7 -0
  73. jaclang/tests/fixtures/funccall_genexpr.py +5 -0
  74. jaclang/tests/fixtures/maxfail_run_test.jac +4 -4
  75. jaclang/tests/fixtures/params/param_syntax_err.jac +9 -0
  76. jaclang/tests/fixtures/params/test_complex_params.jac +42 -0
  77. jaclang/tests/fixtures/params/test_failing_kwonly.jac +207 -0
  78. jaclang/tests/fixtures/params/test_failing_posonly.jac +116 -0
  79. jaclang/tests/fixtures/params/test_failing_varargs.jac +300 -0
  80. jaclang/tests/fixtures/params/test_kwonly_params.jac +29 -0
  81. jaclang/tests/fixtures/py2jac_params.py +8 -0
  82. jaclang/tests/fixtures/run_test.jac +4 -4
  83. jaclang/tests/test_cli.py +159 -7
  84. jaclang/tests/test_language.py +213 -38
  85. jaclang/tests/test_reference.py +3 -1
  86. jaclang/utils/helpers.py +67 -6
  87. jaclang/utils/module_resolver.py +10 -0
  88. jaclang/utils/test.py +8 -0
  89. jaclang/utils/tests/test_lang_tools.py +4 -15
  90. jaclang/utils/treeprinter.py +0 -18
  91. {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/METADATA +1 -2
  92. {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/RECORD +95 -65
  93. {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/WHEEL +1 -1
  94. jaclang/compiler/passes/main/inheritance_pass.py +0 -131
  95. jaclang/compiler/type_system/type_evaluator.py +0 -560
  96. jaclang/langserve/dev_engine.jac +0 -645
  97. jaclang/langserve/dev_server.jac +0 -201
  98. /jaclang/{langserve/tests/server_test/code_test.py → tests/fixtures/py2jac_empty.py} +0 -0
  99. {jaclang-0.8.7.dist-info → jaclang-0.8.9.dist-info}/entry_points.txt +0 -0
jaclang/cli/cli.py CHANGED
@@ -1,12 +1,12 @@
1
1
  """Command line interface tool for the Jac language."""
2
2
 
3
3
  import ast as ast3
4
- import importlib
5
4
  import marshal
6
5
  import os
7
6
  import pickle
8
7
  import sys
9
8
  import types
9
+ from importlib.metadata import version as pkg_version
10
10
  from pathlib import Path
11
11
  from typing import Optional
12
12
 
@@ -18,6 +18,7 @@ from jaclang.runtimelib.builtin import printgraph
18
18
  from jaclang.runtimelib.constructs import WalkerArchetype
19
19
  from jaclang.runtimelib.machine import ExecutionContext, JacMachine as Jac
20
20
  from jaclang.runtimelib.utils import read_file_with_encoding
21
+ from jaclang.settings import settings
21
22
  from jaclang.utils.helpers import debugger as db
22
23
  from jaclang.utils.lang_tools import AstTool
23
24
 
@@ -61,7 +62,7 @@ def format(path: str, outfile: str = "", to_screen: bool = False) -> None:
61
62
  if path.endswith(".jac"):
62
63
  if not path_obj.exists():
63
64
  print(f"Error: File '{path}' does not exist.", file=sys.stderr)
64
- return
65
+ exit(1)
65
66
  formatted_code = JacProgram.jac_file_formatter(str(path_obj))
66
67
  write_formatted_code(formatted_code, str(path_obj))
67
68
  return
@@ -78,6 +79,7 @@ def format(path: str, outfile: str = "", to_screen: bool = False) -> None:
78
79
 
79
80
  # Case 3: Invalid path
80
81
  print(f"Error: '{path}' is not a .jac file or directory.", file=sys.stderr)
82
+ exit(1)
81
83
 
82
84
 
83
85
  def proc_file_sess(
@@ -103,6 +105,7 @@ def proc_file_sess(
103
105
  "Not a valid file!\nOnly supports `.jac`, `.jir`, and `.py`",
104
106
  file=sys.stderr,
105
107
  )
108
+ exit(1)
106
109
  mach = ExecutionContext(session=session, root=root)
107
110
  Jac.set_context(mach)
108
111
  return base, mod, mach
@@ -148,6 +151,8 @@ def run(
148
151
  )
149
152
  except Exception as e:
150
153
  print(f"Error running {filename}: {e}", file=sys.stderr)
154
+ mach.close()
155
+ exit(1)
151
156
  elif filename.endswith(".jir"):
152
157
  try:
153
158
  with open(filename, "rb") as f:
@@ -160,11 +165,8 @@ def run(
160
165
  )
161
166
  except Exception as e:
162
167
  print(f"Error running {filename}: {e}", file=sys.stderr)
163
- else:
164
- print(
165
- "Not a valid file!\nOnly supports `.jac`, `.jir`, and `.py`",
166
- file=sys.stderr,
167
- )
168
+ mach.close()
169
+ exit(1)
168
170
 
169
171
  mach.close()
170
172
 
@@ -212,6 +214,8 @@ def get_object(filename: str, id: str, session: str = "", main: bool = True) ->
212
214
  data = obj.__jac__.__getstate__()
213
215
  else:
214
216
  print(f"Object with id {id} not found.", file=sys.stderr)
217
+ mach.close()
218
+ exit(1)
215
219
  mach.close()
216
220
  return data
217
221
 
@@ -242,6 +246,9 @@ def build(filename: str, typecheck: bool = False) -> None:
242
246
  for alrt in out.errors_had + out.warnings_had:
243
247
  print(alrt.pretty_print(), file=sys.stderr)
244
248
 
249
+ if errs > 0:
250
+ exit(1)
251
+
245
252
  with open(filename[:-4] + ".jir", "wb") as f:
246
253
  pickle.dump(out, f)
247
254
 
@@ -277,8 +284,11 @@ def bind(filename: str, typecheck: bool = False) -> None:
277
284
  divider = "=" * 40
278
285
  print(f"{divider}\n{header}\n{divider}\n{mods.sym_tab.sym_pp()}")
279
286
  print(f"Errors: {errs}, Warnings: {warnings}")
287
+ if errs > 0:
288
+ exit(1)
280
289
  else:
281
290
  print("Not a .jac/.py file.", file=sys.stderr)
291
+ exit(1)
282
292
 
283
293
 
284
294
  @cmd_registry.register
@@ -305,8 +315,11 @@ def check(filename: str, print_errs: bool = True) -> None:
305
315
  for e in prog.errors_had:
306
316
  print("Error:", e, file=sys.stderr)
307
317
  print(f"Errors: {errs}, Warnings: {warnings}")
318
+ if errs > 0:
319
+ exit(1)
308
320
  else:
309
321
  print("Not a .jac file.", file=sys.stderr)
322
+ exit(1)
310
323
 
311
324
 
312
325
  @cmd_registry.register
@@ -322,25 +335,7 @@ def lsp() -> None:
322
335
  Examples:
323
336
  jac lsp
324
337
  """
325
- from jaclang.langserve.server import run_lang_server
326
-
327
- run_lang_server()
328
-
329
-
330
- @cmd_registry.register
331
- def lsp_dev() -> None:
332
- """Run Jac Language Server Protocol in Developer Mode.
333
-
334
- Starts the experimental Jac Language Server with enhanced features
335
- for development and testing. Used by editor extensions in developer mode.
336
-
337
- Args:
338
- This command takes no parameters.
339
-
340
- Examples:
341
- jac lsp_dev
342
- """
343
- from jaclang.langserve.dev_server import run_lang_server
338
+ from jaclang.langserve.server import run_lang_server # type: ignore
344
339
 
345
340
  run_lang_server()
346
341
 
@@ -398,6 +393,8 @@ def enter(
398
393
  (loaded_mod,) = ret_module
399
394
  if not loaded_mod:
400
395
  print("Errors occurred while importing the module.", file=sys.stderr)
396
+ mach.close()
397
+ exit(1)
401
398
  else:
402
399
  archetype = getattr(loaded_mod, entrypoint)(*args)
403
400
 
@@ -488,6 +485,7 @@ def tool(tool: str, args: Optional[list] = None) -> None:
488
485
  raise e
489
486
  else:
490
487
  print(f"Ast tool {tool} not found.", file=sys.stderr)
488
+ exit(1)
491
489
 
492
490
 
493
491
  @cmd_registry.register
@@ -525,8 +523,10 @@ def debug(filename: str, main: bool = True, cache: bool = False) -> None:
525
523
  print("Done debugging.")
526
524
  else:
527
525
  print(f"Error while generating bytecode in {filename}.", file=sys.stderr)
526
+ exit(1)
528
527
  else:
529
528
  print("Not a .jac file.", file=sys.stderr)
529
+ exit(1)
530
530
 
531
531
 
532
532
  @cmd_registry.register
@@ -597,6 +597,7 @@ def dot(
597
597
  jac_machine.close()
598
598
  else:
599
599
  print("Not a .jac file.", file=sys.stderr)
600
+ exit(1)
600
601
 
601
602
 
602
603
  @cmd_registry.register
@@ -629,8 +630,10 @@ def py2jac(filename: str) -> None:
629
630
  print(formatted_code)
630
631
  else:
631
632
  print("Error converting Python code to Jac.", file=sys.stderr)
633
+ exit(1)
632
634
  else:
633
635
  print("Not a .py file.")
636
+ exit(1)
634
637
 
635
638
 
636
639
  @cmd_registry.register
@@ -649,9 +652,46 @@ def jac2py(filename: str) -> None:
649
652
  """
650
653
  if filename.endswith(".jac"):
651
654
  code = JacProgram().compile(file_path=filename).gen.py
652
- print(code)
655
+ if code:
656
+ print(code)
657
+ else:
658
+ exit(1)
653
659
  else:
654
660
  print("Not a .jac file.", file=sys.stderr)
661
+ exit(1)
662
+
663
+
664
+ @cmd_registry.register
665
+ def jac2lib(filename: str) -> None:
666
+ """Convert a Jac file to Python library code.
667
+
668
+ Translates Jac source code to equivalent Python code with library mode enabled.
669
+ In library mode, the generated Python uses direct imports from jaclang.lib
670
+ instead of aliased imports, making the output cleaner and more suitable for
671
+ use as a standalone library.
672
+
673
+ Args:
674
+ filename: Path to the .jac file to convert
675
+
676
+ Examples:
677
+ jac jac2lib myprogram.jac > mylib.py
678
+ """
679
+ if filename.endswith(".jac"):
680
+ # Temporarily enable library mode
681
+ original_library_mode = settings.library_mode
682
+ settings.library_mode = True
683
+ try:
684
+ code = JacProgram().compile(file_path=filename).gen.py
685
+ if code:
686
+ print(code)
687
+ else:
688
+ exit(1)
689
+ finally:
690
+ # Restore original setting
691
+ settings.library_mode = original_library_mode
692
+ else:
693
+ print("Not a .jac file.", file=sys.stderr)
694
+ exit(1)
655
695
 
656
696
 
657
697
  def start_cli() -> None:
@@ -673,8 +713,11 @@ def start_cli() -> None:
673
713
  args = parser.parse_args()
674
714
  cmd_registry.args = args
675
715
 
716
+ # Apply global settings overrides from CLI flags before running commands
717
+ settings.load_command_line_arguments(args)
718
+
676
719
  if args.version:
677
- version = importlib.metadata.version("jaclang")
720
+ version = pkg_version("jaclang")
678
721
  print(f"Jac version {version}")
679
722
  print("Jac path:", __file__)
680
723
  return
@@ -692,7 +735,12 @@ def start_cli() -> None:
692
735
  args_dict = vars(args)
693
736
  args_dict.pop("command")
694
737
  args_dict.pop("version", None)
695
- ret = command.call(**args_dict)
738
+
739
+ # Only pass parameters that the target command accepts
740
+ allowed_params = set(command.sig.parameters.keys())
741
+ filtered_args = {k: v for k, v in args_dict.items() if k in allowed_params}
742
+
743
+ ret = command.call(**filtered_args)
696
744
  if ret:
697
745
  print(ret)
698
746
 
jaclang/cli/cmdreg.py CHANGED
@@ -5,8 +5,11 @@ from __future__ import annotations
5
5
  import argparse
6
6
  import inspect
7
7
  import re
8
+ from dataclasses import fields as dataclass_fields
8
9
  from typing import Callable, Dict, Optional
9
10
 
11
+ from jaclang.settings import Settings as JacSettings
12
+
10
13
 
11
14
  class Command:
12
15
  """Represents a command in the command line interface."""
@@ -106,6 +109,47 @@ class CommandRegistry:
106
109
  )
107
110
  self.args = argparse.Namespace()
108
111
 
112
+ # Global settings overrides
113
+ settings_group = self.parser.add_argument_group(
114
+ "settings",
115
+ "Override Jac settings (from config/env). Provide only flags you want to change.",
116
+ )
117
+ for fld in dataclass_fields(JacSettings):
118
+ name = fld.name
119
+ opt = f"--{name.replace('_', '-')}"
120
+ if fld.type is bool:
121
+ # Tri-state: default None so unspecified won't override
122
+ settings_group.add_argument(
123
+ opt,
124
+ dest=name,
125
+ action="store_true",
126
+ default=None,
127
+ help=f"bool - Override setting '{name}' to true",
128
+ )
129
+ settings_group.add_argument(
130
+ f"--no-{name.replace('_', '-')}",
131
+ dest=name,
132
+ action="store_false",
133
+ default=None,
134
+ help=f"bool - Override setting '{name}' to false",
135
+ )
136
+ elif fld.type is int:
137
+ settings_group.add_argument(
138
+ opt,
139
+ dest=name,
140
+ type=int,
141
+ default=None,
142
+ help=f"int - Override setting '{name}'",
143
+ )
144
+ else:
145
+ settings_group.add_argument(
146
+ opt,
147
+ dest=name,
148
+ type=str,
149
+ default=None,
150
+ help=f"str - Override setting '{name}'",
151
+ )
152
+
109
153
  def register(self, func: Callable) -> Callable:
110
154
  """Register a command in the registry."""
111
155
  name = func.__name__
@@ -178,7 +178,6 @@ class Tokens(str, Enum):
178
178
  KW_WAIT = "KW_WAIT"
179
179
  KW_TEST = "KW_TEST"
180
180
  KW_ASSERT = "KW_ASSERT"
181
- KW_CHECK = "KW_CHECK"
182
181
  COLON = "COLON"
183
182
  PIPE_FWD = "PIPE_FWD"
184
183
  PIPE_BKWD = "PIPE_BKWD"
@@ -198,7 +197,6 @@ class Tokens(str, Enum):
198
197
  BW_AND_EQ = "BW_AND_EQ"
199
198
  BW_OR_EQ = "BW_OR_EQ"
200
199
  BW_XOR_EQ = "BW_XOR_EQ"
201
- BW_NOT_EQ = "BW_NOT_EQ"
202
200
  LSHIFT_EQ = "LSHIFT_EQ"
203
201
  RSHIFT_EQ = "RSHIFT_EQ"
204
202
  WALRUS_EQ = "WALRUS_EQ"
@@ -301,8 +299,14 @@ class Tokens(str, Enum):
301
299
  FSTR_END = "FSTR_END"
302
300
  FSTR_SQ_START = "FSTR_SQ_START"
303
301
  FSTR_SQ_END = "FSTR_SQ_END"
302
+ FSTR_TRIPLE_START = "FSTR_TRIPLE_START"
303
+ FSTR_TRIPLE_END = "FSTR_TRIPLE_END"
304
+ FSTR_SQ_TRIPLE_START = "FSTR_SQ_TRIPLE_START"
305
+ FSTR_SQ_TRIPLE_END = "FSTR_SQ_TRIPLE_END"
304
306
  FSTR_PIECE = "FSTR_PIECE"
305
307
  FSTR_SQ_PIECE = "FSTR_SQ_PIECE"
308
+ FSTR_TRIPLE_PIECE = "FSTR_TRIPLE_PIECE"
309
+ FSTR_SQ_TRIPLE_PIECE = "FSTR_SQ_TRIPLE_PIECE"
306
310
  FSTR_BESC = "FSTR_BESC"
307
311
  COMMENT = "COMMENT"
308
312
  WS = "WS"
jaclang/compiler/jac.lark CHANGED
@@ -28,7 +28,7 @@ import_items: (import_item COMMA)* import_item COMMA?
28
28
  import_item: named_ref (KW_AS NAME)?
29
29
  dotted_name: named_ref (DOT named_ref)*
30
30
 
31
- // [Heading]: Archetypes.
31
+ // [Heading]: Class Archetypes.
32
32
  archetype: decorators? KW_ASYNC? archetype_decl
33
33
  | enum
34
34
 
@@ -44,7 +44,7 @@ arch_type: KW_WALKER
44
44
  | KW_NODE
45
45
  | KW_CLASS
46
46
 
47
- // [Heading]: Archetype bodies.
47
+ // [Heading]: Class Archetype bodies.
48
48
  member_block: LBRACE member_stmt* RBRACE
49
49
  member_stmt: STRING? (py_code_block | ability | archetype | impl_def | has_stmt | free_code)
50
50
  has_stmt: KW_STATIC? (KW_LET | KW_HAS) access_tag? has_assign_list SEMI
@@ -55,7 +55,7 @@ type_tag: COLON expression
55
55
  // [Heading]: Enumerations.
56
56
  enum: decorators? enum_decl
57
57
  enum_decl: KW_ENUM access_tag? NAME inherited_archs? (enum_block | SEMI)
58
- enum_block: LBRACE assignment_list COMMA? (py_code_block | free_code)* RBRACE
58
+ enum_block: LBRACE assignment_list (py_code_block | free_code)* RBRACE
59
59
 
60
60
  // [Heading]: Functions and Abilities.
61
61
  ability: decorators? KW_ASYNC? (ability_decl | function_decl)
@@ -70,6 +70,8 @@ func_decl: (LPAREN func_decl_params? RPAREN) (RETURN_HINT expression)?
70
70
 
71
71
  func_decl_params: (param_var COMMA)* param_var COMMA?
72
72
  param_var: (STAR_POW | STAR_MUL)? named_ref type_tag (EQ expression)?
73
+ | DIV
74
+ | STAR_MUL
73
75
 
74
76
  // [Heading]: Implementations.
75
77
  impl_def: decorators? KW_IMPL dotted_name impl_spec? impl_tail
@@ -77,13 +79,13 @@ impl_spec: inherited_archs | func_decl | event_clause
77
79
  impl_tail: enum_block | block_tail
78
80
 
79
81
  // [Heading]: Semstrings.
80
- sem_def: KW_SEM dotted_name EQ STRING SEMI
82
+ sem_def: KW_SEM dotted_name (EQ | KW_IS) STRING SEMI
81
83
 
82
84
  // [Heading]: Global variables.
83
85
  global_var: (KW_LET | KW_GLOBAL) access_tag? assignment_list SEMI
84
- assignment_list: (assignment_list COMMA)? (assignment | named_ref)
86
+ assignment_list: (assignment | named_ref) (COMMA (assignment | named_ref))* COMMA?
85
87
 
86
- // [Heading]: Free code.
88
+ // [Heading]: With entry blocks.
87
89
  free_code: KW_WITH KW_ENTRY (COLON NAME)? code_block
88
90
 
89
91
  // [Heading]: Inline python.
@@ -113,7 +115,6 @@ statement: import_stmt
113
115
  | (yield_expr | KW_YIELD) SEMI
114
116
  | raise_stmt SEMI
115
117
  | assert_stmt SEMI
116
- | check_stmt SEMI
117
118
  | assignment SEMI
118
119
  | delete_stmt SEMI
119
120
  | report_stmt SEMI
@@ -146,7 +147,6 @@ finally_stmt: KW_FINALLY code_block
146
147
  match_stmt: KW_MATCH expression LBRACE match_case_block+ RBRACE
147
148
  match_case_block: KW_CASE pattern_seq (KW_IF expression)? COLON statement+
148
149
 
149
- // [Heading]: Match patterns.
150
150
  pattern_seq: (or_pattern | as_pattern)
151
151
  or_pattern: (pattern BW_OR)* pattern
152
152
  as_pattern: or_pattern KW_AS NAME
@@ -156,28 +156,18 @@ pattern: literal_pattern
156
156
  | capture_pattern
157
157
  | sequence_pattern
158
158
  | mapping_pattern
159
+ | attr_pattern
159
160
  | class_pattern
160
161
 
161
-
162
- // [Heading]: Match literal patterns.
163
162
  literal_pattern: (INT | FLOAT | multistring)
164
-
165
- // [Heading]: Match singleton patterns.
166
163
  singleton_pattern: (NULL | BOOL)
167
-
168
- // [Heading]: Match capture patterns.
169
164
  capture_pattern: NAME
170
-
171
- // [Heading]: Match sequence patterns.
172
165
  sequence_pattern: LSQUARE list_inner_pattern (COMMA list_inner_pattern)* RSQUARE
173
166
  | LPAREN list_inner_pattern (COMMA list_inner_pattern)* RPAREN
174
-
175
- // [Heading]: Match mapping patterns.
176
167
  mapping_pattern: LBRACE (dict_inner_pattern (COMMA dict_inner_pattern)*)? RBRACE
177
168
  list_inner_pattern: (pattern_seq | STAR_MUL NAME)
178
169
  dict_inner_pattern: (literal_pattern COLON pattern_seq | STAR_POW NAME)
179
-
180
- // [Heading]: Match class patterns.
170
+ attr_pattern: NAME (DOT NAME)+
181
171
  class_pattern: NAME (DOT NAME)* LPAREN kw_pattern_list? RPAREN
182
172
  | NAME (DOT NAME)* LPAREN pattern_list (COMMA kw_pattern_list)? RPAREN
183
173
 
@@ -194,7 +184,7 @@ global_ref: GLOBAL_OP name_list
194
184
  nonlocal_ref: NONLOCAL_OP name_list
195
185
  name_list: (named_ref COMMA)* named_ref
196
186
 
197
- // [Heading]: Object spatial typed context blocks.
187
+ // [Heading]: Typed context blocks (OSP).
198
188
  typed_ctx_block: RETURN_HINT expression code_block
199
189
 
200
190
  // [Heading]: Return statements.
@@ -209,9 +199,6 @@ raise_stmt: KW_RAISE (expression (KW_FROM expression)?)?
209
199
  // [Heading]: Assert statements.
210
200
  assert_stmt: KW_ASSERT expression (COMMA expression)?
211
201
 
212
- // [Heading]: Check statements.
213
- check_stmt: KW_CHECK expression
214
-
215
202
  // [Heading]: Delete statements.
216
203
  delete_stmt: KW_DELETE expression
217
204
 
@@ -221,13 +208,9 @@ report_stmt: KW_REPORT expression
221
208
  // [Heading]: Control statements.
222
209
  ctrl_stmt: KW_SKIP | KW_BREAK | KW_CONTINUE
223
210
 
224
- // [Heading]: Object spatial Walker statements.
211
+ // [Heading]: Walker visit and disengage (OSP).
225
212
  spatial_stmt: visit_stmt | disenage_stmt
226
-
227
- // [Heading]: Visit statements.
228
213
  visit_stmt: KW_VISIT (COLON expression COLON)? expression (else_stmt | SEMI)
229
-
230
- // [Heading]: Disengage statements.
231
214
  disenage_stmt: KW_DISENGAGE SEMI
232
215
 
233
216
  // [Heading]: Assignments.
@@ -237,7 +220,6 @@ assignment: KW_LET? (atomic_chain EQ)+ (yield_expr | expression)
237
220
 
238
221
  aug_op: RSHIFT_EQ
239
222
  | LSHIFT_EQ
240
- | BW_NOT_EQ
241
223
  | BW_XOR_EQ
242
224
  | BW_OR_EQ
243
225
  | BW_AND_EQ
@@ -298,28 +280,29 @@ term: (term (MOD | DIV | FLOOR_DIV | STAR_MUL | DECOR_OP))? power
298
280
  power: (power STAR_POW)? factor
299
281
  factor: (BW_NOT | MINUS | PLUS) factor | connect
300
282
 
301
- // [Heading]: Connect expressions.
283
+ // [Heading]: Connect expressions (OSP).
302
284
  connect: (connect (connect_op | disconnect_op))? atomic_pipe
303
285
 
304
- // [Heading]: Atomic expressions.
286
+ // [Heading]: Pipe atomic expressions.
305
287
  atomic_pipe: (atomic_pipe A_PIPE_FWD)? atomic_pipe_back
306
288
 
307
- // [Heading]: Atomic pipe back expressions.
289
+ // [Heading]: Pipe back atomic expressions.
308
290
  atomic_pipe_back: (atomic_pipe_back A_PIPE_BKWD)? os_spawn
309
291
 
310
- // [Heading]: Object spatial spawn expressions.
292
+ // [Heading]: Spawn expressions (OSP).
311
293
  os_spawn: (os_spawn KW_SPAWN)? unpack
312
294
 
313
295
  // [Heading]: Unpack expressions.
314
296
  unpack: STAR_MUL? ref
315
297
 
316
- // [Heading]: References (unused).
317
- ref: BW_AND? pipe_call
298
+ // [Heading]: References (OSP).
299
+ ref: BW_AND? await_expr
318
300
 
319
- // [Heading]: Object spatial calls.
320
- pipe_call: (PIPE_FWD | A_PIPE_FWD | KW_SPAWN | KW_AWAIT)? atomic_chain
301
+ // [Heading]: Pipe-style function call.
302
+ await_expr: KW_AWAIT? pipe_call
303
+ pipe_call: (PIPE_FWD | A_PIPE_FWD | KW_SPAWN)? atomic_chain
321
304
 
322
- // [Heading]: Subscripted and dotted expressions.
305
+ // [Heading]: Attributes and Subscript expressions.
323
306
  atomic_chain: atomic_chain NULL_OK? (filter_compr | assign_compr | index_slice)
324
307
  | atomic_chain NULL_OK? (DOT_BKWD | DOT_FWD | DOT) named_ref
325
308
  | (atomic_call | atom | edge_ref_chain)
@@ -331,7 +314,7 @@ index_slice: LSQUARE
331
314
  | list_val
332
315
 
333
316
  // [Heading]: Function calls.
334
- atomic_call: atomic_chain LPAREN param_list? by_llm? RPAREN
317
+ atomic_call: atomic_chain (gen_compr | LPAREN param_list? by_llm? RPAREN)
335
318
 
336
319
  by_llm: KW_BY expression
337
320
 
@@ -339,7 +322,7 @@ param_list: expr_list COMMA kw_expr_list COMMA?
339
322
  | kw_expr_list COMMA?
340
323
  | expr_list COMMA?
341
324
 
342
- // [Heading]: Atom.
325
+ // [Heading]: Atomic expressions.
343
326
  atom: named_ref
344
327
  | LPAREN (expression | yield_expr) RPAREN
345
328
  | atom_collection
@@ -363,9 +346,13 @@ multistring: (fstring | STRING)+
363
346
 
364
347
  fstring: FSTR_START fstr_parts FSTR_END
365
348
  | FSTR_SQ_START fstr_sq_parts FSTR_SQ_END
349
+ | FSTR_TRIPLE_START fstr_triple_parts FSTR_TRIPLE_END
350
+ | FSTR_SQ_TRIPLE_START fstr_sq_triple_parts FSTR_SQ_TRIPLE_END
366
351
 
367
352
  fstr_parts: (FSTR_PIECE | FSTR_BESC | LBRACE expression RBRACE )*
368
353
  fstr_sq_parts: (FSTR_SQ_PIECE | FSTR_BESC | LBRACE expression RBRACE )*
354
+ fstr_triple_parts: (FSTR_TRIPLE_PIECE | FSTR_BESC | LBRACE expression RBRACE )*
355
+ fstr_sq_triple_parts: (FSTR_SQ_TRIPLE_PIECE | FSTR_BESC | LBRACE expression RBRACE )*
369
356
 
370
357
  // [Heading]: Collection values.
371
358
  atom_collection: dict_compr
@@ -391,7 +378,6 @@ set_val: LBRACE expr_list COMMA? RBRACE
391
378
  kv_pair: expression COLON expression | STAR_POW expression
392
379
  expr_list: (expr_list COMMA)? expression
393
380
 
394
- // [Heading]: Tuples and Jac Tuples.
395
381
  tuple_list: expression COMMA expr_list COMMA kw_expr_list COMMA?
396
382
  | expression COMMA kw_expr_list COMMA?
397
383
  | expression COMMA expr_list COMMA?
@@ -401,8 +387,8 @@ tuple_list: expression COMMA expr_list COMMA kw_expr_list COMMA?
401
387
  kw_expr_list: (kw_expr_list COMMA)? kw_expr
402
388
  kw_expr: named_ref EQ expression | STAR_POW expression
403
389
 
404
- // [Heading]: Object-Spatial References.
405
- edge_ref_chain: LSQUARE (KW_NODE| KW_EDGE)? expression? (edge_op_ref (filter_compr | expression)?)+ RSQUARE
390
+ // [Heading]: Edge references (OSP).
391
+ edge_ref_chain: LSQUARE KW_ASYNC? (KW_NODE| KW_EDGE)? expression? (edge_op_ref (filter_compr | expression)?)+ RSQUARE
406
392
  edge_op_ref: edge_any | edge_from | edge_to
407
393
  edge_to: ARROW_R | ARROW_R_P1 typed_filter_compare_list ARROW_R_P2
408
394
  edge_from: ARROW_L | ARROW_L_P1 typed_filter_compare_list ARROW_L_P2
@@ -413,7 +399,7 @@ connect_to: CARROW_R | CARROW_R_P1 expression (COLON kw_expr_list)? CARROW_R_P2
413
399
  connect_from: CARROW_L | CARROW_L_P1 expression (COLON kw_expr_list)? CARROW_L_P2
414
400
  connect_any: CARROW_BI | CARROW_L_P1 expression (COLON kw_expr_list)? CARROW_R_P2
415
401
 
416
- // [Heading]: Special Comprehensions.
402
+ // [Heading]: Filter and assign comprehensions.
417
403
  filter_compr: LPAREN NULL_OK filter_compare_list RPAREN
418
404
  | LPAREN TYPE_OP NULL_OK typed_filter_compare_list RPAREN
419
405
  assign_compr: LPAREN EQ kw_expr_list RPAREN
@@ -457,10 +443,16 @@ GLOBAL_OP: "global"
457
443
  NONLOCAL_OP: "nonlocal"
458
444
 
459
445
  // [Heading]: f-string tokens.
446
+ FSTR_TRIPLE_START.2: "f\"\"\""
447
+ FSTR_TRIPLE_END: "\"\"\""
448
+ FSTR_SQ_TRIPLE_START.2: "f'''"
449
+ FSTR_SQ_TRIPLE_END: "'''"
460
450
  FSTR_START.1: "f\""
461
451
  FSTR_END: "\""
462
452
  FSTR_SQ_START.1: "f'"
463
453
  FSTR_SQ_END: "'"
454
+ FSTR_TRIPLE_PIECE.-1: /(?:(?!""")(?![{}])[\s\S])+/
455
+ FSTR_SQ_TRIPLE_PIECE.-1: /(?:(?!''')(?![{}])[\s\S])+/
464
456
  FSTR_PIECE.-1: /[^\{\}\"]+/
465
457
  FSTR_SQ_PIECE.-1: /[^\{\}\']+/
466
458
  FSTR_BESC.1: /{{|}}/
@@ -523,7 +515,6 @@ KW_TEST: "test"
523
515
  KW_IMPL: "impl"
524
516
  KW_SEM: "sem"
525
517
  KW_ASSERT: "assert"
526
- KW_CHECK: "check"
527
518
  KW_IF: "if"
528
519
  KW_ELIF: "elif"
529
520
  KW_ELSE: "else"
@@ -627,7 +618,6 @@ FLOOR_DIV_EQ: "//="
627
618
  BW_AND_EQ: "&="
628
619
  BW_OR_EQ: "|="
629
620
  BW_XOR_EQ: "^="
630
- BW_NOT_EQ: "~="
631
621
  LSHIFT_EQ: "<<="
632
622
  RSHIFT_EQ: ">>="
633
623