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,173 @@
1
+ # tpy: cpp_namespace("tpystd::_bindings::pcre2")
2
+ # tpy: include("<tpy/stdlib/pcre2_h.hpp>")
3
+ # tpy: link("pcre2", managed=True)
4
+ """Raw PCRE2 C bindings.
5
+
6
+ One @native declaration per pcre2_*_8 primitive, matching the upstream C
7
+ ABI 1:1. No Python semantics.
8
+ Consumers (the public `re` facade) build user-visible Pattern / Match
9
+ classes on top of these raw handles, using __del__ for RAII over the
10
+ opaque pcre2_code* / pcre2_match_data* lifetimes.
11
+
12
+ Naming:
13
+ - Opaque type markers: `Code`, `MatchData`, `MatchContext`. The TPy-level
14
+ handle is `Ptr[Code]` etc., which codegens to `pcre2_code_8*`.
15
+ - All function names mirror the PCRE2 C names with the `_8` suffix dropped.
16
+
17
+ Constants are hardcoded UInt32 values matching pcre2.h. PCRE2's flag values
18
+ are part of its public ABI and don't change between versions.
19
+ """
20
+
21
+ from typing import Final
22
+ from tpy import Ptr, UInt8, UInt32, UInt64, Int32, readonly
23
+ from tpy.extern import native
24
+
25
+
26
+ # ---------- Opaque type markers ----------
27
+ # Never instantiated directly; only passed/returned as `Ptr[X]`. The empty
28
+ # native class binds the C struct name so `Ptr[Code]` becomes `pcre2_code_8*`
29
+ # -- declared as a global-scope forward struct + alias in
30
+ # `runtime/cpp/include/tpy/stdlib/pcre2_h.hpp` (matches upstream pcre2.h
31
+ # layout; the real struct definitions live in PCRE2's own .c files).
32
+
33
+ @native("::pcre2_code_8")
34
+ class Code: ...
35
+
36
+ @native("::pcre2_match_data_8")
37
+ class MatchData: ...
38
+
39
+ @native("::pcre2_match_context_8")
40
+ class MatchContext: ...
41
+
42
+ # Context types we never construct -- passed as bare `Ptr[...]` to the
43
+ # PCRE2 functions that accept an optional context override. Caller always
44
+ # passes `None` (= default contexts; `Ptr[T]` is already nullable).
45
+ @native("::pcre2_compile_context_8")
46
+ class CompileContext: ...
47
+
48
+ @native("::pcre2_general_context_8")
49
+ class GeneralContext: ...
50
+
51
+
52
+ # ---------- Compile / match flags (subset we actually use) ----------
53
+ # Names mirror upstream pcre2.h exactly. Safe because pcre2.h is never
54
+ # included in our generated TUs (see runtime/cpp/include/tpy/stdlib/pcre2_h.hpp
55
+ # header comment) -- the preprocessor never sees a `#define PCRE2_CASELESS`
56
+ # in the same TU as our constant declaration. Values are part of PCRE2's
57
+ # stable ABI.
58
+
59
+ PCRE2_CASELESS: Final[UInt32] = 0x00000008
60
+ PCRE2_MULTILINE: Final[UInt32] = 0x00000400
61
+ PCRE2_DOTALL: Final[UInt32] = 0x00000020
62
+ PCRE2_EXTENDED: Final[UInt32] = 0x00000080
63
+ PCRE2_UTF: Final[UInt32] = 0x00080000
64
+ PCRE2_UCP: Final[UInt32] = 0x00020000
65
+ PCRE2_ANCHORED: Final[UInt32] = 0x80000000
66
+ PCRE2_ENDANCHORED: Final[UInt32] = 0x20000000
67
+
68
+ # Match-step option for pcre2_substitute.
69
+ PCRE2_SUBSTITUTE_GLOBAL: Final[UInt32] = 0x00000100
70
+ PCRE2_SUBSTITUTE_OVERFLOW_LENGTH: Final[UInt32] = 0x00001000
71
+
72
+ # pcre2_jit_compile selector: full JIT for normal matching.
73
+ PCRE2_JIT_COMPLETE: Final[UInt32] = 0x00000001
74
+
75
+ # Pattern-info selectors for pcre2_pattern_info.
76
+ PCRE2_INFO_CAPTURECOUNT: Final[UInt32] = 4
77
+
78
+ # pcre2_match return codes. NOMATCH means "no match" (not an error);
79
+ # NOMEMORY is returned by pcre2_substitute when the output buffer is
80
+ # too small AND PCRE2_SUBSTITUTE_OVERFLOW_LENGTH is set.
81
+ PCRE2_ERROR_NOMATCH: Final[Int32] = -1
82
+ PCRE2_ERROR_NOMEMORY: Final[Int32] = -48
83
+
84
+ # Sentinel meaning "this group did not participate". PCRE2_UNSET is
85
+ # (PCRE2_SIZE)~0u = SIZE_MAX in C; we compare against it via raw uint64.
86
+ PCRE2_UNSET: Final[UInt64] = 0xFFFFFFFFFFFFFFFF
87
+
88
+
89
+ # ---------- Compile / free ----------
90
+ # Every binding below is a pure `@native` 1:1 mirror of PCRE2's C ABI.
91
+ # Arguments match pcre2.h exactly. Context-pointer args
92
+ # (pcre2_compile_context*, pcre2_general_context*, etc.) are typed as
93
+ # bare `Ptr[X]`; callers pass `None` (codegens to `nullptr`).
94
+
95
+ @native("::pcre2_compile_8")
96
+ def compile(pattern_data: Ptr[readonly[UInt8]], pattern_len: UInt64,
97
+ flags: UInt32,
98
+ errcode_out: Ptr[Int32], erroff_out: Ptr[UInt64],
99
+ ccontext: Ptr[CompileContext]) -> Ptr[Code]: ...
100
+
101
+ @native("::pcre2_code_free_8")
102
+ def code_free(code: Ptr[Code]) -> None: ...
103
+
104
+ @native("::pcre2_jit_compile_8")
105
+ def jit_compile(code: Ptr[Code], opts: UInt32) -> Int32: ...
106
+
107
+ # Render a PCRE2 numeric error into a human-readable message. Writes into
108
+ # the caller-provided buffer and returns the number of bytes written
109
+ # (negative on error). `PCRE2_UCHAR8` is `uint8_t` -- same as `Ptr[UInt8]`'s
110
+ # underlying C type, so no cast needed.
111
+ @native("::pcre2_get_error_message_8")
112
+ def get_error_message(errcode: Int32, buf: Ptr[UInt8], buflen: UInt64) -> Int32: ...
113
+
114
+
115
+ # ---------- Match contexts and match-data blocks ----------
116
+
117
+ @native("::pcre2_match_context_create_8")
118
+ def match_context_create(
119
+ gcontext: Ptr[GeneralContext]) -> Ptr[MatchContext]: ...
120
+
121
+ @native("::pcre2_match_context_free_8")
122
+ def match_context_free(mctx: Ptr[MatchContext]) -> None: ...
123
+
124
+ @native("::pcre2_match_data_create_from_pattern_8")
125
+ def match_data_create_from_pattern(
126
+ code: Ptr[Code],
127
+ gcontext: Ptr[GeneralContext]) -> Ptr[MatchData]: ...
128
+
129
+ @native("::pcre2_match_data_free_8")
130
+ def match_data_free(md: Ptr[MatchData]) -> None: ...
131
+
132
+
133
+ # ---------- Matching ----------
134
+
135
+ # pcre2_match returns >0 on success (count of matched groups including
136
+ # group 0), 0 if the ovector was too small (we always size correctly via
137
+ # match_data_create_from_pattern), or negative on no-match / error.
138
+ @native("::pcre2_match_8")
139
+ def match(code: Ptr[Code],
140
+ subject_data: Ptr[readonly[UInt8]], subject_len: UInt64,
141
+ start_offset: UInt64, opts: UInt32,
142
+ md: Ptr[MatchData], mctx: Ptr[MatchContext]) -> Int32: ...
143
+
144
+ # Returns Ptr[UInt64] -- pointer into the match-data block holding the
145
+ # ovector (pairs of (start, end) byte offsets, length 2*group_count).
146
+ @native("::pcre2_get_ovector_pointer_8")
147
+ def get_ovector_pointer(md: Ptr[MatchData]) -> Ptr[readonly[UInt64]]: ...
148
+
149
+
150
+ # ---------- Pattern info ----------
151
+
152
+ # pcre2_pattern_info(code, what, where) -- writes the requested info into
153
+ # `where` (typed appropriately for the selector). We only use it to fetch
154
+ # the capture count (uint32_t).
155
+ @native("::pcre2_pattern_info_8")
156
+ def pattern_info_u32(code: Ptr[Code], what: UInt32, out: Ptr[UInt32]) -> Int32: ...
157
+
158
+
159
+ # ---------- Substitution ----------
160
+
161
+ # pcre2_substitute writes the result into a caller-provided UCHAR buffer.
162
+ # If the buffer is too small AND PCRE2_SUBSTITUTE_OVERFLOW_LENGTH is set,
163
+ # *outlen is updated to the size needed and PCRE2_ERROR_NOMEMORY returned;
164
+ # the caller can resize and retry. `mcache` is an optional match_data cache
165
+ # we don't use -- pass None.
166
+ @native("::pcre2_substitute_8")
167
+ def substitute(code: Ptr[Code],
168
+ subject_data: Ptr[readonly[UInt8]], subject_len: UInt64,
169
+ start_offset: UInt64, opts: UInt32,
170
+ mcache: Ptr[MatchData],
171
+ mctx: Ptr[MatchContext],
172
+ repl_data: Ptr[readonly[UInt8]], repl_len: UInt64,
173
+ outbuf: Ptr[UInt8], outlen_inout: Ptr[UInt64]) -> Int32: ...
@@ -0,0 +1,161 @@
1
+ # tpy: native_module
2
+ # tpy: cpp_namespace("tpystd::_bindings::posix_socket")
3
+ # tpy: include("<tpy/stdlib/socket_h.hpp>")
4
+ """Raw POSIX-sockets C bindings.
5
+
6
+ Thin @native layer over libc's `socket`, `bind`, `connect`, ..., plus
7
+ three out-of-line helpers from runtime/cpp/src/stdlib/socket_impl.cpp
8
+ (DNS resolution, errno access, last-resolve-error). One declaration per
9
+ primitive, matching the C ABI 1:1 -- no Python semantics.
10
+
11
+ Consumers (the public `socket` facade) build Socket / SocketError classes
12
+ on top of these raw handles, using __del__ for RAII over file descriptors.
13
+
14
+ Naming:
15
+ * `SockaddrIn` -- @native(binding="C") struct aliased to `sockaddr_in`.
16
+ Fields match POSIX layout (16 bytes total); safe across Linux, *BSD,
17
+ macOS. IPv6 (`sockaddr_in6`) is a separate struct, deferred.
18
+ * All function names mirror their libc counterparts.
19
+ * Wire values (AF_INET etc.) live in the public `socket` facade, not
20
+ here -- posix_socket.py is declaration-only.
21
+
22
+ The `# tpy: native_module` directive means no .cpp/.hpp is generated for
23
+ this module itself; its @native bindings resolve at link time to symbols
24
+ in libc (for the socket/bind/... set) and in socket_impl.cpp (for the
25
+ tpy_* set).
26
+ """
27
+
28
+ from tpy import Int32, UInt8, UInt16, UInt32, UInt64, Int64, Ptr, readonly
29
+ from tpy.extern import native
30
+
31
+
32
+ # ---------- sockaddr_in (POSIX-stable 16-byte layout) ----------
33
+ # Mirror of the `struct sockaddr_in` declaration in socket_h.hpp. TPy-side
34
+ # field access codegens to normal C struct field access; no unsafe_load
35
+ # is needed. Constants for sin_family / sin_port / sin_addr are built by
36
+ # the caller using htons() + tpy_resolve_ipv4() + the AF_* values in the
37
+ # public `socket` facade.
38
+ @native("sockaddr_in", binding="C")
39
+ class SockaddrIn:
40
+ sin_family: UInt16
41
+ sin_port: UInt16
42
+ sin_addr: UInt32
43
+
44
+
45
+ # ---------- Socket lifecycle ----------
46
+
47
+ # All @native names below use a leading `::` to bind to libc's global
48
+ # symbols (`::socket`, `::bind`, ...). Without the `::` prefix, the rename
49
+ # would be treated as relative to this module's `cpp_namespace` and emit
50
+ # `::tpystd::_bindings::posix_socket::socket` -- no such symbol. Absolute
51
+ # renames (containing `::` anywhere in the string) opt out of the
52
+ # namespace prefix, which is what we want for libc bindings.
53
+
54
+ @native("::socket")
55
+ def socket(domain: Int32, type_: Int32, protocol: Int32) -> Int32: ...
56
+
57
+ @native("::close")
58
+ def close(fd: Int32) -> Int32: ...
59
+
60
+ @native("::shutdown")
61
+ def shutdown(fd: Int32, how: Int32) -> Int32: ...
62
+
63
+
64
+ # ---------- Address binding + connection setup ----------
65
+
66
+ @native("::bind")
67
+ def bind(fd: Int32, addr: Ptr[SockaddrIn], addrlen: UInt32) -> Int32: ...
68
+
69
+ @native("::connect")
70
+ def connect(fd: Int32, addr: Ptr[SockaddrIn], addrlen: UInt32) -> Int32: ...
71
+
72
+ @native("::listen")
73
+ def listen(fd: Int32, backlog: Int32) -> Int32: ...
74
+
75
+ @native("::accept")
76
+ def accept(fd: Int32, addr: Ptr[SockaddrIn], addrlen: Ptr[UInt32]) -> Int32: ...
77
+
78
+
79
+ # ---------- Data transfer ----------
80
+ # send/recv return ssize_t (= long on 64-bit *nix). Negative means error;
81
+ # 0 from recv means peer closed (orderly shutdown).
82
+
83
+ @native("::send")
84
+ def send(fd: Int32, buf: Ptr[readonly[UInt8]], len_: UInt64, flags: Int32) -> Int64: ...
85
+
86
+ @native("::recv")
87
+ def recv(fd: Int32, buf: Ptr[UInt8], len_: UInt64, flags: Int32) -> Int64: ...
88
+
89
+
90
+ # ---------- Options + introspection ----------
91
+ # setsockopt's `optval` is polymorphic (int* for boolean-style opts,
92
+ # struct timeval* for timeouts, etc.). Phase 1 only exposes int-valued
93
+ # options; broader shapes arrive with SO_RCVTIMEO / SO_LINGER support.
94
+
95
+ @native("::setsockopt")
96
+ def setsockopt(fd: Int32, level: Int32, optname: Int32,
97
+ optval: Ptr[readonly[Int32]], optlen: UInt32) -> Int32: ...
98
+
99
+ @native("::getsockname")
100
+ def getsockname(fd: Int32, addr: Ptr[SockaddrIn], addrlen: Ptr[UInt32]) -> Int32: ...
101
+
102
+ @native("::getpeername")
103
+ def getpeername(fd: Int32, addr: Ptr[SockaddrIn], addrlen: Ptr[UInt32]) -> Int32: ...
104
+
105
+ @native("::socketpair")
106
+ def socketpair(domain: Int32, type_: Int32, protocol: Int32,
107
+ sv: Ptr[Int32]) -> Int32: ...
108
+
109
+
110
+ # ---------- Byte-order + address conversion ----------
111
+
112
+ @native("::htons")
113
+ def htons(hostshort: UInt16) -> UInt16: ...
114
+
115
+ @native("::ntohs")
116
+ def ntohs(netshort: UInt16) -> UInt16: ...
117
+
118
+ # inet_pton writes the binary form (4 bytes for AF_INET) into `dst`.
119
+ # Returns 1 on success, 0 for bad format, -1 for unsupported family.
120
+ @native("::inet_pton")
121
+ def inet_pton(af: Int32, src: Ptr[readonly[UInt8]], dst: Ptr[UInt8]) -> Int32: ...
122
+
123
+ # inet_ntop writes the text form into `dst` and returns a pointer into it
124
+ # on success, NULL on error. We accept the non-null-terminated return
125
+ # semantics implicitly by copying via dst's span.
126
+ @native("::inet_ntop")
127
+ def inet_ntop(af: Int32, src: Ptr[readonly[UInt8]],
128
+ dst: Ptr[UInt8], size: UInt32) -> Ptr[UInt8]: ...
129
+
130
+
131
+ # ---------- TPy runtime helpers (socket_impl.cpp) ----------
132
+
133
+ # Resolve `host` (first `host_len` bytes, not required null-terminated) to
134
+ # a single IPv4 address via getaddrinfo. Writes 4 network-byte-order bytes
135
+ # to `out`. Returns 0 on success, -1 on failure; caller reads
136
+ # tpy_last_resolve_error for a human message on failure.
137
+ @native("::tpy_resolve_ipv4")
138
+ def tpy_resolve_ipv4(host: Ptr[readonly[UInt8]], host_len: UInt64,
139
+ out: Ptr[UInt8]) -> Int32: ...
140
+
141
+ # errno at the point of call. Indirection for platform portability
142
+ # (glibc uses __errno_location, macOS uses __error).
143
+ @native("::tpy_errno")
144
+ def tpy_errno() -> Int32: ...
145
+
146
+ # Last DNS-resolution error message (thread-local, C string, valid until
147
+ # the next tpy_resolve_ipv4 call on this thread). readonly because the
148
+ # C signature is `const char*` -- callers must not mutate the buffer.
149
+ @native("::tpy_last_resolve_error")
150
+ def tpy_last_resolve_error() -> Ptr[readonly[UInt8]]: ...
151
+
152
+
153
+ # ---------- Raw libc strerror ----------
154
+ # Returns a human-readable description of `errnum`. Null-terminated C
155
+ # string; caller wraps it in a TPy `str` via the usual ptr+length walk.
156
+ # No `# tpy: include` needed for this -- <cstring> is transitively pulled
157
+ # in via tpy.hpp, which declares `char* strerror(int)`. uint8_t* return
158
+ # matches TPy's byte-buffer convention; ABI is identical. readonly because
159
+ # libc's strerror buffer is thread-local / shared and must not be written.
160
+ @native("::strerror")
161
+ def strerror(errnum: Int32) -> Ptr[readonly[UInt8]]: ...
@@ -0,0 +1,80 @@
1
+ # tpy: macro_module
2
+ """Compile-time class macros for `functools`.
3
+
4
+ Hosts `@total_ordering`; the runtime helpers (`reduce`, etc.) live
5
+ in `lib/tpy/functools.py`. The split exists because TPy modules
6
+ cannot mix `# tpy: macro_module` with runtime functions that
7
+ compile to C++.
8
+ """
9
+
10
+ from tpyc.macro_api import ClassInfo, MacroError, class_macro, ast, types
11
+ from _macro_helpers import ORDER_DUNDERS, ORDER_DUNDER_OPS
12
+
13
+
14
+ _ANCHOR_TO_OP = dict(zip(ORDER_DUNDERS, ORDER_DUNDER_OPS))
15
+
16
+
17
+ # (anchor, missing_op) -> builder taking `(sa, eq)` where
18
+ # `sa = self <anchor_op> other` and `eq = self == other`.
19
+ # Each pair has one canonical derivation; `__lt__` and `__gt__`
20
+ # (likewise `__le__` and `__ge__`) share formulas because each
21
+ # strict / weak inequality lets us derive its mirror identically.
22
+ _DERIVATIONS = {
23
+ ("__lt__", "__gt__"): lambda sa, eq: ast.unary("!", ast.binop(sa, "||", eq)),
24
+ ("__lt__", "__le__"): lambda sa, eq: ast.binop(sa, "||", eq),
25
+ ("__lt__", "__ge__"): lambda sa, eq: ast.unary("!", sa),
26
+ ("__le__", "__ge__"): lambda sa, eq: ast.binop(ast.unary("!", sa), "||", eq),
27
+ ("__le__", "__lt__"): lambda sa, eq: ast.binop(sa, "&&", ast.unary("!", eq)),
28
+ ("__le__", "__gt__"): lambda sa, eq: ast.unary("!", sa),
29
+ ("__gt__", "__lt__"): lambda sa, eq: ast.unary("!", ast.binop(sa, "||", eq)),
30
+ ("__gt__", "__ge__"): lambda sa, eq: ast.binop(sa, "||", eq),
31
+ ("__gt__", "__le__"): lambda sa, eq: ast.unary("!", sa),
32
+ ("__ge__", "__le__"): lambda sa, eq: ast.binop(ast.unary("!", sa), "||", eq),
33
+ ("__ge__", "__gt__"): lambda sa, eq: ast.binop(sa, "&&", ast.unary("!", eq)),
34
+ ("__ge__", "__lt__"): lambda sa, eq: ast.unary("!", sa),
35
+ }
36
+
37
+
38
+ def _build_body(anchor: str, op_name: str):
39
+ s = ast.name("self")
40
+ o = ast.name("other")
41
+ sa = ast.binop(s, _ANCHOR_TO_OP[anchor], o)
42
+ eq = ast.binop(s, "==", o)
43
+ return _DERIVATIONS[(anchor, op_name)](sa, eq)
44
+
45
+
46
+ @class_macro
47
+ def total_ordering(cls: ClassInfo) -> None:
48
+ """Synthesize the missing rich-comparison operators on `cls`.
49
+
50
+ Requires `__eq__` plus at least one of `__lt__` / `__le__` /
51
+ `__gt__` / `__ge__`. The first defined ordering op (in that
52
+ order) is the "anchor"; the remaining three are derived from it
53
+ and `__eq__`. Defers the actual synthesis so peer macros like
54
+ `@dataclass` (which adds `__eq__`) compose regardless of
55
+ decorator order.
56
+ """
57
+ cls.defer_until_macros_complete(_apply_total_ordering)
58
+
59
+
60
+ def _apply_total_ordering(cls: ClassInfo) -> None:
61
+ if not cls.has_method_or_inherited("__eq__"):
62
+ raise MacroError(
63
+ f"@total_ordering requires {cls.name!r} to define __eq__"
64
+ )
65
+ defined = [name for name in ORDER_DUNDERS if cls.has_method_or_inherited(name)]
66
+ if not defined:
67
+ raise MacroError(
68
+ f"@total_ordering requires {cls.name!r} to define one of "
69
+ f"__lt__, __le__, __gt__, __ge__"
70
+ )
71
+ anchor = defined[0]
72
+ other_type = types.named(cls.name)
73
+ for op_name in ORDER_DUNDERS:
74
+ if op_name == anchor or cls.has_method_or_inherited(op_name):
75
+ continue
76
+ cls.add_method(ast.function(
77
+ op_name, [("other", other_type)], types.bool,
78
+ [ast.return_(_build_body(anchor, op_name))],
79
+ is_method=True, is_readonly=True,
80
+ ))
@@ -0,0 +1,161 @@
1
+ # tpy: macro_module
2
+ """Shared helpers for TurboPython macro modules.
3
+
4
+ Provides build_* functions for synthesizing common dunder methods
5
+ (__init__, __eq__, __repr__, __hash__, ordering). Used by @dataclass,
6
+ @model, and other class macros.
7
+ """
8
+
9
+ from tpyc.macro_api import (
10
+ ClassInfo, FieldInfo, ast, types, Expr, Stmt, Function, Type,
11
+ )
12
+
13
+
14
+ # Rich-comparison dunders in CPython's documented anchor-priority
15
+ # order, paired with the corresponding binary operator. Used by
16
+ # `build_order` (synthesize all four for `@dataclass(order=True)`)
17
+ # and `@total_ordering` (pick the first defined op as anchor).
18
+ ORDER_DUNDERS = ("__lt__", "__le__", "__gt__", "__ge__")
19
+ ORDER_DUNDER_OPS = ("<", "<=", ">", ">=")
20
+
21
+
22
+ def build_init(
23
+ cls: ClassInfo,
24
+ parent_fields: list[FieldInfo],
25
+ own_fields: list[FieldInfo],
26
+ ) -> Function:
27
+ """Build a synthetic __init__ method from field lists."""
28
+ params: list[tuple[str, Type]] = []
29
+ defaults: list[Expr | None] = []
30
+ body: list[Stmt] = []
31
+
32
+ # Parent fields come first; forwarded via super().__init__()
33
+ for fld in parent_fields:
34
+ param_type = fld.type.raw_type
35
+ if not param_type.is_value_type():
36
+ param_type = types.own(param_type)
37
+ params.append((fld.name, param_type))
38
+ defaults.append(fld.default_expr)
39
+
40
+ if parent_fields:
41
+ super_args = [ast.name(fld.name) for fld in parent_fields]
42
+ super_call = ast.method_call(
43
+ ast.call("super"), "__init__", super_args,
44
+ )
45
+ body.append(ast.expr_stmt(super_call))
46
+
47
+ # Own fields
48
+ for fld in own_fields:
49
+ param_type = fld.type.raw_type
50
+ if not param_type.is_value_type():
51
+ param_type = types.own(param_type)
52
+ params.append((fld.name, param_type))
53
+ defaults.append(fld.default_expr)
54
+ body.append(ast.assign(
55
+ ast.field_access(ast.name("self"), fld.name),
56
+ ast.name(fld.name),
57
+ ))
58
+
59
+ return ast.function(
60
+ "__init__", params, types.void, body,
61
+ is_method=True, defaults=defaults,
62
+ )
63
+
64
+
65
+ def build_eq(cls: ClassInfo, all_fields: list[FieldInfo]) -> Function:
66
+ """Build a synthetic __eq__ method from field list."""
67
+ other_type = types.named(cls.name)
68
+ comparisons = [
69
+ ast.binop(
70
+ ast.field_access(ast.name("self"), fld.name),
71
+ "==",
72
+ ast.field_access(ast.name("other"), fld.name),
73
+ )
74
+ for fld in all_fields
75
+ ]
76
+ if not comparisons:
77
+ return ast.function(
78
+ "__eq__", [("other", other_type)], types.bool, [ast.return_(ast.bool_lit(True))],
79
+ is_method=True,
80
+ )
81
+ eq_expr: Expr = comparisons[0]
82
+ for cmp in comparisons[1:]:
83
+ eq_expr = ast.binop(eq_expr, "&&", cmp)
84
+
85
+ return ast.function(
86
+ "__eq__", [("other", other_type)], types.bool, [ast.return_(eq_expr)],
87
+ is_method=True,
88
+ )
89
+
90
+
91
+ def build_repr(cls: ClassInfo, all_fields: list[FieldInfo]) -> Function:
92
+ """Build a synthetic __repr__ method from field list.
93
+
94
+ Generates: f"ClassName(field1={repr(self.field1)}, field2={repr(self.field2)})"
95
+ """
96
+ parts = ", ".join(
97
+ f"{fld.name}={{repr(self.{fld.name})}}" for fld in all_fields
98
+ )
99
+ source = f'f"{cls.name}({parts})"'
100
+ return ast.function(
101
+ "__repr__", [], types.str,
102
+ [ast.return_(ast.quote_expr(source))],
103
+ is_method=True, is_readonly=True,
104
+ )
105
+
106
+
107
+ def build_hash(cls: ClassInfo, all_fields: list[FieldInfo]) -> Function:
108
+ """Build a synthetic __hash__ method from field list.
109
+
110
+ XORs hash(field) values. Simple but has known weaknesses (symmetric
111
+ collisions, self-cancellation). Good enough until tuple hashing lands,
112
+ at which point this becomes hash((self.f1, self.f2, ...)).
113
+ """
114
+ body: list[Stmt] = []
115
+
116
+ first = all_fields[0]
117
+ body.append(ast.var_decl(
118
+ "h", types.uint64,
119
+ ast.call("hash", [ast.field_access(ast.name("self"), first.name)]),
120
+ ))
121
+
122
+ for fld in all_fields[1:]:
123
+ hash_call = ast.call("hash", [ast.field_access(ast.name("self"), fld.name)])
124
+ body.append(ast.assign(
125
+ ast.name("h"),
126
+ ast.binop(ast.name("h"), "^", hash_call),
127
+ ))
128
+
129
+ body.append(ast.return_(ast.name("h")))
130
+ return ast.function(
131
+ "__hash__", [], types.uint64, body,
132
+ is_method=True, is_readonly=True,
133
+ )
134
+
135
+
136
+ def build_order(cls: ClassInfo, all_fields: list[FieldInfo]) -> list[Function]:
137
+ """Build synthetic ordering methods (__lt__, __le__, __gt__, __ge__).
138
+
139
+ Uses field-by-field chained comparison (lexicographic order).
140
+ """
141
+ other_type = types.named(cls.name)
142
+ results: list[Function] = []
143
+ for dunder, op in zip(ORDER_DUNDERS, ORDER_DUNDER_OPS):
144
+ body: list[Stmt] = []
145
+ for fld in all_fields[:-1]:
146
+ sf = ast.field_access(ast.name("self"), fld.name)
147
+ of = ast.field_access(ast.name("other"), fld.name)
148
+ body.append(ast.if_(
149
+ ast.binop(sf, "!=", of),
150
+ [ast.return_(ast.binop(sf, op, of))],
151
+ ))
152
+ last = all_fields[-1]
153
+ sf = ast.field_access(ast.name("self"), last.name)
154
+ of = ast.field_access(ast.name("other"), last.name)
155
+ body.append(ast.return_(ast.binop(sf, op, of)))
156
+
157
+ results.append(ast.function(
158
+ dunder, [("other", other_type)], types.bool, body,
159
+ is_method=True, is_readonly=True,
160
+ ))
161
+ return results