jaclang 0.8.8__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 (36) hide show
  1. jaclang/cli/cli.py +64 -2
  2. jaclang/compiler/constant.py +6 -1
  3. jaclang/compiler/jac.lark +34 -41
  4. jaclang/compiler/larkparse/jac_parser.py +2 -2
  5. jaclang/compiler/parser.py +143 -27
  6. jaclang/compiler/passes/main/def_use_pass.py +1 -0
  7. jaclang/compiler/passes/main/pyast_gen_pass.py +151 -83
  8. jaclang/compiler/passes/main/pyast_load_pass.py +2 -0
  9. jaclang/compiler/passes/main/tests/test_checker_pass.py +0 -1
  10. jaclang/compiler/passes/main/tests/test_predynamo_pass.py +13 -14
  11. jaclang/compiler/passes/tool/doc_ir_gen_pass.py +104 -20
  12. jaclang/compiler/passes/tool/jac_formatter_pass.py +2 -2
  13. jaclang/compiler/passes/tool/tests/fixtures/import_fmt.jac +7 -1
  14. jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +135 -29
  15. jaclang/compiler/program.py +6 -2
  16. jaclang/compiler/type_system/type_evaluator.jac +959 -0
  17. jaclang/compiler/unitree.py +23 -13
  18. jaclang/lib.py +17 -0
  19. jaclang/runtimelib/archetype.py +25 -25
  20. jaclang/runtimelib/constructs.py +2 -2
  21. jaclang/runtimelib/machine.py +57 -47
  22. jaclang/settings.py +1 -2
  23. jaclang/tests/fixtures/attr_pattern_case.jac +18 -0
  24. jaclang/tests/fixtures/funccall_genexpr.jac +7 -0
  25. jaclang/tests/fixtures/funccall_genexpr.py +5 -0
  26. jaclang/tests/fixtures/py2jac_empty.py +0 -0
  27. jaclang/tests/test_cli.py +134 -18
  28. jaclang/tests/test_language.py +146 -29
  29. jaclang/tests/test_reference.py +3 -1
  30. jaclang/utils/helpers.py +20 -4
  31. jaclang/utils/tests/test_lang_tools.py +4 -15
  32. {jaclang-0.8.8.dist-info → jaclang-0.8.9.dist-info}/METADATA +1 -1
  33. {jaclang-0.8.8.dist-info → jaclang-0.8.9.dist-info}/RECORD +35 -30
  34. jaclang/compiler/type_system/type_evaluator.py +0 -844
  35. {jaclang-0.8.8.dist-info → jaclang-0.8.9.dist-info}/WHEEL +0 -0
  36. {jaclang-0.8.8.dist-info → jaclang-0.8.9.dist-info}/entry_points.txt +0 -0
jaclang/cli/cli.py CHANGED
@@ -62,7 +62,7 @@ def format(path: str, outfile: str = "", to_screen: bool = False) -> None:
62
62
  if path.endswith(".jac"):
63
63
  if not path_obj.exists():
64
64
  print(f"Error: File '{path}' does not exist.", file=sys.stderr)
65
- return
65
+ exit(1)
66
66
  formatted_code = JacProgram.jac_file_formatter(str(path_obj))
67
67
  write_formatted_code(formatted_code, str(path_obj))
68
68
  return
@@ -79,6 +79,7 @@ def format(path: str, outfile: str = "", to_screen: bool = False) -> None:
79
79
 
80
80
  # Case 3: Invalid path
81
81
  print(f"Error: '{path}' is not a .jac file or directory.", file=sys.stderr)
82
+ exit(1)
82
83
 
83
84
 
84
85
  def proc_file_sess(
@@ -104,6 +105,7 @@ def proc_file_sess(
104
105
  "Not a valid file!\nOnly supports `.jac`, `.jir`, and `.py`",
105
106
  file=sys.stderr,
106
107
  )
108
+ exit(1)
107
109
  mach = ExecutionContext(session=session, root=root)
108
110
  Jac.set_context(mach)
109
111
  return base, mod, mach
@@ -149,6 +151,8 @@ def run(
149
151
  )
150
152
  except Exception as e:
151
153
  print(f"Error running {filename}: {e}", file=sys.stderr)
154
+ mach.close()
155
+ exit(1)
152
156
  elif filename.endswith(".jir"):
153
157
  try:
154
158
  with open(filename, "rb") as f:
@@ -161,6 +165,8 @@ def run(
161
165
  )
162
166
  except Exception as e:
163
167
  print(f"Error running {filename}: {e}", file=sys.stderr)
168
+ mach.close()
169
+ exit(1)
164
170
 
165
171
  mach.close()
166
172
 
@@ -208,6 +214,8 @@ def get_object(filename: str, id: str, session: str = "", main: bool = True) ->
208
214
  data = obj.__jac__.__getstate__()
209
215
  else:
210
216
  print(f"Object with id {id} not found.", file=sys.stderr)
217
+ mach.close()
218
+ exit(1)
211
219
  mach.close()
212
220
  return data
213
221
 
@@ -238,6 +246,9 @@ def build(filename: str, typecheck: bool = False) -> None:
238
246
  for alrt in out.errors_had + out.warnings_had:
239
247
  print(alrt.pretty_print(), file=sys.stderr)
240
248
 
249
+ if errs > 0:
250
+ exit(1)
251
+
241
252
  with open(filename[:-4] + ".jir", "wb") as f:
242
253
  pickle.dump(out, f)
243
254
 
@@ -273,8 +284,11 @@ def bind(filename: str, typecheck: bool = False) -> None:
273
284
  divider = "=" * 40
274
285
  print(f"{divider}\n{header}\n{divider}\n{mods.sym_tab.sym_pp()}")
275
286
  print(f"Errors: {errs}, Warnings: {warnings}")
287
+ if errs > 0:
288
+ exit(1)
276
289
  else:
277
290
  print("Not a .jac/.py file.", file=sys.stderr)
291
+ exit(1)
278
292
 
279
293
 
280
294
  @cmd_registry.register
@@ -301,8 +315,11 @@ def check(filename: str, print_errs: bool = True) -> None:
301
315
  for e in prog.errors_had:
302
316
  print("Error:", e, file=sys.stderr)
303
317
  print(f"Errors: {errs}, Warnings: {warnings}")
318
+ if errs > 0:
319
+ exit(1)
304
320
  else:
305
321
  print("Not a .jac file.", file=sys.stderr)
322
+ exit(1)
306
323
 
307
324
 
308
325
  @cmd_registry.register
@@ -376,6 +393,8 @@ def enter(
376
393
  (loaded_mod,) = ret_module
377
394
  if not loaded_mod:
378
395
  print("Errors occurred while importing the module.", file=sys.stderr)
396
+ mach.close()
397
+ exit(1)
379
398
  else:
380
399
  archetype = getattr(loaded_mod, entrypoint)(*args)
381
400
 
@@ -466,6 +485,7 @@ def tool(tool: str, args: Optional[list] = None) -> None:
466
485
  raise e
467
486
  else:
468
487
  print(f"Ast tool {tool} not found.", file=sys.stderr)
488
+ exit(1)
469
489
 
470
490
 
471
491
  @cmd_registry.register
@@ -503,8 +523,10 @@ def debug(filename: str, main: bool = True, cache: bool = False) -> None:
503
523
  print("Done debugging.")
504
524
  else:
505
525
  print(f"Error while generating bytecode in {filename}.", file=sys.stderr)
526
+ exit(1)
506
527
  else:
507
528
  print("Not a .jac file.", file=sys.stderr)
529
+ exit(1)
508
530
 
509
531
 
510
532
  @cmd_registry.register
@@ -575,6 +597,7 @@ def dot(
575
597
  jac_machine.close()
576
598
  else:
577
599
  print("Not a .jac file.", file=sys.stderr)
600
+ exit(1)
578
601
 
579
602
 
580
603
  @cmd_registry.register
@@ -607,8 +630,10 @@ def py2jac(filename: str) -> None:
607
630
  print(formatted_code)
608
631
  else:
609
632
  print("Error converting Python code to Jac.", file=sys.stderr)
633
+ exit(1)
610
634
  else:
611
635
  print("Not a .py file.")
636
+ exit(1)
612
637
 
613
638
 
614
639
  @cmd_registry.register
@@ -627,9 +652,46 @@ def jac2py(filename: str) -> None:
627
652
  """
628
653
  if filename.endswith(".jac"):
629
654
  code = JacProgram().compile(file_path=filename).gen.py
630
- print(code)
655
+ if code:
656
+ print(code)
657
+ else:
658
+ exit(1)
631
659
  else:
632
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)
633
695
 
634
696
 
635
697
  def start_cli() -> None:
@@ -197,7 +197,6 @@ class Tokens(str, Enum):
197
197
  BW_AND_EQ = "BW_AND_EQ"
198
198
  BW_OR_EQ = "BW_OR_EQ"
199
199
  BW_XOR_EQ = "BW_XOR_EQ"
200
- BW_NOT_EQ = "BW_NOT_EQ"
201
200
  LSHIFT_EQ = "LSHIFT_EQ"
202
201
  RSHIFT_EQ = "RSHIFT_EQ"
203
202
  WALRUS_EQ = "WALRUS_EQ"
@@ -300,8 +299,14 @@ class Tokens(str, Enum):
300
299
  FSTR_END = "FSTR_END"
301
300
  FSTR_SQ_START = "FSTR_SQ_START"
302
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"
303
306
  FSTR_PIECE = "FSTR_PIECE"
304
307
  FSTR_SQ_PIECE = "FSTR_SQ_PIECE"
308
+ FSTR_TRIPLE_PIECE = "FSTR_TRIPLE_PIECE"
309
+ FSTR_SQ_TRIPLE_PIECE = "FSTR_SQ_TRIPLE_PIECE"
305
310
  FSTR_BESC = "FSTR_BESC"
306
311
  COMMENT = "COMMENT"
307
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)
@@ -79,13 +79,13 @@ impl_spec: inherited_archs | func_decl | event_clause
79
79
  impl_tail: enum_block | block_tail
80
80
 
81
81
  // [Heading]: Semstrings.
82
- sem_def: KW_SEM dotted_name EQ STRING SEMI
82
+ sem_def: KW_SEM dotted_name (EQ | KW_IS) STRING SEMI
83
83
 
84
84
  // [Heading]: Global variables.
85
85
  global_var: (KW_LET | KW_GLOBAL) access_tag? assignment_list SEMI
86
- assignment_list: (assignment_list COMMA)? (assignment | named_ref)
86
+ assignment_list: (assignment | named_ref) (COMMA (assignment | named_ref))* COMMA?
87
87
 
88
- // [Heading]: Free code.
88
+ // [Heading]: With entry blocks.
89
89
  free_code: KW_WITH KW_ENTRY (COLON NAME)? code_block
90
90
 
91
91
  // [Heading]: Inline python.
@@ -147,7 +147,6 @@ finally_stmt: KW_FINALLY code_block
147
147
  match_stmt: KW_MATCH expression LBRACE match_case_block+ RBRACE
148
148
  match_case_block: KW_CASE pattern_seq (KW_IF expression)? COLON statement+
149
149
 
150
- // [Heading]: Match patterns.
151
150
  pattern_seq: (or_pattern | as_pattern)
152
151
  or_pattern: (pattern BW_OR)* pattern
153
152
  as_pattern: or_pattern KW_AS NAME
@@ -157,28 +156,18 @@ pattern: literal_pattern
157
156
  | capture_pattern
158
157
  | sequence_pattern
159
158
  | mapping_pattern
159
+ | attr_pattern
160
160
  | class_pattern
161
161
 
162
-
163
- // [Heading]: Match literal patterns.
164
162
  literal_pattern: (INT | FLOAT | multistring)
165
-
166
- // [Heading]: Match singleton patterns.
167
163
  singleton_pattern: (NULL | BOOL)
168
-
169
- // [Heading]: Match capture patterns.
170
164
  capture_pattern: NAME
171
-
172
- // [Heading]: Match sequence patterns.
173
165
  sequence_pattern: LSQUARE list_inner_pattern (COMMA list_inner_pattern)* RSQUARE
174
166
  | LPAREN list_inner_pattern (COMMA list_inner_pattern)* RPAREN
175
-
176
- // [Heading]: Match mapping patterns.
177
167
  mapping_pattern: LBRACE (dict_inner_pattern (COMMA dict_inner_pattern)*)? RBRACE
178
168
  list_inner_pattern: (pattern_seq | STAR_MUL NAME)
179
169
  dict_inner_pattern: (literal_pattern COLON pattern_seq | STAR_POW NAME)
180
-
181
- // [Heading]: Match class patterns.
170
+ attr_pattern: NAME (DOT NAME)+
182
171
  class_pattern: NAME (DOT NAME)* LPAREN kw_pattern_list? RPAREN
183
172
  | NAME (DOT NAME)* LPAREN pattern_list (COMMA kw_pattern_list)? RPAREN
184
173
 
@@ -195,7 +184,7 @@ global_ref: GLOBAL_OP name_list
195
184
  nonlocal_ref: NONLOCAL_OP name_list
196
185
  name_list: (named_ref COMMA)* named_ref
197
186
 
198
- // [Heading]: Object spatial typed context blocks.
187
+ // [Heading]: Typed context blocks (OSP).
199
188
  typed_ctx_block: RETURN_HINT expression code_block
200
189
 
201
190
  // [Heading]: Return statements.
@@ -219,13 +208,9 @@ report_stmt: KW_REPORT expression
219
208
  // [Heading]: Control statements.
220
209
  ctrl_stmt: KW_SKIP | KW_BREAK | KW_CONTINUE
221
210
 
222
- // [Heading]: Object spatial Walker statements.
211
+ // [Heading]: Walker visit and disengage (OSP).
223
212
  spatial_stmt: visit_stmt | disenage_stmt
224
-
225
- // [Heading]: Visit statements.
226
213
  visit_stmt: KW_VISIT (COLON expression COLON)? expression (else_stmt | SEMI)
227
-
228
- // [Heading]: Disengage statements.
229
214
  disenage_stmt: KW_DISENGAGE SEMI
230
215
 
231
216
  // [Heading]: Assignments.
@@ -235,7 +220,6 @@ assignment: KW_LET? (atomic_chain EQ)+ (yield_expr | expression)
235
220
 
236
221
  aug_op: RSHIFT_EQ
237
222
  | LSHIFT_EQ
238
- | BW_NOT_EQ
239
223
  | BW_XOR_EQ
240
224
  | BW_OR_EQ
241
225
  | BW_AND_EQ
@@ -296,28 +280,29 @@ term: (term (MOD | DIV | FLOOR_DIV | STAR_MUL | DECOR_OP))? power
296
280
  power: (power STAR_POW)? factor
297
281
  factor: (BW_NOT | MINUS | PLUS) factor | connect
298
282
 
299
- // [Heading]: Connect expressions.
283
+ // [Heading]: Connect expressions (OSP).
300
284
  connect: (connect (connect_op | disconnect_op))? atomic_pipe
301
285
 
302
- // [Heading]: Atomic expressions.
286
+ // [Heading]: Pipe atomic expressions.
303
287
  atomic_pipe: (atomic_pipe A_PIPE_FWD)? atomic_pipe_back
304
288
 
305
- // [Heading]: Atomic pipe back expressions.
289
+ // [Heading]: Pipe back atomic expressions.
306
290
  atomic_pipe_back: (atomic_pipe_back A_PIPE_BKWD)? os_spawn
307
291
 
308
- // [Heading]: Object spatial spawn expressions.
292
+ // [Heading]: Spawn expressions (OSP).
309
293
  os_spawn: (os_spawn KW_SPAWN)? unpack
310
294
 
311
295
  // [Heading]: Unpack expressions.
312
296
  unpack: STAR_MUL? ref
313
297
 
314
- // [Heading]: References (unused).
315
- ref: BW_AND? pipe_call
298
+ // [Heading]: References (OSP).
299
+ ref: BW_AND? await_expr
316
300
 
317
- // [Heading]: Object spatial calls.
318
- 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
319
304
 
320
- // [Heading]: Subscripted and dotted expressions.
305
+ // [Heading]: Attributes and Subscript expressions.
321
306
  atomic_chain: atomic_chain NULL_OK? (filter_compr | assign_compr | index_slice)
322
307
  | atomic_chain NULL_OK? (DOT_BKWD | DOT_FWD | DOT) named_ref
323
308
  | (atomic_call | atom | edge_ref_chain)
@@ -329,7 +314,7 @@ index_slice: LSQUARE
329
314
  | list_val
330
315
 
331
316
  // [Heading]: Function calls.
332
- atomic_call: atomic_chain LPAREN param_list? by_llm? RPAREN
317
+ atomic_call: atomic_chain (gen_compr | LPAREN param_list? by_llm? RPAREN)
333
318
 
334
319
  by_llm: KW_BY expression
335
320
 
@@ -337,7 +322,7 @@ param_list: expr_list COMMA kw_expr_list COMMA?
337
322
  | kw_expr_list COMMA?
338
323
  | expr_list COMMA?
339
324
 
340
- // [Heading]: Atom.
325
+ // [Heading]: Atomic expressions.
341
326
  atom: named_ref
342
327
  | LPAREN (expression | yield_expr) RPAREN
343
328
  | atom_collection
@@ -361,9 +346,13 @@ multistring: (fstring | STRING)+
361
346
 
362
347
  fstring: FSTR_START fstr_parts FSTR_END
363
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
364
351
 
365
352
  fstr_parts: (FSTR_PIECE | FSTR_BESC | LBRACE expression RBRACE )*
366
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 )*
367
356
 
368
357
  // [Heading]: Collection values.
369
358
  atom_collection: dict_compr
@@ -389,7 +378,6 @@ set_val: LBRACE expr_list COMMA? RBRACE
389
378
  kv_pair: expression COLON expression | STAR_POW expression
390
379
  expr_list: (expr_list COMMA)? expression
391
380
 
392
- // [Heading]: Tuples and Jac Tuples.
393
381
  tuple_list: expression COMMA expr_list COMMA kw_expr_list COMMA?
394
382
  | expression COMMA kw_expr_list COMMA?
395
383
  | expression COMMA expr_list COMMA?
@@ -399,7 +387,7 @@ tuple_list: expression COMMA expr_list COMMA kw_expr_list COMMA?
399
387
  kw_expr_list: (kw_expr_list COMMA)? kw_expr
400
388
  kw_expr: named_ref EQ expression | STAR_POW expression
401
389
 
402
- // [Heading]: Object-Spatial References.
390
+ // [Heading]: Edge references (OSP).
403
391
  edge_ref_chain: LSQUARE KW_ASYNC? (KW_NODE| KW_EDGE)? expression? (edge_op_ref (filter_compr | expression)?)+ RSQUARE
404
392
  edge_op_ref: edge_any | edge_from | edge_to
405
393
  edge_to: ARROW_R | ARROW_R_P1 typed_filter_compare_list ARROW_R_P2
@@ -411,7 +399,7 @@ connect_to: CARROW_R | CARROW_R_P1 expression (COLON kw_expr_list)? CARROW_R_P2
411
399
  connect_from: CARROW_L | CARROW_L_P1 expression (COLON kw_expr_list)? CARROW_L_P2
412
400
  connect_any: CARROW_BI | CARROW_L_P1 expression (COLON kw_expr_list)? CARROW_R_P2
413
401
 
414
- // [Heading]: Special Comprehensions.
402
+ // [Heading]: Filter and assign comprehensions.
415
403
  filter_compr: LPAREN NULL_OK filter_compare_list RPAREN
416
404
  | LPAREN TYPE_OP NULL_OK typed_filter_compare_list RPAREN
417
405
  assign_compr: LPAREN EQ kw_expr_list RPAREN
@@ -455,10 +443,16 @@ GLOBAL_OP: "global"
455
443
  NONLOCAL_OP: "nonlocal"
456
444
 
457
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: "'''"
458
450
  FSTR_START.1: "f\""
459
451
  FSTR_END: "\""
460
452
  FSTR_SQ_START.1: "f'"
461
453
  FSTR_SQ_END: "'"
454
+ FSTR_TRIPLE_PIECE.-1: /(?:(?!""")(?![{}])[\s\S])+/
455
+ FSTR_SQ_TRIPLE_PIECE.-1: /(?:(?!''')(?![{}])[\s\S])+/
462
456
  FSTR_PIECE.-1: /[^\{\}\"]+/
463
457
  FSTR_SQ_PIECE.-1: /[^\{\}\']+/
464
458
  FSTR_BESC.1: /{{|}}/
@@ -624,7 +618,6 @@ FLOOR_DIV_EQ: "//="
624
618
  BW_AND_EQ: "&="
625
619
  BW_OR_EQ: "|="
626
620
  BW_XOR_EQ: "^="
627
- BW_NOT_EQ: "~="
628
621
  LSHIFT_EQ: "<<="
629
622
  RSHIFT_EQ: ">>="
630
623