jaclang 0.8.8__py3-none-any.whl → 0.8.10__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 (114) hide show
  1. jaclang/cli/cli.py +194 -10
  2. jaclang/cli/cmdreg.py +144 -8
  3. jaclang/compiler/__init__.py +6 -1
  4. jaclang/compiler/codeinfo.py +16 -1
  5. jaclang/compiler/constant.py +33 -8
  6. jaclang/compiler/jac.lark +154 -62
  7. jaclang/compiler/larkparse/jac_parser.py +2 -2
  8. jaclang/compiler/parser.py +656 -149
  9. jaclang/compiler/passes/__init__.py +2 -1
  10. jaclang/compiler/passes/ast_gen/__init__.py +5 -0
  11. jaclang/compiler/passes/ast_gen/base_ast_gen_pass.py +54 -0
  12. jaclang/compiler/passes/ast_gen/jsx_processor.py +344 -0
  13. jaclang/compiler/passes/ecmascript/__init__.py +25 -0
  14. jaclang/compiler/passes/ecmascript/es_unparse.py +576 -0
  15. jaclang/compiler/passes/ecmascript/esast_gen_pass.py +2068 -0
  16. jaclang/compiler/passes/ecmascript/estree.py +972 -0
  17. jaclang/compiler/passes/ecmascript/tests/__init__.py +1 -0
  18. jaclang/compiler/passes/ecmascript/tests/fixtures/advanced_language_features.jac +170 -0
  19. jaclang/compiler/passes/ecmascript/tests/fixtures/class_separate_impl.impl.jac +30 -0
  20. jaclang/compiler/passes/ecmascript/tests/fixtures/class_separate_impl.jac +14 -0
  21. jaclang/compiler/passes/ecmascript/tests/fixtures/client_jsx.jac +89 -0
  22. jaclang/compiler/passes/ecmascript/tests/fixtures/core_language_features.jac +195 -0
  23. jaclang/compiler/passes/ecmascript/tests/test_esast_gen_pass.py +167 -0
  24. jaclang/compiler/passes/ecmascript/tests/test_js_generation.py +239 -0
  25. jaclang/compiler/passes/main/__init__.py +0 -3
  26. jaclang/compiler/passes/main/annex_pass.py +23 -1
  27. jaclang/compiler/passes/main/def_use_pass.py +1 -0
  28. jaclang/compiler/passes/main/pyast_gen_pass.py +413 -255
  29. jaclang/compiler/passes/main/pyast_load_pass.py +48 -11
  30. jaclang/compiler/passes/main/pyjac_ast_link_pass.py +2 -0
  31. jaclang/compiler/passes/main/sym_tab_build_pass.py +18 -1
  32. jaclang/compiler/passes/main/tests/fixtures/autoimpl.cl.jac +7 -0
  33. jaclang/compiler/passes/main/tests/fixtures/checker_arity.jac +3 -0
  34. jaclang/compiler/passes/main/tests/fixtures/checker_class_construct.jac +33 -0
  35. jaclang/compiler/passes/main/tests/fixtures/defuse_modpath.jac +7 -0
  36. jaclang/compiler/passes/main/tests/fixtures/member_access_type_resolve.jac +2 -1
  37. jaclang/compiler/passes/main/tests/test_checker_pass.py +31 -3
  38. jaclang/compiler/passes/main/tests/test_def_use_pass.py +12 -0
  39. jaclang/compiler/passes/main/tests/test_import_pass.py +23 -4
  40. jaclang/compiler/passes/main/tests/test_predynamo_pass.py +13 -14
  41. jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +25 -0
  42. jaclang/compiler/passes/main/type_checker_pass.py +7 -0
  43. jaclang/compiler/passes/tool/doc_ir_gen_pass.py +219 -20
  44. jaclang/compiler/passes/tool/fuse_comments_pass.py +1 -10
  45. jaclang/compiler/passes/tool/jac_formatter_pass.py +2 -2
  46. jaclang/compiler/passes/tool/tests/fixtures/import_fmt.jac +7 -1
  47. jaclang/compiler/passes/tool/tests/fixtures/tagbreak.jac +135 -29
  48. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +4 -1
  49. jaclang/compiler/passes/transform.py +9 -1
  50. jaclang/compiler/passes/uni_pass.py +5 -7
  51. jaclang/compiler/program.py +27 -26
  52. jaclang/compiler/tests/test_client_codegen.py +113 -0
  53. jaclang/compiler/tests/test_importer.py +12 -10
  54. jaclang/compiler/tests/test_parser.py +249 -3
  55. jaclang/compiler/type_system/type_evaluator.jac +1078 -0
  56. jaclang/compiler/type_system/type_utils.py +1 -1
  57. jaclang/compiler/type_system/types.py +6 -0
  58. jaclang/compiler/unitree.py +438 -82
  59. jaclang/langserve/engine.jac +224 -288
  60. jaclang/langserve/sem_manager.jac +12 -8
  61. jaclang/langserve/server.jac +48 -48
  62. jaclang/langserve/tests/fixtures/greet.py +17 -0
  63. jaclang/langserve/tests/fixtures/md_path.jac +22 -0
  64. jaclang/langserve/tests/fixtures/user.jac +15 -0
  65. jaclang/langserve/tests/test_server.py +66 -371
  66. jaclang/lib.py +17 -0
  67. jaclang/runtimelib/archetype.py +25 -25
  68. jaclang/runtimelib/client_bundle.py +169 -0
  69. jaclang/runtimelib/client_runtime.jac +586 -0
  70. jaclang/runtimelib/constructs.py +4 -2
  71. jaclang/runtimelib/machine.py +308 -139
  72. jaclang/runtimelib/meta_importer.py +111 -22
  73. jaclang/runtimelib/mtp.py +15 -0
  74. jaclang/runtimelib/server.py +1089 -0
  75. jaclang/runtimelib/tests/fixtures/client_app.jac +18 -0
  76. jaclang/runtimelib/tests/fixtures/custom_access_validation.jac +1 -1
  77. jaclang/runtimelib/tests/fixtures/savable_object.jac +4 -5
  78. jaclang/runtimelib/tests/fixtures/serve_api.jac +75 -0
  79. jaclang/runtimelib/tests/test_client_bundle.py +55 -0
  80. jaclang/runtimelib/tests/test_client_render.py +63 -0
  81. jaclang/runtimelib/tests/test_serve.py +1069 -0
  82. jaclang/settings.py +0 -3
  83. jaclang/tests/fixtures/attr_pattern_case.jac +18 -0
  84. jaclang/tests/fixtures/funccall_genexpr.jac +7 -0
  85. jaclang/tests/fixtures/funccall_genexpr.py +5 -0
  86. jaclang/tests/fixtures/iife_functions.jac +142 -0
  87. jaclang/tests/fixtures/iife_functions_client.jac +143 -0
  88. jaclang/tests/fixtures/multistatement_lambda.jac +116 -0
  89. jaclang/tests/fixtures/multistatement_lambda_client.jac +113 -0
  90. jaclang/tests/fixtures/needs_import_dup.jac +6 -4
  91. jaclang/tests/fixtures/py2jac_empty.py +0 -0
  92. jaclang/tests/fixtures/py_run.py +7 -5
  93. jaclang/tests/fixtures/pyfunc_fstr.py +2 -2
  94. jaclang/tests/fixtures/simple_lambda_test.jac +12 -0
  95. jaclang/tests/test_cli.py +134 -18
  96. jaclang/tests/test_language.py +120 -32
  97. jaclang/tests/test_reference.py +20 -3
  98. jaclang/utils/NonGPT.py +375 -0
  99. jaclang/utils/helpers.py +64 -20
  100. jaclang/utils/lang_tools.py +31 -4
  101. jaclang/utils/tests/test_lang_tools.py +5 -16
  102. jaclang/utils/treeprinter.py +8 -3
  103. {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/METADATA +3 -3
  104. {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/RECORD +106 -71
  105. jaclang/compiler/passes/main/binder_pass.py +0 -594
  106. jaclang/compiler/passes/main/tests/fixtures/sym_binder.jac +0 -47
  107. jaclang/compiler/passes/main/tests/test_binder_pass.py +0 -111
  108. jaclang/compiler/type_system/type_evaluator.py +0 -844
  109. jaclang/langserve/tests/session.jac +0 -294
  110. jaclang/langserve/tests/test_dev_server.py +0 -80
  111. jaclang/runtimelib/importer.py +0 -351
  112. jaclang/tests/test_typecheck.py +0 -542
  113. {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/WHEEL +0 -0
  114. {jaclang-0.8.8.dist-info → jaclang-0.8.10.dist-info}/entry_points.txt +0 -0
@@ -4,6 +4,7 @@ import inspect
4
4
  import io
5
5
  import os
6
6
  import sys
7
+ from pathlib import Path
7
8
 
8
9
  from jaclang import JacMachineInterface as Jac
9
10
  from jaclang.compiler import jac_lark as jl
@@ -215,12 +216,12 @@ class TestLarkParser(TestCaseMicroSuite):
215
216
  }
216
217
  """,
217
218
  """
218
- Missing SEMI
219
+ Unexpected token 'bar'
220
+ with entry {
219
221
  foo = Foo(;
220
222
  func(foo bar)
223
+ ^^^
221
224
  foo.bar;
222
- ^^^
223
- }
224
225
  """
225
226
  ]
226
227
  for idx, alrt in enumerate(prog.errors_had):
@@ -229,4 +230,249 @@ class TestLarkParser(TestCaseMicroSuite):
229
230
  line = line.strip()
230
231
  self.assertIn(line, pretty)
231
232
 
233
+ def _load_combined_jsx_fixture(self) -> tuple[str, JacParser]:
234
+ """Parse the consolidated JSX fixture once for downstream assertions."""
235
+ fixture_path = (
236
+ Path(__file__)
237
+ .resolve()
238
+ .parent
239
+ .parent
240
+ / "passes"
241
+ / "ecmascript"
242
+ / "tests"
243
+ / "fixtures"
244
+ / "client_jsx.jac"
245
+ )
246
+ source_text = fixture_path.read_text(encoding="utf-8")
247
+ prse = JacParser(
248
+ root_ir=Source(source_text, mod_path=str(fixture_path)),
249
+ prog=JacProgram(),
250
+ )
251
+ self.assertFalse(
252
+ prse.errors_had,
253
+ f"Parser reported errors for JSX fixture: {[str(e) for e in prse.errors_had]}",
254
+ )
255
+ return source_text, prse
256
+
257
+ def test_jsx_comprehensive_fixture(self) -> None:
258
+ """Ensure the consolidated JSX fixture exercises varied grammar shapes."""
259
+ source_text, prse = self._load_combined_jsx_fixture()
260
+ tree_repr = prse.ir_out.pp()
261
+
262
+ expected_snippets = {
263
+ "self_closing": "<div />",
264
+ "attribute_binding": 'id={name}',
265
+ "namespaced_component": "<Form.Input.Text />",
266
+ "fragment": "<>",
267
+ "spread_attribute": "{...props}",
268
+ "expression_child": '{"Hello " + name + "!"}',
269
+ }
270
+ for label, snippet in expected_snippets.items():
271
+ with self.subTest(label=label):
272
+ self.assertIn(snippet, source_text)
273
+
274
+ ast_markers = {
275
+ "JsxElement": "JsxElement" in tree_repr,
276
+ "FragmentTokens": "Token - <>" in tree_repr and "Token - </>" in tree_repr,
277
+ "JsxSpreadAttribute": "JsxSpreadAttribute" in tree_repr,
278
+ }
279
+ for label, present in ast_markers.items():
280
+ with self.subTest(node=label):
281
+ self.assertTrue(present, f"{label} missing from AST pretty print")
282
+
283
+ def test_client_keyword_tagging(self) -> None:
284
+ """Test that cl keyword properly tags elements as client declarations.
285
+
286
+ Tests:
287
+ - Single statement with cl prefix
288
+ - Statement without cl prefix
289
+ - Block of statements with cl { }
290
+ - Empty cl blocks
291
+ - Multiple cl blocks at top level
292
+ - Various statement types (import, let, obj, test)
293
+ """
294
+ # Test 1: Mixed single and block client markers
295
+ source = """
296
+ cl let foo = 1;
297
+ let bar = 2;
298
+ cl {
299
+ let baz = 3;
300
+ test sample {}
301
+ }
302
+ """
303
+ module = JacProgram().parse_str(source, "test.jac")
304
+ body = module.body
305
+
306
+ self.assertEqual(
307
+ [type(stmt).__name__ for stmt in body],
308
+ ["GlobalVars", "GlobalVars", "GlobalVars", "Test"],
309
+ )
310
+ self.assertEqual(
311
+ [getattr(stmt, "is_client_decl", False) for stmt in body],
312
+ [True, False, True, True], # cl let, let, cl{let}, cl{test}
313
+ )
314
+
315
+ # Test 2: Block with different statement types
316
+ source = """
317
+ cl {
318
+ import foo;
319
+ let x = 1;
320
+ obj MyClass {}
321
+ test my_test {}
322
+ }
323
+ """
324
+ module = JacProgram().parse_str(source, "test.jac")
325
+ body = module.body
326
+
327
+ self.assertEqual(len(body), 4)
328
+ self.assertTrue(
329
+ all(
330
+ getattr(stmt, "is_client_decl", False)
331
+ for stmt in body
332
+ if hasattr(stmt, "is_client_decl")
333
+ )
334
+ )
335
+
336
+ # Test 3: Multiple cl blocks at top level
337
+ source = """
338
+ cl {
339
+ let a = 1;
340
+ }
341
+ let b = 2;
342
+ cl {
343
+ let c = 3;
344
+ }
345
+ """
346
+ module = JacProgram().parse_str(source, "test.jac")
347
+ body = module.body
348
+
349
+ self.assertEqual(len(body), 3)
350
+ self.assertEqual(
351
+ [getattr(stmt, "is_client_decl", False) for stmt in body],
352
+ [True, False, True], # cl{let a}, let b, cl{let c}
353
+ )
354
+
355
+ # Test 4: Empty client block
356
+ source = """
357
+ cl {}
358
+ let x = 1;
359
+ """
360
+ module = JacProgram().parse_str(source, "test.jac")
361
+ body = module.body
362
+
363
+ self.assertEqual(len(body), 1)
364
+ self.assertFalse(getattr(body[0], "is_client_decl", False))
365
+
366
+ # Test 5: Various statement types with single cl marker
367
+ source = """
368
+ cl import foo;
369
+ cl obj MyClass {}
370
+ cl test my_test {}
371
+ """
372
+ module = JacProgram().parse_str(source, "test.jac")
373
+ body = module.body
374
+
375
+ self.assertEqual(len(body), 3)
376
+ self.assertTrue(
377
+ all(
378
+ getattr(stmt, "is_client_decl", False)
379
+ for stmt in body
380
+ if hasattr(stmt, "is_client_decl")
381
+ )
382
+ )
383
+
384
+ def test_anonymous_ability_decl(self) -> None:
385
+ """Test that abilities can be declared without explicit names.
386
+
387
+ Tests:
388
+ - Anonymous ability with entry event
389
+ - Anonymous ability with exit event
390
+ - Named ability still works
391
+ - Autogenerated names are unique based on location
392
+ """
393
+ # Test 1: Anonymous ability with entry event
394
+ source = """
395
+ walker MyWalker {
396
+ can with entry {
397
+ print("hello");
398
+ }
399
+ }
400
+ """
401
+ prog = JacProgram()
402
+ module = prog.parse_str(source, "test.jac")
403
+ self.assertFalse(prog.errors_had)
404
+
405
+ # Find the walker and its ability
406
+ walker = module.body[0]
407
+ abilities = [stmt for stmt in walker.body if type(stmt).__name__ == "Ability"]
408
+ self.assertEqual(len(abilities), 1)
409
+
410
+ ability = abilities[0]
411
+ self.assertIsNone(ability.name_ref)
412
+ # Check that py_resolve_name generates a name
413
+ resolved_name = ability.py_resolve_name()
414
+ self.assertTrue(resolved_name.startswith("__ability_entry_"))
415
+ self.assertTrue(resolved_name.endswith("__"))
416
+
417
+ # Test 2: Anonymous ability with exit event
418
+ source = """
419
+ walker MyWalker {
420
+ can with exit {
421
+ print("goodbye");
422
+ }
423
+ }
424
+ """
425
+ prog = JacProgram()
426
+ module = prog.parse_str(source, "test.jac")
427
+ self.assertFalse(prog.errors_had)
428
+
429
+ walker = module.body[0]
430
+ abilities = [stmt for stmt in walker.body if type(stmt).__name__ == "Ability"]
431
+ ability = abilities[0]
432
+ resolved_name = ability.py_resolve_name()
433
+ self.assertTrue(resolved_name.startswith("__ability_exit_"))
434
+
435
+ # Test 3: Named ability still works
436
+ source = """
437
+ walker MyWalker {
438
+ can my_ability with entry {
439
+ print("named");
440
+ }
441
+ }
442
+ """
443
+ prog = JacProgram()
444
+ module = prog.parse_str(source, "test.jac")
445
+ self.assertFalse(prog.errors_had)
446
+
447
+ walker = module.body[0]
448
+ abilities = [stmt for stmt in walker.body if type(stmt).__name__ == "Ability"]
449
+ ability = abilities[0]
450
+ self.assertIsNotNone(ability.name_ref)
451
+ self.assertEqual(ability.py_resolve_name(), "my_ability")
452
+
453
+ # Test 4: Multiple anonymous abilities generate unique names
454
+ source = """
455
+ walker MyWalker {
456
+ can with entry {
457
+ print("first");
458
+ }
459
+ can with entry {
460
+ print("second");
461
+ }
462
+ }
463
+ """
464
+ prog = JacProgram()
465
+ module = prog.parse_str(source, "test.jac")
466
+ self.assertFalse(prog.errors_had)
467
+
468
+ walker = module.body[0]
469
+ abilities = [stmt for stmt in walker.body if type(stmt).__name__ == "Ability"]
470
+ self.assertEqual(len(abilities), 2)
471
+
472
+ name1 = abilities[0].py_resolve_name()
473
+ name2 = abilities[1].py_resolve_name()
474
+ # Names should be different due to different locations
475
+ self.assertNotEqual(name1, name2)
476
+
477
+
232
478
  TestLarkParser.self_attach_micro_tests()