jaclang 0.8.5__py3-none-any.whl → 0.8.7__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 (70) hide show
  1. jaclang/cli/cli.md +4 -3
  2. jaclang/cli/cli.py +63 -29
  3. jaclang/cli/cmdreg.py +1 -140
  4. jaclang/compiler/passes/main/__init__.py +2 -0
  5. jaclang/compiler/passes/main/cfg_build_pass.py +21 -1
  6. jaclang/compiler/passes/main/inheritance_pass.py +8 -1
  7. jaclang/compiler/passes/main/pyast_gen_pass.py +70 -11
  8. jaclang/compiler/passes/main/pyast_load_pass.py +14 -20
  9. jaclang/compiler/passes/main/sym_tab_build_pass.py +4 -0
  10. jaclang/compiler/passes/main/tests/fixtures/cfg_has_var.jac +12 -0
  11. jaclang/compiler/passes/main/tests/fixtures/cfg_if_no_else.jac +11 -0
  12. jaclang/compiler/passes/main/tests/fixtures/cfg_return.jac +9 -0
  13. jaclang/compiler/passes/main/tests/fixtures/checker_binary_op.jac +21 -0
  14. jaclang/compiler/passes/main/tests/fixtures/checker_call_expr_class.jac +12 -0
  15. jaclang/compiler/passes/main/tests/fixtures/checker_cyclic_symbol.jac +4 -0
  16. jaclang/compiler/passes/main/tests/fixtures/checker_expr_call.jac +9 -0
  17. jaclang/compiler/passes/main/tests/fixtures/checker_import_missing_module.jac +13 -0
  18. jaclang/compiler/passes/main/tests/fixtures/checker_imported.jac +2 -0
  19. jaclang/compiler/passes/main/tests/fixtures/checker_importer.jac +6 -0
  20. jaclang/compiler/passes/main/tests/fixtures/checker_magic_call.jac +17 -0
  21. jaclang/compiler/passes/main/tests/fixtures/checker_mod_path.jac +8 -0
  22. jaclang/compiler/passes/main/tests/fixtures/data_spatial_types.jac +1 -1
  23. jaclang/compiler/passes/main/tests/fixtures/import_symbol_type_infer.jac +11 -0
  24. jaclang/compiler/passes/main/tests/fixtures/infer_type_assignment.jac +5 -0
  25. jaclang/compiler/passes/main/tests/fixtures/member_access_type_inferred.jac +13 -0
  26. jaclang/compiler/passes/main/tests/fixtures/member_access_type_resolve.jac +11 -0
  27. jaclang/compiler/passes/main/tests/fixtures/type_annotation_assignment.jac +8 -0
  28. jaclang/compiler/passes/main/tests/test_cfg_build_pass.py +62 -24
  29. jaclang/compiler/passes/main/tests/test_checker_pass.py +161 -0
  30. jaclang/compiler/passes/main/type_checker_pass.py +147 -0
  31. jaclang/compiler/passes/tool/tests/fixtures/simple_walk_fmt.jac +1 -4
  32. jaclang/compiler/program.py +17 -3
  33. jaclang/compiler/type_system/__init__.py +1 -0
  34. jaclang/compiler/type_system/operations.py +104 -0
  35. jaclang/compiler/type_system/type_evaluator.py +560 -0
  36. jaclang/compiler/type_system/type_utils.py +41 -0
  37. jaclang/compiler/type_system/types.py +240 -0
  38. jaclang/compiler/unitree.py +15 -9
  39. jaclang/langserve/dev_engine.jac +645 -0
  40. jaclang/langserve/dev_server.jac +201 -0
  41. jaclang/langserve/engine.jac +135 -91
  42. jaclang/langserve/server.jac +21 -14
  43. jaclang/langserve/tests/server_test/test_lang_serve.py +2 -5
  44. jaclang/langserve/tests/test_dev_server.py +80 -0
  45. jaclang/langserve/tests/test_server.py +9 -2
  46. jaclang/langserve/utils.jac +44 -48
  47. jaclang/runtimelib/builtin.py +28 -39
  48. jaclang/runtimelib/importer.py +1 -1
  49. jaclang/runtimelib/machine.py +48 -64
  50. jaclang/runtimelib/memory.py +23 -5
  51. jaclang/runtimelib/tests/fixtures/savable_object.jac +10 -2
  52. jaclang/runtimelib/utils.py +13 -6
  53. jaclang/tests/fixtures/edge_node_walk.jac +1 -1
  54. jaclang/tests/fixtures/edges_walk.jac +1 -1
  55. jaclang/tests/fixtures/gendot_bubble_sort.jac +1 -1
  56. jaclang/tests/fixtures/jac_run_py_bugs.py +18 -0
  57. jaclang/tests/fixtures/jac_run_py_import.py +13 -0
  58. jaclang/tests/fixtures/lambda_arg_annotation.jac +15 -0
  59. jaclang/tests/fixtures/lambda_self.jac +18 -0
  60. jaclang/tests/fixtures/py_run.jac +8 -0
  61. jaclang/tests/fixtures/py_run.py +23 -0
  62. jaclang/tests/fixtures/pyfunc.py +2 -0
  63. jaclang/tests/test_cli.py +103 -14
  64. jaclang/tests/test_language.py +10 -4
  65. jaclang/utils/lang_tools.py +3 -0
  66. jaclang/utils/module_resolver.py +1 -1
  67. {jaclang-0.8.5.dist-info → jaclang-0.8.7.dist-info}/METADATA +4 -2
  68. {jaclang-0.8.5.dist-info → jaclang-0.8.7.dist-info}/RECORD +70 -37
  69. {jaclang-0.8.5.dist-info → jaclang-0.8.7.dist-info}/WHEEL +1 -1
  70. {jaclang-0.8.5.dist-info → jaclang-0.8.7.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,240 @@
1
+ """Representation of types used during type analysis."""
2
+
3
+ from __future__ import annotations
4
+
5
+ # Pyright Reference: packages\pyright-internal\src\analyzer\types.ts
6
+ from abc import ABC
7
+ from enum import IntEnum, auto
8
+ from pathlib import Path
9
+ from typing import ClassVar, TYPE_CHECKING
10
+
11
+ if TYPE_CHECKING:
12
+ from jaclang.compiler.unitree import Symbol, UniScopeNode as SymbolTable
13
+
14
+
15
+ class TypeCategory(IntEnum):
16
+ """Enumeration of type categories."""
17
+
18
+ Unbound = auto() # Name is not bound to a value of any type
19
+ Unknown = auto() # Implicit Any type
20
+ Never = auto() # The bottom type, equivalent to an empty union
21
+ Any = auto() # Type can be anything
22
+ Module = auto() # Module instance
23
+ Class = auto() # Class definition
24
+ Function = auto() # Callable type
25
+ Union = auto() # Union of two or more other types
26
+
27
+
28
+ class TypeFlags(IntEnum):
29
+ """Flags to set on a type.
30
+
31
+ foo = 42 # <-- Here type of foo is `int` class, Instance type.
32
+ foo = int # <-- Here type of foo is `type[int]`, Instantiable is set.
33
+ foo: int = 42
34
+ ^^^------- Here the type of the expression `int` is `type[int]`
35
+ That is same as the prefetched int_class that has the
36
+ flag Instantiable set.
37
+
38
+ calling convertToInstance() will return the same type
39
+ with Instance flag set.
40
+ """
41
+
42
+ Null = 0 # Pyright use None but python can't
43
+
44
+ # This type refers to something that can be instantiated.
45
+ Instantiable = 1 << 0
46
+
47
+ # This type refers to something that has been instantiated.
48
+ Instance = 1 << 1
49
+
50
+ # This type is inferred within a py.typed source file and could be
51
+ # inferred differently by other type checkers.
52
+ Ambiguous = 1 << 2
53
+
54
+
55
+ class ParameterCategory(IntEnum):
56
+ """Enumeration of parameter categories."""
57
+
58
+ Positional = auto()
59
+ ArgsList = auto()
60
+ KwargsDict = auto()
61
+
62
+
63
+ class TypeBase(ABC):
64
+ """Maps to pyright's TypeBase<T> in the types.ts file.
65
+
66
+ This is the base class for all type instance of the jaclang that holds
67
+ information about the type's category and any additional metadata and
68
+ utilities to analyze type information and provide type checking.
69
+ """
70
+
71
+ # Each subclass should provide a class-level CATEGORY constant indicating its type category.
72
+ CATEGORY: ClassVar[TypeCategory]
73
+
74
+ def __init__(self, flags: TypeFlags = TypeFlags.Null) -> None:
75
+ """Initialize obviously."""
76
+ self.flags: TypeFlags = flags
77
+
78
+ @property
79
+ def category(self) -> TypeCategory:
80
+ """Returns the category of the type."""
81
+ return self.CATEGORY
82
+
83
+ @staticmethod
84
+ def unknown() -> "UnknownType":
85
+ """Return an instance of an unknown type."""
86
+ return UnknownType()
87
+
88
+ def is_instantiable(self) -> bool:
89
+ """Return whether the type is instantiable."""
90
+ return bool(self.flags & TypeFlags.Instantiable)
91
+
92
+ def is_instance(self) -> bool:
93
+ """Return whether the type is an instance."""
94
+ return bool(self.flags & TypeFlags.Instance)
95
+
96
+ def is_instantiable_class(self) -> bool:
97
+ """Return whether the class can be instantiated."""
98
+ return (self.category == TypeCategory.Class) and self.is_instantiable()
99
+
100
+ def is_class_instance(self) -> bool:
101
+ """Return whether the class is an instance."""
102
+ return (self.category == TypeCategory.Class) and self.is_instance()
103
+
104
+
105
+ class UnboundType(TypeBase):
106
+ """Represents a type that is not bound to a specific value or context."""
107
+
108
+ CATEGORY: ClassVar[TypeCategory] = TypeCategory.Unbound
109
+
110
+
111
+ class UnknownType(TypeBase):
112
+ """Represents a type that is not known or cannot be determined."""
113
+
114
+ CATEGORY: ClassVar[TypeCategory] = TypeCategory.Unknown
115
+
116
+
117
+ class NeverType(TypeBase):
118
+ """Represents a type that can never occur."""
119
+
120
+ CATEGORY: ClassVar[TypeCategory] = TypeCategory.Never
121
+
122
+
123
+ class AnyType(TypeBase):
124
+ """Represents a type that can be anything."""
125
+
126
+ CATEGORY: ClassVar[TypeCategory] = TypeCategory.Any
127
+
128
+
129
+ class ModuleType(TypeBase):
130
+ """Represents a module type."""
131
+
132
+ CATEGORY: ClassVar[TypeCategory] = TypeCategory.Module
133
+
134
+ def __init__(
135
+ self, mod_name: str, file_uri: Path, symbol_table: SymbolTable
136
+ ) -> None:
137
+ """Initialize the class."""
138
+ super().__init__()
139
+ self.mod_name = mod_name
140
+ self.file_uri = file_uri
141
+ self.symbol_table = symbol_table
142
+
143
+
144
+ class ClassType(TypeBase):
145
+ """Represents a class type."""
146
+
147
+ CATEGORY: ClassVar[TypeCategory] = TypeCategory.Class
148
+
149
+ # Pyright has both ClassDetailsShared; and ClassDetailsPriv;
150
+ # however we're only using shared instance and the private details
151
+ # will be part of the class itself.
152
+
153
+ class ClassDetailsShared:
154
+ """Holds the shared details of class type.
155
+
156
+ The shared detail of classes will points to the same instance across multiple clones
157
+ of the same class. This is needed when we do `==` between two classes, if they have the
158
+ same shared object, that means they both are the same class (with different context).
159
+ """
160
+
161
+ def __init__(
162
+ self,
163
+ class_name: str,
164
+ symbol_table: SymbolTable,
165
+ base_classes: list[TypeBase] | None = None,
166
+ ) -> None:
167
+ """Initialize obviously."""
168
+ self.class_name = class_name
169
+ self.symbol_table = symbol_table
170
+ self.base_classes = base_classes or []
171
+
172
+ def __init__(
173
+ self,
174
+ shared: ClassType.ClassDetailsShared,
175
+ flags: TypeFlags = TypeFlags.Null,
176
+ ) -> None:
177
+ """Initialize the class type."""
178
+ super().__init__(flags=flags)
179
+ self.shared = shared
180
+
181
+ def clone_as_instance(self) -> "ClassType":
182
+ """Clone this class type as an instance type."""
183
+ if self.is_instance():
184
+ return self
185
+ new_instance = ClassType(self.shared)
186
+
187
+ # TODO: There is more to this but we're not over complicating this atm.
188
+ new_flag = self.flags
189
+ new_flag = TypeFlags(new_flag & ~TypeFlags.Instantiable)
190
+ new_flags = TypeFlags(new_flag | TypeFlags.Instance)
191
+ new_instance.flags = new_flags
192
+
193
+ return new_instance
194
+
195
+ def lookup_member_symbol(self, member: str) -> Symbol | None:
196
+ """Lookup a member in the class type."""
197
+ return self.shared.symbol_table.lookup(member, deep=True)
198
+
199
+
200
+ class Parameter:
201
+ """Represents a function parameter."""
202
+
203
+ def __init__(
204
+ self, name: str, category: ParameterCategory, param_type: TypeBase | None
205
+ ) -> None:
206
+ """Initialize obviously."""
207
+ super().__init__()
208
+ self.name = name
209
+ self.category = category
210
+ self.param_type = param_type
211
+
212
+
213
+ class FunctionType(TypeBase):
214
+ """Represents a function type."""
215
+
216
+ CATEGORY: ClassVar[TypeCategory] = TypeCategory.Function
217
+
218
+ def __init__(
219
+ self,
220
+ func_name: str,
221
+ return_type: TypeBase | None = None,
222
+ parameters: list[Parameter] | None = None,
223
+ flags: TypeFlags = TypeFlags.Null,
224
+ ) -> None:
225
+ """Initialize obviously."""
226
+ super().__init__(flags=flags)
227
+ self.func_name = func_name
228
+ self.return_type = return_type
229
+ self.parameters = parameters or []
230
+
231
+
232
+ class UnionType(TypeBase):
233
+ """Represents a union type."""
234
+
235
+ CATEGORY: ClassVar[TypeCategory] = TypeCategory.Union
236
+
237
+ def __init__(self, types: list[TypeBase]) -> None:
238
+ """Initialize obviously."""
239
+ super().__init__()
240
+ self.types = types
@@ -30,6 +30,7 @@ from jaclang.compiler.constant import (
30
30
  SymbolType,
31
31
  )
32
32
  from jaclang.compiler.constant import DELIM_MAP, SymbolAccess, Tokens as Tok
33
+ from jaclang.compiler.type_system.types import TypeBase
33
34
  from jaclang.utils import resolve_relative_path
34
35
  from jaclang.utils.treeprinter import (
35
36
  print_ast_tree,
@@ -721,6 +722,14 @@ class Expr(UniNode):
721
722
  self._sym_type: str = "NoType"
722
723
  self._type_sym_tab: Optional[UniScopeNode] = None
723
724
 
725
+ # When the type of an expression is resolved, we'll be caching
726
+ # the type here.
727
+ #
728
+ # TODO:
729
+ # 1. Find a better name for this
730
+ # 2. Migrate this to expr_type property
731
+ self.type: TypeBase | None = None
732
+
724
733
  @property
725
734
  def expr_type(self) -> str:
726
735
  return self._sym_type
@@ -1371,7 +1380,7 @@ class ModuleItem(AstSymbolNode):
1371
1380
  AstSymbolNode.__init__(
1372
1381
  self,
1373
1382
  sym_name=alias.sym_name if alias else name.sym_name,
1374
- name_spec=alias if alias else name,
1383
+ name_spec=alias or name,
1375
1384
  sym_category=SymbolType.MOD_VAR,
1376
1385
  )
1377
1386
  self.abs_path: Optional[str] = None
@@ -1379,13 +1388,9 @@ class ModuleItem(AstSymbolNode):
1379
1388
  @property
1380
1389
  def from_parent(self) -> Import:
1381
1390
  """Get import parent."""
1382
- if (
1383
- not self.parent
1384
- or not self.parent.parent
1385
- or not isinstance(self.parent.parent, Import)
1386
- ):
1391
+ if not self.parent or not isinstance(self.parent, Import):
1387
1392
  raise ValueError("Import parent not found. Not Possible.")
1388
- return self.parent.parent
1393
+ return self.parent
1389
1394
 
1390
1395
  @property
1391
1396
  def from_mod_path(self) -> ModulePath:
@@ -1524,7 +1529,8 @@ class Archetype(
1524
1529
  new_kid.append(stmt)
1525
1530
  new_kid.append(self.gen_token(Tok.RBRACE))
1526
1531
  else:
1527
- new_kid.append(self.gen_token(Tok.SEMI))
1532
+ new_kid.append(self.gen_token(Tok.LBRACE))
1533
+ new_kid.append(self.gen_token(Tok.RBRACE))
1528
1534
  self.set_kids(nodes=new_kid)
1529
1535
  return res
1530
1536
 
@@ -4655,7 +4661,7 @@ class String(Literal):
4655
4661
 
4656
4662
  def unparse(self) -> str:
4657
4663
  super().unparse()
4658
- return repr(self.value)
4664
+ return self.value
4659
4665
 
4660
4666
 
4661
4667
  class Bool(Literal):