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
@@ -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,
@@ -209,7 +210,7 @@ class UniNode:
209
210
 
210
211
  def flatten(self) -> list[UniNode]:
211
212
  """Flatten ast."""
212
- ret = [self]
213
+ ret: list[UniNode] = [self]
213
214
  for k in self.kid:
214
215
  ret += k.flatten()
215
216
  return ret
@@ -235,10 +236,12 @@ class Symbol:
235
236
  defn: NameAtom,
236
237
  access: SymbolAccess,
237
238
  parent_tab: UniScopeNode,
239
+ imported: bool = False,
238
240
  ) -> None:
239
241
  """Initialize."""
240
242
  self.defn: list[NameAtom] = [defn]
241
243
  self.uses: list[NameAtom] = []
244
+ self.imported: bool = imported
242
245
  defn.sym = self
243
246
  self.access: SymbolAccess = access
244
247
  self.parent_tab = parent_tab
@@ -271,7 +274,7 @@ class Symbol:
271
274
  return ".".join(out)
272
275
 
273
276
  @property
274
- def fetch_sym_tab(self) -> Optional[UniScopeNode]:
277
+ def symbol_table(self) -> Optional[UniScopeNode]:
275
278
  """Get symbol table."""
276
279
  return self.parent_tab.find_scope(self.sym_name)
277
280
 
@@ -333,6 +336,7 @@ class UniScopeNode(UniNode):
333
336
  access_spec: Optional[AstAccessNode] | SymbolAccess = None,
334
337
  single: bool = False,
335
338
  force_overwrite: bool = False,
339
+ imported: bool = False,
336
340
  ) -> Optional[UniNode]:
337
341
  """Set a variable in the symbol table.
338
342
 
@@ -353,6 +357,7 @@ class UniScopeNode(UniNode):
353
357
  else access_spec.access_type if access_spec else SymbolAccess.PUBLIC
354
358
  ),
355
359
  parent_tab=self,
360
+ imported=imported,
356
361
  )
357
362
  else:
358
363
  self.names_in_scope[node.sym_name].add_defn(node.name_spec)
@@ -386,6 +391,7 @@ class UniScopeNode(UniNode):
386
391
  access_spec: Optional[AstAccessNode] | SymbolAccess = None,
387
392
  single_decl: Optional[str] = None,
388
393
  force_overwrite: bool = False,
394
+ imported: bool = False,
389
395
  ) -> Optional[Symbol]:
390
396
  """Insert into symbol table."""
391
397
  if node.sym and self == node.sym.parent_tab:
@@ -395,6 +401,7 @@ class UniScopeNode(UniNode):
395
401
  single=single_decl is not None,
396
402
  access_spec=access_spec,
397
403
  force_overwrite=force_overwrite,
404
+ imported=imported,
398
405
  )
399
406
  self.update_py_ctx_for_def(node)
400
407
  return node.sym
@@ -715,6 +722,14 @@ class Expr(UniNode):
715
722
  self._sym_type: str = "NoType"
716
723
  self._type_sym_tab: Optional[UniScopeNode] = None
717
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
+
718
733
  @property
719
734
  def expr_type(self) -> str:
720
735
  return self._sym_type
@@ -967,8 +982,10 @@ class Module(AstDocNode, UniScopeNode):
967
982
  prog=JacProgram(),
968
983
  ).ir_out.gen.jac
969
984
 
970
- def unparse(self) -> str:
971
- super().unparse()
985
+ def unparse(self, requires_format: bool = True) -> str:
986
+ unparsed = super().unparse()
987
+ if not requires_format:
988
+ return unparsed
972
989
  return self.format()
973
990
 
974
991
  @staticmethod
@@ -1363,7 +1380,7 @@ class ModuleItem(AstSymbolNode):
1363
1380
  AstSymbolNode.__init__(
1364
1381
  self,
1365
1382
  sym_name=alias.sym_name if alias else name.sym_name,
1366
- name_spec=alias if alias else name,
1383
+ name_spec=alias or name,
1367
1384
  sym_category=SymbolType.MOD_VAR,
1368
1385
  )
1369
1386
  self.abs_path: Optional[str] = None
@@ -1371,13 +1388,9 @@ class ModuleItem(AstSymbolNode):
1371
1388
  @property
1372
1389
  def from_parent(self) -> Import:
1373
1390
  """Get import parent."""
1374
- if (
1375
- not self.parent
1376
- or not self.parent.parent
1377
- or not isinstance(self.parent.parent, Import)
1378
- ):
1391
+ if not self.parent or not isinstance(self.parent, Import):
1379
1392
  raise ValueError("Import parent not found. Not Possible.")
1380
- return self.parent.parent
1393
+ return self.parent
1381
1394
 
1382
1395
  @property
1383
1396
  def from_mod_path(self) -> ModulePath:
@@ -1516,7 +1529,8 @@ class Archetype(
1516
1529
  new_kid.append(stmt)
1517
1530
  new_kid.append(self.gen_token(Tok.RBRACE))
1518
1531
  else:
1519
- 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))
1520
1534
  self.set_kids(nodes=new_kid)
1521
1535
  return res
1522
1536
 
@@ -1529,7 +1543,7 @@ class ImplDef(CodeBlockStmt, ElementStmt, ArchBlockStmt, AstSymbolNode, UniScope
1529
1543
  decorators: Optional[Sequence[Expr]],
1530
1544
  target: Sequence[NameAtom],
1531
1545
  spec: Sequence[Expr] | FuncSignature | EventSignature | None,
1532
- body: Sequence[CodeBlockStmt] | Sequence[EnumBlockStmt] | FuncCall,
1546
+ body: Sequence[CodeBlockStmt] | Sequence[EnumBlockStmt] | Expr,
1533
1547
  kid: Sequence[UniNode],
1534
1548
  doc: Optional[String] = None,
1535
1549
  decl_link: Optional[UniNode] = None,
@@ -1575,7 +1589,7 @@ class ImplDef(CodeBlockStmt, ElementStmt, ArchBlockStmt, AstSymbolNode, UniScope
1575
1589
  res = res and sp.normalize(deep)
1576
1590
  else:
1577
1591
  res = res and self.spec.normalize(deep) if self.spec else res
1578
- if isinstance(self.body, FuncCall):
1592
+ if isinstance(self.body, Expr):
1579
1593
  res = res and self.body.normalize(deep)
1580
1594
  else:
1581
1595
  for stmt in self.body:
@@ -1608,7 +1622,7 @@ class ImplDef(CodeBlockStmt, ElementStmt, ArchBlockStmt, AstSymbolNode, UniScope
1608
1622
  new_kid.append(self.gen_token(Tok.RPAREN))
1609
1623
  else:
1610
1624
  new_kid.append(self.spec)
1611
- if isinstance(self.body, FuncCall):
1625
+ if isinstance(self.body, Expr):
1612
1626
  new_kid.append(self.body)
1613
1627
  else:
1614
1628
  new_kid.append(self.gen_token(Tok.LBRACE))
@@ -1781,7 +1795,7 @@ class Ability(
1781
1795
  is_abstract: bool,
1782
1796
  access: Optional[SubTag[Token]],
1783
1797
  signature: FuncSignature | EventSignature | None,
1784
- body: Sequence[CodeBlockStmt] | ImplDef | FuncCall | None,
1798
+ body: Sequence[CodeBlockStmt] | ImplDef | Expr | None,
1785
1799
  kid: Sequence[UniNode],
1786
1800
  doc: Optional[String] = None,
1787
1801
  decorators: Sequence[Expr] | None = None,
@@ -1832,7 +1846,7 @@ class Ability(
1832
1846
 
1833
1847
  @property
1834
1848
  def is_genai_ability(self) -> bool:
1835
- return isinstance(self.body, FuncCall)
1849
+ return isinstance(self.body, Expr)
1836
1850
 
1837
1851
  def get_pos_argc_range(self) -> tuple[int, int]:
1838
1852
  """Get the range of positional arguments for this ability.
@@ -2285,8 +2299,7 @@ class ExprStmt(CodeBlockStmt):
2285
2299
  CodeBlockStmt.__init__(self)
2286
2300
 
2287
2301
  def normalize(self, deep: bool = True) -> bool:
2288
- if deep:
2289
- res = self.expr.normalize(deep)
2302
+ res = self.expr.normalize(deep) if deep else False
2290
2303
  new_kid: list[UniNode] = []
2291
2304
  if self.in_fstring:
2292
2305
  new_kid.append(self.expr)
@@ -3488,7 +3501,7 @@ class InnerCompr(AstAsyncNode, UniScopeNode):
3488
3501
  return res
3489
3502
 
3490
3503
 
3491
- class ListCompr(AtomExpr):
3504
+ class ListCompr(AtomExpr, UniScopeNode):
3492
3505
  """ListCompr node type for Jac Ast."""
3493
3506
 
3494
3507
  def __init__(
@@ -3502,6 +3515,7 @@ class ListCompr(AtomExpr):
3502
3515
  UniNode.__init__(self, kid=kid)
3503
3516
  Expr.__init__(self)
3504
3517
  AstSymbolStubNode.__init__(self, sym_type=SymbolType.SEQUENCE)
3518
+ UniScopeNode.__init__(self, name=f"{self.__class__.__name__}")
3505
3519
 
3506
3520
  def normalize(self, deep: bool = False) -> bool:
3507
3521
  res = True
@@ -3702,14 +3716,12 @@ class FuncCall(Expr):
3702
3716
  self,
3703
3717
  target: Expr,
3704
3718
  params: Sequence[Expr | KWPair] | None,
3705
- genai_call: Optional[FuncCall],
3719
+ genai_call: Optional[Expr],
3706
3720
  kid: Sequence[UniNode],
3707
- body_genai_call: Optional[FuncCall] = None,
3708
3721
  ) -> None:
3709
3722
  self.target = target
3710
3723
  self.params = list(params) if params else []
3711
3724
  self.genai_call = genai_call
3712
- self.body_genai_call = body_genai_call
3713
3725
  UniNode.__init__(self, kid=kid)
3714
3726
  Expr.__init__(self)
3715
3727
 
@@ -4649,7 +4661,7 @@ class String(Literal):
4649
4661
 
4650
4662
  def unparse(self) -> str:
4651
4663
  super().unparse()
4652
- return repr(self.value)
4664
+ return self.value
4653
4665
 
4654
4666
 
4655
4667
  class Bool(Literal):