jaclang 0.8.4__py3-none-any.whl → 0.8.6__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 (88) hide show
  1. jaclang/cli/cli.md +1 -0
  2. jaclang/cli/cli.py +109 -37
  3. jaclang/compiler/jac.lark +3 -3
  4. jaclang/compiler/larkparse/jac_parser.py +2 -2
  5. jaclang/compiler/parser.py +14 -21
  6. jaclang/compiler/passes/main/__init__.py +5 -1
  7. jaclang/compiler/passes/main/binder_pass.py +594 -0
  8. jaclang/compiler/passes/main/cfg_build_pass.py +21 -1
  9. jaclang/compiler/passes/main/import_pass.py +8 -256
  10. jaclang/compiler/passes/main/inheritance_pass.py +10 -3
  11. jaclang/compiler/passes/main/pyast_gen_pass.py +92 -77
  12. jaclang/compiler/passes/main/pyast_load_pass.py +24 -13
  13. jaclang/compiler/passes/main/sem_def_match_pass.py +1 -1
  14. jaclang/compiler/passes/main/sym_tab_build_pass.py +4 -0
  15. jaclang/compiler/passes/main/tests/fixtures/M1.jac +3 -0
  16. jaclang/compiler/passes/main/tests/fixtures/cfg_has_var.jac +12 -0
  17. jaclang/compiler/passes/main/tests/fixtures/cfg_if_no_else.jac +11 -0
  18. jaclang/compiler/passes/main/tests/fixtures/cfg_return.jac +9 -0
  19. jaclang/compiler/passes/main/tests/fixtures/checker_imported.jac +2 -0
  20. jaclang/compiler/passes/main/tests/fixtures/checker_importer.jac +6 -0
  21. jaclang/compiler/passes/main/tests/fixtures/data_spatial_types.jac +1 -1
  22. jaclang/compiler/passes/main/tests/fixtures/import_symbol_type_infer.jac +11 -0
  23. jaclang/compiler/passes/main/tests/fixtures/infer_type_assignment.jac +5 -0
  24. jaclang/compiler/passes/main/tests/fixtures/member_access_type_inferred.jac +13 -0
  25. jaclang/compiler/passes/main/tests/fixtures/member_access_type_resolve.jac +11 -0
  26. jaclang/compiler/passes/main/tests/fixtures/sym_binder.jac +47 -0
  27. jaclang/compiler/passes/main/tests/fixtures/type_annotation_assignment.jac +8 -0
  28. jaclang/compiler/passes/main/tests/test_binder_pass.py +111 -0
  29. jaclang/compiler/passes/main/tests/test_cfg_build_pass.py +62 -24
  30. jaclang/compiler/passes/main/tests/test_checker_pass.py +87 -0
  31. jaclang/compiler/passes/main/tests/test_pyast_gen_pass.py +13 -13
  32. jaclang/compiler/passes/main/tests/test_sem_def_match_pass.py +6 -6
  33. jaclang/compiler/passes/main/type_checker_pass.py +128 -0
  34. jaclang/compiler/passes/tool/doc_ir_gen_pass.py +2 -0
  35. jaclang/compiler/passes/tool/tests/fixtures/simple_walk_fmt.jac +3 -0
  36. jaclang/compiler/program.py +32 -11
  37. jaclang/compiler/tests/test_sr_errors.py +32 -0
  38. jaclang/compiler/type_system/__init__.py +1 -0
  39. jaclang/compiler/type_system/type_evaluator.py +421 -0
  40. jaclang/compiler/type_system/type_utils.py +41 -0
  41. jaclang/compiler/type_system/types.py +240 -0
  42. jaclang/compiler/unitree.py +36 -24
  43. jaclang/langserve/dev_engine.jac +645 -0
  44. jaclang/langserve/dev_server.jac +201 -0
  45. jaclang/langserve/engine.jac +24 -5
  46. jaclang/langserve/tests/server_test/test_lang_serve.py +2 -2
  47. jaclang/langserve/tests/test_dev_server.py +80 -0
  48. jaclang/langserve/tests/test_server.py +13 -0
  49. jaclang/runtimelib/builtin.py +28 -39
  50. jaclang/runtimelib/importer.py +34 -63
  51. jaclang/runtimelib/machine.py +48 -64
  52. jaclang/runtimelib/memory.py +23 -5
  53. jaclang/runtimelib/tests/fixtures/savable_object.jac +10 -2
  54. jaclang/runtimelib/utils.py +42 -6
  55. jaclang/tests/fixtures/edge_node_walk.jac +1 -1
  56. jaclang/tests/fixtures/edges_walk.jac +1 -1
  57. jaclang/tests/fixtures/gendot_bubble_sort.jac +1 -1
  58. jaclang/tests/fixtures/py_run.jac +8 -0
  59. jaclang/tests/fixtures/py_run.py +23 -0
  60. jaclang/tests/fixtures/pyfunc.py +2 -0
  61. jaclang/tests/fixtures/pyfunc_fmt.py +60 -0
  62. jaclang/tests/fixtures/pyfunc_fstr.py +25 -0
  63. jaclang/tests/fixtures/pyfunc_kwesc.py +33 -0
  64. jaclang/tests/fixtures/python_run_test.py +19 -0
  65. jaclang/tests/test_cli.py +107 -0
  66. jaclang/tests/test_language.py +106 -5
  67. jaclang/utils/lang_tools.py +6 -3
  68. jaclang/utils/module_resolver.py +90 -0
  69. jaclang/utils/symtable_test_helpers.py +125 -0
  70. jaclang/utils/test.py +3 -4
  71. jaclang/vendor/interegular/__init__.py +34 -0
  72. jaclang/vendor/interegular/comparator.py +163 -0
  73. jaclang/vendor/interegular/fsm.py +1015 -0
  74. jaclang/vendor/interegular/patterns.py +732 -0
  75. jaclang/vendor/interegular/py.typed +0 -0
  76. jaclang/vendor/interegular/utils/__init__.py +15 -0
  77. jaclang/vendor/interegular/utils/simple_parser.py +165 -0
  78. jaclang/vendor/interegular-0.3.3.dist-info/INSTALLER +1 -0
  79. jaclang/vendor/interegular-0.3.3.dist-info/LICENSE.txt +21 -0
  80. jaclang/vendor/interegular-0.3.3.dist-info/METADATA +64 -0
  81. jaclang/vendor/interegular-0.3.3.dist-info/RECORD +20 -0
  82. jaclang/vendor/interegular-0.3.3.dist-info/REQUESTED +0 -0
  83. jaclang/vendor/interegular-0.3.3.dist-info/WHEEL +5 -0
  84. jaclang/vendor/interegular-0.3.3.dist-info/top_level.txt +1 -0
  85. {jaclang-0.8.4.dist-info → jaclang-0.8.6.dist-info}/METADATA +2 -1
  86. {jaclang-0.8.4.dist-info → jaclang-0.8.6.dist-info}/RECORD +88 -43
  87. {jaclang-0.8.4.dist-info → jaclang-0.8.6.dist-info}/WHEEL +0 -0
  88. {jaclang-0.8.4.dist-info → jaclang-0.8.6.dist-info}/entry_points.txt +0 -0
jaclang/cli/cli.md CHANGED
@@ -36,6 +36,7 @@ Parameters to execute the tool command:
36
36
  - `sym.`: Generates a dot graph representation of the symbol table for the specified .jac file.
37
37
  - `ast`: Displays the Abstract Syntax Tree (AST) of the specified .jac file.
38
38
  - `ast.`: Generates a dot graph representation of the AST for the specified .jac file.
39
+ - `cfg.`: Generates a dot graph representatuin of the CFG(Control Flow Graph) for a specific .jac file
39
40
  - `pyast`: Generates the Python AST for a .py file or the relevant Python AST for the generated Python code from a .jac file.
40
41
  - `py`: Displays the relevant generated Python code for the respective Jac code in a .jac file.
41
42
  - `file_path`: Path to the .jac or .py file.
jaclang/cli/cli.py CHANGED
@@ -16,16 +16,12 @@ from jaclang.compiler.passes.main import PyastBuildPass
16
16
  from jaclang.compiler.program import JacProgram
17
17
  from jaclang.runtimelib.builtin import printgraph
18
18
  from jaclang.runtimelib.constructs import WalkerArchetype
19
- from jaclang.runtimelib.machine import (
20
- ExecutionContext,
21
- JacMachine as Jac,
22
- JacMachineInterface as JacInterface,
23
- )
19
+ from jaclang.runtimelib.machine import ExecutionContext, JacMachine as Jac
20
+ from jaclang.runtimelib.utils import read_file_with_encoding
24
21
  from jaclang.utils.helpers import debugger as db
25
22
  from jaclang.utils.lang_tools import AstTool
26
23
 
27
-
28
- JacInterface.create_cmd()
24
+ Jac.create_cmd()
29
25
  Jac.setup()
30
26
 
31
27
 
@@ -98,7 +94,15 @@ def proc_file_sess(
98
94
  )
99
95
  base, mod = os.path.split(filename)
100
96
  base = base if base else "./"
101
- mod = mod[:-4]
97
+ if filename.endswith(".jac") or filename.endswith(".jir"):
98
+ mod = mod[:-4]
99
+ elif filename.endswith(".py"):
100
+ mod = mod[:-3]
101
+ else:
102
+ print(
103
+ "Not a valid file!\nOnly supports `.jac`, `.jir`, and `.py`",
104
+ file=sys.stderr,
105
+ )
102
106
  mach = ExecutionContext(session=session, root=root)
103
107
  Jac.set_context(mach)
104
108
  return base, mod, mach
@@ -111,36 +115,39 @@ def run(
111
115
  main: bool = True,
112
116
  cache: bool = True,
113
117
  ) -> None:
114
- """Run the specified .jac file.
118
+ """Run the specified .jac, .jir, or .py file.
115
119
 
116
- Executes a Jac program file, loading it into the Jac runtime environment
117
- and running its code. This is the primary way to execute Jac programs.
120
+ Executes a Jac program file or Python file, loading it into the Jac runtime environment
121
+ and running its code. Python files are converted to Jac AST for execution.
118
122
 
119
123
  Args:
120
- filename: Path to the .jac or .jir file to run
124
+ filename: Path to the .jac, .jir, or .py file to run
121
125
  session: Optional session identifier for persistent state
122
126
  main: Treat the module as __main__ (default: True)
123
127
  cache: Use cached compilation if available (default: True)
124
128
 
125
129
  Examples:
126
130
  jac run myprogram.jac
131
+ jac run myscript.py
127
132
  jac run myprogram.jac --session mysession
128
133
  jac run myprogram.jac --no-main
129
134
  """
130
135
  # if no session specified, check if it was defined when starting the command shell
131
136
  # otherwise default to jaclang.session
132
137
  base, mod, mach = proc_file_sess(filename, session)
138
+ lng = filename.split(".")[-1]
133
139
  Jac.set_base_path(base)
134
140
 
135
- if filename.endswith(".jac"):
141
+ if filename.endswith((".jac", ".py")):
136
142
  try:
137
143
  Jac.jac_import(
138
144
  target=mod,
139
145
  base_path=base,
140
146
  override_name="__main__" if main else None,
147
+ lng=lng,
141
148
  )
142
149
  except Exception as e:
143
- print(e, file=sys.stderr)
150
+ print(f"Error running {filename}: {e}", file=sys.stderr)
144
151
  elif filename.endswith(".jir"):
145
152
  try:
146
153
  with open(filename, "rb") as f:
@@ -149,12 +156,16 @@ def run(
149
156
  target=mod,
150
157
  base_path=base,
151
158
  override_name="__main__" if main else None,
159
+ lng=lng,
152
160
  )
153
161
  except Exception as e:
154
- print(e, file=sys.stderr)
155
-
162
+ print(f"Error running {filename}: {e}", file=sys.stderr)
156
163
  else:
157
- print("Not a valid file!\nOnly supports `.jac` and `.jir`")
164
+ print(
165
+ "Not a valid file!\nOnly supports `.jac`, `.jir`, and `.py`",
166
+ file=sys.stderr,
167
+ )
168
+
158
169
  mach.close()
159
170
 
160
171
 
@@ -206,7 +217,7 @@ def get_object(filename: str, id: str, session: str = "", main: bool = True) ->
206
217
 
207
218
 
208
219
  @cmd_registry.register
209
- def build(filename: str) -> None:
220
+ def build(filename: str, typecheck: bool = False) -> None:
210
221
  """Build the specified .jac file.
211
222
 
212
223
  Compiles a Jac source file into a Jac Intermediate Representation (.jir) file,
@@ -214,21 +225,60 @@ def build(filename: str) -> None:
214
225
 
215
226
  Args:
216
227
  filename: Path to the .jac file to build
217
- typecheck: Perform type checking during build (default: True)
228
+ typecheck: Perform type checking during build (default: False)
218
229
 
219
230
  Examples:
220
231
  jac build myprogram.jac
221
- jac build myprogram.jac --no-typecheck
232
+ jac build myprogram.jac --typecheck
222
233
  """
223
- if filename.endswith(".jac"):
224
- (out := JacProgram()).compile(file_path=filename)
234
+ if not filename.endswith(".jac"):
235
+ print("Not a .jac file.", file=sys.stderr)
236
+ exit(1)
237
+ (out := JacProgram()).compile(file_path=filename, type_check=typecheck)
238
+ errs = len(out.errors_had)
239
+ warnings = len(out.warnings_had)
240
+ print(f"Errors: {errs}, Warnings: {warnings}")
241
+
242
+ for alrt in out.errors_had + out.warnings_had:
243
+ print(alrt.pretty_print(), file=sys.stderr)
244
+
245
+ with open(filename[:-4] + ".jir", "wb") as f:
246
+ pickle.dump(out, f)
247
+
248
+
249
+ @cmd_registry.register
250
+ def bind(filename: str, typecheck: bool = False) -> None:
251
+ """Bind the specified .jac file.
252
+
253
+ Parses and binds a Jac source file, resolving symbols and preparing it for execution.
254
+ This step is necessary before running the program, as it ensures all references
255
+ are correctly linked and the program structure is validated.
256
+ TODO: performs type checking.
257
+
258
+ Args:
259
+ filename: Path to the .jac file to bind
260
+ typecheck: Print the symbol table after binding (default: False)
261
+
262
+ Examples:
263
+ jac bind myprogram.jac
264
+ jac bind myprogram.jac -t
265
+ """
266
+ if filename.endswith((".jac", ".py")):
267
+ (out := JacProgram()).bind(file_path=filename)
225
268
  errs = len(out.errors_had)
226
269
  warnings = len(out.warnings_had)
270
+ if typecheck:
271
+ for mods in out.mod.hub.values():
272
+ if mods.name == "builtins":
273
+ continue
274
+ header = (
275
+ f"{'=' * 6} SymTable({mods.name}) {'=' * (22 - len(mods.name))}"
276
+ )
277
+ divider = "=" * 40
278
+ print(f"{divider}\n{header}\n{divider}\n{mods.sym_tab.sym_pp()}")
227
279
  print(f"Errors: {errs}, Warnings: {warnings}")
228
- with open(filename[:-4] + ".jir", "wb") as f:
229
- pickle.dump(out, f)
230
280
  else:
231
- print("Not a .jac file.", file=sys.stderr)
281
+ print("Not a .jac/.py file.", file=sys.stderr)
232
282
 
233
283
 
234
284
  @cmd_registry.register
@@ -277,6 +327,24 @@ def lsp() -> None:
277
327
  run_lang_server()
278
328
 
279
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
344
+
345
+ run_lang_server()
346
+
347
+
280
348
  @cmd_registry.register
281
349
  def enter(
282
350
  filename: str,
@@ -546,16 +614,21 @@ def py2jac(filename: str) -> None:
546
614
  jac py2jac myscript.py > converted.jac
547
615
  """
548
616
  if filename.endswith(".py"):
549
- with open(filename, "r") as f:
550
- file_source = f.read()
551
- code = PyastBuildPass(
552
- ir_in=uni.PythonModuleAst(
553
- ast3.parse(file_source),
554
- orig_src=uni.Source(file_source, filename),
555
- ),
556
- prog=JacProgram(),
557
- ).ir_out.unparse()
558
- print(code)
617
+ file_source = read_file_with_encoding(filename)
618
+ code = PyastBuildPass(
619
+ ir_in=uni.PythonModuleAst(
620
+ ast3.parse(file_source),
621
+ orig_src=uni.Source(file_source, filename),
622
+ ),
623
+ prog=JacProgram(),
624
+ ).ir_out.unparse(requires_format=False)
625
+ formatted_code = JacProgram().jac_str_formatter(
626
+ source_str=code, file_path=filename
627
+ )
628
+ if formatted_code:
629
+ print(formatted_code)
630
+ else:
631
+ print("Error converting Python code to Jac.", file=sys.stderr)
559
632
  else:
560
633
  print("Not a .py file.")
561
634
 
@@ -575,8 +648,7 @@ def jac2py(filename: str) -> None:
575
648
  jac jac2py myprogram.jac > converted.py
576
649
  """
577
650
  if filename.endswith(".jac"):
578
- with open(filename, "r"):
579
- code = JacProgram().compile(file_path=filename).gen.py
651
+ code = JacProgram().compile(file_path=filename).gen.py
580
652
  print(code)
581
653
  else:
582
654
  print("Not a .jac file.", file=sys.stderr)
jaclang/compiler/jac.lark CHANGED
@@ -62,7 +62,7 @@ ability: decorators? KW_ASYNC? (ability_decl | function_decl)
62
62
 
63
63
  function_decl: KW_OVERRIDE? KW_STATIC? KW_DEF access_tag? named_ref func_decl? (block_tail | KW_ABSTRACT? SEMI)
64
64
  ability_decl: KW_OVERRIDE? KW_STATIC? KW_CAN access_tag? named_ref event_clause (block_tail | KW_ABSTRACT? SEMI)
65
- block_tail: code_block | KW_BY atomic_call SEMI
65
+ block_tail: code_block | KW_BY expression SEMI
66
66
  event_clause: KW_WITH expression? (KW_EXIT | KW_ENTRY)
67
67
 
68
68
  func_decl: (LPAREN func_decl_params? RPAREN) (RETURN_HINT expression)?
@@ -331,9 +331,9 @@ index_slice: LSQUARE
331
331
  | list_val
332
332
 
333
333
  // [Heading]: Function calls.
334
- atomic_call: atomic_chain LPAREN param_list? by_call? RPAREN by_call?
334
+ atomic_call: atomic_chain LPAREN param_list? by_llm? RPAREN
335
335
 
336
- by_call: KW_BY expression
336
+ by_llm: KW_BY expression
337
337
 
338
338
  param_list: expr_list COMMA kw_expr_list COMMA?
339
339
  | kw_expr_list COMMA?