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,467 @@
1
+ # tpy: cpp_namespace("tpystd::re")
2
+ """Regular expressions, CPython-compatible surface, backed by PCRE2.
3
+
4
+ Architecture:
5
+ * `_bindings.pcre2` -- raw @native bindings to the PCRE2 C API.
6
+ * this module -- pure-TPy facade. Pattern / Match classes manage PCRE2
7
+ handle lifetimes via __del__. All Python semantics (flag mapping, group
8
+ accessors, sub/split logic, error model) live here, not in C++.
9
+
10
+ Slice 1 surface:
11
+ * compile(), search(), match(), fullmatch(), findall(), sub(), split()
12
+ * Pattern + Match classes with the methods above.
13
+ * Flags: IGNORECASE, MULTILINE, DOTALL, VERBOSE, ASCII (CPython bit values).
14
+ * `re.error` exception, raised on invalid patterns.
15
+
16
+ TODO(v2): items deferred to a follow-up slice -- each is independent:
17
+ * `re.compile` cache. Needs module-level mutable state (see
18
+ STDLIB_ROADMAP "stdlib-enablement workstream"). Until then,
19
+ `re.search("...", s)` in a hot loop is slower than caching a Pattern.
20
+ * Named-group accessors: `match.group("name")` / `match.groupdict()`.
21
+ Needs PCRE2 nametable walk + named-group index lookup.
22
+ * finditer as a true generator (currently returns list[Own[Match]]).
23
+ Loses streaming; minor for typical use, real for huge subjects.
24
+ * bytes input on the public API (today: str only). Pattern + Match
25
+ accept str; PCRE2 internally takes uint8_t* + length, so the lower
26
+ layer is bytes-ready.
27
+ * Python -> PCRE2 syntax translator. Not required for the current
28
+ surface (PCRE2 accepts Python's `(?P<name>...)` form natively for
29
+ back-compat). Add when we hit a real divergence -- candidates:
30
+ `\1`-style backrefs in `sub` replacements, `(?#comment)` syntax,
31
+ a few Unicode property edge cases.
32
+ * `count` arg on `Pattern.sub` / module-level `sub` (limit number of
33
+ replacements). Naive impl: walk finditer + manual splice; cleaner:
34
+ a single `pcre2_substitute` call in non-global mode, looped.
35
+ * `Match.span` / `start` / `end` returning `int` (BigInt) instead of
36
+ `Int32` to match CPython exactly. Today they return `Int32` -- in
37
+ practice tuple printing happens to match CPython, but type inference
38
+ for downstream code differs (e.g. arithmetic on Match.start() picks
39
+ Int32 ops vs CPython's int).
40
+ * `Pattern.__repr__` / `Match.__repr__` matching CPython's format
41
+ (`re.compile('...')` / `<re.Match object; span=(a, b), match='...'>`).
42
+ Blocked on a Python-style `repr(str)` helper (escape backslashes,
43
+ quotes, non-printables) and a flag-bits-to-name decoder. Land together
44
+ to avoid asymmetric support.
45
+ """
46
+
47
+ from __future__ import annotations
48
+ from typing import Final, Optional
49
+ from tpy import (
50
+ Int32, UInt8, UInt32, UInt64, Ptr, readonly, Own, String, nocopy,
51
+ )
52
+ from tpy.extern import cpp_template
53
+ from tpy.mem import UninitArrayStorage, UninitHeapStorage
54
+ from tpy.unsafe import unsafe_ptr, unsafe_cast, unsafe_load, unsafe_str_from_buf
55
+ from tpy import take_ptr
56
+
57
+ # Bare `0`/`1` flow through to `size_t` / `uint32_t` PCRE2 args because the
58
+ # compiler treats integer literals (and literal-seeded locals like
59
+ # `offset = 0`) as polymorphic enough to retro-fit unsigned targets when
60
+ # the value provably fits. The remaining `UInt64(...)` / `UInt32(...)`
61
+ # casts in this file are on `len(...)` results (BigInt) and other typed
62
+ # sources, where a runtime narrowing check is intentional.
63
+ from _bindings import pcre2
64
+
65
+
66
+ # ---------- RAII wrappers for PCRE2 handles ----------
67
+ # Every handle is wrapped in an @nocopy owning type so the corresponding
68
+ # free runs automatically on scope exit (returns, raises, field-holding
69
+ # record destruction). All three free functions are null-safe, so __del__
70
+ # needs no null check.
71
+ #
72
+ # @nocopy+__del__ wrappers have their auto default ctor suppressed, so
73
+ # the enclosing record's field init must MIL-hoist (RHS references only
74
+ # ctor params / module-level names, no body-locals). That's why _OwnedCode
75
+ # takes high-level args in __init__ and delegates the multi-step PCRE2
76
+ # call sequence to a staticmethod returning Ptr[pcre2.Code] -- the
77
+ # dangling-return check trusts locals bound from call returns.
78
+
79
+
80
+ @nocopy
81
+ class _OwnedMatchData:
82
+ _p: Ptr[pcre2.MatchData]
83
+ def __init__(self, p: Ptr[pcre2.MatchData]) -> None:
84
+ self._p = p
85
+ def __del__(self) -> None:
86
+ pcre2.match_data_free(self._p)
87
+ def get(self) -> Ptr[pcre2.MatchData]:
88
+ return self._p
89
+
90
+
91
+ # ---------- re.error exception ----------
92
+ # Must be defined BEFORE _OwnedCode because its _compile staticmethod is
93
+ # emitted inline in the generated header and throws `error`, which
94
+ # requires a complete type at the throw site (not just a forward decl).
95
+ class error(Exception):
96
+ """Raised when PCRE2 rejects a pattern at compile time, or hits a
97
+ match-time error (rare). Catchable as a normal exception.
98
+
99
+ Caller-side gap that still bites: `except re.error:` is blocked by
100
+ the qualified-except-clause limitation (BUGS.md). Users today
101
+ must `from re import error` (no alias) then `except error:`.
102
+ """
103
+ pass
104
+
105
+
106
+ # Convert a PCRE2 negative error code into a human-readable message via
107
+ # pcre2_get_error_message. Buffer is stack-allocated 256 bytes via
108
+ # UninitArrayStorage -- RAII, no manual free.
109
+ def _pcre2_error_msg(errcode: Int32) -> str:
110
+ buf = UninitArrayStorage[UInt8, 256]()
111
+ n = pcre2.get_error_message(errcode, buf.ptr(), 256)
112
+ if n < 0:
113
+ return "unknown error"
114
+ return unsafe_str_from_buf(unsafe_cast(buf.ptr()), UInt64(n))
115
+
116
+
117
+ @nocopy
118
+ class _OwnedCode:
119
+ _p: Ptr[pcre2.Code]
120
+ def __init__(self, pattern: str, flags: Int32) -> None:
121
+ self._p = _OwnedCode._compile(pattern, flags)
122
+ def __del__(self) -> None:
123
+ pcre2.code_free(self._p)
124
+ def get(self) -> Ptr[pcre2.Code]:
125
+ return self._p
126
+
127
+ @staticmethod
128
+ def _compile(pattern: str, flags: Int32) -> Ptr[pcre2.Code]:
129
+ errcode: Int32 = 0
130
+ erroff: UInt64 = 0
131
+ opts = _to_pcre2_opts(flags)
132
+ p_data: Ptr[readonly[UInt8]] = unsafe_cast(unsafe_ptr(pattern))
133
+ code = pcre2.compile(p_data, UInt64(len(pattern)),
134
+ opts, take_ptr(errcode), take_ptr(erroff),
135
+ None)
136
+ if code is None:
137
+ msg = _pcre2_error_msg(errcode)
138
+ raise error(f"compile error at offset {erroff}: {msg}")
139
+ return code
140
+
141
+
142
+ @nocopy
143
+ class _OwnedMatchContext:
144
+ _p: Ptr[pcre2.MatchContext]
145
+ def __init__(self) -> None:
146
+ self._p = pcre2.match_context_create(None)
147
+ def __del__(self) -> None:
148
+ pcre2.match_context_free(self._p)
149
+ def get(self) -> Ptr[pcre2.MatchContext]:
150
+ return self._p
151
+
152
+
153
+ # ---------- Public flag constants (CPython-compatible bit values) ----------
154
+
155
+ # User-facing flags are `Int32`: the total bit surface is tiny (max 256),
156
+ # negative values are never valid, and Int32 is TPy's DefaultInt so users
157
+ # don't need to write `UInt32(...)` when mixing flags with bare literals.
158
+ # Internally `_to_pcre2_opts` translates to PCRE2's `UInt32` flag space
159
+ # where top-bit values like pcre2.PCRE2_ANCHORED require the wider unsigned range.
160
+ NOFLAG: Final[Int32] = 0
161
+ IGNORECASE: Final[Int32] = 2
162
+ MULTILINE: Final[Int32] = 8
163
+ DOTALL: Final[Int32] = 16
164
+ VERBOSE: Final[Int32] = 64
165
+ ASCII: Final[Int32] = 256
166
+
167
+ # Short aliases (CPython exposes both forms).
168
+ I: Final[Int32] = IGNORECASE
169
+ M: Final[Int32] = MULTILINE
170
+ S: Final[Int32] = DOTALL
171
+ X: Final[Int32] = VERBOSE
172
+ A: Final[Int32] = ASCII
173
+
174
+
175
+ def _to_pcre2_opts(flags: Int32) -> UInt32:
176
+ """Translate `re.*` flag bits to PCRE2 option bits.
177
+
178
+ UTF + UCP are on by default (matches CPython str-mode regex behavior:
179
+ Unicode-aware \\d, \\w, \\s, case-folding). `re.ASCII` opts out.
180
+ """
181
+ opts: UInt32 = pcre2.PCRE2_UTF | pcre2.PCRE2_UCP
182
+ if (flags & IGNORECASE) != 0:
183
+ opts |= pcre2.PCRE2_CASELESS
184
+ if (flags & MULTILINE) != 0:
185
+ opts |= pcre2.PCRE2_MULTILINE
186
+ if (flags & DOTALL) != 0:
187
+ opts |= pcre2.PCRE2_DOTALL
188
+ if (flags & VERBOSE) != 0:
189
+ opts |= pcre2.PCRE2_EXTENDED
190
+ if (flags & ASCII) != 0:
191
+ opts &= ~(pcre2.PCRE2_UTF | pcre2.PCRE2_UCP)
192
+ return opts
193
+
194
+
195
+ # ---------- Match ----------
196
+
197
+ class Match:
198
+ """Result of a successful match. Owns its PCRE2 match-data block (via
199
+ the `_OwnedMatchData` wrapper -- freed automatically on destruction)
200
+ and a copy of the subject string (so group() can return slices that
201
+ outlive the originating user variable)."""
202
+
203
+ _md: _OwnedMatchData
204
+ _subject: str
205
+ _ngroups: Int32 # number of populated entries in the ovector
206
+
207
+ def __init__(self, md: Own[_OwnedMatchData], subject: str,
208
+ ngroups: Int32) -> None:
209
+ self._md = md
210
+ self._subject = subject
211
+ self._ngroups = ngroups
212
+
213
+ def _ovec_load(self, i: UInt32) -> UInt64:
214
+ ovec = pcre2.get_ovector_pointer(self._md.get())
215
+ return unsafe_load(ovec, i)
216
+
217
+ def span(self, group: Int32 = 0) -> tuple[Int32, Int32]:
218
+ """(start, end) byte offsets of `group` in the subject. (-1, -1)
219
+ means the group did not participate.
220
+
221
+ TODO(v2): non-participating group should surface as `(-1, -1)` to
222
+ match CPython; today returns `(0, 0)`. Trivial to fix once the
223
+ Match accessor APIs commit to either Int32 or BigInt return type
224
+ (-1 needs a signed type)."""
225
+ if group < 0 or group >= self._ngroups:
226
+ raise error(f"no such group: {group}")
227
+ start = self._ovec_load(UInt32.trunc(group * 2))
228
+ end = self._ovec_load(UInt32.trunc(group * 2 + 1))
229
+ if start == pcre2.PCRE2_UNSET or end == pcre2.PCRE2_UNSET:
230
+ return (0, 0)
231
+ return (Int32.trunc(start), Int32.trunc(end))
232
+
233
+ def start(self, group: Int32 = 0) -> Int32:
234
+ return self.span(group)[0]
235
+
236
+ def end(self, group: Int32 = 0) -> Int32:
237
+ return self.span(group)[1]
238
+
239
+ def group(self, i: Int32 = 0) -> str:
240
+ """Substring of the subject for `group` (0 = full match)."""
241
+ s, e = self.span(i)
242
+ return self._subject[s:e]
243
+
244
+ def groups(self) -> Own[list[str]]:
245
+ """All capture groups as a list (excluding group 0).
246
+
247
+ TODO(v2): return `tuple[str, ...]` to match CPython instead of
248
+ list. Blocked on varadic-tuple support in TPy."""
249
+ out: list[str] = []
250
+ for i in range(1, self._ngroups):
251
+ out.append(self.group(i))
252
+ return out
253
+
254
+
255
+ # ---------- Pattern ----------
256
+
257
+ class Pattern:
258
+ """Compiled regex. Holds the PCRE2 code + match-context handles; the
259
+ _OwnedCode / _OwnedMatchContext wrappers free them on destruction."""
260
+
261
+ _code: _OwnedCode
262
+ _mctx: _OwnedMatchContext
263
+ pattern: str
264
+ flags: Int32
265
+
266
+ def __init__(self, pattern: str, flags: Int32 = NOFLAG) -> None:
267
+ # Both field initializers reference only ctor params / module-level
268
+ # names -- no body-locals -- so they MIL-hoist into move-construction
269
+ # (safe on @nocopy+__del__ fields).
270
+ self._code = _OwnedCode(pattern, flags)
271
+ self._mctx = _OwnedMatchContext()
272
+ # JIT-compile for ~10x match speedup. Failure here is non-fatal --
273
+ # PCRE2 falls back to interpreted matching on patterns the JIT
274
+ # can't handle.
275
+ pcre2.jit_compile(self._code.get(), pcre2.PCRE2_JIT_COMPLETE)
276
+ self.pattern = pattern
277
+ self.flags = flags
278
+
279
+ def _do_match(self, subject: str, start_offset: UInt64,
280
+ opts: UInt32) -> Optional[Own[Match]]:
281
+ md_raw = pcre2.match_data_create_from_pattern(self._code.get(), None)
282
+ if md_raw is None:
283
+ raise error("out of memory allocating match data")
284
+ md = _OwnedMatchData(md_raw)
285
+ s_data: Ptr[readonly[UInt8]] = unsafe_cast(unsafe_ptr(subject))
286
+ rc = pcre2.match(self._code.get(), s_data, UInt64(len(subject)),
287
+ start_offset, opts, md.get(), self._mctx.get())
288
+ if rc < 0:
289
+ if rc == pcre2.PCRE2_ERROR_NOMATCH:
290
+ return None # md drops here, frees automatically
291
+ raise error(_pcre2_error_msg(rc)) # same
292
+ return Match(md, subject, rc) # md moves into the Match
293
+
294
+ def search(self, subject: str) -> Optional[Own[Match]]:
295
+ return self._do_match(subject, 0, 0)
296
+
297
+ def match(self, subject: str) -> Optional[Own[Match]]:
298
+ return self._do_match(subject, 0, pcre2.PCRE2_ANCHORED)
299
+
300
+ def fullmatch(self, subject: str) -> Optional[Own[Match]]:
301
+ return self._do_match(subject, 0,
302
+ pcre2.PCRE2_ANCHORED | pcre2.PCRE2_ENDANCHORED)
303
+
304
+ def finditer(self, subject: str) -> Own[list[Match]]:
305
+ """All non-overlapping matches as a list.
306
+
307
+ TODO(v2): return a true generator like CPython (lazy iteration).
308
+ Today materializes the full list -- fine for typical cases, real
309
+ memory cost on huge subjects."""
310
+ out: list[Match] = []
311
+ offset: UInt64 = 0
312
+ sub_len = UInt64(len(subject))
313
+ s_data: Ptr[readonly[UInt8]] = unsafe_cast(unsafe_ptr(subject))
314
+ while offset <= sub_len:
315
+ md_raw = pcre2.match_data_create_from_pattern(self._code.get(), None)
316
+ if md_raw is None:
317
+ raise error("out of memory allocating match data")
318
+ md = _OwnedMatchData(md_raw)
319
+ rc = pcre2.match(self._code.get(), s_data, sub_len, offset,
320
+ 0, md.get(), self._mctx.get())
321
+ if rc < 0:
322
+ if rc == pcre2.PCRE2_ERROR_NOMATCH:
323
+ break # md drops at end of iteration
324
+ raise error(_pcre2_error_msg(rc)) # md drops
325
+ ovec = pcre2.get_ovector_pointer(md.get())
326
+ mstart = unsafe_load(ovec, 0)
327
+ mend = unsafe_load(ovec, 1)
328
+ out.append(Match(md, subject, rc)) # md moves into Match
329
+ # Bump-along by one byte on zero-width match to avoid an
330
+ # infinite loop.
331
+ if mend == mstart:
332
+ offset = mend + 1
333
+ else:
334
+ offset = mend
335
+ return out
336
+
337
+ def findall(self, subject: str) -> Own[list[str]]:
338
+ """All non-overlapping match strings (group 0).
339
+
340
+ TODO(v2): for patterns with capture groups, CPython returns a list
341
+ of capture-tuples (or single captures for one-group patterns), not
342
+ the whole-match string. Today we always return group(0) regardless
343
+ of pattern shape -- divergence flagged in `no_cpython.txt`."""
344
+ out: list[str] = []
345
+ # TODO(compiler): the natural form `for m in self.finditer(subject):`
346
+ # fails C++ compilation -- "cannot bind non-const lvalue reference
347
+ # to rvalue" -- because finditer returns `Own[list[Match]]`. See
348
+ # BUGS.md entry "Iterating directly over a call that returns
349
+ # Own[list[T]]". When the codegen fix lands (use `auto&&` for the
350
+ # iteration temp on rvalue iterables), drop the `matches` local.
351
+ matches = self.finditer(subject)
352
+ for m in matches:
353
+ out.append(m.group(Int32(0)))
354
+ return out
355
+
356
+ def sub(self, repl: str, subject: str) -> str:
357
+ """Replace every match of the pattern in `subject` with `repl`.
358
+ PCRE2-native backref syntax: $1..$9, ${name}.
359
+
360
+ TODO(v2): support CPython's `count` parameter (limit number of
361
+ replacements). Naive: walk finditer + manual splice; cleaner: loop
362
+ `pcre2_substitute` in non-global mode `count` times.
363
+
364
+ TODO(v2): translate CPython's `\\1`-style backref syntax in `repl`
365
+ to PCRE2's `$1` so users can copy regex code over without
366
+ rewriting replacements. Today `\\1` is treated as a literal."""
367
+ sub_data: Ptr[readonly[UInt8]] = unsafe_cast(unsafe_ptr(subject))
368
+ repl_data: Ptr[readonly[UInt8]] = unsafe_cast(unsafe_ptr(repl))
369
+ # `outlen` is both input (buffer capacity PCRE2 reads on entry) and
370
+ # output (actual bytes written / bytes needed). A plain local +
371
+ # take_ptr avoids needing a separate single-cell storage object.
372
+ # `outbuf` is heap-allocated via UninitHeapStorage -- freed on
373
+ # scope exit, including the raise path and on retry-reassignment.
374
+ # `cap` stays as an explicit UInt64(...) cast because len() returns
375
+ # Int32; the signed->unsigned conversion isn't automatic in TPy
376
+ # (cross-sign widening is unsigned->signed-only). See BUGS.md.
377
+ cap = UInt64(len(subject) * 2 + len(repl) + 16)
378
+ outlen: UInt64 = cap
379
+ outbuf = UninitHeapStorage[UInt8](UInt32.trunc(cap))
380
+ opts = pcre2.PCRE2_SUBSTITUTE_GLOBAL | pcre2.PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
381
+ rc = pcre2.substitute(
382
+ self._code.get(), sub_data, UInt64(len(subject)),
383
+ 0, opts, None, self._mctx.get(),
384
+ repl_data, UInt64(len(repl)),
385
+ outbuf.ptr(), take_ptr(outlen),
386
+ )
387
+ if rc == pcre2.PCRE2_ERROR_NOMEMORY:
388
+ # PCRE2 wrote the required size into outlen. Reallocate outbuf
389
+ # at that exact size (reassignment drops the old storage).
390
+ # Drop OVERFLOW_LENGTH on retry: buffer is now correctly sized,
391
+ # and asking for overflow-length again would make PCRE2 redo
392
+ # the sizing pass for nothing.
393
+ outbuf = UninitHeapStorage[UInt8](UInt32.trunc(outlen))
394
+ rc = pcre2.substitute(
395
+ self._code.get(), sub_data, UInt64(len(subject)),
396
+ 0, pcre2.PCRE2_SUBSTITUTE_GLOBAL, None,
397
+ self._mctx.get(), repl_data, UInt64(len(repl)),
398
+ outbuf.ptr(), take_ptr(outlen),
399
+ )
400
+ if rc < 0:
401
+ raise error(_pcre2_error_msg(rc))
402
+ return unsafe_str_from_buf(unsafe_cast(outbuf.ptr()), outlen)
403
+
404
+ def split(self, subject: str, maxsplit: Int32 = 0) -> Own[list[str]]:
405
+ """Split `subject` at each match. `maxsplit=0` means no limit."""
406
+ out: list[str] = []
407
+ offset: UInt64 = 0
408
+ splits: Int32 = 0
409
+ sub_len = UInt64(len(subject))
410
+ s_data: Ptr[readonly[UInt8]] = unsafe_cast(unsafe_ptr(subject))
411
+ md_raw = pcre2.match_data_create_from_pattern(self._code.get(), None)
412
+ if md_raw is None:
413
+ raise error("out of memory allocating match data")
414
+ md = _OwnedMatchData(md_raw)
415
+ while offset <= sub_len:
416
+ if maxsplit > Int32(0) and splits >= maxsplit:
417
+ break
418
+ rc = pcre2.match(self._code.get(), s_data, sub_len, offset,
419
+ 0, md.get(), self._mctx.get())
420
+ if rc < 0:
421
+ if rc == pcre2.PCRE2_ERROR_NOMATCH:
422
+ break
423
+ raise error(_pcre2_error_msg(rc)) # md drops
424
+ ovec = pcre2.get_ovector_pointer(md.get())
425
+ mstart = unsafe_load(ovec, 0)
426
+ mend = unsafe_load(ovec, 1)
427
+ out.append(subject[Int32.trunc(offset):Int32.trunc(mstart)])
428
+ if mend == mstart:
429
+ offset = mend + 1
430
+ else:
431
+ offset = mend
432
+ splits += Int32(1)
433
+ out.append(subject[Int32.trunc(offset):])
434
+ return out # md drops at end of scope
435
+
436
+
437
+ # ---------- Module-level wrappers ----------
438
+ # CPython's `re.compile` returns a Pattern; we do the same.
439
+ # `re.search("...", subj)` etc. compile-and-throw-away -- the compile cache
440
+ # that CPython has needs module-level mutable state, deferred.
441
+
442
+ def compile(pattern: str, flags: Int32 = NOFLAG) -> Own[Pattern]:
443
+ return Pattern(pattern, flags)
444
+
445
+ def search(pattern: str, subject: str,
446
+ flags: Int32 = NOFLAG) -> Optional[Own[Match]]:
447
+ return Pattern(pattern, flags).search(subject)
448
+
449
+ def match(pattern: str, subject: str,
450
+ flags: Int32 = NOFLAG) -> Optional[Own[Match]]:
451
+ return Pattern(pattern, flags).match(subject)
452
+
453
+ def fullmatch(pattern: str, subject: str,
454
+ flags: Int32 = NOFLAG) -> Optional[Own[Match]]:
455
+ return Pattern(pattern, flags).fullmatch(subject)
456
+
457
+ def findall(pattern: str, subject: str,
458
+ flags: Int32 = NOFLAG) -> Own[list[str]]:
459
+ return Pattern(pattern, flags).findall(subject)
460
+
461
+ def sub(pattern: str, repl: str, subject: str,
462
+ flags: Int32 = NOFLAG) -> str:
463
+ return Pattern(pattern, flags).sub(repl, subject)
464
+
465
+ def split(pattern: str, subject: str, maxsplit: Int32 = Int32(0),
466
+ flags: Int32 = NOFLAG) -> Own[list[str]]:
467
+ return Pattern(pattern, flags).split(subject, maxsplit)