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,597 @@
1
+ # random -- CPython-compatible Mersenne Twister (MT19937) + distributions.
2
+ #
3
+ # Pure-TPy port of the upstream MT19937 reference (Matsumoto & Nishimura)
4
+ # and CPython's `_randommodule.c` seeding + CPython's `random.Random`
5
+ # distribution methods. For a non-negative Int32 seed that fits in one
6
+ # uint32 word, getrandbits(32) / random() return byte-identical output to
7
+ # CPython after the same seed. Distributions (gauss, gammavariate,
8
+ # normalvariate, etc.) are straight ports of CPython's Lib/random.py so the
9
+ # per-seed output stream matches CPython exactly -- the cpython-phase test
10
+ # in cases/stdlib/random verifies this.
11
+ #
12
+ # Architecture:
13
+ # - Random: class holding the 624-word MT state vector plus cached
14
+ # second value from gauss() / normalvariate(). Per-instance RNGs and
15
+ # all distribution methods live here.
16
+ # - Module-level `_inst: Random` singleton, mutated in place by `seed()`.
17
+ # Module-level `random()`, `randint()`, ... delegate to `_inst`.
18
+ #
19
+ # Thread safety: the module-level functions share `_inst` and are NOT
20
+ # thread-safe. Concurrent calls from multiple threads can corrupt the
21
+ # 624-word state (double-twist, interleaved index updates, torn reads).
22
+ # This is currently theoretical because TPy has no threading primitives
23
+ # -- when `threading` lands we'll need to pick a model (thread-local
24
+ # _inst / lock inside Random / deprecate module-level in favour of
25
+ # explicit instances) and revisit. CPython punts the same way: its docs
26
+ # tell users to use per-thread `Random()` instances, and free-threaded
27
+ # CPython (PEP 703, 3.13+) added internal locking to the C module.
28
+ # Until then, multi-threaded code should construct its own `Random(seed)`
29
+ # per thread rather than calling `random.random()` directly.
30
+ #
31
+ # TODO -- Tier 2 (should work, haven't pressure-tested):
32
+ # - `getstate()` / `setstate(state)`: TPy can't easily synthesize a
33
+ # 625-tuple to match CPython's state type. A `list[UInt32]`-based
34
+ # shape works but is not CPython-compat.
35
+ #
36
+ # TODO -- Tier 3 (genuinely blocked on language work or missing
37
+ # primitives):
38
+ # - `choices(pop, weights=, cum_weights=, k=)`: mechanical sigs +
39
+ # weighted-selection wiring. The list-literal-vs-Iterable[T]
40
+ # conformance gap that used to block this is now resolved.
41
+ # - `sample(pop, k, counts=None)`: more involved algorithm (reservoir /
42
+ # Floyd's) + same signature shape.
43
+ # - `SystemRandom`: needs class-hierarchy decisions (subclass Random
44
+ # with overrides, or standalone class). The OS entropy primitive
45
+ # itself is wired (see `_os_entropy_uint32`).
46
+ # - `seed(int)` for BigInt / `seed(bytes)` / `seed(str)`: need BigInt
47
+ # word-iteration for the key array and/or bytes hashing.
48
+ # - `binomialvariate(n, p)`: BTRS algorithm (Hormann 1993) is a
49
+ # multi-case state machine and needs gauss()-driven path; defer until
50
+ # demand surfaces.
51
+ #
52
+ # User-visible caveats (limitations of the currently-shipped API):
53
+ # - `seed(n)` takes any Int32 (negatives are mapped to abs()); BigInt /
54
+ # bytes / str seeds are not accepted (see Tier 3 above).
55
+ # - `randint(a, b)` requires `b - a + 1` to fit in Int32. `randint(0,
56
+ # INT32_MAX)` panics on the width computation. Use explicit `Random`
57
+ # instances with custom code for wider ranges today.
58
+ # - `randbytes(n)` produces byte-identical output to CPython's
59
+ # `getrandbits(n*8).to_bytes(n, 'little')` for all n on any host,
60
+ # including `n % 4 != 0` (partial-word packing uses the TOP bytes of
61
+ # the final uint32, per CPython's getrandbits packing).
62
+ # - `getrandbits(0)` raises `ValueError`. CPython returns 0 for k=0;
63
+ # supporting it would require special-casing the BigInt zero return
64
+ # and is rarely used. Match CPython if a real workload needs it.
65
+ # - `choice([])` raises `ValueError`. CPython raises `IndexError`; TPy
66
+ # doesn't yet have `IndexError` as a catchable type (STDLIB_ROADMAP
67
+ # "builtins" section). Switch to `IndexError` once it lands.
68
+ #
69
+ # Uses `UInt32.add_wrap / sub_wrap / mul_wrap / shl_wrap` for the modular
70
+ # arithmetic MT needs (TPy's +/-/*/<< on fixed-width ints are
71
+ # overflow-checked).
72
+ #
73
+ # Performance notes (bench: tpyc -xO, x86_64, ccache):
74
+ # Raw engine (genrand_uint32): ~2 ns/call (hand-C++ same algo: 1.2 ns)
75
+ # random() (genrand_res53): ~7 ns/call (hand-C++ same algo: 3 ns)
76
+ # randint(a, b): ~10 ns/call
77
+ # Comparison: CPython's random() is ~54 ns/call; std::mt19937 (different
78
+ # distribution algo) is ~3 ns/call for `uniform_real_distribution`.
79
+ #
80
+ # The ~0.8-4 ns gap vs same-algorithm hand-C++ is pure TPy safety overhead
81
+ # in the hot path, not codegen style or algorithm. Disassembly of
82
+ # _genrand_uint32 shows four sources, each individually tiny but additive:
83
+ # - `__getitem__` bounds check on `_state[_index]` (`ja` branch +
84
+ # `cmovs` for the negative-index normalize). `_index` is provably in
85
+ # [0, N) from the `if _index >= N: generate()` guard, but the
86
+ # optimizer doesn't see through it.
87
+ # - `add_check<int32_t>` overflow check on `_index += 1` (`jo` branch).
88
+ # `_index` is provably <= N = 624, never overflows.
89
+ # - `-fstack-protector` canary (fs:0x28 load + compare on exit).
90
+ # Build-config overhead, not random-specific.
91
+ #
92
+ # Possible future optimizations when/if the language supports them (none
93
+ # of these are worth adding ad-hoc workarounds for today -- the module is
94
+ # already ~7x faster than CPython, diminishing returns from here):
95
+ # - `@unchecked` / `@noalloc` function attribute that suppresses
96
+ # add_check/sub_check/mul_check and list bounds checks inside the
97
+ # body. Would close most of the gap in one pass.
98
+ # - `tpy.unsafe.get_unchecked(arr, i)` for bounds-free subscript at
99
+ # specific sites. More surgical than @unchecked.
100
+ # - Sema value-range analysis proving `_index in [0, 624)` so the
101
+ # bounds check in `__getitem__` folds away. Already scaffolded for
102
+ # other uses (tpyc/sema/value_range.py); would need plumbing to
103
+ # codegen's __getitem__ lowering.
104
+ # - `-fno-stack-protector` on release / noalloc builds (compiler-flag
105
+ # decision, affects all code).
106
+ # tpy: cpp_namespace("tpystd::random")
107
+ # tpy: include("<tpy/stdlib/random.hpp>")
108
+ from tpy import Int32, UInt8, UInt32, Array, copy
109
+ from tpy.extern import native
110
+ from typing import overload
111
+ import math
112
+
113
+
114
+ @native("tpy::stdlib::random::os_entropy_uint32")
115
+ def _os_entropy_uint32() -> UInt32: ...
116
+
117
+ _N: Int32 = 624
118
+ _M: Int32 = 397
119
+ _MATRIX_A: UInt32 = 0x9908b0df
120
+ _UPPER_MASK: UInt32 = 0x80000000
121
+ _LOWER_MASK: UInt32 = 0x7fffffff
122
+
123
+ # Constants for distributions, mirroring CPython's Lib/random.py.
124
+ _TWOPI: float = 2.0 * math.pi
125
+ _LOG4: float = math.log(4.0)
126
+ _SG_MAGICCONST: float = 1.0 + math.log(4.5)
127
+ _NV_MAGICCONST: float = 4.0 * math.exp(-0.5) / math.sqrt(2.0)
128
+
129
+ class Random:
130
+ # Inline fixed-size state (std::array<uint32_t, 624>). Stack-allocated,
131
+ # compile-time size enables bounds-check elision in __getitem__, and
132
+ # loop unrolling / auto-vectorization in the twist. Measured ~3x
133
+ # speedup vs list[UInt32] on MT hot path.
134
+ _state: Array[UInt32, 624]
135
+ _index: Int32
136
+ # Cached second value from gauss()'s Box-Muller pair. Matches CPython's
137
+ # self.gauss_next using a bool flag instead of float|None sentinel.
138
+ _gauss_next: float
139
+ _has_gauss_next: bool
140
+
141
+ def __init__(self, seed_value: UInt32 | None = None) -> None:
142
+ # std::array<uint32_t, 624>{} zero-inits every slot.
143
+ self._state = Array[UInt32, 624]()
144
+ self._index = _N
145
+ self._gauss_next = 0.0
146
+ self._has_gauss_next = False
147
+ if seed_value is None:
148
+ self._seed(_os_entropy_uint32())
149
+ else:
150
+ self._seed(seed_value)
151
+
152
+ def _init_genrand(self, s: UInt32) -> None:
153
+ self._state[0] = s
154
+ mti: Int32 = 1
155
+ while mti < _N:
156
+ prev: UInt32 = self._state[mti - 1]
157
+ self._state[mti] = UInt32.add_wrap(
158
+ UInt32.mul_wrap(1812433253, prev ^ (prev >> 30)),
159
+ UInt32(mti),
160
+ )
161
+ mti += 1
162
+ self._index = _N
163
+
164
+ def _seed(self, s: UInt32) -> None:
165
+ # CPython's init_by_array specialised for a single-uint32 key [s].
166
+ self._init_genrand(19650218)
167
+ key0: UInt32 = s
168
+ key_length: Int32 = 1
169
+ i: Int32 = 1
170
+ j: Int32 = 0
171
+ k: Int32 = _N
172
+ if k < key_length:
173
+ k = key_length
174
+ while k > 0:
175
+ prev: UInt32 = self._state[i - 1]
176
+ mixed: UInt32 = UInt32.mul_wrap(prev ^ (prev >> 30), 1664525)
177
+ self._state[i] = UInt32.add_wrap(
178
+ UInt32.add_wrap(self._state[i] ^ mixed, key0),
179
+ UInt32(j),
180
+ )
181
+ i += 1
182
+ j += 1
183
+ if i >= _N:
184
+ self._state[0] = self._state[_N - 1]
185
+ i = 1
186
+ if j >= key_length:
187
+ j = 0
188
+ k -= 1
189
+ k = _N - 1
190
+ while k > 0:
191
+ prev2: UInt32 = self._state[i - 1]
192
+ mixed2: UInt32 = UInt32.mul_wrap(prev2 ^ (prev2 >> 30), 1566083941)
193
+ self._state[i] = UInt32.sub_wrap(self._state[i] ^ mixed2, UInt32(i))
194
+ i += 1
195
+ if i >= _N:
196
+ self._state[0] = self._state[_N - 1]
197
+ i = 1
198
+ k -= 1
199
+ # MSB=1 ensures non-zero initial state.
200
+ self._state[0] = 0x80000000
201
+ self._index = _N
202
+ # Reset cached gauss value on reseed -- matches CPython's
203
+ # Random.seed() setting self.gauss_next = None.
204
+ self._has_gauss_next = False
205
+
206
+ def _generate(self) -> None:
207
+ kk: Int32 = 0
208
+ while kk < _N - _M:
209
+ y: UInt32 = (self._state[kk] & _UPPER_MASK) | (self._state[kk + 1] & _LOWER_MASK)
210
+ mag: UInt32 = 0
211
+ if (y & 1) != 0:
212
+ mag = _MATRIX_A
213
+ self._state[kk] = self._state[kk + _M] ^ (y >> 1) ^ mag
214
+ kk += 1
215
+ while kk < _N - 1:
216
+ y2: UInt32 = (self._state[kk] & _UPPER_MASK) | (self._state[kk + 1] & _LOWER_MASK)
217
+ mag2: UInt32 = 0
218
+ if (y2 & 1) != 0:
219
+ mag2 = _MATRIX_A
220
+ self._state[kk] = self._state[kk + _M - _N] ^ (y2 >> 1) ^ mag2
221
+ kk += 1
222
+ y3: UInt32 = (self._state[_N - 1] & _UPPER_MASK) | (self._state[0] & _LOWER_MASK)
223
+ mag3: UInt32 = 0
224
+ if (y3 & 1) != 0:
225
+ mag3 = _MATRIX_A
226
+ self._state[_N - 1] = self._state[_M - 1] ^ (y3 >> 1) ^ mag3
227
+ self._index = 0
228
+
229
+ def _genrand_uint32(self) -> UInt32:
230
+ if self._index >= _N:
231
+ self._generate()
232
+ y: UInt32 = self._state[self._index]
233
+ self._index += 1
234
+ # Tempering.
235
+ y = y ^ (y >> 11)
236
+ y = y ^ (UInt32.shl_wrap(y, 7) & 0x9d2c5680)
237
+ y = y ^ (UInt32.shl_wrap(y, 15) & 0xefc60000)
238
+ y = y ^ (y >> 18)
239
+ return y
240
+
241
+ def random(self) -> float:
242
+ # genrand_res53 -- 53-bit uniform in [0, 1), matches CPython.
243
+ a: UInt32 = self._genrand_uint32() >> 5 # top 27 bits
244
+ b: UInt32 = self._genrand_uint32() >> 6 # top 26 bits
245
+ return (float(a) * 67108864.0 + float(b)) * (1.0 / 9007199254740992.0)
246
+
247
+ def _genrand_top_bits(self, k: Int32) -> UInt32:
248
+ # k in [1, 32]. Avoids the BigInt promotion that public
249
+ # getrandbits does, so _randbelow's rejection loop stays uint32.
250
+ return self._genrand_uint32() >> UInt32(32 - k)
251
+
252
+ def getrandbits(self, k: Int32) -> int:
253
+ # CPython-compatible: returns an int (BigInt) of k random bits.
254
+ # k in [1, 32] uses one MT word; k > 32 concatenates ceil(k/32)
255
+ # words little-endian (word[0] = low 32 bits), matching CPython.
256
+ if k <= 0:
257
+ raise ValueError("number of bits must be greater than zero")
258
+ if k <= 32:
259
+ return int(self._genrand_top_bits(k))
260
+ numwords: Int32 = (k + 31) // 32
261
+ result: int = int(0)
262
+ i: Int32 = 0
263
+ while i < numwords - 1:
264
+ result = result | (int(self._genrand_uint32()) << (32 * i))
265
+ i += 1
266
+ last_k: Int32 = k - 32 * i
267
+ last_word: UInt32 = self._genrand_uint32() >> UInt32(32 - last_k)
268
+ result = result | (int(last_word) << (32 * i))
269
+ return result
270
+
271
+ # ---------- Integer helpers ----------
272
+
273
+ def _randbelow(self, n: UInt32) -> UInt32:
274
+ # Uniform int in [0, n) via rejection sampling over a top-bits
275
+ # slice where k = bit_length(n). Matches CPython's
276
+ # _randbelow_with_getrandbits. Using bit_length(n-1) would agree
277
+ # for non-power-of-2 widths but draws fewer bits per call for
278
+ # powers of 2, diverging the MT stream from CPython.
279
+ if n == 0:
280
+ raise ValueError("_randbelow requires positive n")
281
+ if n == 1:
282
+ return 0
283
+ m: UInt32 = n
284
+ k: Int32 = 0
285
+ while m > 0:
286
+ k += 1
287
+ m = m >> 1
288
+ r: UInt32 = self._genrand_top_bits(k)
289
+ while r >= n:
290
+ r = self._genrand_top_bits(k)
291
+ return r
292
+
293
+ def randint(self, a: Int32, b: Int32) -> Int32:
294
+ # Inclusive [a, b]. v1 constraint: b - a + 1 must fit in Int32
295
+ # (i.e. b - a <= INT32_MAX - 1). CPython handles arbitrary ints.
296
+ if b < a:
297
+ raise ValueError("empty range for randint()")
298
+ width: Int32 = b - a + 1
299
+ return a + Int32(self._randbelow(UInt32(width)))
300
+
301
+ @overload
302
+ def randrange(self, stop: Int32) -> Int32:
303
+ if stop <= 0:
304
+ raise ValueError("empty range for randrange()")
305
+ return Int32(self._randbelow(UInt32(stop)))
306
+
307
+ @overload
308
+ def randrange(self, start: Int32, stop: Int32) -> Int32:
309
+ if stop <= start:
310
+ raise ValueError("empty range for randrange()")
311
+ return start + Int32(self._randbelow(UInt32(stop - start)))
312
+
313
+ @overload
314
+ def randrange(self, start: Int32, stop: Int32, step: Int32) -> Int32:
315
+ if step == 0:
316
+ raise ValueError("zero step for randrange()")
317
+ width: Int32 = 0
318
+ if step > 0:
319
+ if stop <= start:
320
+ raise ValueError("empty range for randrange()")
321
+ # ceil((stop - start) / step)
322
+ width = (stop - start + step - 1) // step
323
+ else:
324
+ if stop >= start:
325
+ raise ValueError("empty range for randrange()")
326
+ neg_step: Int32 = -step
327
+ width = (start - stop + neg_step - 1) // neg_step
328
+ return start + step * Int32(self._randbelow(UInt32(width)))
329
+
330
+ def randbytes(self, n: Int32) -> bytes:
331
+ # Matches CPython's `self.getrandbits(n * 8).to_bytes(n, 'little')`.
332
+ # Full uint32 chunks yield their 4 bytes low-to-high (little-endian).
333
+ # The last partial word uses its TOP `rem*8` bits (CPython's
334
+ # getrandbits shifts each final word right by `32 - remaining_k`
335
+ # before packing), so the partial bytes come from
336
+ # `(w >> (32 - rem*8 + k*8)) & 0xff` for k in [0, rem).
337
+ if n < 0:
338
+ raise ValueError("n must be non-negative")
339
+ out: bytearray = bytearray()
340
+ i: Int32 = 0
341
+ full: Int32 = n // 4
342
+ while i < full:
343
+ v: UInt32 = self._genrand_uint32()
344
+ out.append(UInt8(v & 0xFF))
345
+ out.append(UInt8((v >> 8) & 0xFF))
346
+ out.append(UInt8((v >> 16) & 0xFF))
347
+ out.append(UInt8((v >> 24) & 0xFF))
348
+ i += 1
349
+ rem: Int32 = n - full * 4
350
+ if rem > 0:
351
+ w: UInt32 = self._genrand_uint32()
352
+ shift_base: Int32 = 32 - rem * 8
353
+ j: Int32 = 0
354
+ while j < rem:
355
+ out.append(UInt8((w >> UInt32(shift_base + j * 8)) & 0xFF))
356
+ j += 1
357
+ return bytes(out)
358
+
359
+ # ---------- Sequence helpers ----------
360
+
361
+ def choice[T](self, seq: list[T]) -> T:
362
+ n: Int32 = Int32(len(seq))
363
+ if n == 0:
364
+ # ValueError instead of CPython's IndexError -- see caveats.
365
+ raise ValueError("Cannot choose from an empty sequence")
366
+ return copy(seq[Int32(self._randbelow(UInt32(n)))])
367
+
368
+ def shuffle[T](self, seq: list[T]) -> None:
369
+ # Fisher-Yates / Durstenfeld in place. Matches CPython's
370
+ # random.shuffle MT call sequence (one _randbelow(i+1) per step,
371
+ # i from len-1 down to 1).
372
+ i: Int32 = Int32(len(seq)) - 1
373
+ while i > 0:
374
+ j: Int32 = Int32(self._randbelow(UInt32(i + 1)))
375
+ tmp: T = copy(seq[i])
376
+ seq[i] = copy(seq[j])
377
+ seq[j] = tmp
378
+ i -= 1
379
+
380
+ # ---------- Continuous distributions ----------
381
+ # All straight ports of CPython's Lib/random.py methods. Byte-identical
382
+ # output on the same seed because libm (cos/sin/log/exp/sqrt) is the
383
+ # same underlying implementation under CPython and TPy on Linux.
384
+
385
+ def uniform(self, a: float, b: float) -> float:
386
+ return a + (b - a) * self.random()
387
+
388
+ def triangular(self, low: float = 0.0, high: float = 1.0, mode: float | None = None) -> float:
389
+ u: float = self.random()
390
+ if high == low:
391
+ return low
392
+ c: float = 0.5
393
+ if mode is not None:
394
+ c = (mode - low) / (high - low)
395
+ if u > c:
396
+ u = 1.0 - u
397
+ c = 1.0 - c
398
+ # CPython swaps low/high here; equivalent rewrite:
399
+ return high + (low - high) * math.sqrt(u * c)
400
+ return low + (high - low) * math.sqrt(u * c)
401
+
402
+ def gauss(self, mu: float, sigma: float) -> float:
403
+ # Box-Muller. Matches CPython's self.gauss(), which caches the
404
+ # second generated value for the next call.
405
+ if self._has_gauss_next:
406
+ z: float = self._gauss_next
407
+ self._has_gauss_next = False
408
+ return mu + z * sigma
409
+ x2pi: float = self.random() * _TWOPI
410
+ g2rad: float = math.sqrt(-2.0 * math.log(1.0 - self.random()))
411
+ z2: float = math.cos(x2pi) * g2rad
412
+ self._gauss_next = math.sin(x2pi) * g2rad
413
+ self._has_gauss_next = True
414
+ return mu + z2 * sigma
415
+
416
+ def normalvariate(self, mu: float, sigma: float) -> float:
417
+ # Kinderman-Monahan method, distinct from gauss(). Matches CPython.
418
+ # Does NOT populate _gauss_next: each call consumes fresh MT words.
419
+ # gauss() and normalvariate() produce uncorrelated streams even when
420
+ # interleaved; _gauss_next is gauss-only state.
421
+ while True:
422
+ u1: float = self.random()
423
+ u2: float = 1.0 - self.random()
424
+ z: float = _NV_MAGICCONST * (u1 - 0.5) / u2
425
+ zz: float = z * z / 4.0
426
+ if zz <= -math.log(u2):
427
+ return mu + z * sigma
428
+
429
+ def lognormvariate(self, mu: float, sigma: float) -> float:
430
+ return math.exp(self.normalvariate(mu, sigma))
431
+
432
+ def expovariate(self, lambd: float) -> float:
433
+ # 1.0 - random() is in (0, 1], so log is in (-inf, 0], result >= 0.
434
+ return -math.log(1.0 - self.random()) / lambd
435
+
436
+ def paretovariate(self, alpha: float) -> float:
437
+ u: float = 1.0 - self.random()
438
+ return u ** (-1.0 / alpha)
439
+
440
+ def weibullvariate(self, alpha: float, beta: float) -> float:
441
+ u: float = 1.0 - self.random()
442
+ return alpha * (-math.log(u)) ** (1.0 / beta)
443
+
444
+ def gammavariate(self, alpha: float, beta: float) -> float:
445
+ # CPython's algorithm: Cheng (1977) for alpha > 1, exponential for
446
+ # alpha == 1, Ahrens-Dieter for 0 < alpha < 1.
447
+ if alpha <= 0.0 or beta <= 0.0:
448
+ raise ValueError("gammavariate: alpha and beta must be > 0")
449
+ if alpha > 1.0:
450
+ ainv: float = math.sqrt(2.0 * alpha - 1.0)
451
+ bbb: float = alpha - _LOG4
452
+ ccc: float = alpha + ainv
453
+ while True:
454
+ u1: float = self.random()
455
+ if u1 <= 1e-7 or u1 >= 0.9999999:
456
+ continue
457
+ u2: float = 1.0 - self.random()
458
+ v: float = math.log(u1 / (1.0 - u1)) / ainv
459
+ x: float = alpha * math.exp(v)
460
+ z: float = u1 * u1 * u2
461
+ r: float = bbb + ccc * v - x
462
+ if r + _SG_MAGICCONST - 4.5 * z >= 0.0 or r >= math.log(z):
463
+ return x * beta
464
+ if alpha == 1.0:
465
+ return -math.log(1.0 - self.random()) * beta
466
+ # 0 < alpha < 1: Ahrens-Dieter rejection sampling.
467
+ b: float = (math.e + alpha) / math.e
468
+ while True:
469
+ u: float = self.random()
470
+ p: float = b * u
471
+ x2: float = 0.0
472
+ if p <= 1.0:
473
+ x2 = p ** (1.0 / alpha)
474
+ else:
475
+ x2 = -math.log((b - p) / alpha)
476
+ u1b: float = self.random()
477
+ if p > 1.0:
478
+ if u1b <= x2 ** (alpha - 1.0):
479
+ return x2 * beta
480
+ else:
481
+ if u1b <= math.exp(-x2):
482
+ return x2 * beta
483
+
484
+ def betavariate(self, alpha: float, beta: float) -> float:
485
+ y: float = self.gammavariate(alpha, 1.0)
486
+ if y <= 0.0:
487
+ return 0.0
488
+ return y / (y + self.gammavariate(beta, 1.0))
489
+
490
+ def vonmisesvariate(self, mu: float, kappa: float) -> float:
491
+ if kappa <= 1e-6:
492
+ return _TWOPI * self.random()
493
+ s: float = 0.5 / kappa
494
+ r: float = s + math.sqrt(1.0 + s * s)
495
+ z: float = 0.0
496
+ while True:
497
+ u1: float = self.random()
498
+ z = math.cos(math.pi * u1)
499
+ d: float = z / (r + z)
500
+ u2: float = self.random()
501
+ if u2 < 1.0 - d * d or u2 <= (1.0 - d) * math.exp(d):
502
+ break
503
+ q: float = 1.0 / r
504
+ f: float = (q + z) / (1.0 + q * z)
505
+ u3: float = self.random()
506
+ mu_mod: float = mu % _TWOPI
507
+ theta: float = 0.0
508
+ if u3 > 0.5:
509
+ theta = mu_mod + math.acos(f)
510
+ else:
511
+ theta = mu_mod - math.acos(f)
512
+ return theta % _TWOPI
513
+
514
+
515
+ _inst: Random = Random()
516
+
517
+ # ---------- Module-level convenience API ----------
518
+ # All delegate to the singleton _inst. CPython does the same.
519
+
520
+ def random() -> float:
521
+ return _inst.random()
522
+
523
+ @overload
524
+ def seed() -> None:
525
+ # No-arg form: re-seed from OS entropy (matches CPython's seed()
526
+ # default behavior when called without arguments).
527
+ _inst._seed(_os_entropy_uint32())
528
+
529
+ @overload
530
+ def seed(n: Int32) -> None:
531
+ # CPython treats negative seeds as their absolute value. For
532
+ # INT32_MIN the mathematical abs doesn't fit in Int32, but
533
+ # `0 - n` in UInt32 (mod 2^32) equals abs(n) for any negative n.
534
+ if n < 0:
535
+ _inst._seed(UInt32.sub_wrap(UInt32(0), UInt32.trunc(n)))
536
+ else:
537
+ _inst._seed(UInt32(n))
538
+
539
+ def getrandbits(k: Int32) -> int:
540
+ return _inst.getrandbits(k)
541
+
542
+ def randint(a: Int32, b: Int32) -> Int32:
543
+ return _inst.randint(a, b)
544
+
545
+ def choice[T](seq: list[T]) -> T:
546
+ return _inst.choice(seq)
547
+
548
+ def shuffle[T](seq: list[T]) -> None:
549
+ _inst.shuffle(seq)
550
+
551
+ @overload
552
+ def randrange(stop: Int32) -> Int32:
553
+ return _inst.randrange(stop)
554
+
555
+ @overload
556
+ def randrange(start: Int32, stop: Int32) -> Int32:
557
+ return _inst.randrange(start, stop)
558
+
559
+ @overload
560
+ def randrange(start: Int32, stop: Int32, step: Int32) -> Int32:
561
+ return _inst.randrange(start, stop, step)
562
+
563
+ def randbytes(n: Int32) -> bytes:
564
+ return _inst.randbytes(n)
565
+
566
+ def uniform(a: float, b: float) -> float:
567
+ return _inst.uniform(a, b)
568
+
569
+ def triangular(low: float = 0.0, high: float = 1.0, mode: float | None = None) -> float:
570
+ return _inst.triangular(low, high, mode)
571
+
572
+ def gauss(mu: float, sigma: float) -> float:
573
+ return _inst.gauss(mu, sigma)
574
+
575
+ def normalvariate(mu: float, sigma: float) -> float:
576
+ return _inst.normalvariate(mu, sigma)
577
+
578
+ def lognormvariate(mu: float, sigma: float) -> float:
579
+ return _inst.lognormvariate(mu, sigma)
580
+
581
+ def expovariate(lambd: float) -> float:
582
+ return _inst.expovariate(lambd)
583
+
584
+ def paretovariate(alpha: float) -> float:
585
+ return _inst.paretovariate(alpha)
586
+
587
+ def weibullvariate(alpha: float, beta: float) -> float:
588
+ return _inst.weibullvariate(alpha, beta)
589
+
590
+ def gammavariate(alpha: float, beta: float) -> float:
591
+ return _inst.gammavariate(alpha, beta)
592
+
593
+ def betavariate(alpha: float, beta: float) -> float:
594
+ return _inst.betavariate(alpha, beta)
595
+
596
+ def vonmisesvariate(mu: float, kappa: float) -> float:
597
+ return _inst.vonmisesvariate(mu, kappa)