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
@@ -0,0 +1,629 @@
1
+ """Method resolution, iterator/span helpers, extends-arg parsing.
2
+
3
+ Shared utilities that don't belong on a single TpyType subclass:
4
+ extends-clause string parsing, type-param substitution for method
5
+ signatures, and the iter/span element-type discovery used by sema. The
6
+ generic-type-factory table that used to live here now lives on
7
+ `TypeDef`.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import re
13
+ from typing import TYPE_CHECKING
14
+
15
+ if TYPE_CHECKING:
16
+ from tpyc.typesys import TypeRegistry, RecordInfo, FunctionInfo
17
+
18
+ from tpyc.typesys import (
19
+ TypeParamRef, NominalType, PtrType, TupleType,
20
+ TpyType, CHAR, OwnType, GenExprType,
21
+ is_any_str_type, is_protocol_type, unwrap_ref_type, unwrap_qualifiers,
22
+ )
23
+ from tpyc.type_def_registry import is_span, is_span_iter, is_copy_iter, is_own_iter, is_iterator_adapter, protocol_info_of
24
+ from tpyc.modules.defs import ParamDef, MethodDef
25
+
26
+
27
+ def _compose_parent_subst(
28
+ parent: "NominalType", parent_info: "RecordInfo",
29
+ type_subst: "dict[str, TpyType]",
30
+ ) -> "dict[str, TpyType]":
31
+ """Extend type_subst with parent's type-parameter bindings from parent.type_args.
32
+
33
+ Each parent_info.type_params[i] maps to parent.type_args[i], composed through
34
+ the existing subst so TypeParamRefs from the child level get resolved first.
35
+ """
36
+ result = dict(type_subst)
37
+ if parent.type_args and parent_info.type_params:
38
+ for param_name, arg in zip(parent_info.type_params, parent.type_args):
39
+ if isinstance(arg, TypeParamRef) and arg.name in type_subst:
40
+ result[param_name] = type_subst[arg.name]
41
+ else:
42
+ result[param_name] = arg
43
+ return result
44
+
45
+
46
+ # ---------------------------------------------------------------------------
47
+ # Concrete type name resolution
48
+ # ---------------------------------------------------------------------------
49
+
50
+ def _resolve_concrete_type_name(name: str) -> "TpyType | None":
51
+ """Resolve a concrete type name (like 'Char', 'Int32') to its TpyType singleton.
52
+
53
+ Used for resolving extends declarations like extends=["NativeIterable[Char]"].
54
+ """
55
+ from tpyc.typesys import (
56
+ CHAR, BOOL, STR, STRING, STRVIEW, VOID, BIGINT, FLOAT, FLOAT32,
57
+ BASIC_SLICE, SLICE, BYTES, BYTEARRAY, BYTESVIEW,
58
+ INT8, INT16, INT32, INT64, UINT8, UINT16, UINT32, UINT64,
59
+ )
60
+
61
+ # Map of simple type names to their singleton instances
62
+ type_map = {
63
+ "bool": BOOL,
64
+ "Char": CHAR,
65
+ "Int8": INT8, "Int16": INT16, "Int32": INT32, "Int64": INT64,
66
+ "UInt8": UINT8, "UInt16": UINT16, "UInt32": UINT32, "UInt64": UINT64,
67
+ "Float32": FLOAT32,
68
+ "str": STR, "String": STRING, "StrView": STRVIEW,
69
+ "int": BIGINT,
70
+ "float": FLOAT,
71
+ "bytes": BYTES, "bytearray": BYTEARRAY, "BytesView": BYTESVIEW,
72
+ "basic_slice": BASIC_SLICE,
73
+ "slice": SLICE,
74
+ "None": VOID,
75
+ }
76
+ return type_map.get(name)
77
+
78
+
79
+ def _resolve_extends_type_arg(type_str: str, type_params: dict[str, "TpyType"]) -> "TpyType | None":
80
+ """Resolve an extends type arg string to a TpyType.
81
+
82
+ Handles:
83
+ - Simple type param refs: "K", "V", "T"
84
+ - Concrete type names: "Char", "Int32"
85
+ - Tuple types: "tuple[K, V]"
86
+ """
87
+ # Handle tuple[...] pattern
88
+ tuple_match = re.match(r"tuple\[(.+)\]$", type_str)
89
+ if tuple_match:
90
+ inner = tuple_match.group(1)
91
+ parts = [p.strip() for p in inner.split(",")]
92
+ resolved = []
93
+ for part in parts:
94
+ if part in type_params:
95
+ resolved.append(type_params[part])
96
+ else:
97
+ concrete = _resolve_concrete_type_name(part)
98
+ if concrete is None:
99
+ return None
100
+ resolved.append(concrete)
101
+ return TupleType(tuple(resolved))
102
+
103
+ # Simple name: type param or concrete type
104
+ if type_str in type_params:
105
+ return type_params[type_str]
106
+ return _resolve_concrete_type_name(type_str)
107
+
108
+
109
+ # ---------------------------------------------------------------------------
110
+ # Type param extraction and method resolution
111
+ # ---------------------------------------------------------------------------
112
+
113
+ def extract_type_params(tpy_type: "TpyType") -> dict[str, "TpyType"]:
114
+ """Extract type parameters from a concrete type instance.
115
+
116
+ For list[Int32], returns {"T": Int32}.
117
+ For dict[str, Int32], returns {"K": str, "V": Int32}.
118
+ For Container[Point, 10], returns {"T": Point}.
119
+ For Ptr[Point], returns {"T": Point}.
120
+
121
+ Note: Only type parameters that are themselves types are extracted.
122
+ Integer parameters like N in Container[T, N] are not included.
123
+ """
124
+ from tpyc.typesys import PtrType
125
+ from tpyc.type_def_registry import is_dict_view, is_dict
126
+ if is_dict(tpy_type) or is_dict_view(tpy_type):
127
+ return {"K": tpy_type.type_args[0], "V": tpy_type.type_args[1]}
128
+ # Pointer types: use the full pointee (preserving readonly if present).
129
+ # For Ptr[readonly[T]], T maps to readonly[T] so that methods like
130
+ # span() -> Span[T] correctly produce Span[readonly[T]].
131
+ # The deref chains in expressions.py and methods.py handle unwrapping
132
+ # ReadonlyType from __deref__() results for field/method access.
133
+ if isinstance(tpy_type, PtrType):
134
+ return {"T": tpy_type.pointee}
135
+ if (elem_type := tpy_type.get_element_type()) is not None:
136
+ return {"T": elem_type}
137
+ return {}
138
+
139
+
140
+ def _resolve_type_or_param(t: "TpyType", type_params: dict[str, "TpyType"]) -> "TpyType":
141
+ """Resolve TypeParamRef instances to concrete types.
142
+
143
+ Handles:
144
+ - TypeParamRef("T") -> type_params["T"]
145
+ - SelfType -> type_params["Self"] if available, else SELF
146
+ - NominalType (protocol) with TypeParamRef args -> resolved NominalType
147
+ - PtrType with TypeParamRef pointee -> resolved pointer type
148
+ - Other TpyType -> returned as-is (uses map_inner_types for nested resolution)
149
+ """
150
+ from tpyc.typesys import SelfType, SELF
151
+
152
+ # Handle SelfType
153
+ if isinstance(t, SelfType):
154
+ if "Self" in type_params:
155
+ return type_params["Self"]
156
+ return SELF
157
+
158
+ # Handle TypeParamRef directly
159
+ if isinstance(t, TypeParamRef):
160
+ if t.name not in type_params:
161
+ raise ValueError(f"Unresolved type parameter: {t.name}")
162
+ return type_params[t.name]
163
+
164
+ # Handle NominalType (protocol) with TypeParamRef in type_args
165
+ if isinstance(t, NominalType) and t.is_protocol and t.type_args:
166
+ resolved_args = tuple(
167
+ _resolve_type_or_param(arg, type_params) for arg in t.type_args
168
+ )
169
+ return NominalType(t.name, resolved_args, is_protocol=True)
170
+
171
+ # Handle PtrType with TypeParamRef pointee
172
+ if isinstance(t, PtrType):
173
+ resolved_pointee = _resolve_type_or_param(t.pointee, type_params)
174
+ return PtrType(resolved_pointee, is_readonly=t.is_readonly)
175
+
176
+ # For other types, use map_inner_types for recursive substitution
177
+ return t.map_inner_types(lambda inner: _resolve_type_or_param(inner, type_params))
178
+
179
+
180
+ def resolve_method(method: MethodDef, type_params: dict[str, "TpyType"]) -> MethodDef:
181
+ """Resolve TypeParamRef instances in a method signature to concrete types.
182
+
183
+ Given a method with TypeParamRef placeholders and a dict mapping
184
+ param names to concrete types, returns a new MethodDef with all types resolved.
185
+
186
+ Example:
187
+ method = MethodDef(params=[ParamDef("value", TypeParamRef("T"))],
188
+ returns=TypeParamRef("T"), cpp=...)
189
+ resolved = resolve_method(method, {"T": Int32})
190
+ # resolved.params[0].type == Int32, resolved.returns == Int32
191
+ """
192
+ resolved_params = [
193
+ ParamDef(name=p.name, type=_resolve_type_or_param(p.type, type_params),
194
+ requires_mutable_lvalue=p.requires_mutable_lvalue)
195
+ for p in method.params
196
+ ]
197
+ resolved_returns = _resolve_type_or_param(method.returns, type_params)
198
+ return MethodDef(
199
+ params=resolved_params,
200
+ returns=resolved_returns,
201
+ cpp=method.cpp,
202
+ is_noalloc=method.is_noalloc,
203
+ is_readonly=method.is_readonly,
204
+ is_pure=method.is_pure,
205
+ type_params=method.type_params,
206
+ type_param_bounds=method.type_param_bounds,
207
+ )
208
+
209
+
210
+ # ---------------------------------------------------------------------------
211
+ # Iterator / span helpers
212
+ # ---------------------------------------------------------------------------
213
+
214
+ # Protocols whose single type argument is the iteration element type.
215
+ ITERABLE_PROTOCOL_QNAMES = frozenset({
216
+ "typing.Iterator", "typing.Iterable",
217
+ "tpy.NativeIterable", "tpy.Spannable",
218
+ })
219
+
220
+ def is_native_iterable(tpy_type: "TpyType", registry: "TypeRegistry") -> bool:
221
+ """Check if type extends NativeIterable (uses range-based for in C++)."""
222
+ record = registry.get_record_for_type(tpy_type)
223
+ if record is None:
224
+ return False
225
+ # Builtin types: check extends_protocols strings
226
+ if record.extends_protocols:
227
+ if any(ext.startswith("NativeIterable") for ext in record.extends_protocols):
228
+ return True
229
+ # User records: check explicitly declared implemented_protocols
230
+ for proto in record.implemented_protocols:
231
+ if proto.name == "NativeIterable":
232
+ return True
233
+ return False
234
+
235
+
236
+ def get_extends_protocol_type_arg(
237
+ tpy_type: "TpyType", protocol_name: str,
238
+ registry: "TypeRegistry | None" = None,
239
+ ) -> "TpyType | None":
240
+ """Extract the first type arg from a type's extends declaration for a protocol.
241
+
242
+ For example, Ptr[Int32] extends Deref[T] with T=Int32, so
243
+ get_extends_protocol_type_arg(Ptr[Int32], "Deref") returns Int32.
244
+
245
+ Checks builtin type extends strings first, then user record
246
+ implemented_protocols if a registry is provided.
247
+ """
248
+ from tpyc.typesys import impl_proto_matches_name, get_protocol_qname
249
+
250
+ # Mirror classify_protocol_conformance: conformance is on the
251
+ # underlying record, not its Ref/readonly/Own wrapper.
252
+ tpy_type = unwrap_qualifiers(tpy_type)
253
+
254
+ type_params = extract_type_params(tpy_type)
255
+
256
+ # Check RecordInfo extends_protocols
257
+ if registry is not None:
258
+ record_info = registry.get_record_for_type(tpy_type)
259
+ if record_info is not None:
260
+ for ext in record_info.extends_protocols:
261
+ match = re.match(r"(\w+)\[(.+)\]", ext)
262
+ if match and match.group(1) == protocol_name:
263
+ return _resolve_extends_type_arg(match.group(2), type_params)
264
+
265
+ # Fallback: check implemented_protocols (NominalType objects)
266
+ target_qname = get_protocol_qname(protocol_name)
267
+ for impl_proto in record_info.implemented_protocols:
268
+ if impl_proto_matches_name(impl_proto, protocol_name, target_qname) and impl_proto.type_args:
269
+ return impl_proto.type_args[0]
270
+
271
+ return None
272
+
273
+
274
+ def get_error_return_next_element_type(tpy_type: "TpyType", registry: "TypeRegistry") -> "TpyType | None":
275
+ """If type has __next__() with @error_return(StopIteration), return element type T."""
276
+ from tpyc.typesys import NominalType, unwrap_ref_type
277
+
278
+ tpy_type = unwrap_ref_type(tpy_type)
279
+ if not isinstance(tpy_type, NominalType) or not tpy_type.is_user_record:
280
+ return None
281
+ return _find_error_return_next_element(tpy_type.name, tpy_type.type_args, registry)
282
+
283
+
284
+ def _find_error_return_next_element(
285
+ record_name: str, type_args: "list[TpyType] | None", registry: "TypeRegistry",
286
+ ) -> "TpyType | None":
287
+ """Walk a record's method table (and parent chain) looking for __next__() with error_return."""
288
+ from tpyc.typesys import NominalType, OwnType, TypeParamRef, unwrap_ref_type
289
+
290
+ record = registry.find_record(record_name)
291
+ if record is None:
292
+ return None
293
+
294
+ type_subst: dict[str, "TpyType"] = {}
295
+ if record.type_params and type_args:
296
+ type_subst = dict(zip(record.type_params, type_args))
297
+
298
+ for method in record.get_method_overloads("__next__"):
299
+ if method.error_return_type == "builtins.StopIteration" and len(method.params) == 0:
300
+ inner = unwrap_ref_type(method.return_type)
301
+ if isinstance(inner, OwnType):
302
+ inner = inner.wrapped
303
+ if isinstance(inner, TypeParamRef) and inner.name in type_subst:
304
+ return type_subst[inner.name]
305
+ return inner
306
+
307
+ # Walk each parent chain (first match wins; diamond-free guarantees uniqueness)
308
+ for parent in record.parents:
309
+ if not (isinstance(parent, NominalType) and parent.is_user_record):
310
+ continue
311
+ parent_args = list(parent.type_args) if parent.type_args else None
312
+ if type_subst and parent_args:
313
+ parent_args = [
314
+ type_subst[a.name] if isinstance(a, TypeParamRef) and a.name in type_subst else a
315
+ for a in parent_args
316
+ ]
317
+ result = _find_error_return_next_element(parent.name, parent_args, registry)
318
+ if result is not None:
319
+ return result
320
+
321
+ return None
322
+
323
+
324
+ def get_iter_element_type(tpy_type: "TpyType", registry: "TypeRegistry") -> "TpyType | None":
325
+ """If type has __iter__() returning a concrete iterator, return element type T."""
326
+ from tpyc.typesys import NominalType, unwrap_ref_type
327
+
328
+ tpy_type = unwrap_ref_type(tpy_type)
329
+ # Try user records (walks parent chain).
330
+ # allow_protocol_return=True: user __iter__ returning Iterator[T] is recognized.
331
+ if isinstance(tpy_type, NominalType) and tpy_type.is_user_record:
332
+ record = registry.get_record(tpy_type.name)
333
+ if record is not None:
334
+ type_subst: dict[str, "TpyType"] = {"Self": tpy_type}
335
+ if record.type_params and tpy_type.type_args:
336
+ type_subst.update(zip(record.type_params, tpy_type.type_args))
337
+ result = _find_record_iter_element(record, type_subst, registry,
338
+ allow_protocol_return=True)
339
+ if result is not None:
340
+ return result
341
+
342
+ # Try builtin types via registry.
343
+ # allow_protocol_return=True: builtin __iter__() stubs return Iterator[T]
344
+ # (e.g. list, dict, set, Span, Array, Range, str) and sema recognizes them
345
+ # structurally -- this is the single iteration-protocol entry point (see
346
+ # docs/ITERATOR_DESIGN.md).
347
+ record = registry.get_record_for_type(tpy_type)
348
+ if record is not None:
349
+ # extract_type_params handles NominalType.type_args as well as
350
+ # structural wrappers (PtrType.pointee, etc.) via each type's
351
+ # get_element_type() hook.
352
+ # Include Self so that __iter__(self) -> Self substitutes to the
353
+ # record's own type (used by SpanIter and similar self-iterator types).
354
+ type_subst_b = extract_type_params(tpy_type)
355
+ type_subst_b["Self"] = tpy_type
356
+ result = _find_record_iter_element(record, type_subst_b, registry,
357
+ allow_protocol_return=True)
358
+ if result is not None:
359
+ return result
360
+
361
+ return None
362
+
363
+
364
+ def _ancestor_iter_element(
365
+ proto: "NominalType", visited: "set[str] | None" = None,
366
+ ) -> "TpyType | None":
367
+ """Walk parent protocols looking for an ancestor whose qname is in
368
+ ITERABLE_PROTOCOL_QNAMES; return the inherited element type with the
369
+ inheritance binding chain applied.
370
+
371
+ For `class Counted[T](Iterable[T], Protocol)` instantiated as
372
+ `Counted[Int32]`, the element type is `Int32` -- read off Iterable's
373
+ type_args after substituting Counted's own T->Int32 binding.
374
+ """
375
+ if visited is None:
376
+ visited = set()
377
+ info = protocol_info_of(proto)
378
+ if info is None:
379
+ return None
380
+ qname = proto.qualified_name() or proto.name
381
+ if qname in visited:
382
+ return None
383
+ visited.add(qname)
384
+
385
+ self_subst: dict[str, TpyType] = {}
386
+ if info.type_params and proto.type_args:
387
+ for name, arg in zip(info.type_params, proto.type_args):
388
+ if isinstance(arg, TpyType):
389
+ self_subst[name] = arg
390
+
391
+ for parent in info.parent_protocols:
392
+ resolved_args = tuple(
393
+ self_subst.get(arg.name, arg) if isinstance(arg, TypeParamRef) else arg
394
+ for arg in parent.type_args
395
+ )
396
+ resolved_parent = NominalType(
397
+ name=parent.name,
398
+ type_args=resolved_args,
399
+ is_protocol=True,
400
+ _module_qname=parent._module_qname,
401
+ )
402
+ if resolved_parent.qualified_name() in ITERABLE_PROTOCOL_QNAMES:
403
+ if resolved_args:
404
+ first = resolved_args[0]
405
+ return first if isinstance(first, TpyType) else None
406
+ return None
407
+ result = _ancestor_iter_element(resolved_parent, visited)
408
+ if result is not None:
409
+ return result
410
+ return None
411
+
412
+
413
+ def get_iterable_element_type(tpy_type: "TpyType", registry: "TypeRegistry") -> "TpyType | None":
414
+ """Unified element-type accessor for any iterable type.
415
+
416
+ Single source of truth for "what element type does iterating this produce?"
417
+ Covers all iterable categories:
418
+ - Compiler-internal adapters (CopyIter, OwnIter, GenExpr, SpanIter)
419
+ - Protocol-typed params (Iterator[T], Iterable[T], NativeIterable[T], Spannable[T])
420
+ - String types -> Char
421
+ - error_return __next__ iterators
422
+ - __iter__() method (built-in containers + user records)
423
+
424
+ Returns None if the type is not iterable.
425
+ """
426
+ tpy_type = unwrap_ref_type(tpy_type)
427
+ if isinstance(tpy_type, OwnType):
428
+ tpy_type = tpy_type.wrapped
429
+
430
+ # Compiler-internal iterator adapters (no stubs) plus SpanIter
431
+ if is_iterator_adapter(tpy_type) or isinstance(tpy_type, GenExprType):
432
+ return tpy_type.element_type if isinstance(tpy_type, GenExprType) else tpy_type.type_args[0]
433
+
434
+ # Protocol-typed iterables: single type_arg is T
435
+ if is_protocol_type(tpy_type) and tpy_type.qualified_name() in ITERABLE_PROTOCOL_QNAMES:
436
+ if tpy_type.type_args:
437
+ first = tpy_type.type_args[0]
438
+ return first if isinstance(first, TpyType) else None
439
+ return None
440
+
441
+ # Protocol-typed iterables that inherit from one of the above (e.g.
442
+ # `class Counted[T](Iterable[T], Protocol)`). Walks parent protocols and
443
+ # resolves the inherited element type via the inheritance binding chain.
444
+ if is_protocol_type(tpy_type) and isinstance(tpy_type, NominalType):
445
+ ancestor_elem = _ancestor_iter_element(tpy_type)
446
+ if ancestor_elem is not None:
447
+ return ancestor_elem
448
+
449
+ # String types -> Char
450
+ if is_any_str_type(tpy_type):
451
+ return CHAR
452
+
453
+ # error_return __next__ (user-defined iterators)
454
+ er_elem = get_error_return_next_element_type(tpy_type, registry)
455
+ if er_elem is not None:
456
+ return er_elem
457
+
458
+ # __iter__() method (built-in containers + user records)
459
+ iter_elem = get_iter_element_type(tpy_type, registry)
460
+ if iter_elem is not None:
461
+ return iter_elem
462
+
463
+ return None
464
+
465
+
466
+ def _find_record_iter_element(
467
+ record: "RecordInfo", type_subst: "dict[str, TpyType]", registry: "TypeRegistry",
468
+ *, allow_protocol_return: bool = False,
469
+ ) -> "TpyType | None":
470
+ """Check if record (or its parents) has __iter__() returning a concrete iterator; return element type."""
471
+ from tpyc.typesys import NominalType, TypeParamRef
472
+
473
+ result = _find_iter_method_element(record.get_method_overloads("__iter__"), type_subst, registry,
474
+ allow_protocol_return=allow_protocol_return)
475
+ if result is not None:
476
+ return result
477
+
478
+ # Walk each parent chain (first match wins)
479
+ for parent in record.parents:
480
+ if not (isinstance(parent, NominalType) and parent.is_user_record):
481
+ continue
482
+ parent_info = registry.get_record(parent.name)
483
+ if parent_info is None:
484
+ continue
485
+ parent_subst = _compose_parent_subst(parent, parent_info, type_subst)
486
+ result = _find_record_iter_element(parent_info, parent_subst, registry,
487
+ allow_protocol_return=allow_protocol_return)
488
+ if result is not None:
489
+ return result
490
+
491
+ return None
492
+
493
+
494
+ def _find_iter_method_element(
495
+ methods: "list[MethodDef | FunctionInfo]", type_subst: "dict[str, TpyType]", registry: "TypeRegistry",
496
+ *, allow_protocol_return: bool = False,
497
+ ) -> "TpyType | None":
498
+ """Check __iter__() methods for a concrete iterator return type and extract element type."""
499
+ from tpyc.typesys import FunctionInfo, NominalType, OwnType, SelfType, TypeParamRef, is_protocol_type, unwrap_ref_type
500
+
501
+ for method in methods:
502
+ if len(method.params) != 0:
503
+ continue
504
+ if isinstance(method, FunctionInfo):
505
+ ret = unwrap_ref_type(method.return_type)
506
+ else:
507
+ ret = method.returns
508
+ # __iter__(self) -> Self handling. SelfType returns substitute
509
+ # to the record's own type. User iterators with Self return
510
+ # resolve to their NominalType (is_user_record=True) and are
511
+ # handled by the error_return __next__ branch below.
512
+ # Note: builtins like SpanIter whose __iter__ returns Self end
513
+ # up as plain NominalType("SpanIter", ...) after parser resolution
514
+ # and are NOT matched here; they rely on the compiler-internal
515
+ # adapter list in IterableHelper. The parser doesn't resolve Self
516
+ # to the SpanIterType typesys subclass; low-priority follow-up
517
+ # while the adapter list stays tiny.
518
+ if isinstance(ret, SelfType) and "Self" in type_subst:
519
+ ret = type_subst["Self"]
520
+ if isinstance(ret, TypeParamRef) and ret.name in type_subst:
521
+ ret = type_subst[ret.name]
522
+ if isinstance(ret, OwnType):
523
+ ret = ret.wrapped
524
+
525
+ # SpanIter[T] -- known NativeIterable with element type T
526
+ if is_span_iter(ret):
527
+ elem = ret.type_args[0]
528
+ if isinstance(elem, TypeParamRef) and elem.name in type_subst:
529
+ elem = type_subst[elem.name]
530
+ return elem
531
+
532
+ # Iterator[T] protocol return type (not Iterable -- codegen emits
533
+ # .__next__() directly, which requires Iterator, not Iterable).
534
+ # Recursively substitute type params in compound element types so
535
+ # that e.g. dict_items.__iter__() -> Iterator[tuple[K, V]] yields
536
+ # tuple[str, Point] when instantiated as dict_items[str, Point].
537
+ if (allow_protocol_return
538
+ and is_protocol_type(ret) and isinstance(ret, NominalType)
539
+ and ret.qualified_name() == "typing.Iterator" and ret.type_args):
540
+ elem = ret.type_args[0]
541
+ if type_subst:
542
+ try:
543
+ # Successful resolution settles the element type even when
544
+ # it resolves to another type param: iterating Span[T] in
545
+ # a generic body yields T, a valid in-scope element type
546
+ # (parallel to args[0] indexing). Only an unresolved param
547
+ # (ValueError) means the element is genuinely unknown here.
548
+ return _resolve_type_or_param(elem, type_subst)
549
+ except ValueError:
550
+ pass
551
+ elif not isinstance(elem, TypeParamRef):
552
+ # No substitution context: a bare type param is meaningless.
553
+ return elem
554
+
555
+ # User-defined iterator with error_return __next__
556
+ if isinstance(ret, NominalType) and ret.is_user_record:
557
+ iter_type_args = ret.type_args
558
+ if iter_type_args and type_subst:
559
+ iter_type_args = [
560
+ type_subst.get(a.name, a) if isinstance(a, TypeParamRef) else a
561
+ for a in iter_type_args
562
+ ]
563
+ elem = _find_error_return_next_element(ret.name, iter_type_args, registry)
564
+ if elem is not None:
565
+ return elem
566
+
567
+ return None
568
+
569
+
570
+ def get_span_element_type(tpy_type: "TpyType", registry: "TypeRegistry") -> "TpyType | None":
571
+ """If type has __span__() -> Span[T] or Span[readonly[T]], return element type T."""
572
+ span_type = get_span_return_type(tpy_type, registry)
573
+ if span_type is not None:
574
+ from tpyc.typesys import unwrap_readonly
575
+ return unwrap_readonly(span_type.type_args[0])
576
+ return None
577
+
578
+
579
+ def get_span_return_type(tpy_type: "TpyType", registry: "TypeRegistry") -> "NominalType | None":
580
+ """If type has __span__() -> Span[T] or Span[readonly[T]], return the full Span NominalType."""
581
+ from tpyc.typesys import NominalType, TypeParamRef
582
+
583
+ if isinstance(tpy_type, NominalType) and tpy_type.is_user_record:
584
+ record = registry.get_record(tpy_type.name)
585
+ else:
586
+ # Builtin types (list, Array, Span, etc.)
587
+ record = registry.get_record_for_type(tpy_type)
588
+ if record is None:
589
+ return None
590
+ type_subst: dict[str, "TpyType"] = {}
591
+ if record.type_params and isinstance(tpy_type, NominalType) and tpy_type.type_args:
592
+ type_subst = dict(zip(record.type_params, tpy_type.type_args))
593
+ return _find_span_method_return_type(record, type_subst, registry)
594
+
595
+
596
+ def _find_span_method_return_type(
597
+ record: "RecordInfo", type_subst: "dict[str, TpyType]", registry: "TypeRegistry",
598
+ ) -> "NominalType | None":
599
+ """Check if record has __span__() returning Span[T]/Span[readonly[T]], and return the Span NominalType."""
600
+ from tpyc.typesys import NominalType, TypeParamRef, make_span
601
+
602
+ for method in record.get_method_overloads("__span__"):
603
+ if len(method.params) != 0:
604
+ continue
605
+ ret = method.return_type
606
+ if isinstance(ret, TypeParamRef) and ret.name in type_subst:
607
+ ret = type_subst[ret.name]
608
+ if is_span(ret):
609
+ # Use inner element (unwrapped) for TypeParamRef resolution,
610
+ # then reconstruct with the original readonly-ness.
611
+ from tpyc.typesys import unwrap_readonly, is_readonly_span
612
+ elem = unwrap_readonly(ret.type_args[0])
613
+ if isinstance(elem, TypeParamRef) and elem.name in type_subst:
614
+ elem = type_subst[elem.name]
615
+ return make_span(elem, is_readonly=is_readonly_span(ret))
616
+
617
+ # Walk each parent chain (first match wins)
618
+ for parent in record.parents:
619
+ if not (isinstance(parent, NominalType) and parent.is_user_record):
620
+ continue
621
+ parent_info = registry.get_record(parent.name)
622
+ if parent_info is None:
623
+ continue
624
+ parent_subst = _compose_parent_subst(parent, parent_info, type_subst)
625
+ result = _find_span_method_return_type(parent_info, parent_subst, registry)
626
+ if result is not None:
627
+ return result
628
+
629
+ return None