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,354 @@
1
+ # tpy: macro_module
2
+ """Dataclass macro for TurboPython.
3
+
4
+ This module implements @dataclass as a compile-time class macro.
5
+ It is loaded by the compiler via CPython (not compiled to C++).
6
+ """
7
+
8
+ from tpyc.macro_api import (
9
+ ClassInfo, FieldInfo, TypeInfo, CallMacroContext, MacroArg, MacroError,
10
+ class_macro, call_macro,
11
+ expr_to_cpp_default, ast, types, Expr, Stmt, Function, Type,
12
+ )
13
+ from _macro_helpers import (
14
+ ORDER_DUNDERS, build_init, build_eq, build_repr, build_hash, build_order,
15
+ )
16
+
17
+ _MISSING = object()
18
+
19
+ # Module-level registry: tracks which records were built by @dataclass.
20
+ # Class macro writes here; call macros (asdict/astuple) read it.
21
+ _dataclass_records: set[str] = set()
22
+
23
+
24
+ class Field:
25
+ """Descriptor returned by field(). Inspected by @dataclass macro."""
26
+
27
+ def __init__(self, *, default=_MISSING, default_factory=_MISSING):
28
+ if default is not _MISSING and default_factory is not _MISSING:
29
+ raise TypeError("cannot specify both 'default' and 'default_factory'")
30
+ if default is _MISSING and default_factory is _MISSING:
31
+ raise TypeError("requires 'default' or 'default_factory'")
32
+ self.default = default
33
+ self.default_factory = default_factory
34
+
35
+
36
+ def field(*, default=_MISSING, default_factory=_MISSING) -> Field:
37
+ """Declare field metadata in @dataclass classes."""
38
+ return Field(default=default, default_factory=default_factory)
39
+
40
+
41
+ @class_macro
42
+ def dataclass(cls: ClassInfo, *, frozen: bool = False, order: bool = False) -> None:
43
+ """Transform a class into a dataclass with auto-generated methods."""
44
+ cls.is_frozen = frozen
45
+
46
+ _process_field_defaults(cls)
47
+
48
+ # Only inherit fields from parent @dataclass records
49
+ parent_name = cls.parent.name if cls.parent else None
50
+ if parent_name and parent_name in _dataclass_records:
51
+ parent_fields = cls.get_parent_fields()
52
+ _validate_frozen_consistency(cls, frozen)
53
+ else:
54
+ parent_fields = []
55
+ all_fields = parent_fields + cls.fields
56
+ has_parent = len(parent_fields) > 0
57
+
58
+ # Synthesize __init__ (silently skipped when the user wrote one --
59
+ # matches CPython, which also defers to an explicit __init__).
60
+ if not cls.has_method("__init__"):
61
+ if not all_fields:
62
+ raise MacroError(
63
+ f"@dataclass class '{cls.name}' must have at least one field annotation"
64
+ )
65
+ _validate_field_order(cls, all_fields)
66
+ init_fn = build_init(cls, parent_fields, cls.fields)
67
+ cls.add_method(init_fn)
68
+
69
+ # Synthesize __eq__ (silently skipped when the user wrote one).
70
+ if all_fields and not cls.has_method("__eq__"):
71
+ eq_fn = build_eq(cls, all_fields)
72
+ eq_fn.hides_parent = has_parent
73
+ cls.add_method(eq_fn)
74
+
75
+ # Generate __repr__
76
+ if all_fields and not cls.has_method("__repr__"):
77
+ repr_fn = build_repr(cls, all_fields)
78
+ repr_fn.hides_parent = has_parent
79
+ cls.add_method(repr_fn)
80
+
81
+ # Generate __hash__ for frozen dataclasses
82
+ if frozen and all_fields and not cls.has_method("__hash__"):
83
+ hash_fn = build_hash(cls, all_fields)
84
+ hash_fn.hides_parent = has_parent
85
+ cls.add_method(hash_fn)
86
+
87
+ # Generate ordering methods
88
+ if order and all_fields:
89
+ _synthesize_order_methods(cls, all_fields, has_parent)
90
+
91
+ cls.set_match_args([f.name for f in all_fields])
92
+ _dataclass_records.add(cls.name)
93
+
94
+
95
+ def _process_field_defaults(cls: ClassInfo) -> None:
96
+ """Unwrap Field descriptors set by field() calls."""
97
+ for fld in cls.fields:
98
+ if not isinstance(fld.default_obj, Field):
99
+ continue
100
+ spec = fld.default_obj
101
+ if spec.default is not _MISSING:
102
+ fld.set_default(spec.default, default_value=expr_to_cpp_default(spec.default))
103
+ elif spec.default_factory is not _MISSING:
104
+ factory_name = ast.get_name(spec.default_factory)
105
+ if factory_name is None:
106
+ raise MacroError(
107
+ "default_factory must be a type name (e.g., list, dict, MyRecord)",
108
+ loc=fld.loc,
109
+ )
110
+ factory_call = ast.call(factory_name)
111
+ # Preserve source location on the generated call
112
+ factory_call.loc = fld.loc
113
+ fld.set_default(factory_call, is_factory=True)
114
+
115
+
116
+ def _validate_frozen_consistency(cls: ClassInfo, frozen: bool) -> None:
117
+ """Validate frozen/non-frozen consistency across inheritance."""
118
+ result = cls.is_parent_frozen()
119
+ if result is None:
120
+ return
121
+ parent_frozen, parent_name = result
122
+ if parent_frozen and not frozen:
123
+ raise MacroError(
124
+ f"Cannot inherit non-frozen @dataclass '{cls.name}' "
125
+ f"from frozen @dataclass '{parent_name}'"
126
+ )
127
+ if not parent_frozen and frozen:
128
+ raise MacroError(
129
+ f"Cannot inherit frozen @dataclass '{cls.name}' "
130
+ f"from non-frozen @dataclass '{parent_name}'"
131
+ )
132
+
133
+
134
+ def _validate_field_order(cls: ClassInfo, all_fields: list[FieldInfo]) -> None:
135
+ """Validate no non-default field follows a field with default."""
136
+ seen_default = False
137
+ for fld in all_fields:
138
+ if fld.has_default:
139
+ seen_default = True
140
+ elif seen_default:
141
+ raise MacroError(
142
+ f"Field '{fld.name}' without default follows field with default "
143
+ f"in @dataclass class '{cls.name}'",
144
+ loc=fld.loc,
145
+ )
146
+
147
+
148
+ def _synthesize_order_methods(
149
+ cls: ClassInfo, all_fields: list[FieldInfo], has_parent: bool,
150
+ ) -> None:
151
+ """Add ordering methods for @dataclass(order=True)."""
152
+ for dunder in ORDER_DUNDERS:
153
+ if cls.has_method(dunder):
154
+ raise MacroError(
155
+ f"@dataclass(order=True) cannot overwrite '{dunder}' "
156
+ f"defined in class '{cls.name}'"
157
+ )
158
+ for fn in build_order(cls, all_fields):
159
+ fn.hides_parent = has_parent
160
+ cls.add_method(fn)
161
+
162
+
163
+ # ---------------------------------------------------------------------------
164
+ # Call-site macros: asdict, astuple
165
+ # ---------------------------------------------------------------------------
166
+
167
+ @call_macro
168
+ def asdict(ctx: CallMacroContext, obj: MacroArg) -> Expr:
169
+ """Convert a dataclass instance to a dict."""
170
+ return _build_asdict(ctx, obj.expr, obj.type)
171
+
172
+
173
+ def _has_dc(ctx: CallMacroContext, type_info: TypeInfo) -> bool:
174
+ """Check if a type contains dataclass instances needing recursion."""
175
+ inner = type_info.unwrap_optional()
176
+ if inner is not None:
177
+ return _has_dc(ctx, inner)
178
+ if type_info.is_record and type_info.name in _dataclass_records:
179
+ return True
180
+ # Check dict/tuple before iterable -- iterating a dict yields keys,
181
+ # which would incorrectly match dict[DC_Key, V] as list[DC_Key].
182
+ if type_info.is_dict and len(type_info.type_args) == 2:
183
+ return any(_has_dc(ctx, t) for t in type_info.type_args)
184
+ if type_info.is_tuple and type_info.type_args:
185
+ return any(_has_dc(ctx, t) for t in type_info.type_args)
186
+ # Skip sets: the result (dict) isn't hashable, so set[DC] -> set[DC]
187
+ # unchanged (matches CPython). Only recurse into list-like iterables.
188
+ if type_info.is_set:
189
+ return False
190
+ elem = ctx.get_iterable_element_type(type_info)
191
+ if elem is not None and _has_dc(ctx, elem):
192
+ return True
193
+ return False
194
+
195
+
196
+ def _value_transform(
197
+ ctx: CallMacroContext, access: Expr, fld_type: TypeInfo,
198
+ dc_fn: 'Callable',
199
+ value_fn: 'Callable',
200
+ ) -> Expr:
201
+ """Shared recursion for _asdict_value / _astuple_value.
202
+
203
+ dc_fn: called for direct dataclass fields (e.g. _build_asdict or _build_astuple)
204
+ value_fn: called recursively for nested elements (e.g. _asdict_value or _astuple_value)
205
+ """
206
+ # Optional[T] -> None if access is None else recurse(access, T)
207
+ inner = fld_type.unwrap_optional()
208
+ if inner is not None and _has_dc(ctx, inner):
209
+ # Clone to avoid sharing AST nodes between condition and body --
210
+ # sema sets resolved types on nodes, so reuse would cause overwrites.
211
+ transformed = _value_transform(ctx, ast.clone(access), inner, dc_fn, value_fn)
212
+ return ast.if_expr(
213
+ ast.binop(access, "is not", ast.none_lit()),
214
+ transformed,
215
+ ast.none_lit(),
216
+ )
217
+ if fld_type.is_record and fld_type.name in _dataclass_records:
218
+ return dc_fn(ctx, access, fld_type)
219
+ # dict/tuple before iterable (see _has_dc comment)
220
+ if fld_type.is_dict and len(fld_type.type_args) == 2:
221
+ key_type, val_type = fld_type.type_args
222
+ if _has_dc(ctx, key_type) or _has_dc(ctx, val_type):
223
+ return _build_dict_comprehension(ctx, access, key_type, val_type, value_fn)
224
+ if fld_type.is_tuple and fld_type.type_args:
225
+ if any(_has_dc(ctx, t) for t in fld_type.type_args):
226
+ return _build_tuple_expansion(ctx, access, fld_type.type_args, value_fn)
227
+ elem = ctx.get_iterable_element_type(fld_type)
228
+ if elem is not None and _has_dc(ctx, elem):
229
+ var = ast.fresh_tmp("macro")
230
+ return ast.list_comprehension(
231
+ value_fn(ctx, ast.name(var), elem),
232
+ ast.comprehension_generator(var, access),
233
+ )
234
+ return access
235
+
236
+
237
+ def _build_dict_comprehension(
238
+ ctx: CallMacroContext, access: Expr,
239
+ key_type: TypeInfo, val_type: TypeInfo,
240
+ value_fn: 'Callable',
241
+ ) -> Expr:
242
+ """Expand dict field: {f(k): f(v) for k, v in field.items()}"""
243
+ k_var = ast.fresh_tmp("macro")
244
+ v_var = ast.fresh_tmp("macro")
245
+ items_call = ast.method_call(access, "items")
246
+ return ast.dict_comprehension(
247
+ value_fn(ctx, ast.name(k_var), key_type),
248
+ value_fn(ctx, ast.name(v_var), val_type),
249
+ ast.comprehension_generator("__comp_tup", items_call,
250
+ unpack_vars=[k_var, v_var]),
251
+ )
252
+
253
+
254
+ def _build_tuple_expansion(
255
+ ctx: CallMacroContext, access: Expr,
256
+ elem_types: list[TypeInfo],
257
+ value_fn: 'Callable',
258
+ ) -> Expr:
259
+ """Expand tuple field: (f(field[0]), f(field[1]), ...)"""
260
+ elements = []
261
+ for i, elem_type in enumerate(elem_types):
262
+ subscript = ast.subscript(access, ast.int_lit(i))
263
+ elements.append(value_fn(ctx, subscript, elem_type))
264
+ return ast.tuple_lit(elements)
265
+
266
+
267
+ def _asdict_value(ctx: CallMacroContext, access: Expr, fld_type: TypeInfo) -> Expr:
268
+ """Build the value expression for a single field in asdict expansion."""
269
+ return _value_transform(ctx, access, fld_type, _build_asdict, _asdict_value)
270
+
271
+
272
+ def _build_asdict(ctx: CallMacroContext, expr: Expr, type_info: TypeInfo) -> Expr:
273
+ if type_info.name not in _dataclass_records:
274
+ raise MacroError(f"asdict() requires a @dataclass instance, got '{type_info.name}'")
275
+ fields = ctx.get_record_fields(type_info.name)
276
+ keys = []
277
+ values = []
278
+ value_tpy_types = []
279
+ for fld in fields:
280
+ keys.append(ast.str_lit(fld.name))
281
+ access = ast.field_access(expr, fld.name)
282
+ value = _asdict_value(ctx, access, fld.type)
283
+ values.append(value)
284
+ value_tpy_types.append(_asdict_result_type(ctx, fld.type))
285
+
286
+ dict_literal = ast.dict_lit(keys, values)
287
+
288
+ # For mixed-type fields, wrap in typed dict constructor: dict[str, A|B]({...})
289
+ unique = list(dict.fromkeys(str(t) for t in value_tpy_types))
290
+ if len(unique) > 1:
291
+ value_type = types.union(tuple(value_tpy_types))
292
+ return ast.call("dict", [dict_literal],
293
+ call_type=types.dict(types.str, value_type))
294
+ return dict_literal
295
+
296
+
297
+ def _asdict_result_type(ctx: CallMacroContext, type_info: TypeInfo) -> Type:
298
+ """Compute the result type for a field in asdict expansion."""
299
+ # Optional[T] -> Optional[result_type(T)]
300
+ inner = type_info.unwrap_optional()
301
+ if inner is not None and _has_dc(ctx, inner):
302
+ return types.optional(_asdict_result_type(ctx, inner))
303
+ # Direct dataclass
304
+ if type_info.is_record and type_info.name in _dataclass_records:
305
+ fields = ctx.get_record_fields(type_info.name)
306
+ if fields is None:
307
+ return type_info.raw_type
308
+ value_types = [_asdict_result_type(ctx, fld.type) for fld in fields]
309
+ unique = list(dict.fromkeys(str(t) for t in value_types))
310
+ if len(unique) > 1:
311
+ return types.dict(types.str, types.union(tuple(value_types)))
312
+ return types.dict(types.str, value_types[0])
313
+ # dict/tuple before iterable (same ordering as _has_dc)
314
+ if type_info.is_dict and len(type_info.type_args) == 2:
315
+ key_type, val_type = type_info.type_args
316
+ if _has_dc(ctx, key_type) or _has_dc(ctx, val_type):
317
+ return types.dict(
318
+ _asdict_result_type(ctx, key_type),
319
+ _asdict_result_type(ctx, val_type),
320
+ )
321
+ if type_info.is_tuple and type_info.type_args:
322
+ if any(_has_dc(ctx, t) for t in type_info.type_args):
323
+ return types.tuple(tuple(
324
+ _asdict_result_type(ctx, t) for t in type_info.type_args
325
+ ))
326
+ # list[Dataclass] -> list[dict[...]] (sets excluded by _has_dc)
327
+ elem = ctx.get_iterable_element_type(type_info)
328
+ if elem is not None and _has_dc(ctx, elem):
329
+ return types.list(_asdict_result_type(ctx, elem))
330
+ return type_info.raw_type
331
+
332
+
333
+ @call_macro
334
+ def astuple(ctx: CallMacroContext, obj: MacroArg) -> Expr:
335
+ """Convert a dataclass instance to a tuple."""
336
+ return _build_astuple(ctx, obj.expr, obj.type)
337
+
338
+
339
+ def _build_astuple(ctx: CallMacroContext, expr: Expr, type_info: TypeInfo) -> Expr:
340
+ # Result type is inferred by sema from the element types;
341
+ # no explicit type annotation needed (unlike _build_asdict for mixed fields).
342
+ if type_info.name not in _dataclass_records:
343
+ raise MacroError(f"astuple() requires a @dataclass instance, got '{type_info.name}'")
344
+ fields = ctx.get_record_fields(type_info.name)
345
+ elements = []
346
+ for fld in fields:
347
+ access = ast.field_access(expr, fld.name)
348
+ elements.append(_astuple_value(ctx, access, fld.type))
349
+ return ast.tuple_lit(elements)
350
+
351
+
352
+ def _astuple_value(ctx: CallMacroContext, access: Expr, fld_type: TypeInfo) -> Expr:
353
+ """Build the value expression for a single field in astuple expansion."""
354
+ return _value_transform(ctx, access, fld_type, _build_astuple, _astuple_value)
@@ -0,0 +1,23 @@
1
+ # tpy: macro_module
2
+ """Enum module for TurboPython.
3
+
4
+ Provides Enum, IntEnum base classes and auto() for member values.
5
+ The parser resolves base class names and auto() calls to ("enum", ...)
6
+ via normal import tracking. This module is loaded via CPython during
7
+ compilation (not compiled to C++).
8
+ """
9
+
10
+
11
+ class Enum:
12
+ """Base class for enumeration types."""
13
+ pass
14
+
15
+
16
+ class IntEnum(Enum):
17
+ """Base class for integer enumeration types."""
18
+ pass
19
+
20
+
21
+ def auto():
22
+ """Sentinel for auto-incrementing enum member values."""
23
+ pass
@@ -0,0 +1,33 @@
1
+ # functools -- higher-order tools (pure TPy).
2
+ #
3
+ # Surface compared to CPython:
4
+ # - reduce(func, a, initial): 3-arg form on Iterable[T].
5
+ # - reduce(func, a): 2-arg form on list[T] only (random access; raises
6
+ # on empty). TPy lacks CPython's iter/next + StopIteration, so the
7
+ # 2-arg form can't accept arbitrary Iterable[T].
8
+ # - total_ordering: re-exported from `_functools_macros` (sibling
9
+ # macro module).
10
+ #
11
+ # Gaps tracked in STDLIB_ROADMAP.md.
12
+ # tpy: cpp_namespace("tpystd::functools")
13
+ from typing import Iterable, overload
14
+ from tpy import Fn, Own, copy
15
+ from _functools_macros import total_ordering
16
+
17
+
18
+ @overload
19
+ def reduce[T, U](func: Fn[[U, T], U], a: Iterable[T], initial: U) -> Own[U]:
20
+ acc: U = copy(initial)
21
+ for x in a:
22
+ acc = func(acc, x)
23
+ return acc
24
+
25
+
26
+ @overload
27
+ def reduce[T](func: Fn[[T, T], T], a: list[T]) -> Own[T]:
28
+ if len(a) == 0:
29
+ raise ValueError("reduce() of empty list with no initial value")
30
+ acc: T = copy(a[0])
31
+ for i in range(1, len(a)):
32
+ acc = func(acc, a[i])
33
+ return acc
@@ -0,0 +1,206 @@
1
+ # hashlib -- cryptographic hash algorithms.
2
+ #
3
+ # Only SHA-256 (FIPS 180-4) is shipped today. Pure-TPy straight-line port
4
+ # of the reference algorithm; no SIMD, no OpenSSL binding. Correctness
5
+ # first; an optional fast backend is a future follow-up (see
6
+ # STDLIB_ROADMAP).
7
+ #
8
+ # TODO -- algorithms to add (each follows the same class + factory
9
+ # pattern used by SHA256 below; mechanical copies differing only in
10
+ # round function, initial state, word width, and endianness):
11
+ # - MD5 (RFC 1321) -- UInt32, little-endian state, 128-bit digest
12
+ # - SHA-1 (FIPS 180-4) -- UInt32, big-endian, 160-bit digest
13
+ # - SHA-512 (FIPS 180-4) -- UInt64, big-endian, 512-bit digest
14
+ # - BLAKE2b / BLAKE2s -- separate family, larger surface
15
+ # - SHA-3 / SHAKE -- Keccak sponge, separate algorithm
16
+ #
17
+ # TODO -- module-level surface missing:
18
+ # - `hashlib.new(name, data=None)` -- factory-by-name dispatcher.
19
+ # Needs either a dict-of-factories or runtime type resolution.
20
+ # - `algorithms_available` / `algorithms_guaranteed` -- frozenset[str].
21
+ #
22
+ # TODO -- perf:
23
+ # - Bind OpenSSL / libcrypto as an optional fast backend, gated by the
24
+ # F8 feature-flag system (see FEATURE_ROADMAP.md). Drop-in replacement
25
+ # for the pure-TPy inner loop; pure-TPy stays as deps-free default.
26
+ #
27
+ # Language / compiler gaps hit while porting SHA-256 (see BUGS.md for
28
+ # detail; none of them are hashlib-specific, but they shaped this file):
29
+ # - Default parameter value `b""` rejected as non-constant; we use
30
+ # `bytes | None = None` instead.
31
+ # - Free function with a `bytearray` param + `.append()` inside gets
32
+ # auto-inferred as const, producing "discards qualifiers" C++ errors.
33
+ # Worked around by inlining `_pack_be32` into `digest()`.
34
+ # - Forward-ref string annotations (`-> "SHA256"`) fail parse; class is
35
+ # defined before the factory to avoid them.
36
+ #
37
+ # Uses tpy.bits.rotr32 for rotation and UIntN.add_wrap for wrapping
38
+ # addition (TPy's +/<< on fixed-width ints are overflow-checked; hash
39
+ # algorithms need modular arithmetic).
40
+ # tpy: cpp_namespace("tpystd::hashlib")
41
+ from tpy import Int32, UInt8, UInt32, UInt64, Own
42
+ from tpy.bits import rotr32
43
+
44
+ # ---------- SHA-256 ----------
45
+
46
+ _SHA256_H0: list[UInt32] = [
47
+ UInt32(0x6a09e667), UInt32(0xbb67ae85), UInt32(0x3c6ef372), UInt32(0xa54ff53a),
48
+ UInt32(0x510e527f), UInt32(0x9b05688c), UInt32(0x1f83d9ab), UInt32(0x5be0cd19),
49
+ ]
50
+
51
+ _SHA256_K: list[UInt32] = [
52
+ UInt32(0x428a2f98), UInt32(0x71374491), UInt32(0xb5c0fbcf), UInt32(0xe9b5dba5),
53
+ UInt32(0x3956c25b), UInt32(0x59f111f1), UInt32(0x923f82a4), UInt32(0xab1c5ed5),
54
+ UInt32(0xd807aa98), UInt32(0x12835b01), UInt32(0x243185be), UInt32(0x550c7dc3),
55
+ UInt32(0x72be5d74), UInt32(0x80deb1fe), UInt32(0x9bdc06a7), UInt32(0xc19bf174),
56
+ UInt32(0xe49b69c1), UInt32(0xefbe4786), UInt32(0x0fc19dc6), UInt32(0x240ca1cc),
57
+ UInt32(0x2de92c6f), UInt32(0x4a7484aa), UInt32(0x5cb0a9dc), UInt32(0x76f988da),
58
+ UInt32(0x983e5152), UInt32(0xa831c66d), UInt32(0xb00327c8), UInt32(0xbf597fc7),
59
+ UInt32(0xc6e00bf3), UInt32(0xd5a79147), UInt32(0x06ca6351), UInt32(0x14292967),
60
+ UInt32(0x27b70a85), UInt32(0x2e1b2138), UInt32(0x4d2c6dfc), UInt32(0x53380d13),
61
+ UInt32(0x650a7354), UInt32(0x766a0abb), UInt32(0x81c2c92e), UInt32(0x92722c85),
62
+ UInt32(0xa2bfe8a1), UInt32(0xa81a664b), UInt32(0xc24b8b70), UInt32(0xc76c51a3),
63
+ UInt32(0xd192e819), UInt32(0xd6990624), UInt32(0xf40e3585), UInt32(0x106aa070),
64
+ UInt32(0x19a4c116), UInt32(0x1e376c08), UInt32(0x2748774c), UInt32(0x34b0bcb5),
65
+ UInt32(0x391c0cb3), UInt32(0x4ed8aa4a), UInt32(0x5b9cca4f), UInt32(0x682e6ff3),
66
+ UInt32(0x748f82ee), UInt32(0x78a5636f), UInt32(0x84c87814), UInt32(0x8cc70208),
67
+ UInt32(0x90befffa), UInt32(0xa4506ceb), UInt32(0xbef9a3f7), UInt32(0xc67178f2),
68
+ ]
69
+
70
+ def _load_be32(data: bytes, off: Int32) -> UInt32:
71
+ return (UInt32(data[off]) << 24) | (UInt32(data[off + 1]) << 16) | (UInt32(data[off + 2]) << 8) | UInt32(data[off + 3])
72
+
73
+ class SHA256:
74
+ h: list[UInt32]
75
+ buffer: bytearray
76
+ length: UInt64
77
+ digest_size: Int32
78
+ block_size: Int32
79
+ name: str
80
+
81
+ def __init__(self) -> None:
82
+ self.h = []
83
+ i: Int32 = 0
84
+ while i < 8:
85
+ self.h.append(_SHA256_H0[i])
86
+ i += 1
87
+ self.buffer = bytearray()
88
+ self.length = 0
89
+ self.digest_size = 32
90
+ self.block_size = 64
91
+ self.name = "sha256"
92
+
93
+ def update(self, data: bytes) -> None:
94
+ n: Int32 = Int32(len(data))
95
+ self.length = UInt64.add_wrap(self.length, UInt64(n))
96
+ k: Int32 = 0
97
+ while k < n:
98
+ self.buffer.append(data[k])
99
+ k += 1
100
+ self._drain_blocks()
101
+
102
+ def _drain_blocks(self) -> None:
103
+ while Int32(len(self.buffer)) >= 64:
104
+ self._process_block(bytes(self.buffer), 0)
105
+ new_buf: bytearray = bytearray()
106
+ j: Int32 = 64
107
+ total: Int32 = Int32(len(self.buffer))
108
+ while j < total:
109
+ new_buf.append(self.buffer[j])
110
+ j += 1
111
+ self.buffer = new_buf
112
+
113
+ def _process_block(self, data: bytes, off: Int32) -> None:
114
+ w: list[UInt32] = []
115
+ i: Int32 = 0
116
+ while i < 16:
117
+ w.append(_load_be32(data, off + 4 * i))
118
+ i += 1
119
+ while i < 64:
120
+ w15: UInt32 = w[i - 15]
121
+ w2: UInt32 = w[i - 2]
122
+ s0: UInt32 = rotr32(w15, 7) ^ rotr32(w15, 18) ^ (w15 >> 3)
123
+ s1: UInt32 = rotr32(w2, 17) ^ rotr32(w2, 19) ^ (w2 >> 10)
124
+ w.append(UInt32.add_wrap(UInt32.add_wrap(UInt32.add_wrap(w[i - 16], s0), w[i - 7]), s1))
125
+ i += 1
126
+ a: UInt32 = self.h[0]
127
+ b: UInt32 = self.h[1]
128
+ c: UInt32 = self.h[2]
129
+ d: UInt32 = self.h[3]
130
+ e: UInt32 = self.h[4]
131
+ f: UInt32 = self.h[5]
132
+ g: UInt32 = self.h[6]
133
+ hh: UInt32 = self.h[7]
134
+ t: Int32 = 0
135
+ while t < 64:
136
+ bsig1: UInt32 = rotr32(e, 6) ^ rotr32(e, 11) ^ rotr32(e, 25)
137
+ ch: UInt32 = (e & f) ^ ((~e) & g)
138
+ t1: UInt32 = UInt32.add_wrap(UInt32.add_wrap(UInt32.add_wrap(UInt32.add_wrap(hh, bsig1), ch), _SHA256_K[t]), w[t])
139
+ bsig0: UInt32 = rotr32(a, 2) ^ rotr32(a, 13) ^ rotr32(a, 22)
140
+ maj: UInt32 = (a & b) ^ (a & c) ^ (b & c)
141
+ t2: UInt32 = UInt32.add_wrap(bsig0, maj)
142
+ hh = g
143
+ g = f
144
+ f = e
145
+ e = UInt32.add_wrap(d, t1)
146
+ d = c
147
+ c = b
148
+ b = a
149
+ a = UInt32.add_wrap(t1, t2)
150
+ t += 1
151
+ self.h[0] = UInt32.add_wrap(self.h[0], a)
152
+ self.h[1] = UInt32.add_wrap(self.h[1], b)
153
+ self.h[2] = UInt32.add_wrap(self.h[2], c)
154
+ self.h[3] = UInt32.add_wrap(self.h[3], d)
155
+ self.h[4] = UInt32.add_wrap(self.h[4], e)
156
+ self.h[5] = UInt32.add_wrap(self.h[5], f)
157
+ self.h[6] = UInt32.add_wrap(self.h[6], g)
158
+ self.h[7] = UInt32.add_wrap(self.h[7], hh)
159
+
160
+ def digest(self) -> bytes:
161
+ clone: SHA256 = self.copy()
162
+ bit_len: UInt64 = UInt64.add_wrap(clone.length, clone.length)
163
+ bit_len = UInt64.add_wrap(bit_len, bit_len)
164
+ bit_len = UInt64.add_wrap(bit_len, bit_len) # x8 for bits
165
+ clone.buffer.append(0x80)
166
+ while Int32(len(clone.buffer)) % 64 != 56:
167
+ clone.buffer.append(0)
168
+ i: Int32 = 7
169
+ while i >= 0:
170
+ shift: UInt64 = UInt64(i * 8)
171
+ clone.buffer.append(UInt8((bit_len >> shift) & 0xFF))
172
+ i -= 1
173
+ clone._drain_blocks()
174
+ out: bytearray = bytearray()
175
+ i = 0
176
+ while i < 8:
177
+ v: UInt32 = clone.h[i]
178
+ out.append(UInt8((v >> 24) & UInt32(0xFF)))
179
+ out.append(UInt8((v >> 16) & UInt32(0xFF)))
180
+ out.append(UInt8((v >> 8) & UInt32(0xFF)))
181
+ out.append(UInt8(v & UInt32(0xFF)))
182
+ i += 1
183
+ return bytes(out)
184
+
185
+ def hexdigest(self) -> str:
186
+ return self.digest().hex()
187
+
188
+ def copy(self) -> Own[SHA256]:
189
+ c: SHA256 = SHA256()
190
+ i: Int32 = 0
191
+ while i < 8:
192
+ c.h[i] = self.h[i]
193
+ i += 1
194
+ c.length = self.length
195
+ j: Int32 = 0
196
+ n: Int32 = Int32(len(self.buffer))
197
+ while j < n:
198
+ c.buffer.append(self.buffer[j])
199
+ j += 1
200
+ return c
201
+
202
+ def sha256(data: bytes | None = None) -> Own[SHA256]:
203
+ h: SHA256 = SHA256()
204
+ if data is not None:
205
+ h.update(data)
206
+ return h