jaclang 0.8.7__py3-none-any.whl → 0.8.8__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 (89) hide show
  1. jaclang/cli/cli.py +13 -27
  2. jaclang/cli/cmdreg.py +44 -0
  3. jaclang/compiler/constant.py +0 -1
  4. jaclang/compiler/jac.lark +3 -6
  5. jaclang/compiler/larkparse/jac_parser.py +2 -2
  6. jaclang/compiler/parser.py +213 -34
  7. jaclang/compiler/passes/main/__init__.py +2 -4
  8. jaclang/compiler/passes/main/def_use_pass.py +0 -4
  9. jaclang/compiler/passes/main/predynamo_pass.py +221 -0
  10. jaclang/compiler/passes/main/pyast_gen_pass.py +70 -52
  11. jaclang/compiler/passes/main/pyast_load_pass.py +52 -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 +191 -0
  27. jaclang/compiler/passes/main/tests/test_predynamo_pass.py +57 -0
  28. jaclang/compiler/passes/main/type_checker_pass.py +29 -73
  29. jaclang/compiler/passes/tool/doc_ir_gen_pass.py +204 -44
  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/tagbreak.jac +171 -11
  34. jaclang/compiler/passes/transform.py +12 -8
  35. jaclang/compiler/program.py +14 -6
  36. jaclang/compiler/tests/fixtures/jac_import_py_files.py +4 -0
  37. jaclang/compiler/tests/fixtures/jac_module.jac +3 -0
  38. jaclang/compiler/tests/fixtures/multiple_syntax_errors.jac +10 -0
  39. jaclang/compiler/tests/fixtures/python_module.py +1 -0
  40. jaclang/compiler/tests/test_importer.py +39 -0
  41. jaclang/compiler/tests/test_parser.py +49 -0
  42. jaclang/compiler/type_system/type_evaluator.py +351 -67
  43. jaclang/compiler/type_system/type_utils.py +246 -0
  44. jaclang/compiler/type_system/types.py +58 -2
  45. jaclang/compiler/unitree.py +79 -94
  46. jaclang/langserve/engine.jac +138 -159
  47. jaclang/langserve/server.jac +25 -1
  48. jaclang/langserve/tests/fixtures/circle.jac +3 -3
  49. jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
  50. jaclang/langserve/tests/fixtures/circle_pure.test.jac +3 -3
  51. jaclang/langserve/tests/fixtures/completion_test_err.jac +10 -0
  52. jaclang/langserve/tests/server_test/circle_template.jac +80 -0
  53. jaclang/langserve/tests/server_test/glob_template.jac +4 -0
  54. jaclang/langserve/tests/server_test/test_lang_serve.py +154 -309
  55. jaclang/langserve/tests/server_test/utils.py +153 -116
  56. jaclang/langserve/tests/test_server.py +21 -84
  57. jaclang/langserve/utils.jac +12 -15
  58. jaclang/runtimelib/machine.py +7 -0
  59. jaclang/runtimelib/meta_importer.py +27 -1
  60. jaclang/runtimelib/tests/fixtures/custom_access_validation.jac +1 -1
  61. jaclang/runtimelib/tests/fixtures/savable_object.jac +2 -2
  62. jaclang/settings.py +18 -14
  63. jaclang/tests/fixtures/abc_check.jac +3 -3
  64. jaclang/tests/fixtures/arch_rel_import_creation.jac +12 -12
  65. jaclang/tests/fixtures/chandra_bugs2.jac +3 -3
  66. jaclang/tests/fixtures/create_dynamic_archetype.jac +13 -13
  67. jaclang/tests/fixtures/maxfail_run_test.jac +4 -4
  68. jaclang/tests/fixtures/params/param_syntax_err.jac +9 -0
  69. jaclang/tests/fixtures/params/test_complex_params.jac +42 -0
  70. jaclang/tests/fixtures/params/test_failing_kwonly.jac +207 -0
  71. jaclang/tests/fixtures/params/test_failing_posonly.jac +116 -0
  72. jaclang/tests/fixtures/params/test_failing_varargs.jac +300 -0
  73. jaclang/tests/fixtures/params/test_kwonly_params.jac +29 -0
  74. jaclang/tests/fixtures/py2jac_params.py +8 -0
  75. jaclang/tests/fixtures/run_test.jac +4 -4
  76. jaclang/tests/test_cli.py +37 -1
  77. jaclang/tests/test_language.py +74 -16
  78. jaclang/utils/helpers.py +47 -2
  79. jaclang/utils/module_resolver.py +10 -0
  80. jaclang/utils/test.py +8 -0
  81. jaclang/utils/treeprinter.py +0 -18
  82. {jaclang-0.8.7.dist-info → jaclang-0.8.8.dist-info}/METADATA +1 -2
  83. {jaclang-0.8.7.dist-info → jaclang-0.8.8.dist-info}/RECORD +85 -60
  84. {jaclang-0.8.7.dist-info → jaclang-0.8.8.dist-info}/WHEEL +1 -1
  85. jaclang/compiler/passes/main/inheritance_pass.py +0 -131
  86. jaclang/langserve/dev_engine.jac +0 -645
  87. jaclang/langserve/dev_server.jac +0 -201
  88. jaclang/langserve/tests/server_test/code_test.py +0 -0
  89. {jaclang-0.8.7.dist-info → jaclang-0.8.8.dist-info}/entry_points.txt +0 -0
@@ -2,21 +2,19 @@
2
2
 
3
3
  import os
4
4
  import tempfile
5
-
5
+ from typing import Optional
6
+ from dataclasses import dataclass
7
+
8
+ from lsprotocol.types import (
9
+ DidOpenTextDocumentParams,
10
+ TextDocumentItem,
11
+ DidSaveTextDocumentParams,
12
+ DidChangeTextDocumentParams,
13
+ VersionedTextDocumentIdentifier,
14
+ )
6
15
  from jaclang.vendor.pygls.uris import from_fs_path
7
16
  from jaclang.vendor.pygls.workspace import Workspace
8
17
 
9
- from textwrap import dedent
10
-
11
-
12
- def get_jac_file_path():
13
- """Return the absolute path to the sample Jac file used for testing."""
14
- return os.path.abspath(
15
- os.path.join(
16
- os.path.dirname(__file__), "../../../../examples/manual_code/circle.jac"
17
- )
18
- )
19
-
20
18
 
21
19
  def create_temp_jac_file(initial_content: str = "") -> str:
22
20
  """Create a temporary Jac file with optional initial content and return its path."""
@@ -28,110 +26,11 @@ def create_temp_jac_file(initial_content: str = "") -> str:
28
26
  return temp.name
29
27
 
30
28
 
31
- def get_code(code: str) -> str:
32
- """Generate a sample Jac code snippet with optional test code injected."""
33
- jac_code = dedent(
34
- f'''
35
- """
36
- This module demonstrates a simple circle class and a function to calculate
37
- the area of a circle in all of Jac's glory.
38
- """
39
-
40
- import math;
41
-
42
- # Module-level global variable
43
- glob RAD = 5;
44
-
45
- """Function to calculate the area of a circle."""
46
- def calculate_area(radius: float) -> float {{
47
- return math.pi * radius * radius;
48
- }}
49
-
50
- #* (This is a multiline comment in Jac)
51
- Above we have the demonstration of a function to calculate the area of a circle.
52
- Below we have the demonstration of a class to calculate the area of a circle.
53
- *#
54
-
55
- """Enum for shape types"""
56
- enum ShapeType {{
57
- CIRCLE = "Circle",
58
- UNKNOWN = "Unknown"
59
- }}
60
-
61
- """Base class for a shape."""
62
- obj Shape {{
63
- has shape_type: ShapeType;
64
-
65
- """Abstract method to calculate the area of a shape."""
66
- def area -> float abs;
67
- }}
68
-
69
- """Circle class inherits from Shape."""
70
- obj Circle(Shape) {{
71
- def init(radius: float) {{
72
- super.init(ShapeType.CIRCLE);
73
- self.radius = radius;
74
- }}
75
-
76
- """Overridden method to calculate the area of the circle."""
77
- override def area -> float {{
78
- return math.pi * self.radius * self.radius;
79
- }}
80
- }}
81
-
82
- with entry {{
83
- c = Circle(RAD);
84
- }}
85
-
86
- # Global also works here
87
-
88
- with entry:__main__ {{
89
- # To run the program functionality
90
- print(
91
- f"Area of a circle with radius {{RAD}} using function: {{calculate_area(RAD)}}"
92
- );
93
- print(
94
- f"Area of a {{c.shape_type.value}} with radius {{RAD}} using class: {{c.area()}}"
95
- );
96
- }}
97
-
98
- # Unit Tests!
99
- glob expected_area = 78.53981633974483;
100
- {code}
101
-
102
- test calc_area {{
103
- check almostEqual(calculate_area(RAD), expected_area);
104
- }}
105
-
106
- test circle_area {{
107
- c = Circle(RAD);
108
- check almostEqual(c.area(), expected_area);
109
- }}
110
-
111
- test circle_type {{
112
- c = Circle(RAD);
113
- check c.shape_type == ShapeType.CIRCLE;
114
- }}
115
- '''
116
- )
117
- return jac_code
118
-
119
-
120
- def get_simple_code(code: str) -> str:
121
- """Generate a sample Jac code snippet with optional test code injected."""
122
- jac_code = dedent(
123
- f"""
124
-
125
- # Unit Tests!
126
- glob expected_area0 = 78.53981633974483;
127
- glob expected_area1 = 78.53981633974483;
128
- {code}
129
- glob expected_area2 = 78.53981633974483;
130
-
131
-
132
- """
133
- )
134
- return jac_code
29
+ def load_jac_template(template_file: str, code: str = "") -> str:
30
+ """Load a Jac template file and inject code into placeholder."""
31
+ with open(template_file, "r") as f:
32
+ jac_template = f.read()
33
+ return jac_template.replace("#{{INJECT_CODE}}", code)
135
34
 
136
35
 
137
36
  def create_ls_with_workspace(file_path: str):
@@ -142,3 +41,141 @@ def create_ls_with_workspace(file_path: str):
142
41
  uri = from_fs_path(file_path)
143
42
  ls.lsp._workspace = Workspace(os.path.dirname(file_path), ls)
144
43
  return uri, ls
44
+
45
+
46
+ @dataclass
47
+ class TestFile:
48
+ """Encapsulates test file information and operations."""
49
+
50
+ path: str
51
+ uri: str
52
+ code: str
53
+ version: int = 1
54
+
55
+ @classmethod
56
+ def from_template(cls, template_name: str, content: str = "") -> "TestFile":
57
+ """Create a test file from a template."""
58
+ code = load_jac_template(cls._get_template_path(template_name), content)
59
+ temp_path = create_temp_jac_file(code)
60
+ uri = from_fs_path(temp_path)
61
+ return cls(
62
+ path=temp_path,
63
+ uri=uri or "",
64
+ code=code,
65
+ )
66
+
67
+ @staticmethod
68
+ def _get_template_path(file_name: str) -> str:
69
+ """Get absolute path to test template file."""
70
+ return os.path.abspath(
71
+ os.path.join(os.path.dirname(__file__), file_name)
72
+ )
73
+
74
+ def cleanup(self):
75
+ """Remove temporary test file."""
76
+ if os.path.exists(self.path):
77
+ os.remove(self.path)
78
+
79
+ def increment_version(self) -> int:
80
+ """Increment and return the version number."""
81
+ self.version += 1
82
+ return self.version
83
+
84
+
85
+ class LanguageServerTestHelper:
86
+ """Helper class for language server testing operations."""
87
+
88
+ def __init__(self, ls, test_file: TestFile):
89
+ self.ls = ls
90
+ self.test_file = test_file
91
+
92
+ async def open_document(self) -> None:
93
+ """Open a document in the language server."""
94
+ from jaclang.langserve.server import did_open
95
+
96
+ params = DidOpenTextDocumentParams(
97
+ text_document=TextDocumentItem(
98
+ uri=self.test_file.uri,
99
+ language_id="jac",
100
+ version=self.test_file.version,
101
+ text=self.test_file.code,
102
+ )
103
+ )
104
+ await did_open(self.ls, params)
105
+
106
+ async def save_document(self, code: Optional[str] = None) -> None:
107
+ """Save a document in the language server."""
108
+ from jaclang.langserve.server import did_save
109
+
110
+ content = code if code is not None else self.test_file.code
111
+ version = self.test_file.increment_version()
112
+
113
+ if code:
114
+ self._update_workspace(code, version)
115
+
116
+ from lsprotocol.types import TextDocumentIdentifier
117
+
118
+ params = DidSaveTextDocumentParams(
119
+ text_document=TextDocumentIdentifier(uri=self.test_file.uri),
120
+ text=content
121
+ )
122
+ await did_save(self.ls, params)
123
+
124
+ async def change_document(self, code: str) -> None:
125
+ """Change document content in the language server."""
126
+ from jaclang.langserve.server import did_change
127
+
128
+ version = self.test_file.increment_version()
129
+ self._update_workspace(code, version)
130
+
131
+ params = DidChangeTextDocumentParams(
132
+ text_document=VersionedTextDocumentIdentifier(
133
+ uri=self.test_file.uri,
134
+ version=version
135
+ ),
136
+ content_changes=[{"text": code}], # type: ignore
137
+ )
138
+ await did_change(self.ls, params)
139
+
140
+ def _update_workspace(self, code: str, version: int) -> None:
141
+ """Update workspace with new document content."""
142
+ self.ls.workspace.put_text_document(
143
+ TextDocumentItem(
144
+ uri=self.test_file.uri,
145
+ language_id="jac",
146
+ version=version,
147
+ text=code,
148
+ )
149
+ )
150
+
151
+ def get_diagnostics(self) -> list:
152
+ """Get diagnostics for the current document."""
153
+ return self.ls.diagnostics.get(self.test_file.uri, [])
154
+
155
+ def get_semantic_tokens(self):
156
+ """Get semantic tokens for the current document."""
157
+ return self.ls.get_semantic_tokens(self.test_file.uri)
158
+
159
+ def assert_no_diagnostics(self) -> None:
160
+ """Assert that there are no diagnostics."""
161
+ diagnostics = self.get_diagnostics()
162
+ assert isinstance(diagnostics, list)
163
+ assert len(diagnostics) == 0, f"Expected no diagnostics, found {len(diagnostics)}"
164
+
165
+ def assert_has_diagnostics(self, count: int = 1, message_contains: Optional[str] = None) -> None:
166
+ """Assert that diagnostics exist with optional message validation."""
167
+ diagnostics = self.get_diagnostics()
168
+ assert isinstance(diagnostics, list)
169
+ assert len(diagnostics) == count, f"Expected {count} diagnostic(s), found {len(diagnostics)}"
170
+
171
+ if message_contains:
172
+ assert message_contains in diagnostics[0].message, \
173
+ f"Expected '{message_contains}' in diagnostic message"
174
+
175
+ def assert_semantic_tokens_count(self, expected_count: int) -> None:
176
+ """Assert semantic tokens data has expected count."""
177
+ tokens = self.get_semantic_tokens()
178
+ assert hasattr(tokens, "data")
179
+ assert isinstance(tokens.data, list)
180
+ assert len(tokens.data) == expected_count, \
181
+ f"Expected {expected_count} tokens, found {len(tokens.data)}"
@@ -1,3 +1,4 @@
1
+ from dataclasses import dataclass
1
2
  from jaclang.utils.test import TestCase
2
3
  from jaclang.vendor.pygls import uris
3
4
  from jaclang.vendor.pygls.workspace import Workspace
@@ -310,7 +311,6 @@ class TestJacLangServer(TestCase):
310
311
  for token_type, expected_count in expected_counts:
311
312
  self.assertEqual(str(sem_list).count(token_type), expected_count)
312
313
 
313
- @pytest.mark.xfail(reason="TODO: Fix when we have the type checker")
314
314
  def test_completion(self) -> None:
315
315
  """Test that the completions are correct."""
316
316
  lsp = JacLangServer()
@@ -318,95 +318,28 @@ class TestJacLangServer(TestCase):
318
318
  workspace = Workspace(workspace_path, lsp)
319
319
  lsp.lsp._workspace = workspace
320
320
  base_module_file = uris.from_fs_path(
321
- self.fixture_abs_path("base_module_structure.jac")
321
+ self.fixture_abs_path("completion_test_err.jac")
322
322
  )
323
323
  lsp.deep_check(base_module_file)
324
- test_cases = [
325
- (lspt.Position(38, 16), ["get_color1", "color1", "point1"], 3),
326
- (lspt.Position(42, 22), ["RED", "GREEN", "BLUE"], 3),
327
- (lspt.Position(42, 33), ["RED", "GREEN", "BLUE"], 3),
328
- (lspt.Position(42, 45), ["RED", "GREEN", "BLUE"], 3),
329
- (lspt.Position(46, 20), ["RED22", "GREEN22", "BLUE22"], 3),
330
- (lspt.Position(46, 30), ["RED22", "GREEN22", "BLUE22"], 3),
331
- (lspt.Position(46, 41), ["RED22", "GREEN22", "BLUE22"], 3),
332
- (
333
- lspt.Position(51, 32),
334
- ["RED22", "GREEN22", "BLUE22"],
335
- 3,
336
- ),
337
- (
338
- lspt.Position(65, 13),
339
- [
340
- "get_color1",
341
- "color1",
342
- "point1",
343
- "base_colorred",
344
- "pointred",
345
- "inner_red",
346
- "doubleinner",
347
- "apply_red",
348
- ],
349
- 11,
350
- ),
351
- (
352
- lspt.Position(65, 23),
353
- ["color22", "doublepoint22", "point22", "apply_inner_red", "enum_red"],
354
- 5,
355
- ),
356
- (
357
- lspt.Position(65, 31),
358
- ["RED22", "GREEN22", "BLUE22"],
359
- 3,
360
- ),
361
- (
362
- lspt.Position(35, 28),
363
- [],
364
- 0,
365
- ),
366
- (
367
- lspt.Position(72, 12),
368
- [
369
- "get_color1",
370
- "color1",
371
- "point1",
372
- "base_colorred",
373
- "pointred",
374
- "inner_red",
375
- "doubleinner",
376
- "apply_red",
377
- ],
378
- 11,
379
- ),
380
- (
381
- lspt.Position(73, 22),
382
- ["color22", "doublepoint22", "apply_inner_red", "point22", "enum_red"],
383
- 5,
384
- ),
385
- (
386
- lspt.Position(37, 12),
387
- ["self", "add", "subtract", "x", "Colorenum", "Colour1", "red", "r"],
388
- 153,
389
- None,
324
+
325
+ @dataclass
326
+ class Case:
327
+ pos: lspt.Position
328
+ expected: list[str]
329
+ trigger: str = "."
330
+
331
+ test_cases: list[Case] = [
332
+ Case(
333
+ lspt.Position(8, 8),
334
+ ["bar", "baz"],
390
335
  ),
391
336
  ]
392
- default_trigger = "."
393
337
  for case in test_cases:
394
- position, expected_completions, expected_length = case[:3]
395
- completion_trigger = case[3] if len(case) > 3 else default_trigger
396
338
  completions = lsp.get_completion(
397
- base_module_file, position, completion_trigger=completion_trigger
339
+ base_module_file, case.pos, completion_trigger=case.trigger
398
340
  ).items
399
- for completion in expected_completions:
341
+ for completion in case.expected:
400
342
  self.assertIn(completion, str(completions))
401
- self.assertEqual(expected_length, len(completions))
402
-
403
- if position == lspt.Position(73, 12):
404
- self.assertEqual(
405
- 2, str(completions).count("kind=<CompletionItemKind.Function: 3>")
406
- )
407
- self.assertEqual(
408
- 4, str(completions).count("kind=<CompletionItemKind.Field: 5>")
409
- )
410
343
 
411
344
  def test_go_to_reference(self) -> None:
412
345
  """Test that the go to reference is correct."""
@@ -419,8 +352,8 @@ class TestJacLangServer(TestCase):
419
352
  lsp.deep_check(circle_file)
420
353
  test_cases = [
421
354
  (47, 12, ["circle.jac:47:8-47:14", "69:8-69:14", "74:8-74:14"]),
422
- (54, 66, ["54:62-54:76", "65:22-65:36"]),
423
- (62, 14, ["65:43-65:56", "70:32-70:45"]),
355
+ (54, 66, ["54:62-54:76", "65:23-65:37"]),
356
+ (62, 14, ["65:44-65:57", "70:33-70:46"]),
424
357
  ]
425
358
  for line, char, expected_refs in test_cases:
426
359
  references = str(lsp.get_references(circle_file, lspt.Position(line, char)))
@@ -608,3 +541,7 @@ class TestJacLangServer(TestCase):
608
541
  "/tests/fixtures/M1.jac:0:0-0:0",
609
542
  str(lsp.get_definition(guess_game_file, lspt.Position(29, 9))),
610
543
  )
544
+
545
+
546
+
547
+ TestJacLangServer().test_completion()
@@ -1,5 +1,6 @@
1
1
  """Utility functions for the language server."""
2
2
 
3
+
3
4
  import asyncio;
4
5
  import builtins;
5
6
  import re;
@@ -112,25 +113,21 @@ def find_deepest_symbol_node_at_pos(
112
113
 
113
114
 
114
115
  """Check if the position falls within the node's location."""
115
- def position_within_node(<>node: uni.UniNode, line: int, character: int) -> bool {
116
- if <>node.loc.first_line < (line + 1) < <>node.loc.last_line {
116
+ # All lines and columns are 1-Based
117
+ def position_within_node(n: uni.UniNode, line: int, character: int) -> bool {
118
+ if n.loc.first_line < line < n.loc.last_line {
117
119
  return True;
118
120
  }
119
- if <>node.loc.first_line == (line + 1)
120
- and <>node.loc.col_start <= (character + 1)
121
- and <>node.loc.last_line == (line + 1)
122
- and <>node.loc.col_end >= (character + 1)
123
-
124
- or <>node.loc.last_line > (line + 1)
125
- {
126
- return True;
121
+ if line < n.loc.first_line or line > n.loc.last_line {
122
+ return False;
127
123
  }
128
- if <>node.loc.last_line == (line + 1)
129
- and <>node.loc.col_start <= (character + 1) <= <>node.loc.col_end
130
- {
131
- return True;
124
+ if line == n.loc.first_line and character < n.loc.col_start {
125
+ return False;
126
+ }
127
+ if line == n.loc.last_line and character >= n.loc.col_end {
128
+ return False;
132
129
  }
133
- return False;
130
+ return True;
134
131
  }
135
132
 
136
133
 
@@ -1132,6 +1132,13 @@ class JacBasics:
1132
1132
  return JacMachineInterface.get_edges(origin, path.destinations[-1])
1133
1133
  return origin
1134
1134
 
1135
+ @staticmethod
1136
+ async def arefs(
1137
+ path: DataSpatialPath | NodeArchetype | list[NodeArchetype],
1138
+ ) -> None:
1139
+ """Jac's apply_dir stmt feature."""
1140
+ pass
1141
+
1135
1142
  @staticmethod
1136
1143
  def filter(
1137
1144
  items: list[Archetype],
@@ -9,7 +9,8 @@ from typing import Optional, Sequence
9
9
 
10
10
  from jaclang.runtimelib.machine import JacMachine as Jac
11
11
  from jaclang.runtimelib.machine import JacMachineInterface
12
- from jaclang.utils.module_resolver import get_jac_search_paths
12
+ from jaclang.settings import settings
13
+ from jaclang.utils.module_resolver import get_jac_search_paths, get_py_search_paths
13
14
 
14
15
 
15
16
  class JacMetaImporter(importlib.abc.MetaPathFinder, importlib.abc.Loader):
@@ -48,6 +49,30 @@ class JacMetaImporter(importlib.abc.MetaPathFinder, importlib.abc.Loader):
48
49
  return importlib.util.spec_from_file_location(
49
50
  fullname, candidate_path + ".jac", loader=self
50
51
  )
52
+
53
+ # TODO: We can remove it once python modules are fully supported in jac
54
+ if path is None and settings.pyfile_raise:
55
+ if settings.pyfile_raise_full:
56
+ paths_to_search = get_jac_search_paths()
57
+ else:
58
+ paths_to_search = get_py_search_paths()
59
+ for search_path in paths_to_search:
60
+ candidate_path = os.path.join(search_path, *module_path_parts)
61
+ # Check for directory package
62
+ if os.path.isdir(candidate_path):
63
+ init_file = os.path.join(candidate_path, "__init__.py")
64
+ if os.path.isfile(init_file):
65
+ return importlib.util.spec_from_file_location(
66
+ fullname,
67
+ init_file,
68
+ loader=self,
69
+ submodule_search_locations=[candidate_path],
70
+ )
71
+ # Check for .py file
72
+ if os.path.isfile(candidate_path + ".py"):
73
+ return importlib.util.spec_from_file_location(
74
+ fullname, candidate_path + ".py", loader=self
75
+ )
51
76
  return None
52
77
 
53
78
  def create_module(
@@ -78,6 +103,7 @@ class JacMetaImporter(importlib.abc.MetaPathFinder, importlib.abc.Loader):
78
103
  target=target,
79
104
  base_path=base_path,
80
105
  override_name=module.__name__,
106
+ lng="py" if file_path.endswith(".py") else "jac",
81
107
  )
82
108
  if ret:
83
109
  loaded_module = ret[0]
@@ -27,7 +27,7 @@ node A {
27
27
  walker create_other_root {
28
28
  can enter with `root entry {
29
29
  other_root = `root().__jac__;
30
- _.save(other_root);
30
+ _jl.save(other_root);
31
31
  print(other_root.id);
32
32
  }
33
33
  }
@@ -44,7 +44,7 @@ walker create_custom_object {
44
44
 
45
45
  can exit1 with `root exit {
46
46
  # get directly from shelf
47
- o = _.get_context().mem.__shelf__.get(str(self.obj.__jac__.id)).archetype;
47
+ o = _jl.get_context().mem.__shelf__.get(str(self.obj.__jac__.id)).archetype;
48
48
  print(jid(o));
49
49
  print(o);
50
50
  }
@@ -87,6 +87,6 @@ walker delete_custom_object {
87
87
  has object_id: str;
88
88
 
89
89
  can enter1 with `root entry {
90
- _.destroy([&(self.object_id)]);
90
+ _jl.destroy([&(self.object_id)]);
91
91
  }
92
92
  }
jaclang/settings.py CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  import configparser
4
4
  import os
5
+ from argparse import Namespace
5
6
  from dataclasses import dataclass, fields
6
7
 
7
8
 
@@ -19,11 +20,16 @@ class Settings:
19
20
  # Compiler configuration
20
21
  disable_mtllm: bool = False
21
22
  ignore_test_annex: bool = False
22
- pyout_jaclib_alias: str = "_"
23
+ pyout_jaclib_alias: str = "_jl"
24
+ pyfile_raise: bool = False
25
+ pyfile_raise_full: bool = False
23
26
 
24
27
  # Formatter configuration
25
28
  max_line_length: int = 88
26
29
 
30
+ # pytorch configuration
31
+ predynamo_pass: bool = False
32
+
27
33
  # LSP configuration
28
34
  lsp_debug: bool = False
29
35
 
@@ -42,6 +48,8 @@ class Settings:
42
48
  """Load settings from all available sources."""
43
49
  self.load_config_file()
44
50
  self.load_env_vars()
51
+ # CLI arguments are applied by the CLI after parsing, via
52
+ # `settings.load_command_line_arguments(args)` in start_cli.
45
53
 
46
54
  def load_config_file(self) -> None:
47
55
  """Load settings from a configuration file."""
@@ -64,19 +72,15 @@ class Settings:
64
72
  if env_value is not None:
65
73
  setattr(self, key, self.convert_type(env_value))
66
74
 
67
- # def load_command_line_arguments(self):
68
- # """Override settings from command-line arguments if provided."""
69
- # parser = argparse.ArgumentParser()
70
- # parser.add_argument(
71
- # "--debug",
72
- # type=self.str_to_bool,
73
- # nargs="?",
74
- # const=True,
75
- # default=self.config["debug"],
76
- # )
77
- # parser.add_argument("--port", type=int, default=self.config["port"])
78
- # parser.add_argument("--host", default=self.config["host"])
79
- # args = parser.parse_args()
75
+ def load_command_line_arguments(self, args: Namespace) -> None:
76
+ """Override settings from command-line arguments if provided."""
77
+ args_dict = vars(args) if not isinstance(args, dict) else args
78
+ for key in [f.name for f in fields(self)]:
79
+ if key in args_dict and args_dict[key] is not None:
80
+ val = args_dict[key]
81
+ if isinstance(val, str):
82
+ val = self.convert_type(val)
83
+ setattr(self, key, val)
80
84
 
81
85
  def str_to_bool(self, value: str) -> bool:
82
86
  """Convert string to boolean."""
@@ -63,15 +63,15 @@ with entry:__main__ {
63
63
  glob expected_area = 78.53981633974483;
64
64
 
65
65
  test calc_area {
66
- check almostEqual(calculate_area(RAD), expected_area);
66
+ assert almostEqual(calculate_area(RAD), expected_area);
67
67
  }
68
68
 
69
69
  test circle_area {
70
70
  c = Circle(RAD);
71
- check almostEqual(c.area(), expected_area);
71
+ assert almostEqual(c.area(), expected_area);
72
72
  }
73
73
 
74
74
  test circle_type {
75
75
  c = Circle(RAD);
76
- check c.shape_type == ShapeType.CIRCLE;
76
+ assert c.shape_type == ShapeType.CIRCLE;
77
77
  }
@@ -3,20 +3,20 @@ import from jaclang.runtimelib.machine { JacMachine }
3
3
 
4
4
  glob dynamic_module_source =
5
5
  """
6
- import from arch_create_util {UtilityNode}
6
+ import from arch_create_util {UtilityNode}
7
7
 
8
- walker DynamicWalker {
9
- can start with entry {
10
- print("DynamicWalker Started");
11
- here ++> UtilityNode(data=42);
12
- visit [-->](`?UtilityNode);
13
- }
8
+ walker DynamicWalker {
9
+ can start with entry {
10
+ print("DynamicWalker Started");
11
+ here ++> UtilityNode(data=42);
12
+ visit [-->](`?UtilityNode);
13
+ }
14
14
 
15
- def UtilityNode {
16
- here.display_data();
17
- }
18
- }
19
- """;
15
+ def UtilityNode {
16
+ here.display_data();
17
+ }
18
+ }
19
+ """;
20
20
 
21
21
 
22
22
  with entry {