literals.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. from __future__ import annotations
  2. from typing import Any, Final, Iterable, Optional, Tuple
  3. from typing_extensions import TypeAlias as _TypeAlias
  4. from mypy.nodes import (
  5. LITERAL_NO,
  6. LITERAL_TYPE,
  7. LITERAL_YES,
  8. AssertTypeExpr,
  9. AssignmentExpr,
  10. AwaitExpr,
  11. BytesExpr,
  12. CallExpr,
  13. CastExpr,
  14. ComparisonExpr,
  15. ComplexExpr,
  16. ConditionalExpr,
  17. DictExpr,
  18. DictionaryComprehension,
  19. EllipsisExpr,
  20. EnumCallExpr,
  21. Expression,
  22. FloatExpr,
  23. GeneratorExpr,
  24. IndexExpr,
  25. IntExpr,
  26. LambdaExpr,
  27. ListComprehension,
  28. ListExpr,
  29. MemberExpr,
  30. NamedTupleExpr,
  31. NameExpr,
  32. NewTypeExpr,
  33. OpExpr,
  34. ParamSpecExpr,
  35. PromoteExpr,
  36. RevealExpr,
  37. SetComprehension,
  38. SetExpr,
  39. SliceExpr,
  40. StarExpr,
  41. StrExpr,
  42. SuperExpr,
  43. TempNode,
  44. TupleExpr,
  45. TypeAliasExpr,
  46. TypeApplication,
  47. TypedDictExpr,
  48. TypeVarExpr,
  49. TypeVarTupleExpr,
  50. UnaryExpr,
  51. Var,
  52. YieldExpr,
  53. YieldFromExpr,
  54. )
  55. from mypy.visitor import ExpressionVisitor
  56. # [Note Literals and literal_hash]
  57. # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  58. #
  59. # Mypy uses the term "literal" to refer to any expression built out of
  60. # the following:
  61. #
  62. # * Plain literal expressions, like `1` (integer, float, string, etc.)
  63. #
  64. # * Compound literal expressions, like `(lit1, lit2)` (list, dict,
  65. # set, or tuple)
  66. #
  67. # * Operator expressions, like `lit1 + lit2`
  68. #
  69. # * Variable references, like `x`
  70. #
  71. # * Member references, like `lit.m`
  72. #
  73. # * Index expressions, like `lit[0]`
  74. #
  75. # A typical "literal" looks like `x[(i,j+1)].m`.
  76. #
  77. # An expression that is a literal has a `literal_hash`, with the
  78. # following properties.
  79. #
  80. # * `literal_hash` is a Key: a tuple containing basic data types and
  81. # possibly other Keys. So it can be used as a key in a dictionary
  82. # that will be compared by value (as opposed to the Node itself,
  83. # which is compared by identity).
  84. #
  85. # * Two expressions have equal `literal_hash`es if and only if they
  86. # are syntactically equal expressions. (NB: Actually, we also
  87. # identify as equal expressions like `3` and `3.0`; is this a good
  88. # idea?)
  89. #
  90. # * The elements of `literal_hash` that are tuples are exactly the
  91. # subexpressions of the original expression (e.g. the base and index
  92. # of an index expression, or the operands of an operator expression).
  93. def literal(e: Expression) -> int:
  94. if isinstance(e, ComparisonExpr):
  95. return min(literal(o) for o in e.operands)
  96. elif isinstance(e, OpExpr):
  97. return min(literal(e.left), literal(e.right))
  98. elif isinstance(e, (MemberExpr, UnaryExpr, StarExpr)):
  99. return literal(e.expr)
  100. elif isinstance(e, AssignmentExpr):
  101. return literal(e.target)
  102. elif isinstance(e, IndexExpr):
  103. if literal(e.index) == LITERAL_YES:
  104. return literal(e.base)
  105. else:
  106. return LITERAL_NO
  107. elif isinstance(e, NameExpr):
  108. if isinstance(e.node, Var) and e.node.is_final and e.node.final_value is not None:
  109. return LITERAL_YES
  110. return LITERAL_TYPE
  111. if isinstance(e, (IntExpr, FloatExpr, ComplexExpr, StrExpr, BytesExpr)):
  112. return LITERAL_YES
  113. if literal_hash(e):
  114. return LITERAL_YES
  115. return LITERAL_NO
  116. Key: _TypeAlias = Tuple[Any, ...]
  117. def subkeys(key: Key) -> Iterable[Key]:
  118. return [elt for elt in key if isinstance(elt, tuple)]
  119. def literal_hash(e: Expression) -> Key | None:
  120. return e.accept(_hasher)
  121. def extract_var_from_literal_hash(key: Key) -> Var | None:
  122. """If key refers to a Var node, return it.
  123. Return None otherwise.
  124. """
  125. if len(key) == 2 and key[0] == "Var" and isinstance(key[1], Var):
  126. return key[1]
  127. return None
  128. class _Hasher(ExpressionVisitor[Optional[Key]]):
  129. def visit_int_expr(self, e: IntExpr) -> Key:
  130. return ("Literal", e.value)
  131. def visit_str_expr(self, e: StrExpr) -> Key:
  132. return ("Literal", e.value)
  133. def visit_bytes_expr(self, e: BytesExpr) -> Key:
  134. return ("Literal", e.value)
  135. def visit_float_expr(self, e: FloatExpr) -> Key:
  136. return ("Literal", e.value)
  137. def visit_complex_expr(self, e: ComplexExpr) -> Key:
  138. return ("Literal", e.value)
  139. def visit_star_expr(self, e: StarExpr) -> Key:
  140. return ("Star", literal_hash(e.expr))
  141. def visit_name_expr(self, e: NameExpr) -> Key:
  142. if isinstance(e.node, Var) and e.node.is_final and e.node.final_value is not None:
  143. return ("Literal", e.node.final_value)
  144. # N.B: We use the node itself as the key, and not the name,
  145. # because using the name causes issues when there is shadowing
  146. # (for example, in list comprehensions).
  147. return ("Var", e.node)
  148. def visit_member_expr(self, e: MemberExpr) -> Key:
  149. return ("Member", literal_hash(e.expr), e.name)
  150. def visit_op_expr(self, e: OpExpr) -> Key:
  151. return ("Binary", e.op, literal_hash(e.left), literal_hash(e.right))
  152. def visit_comparison_expr(self, e: ComparisonExpr) -> Key:
  153. rest: tuple[str | Key | None, ...] = tuple(e.operators)
  154. rest += tuple(literal_hash(o) for o in e.operands)
  155. return ("Comparison",) + rest
  156. def visit_unary_expr(self, e: UnaryExpr) -> Key:
  157. return ("Unary", e.op, literal_hash(e.expr))
  158. def seq_expr(self, e: ListExpr | TupleExpr | SetExpr, name: str) -> Key | None:
  159. if all(literal(x) == LITERAL_YES for x in e.items):
  160. rest: tuple[Key | None, ...] = tuple(literal_hash(x) for x in e.items)
  161. return (name,) + rest
  162. return None
  163. def visit_list_expr(self, e: ListExpr) -> Key | None:
  164. return self.seq_expr(e, "List")
  165. def visit_dict_expr(self, e: DictExpr) -> Key | None:
  166. if all(a and literal(a) == literal(b) == LITERAL_YES for a, b in e.items):
  167. rest: tuple[Key | None, ...] = tuple(
  168. (literal_hash(a) if a else None, literal_hash(b)) for a, b in e.items
  169. )
  170. return ("Dict",) + rest
  171. return None
  172. def visit_tuple_expr(self, e: TupleExpr) -> Key | None:
  173. return self.seq_expr(e, "Tuple")
  174. def visit_set_expr(self, e: SetExpr) -> Key | None:
  175. return self.seq_expr(e, "Set")
  176. def visit_index_expr(self, e: IndexExpr) -> Key | None:
  177. if literal(e.index) == LITERAL_YES:
  178. return ("Index", literal_hash(e.base), literal_hash(e.index))
  179. return None
  180. def visit_assignment_expr(self, e: AssignmentExpr) -> Key | None:
  181. return literal_hash(e.target)
  182. def visit_call_expr(self, e: CallExpr) -> None:
  183. return None
  184. def visit_slice_expr(self, e: SliceExpr) -> None:
  185. return None
  186. def visit_cast_expr(self, e: CastExpr) -> None:
  187. return None
  188. def visit_assert_type_expr(self, e: AssertTypeExpr) -> None:
  189. return None
  190. def visit_conditional_expr(self, e: ConditionalExpr) -> None:
  191. return None
  192. def visit_ellipsis(self, e: EllipsisExpr) -> None:
  193. return None
  194. def visit_yield_from_expr(self, e: YieldFromExpr) -> None:
  195. return None
  196. def visit_yield_expr(self, e: YieldExpr) -> None:
  197. return None
  198. def visit_reveal_expr(self, e: RevealExpr) -> None:
  199. return None
  200. def visit_super_expr(self, e: SuperExpr) -> None:
  201. return None
  202. def visit_type_application(self, e: TypeApplication) -> None:
  203. return None
  204. def visit_lambda_expr(self, e: LambdaExpr) -> None:
  205. return None
  206. def visit_list_comprehension(self, e: ListComprehension) -> None:
  207. return None
  208. def visit_set_comprehension(self, e: SetComprehension) -> None:
  209. return None
  210. def visit_dictionary_comprehension(self, e: DictionaryComprehension) -> None:
  211. return None
  212. def visit_generator_expr(self, e: GeneratorExpr) -> None:
  213. return None
  214. def visit_type_var_expr(self, e: TypeVarExpr) -> None:
  215. return None
  216. def visit_paramspec_expr(self, e: ParamSpecExpr) -> None:
  217. return None
  218. def visit_type_var_tuple_expr(self, e: TypeVarTupleExpr) -> None:
  219. return None
  220. def visit_type_alias_expr(self, e: TypeAliasExpr) -> None:
  221. return None
  222. def visit_namedtuple_expr(self, e: NamedTupleExpr) -> None:
  223. return None
  224. def visit_enum_call_expr(self, e: EnumCallExpr) -> None:
  225. return None
  226. def visit_typeddict_expr(self, e: TypedDictExpr) -> None:
  227. return None
  228. def visit_newtype_expr(self, e: NewTypeExpr) -> None:
  229. return None
  230. def visit__promote_expr(self, e: PromoteExpr) -> None:
  231. return None
  232. def visit_await_expr(self, e: AwaitExpr) -> None:
  233. return None
  234. def visit_temp_node(self, e: TempNode) -> None:
  235. return None
  236. _hasher: Final = _Hasher()