tpy-lang 0.3.0.dev0__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.
Files changed (333) hide show
  1. tpy_lang-0.3.0.dev0.dist-info/METADATA +151 -0
  2. tpy_lang-0.3.0.dev0.dist-info/RECORD +333 -0
  3. tpy_lang-0.3.0.dev0.dist-info/WHEEL +4 -0
  4. tpy_lang-0.3.0.dev0.dist-info/entry_points.txt +3 -0
  5. tpyc/__init__.py +104 -0
  6. tpyc/__main__.py +6 -0
  7. tpyc/_buildinfo.py +1 -0
  8. tpyc/_data/docs/LANGUAGE_FEATURES.md +6278 -0
  9. tpyc/_data/docs/STDLIB_ROADMAP.md +1258 -0
  10. tpyc/_data/docs/TPY_FOR_AGENTS.md +556 -0
  11. tpyc/_data/lib/tpy/_bindings/__init__.py +6 -0
  12. tpyc/_data/lib/tpy/_bindings/pcre2.py +173 -0
  13. tpyc/_data/lib/tpy/_bindings/posix_socket.py +161 -0
  14. tpyc/_data/lib/tpy/_functools_macros.py +80 -0
  15. tpyc/_data/lib/tpy/_macro_helpers.py +161 -0
  16. tpyc/_data/lib/tpy/argparse.py +2062 -0
  17. tpyc/_data/lib/tpy/asyncio/__init__.py +744 -0
  18. tpyc/_data/lib/tpy/asyncio/_executor.py +515 -0
  19. tpyc/_data/lib/tpy/base64.py +410 -0
  20. tpyc/_data/lib/tpy/bisect.py +39 -0
  21. tpyc/_data/lib/tpy/builtins.py +38 -0
  22. tpyc/_data/lib/tpy/dataclasses.py +354 -0
  23. tpyc/_data/lib/tpy/enum.py +23 -0
  24. tpyc/_data/lib/tpy/functools.py +33 -0
  25. tpyc/_data/lib/tpy/hashlib.py +206 -0
  26. tpyc/_data/lib/tpy/heapq.py +118 -0
  27. tpyc/_data/lib/tpy/io.py +395 -0
  28. tpyc/_data/lib/tpy/json.py +221 -0
  29. tpyc/_data/lib/tpy/math.py +406 -0
  30. tpyc/_data/lib/tpy/random.py +597 -0
  31. tpyc/_data/lib/tpy/re.py +467 -0
  32. tpyc/_data/lib/tpy/socket.py +379 -0
  33. tpyc/_data/lib/tpy/struct.py +178 -0
  34. tpyc/_data/lib/tpy/sys.py +40 -0
  35. tpyc/_data/lib/tpy/time.py +39 -0
  36. tpyc/_data/lib/tpy/tpy/__init__.py +78 -0
  37. tpyc/_data/lib/tpy/tpy/_bootstrap/__init__.py +10 -0
  38. tpyc/_data/lib/tpy/tpy/_bootstrap/_decorators.py +37 -0
  39. tpyc/_data/lib/tpy/tpy/_bootstrap/_extern.py +64 -0
  40. tpyc/_data/lib/tpy/tpy/_builtins/__init__.py +11 -0
  41. tpyc/_data/lib/tpy/tpy/_builtins/_bytes.py +378 -0
  42. tpyc/_data/lib/tpy/tpy/_builtins/_dict.py +151 -0
  43. tpyc/_data/lib/tpy/tpy/_builtins/_exceptions.py +125 -0
  44. tpyc/_data/lib/tpy/tpy/_builtins/_funcs.py +681 -0
  45. tpyc/_data/lib/tpy/tpy/_builtins/_io.py +97 -0
  46. tpyc/_data/lib/tpy/tpy/_builtins/_list.py +127 -0
  47. tpyc/_data/lib/tpy/tpy/_builtins/_range.py +52 -0
  48. tpyc/_data/lib/tpy/tpy/_builtins/_set.py +139 -0
  49. tpyc/_data/lib/tpy/tpy/_builtins/_super.py +11 -0
  50. tpyc/_data/lib/tpy/tpy/_builtins/_types.py +661 -0
  51. tpyc/_data/lib/tpy/tpy/_core/__init__.py +23 -0
  52. tpyc/_data/lib/tpy/tpy/_core/_bytes_view.py +129 -0
  53. tpyc/_data/lib/tpy/tpy/_core/_containers.py +137 -0
  54. tpyc/_data/lib/tpy/tpy/_core/_functions.py +40 -0
  55. tpyc/_data/lib/tpy/tpy/_core/_types.py +2061 -0
  56. tpyc/_data/lib/tpy/tpy/_typing/__init__.py +77 -0
  57. tpyc/_data/lib/tpy/tpy/_version.py +29 -0
  58. tpyc/_data/lib/tpy/tpy/bits.py +28 -0
  59. tpyc/_data/lib/tpy/tpy/coro/__init__.py +127 -0
  60. tpyc/_data/lib/tpy/tpy/extern.py +8 -0
  61. tpyc/_data/lib/tpy/tpy/mem.py +49 -0
  62. tpyc/_data/lib/tpy/tpy/unsafe.py +195 -0
  63. tpyc/_data/lib/tpy/tpy/version.py +21 -0
  64. tpyc/_data/lib/tpy/typing.py +13 -0
  65. tpyc/_data/runtime/cpp/include/tpy/any.hpp +461 -0
  66. tpyc/_data/runtime/cpp/include/tpy/as_ostream.hpp +117 -0
  67. tpyc/_data/runtime/cpp/include/tpy/async.hpp +76 -0
  68. tpyc/_data/runtime/cpp/include/tpy/bigint.hpp +1343 -0
  69. tpyc/_data/runtime/cpp/include/tpy/builtins.hpp +400 -0
  70. tpyc/_data/runtime/cpp/include/tpy/bytes_ops.hpp +469 -0
  71. tpyc/_data/runtime/cpp/include/tpy/container_ops.hpp +487 -0
  72. tpyc/_data/runtime/cpp/include/tpy/copy_iter.hpp +82 -0
  73. tpyc/_data/runtime/cpp/include/tpy/core.hpp +558 -0
  74. tpyc/_data/runtime/cpp/include/tpy/dict_ops.hpp +289 -0
  75. tpyc/_data/runtime/cpp/include/tpy/dunder.hpp +750 -0
  76. tpyc/_data/runtime/cpp/include/tpy/dynamic.hpp +44 -0
  77. tpyc/_data/runtime/cpp/include/tpy/enum.hpp +40 -0
  78. tpyc/_data/runtime/cpp/include/tpy/file.hpp +245 -0
  79. tpyc/_data/runtime/cpp/include/tpy/fixed_int.hpp +317 -0
  80. tpyc/_data/runtime/cpp/include/tpy/format.hpp +954 -0
  81. tpyc/_data/runtime/cpp/include/tpy/frame_slot.hpp +120 -0
  82. tpyc/_data/runtime/cpp/include/tpy/generator.hpp +47 -0
  83. tpyc/_data/runtime/cpp/include/tpy/iterable_ops.hpp +122 -0
  84. tpyc/_data/runtime/cpp/include/tpy/itertools.hpp +749 -0
  85. tpyc/_data/runtime/cpp/include/tpy/next_iter.hpp +82 -0
  86. tpyc/_data/runtime/cpp/include/tpy/ordered_map.hpp +518 -0
  87. tpyc/_data/runtime/cpp/include/tpy/ordered_set.hpp +337 -0
  88. tpyc/_data/runtime/cpp/include/tpy/own_iter.hpp +54 -0
  89. tpyc/_data/runtime/cpp/include/tpy/pascal_graph_sdl.hpp +192 -0
  90. tpyc/_data/runtime/cpp/include/tpy/printing.hpp +302 -0
  91. tpyc/_data/runtime/cpp/include/tpy/protocols.hpp +61 -0
  92. tpyc/_data/runtime/cpp/include/tpy/range.hpp +115 -0
  93. tpyc/_data/runtime/cpp/include/tpy/ranges.hpp +212 -0
  94. tpyc/_data/runtime/cpp/include/tpy/set_ops.hpp +265 -0
  95. tpyc/_data/runtime/cpp/include/tpy/slice.hpp +47 -0
  96. tpyc/_data/runtime/cpp/include/tpy/span_iter.hpp +42 -0
  97. tpyc/_data/runtime/cpp/include/tpy/stdlib/math.hpp +41 -0
  98. tpyc/_data/runtime/cpp/include/tpy/stdlib/pcre2_h.hpp +96 -0
  99. tpyc/_data/runtime/cpp/include/tpy/stdlib/random.hpp +25 -0
  100. tpyc/_data/runtime/cpp/include/tpy/stdlib/socket_h.hpp +145 -0
  101. tpyc/_data/runtime/cpp/include/tpy/stdlib/time.hpp +62 -0
  102. tpyc/_data/runtime/cpp/include/tpy/system.hpp +121 -0
  103. tpyc/_data/runtime/cpp/include/tpy/throwable.hpp +55 -0
  104. tpyc/_data/runtime/cpp/include/tpy/tpy.hpp +156 -0
  105. tpyc/_data/runtime/cpp/include/tpy/type_name.hpp +77 -0
  106. tpyc/_data/runtime/cpp/include/tpy/type_traits.hpp +240 -0
  107. tpyc/_data/runtime/cpp/include/tpy/uninit_array_storage.hpp +250 -0
  108. tpyc/_data/runtime/cpp/include/tpy/uninit_heap_storage.hpp +277 -0
  109. tpyc/_data/runtime/cpp/include/tpy/varargs.hpp +174 -0
  110. tpyc/_data/runtime/cpp/include/tpy/variant_ref.hpp +118 -0
  111. tpyc/_data/runtime/cpp/src/stdlib/socket_impl.cpp +104 -0
  112. tpyc/_data/runtime/cpp/third_party/README.md +58 -0
  113. tpyc/_data/runtime/cpp/third_party/pcre2/AUTHORS +36 -0
  114. tpyc/_data/runtime/cpp/third_party/pcre2/CMakeLists.txt +1233 -0
  115. tpyc/_data/runtime/cpp/third_party/pcre2/COPYING +5 -0
  116. tpyc/_data/runtime/cpp/third_party/pcre2/ChangeLog +3097 -0
  117. tpyc/_data/runtime/cpp/third_party/pcre2/HACKING +853 -0
  118. tpyc/_data/runtime/cpp/third_party/pcre2/INSTALL +368 -0
  119. tpyc/_data/runtime/cpp/third_party/pcre2/LICENCE +94 -0
  120. tpyc/_data/runtime/cpp/third_party/pcre2/NEWS +492 -0
  121. tpyc/_data/runtime/cpp/third_party/pcre2/NON-AUTOTOOLS-BUILD +430 -0
  122. tpyc/_data/runtime/cpp/third_party/pcre2/README +956 -0
  123. tpyc/_data/runtime/cpp/third_party/pcre2/cmake/COPYING-CMAKE-SCRIPTS +22 -0
  124. tpyc/_data/runtime/cpp/third_party/pcre2/cmake/FindEditline.cmake +16 -0
  125. tpyc/_data/runtime/cpp/third_party/pcre2/cmake/FindPackageHandleStandardArgs.cmake +58 -0
  126. tpyc/_data/runtime/cpp/third_party/pcre2/cmake/FindReadline.cmake +29 -0
  127. tpyc/_data/runtime/cpp/third_party/pcre2/cmake/pcre2-config-version.cmake.in +15 -0
  128. tpyc/_data/runtime/cpp/third_party/pcre2/cmake/pcre2-config.cmake.in +148 -0
  129. tpyc/_data/runtime/cpp/third_party/pcre2/config-cmake.h.in +56 -0
  130. tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-16.pc.in +13 -0
  131. tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-32.pc.in +13 -0
  132. tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-8.pc.in +13 -0
  133. tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-posix.pc.in +13 -0
  134. tpyc/_data/runtime/cpp/third_party/pcre2/pcre2-config.in +121 -0
  135. tpyc/_data/runtime/cpp/third_party/pcre2/src/config.h +483 -0
  136. tpyc/_data/runtime/cpp/third_party/pcre2/src/config.h.generic +483 -0
  137. tpyc/_data/runtime/cpp/third_party/pcre2/src/config.h.in +460 -0
  138. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2.h +1010 -0
  139. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2.h.generic +1010 -0
  140. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2.h.in +1010 -0
  141. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_auto_possess.c +1371 -0
  142. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_chartables.c +196 -0
  143. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_chartables.c.dist +196 -0
  144. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_chkdint.c +96 -0
  145. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_compile.c +11001 -0
  146. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_config.c +252 -0
  147. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_context.c +510 -0
  148. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_convert.c +1189 -0
  149. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_dfa_match.c +4119 -0
  150. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_dftables.c +297 -0
  151. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_error.c +345 -0
  152. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_extuni.c +162 -0
  153. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_find_bracket.c +219 -0
  154. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_fuzzsupport.c +792 -0
  155. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_internal.h +2084 -0
  156. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_intmodedep.h +940 -0
  157. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_compile.c +14972 -0
  158. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_match.c +200 -0
  159. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_misc.c +234 -0
  160. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_neon_inc.h +354 -0
  161. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_simd_inc.h +2355 -0
  162. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_test.c +2528 -0
  163. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_maketables.c +165 -0
  164. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_match.c +7777 -0
  165. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_match_data.c +185 -0
  166. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_newline.c +243 -0
  167. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ord2utf.c +120 -0
  168. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_pattern_info.c +432 -0
  169. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_printint.c +886 -0
  170. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_script_run.c +344 -0
  171. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_serialize.c +286 -0
  172. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_string_utils.c +237 -0
  173. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_study.c +1915 -0
  174. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_substitute.c +1009 -0
  175. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_substring.c +550 -0
  176. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_tables.c +234 -0
  177. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ucd.c +5460 -0
  178. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ucp.h +396 -0
  179. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ucptables.c +1533 -0
  180. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_valid_utf.c +398 -0
  181. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_xclass.c +308 -0
  182. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2demo.c +497 -0
  183. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2grep.c +4606 -0
  184. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2posix.c +425 -0
  185. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2posix.h +187 -0
  186. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2posix_test.c +209 -0
  187. tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2test.c +9708 -0
  188. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorApple.c +137 -0
  189. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorCore.c +327 -0
  190. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorFreeBSD.c +89 -0
  191. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorPosix.c +62 -0
  192. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorWindows.c +40 -0
  193. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorNetBSD.c +72 -0
  194. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorPosix.c +172 -0
  195. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorPosix.c +141 -0
  196. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorWindows.c +102 -0
  197. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitConfig.h +142 -0
  198. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitConfigCPU.h +188 -0
  199. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitConfigInternal.h +907 -0
  200. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitLir.c +3561 -0
  201. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitLir.h +2466 -0
  202. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeARM_32.c +4636 -0
  203. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeARM_64.c +3491 -0
  204. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeARM_T2_32.c +4302 -0
  205. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeLOONGARCH_64.c +3765 -0
  206. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeMIPS_32.c +472 -0
  207. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeMIPS_64.c +387 -0
  208. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeMIPS_common.c +4259 -0
  209. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativePPC_32.c +485 -0
  210. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativePPC_64.c +719 -0
  211. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativePPC_common.c +3161 -0
  212. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeRISCV_32.c +142 -0
  213. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeRISCV_64.c +222 -0
  214. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeRISCV_common.c +3121 -0
  215. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeS390X.c +4526 -0
  216. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeX86_32.c +1685 -0
  217. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeX86_64.c +1398 -0
  218. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeX86_common.c +5001 -0
  219. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitSerialize.c +516 -0
  220. tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitUtils.c +344 -0
  221. tpyc/_data/runtime/cpp/third_party/pcre2.sources.txt +54 -0
  222. tpyc/_data/runtime/cpp/third_party/pcre2.vendor.json +7 -0
  223. tpyc/build/__init__.py +7 -0
  224. tpyc/build/pcre2.py +122 -0
  225. tpyc/build/third_party.py +413 -0
  226. tpyc/cli.py +822 -0
  227. tpyc/codegen_cpp/__init__.py +18 -0
  228. tpyc/codegen_cpp/builtins.py +484 -0
  229. tpyc/codegen_cpp/context.py +2064 -0
  230. tpyc/codegen_cpp/expressions.py +5940 -0
  231. tpyc/codegen_cpp/functions.py +1913 -0
  232. tpyc/codegen_cpp/gen_async.py +3258 -0
  233. tpyc/codegen_cpp/gen_generators.py +657 -0
  234. tpyc/codegen_cpp/generator.py +2258 -0
  235. tpyc/codegen_cpp/match.py +1997 -0
  236. tpyc/codegen_cpp/param_const.py +172 -0
  237. tpyc/codegen_cpp/protocols.py +907 -0
  238. tpyc/codegen_cpp/records.py +1654 -0
  239. tpyc/codegen_cpp/resumable_cfg.py +1651 -0
  240. tpyc/codegen_cpp/statements.py +4963 -0
  241. tpyc/codegen_cpp/string_dispatch.py +76 -0
  242. tpyc/codegen_cpp/test_context.py +46 -0
  243. tpyc/codegen_cpp/test_param_const.py +113 -0
  244. tpyc/codegen_cpp/test_resumable_cfg.py +182 -0
  245. tpyc/codegen_cpp/type_resolution.py +53 -0
  246. tpyc/codegen_cpp/types.py +436 -0
  247. tpyc/codegen_cpp/variant_access.py +135 -0
  248. tpyc/coercions.py +749 -0
  249. tpyc/compilation_context.py +57 -0
  250. tpyc/compiler.py +3945 -0
  251. tpyc/cycle_detection.py +358 -0
  252. tpyc/diagnostics.py +135 -0
  253. tpyc/dump_types.py +353 -0
  254. tpyc/frontend_diagnostics.py +47 -0
  255. tpyc/frontend_ir/__init__.py +140 -0
  256. tpyc/frontend_ir/lower.py +1098 -0
  257. tpyc/frontend_ir/nodes.py +718 -0
  258. tpyc/frontend_ir/resolver_adapter.py +151 -0
  259. tpyc/frontend_plugin.py +209 -0
  260. tpyc/install_docs.py +81 -0
  261. tpyc/liveness.py +756 -0
  262. tpyc/macro_api.py +1724 -0
  263. tpyc/macro_loader.py +497 -0
  264. tpyc/module_names.py +64 -0
  265. tpyc/modules/__init__.py +31 -0
  266. tpyc/modules/defs.py +89 -0
  267. tpyc/modules/registry.py +36 -0
  268. tpyc/modules/resolver.py +192 -0
  269. tpyc/modules/type_resolution.py +629 -0
  270. tpyc/namespace.py +172 -0
  271. tpyc/parse/__init__.py +84 -0
  272. tpyc/parse/imports.py +490 -0
  273. tpyc/parse/nodes.py +1732 -0
  274. tpyc/parse/parser.py +4043 -0
  275. tpyc/parse/resolve_refs.py +466 -0
  276. tpyc/parse/type_resolver.py +1060 -0
  277. tpyc/prescan.py +254 -0
  278. tpyc/qnames.py +149 -0
  279. tpyc/repl.py +529 -0
  280. tpyc/repl_backends.py +848 -0
  281. tpyc/sema/__init__.py +21 -0
  282. tpyc/sema/analyzer.py +3625 -0
  283. tpyc/sema/bound_check.py +72 -0
  284. tpyc/sema/builder_trace.py +684 -0
  285. tpyc/sema/calls.py +5406 -0
  286. tpyc/sema/compatibility.py +2107 -0
  287. tpyc/sema/context.py +1243 -0
  288. tpyc/sema/expressions.py +3737 -0
  289. tpyc/sema/flow_facts.py +199 -0
  290. tpyc/sema/init_tracker.py +150 -0
  291. tpyc/sema/list_literals.py +69 -0
  292. tpyc/sema/literal_utils.py +27 -0
  293. tpyc/sema/local_deduction.py +1088 -0
  294. tpyc/sema/macros.py +179 -0
  295. tpyc/sema/match.py +1177 -0
  296. tpyc/sema/method_expansion.py +347 -0
  297. tpyc/sema/methods.py +2197 -0
  298. tpyc/sema/mutation_propagation.py +268 -0
  299. tpyc/sema/narrowing.py +857 -0
  300. tpyc/sema/numeric_lattice.py +160 -0
  301. tpyc/sema/operators.py +402 -0
  302. tpyc/sema/overloads.py +841 -0
  303. tpyc/sema/protocols.py +1209 -0
  304. tpyc/sema/reach_analysis.py +202 -0
  305. tpyc/sema/registration.py +3156 -0
  306. tpyc/sema/scope_tracker.py +193 -0
  307. tpyc/sema/statements.py +4426 -0
  308. tpyc/sema/type_ops.py +1879 -0
  309. tpyc/sema/value_range.py +181 -0
  310. tpyc/symbol_binding.py +259 -0
  311. tpyc/test_c3_mro.py +208 -0
  312. tpyc/test_cli_argv.py +52 -0
  313. tpyc/test_compiler.py +559 -0
  314. tpyc/test_contains_type_param.py +101 -0
  315. tpyc/test_cycle_detection.py +221 -0
  316. tpyc/test_dump_types.py +225 -0
  317. tpyc/test_install_docs.py +65 -0
  318. tpyc/test_local_cpp_form.py +135 -0
  319. tpyc/test_macro_loader.py +76 -0
  320. tpyc/test_method_expansion.py +254 -0
  321. tpyc/test_nominal_identity.py +182 -0
  322. tpyc/test_overloads.py +410 -0
  323. tpyc/test_parse.py +303 -0
  324. tpyc/test_parse_type_ref.py +506 -0
  325. tpyc/test_parse_version_info.py +58 -0
  326. tpyc/test_reach_analysis.py +72 -0
  327. tpyc/test_ref_type.py +216 -0
  328. tpyc/test_send_sync_substitution.py +276 -0
  329. tpyc/test_tuple_mutation_propagation.py +206 -0
  330. tpyc/test_type_def_registry.py +1729 -0
  331. tpyc/test_union_types.py +195 -0
  332. tpyc/type_def_registry.py +975 -0
  333. tpyc/typesys.py +5104 -0
tpyc/sema/overloads.py ADDED
@@ -0,0 +1,841 @@
1
+ """
2
+ TurboPython Shared Overload Resolution
3
+
4
+ Unified type matching and overload resolution used across
5
+ operators, calls, methods, and module infrastructure.
6
+ """
7
+
8
+ from __future__ import annotations
9
+ from dataclasses import replace as dc_replace
10
+ from enum import Enum
11
+ from typing import TYPE_CHECKING, Callable
12
+
13
+ from ..typesys import (
14
+ TpyType, IntLiteralType, FloatLiteralType, BIGINT,
15
+ TypeParamRef, TypeParamKind, FunctionInfo, is_protocol_type, unwrap_readonly,
16
+ PendingStrType, PendingViewType, LiteralType, LiteralTag,
17
+ PendingBytesType, TupleType, UnknownElementType,
18
+ NominalType, PtrType, OwnType, ReadonlyType, RefType, CallableType, is_fn_type, VoidType, NoneType,
19
+ OptionalType,
20
+ unwrap_ref_type,
21
+ is_callable_type, is_float_type, is_integer_type, is_any_float_type,
22
+ contains_type_param,
23
+ )
24
+ from ..type_def_registry import (
25
+ is_fixed_int_type, is_big_int_type, is_bool_type,
26
+ is_str_type, is_bytes_type, is_str_category, is_bytes_category,
27
+ int_traits_of,
28
+ )
29
+ from ..coercions import resolve_coercion, CoercionContext
30
+ from .protocols import ProtocolConformanceKind
31
+
32
+ if TYPE_CHECKING:
33
+ from .type_ops import TypeOperations
34
+ ProtocolChecker = Callable[[TpyType, TpyType], bool]
35
+ ProtocolClassifier = Callable[[TpyType, TpyType], 'ProtocolConformanceKind | None']
36
+ DerefChecker = Callable[[TpyType], TpyType | None]
37
+ SubclassChecker = Callable[['NominalType', 'NominalType'], bool]
38
+
39
+
40
+ class MatchTier(Enum):
41
+ """Specificity of a strict-pass overload match.
42
+
43
+ The integer ``value`` is the rank (lower = more specific) and doubles as
44
+ an index into the per-tier count array in ``_score``. Not an ``IntEnum``
45
+ so that stray int arithmetic or ``tier == 1`` comparisons don't silently
46
+ type-check.
47
+ """
48
+ EXACT_CONCRETE = 1 # arg_inner == param_inner (or nominal-adjacent: IntLit->FixedInt, NoneType->Void, Callable->Fn, ...)
49
+ EXACT_GENERIC_SHAPE = 2 # generic param with concrete outer shape: list[T] vs list[Int32]
50
+ PROTOCOL_EXPLICIT = 3 # protocol conformance via classify_protocol_conformance -> EXPLICIT
51
+ PROTOCOL_STRUCTURAL = 4 # protocol conformance via classify_protocol_conformance -> STRUCTURAL
52
+ GENERIC_PROTOCOL_EXPLICIT = 5 # generic over protocol param, explicit conformance
53
+ GENERIC_PROTOCOL_STRUCTURAL = 6 # generic over protocol param, structural conformance
54
+ GENERIC_WILDCARD = 7 # bare T / unconstrained generic
55
+
56
+
57
+ _NUM_MATCH_TIERS = len(MatchTier)
58
+
59
+
60
+ # MatchTier enum is 1-indexed (EXACT_CONCRETE = 1), so score vectors drop slot 0.
61
+ _TIER_COUNTS_SIZE = _NUM_MATCH_TIERS + 1
62
+
63
+
64
+ class OverloadAmbiguityError(Exception):
65
+ """Raised by ``resolve_overload`` when multiple candidates tie at the top
66
+ of first-pass ranking (same tier counts, same widening cost, distinct
67
+ signatures).
68
+
69
+ Callers with source-location context should catch this and re-raise as a
70
+ proper ``SemanticError`` so the user sees the call site, not a bare
71
+ traceback. Uncaught, the exception still carries the tied candidates so
72
+ the default message is actionable.
73
+ """
74
+ def __init__(self, candidates: tuple[FunctionInfo, ...]):
75
+ self.candidates = candidates
76
+ sigs = ", ".join(
77
+ f"{c.name}({', '.join(str(p.type) for p in c.params)})"
78
+ for c in candidates
79
+ )
80
+ super().__init__(f"Ambiguous overload: {sigs}")
81
+
82
+
83
+ def _always_false_checker(arg: 'TpyType', param: 'TpyType') -> bool:
84
+ return False
85
+
86
+
87
+ def _score(per_arg: tuple[tuple[MatchTier, int], ...]) -> tuple[tuple[int, ...], int]:
88
+ """Score a per-arg tier vector: lower is better.
89
+
90
+ Primary key is aggregate tier counts (higher tier-count at the strongest
91
+ tier wins); secondary key is total widening cost so same-tier candidates
92
+ prefer the narrowest widening.
93
+ """
94
+ counts = [0] * _TIER_COUNTS_SIZE
95
+ total_cost = 0
96
+ for tier, cost in per_arg:
97
+ counts[tier.value] += 1
98
+ total_cost += cost
99
+ return (tuple(-c for c in counts[1:]), total_cost)
100
+
101
+
102
+ def _structural_match(arg: TpyType, param: TpyType) -> bool:
103
+ """Structural match with TypeParamRef as wildcard."""
104
+ if isinstance(param, TypeParamRef):
105
+ return True
106
+ # Unwrap Ref, Own, Readonly from both sides (transparent for matching)
107
+ arg = unwrap_ref_type(arg)
108
+ param = unwrap_ref_type(param)
109
+ if isinstance(param, TypeParamRef):
110
+ return True
111
+ if isinstance(arg, OwnType):
112
+ arg = arg.wrapped
113
+ if isinstance(param, ReadonlyType):
114
+ return _structural_match(unwrap_readonly(arg), param.wrapped)
115
+ arg = unwrap_readonly(arg)
116
+ # Callable -> Fn: structurally compatible callable types
117
+ if isinstance(arg, CallableType) and is_fn_type(param):
118
+ if len(arg.param_types) != len(param.param_types):
119
+ return False
120
+ return (all(_structural_match(a, p) for a, p in zip(arg.param_types, param.param_types))
121
+ and _structural_match(arg.return_type, param.return_type))
122
+ # None literal (NoneType) matches None annotation (VoidType)
123
+ if isinstance(arg, NoneType) and isinstance(param, VoidType):
124
+ return True
125
+ if type(arg) != type(param):
126
+ return False
127
+ # Post-Phase-D all containers/primitives/records are NominalType; type()
128
+ # equality alone passes list[Int32] vs set[Int32]. Require matching name
129
+ # so structural recursion only fires for same-kind NominalType pairs.
130
+ if isinstance(arg, NominalType) and arg.name != param.name:
131
+ return False
132
+ # PtrType: readonly arg cannot match mutable param (would drop const)
133
+ if isinstance(arg, PtrType) and isinstance(param, PtrType):
134
+ if arg.is_readonly and not param.is_readonly:
135
+ return False
136
+ arg_inners = list(arg.inner_types())
137
+ param_inners = list(param.inner_types())
138
+ if len(arg_inners) != len(param_inners):
139
+ return False
140
+ if not arg_inners:
141
+ return arg == param
142
+ return all(_structural_match(a, p) for a, p in zip(arg_inners, param_inners))
143
+
144
+
145
+ def _scalar_widening_cost(
146
+ actual: TpyType,
147
+ expected: TpyType,
148
+ default_int_type: TpyType | None = None,
149
+ ) -> int:
150
+ """Cost of widening ``actual`` to ``expected`` for a single type slot.
151
+
152
+ Returns 0 when the types are identical and a positive distance when
153
+ ``actual`` widens to ``expected``. Used as a secondary sort key inside a
154
+ match tier so that e.g. ``list[Int32]`` prefers ``Iterable[Int32]`` over
155
+ ``Iterable[Int64]`` / ``Iterable[int]`` / ``Iterable[float]``.
156
+
157
+ ``IntLiteralType`` ranks as the ``default_int_type`` would (so a list of
158
+ ``int`` literals under ``default_int=Int32`` scores ``Iterable[Int32]``
159
+ exactly like ``list[Int32]`` does). When ``default_int_type`` is None,
160
+ IntLiteral comparisons fall back to the generic cross-type distance.
161
+ """
162
+ if actual == expected:
163
+ return 0
164
+ # IntLiteralType and UnknownElementType (empty-list literal): compute cost
165
+ # as if widening from default_int_type. This matches the CPython
166
+ # convention that ``sum([]) == 0`` (int) regardless of which numeric
167
+ # overload is declared first in the stdlib.
168
+ if isinstance(actual, (IntLiteralType, UnknownElementType)):
169
+ if default_int_type is None:
170
+ return 1
171
+ if expected == default_int_type:
172
+ return 0
173
+ return _scalar_widening_cost(default_int_type, expected, default_int_type)
174
+ a_tr = int_traits_of(actual)
175
+ e_tr = int_traits_of(expected)
176
+ if a_tr is not None and e_tr is not None:
177
+ # Fixed-int -> fixed-int: bit-width gap, plus a small sign-flip penalty
178
+ # so e.g. Int32 -> Int64 beats Int32 -> UInt64.
179
+ gap = max(0, (e_tr.bits - a_tr.bits)) // 8
180
+ sign_penalty = 1 if a_tr.signed != e_tr.signed else 0
181
+ return max(1, gap) + sign_penalty
182
+ if a_tr is not None and is_big_int_type(expected):
183
+ return 8
184
+ if a_tr is not None and is_any_float_type(expected):
185
+ return 16
186
+ if is_any_float_type(actual) and is_any_float_type(expected):
187
+ return 1
188
+ # Unknown shape -- treat as a single widening step.
189
+ return 1
190
+
191
+
192
+ def _type_args_widening_cost(
193
+ actual: TpyType,
194
+ param: NominalType,
195
+ default_int_type: TpyType | None = None,
196
+ ) -> int:
197
+ """Aggregate widening cost between ``actual``'s and ``param``'s type args.
198
+
199
+ Caller has already confirmed ``actual`` conforms to ``param``. Walks the
200
+ type-arg tuples pairwise when they line up; for single-element protocols
201
+ also falls back to ``actual.get_element_type()`` so non-parameterised
202
+ containers (``bytes``/``bytearray`` -> ``Iterable[UInt8]``) can be scored
203
+ by their baked-in element type. Returns 0 when no type-arg information
204
+ is available.
205
+ """
206
+ if not isinstance(param, NominalType) or not param.type_args:
207
+ return 0
208
+ actual_args: tuple[TpyType, ...] = ()
209
+ if isinstance(actual, NominalType):
210
+ actual_args = tuple(a for a in actual.type_args if isinstance(a, TpyType))
211
+ elif isinstance(actual, TupleType):
212
+ # Tuples collapse to a protocol over a single element type only when
213
+ # all elements are identical; otherwise element-level widening is
214
+ # not well-defined here.
215
+ if actual.element_types and all(t == actual.element_types[0] for t in actual.element_types):
216
+ actual_args = (actual.element_types[0],)
217
+ # Fallback for single-element protocols where the actual's element type
218
+ # isn't directly visible in type_args -- non-parameterised containers
219
+ # (bytes/bytearray -> UInt8) and PendingListType expose it via
220
+ # get_element_type().
221
+ if not actual_args and len(param.type_args) == 1 and hasattr(actual, 'get_element_type'):
222
+ elem = actual.get_element_type()
223
+ if elem is not None:
224
+ actual_args = (elem,)
225
+ if len(actual_args) != len(param.type_args):
226
+ return 0
227
+ total = 0
228
+ for a, p in zip(actual_args, param.type_args):
229
+ if not isinstance(p, TpyType):
230
+ continue
231
+ total += _scalar_widening_cost(a, p, default_int_type)
232
+ return total
233
+
234
+
235
+ def _classify_strict_match(
236
+ arg_type: TpyType,
237
+ param_type: TpyType,
238
+ protocol_classifier: ProtocolClassifier | None = None,
239
+ default_int_type: TpyType | None = None,
240
+ ) -> tuple[MatchTier, int] | None:
241
+ """Strict (no-coercion) match with specificity tier + widening cost.
242
+
243
+ Returns ``(tier, cost)`` on success, ``None`` otherwise. ``cost`` is 0
244
+ for exact element-type matches and grows with widening distance (used as
245
+ a secondary sort key by ``resolve_overload_result``).
246
+ """
247
+ # Unwrap ReadonlyType, OwnType, RefType -- these are ownership/ref
248
+ # qualifiers transparent for overload matching.
249
+ arg_inner = unwrap_ref_type(unwrap_readonly(arg_type))
250
+ if isinstance(arg_inner, OwnType):
251
+ arg_inner = arg_inner.wrapped
252
+ param_inner = unwrap_ref_type(unwrap_readonly(param_type))
253
+ if isinstance(param_inner, OwnType):
254
+ param_inner = param_inner.wrapped
255
+ if arg_inner == param_inner:
256
+ return (MatchTier.EXACT_CONCRETE, 0)
257
+ # CallableType (Fn and Callable): compare with qualifier unwrapping on inner
258
+ # types. The arg callable may have Own/Ref on param/return types from FI,
259
+ # while the resolved overload's callable has bare types from substitution.
260
+ if (is_callable_type(arg_inner)
261
+ and is_callable_type(param_inner)
262
+ and len(arg_inner.param_types) == len(param_inner.param_types)):
263
+ def _strip(t: TpyType) -> TpyType:
264
+ t = unwrap_ref_type(t)
265
+ if isinstance(t, OwnType): t = t.wrapped
266
+ if isinstance(t, PendingViewType): t = t.family.owned_type
267
+ return t
268
+ if (all(_strip(a) == _strip(p) for a, p in zip(arg_inner.param_types, param_inner.param_types))
269
+ and _strip(arg_inner.return_type) == _strip(param_inner.return_type)):
270
+ return (MatchTier.EXACT_CONCRETE, 0)
271
+ # IntLiteralType matches the specific fixed-width int it was inferred to (from
272
+ # generic resolution). This allows resolved-generic overloads like
273
+ # range(stop: Int32) to match IntLiteralType(5) in the first pass.
274
+ # Cost ranks by widening distance from default_int_type so str(IntLiteralType)
275
+ # picks the default-width overload (Int32) over the smallest-fitting one
276
+ # (Int8) when multiple fixed-int overloads accept the value.
277
+ if isinstance(arg_inner, IntLiteralType) and is_fixed_int_type(param_inner):
278
+ tr = int_traits_of(param_inner)
279
+ if arg_inner.value is None or tr.min_value <= arg_inner.value <= tr.max_value:
280
+ return (MatchTier.EXACT_CONCRETE,
281
+ _scalar_widening_cost(arg_inner, param_inner, default_int_type))
282
+ # None literal (NoneType) matches None type annotation (VoidType)
283
+ if isinstance(arg_inner, NoneType) and isinstance(param_inner, VoidType):
284
+ return (MatchTier.EXACT_CONCRETE, 0)
285
+ # T -> Optional[T] and None -> Optional[T]
286
+ if isinstance(param_inner, OptionalType):
287
+ if isinstance(arg_inner, NoneType):
288
+ return (MatchTier.EXACT_CONCRETE, 0)
289
+ return _classify_strict_match(arg_inner, param_inner.inner, protocol_classifier, default_int_type)
290
+ # Callable -> Fn: std::function satisfies template requires clauses
291
+ if (isinstance(arg_inner, CallableType) and is_fn_type(param_inner)
292
+ and arg_inner.param_types == param_inner.param_types
293
+ and (arg_inner.return_type == param_inner.return_type
294
+ or isinstance(param_inner.return_type, VoidType))):
295
+ return (MatchTier.EXACT_CONCRETE, 0)
296
+ # PendingViewType: same-family pending types match each other and their resolved types
297
+ if isinstance(arg_inner, PendingViewType) and isinstance(param_inner, PendingViewType):
298
+ if arg_inner.family is param_inner.family:
299
+ return (MatchTier.EXACT_CONCRETE, 0)
300
+ if isinstance(arg_inner, PendingStrType) and is_str_type(param_inner):
301
+ return (MatchTier.EXACT_CONCRETE, 0)
302
+ # Single-value LiteralType matches multi-value LiteralType if value is in the set.
303
+ # Only in strict pass -- LiteralType -> base type is deferred to coercion pass
304
+ # so that Literal stubs are preferred over plain stubs regardless of order.
305
+ if isinstance(arg_inner, LiteralType) and isinstance(param_inner, LiteralType):
306
+ return ((MatchTier.EXACT_CONCRETE, 0)
307
+ if all(v in param_inner.values for v in arg_inner.values) else None)
308
+ # IntLiteralType matches LiteralType with int base if value is in the set.
309
+ if isinstance(arg_inner, IntLiteralType) and isinstance(param_inner, LiteralType) and param_inner.is_int_base():
310
+ if arg_inner.value is not None and param_inner.contains(LiteralTag.INT, arg_inner.value):
311
+ return (MatchTier.EXACT_CONCRETE, 0)
312
+ return None
313
+ # PendingBytesType (unresolved bytes local) matches bytes params
314
+ if isinstance(arg_inner, PendingBytesType) and is_bytes_type(param_inner):
315
+ return (MatchTier.EXACT_CONCRETE, 0)
316
+ if protocol_classifier is not None and is_protocol_type(param_inner):
317
+ # Unwrap Own[T] from arg -- copy()-wrapped return values should still match
318
+ # plain protocol params (Own is a caller-side ownership marker, not a new type).
319
+ check_arg = arg_inner.wrapped if isinstance(arg_inner, OwnType) else arg_inner
320
+ # Strip Own[T] wrappers from protocol type args so that e.g.
321
+ # list[Node] matches Iterable[Own[Node]] for protocol conformance.
322
+ check_param = param_inner
323
+ if (isinstance(param_inner, NominalType) and param_inner.type_args
324
+ and any(isinstance(a, OwnType) for a in param_inner.type_args)):
325
+ stripped = tuple(a.wrapped if isinstance(a, OwnType) else a for a in param_inner.type_args)
326
+ check_param = dc_replace(param_inner, type_args=stripped)
327
+ kind = protocol_classifier(check_arg, check_param)
328
+ if kind is ProtocolConformanceKind.EXPLICIT:
329
+ return (MatchTier.PROTOCOL_EXPLICIT,
330
+ _type_args_widening_cost(check_arg, check_param, default_int_type))
331
+ if kind is ProtocolConformanceKind.STRUCTURAL:
332
+ return (MatchTier.PROTOCOL_STRUCTURAL, 0)
333
+ return None
334
+ # Non-protocol NominalType with Own[T] in type args: strip Own for overload matching.
335
+ # Applies to any concrete container (e.g. dict[K, Own[V]]) not just DictType.
336
+ # Copy warnings are emitted later by check_type_compatible.
337
+ if (isinstance(param_inner, NominalType) and not is_protocol_type(param_inner)
338
+ and any(isinstance(a, OwnType) for a in param_inner.inner_types())):
339
+ stripped_inner = tuple(a.wrapped if isinstance(a, OwnType) else a for a in param_inner.inner_types())
340
+ stripped_param = param_inner.with_inner_types(stripped_inner)
341
+ return (MatchTier.EXACT_CONCRETE, 0) if arg_inner == stripped_param else None
342
+ return None
343
+
344
+
345
+ def _bool_checker_to_classifier(
346
+ protocol_checker: ProtocolChecker | None,
347
+ ) -> ProtocolClassifier | None:
348
+ """Wrap a bool ``protocol_checker`` as a classifier.
349
+
350
+ Callers outside ``resolve_overload`` only have the bool API; conservatively
351
+ report STRUCTURAL on a hit so tier info is never fabricated as EXPLICIT.
352
+ """
353
+ if protocol_checker is None:
354
+ return None
355
+ def _adapter(arg: TpyType, param: TpyType) -> ProtocolConformanceKind | None:
356
+ return ProtocolConformanceKind.STRUCTURAL if protocol_checker(arg, param) else None
357
+ return _adapter
358
+
359
+
360
+ def type_matches_strict(
361
+ arg_type: TpyType,
362
+ param_type: TpyType,
363
+ protocol_checker: ProtocolChecker | None = None,
364
+ ) -> bool:
365
+ """Strict type matching: exact equality or protocol conformance.
366
+
367
+ Used for first-pass overload resolution where no coercions are desired.
368
+ """
369
+ result = _classify_strict_match(
370
+ arg_type, param_type, _bool_checker_to_classifier(protocol_checker)
371
+ )
372
+ return result is not None
373
+
374
+
375
+ def _classify_generic_param_match(
376
+ param_type: TpyType,
377
+ arg_type: TpyType,
378
+ inferred: dict[str, TpyType],
379
+ type_ops: 'TypeOperations',
380
+ protocol_classifier: ProtocolClassifier | None,
381
+ default_int_type: TpyType | None = None,
382
+ ) -> tuple[MatchTier, int]:
383
+ """Tier + widening cost for a generic-overload param with ``TypeParamRef``.
384
+
385
+ Must be called only for params where ``contains_type_param(param_type)``
386
+ is True and ``infer_type_params_for_function`` has already succeeded for the
387
+ whole overload (guaranteeing this param's own inference consistency).
388
+
389
+ Shape taxonomy:
390
+ - Bare ``TypeParamRef`` (possibly wrapped in Ref/Readonly) -> GENERIC_WILDCARD.
391
+ - Protocol with ``TypeParamRef`` in type args -> GENERIC_PROTOCOL_EXPLICIT
392
+ or GENERIC_PROTOCOL_STRUCTURAL (fall back to STRUCTURAL if no classifier).
393
+ - Anything else (concrete outer shape: ``list[T]``, ``tuple[T, T]``,
394
+ ``Ptr[T]``, user record with T slot, ...) -> EXACT_GENERIC_SHAPE.
395
+
396
+ Cost is 0 except for protocol matches where arg type args widen to the
397
+ substituted protocol type args.
398
+ """
399
+ inspect = param_type
400
+ while isinstance(inspect, (RefType, ReadonlyType)):
401
+ inspect = inspect.wrapped
402
+ if isinstance(inspect, TypeParamRef):
403
+ return (MatchTier.GENERIC_WILDCARD, 0)
404
+ if is_protocol_type(inspect) and contains_type_param(inspect):
405
+ substituted = type_ops.substitute_types(inspect, inferred)
406
+ check_arg = unwrap_ref_type(unwrap_readonly(arg_type))
407
+ if isinstance(check_arg, OwnType):
408
+ check_arg = check_arg.wrapped
409
+ if protocol_classifier is not None and is_protocol_type(substituted):
410
+ kind = protocol_classifier(check_arg, substituted)
411
+ if kind is ProtocolConformanceKind.EXPLICIT:
412
+ return (MatchTier.GENERIC_PROTOCOL_EXPLICIT,
413
+ _type_args_widening_cost(check_arg, substituted, default_int_type))
414
+ if kind is ProtocolConformanceKind.STRUCTURAL:
415
+ return (MatchTier.GENERIC_PROTOCOL_STRUCTURAL, 0)
416
+ return (MatchTier.GENERIC_PROTOCOL_STRUCTURAL, 0)
417
+ return (MatchTier.EXACT_GENERIC_SHAPE, 0)
418
+
419
+
420
+ def type_matches_numeric(
421
+ arg_type: TpyType,
422
+ param_type: TpyType,
423
+ ) -> bool:
424
+ """Type matching for numeric operators and constructors.
425
+
426
+ Handles IntLiteralType and TypeParamRef(INT) flexibility without
427
+ triggering general type coercions (e.g., Int32->BigInt promotion).
428
+
429
+ - Exact equality
430
+ - IntLiteralType matches IntLiteralType, any fixed-width int, BigInt, float, or Float32
431
+ - INT TypeParamRef matches any fixed-width int or BigInt
432
+ """
433
+ if arg_type == param_type:
434
+ return True
435
+ if isinstance(arg_type, IntLiteralType):
436
+ if is_fixed_int_type(param_type):
437
+ if arg_type.value is None:
438
+ return True # Unknown value -- can't range-check, allow match
439
+ tr = int_traits_of(param_type)
440
+ return tr.min_value <= arg_type.value <= tr.max_value
441
+ if is_big_int_type(param_type) or isinstance(param_type, IntLiteralType):
442
+ return True
443
+ if is_float_type(param_type):
444
+ return True
445
+ if isinstance(arg_type, FloatLiteralType):
446
+ if is_any_float_type(param_type):
447
+ return True
448
+ if isinstance(arg_type, TypeParamRef) and arg_type.kind == TypeParamKind.INT:
449
+ if is_integer_type(param_type):
450
+ return True
451
+ # T -> Optional[T]: unwrap Optional param and match inner type
452
+ if isinstance(param_type, OptionalType):
453
+ return type_matches_numeric(arg_type, param_type.inner)
454
+ # Recursive container matching: e.g. make_list(IntLiteralType) vs make_list(Int32).
455
+ # Post-Phase-D all builtin containers share the NominalType class, so also
456
+ # require matching name (list vs set etc. would otherwise both pass type()
457
+ # equality and fall into the element-only check).
458
+ if type(arg_type) == type(param_type):
459
+ if isinstance(arg_type, NominalType):
460
+ if arg_type.name != param_type.name:
461
+ return False
462
+ arg_elem = arg_type.get_element_type()
463
+ param_elem = param_type.get_element_type()
464
+ if arg_elem is not None and param_elem is not None:
465
+ return type_matches_numeric(arg_elem, param_elem)
466
+ return False
467
+
468
+
469
+ def type_matches_with_coercion(
470
+ arg_type: TpyType,
471
+ param_type: TpyType,
472
+ protocol_checker: ProtocolChecker | None = None,
473
+ deref_checker: DerefChecker | None = None,
474
+ subclass_checker: SubclassChecker | None = None,
475
+ ) -> bool:
476
+ """Type matching allowing IntLiteral flexibility, protocols, and registered coercions.
477
+
478
+ Used for overload resolution second pass and constructor matching.
479
+ """
480
+ # Unwrap ReadonlyType, OwnType, RefType from args -- mutable values match
481
+ # readonly params, Own[T] variables match T params, and Ref[T] is transparent.
482
+ arg_inner = unwrap_ref_type(unwrap_readonly(arg_type))
483
+ if isinstance(arg_inner, OwnType):
484
+ arg_inner = arg_inner.wrapped
485
+ param_inner = unwrap_ref_type(unwrap_readonly(param_type))
486
+ # Own[T] param accepts T values (ownership marker, not a distinct type)
487
+ if isinstance(param_inner, OwnType):
488
+ param_inner = param_inner.wrapped
489
+ if type_matches_numeric(arg_inner, param_inner):
490
+ return True
491
+ # None -> Optional[T]
492
+ if isinstance(arg_inner, NoneType) and isinstance(param_inner, OptionalType):
493
+ return True
494
+ # PendingStrType matches any string type (str, String, StrView)
495
+ if isinstance(arg_inner, PendingStrType) and is_str_category(param_inner):
496
+ return True
497
+ # Single-value LiteralType matches multi-value LiteralType if value is in the set
498
+ if isinstance(arg_inner, LiteralType) and isinstance(param_inner, LiteralType):
499
+ return all(v in param_inner.values for v in arg_inner.values)
500
+ # LiteralType falls back to matching its base type
501
+ if isinstance(arg_inner, LiteralType):
502
+ if arg_inner.is_str_base() and is_str_category(param_inner):
503
+ return True
504
+ if arg_inner.is_int_base() and is_integer_type(param_inner):
505
+ return True
506
+ if arg_inner.is_bool_base() and is_bool_type(param_inner):
507
+ return True
508
+ # IntLiteralType matches LiteralType with int base if value is in the set
509
+ if isinstance(arg_inner, IntLiteralType) and isinstance(param_inner, LiteralType) and param_inner.is_int_base():
510
+ if arg_inner.value is not None:
511
+ return param_inner.contains(LiteralTag.INT, arg_inner.value)
512
+ return False
513
+ # PendingBytesType matches any bytes type (bytes, bytearray, BytesView)
514
+ if isinstance(arg_inner, PendingBytesType) and is_bytes_category(param_inner):
515
+ return True
516
+ if protocol_checker and is_protocol_type(param_inner):
517
+ # Unwrap Own[T] -- ownership marker, not a distinct type.
518
+ # Mirrors the unwrapping in type_matches_strict.
519
+ check_arg = arg_inner.wrapped if isinstance(arg_inner, OwnType) else arg_inner
520
+ return protocol_checker(check_arg, param_inner)
521
+ # Callable -> Fn: std::function satisfies template requires clauses
522
+ if (isinstance(arg_inner, CallableType) and is_fn_type(param_inner)
523
+ and arg_inner.param_types == param_inner.param_types
524
+ and (arg_inner.return_type == param_inner.return_type
525
+ or isinstance(param_inner.return_type, VoidType))):
526
+ return True
527
+ if resolve_coercion(arg_inner, param_inner, CoercionContext.ARG) is not None:
528
+ return True
529
+ if deref_checker:
530
+ deref_target = deref_checker(arg_inner)
531
+ if deref_target is not None and deref_target == param_inner:
532
+ return True
533
+ # Inheritance: Child -> Parent (value upcast and pointer coercions)
534
+ if subclass_checker:
535
+ if isinstance(arg_inner, NominalType) and arg_inner.is_user_record:
536
+ if isinstance(param_inner, NominalType) and param_inner.is_user_record:
537
+ if subclass_checker(arg_inner, param_inner):
538
+ return True
539
+ pointee = getattr(param_inner, 'pointee', None)
540
+ if isinstance(pointee, NominalType) and pointee.is_user_record:
541
+ if subclass_checker(arg_inner, pointee):
542
+ return True
543
+ if isinstance(arg_inner, PtrType) and isinstance(arg_inner.pointee, NominalType):
544
+ if isinstance(param_inner, PtrType) and isinstance(param_inner.pointee, NominalType):
545
+ # Ptr[readonly[T]] cannot coerce to mutable Ptr (would drop const)
546
+ if not (arg_inner.is_readonly and not param_inner.is_readonly):
547
+ if subclass_checker(arg_inner.pointee, param_inner.pointee):
548
+ return True
549
+ # Non-protocol NominalType with Own[T] in type args: strip Own for overload matching.
550
+ # Symmetric with the same block in type_matches_strict.
551
+ if (isinstance(param_inner, NominalType) and not is_protocol_type(param_inner)
552
+ and any(isinstance(a, OwnType) for a in param_inner.inner_types())):
553
+ stripped_inner = tuple(a.wrapped if isinstance(a, OwnType) else a for a in param_inner.inner_types())
554
+ stripped_param = param_inner.with_inner_types(stripped_inner)
555
+ return arg_inner == stripped_param
556
+ return False
557
+
558
+
559
+ def _expand_arg_types_with_kwargs(
560
+ arg_types: list[TpyType],
561
+ kwarg_types: dict[str, TpyType],
562
+ overload: FunctionInfo,
563
+ ) -> list[TpyType] | None:
564
+ """Expand positional arg_types by inserting kwarg types at their param slots.
565
+
566
+ Mirrors ``resolve_kwargs`` index-mapping logic but operates on types so
567
+ ``resolve_overload`` can score kwargs-disambiguated candidates. Returns
568
+ ``None`` when the overload cannot accept the given kwargs (unknown name,
569
+ duplicate of a positional, or missing required param); the overload is
570
+ then rejected at the candidate level.
571
+
572
+ Defaulted positional gaps between the last positional arg and the rightmost
573
+ kwarg are filled with the param's own type -- trivially matches itself and
574
+ does not skew cross-overload scoring.
575
+ """
576
+ name_to_index = {p.name: i for i, p in enumerate(overload.params) if not p.is_variadic}
577
+
578
+ # One pass over kwargs: validate name, reject positional collisions,
579
+ # and track the rightmost explicitly-provided slot.
580
+ rightmost = len(arg_types) - 1
581
+ for kw_name in kwarg_types:
582
+ idx = name_to_index.get(kw_name)
583
+ if idx is None:
584
+ return None
585
+ if idx < len(arg_types) and not overload.params[idx].keyword_only:
586
+ return None
587
+ if idx > rightmost:
588
+ rightmost = idx
589
+
590
+ # Variadic: positional args feed *args; kwargs feed kwonly slots.
591
+ # Append kwonly types in declaration order so _classify_overload can
592
+ # score them at the right positions. Defensive: the parser currently
593
+ # blocks `*args` on `@overload` (parser.py raises "*args is not supported
594
+ # on @overload stubs"), so this branch is unreachable from user code
595
+ # today. Kept correct in case that gate ever opens.
596
+ if overload.has_variadic:
597
+ result = list(arg_types)
598
+ for p in overload.params:
599
+ if not p.keyword_only:
600
+ continue
601
+ if p.name in kwarg_types:
602
+ result.append(kwarg_types[p.name])
603
+ elif not p.has_default:
604
+ return None
605
+ return result
606
+
607
+ result: list[TpyType] = []
608
+ for i in range(rightmost + 1):
609
+ p = overload.params[i]
610
+ if i < len(arg_types):
611
+ result.append(arg_types[i])
612
+ elif p.name in kwarg_types:
613
+ result.append(kwarg_types[p.name])
614
+ elif p.has_default:
615
+ result.append(p.type)
616
+ else:
617
+ return None
618
+
619
+ # Required kwonly beyond rightmost must be in kwargs
620
+ for i, p in enumerate(overload.params):
621
+ if i > rightmost and p.keyword_only and not p.has_default and p.name not in kwarg_types:
622
+ return None
623
+
624
+ return result
625
+
626
+
627
+ def _classify_overload(
628
+ overload: FunctionInfo,
629
+ arg_types: list[TpyType],
630
+ protocol_checker: ProtocolChecker | None,
631
+ classifier: ProtocolClassifier | None,
632
+ default_int_type: TpyType | None,
633
+ type_ops: 'TypeOperations | None',
634
+ kwarg_types: dict[str, TpyType] | None = None,
635
+ ) -> tuple[tuple[MatchTier, int], ...] | None:
636
+ """Classify every arg against ``overload``'s params, returning a
637
+ per-arg tier vector on match or ``None`` if any arg rejects.
638
+
639
+ For generic overloads (``TypeParamRef`` in params), inference runs first
640
+ (using ``protocol_checker`` to validate type-parameter bounds) and
641
+ ``_classify_generic_param_match`` is used for the TPR params; other
642
+ params fall through to the regular strict classifier.
643
+ """
644
+ if kwarg_types:
645
+ expanded = _expand_arg_types_with_kwargs(arg_types, kwarg_types, overload)
646
+ if expanded is None:
647
+ return None
648
+ arg_types = expanded
649
+ if len(arg_types) < overload.min_args or len(arg_types) > overload.max_args:
650
+ return None
651
+ has_tpr = overload.is_generic() and any(
652
+ contains_type_param(p.type) for p in overload.params)
653
+ inferred: dict[str, TpyType] | None = None
654
+ if has_tpr:
655
+ if type_ops is None:
656
+ return None
657
+ inferred = type_ops.infer_type_params_for_function(
658
+ overload, arg_types, protocol_checker or _always_false_checker,
659
+ )
660
+ if inferred is None:
661
+ return None
662
+ per_arg: list[tuple[MatchTier, int]] = []
663
+ for arg_t, (_, ptype) in zip(arg_types, overload.params):
664
+ if has_tpr and contains_type_param(ptype):
665
+ cell = _classify_generic_param_match(
666
+ ptype, arg_t, inferred, type_ops, classifier, default_int_type,
667
+ )
668
+ else:
669
+ cell = _classify_strict_match(arg_t, ptype, classifier, default_int_type)
670
+ if cell is None:
671
+ return None
672
+ per_arg.append(cell)
673
+ return tuple(per_arg)
674
+
675
+
676
+ def resolve_overload(
677
+ overloads: list[FunctionInfo],
678
+ arg_types: list[TpyType],
679
+ protocol_checker: ProtocolChecker | None = None,
680
+ deref_checker: DerefChecker | None = None,
681
+ default_int_type: TpyType | None = None,
682
+ subclass_checker: SubclassChecker | None = None,
683
+ is_readonly_receiver: bool | None = None,
684
+ is_consuming_receiver: bool | None = None,
685
+ protocol_classifier: ProtocolClassifier | None = None,
686
+ type_ops: 'TypeOperations | None' = None,
687
+ kwarg_types: dict[str, TpyType] | None = None,
688
+ ) -> FunctionInfo | None:
689
+ """Two-pass overload resolution: strict tier-ranked match, then coercions.
690
+
691
+ ``protocol_classifier`` enables explicit-vs-structural tier discrimination;
692
+ when omitted, protocol hits are conservatively scored as STRUCTURAL.
693
+ ``type_ops`` enables the generic first-pass path (inference + tier
694
+ ranking); when omitted, generic overloads fall back to the legacy
695
+ structural match (first-match-wins in declaration order).
696
+
697
+ ``kwarg_types`` maps kwarg names to their analyzed types; per-overload
698
+ expansion inserts them at the matching param slots so kwargs can
699
+ disambiguate overloads that positional args tie on.
700
+
701
+ Returns the winning ``FunctionInfo`` or ``None`` (no match, or ambiguous
702
+ -- genuine ties at the top of the first-pass score are refused rather
703
+ than broken by declaration order).
704
+ """
705
+ # Pre-filter consuming vs borrowing overloads by receiver ownership.
706
+ # Must run BEFORE readonly filter: consuming overloads are non-readonly,
707
+ # so the readonly filter would drop the borrowing (readonly) overload
708
+ # and leave only the consuming one for mutable receivers.
709
+ if is_consuming_receiver is not None and any(m.is_consuming for m in overloads):
710
+ if is_consuming_receiver:
711
+ consuming = [m for m in overloads if m.is_consuming]
712
+ if consuming:
713
+ overloads = consuming
714
+ else:
715
+ borrowing = [m for m in overloads if not m.is_consuming]
716
+ if borrowing:
717
+ overloads = borrowing
718
+
719
+ if is_readonly_receiver is not None:
720
+ if is_readonly_receiver:
721
+ ro = [m for m in overloads if m.is_readonly]
722
+ if ro:
723
+ overloads = ro
724
+ else:
725
+ mut = [m for m in overloads if not m.is_readonly]
726
+ if mut:
727
+ overloads = mut
728
+
729
+ classifier = protocol_classifier or _bool_checker_to_classifier(protocol_checker)
730
+
731
+ first_generic_match_fallback: FunctionInfo | None = None
732
+ scored_candidates: list[tuple[tuple[tuple[int, ...], int], FunctionInfo]] = []
733
+ for overload in overloads:
734
+ if type_ops is None and overload.is_generic() and any(
735
+ contains_type_param(p.type) for p in overload.params):
736
+ # Legacy structural-match fallback for generic overloads when the
737
+ # caller hasn't plumbed type_ops (e.g. the error-message-preservation
738
+ # path in calls.py). Kwargs aren't supported on this fallback path
739
+ # because it uses raw structural matching without arity expansion.
740
+ if kwarg_types:
741
+ continue
742
+ if (first_generic_match_fallback is None
743
+ and len(arg_types) >= overload.min_args
744
+ and len(arg_types) <= overload.max_args
745
+ and all(_structural_match(arg_t, ptype)
746
+ for arg_t, (_, ptype) in zip(arg_types, overload.params))):
747
+ first_generic_match_fallback = overload
748
+ continue
749
+ per_arg = _classify_overload(
750
+ overload, arg_types, protocol_checker, classifier, default_int_type, type_ops,
751
+ kwarg_types=kwarg_types,
752
+ )
753
+ if per_arg is not None:
754
+ scored_candidates.append((_score(per_arg), overload))
755
+
756
+ if scored_candidates:
757
+ if len(scored_candidates) == 1:
758
+ return scored_candidates[0][1]
759
+ scored_candidates.sort(key=lambda c: c[0])
760
+ best_score = scored_candidates[0][0]
761
+ # Functionally-identical signatures aren't genuine ambiguity: a
762
+ # substituted generic and its concrete twin (both appended by
763
+ # calls.py's unified pool) match identically. Dedupe by param-type
764
+ # sequence; stable sort keeps the first-declared.
765
+ seen: set[tuple[TpyType, ...]] = set()
766
+ unique_tied: list[FunctionInfo] = []
767
+ for score, ov in scored_candidates:
768
+ if score != best_score:
769
+ break
770
+ key = tuple(p.type for p in ov.params)
771
+ if key not in seen:
772
+ seen.add(key)
773
+ unique_tied.append(ov)
774
+ if len(unique_tied) > 1:
775
+ raise OverloadAmbiguityError(tuple(unique_tied))
776
+ return unique_tied[0]
777
+
778
+ if first_generic_match_fallback is not None:
779
+ return first_generic_match_fallback
780
+
781
+ # Second pass: allow coercions, prefer overload with most non-coercion
782
+ # matches and fewest narrowing conversions (BigInt->Int32 is lossy).
783
+ candidates: list[tuple[int, int, FunctionInfo, list[TpyType]]] = []
784
+ for overload in overloads:
785
+ effective_args = arg_types
786
+ if kwarg_types:
787
+ expanded = _expand_arg_types_with_kwargs(arg_types, kwarg_types, overload)
788
+ if expanded is None:
789
+ continue
790
+ effective_args = expanded
791
+ if len(effective_args) < overload.min_args or len(effective_args) > overload.max_args:
792
+ continue
793
+ if all(type_matches_with_coercion(arg_t, ptype, protocol_checker, deref_checker, subclass_checker)
794
+ for arg_t, (_, ptype) in zip(effective_args, overload.params)):
795
+ score = sum(1 for arg_t, (_, ptype) in zip(effective_args, overload.params)
796
+ if type_matches_numeric(arg_t, ptype))
797
+ narrowing = sum(1 for arg_t, (_, ptype) in zip(effective_args, overload.params)
798
+ if is_big_int_type(arg_t) and is_fixed_int_type(unwrap_ref_type(ptype)))
799
+ candidates.append((score, narrowing, overload, effective_args))
800
+
801
+ if candidates:
802
+ if default_int_type is None:
803
+ default_int_type = BIGINT
804
+
805
+ def _int_literal_penalty(arg_t: TpyType, ptype: TpyType) -> int:
806
+ if not isinstance(arg_t, IntLiteralType):
807
+ return 0
808
+ ptype = unwrap_ref_type(ptype)
809
+ # Prefer the configured default integer type for integer literals.
810
+ if ptype == default_int_type:
811
+ return 0
812
+ default_tr = int_traits_of(default_int_type)
813
+ if default_tr is not None:
814
+ ptype_tr = int_traits_of(ptype)
815
+ if ptype_tr is not None:
816
+ # Keep preference stable around configured width/signedness.
817
+ width_gap = abs(ptype_tr.bits - default_tr.bits) // 8
818
+ sign_penalty = 1 if ptype_tr.signed != default_tr.signed else 0
819
+ return 1 + width_gap + sign_penalty
820
+ if is_big_int_type(ptype):
821
+ return 8
822
+ if is_big_int_type(default_int_type):
823
+ if is_fixed_int_type(ptype):
824
+ return 2
825
+ return 1
826
+
827
+ # Apply literal penalty to break ties deterministically.
828
+ # Covers both same-return (e.g. range(IntLiteral) over many fixed-int
829
+ # overloads) and different-return cases (IntLiteral->FixedInt narrowing).
830
+ if len(candidates) > 1:
831
+ for i, (score, narrowing, overload, effective_args) in enumerate(candidates):
832
+ extra = sum(
833
+ _int_literal_penalty(arg_t, ptype)
834
+ for arg_t, (_, ptype) in zip(effective_args, overload.params)
835
+ )
836
+ candidates[i] = (score, narrowing + extra, overload, effective_args)
837
+ # Best: most numeric matches, then fewest narrowing conversions
838
+ candidates.sort(key=lambda x: (-x[0], x[1]))
839
+ return candidates[0][2]
840
+
841
+ return None