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/macro_loader.py ADDED
@@ -0,0 +1,497 @@
1
+ """
2
+ TurboPython Macro Module Loader
3
+
4
+ Discovers and loads ``# tpy: macro_module`` files via CPython during
5
+ compilation. Macro modules are NOT compiled to C++ -- they run at compile
6
+ time only.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import importlib.util
12
+ import inspect
13
+ import re
14
+ import sys
15
+ import typing
16
+ from pathlib import Path
17
+ from typing import Any, Callable
18
+
19
+ import builtins as _builtins_module
20
+
21
+ from . import macro_api as _macro_api
22
+
23
+
24
+ # ---------------------------------------------------------------------------
25
+ # Macro module import/builtin restrictions
26
+ # ---------------------------------------------------------------------------
27
+ # Soft restrictions to keep macro modules on the stable tpyc.macro_api surface.
28
+ # NOT a security sandbox -- Python cannot be fully sandboxed via __builtins__.
29
+ # The goal is forward compatibility: when the compiler is self-hosted, macro
30
+ # code will run in a VM where only the macro_api surface is available.
31
+
32
+ # Modules that macro code is allowed to import.
33
+ _ALLOWED_IMPORTS: frozenset[str] = frozenset({
34
+ "tpyc.macro_api",
35
+ })
36
+
37
+ # Builtins that are NOT available in macro modules.
38
+ _BLOCKED_BUILTINS: frozenset[str] = frozenset({
39
+ "open", "exec", "eval", "compile",
40
+ "input", "breakpoint", "exit", "quit",
41
+ "memoryview",
42
+ })
43
+
44
+ _original_import = _builtins_module.__import__
45
+
46
+
47
+ def _make_restricted_import(
48
+ module_name: str, registry: "MacroRegistry",
49
+ ) -> Callable:
50
+ """Create a restricted __import__ for a macro module."""
51
+ def _restricted_import(name: str, *args: Any, **kwargs: Any) -> Any:
52
+ if not name:
53
+ raise ImportError(
54
+ f"Macro module '{module_name}' cannot use relative imports"
55
+ )
56
+ for allowed in _ALLOWED_IMPORTS:
57
+ if name == allowed or name.startswith(allowed + "."):
58
+ return _original_import(name, *args, **kwargs)
59
+ # Try resolving as another macro module from lib search paths
60
+ mod = registry._resolve_macro_import(name)
61
+ if mod is not None:
62
+ return mod
63
+ raise ImportError(
64
+ f"Macro module '{module_name}' cannot import '{name}' "
65
+ f"-- only tpyc.macro_api and other macro modules are allowed"
66
+ )
67
+ return _restricted_import
68
+
69
+
70
+ def _make_restricted_builtins(
71
+ module_name: str, registry: "MacroRegistry",
72
+ ) -> dict[str, Any]:
73
+ """Create a restricted __builtins__ dict for a macro module."""
74
+ restricted = {
75
+ k: v for k, v in _builtins_module.__dict__.items()
76
+ if k not in _BLOCKED_BUILTINS
77
+ }
78
+ restricted["__import__"] = _make_restricted_import(module_name, registry)
79
+ return restricted
80
+
81
+
82
+ _MACRO_MODULE_RE = re.compile(r'^\s*#\s*tpy:\s+macro_module\s*$')
83
+
84
+
85
+ def is_macro_module_source(source: str) -> bool:
86
+ """Quick check whether source text contains ``# tpy: macro_module``."""
87
+ # Only scan the preamble (before first non-comment, non-blank line)
88
+ for line in source.splitlines():
89
+ stripped = line.strip()
90
+ if stripped and not stripped.startswith('#'):
91
+ break
92
+ if _MACRO_MODULE_RE.match(line):
93
+ return True
94
+ return False
95
+
96
+
97
+ def call_macro_field_function(
98
+ registry: Any,
99
+ call: Any,
100
+ loc: Any,
101
+ ) -> Any | None:
102
+ """Call a macro-module function from a field default and return the result.
103
+
104
+ If the call's resolved_import points to a loaded macro module, looks up
105
+ the function, extracts kwargs, and calls it. Returns None if not resolvable.
106
+ """
107
+ from .diagnostics import SemanticError
108
+
109
+ resolved = getattr(call, 'resolved_import', None)
110
+ if resolved is None:
111
+ return None
112
+ mod_name, func_name = resolved
113
+ func = registry.get_export(mod_name, func_name)
114
+ if func is None:
115
+ return None
116
+
117
+ if call.args:
118
+ raise SemanticError(
119
+ f"{func_name}() does not accept positional arguments", loc)
120
+
121
+ # Unwrap literal kwargs to plain Python values so macro field functions
122
+ # see the same types in both compiler and CPython paths.
123
+ from .parse import (
124
+ TpyStrLiteral, TpyIntLiteral, TpyFloatLiteral, TpyBoolLiteral, TpyNoneLiteral,
125
+ )
126
+ kwargs = {}
127
+ for k, v in call.kwargs.items():
128
+ if isinstance(v, TpyBoolLiteral):
129
+ kwargs[k] = v.value
130
+ elif isinstance(v, (TpyIntLiteral, TpyFloatLiteral, TpyStrLiteral)):
131
+ kwargs[k] = v.value
132
+ elif isinstance(v, TpyNoneLiteral):
133
+ kwargs[k] = None
134
+ else:
135
+ kwargs[k] = v # non-literal (e.g. TpyName for default_factory)
136
+ try:
137
+ return func(**kwargs)
138
+ except TypeError as e:
139
+ raise SemanticError(f"{func_name}(): {e}", loc) from e
140
+
141
+
142
+ def validate_and_call_macro(
143
+ macro_fn: Callable,
144
+ cls_info: Any,
145
+ kwargs: dict[str, Any],
146
+ macro_name: str,
147
+ loc: Any,
148
+ ) -> None:
149
+ """Validate kwargs against macro signature and invoke the macro.
150
+
151
+ Inspects the macro function's signature to check for unknown kwargs,
152
+ missing required kwargs, and type mismatches. Wraps errors as
153
+ SemanticError with the decorator's source location.
154
+ """
155
+ # Deferred: sema.registration imports macro_loader, so importing
156
+ # diagnostics at module level would create a circular import.
157
+ from .diagnostics import SemanticError
158
+
159
+ sig = inspect.signature(macro_fn)
160
+ params = sig.parameters
161
+
162
+ # Skip the first parameter (cls: ClassInfo)
163
+ param_list = list(params.values())
164
+ if not param_list:
165
+ raise SemanticError(
166
+ f"@{macro_name}: macro function must accept a ClassInfo parameter",
167
+ loc,
168
+ )
169
+ _SKIP_KINDS = (inspect.Parameter.VAR_KEYWORD, inspect.Parameter.VAR_POSITIONAL)
170
+ macro_params = {p.name: p for p in param_list[1:] if p.kind not in _SKIP_KINDS}
171
+
172
+ # Check for **kwargs -- if present, skip unknown-kwarg validation
173
+ has_var_keyword = any(
174
+ p.kind == inspect.Parameter.VAR_KEYWORD for p in param_list[1:]
175
+ )
176
+
177
+ # Reject unknown kwargs
178
+ if not has_var_keyword:
179
+ for key in kwargs:
180
+ if key not in macro_params:
181
+ if macro_params:
182
+ known = "(supported: " + ", ".join(sorted(macro_params)) + ")"
183
+ else:
184
+ known = "(takes no keyword arguments)"
185
+ raise SemanticError(
186
+ f"@{macro_name}: unknown keyword argument '{key}' {known}",
187
+ loc,
188
+ )
189
+
190
+ # Check for missing required kwargs (no default value)
191
+ for name, param in macro_params.items():
192
+ if param.default is inspect.Parameter.empty and name not in kwargs:
193
+ raise SemanticError(
194
+ f"@{macro_name}: missing required keyword argument '{name}'",
195
+ loc,
196
+ )
197
+
198
+ # Resolve annotations (handles `from __future__ import annotations`
199
+ # which turns annotations into strings at runtime)
200
+ try:
201
+ hints = typing.get_type_hints(macro_fn)
202
+ except Exception:
203
+ hints = {}
204
+
205
+ # Type-check values against annotations
206
+ for key, value in kwargs.items():
207
+ if key not in macro_params:
208
+ continue
209
+ ann = hints.get(key)
210
+ if ann is None:
211
+ continue
212
+ if not isinstance(ann, type):
213
+ continue
214
+ if not isinstance(value, ann):
215
+ raise SemanticError(
216
+ f"@{macro_name}: '{key}' must be {ann.__name__}, "
217
+ f"got {type(value).__name__} ({value!r})",
218
+ loc,
219
+ )
220
+
221
+ # Call the macro, wrapping unexpected exceptions
222
+ from .macro_api import MacroError, ast as _ast_builder
223
+
224
+ _ast_builder.reset_tmp_counter()
225
+ try:
226
+ macro_fn(cls_info, **kwargs)
227
+ except MacroError as e:
228
+ raise SemanticError(str(e), e.loc or loc) from e
229
+ except SemanticError:
230
+ raise
231
+ except Exception as e:
232
+ raise SemanticError(
233
+ f"@{macro_name}: macro raised {type(e).__name__}: {e}",
234
+ loc,
235
+ ) from e
236
+
237
+
238
+ _EXTRACTABLE_TYPES = (str, int, float, bool)
239
+
240
+
241
+ def _extract_macro_arg_value(macro_arg: Any, expected_type: type, param_name: str,
242
+ macro_name: str, loc: Any) -> Any:
243
+ """Extract a Python value from a MacroArg for simple-typed parameters."""
244
+ from .diagnostics import SemanticError
245
+ from .parse import TpyStrLiteral, TpyIntLiteral, TpyFloatLiteral, TpyBoolLiteral
246
+
247
+ expr = macro_arg.expr
248
+ _LITERAL_MAP = {
249
+ str: (TpyStrLiteral, "a string literal"),
250
+ int: (TpyIntLiteral, "an integer literal"),
251
+ float: (TpyFloatLiteral, "a float literal"),
252
+ bool: (TpyBoolLiteral, "a boolean literal"),
253
+ }
254
+ literal_type, desc = _LITERAL_MAP[expected_type]
255
+ if not isinstance(expr, literal_type):
256
+ raise SemanticError(
257
+ f"{macro_name}(): '{param_name}' must be {desc}", loc)
258
+ return expr.value
259
+
260
+
261
+ def expand_call_macro(
262
+ macro_fn: Callable,
263
+ ctx: Any,
264
+ macro_args: list,
265
+ macro_kwargs: dict,
266
+ macro_name: str,
267
+ loc: Any,
268
+ ) -> Any:
269
+ """Validate args and call a call-site macro, returning the replacement TpyExpr.
270
+
271
+ Kwargs annotated with simple types (str, int, float, bool) are extracted
272
+ from the MacroArg automatically. Wraps unexpected exceptions as SemanticError.
273
+ """
274
+ # Deferred: sema.registration imports macro_loader
275
+ from .diagnostics import SemanticError
276
+ from .macro_api import MacroError, ast as _ast_builder
277
+
278
+ _ast_builder.reset_tmp_counter()
279
+
280
+ # Inspect signature: extract plain values for simple-typed kwargs
281
+ sig = inspect.signature(macro_fn)
282
+ params = list(sig.parameters.values())
283
+ resolved_kwargs: dict[str, Any] = {}
284
+ try:
285
+ hints = typing.get_type_hints(macro_fn)
286
+ except Exception:
287
+ hints = {}
288
+ for key, macro_arg in macro_kwargs.items():
289
+ ann = hints.get(key)
290
+ if isinstance(ann, type) and ann in _EXTRACTABLE_TYPES:
291
+ resolved_kwargs[key] = _extract_macro_arg_value(
292
+ macro_arg, ann, key, macro_name, loc)
293
+ else:
294
+ resolved_kwargs[key] = macro_arg
295
+
296
+ try:
297
+ result = macro_fn(ctx, *macro_args, **resolved_kwargs)
298
+ except MacroError as e:
299
+ raise SemanticError(str(e), e.loc or loc) from e
300
+ except SemanticError:
301
+ raise
302
+ except Exception as e:
303
+ raise SemanticError(
304
+ f"{macro_name}(): macro raised {type(e).__name__}: {e}",
305
+ loc,
306
+ ) from e
307
+
308
+ from .parse import TpyExpr
309
+ if not isinstance(result, TpyExpr):
310
+ raise SemanticError(
311
+ f"{macro_name}(): call macro must return a TpyExpr, "
312
+ f"got {type(result).__name__}",
313
+ loc,
314
+ )
315
+ return result
316
+
317
+
318
+ def _wrap_macro_call(
319
+ fn: Callable, what: str, loc: Any, args: tuple, kwargs: dict,
320
+ ) -> Any:
321
+ """Invoke a builder-macro Python callable, wrapping unexpected
322
+ exceptions as SemanticError. Mirrors expand_call_macro's pattern.
323
+ """
324
+ from .diagnostics import SemanticError
325
+ from .macro_api import MacroError, ast as _ast_builder
326
+ _ast_builder.reset_tmp_counter()
327
+ try:
328
+ return fn(*args, **kwargs)
329
+ except MacroError as e:
330
+ raise SemanticError(str(e), e.loc or loc) from e
331
+ except SemanticError:
332
+ raise
333
+ except Exception as e:
334
+ raise SemanticError(
335
+ f"{what}: macro raised {type(e).__name__}: {e}", loc) from e
336
+
337
+
338
+ def validate_builder_macro(
339
+ macro_cls: type, ctx_obj: Any, args: Any, qname: str, loc: Any,
340
+ ) -> Any:
341
+ """Instantiate a @builder_macro state class.
342
+
343
+ ``macro_cls`` is the user-defined class. ``ctx_obj`` is a
344
+ ``BuilderContext`` (passed positionally to ``__init__``). ``args`` is
345
+ a ``MacroArgs`` value carrying the constructor's positional + kw
346
+ arguments. Returns the constructed state instance.
347
+ """
348
+ return _wrap_macro_call(
349
+ macro_cls, qname, loc, (ctx_obj, args), {})
350
+
351
+
352
+ def expand_builder_method(
353
+ handler: Callable, qname: str, ctx_obj: Any, args: Any, loc: Any,
354
+ ) -> Any:
355
+ """Invoke a @builder_method / @builder_returns / @builder_terminal
356
+ handler bound to its state instance. Returns the handler's return
357
+ value (None for void steps; child instance for builder_returns;
358
+ TypeInfo for builder_terminal).
359
+ """
360
+ return _wrap_macro_call(
361
+ handler, qname, loc, (ctx_obj, args), {})
362
+
363
+
364
+ class MacroRegistry:
365
+ """Registry of loaded class macros.
366
+
367
+ Maps ``(module_name, decorator_name)`` to the Python callable that
368
+ implements the macro.
369
+ """
370
+
371
+ def __init__(self, search_dirs: list[Path] | None = None) -> None:
372
+ self._macros: dict[tuple[str, str], Callable] = {}
373
+ self._call_macros: dict[tuple[str, str], Callable] = {}
374
+ # Builder-trace macros: (module, name) -> class object
375
+ self._builder_macros: dict[tuple[str, str], type] = {}
376
+ self._modules: dict[str, Any] = {}
377
+ self._loaded_modules: set[str] = set()
378
+ # module_name -> {dep_module: names_or_None}
379
+ # None means all exports, list means specific names only.
380
+ self._macro_deps: dict[str, dict[str, list[str] | None]] = {}
381
+ # Lib search dirs for resolving macro-to-macro imports
382
+ self._search_dirs: list[Path] = list(search_dirs or [])
383
+ # Guard against circular macro imports
384
+ self._loading: set[str] = set()
385
+
386
+ def register(self, module: str, name: str, func: Callable) -> None:
387
+ self._macros[(module, name)] = func
388
+
389
+ def get_macro(self, module: str, name: str) -> Callable | None:
390
+ return self._macros.get((module, name))
391
+
392
+ def get_call_macro(self, module: str, name: str) -> Callable | None:
393
+ return self._call_macros.get((module, name))
394
+
395
+ def get_builder_macro(self, module: str, name: str) -> type | None:
396
+ """Look up a @builder_macro state class by (module, name)."""
397
+ return self._builder_macros.get((module, name))
398
+
399
+ def builder_macro_modules(self) -> set[str]:
400
+ """Module names that have any registered @builder_macro classes."""
401
+ return {mod for mod, _ in self._builder_macros}
402
+
403
+ def has_builder_macros(self) -> bool:
404
+ """True if any @builder_macro classes are registered."""
405
+ return bool(self._builder_macros)
406
+
407
+ def get_export(self, module: str, name: str) -> Any | None:
408
+ """Look up any exported name from a loaded macro module."""
409
+ mod = self._modules.get(module)
410
+ if mod is None:
411
+ return None
412
+ return getattr(mod, name, None)
413
+
414
+ def get_deps(self, module_name: str) -> dict[str, list[str] | None]:
415
+ """Return MACRO_DEPS for a loaded macro module.
416
+
417
+ Returns dict mapping dep module name to list of specific names (or None
418
+ for all exports). Empty dict if no deps declared.
419
+ """
420
+ return self._macro_deps.get(module_name, {})
421
+
422
+ def _resolve_macro_import(self, name: str) -> Any | None:
423
+ """Resolve an import to another macro module from lib search paths.
424
+
425
+ Returns the loaded module object, or None if not found.
426
+ """
427
+ if name in self._modules:
428
+ return self._modules[name]
429
+ if name in self._loading:
430
+ raise ImportError(f"Circular macro module import: '{name}'")
431
+ for d in self._search_dirs:
432
+ path = d / Path(name.replace(".", "/")).with_suffix(".py")
433
+ if path.is_file():
434
+ source = path.read_text()
435
+ if is_macro_module_source(source):
436
+ self.load_module(name, path)
437
+ return self._modules.get(name)
438
+ return None
439
+
440
+ def is_loaded(self, module_name: str) -> bool:
441
+ return module_name in self._loaded_modules
442
+
443
+ def load_module(self, module_name: str, file_path: Path) -> None:
444
+ """Load a macro module via CPython and register its exports.
445
+
446
+ Functions decorated with ``@class_macro`` are registered automatically.
447
+ """
448
+ if module_name in self._loaded_modules:
449
+ return
450
+
451
+ # Ensure tpyc is importable (macro modules import from tpyc.macro_api)
452
+ tpyc_parent = str(Path(__file__).resolve().parent.parent)
453
+ if tpyc_parent not in sys.path:
454
+ sys.path.insert(0, tpyc_parent)
455
+
456
+ spec = importlib.util.spec_from_file_location(
457
+ f"_tpy_macro_{module_name}", str(file_path)
458
+ )
459
+ if spec is None or spec.loader is None:
460
+ raise RuntimeError(
461
+ f"Cannot load macro module '{module_name}' from {file_path}"
462
+ )
463
+
464
+ mod = importlib.util.module_from_spec(spec)
465
+ mod.__builtins__ = _make_restricted_builtins(module_name, self)
466
+ self._loading.add(module_name)
467
+ try:
468
+ spec.loader.exec_module(mod)
469
+ except Exception as e:
470
+ _macro_api._pending_macro_deps = None
471
+ raise RuntimeError(
472
+ f"Error executing macro module '{module_name}' ({file_path}): {e}"
473
+ ) from e
474
+ finally:
475
+ self._loading.discard(module_name)
476
+
477
+ self._modules[module_name] = mod
478
+
479
+ # Read deps registered via macro_deps() during module execution
480
+ if _macro_api._pending_macro_deps is not None:
481
+ self._macro_deps[module_name] = _macro_api._pending_macro_deps
482
+ _macro_api._pending_macro_deps = None
483
+
484
+ # Scan for @class_macro and @call_macro decorated functions, and
485
+ # @builder_macro decorated classes.
486
+ for attr_name in dir(mod):
487
+ obj = getattr(mod, attr_name)
488
+ if isinstance(obj, type) and getattr(obj, '_is_builder_macro', False):
489
+ self._builder_macros[(module_name, attr_name)] = obj
490
+ continue
491
+ if callable(obj):
492
+ if getattr(obj, '_is_class_macro', False):
493
+ self.register(module_name, attr_name, obj)
494
+ if getattr(obj, '_is_call_macro', False):
495
+ self._call_macros[(module_name, attr_name)] = obj
496
+
497
+ self._loaded_modules.add(module_name)
tpyc/module_names.py ADDED
@@ -0,0 +1,64 @@
1
+ """Module-name normalization helpers."""
2
+ from __future__ import annotations
3
+
4
+ from typing import TYPE_CHECKING
5
+
6
+ if TYPE_CHECKING:
7
+ from .typesys import TypeRegistry
8
+
9
+
10
+ def module_from_qname(qname: str, registry: TypeRegistry) -> str | None:
11
+ """Return the module whose generated header declares the named
12
+ symbol, used to drive `#include` emission and cross-module lookups.
13
+
14
+ A `@builtin_type` record's qname is a TPy-side label that need not
15
+ match its defining file: `Poll` is tagged `tpy.coro.Poll` but
16
+ declared in `tpy/_core/_types.py`. Prefix-walking the qname to
17
+ `tpy.coro` would route includes through the wrong header. For
18
+ records, consult the registry's qname indexes directly and return
19
+ `RecordInfo.module`. The two indexes (`_qname_index` for builtins,
20
+ `_user_qname_index` for user records) are accessed in preference to
21
+ the public `find_record_by_qname` because its short-name fallback
22
+ walks every module's records dict (O(workspace size)), wrong for a
23
+ helper that runs on every nominal type during reach analysis.
24
+
25
+ Falls back to a prefix walk for enums, protocols, parser
26
+ placeholders, and any other qname not in the record indexes.
27
+ """
28
+ record = registry._qname_index.get(qname) or registry._user_qname_index.get(qname)
29
+ if record is not None and record.module:
30
+ return record.module
31
+ parts = qname.split(".")
32
+ for i in range(len(parts) - 1, 0, -1):
33
+ candidate = ".".join(parts[:i])
34
+ if registry.get_module(candidate) is not None:
35
+ return candidate
36
+ if len(parts) >= 2:
37
+ return parts[0]
38
+ return None
39
+
40
+
41
+ def public_module_name(module_name: str, cpp_namespace: str | None = None) -> str:
42
+ """Map a private submodule name to its public module identity.
43
+
44
+ e.g. "tpy._core._types" -> "tpy", "tpy._builtins._list" -> "tpy"
45
+
46
+ When cpp_namespace is provided (e.g. "tpystd::typing" for tpy._typing),
47
+ derives the public name from the namespace instead of the module path.
48
+ This handles cross-package implementations like typing protocols defined
49
+ in tpy._typing.
50
+ """
51
+ if cpp_namespace and "._" in module_name:
52
+ # Derive from namespace: "tpystd::typing" -> "typing", "tpystd::tpy" -> "tpy"
53
+ ns_parts = cpp_namespace.split("::")
54
+ # Skip the common prefix (e.g. "tpystd") and join the rest
55
+ if len(ns_parts) >= 2 and ns_parts[0] == "tpystd":
56
+ return ".".join(ns_parts[1:])
57
+ parts = module_name.split(".")
58
+ # Keep only parts up to (but not including) the first private component
59
+ public_parts = []
60
+ for part in parts:
61
+ if part.startswith("_"):
62
+ break
63
+ public_parts.append(part)
64
+ return ".".join(public_parts) if public_parts else module_name
@@ -0,0 +1,31 @@
1
+ """
2
+ TurboPython built-in modules infrastructure.
3
+
4
+ Provides a registry for built-in functions and types that can be used
5
+ by the semantic analyzer and code generator.
6
+ """
7
+
8
+ # --- Data classes, constants ---
9
+ from tpyc.modules.defs import ( # noqa: F401
10
+ ParamDef, MethodDef,
11
+ DUNDER_CPP_TEMPLATES, get_dunder_cpp_template,
12
+ BINOP_TO_METHOD, BINOP_TO_RMETHOD, AUGOP_TO_IMETHOD, UNARYOP_TO_METHOD,
13
+ )
14
+
15
+ # --- Module registry ---
16
+ from tpyc.modules.registry import ( # noqa: F401
17
+ get_builtin_module_names, get_builtin_type_obj,
18
+ )
19
+
20
+ # --- Method resolution, iteration helpers ---
21
+ # (Generic type factories and lookups live in `tpyc.type_def_registry`;
22
+ # import from there directly.)
23
+ from tpyc.modules.type_resolution import ( # noqa: F401
24
+ _resolve_concrete_type_name, _resolve_extends_type_arg,
25
+ extract_type_params, resolve_method,
26
+ ITERABLE_PROTOCOL_QNAMES,
27
+ is_native_iterable, get_extends_protocol_type_arg,
28
+ get_error_return_next_element_type,
29
+ get_iter_element_type, get_iterable_element_type,
30
+ get_span_element_type, get_span_return_type,
31
+ )
tpyc/modules/defs.py ADDED
@@ -0,0 +1,89 @@
1
+ """
2
+ Built-in module data classes and constant tables.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from dataclasses import dataclass, field
8
+ from typing import TYPE_CHECKING
9
+
10
+ if TYPE_CHECKING:
11
+ from tpyc.typesys import TpyType
12
+
13
+
14
+ @dataclass
15
+ class ParamDef:
16
+ """Parameter definition for a function/method."""
17
+ name: str
18
+ type: "TpyType" # TpyType, use TypeParamRef("T") for type params
19
+ requires_mutable_lvalue: bool = False
20
+
21
+
22
+ @dataclass
23
+ class MethodDef:
24
+ """Definition of a function overload or type method."""
25
+ params: list[ParamDef]
26
+ returns: "TpyType" # TpyType, use TypeParamRef("T") for type params
27
+ cpp: str # Template: "{0}" for args, "{self}" for receiver
28
+ is_noalloc: bool = False
29
+ is_readonly: bool = False
30
+ is_pure: bool = False
31
+ is_static: bool = False
32
+ # Per-method type params and bounds (for constraining class-level type params)
33
+ type_params: list[str] = field(default_factory=list)
34
+ type_param_bounds: dict[str, "TpyType"] = field(default_factory=dict)
35
+
36
+
37
+ # C++ expression templates for Python dunder methods.
38
+ # Used when .py-defined protocols don't carry cpp templates.
39
+ DUNDER_CPP_TEMPLATES: dict[str, str] = {
40
+ "__len__": "::tpy::__len__({self})",
41
+ "__getitem__": "::tpy::__getitem__({self}, {0})",
42
+ "__setitem__": "::tpy::__setitem__({self}, {0}, {1})",
43
+ "__iter__": "::tpy::__iter__({self})",
44
+ "__next__": "{self}.__next__()",
45
+ "__contains__": "::tpy::__contains__({self}, {0})",
46
+ "__delitem__": "::tpy::__delitem__({self}, {0})",
47
+ "__bool__": "::tpy::__bool__({self})",
48
+ "__str__": "::tpy::__str__({self})",
49
+ "__repr__": "::tpy::repr_of({self})",
50
+ "__hash__": "::tpy::__hash__({self})",
51
+ "__deref__": "::tpy::deref_check({self})",
52
+ "__span__": "::tpy::as_span({self})",
53
+ }
54
+
55
+
56
+ def get_dunder_cpp_template(method_name: str) -> str | None:
57
+ """Get the C++ expression template for a dunder method, or None."""
58
+ return DUNDER_CPP_TEMPLATES.get(method_name)
59
+
60
+
61
+ # Operator to method name mappings
62
+ BINOP_TO_METHOD = {
63
+ "+": "__add__", "-": "__sub__", "*": "__mul__",
64
+ "div": "__truediv__", "//": "__floordiv__", "%": "__mod__", "**": "__pow__",
65
+ "<<": "__lshift__", ">>": "__rshift__",
66
+ "&": "__and__", "|": "__or__", "^": "__xor__",
67
+ "==": "__eq__", "!=": "__ne__",
68
+ "<": "__lt__", "<=": "__le__", ">": "__gt__", ">=": "__ge__",
69
+ }
70
+
71
+ BINOP_TO_RMETHOD = {
72
+ "+": "__radd__", "-": "__rsub__", "*": "__rmul__",
73
+ "div": "__rtruediv__", "//": "__rfloordiv__", "%": "__rmod__", "**": "__rpow__",
74
+ "<<": "__rlshift__", ">>": "__rrshift__",
75
+ "&": "__rand__", "|": "__ror__", "^": "__rxor__",
76
+ }
77
+
78
+ AUGOP_TO_IMETHOD = {
79
+ "+": "__iadd__", "-": "__isub__", "*": "__imul__",
80
+ "div": "__itruediv__", "//": "__ifloordiv__", "%": "__imod__",
81
+ "<<": "__ilshift__", ">>": "__irshift__",
82
+ "|": "__ior__", "&": "__iand__", "^": "__ixor__",
83
+ }
84
+
85
+ UNARYOP_TO_METHOD = {
86
+ "+": "__pos__",
87
+ "-": "__neg__",
88
+ "~": "__invert__",
89
+ }