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.
- tpy_lang-0.3.0.dev0.dist-info/METADATA +151 -0
- tpy_lang-0.3.0.dev0.dist-info/RECORD +333 -0
- tpy_lang-0.3.0.dev0.dist-info/WHEEL +4 -0
- tpy_lang-0.3.0.dev0.dist-info/entry_points.txt +3 -0
- tpyc/__init__.py +104 -0
- tpyc/__main__.py +6 -0
- tpyc/_buildinfo.py +1 -0
- tpyc/_data/docs/LANGUAGE_FEATURES.md +6278 -0
- tpyc/_data/docs/STDLIB_ROADMAP.md +1258 -0
- tpyc/_data/docs/TPY_FOR_AGENTS.md +556 -0
- tpyc/_data/lib/tpy/_bindings/__init__.py +6 -0
- tpyc/_data/lib/tpy/_bindings/pcre2.py +173 -0
- tpyc/_data/lib/tpy/_bindings/posix_socket.py +161 -0
- tpyc/_data/lib/tpy/_functools_macros.py +80 -0
- tpyc/_data/lib/tpy/_macro_helpers.py +161 -0
- tpyc/_data/lib/tpy/argparse.py +2062 -0
- tpyc/_data/lib/tpy/asyncio/__init__.py +744 -0
- tpyc/_data/lib/tpy/asyncio/_executor.py +515 -0
- tpyc/_data/lib/tpy/base64.py +410 -0
- tpyc/_data/lib/tpy/bisect.py +39 -0
- tpyc/_data/lib/tpy/builtins.py +38 -0
- tpyc/_data/lib/tpy/dataclasses.py +354 -0
- tpyc/_data/lib/tpy/enum.py +23 -0
- tpyc/_data/lib/tpy/functools.py +33 -0
- tpyc/_data/lib/tpy/hashlib.py +206 -0
- tpyc/_data/lib/tpy/heapq.py +118 -0
- tpyc/_data/lib/tpy/io.py +395 -0
- tpyc/_data/lib/tpy/json.py +221 -0
- tpyc/_data/lib/tpy/math.py +406 -0
- tpyc/_data/lib/tpy/random.py +597 -0
- tpyc/_data/lib/tpy/re.py +467 -0
- tpyc/_data/lib/tpy/socket.py +379 -0
- tpyc/_data/lib/tpy/struct.py +178 -0
- tpyc/_data/lib/tpy/sys.py +40 -0
- tpyc/_data/lib/tpy/time.py +39 -0
- tpyc/_data/lib/tpy/tpy/__init__.py +78 -0
- tpyc/_data/lib/tpy/tpy/_bootstrap/__init__.py +10 -0
- tpyc/_data/lib/tpy/tpy/_bootstrap/_decorators.py +37 -0
- tpyc/_data/lib/tpy/tpy/_bootstrap/_extern.py +64 -0
- tpyc/_data/lib/tpy/tpy/_builtins/__init__.py +11 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_bytes.py +378 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_dict.py +151 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_exceptions.py +125 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_funcs.py +681 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_io.py +97 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_list.py +127 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_range.py +52 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_set.py +139 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_super.py +11 -0
- tpyc/_data/lib/tpy/tpy/_builtins/_types.py +661 -0
- tpyc/_data/lib/tpy/tpy/_core/__init__.py +23 -0
- tpyc/_data/lib/tpy/tpy/_core/_bytes_view.py +129 -0
- tpyc/_data/lib/tpy/tpy/_core/_containers.py +137 -0
- tpyc/_data/lib/tpy/tpy/_core/_functions.py +40 -0
- tpyc/_data/lib/tpy/tpy/_core/_types.py +2061 -0
- tpyc/_data/lib/tpy/tpy/_typing/__init__.py +77 -0
- tpyc/_data/lib/tpy/tpy/_version.py +29 -0
- tpyc/_data/lib/tpy/tpy/bits.py +28 -0
- tpyc/_data/lib/tpy/tpy/coro/__init__.py +127 -0
- tpyc/_data/lib/tpy/tpy/extern.py +8 -0
- tpyc/_data/lib/tpy/tpy/mem.py +49 -0
- tpyc/_data/lib/tpy/tpy/unsafe.py +195 -0
- tpyc/_data/lib/tpy/tpy/version.py +21 -0
- tpyc/_data/lib/tpy/typing.py +13 -0
- tpyc/_data/runtime/cpp/include/tpy/any.hpp +461 -0
- tpyc/_data/runtime/cpp/include/tpy/as_ostream.hpp +117 -0
- tpyc/_data/runtime/cpp/include/tpy/async.hpp +76 -0
- tpyc/_data/runtime/cpp/include/tpy/bigint.hpp +1343 -0
- tpyc/_data/runtime/cpp/include/tpy/builtins.hpp +400 -0
- tpyc/_data/runtime/cpp/include/tpy/bytes_ops.hpp +469 -0
- tpyc/_data/runtime/cpp/include/tpy/container_ops.hpp +487 -0
- tpyc/_data/runtime/cpp/include/tpy/copy_iter.hpp +82 -0
- tpyc/_data/runtime/cpp/include/tpy/core.hpp +558 -0
- tpyc/_data/runtime/cpp/include/tpy/dict_ops.hpp +289 -0
- tpyc/_data/runtime/cpp/include/tpy/dunder.hpp +750 -0
- tpyc/_data/runtime/cpp/include/tpy/dynamic.hpp +44 -0
- tpyc/_data/runtime/cpp/include/tpy/enum.hpp +40 -0
- tpyc/_data/runtime/cpp/include/tpy/file.hpp +245 -0
- tpyc/_data/runtime/cpp/include/tpy/fixed_int.hpp +317 -0
- tpyc/_data/runtime/cpp/include/tpy/format.hpp +954 -0
- tpyc/_data/runtime/cpp/include/tpy/frame_slot.hpp +120 -0
- tpyc/_data/runtime/cpp/include/tpy/generator.hpp +47 -0
- tpyc/_data/runtime/cpp/include/tpy/iterable_ops.hpp +122 -0
- tpyc/_data/runtime/cpp/include/tpy/itertools.hpp +749 -0
- tpyc/_data/runtime/cpp/include/tpy/next_iter.hpp +82 -0
- tpyc/_data/runtime/cpp/include/tpy/ordered_map.hpp +518 -0
- tpyc/_data/runtime/cpp/include/tpy/ordered_set.hpp +337 -0
- tpyc/_data/runtime/cpp/include/tpy/own_iter.hpp +54 -0
- tpyc/_data/runtime/cpp/include/tpy/pascal_graph_sdl.hpp +192 -0
- tpyc/_data/runtime/cpp/include/tpy/printing.hpp +302 -0
- tpyc/_data/runtime/cpp/include/tpy/protocols.hpp +61 -0
- tpyc/_data/runtime/cpp/include/tpy/range.hpp +115 -0
- tpyc/_data/runtime/cpp/include/tpy/ranges.hpp +212 -0
- tpyc/_data/runtime/cpp/include/tpy/set_ops.hpp +265 -0
- tpyc/_data/runtime/cpp/include/tpy/slice.hpp +47 -0
- tpyc/_data/runtime/cpp/include/tpy/span_iter.hpp +42 -0
- tpyc/_data/runtime/cpp/include/tpy/stdlib/math.hpp +41 -0
- tpyc/_data/runtime/cpp/include/tpy/stdlib/pcre2_h.hpp +96 -0
- tpyc/_data/runtime/cpp/include/tpy/stdlib/random.hpp +25 -0
- tpyc/_data/runtime/cpp/include/tpy/stdlib/socket_h.hpp +145 -0
- tpyc/_data/runtime/cpp/include/tpy/stdlib/time.hpp +62 -0
- tpyc/_data/runtime/cpp/include/tpy/system.hpp +121 -0
- tpyc/_data/runtime/cpp/include/tpy/throwable.hpp +55 -0
- tpyc/_data/runtime/cpp/include/tpy/tpy.hpp +156 -0
- tpyc/_data/runtime/cpp/include/tpy/type_name.hpp +77 -0
- tpyc/_data/runtime/cpp/include/tpy/type_traits.hpp +240 -0
- tpyc/_data/runtime/cpp/include/tpy/uninit_array_storage.hpp +250 -0
- tpyc/_data/runtime/cpp/include/tpy/uninit_heap_storage.hpp +277 -0
- tpyc/_data/runtime/cpp/include/tpy/varargs.hpp +174 -0
- tpyc/_data/runtime/cpp/include/tpy/variant_ref.hpp +118 -0
- tpyc/_data/runtime/cpp/src/stdlib/socket_impl.cpp +104 -0
- tpyc/_data/runtime/cpp/third_party/README.md +58 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/AUTHORS +36 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/CMakeLists.txt +1233 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/COPYING +5 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/ChangeLog +3097 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/HACKING +853 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/INSTALL +368 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/LICENCE +94 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/NEWS +492 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/NON-AUTOTOOLS-BUILD +430 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/README +956 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/cmake/COPYING-CMAKE-SCRIPTS +22 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/cmake/FindEditline.cmake +16 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/cmake/FindPackageHandleStandardArgs.cmake +58 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/cmake/FindReadline.cmake +29 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/cmake/pcre2-config-version.cmake.in +15 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/cmake/pcre2-config.cmake.in +148 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/config-cmake.h.in +56 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-16.pc.in +13 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-32.pc.in +13 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-8.pc.in +13 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/libpcre2-posix.pc.in +13 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/pcre2-config.in +121 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/config.h +483 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/config.h.generic +483 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/config.h.in +460 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2.h +1010 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2.h.generic +1010 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2.h.in +1010 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_auto_possess.c +1371 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_chartables.c +196 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_chartables.c.dist +196 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_chkdint.c +96 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_compile.c +11001 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_config.c +252 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_context.c +510 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_convert.c +1189 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_dfa_match.c +4119 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_dftables.c +297 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_error.c +345 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_extuni.c +162 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_find_bracket.c +219 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_fuzzsupport.c +792 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_internal.h +2084 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_intmodedep.h +940 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_compile.c +14972 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_match.c +200 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_misc.c +234 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_neon_inc.h +354 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_simd_inc.h +2355 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_jit_test.c +2528 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_maketables.c +165 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_match.c +7777 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_match_data.c +185 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_newline.c +243 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ord2utf.c +120 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_pattern_info.c +432 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_printint.c +886 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_script_run.c +344 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_serialize.c +286 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_string_utils.c +237 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_study.c +1915 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_substitute.c +1009 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_substring.c +550 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_tables.c +234 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ucd.c +5460 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ucp.h +396 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_ucptables.c +1533 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_valid_utf.c +398 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2_xclass.c +308 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2demo.c +497 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2grep.c +4606 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2posix.c +425 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2posix.h +187 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2posix_test.c +209 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/pcre2test.c +9708 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorApple.c +137 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorCore.c +327 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorFreeBSD.c +89 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorPosix.c +62 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitExecAllocatorWindows.c +40 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorNetBSD.c +72 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitProtExecAllocatorPosix.c +172 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorPosix.c +141 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/allocator_src/sljitWXExecAllocatorWindows.c +102 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitConfig.h +142 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitConfigCPU.h +188 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitConfigInternal.h +907 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitLir.c +3561 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitLir.h +2466 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeARM_32.c +4636 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeARM_64.c +3491 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeARM_T2_32.c +4302 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeLOONGARCH_64.c +3765 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeMIPS_32.c +472 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeMIPS_64.c +387 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeMIPS_common.c +4259 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativePPC_32.c +485 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativePPC_64.c +719 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativePPC_common.c +3161 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeRISCV_32.c +142 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeRISCV_64.c +222 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeRISCV_common.c +3121 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeS390X.c +4526 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeX86_32.c +1685 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeX86_64.c +1398 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitNativeX86_common.c +5001 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitSerialize.c +516 -0
- tpyc/_data/runtime/cpp/third_party/pcre2/src/sljit/sljitUtils.c +344 -0
- tpyc/_data/runtime/cpp/third_party/pcre2.sources.txt +54 -0
- tpyc/_data/runtime/cpp/third_party/pcre2.vendor.json +7 -0
- tpyc/build/__init__.py +7 -0
- tpyc/build/pcre2.py +122 -0
- tpyc/build/third_party.py +413 -0
- tpyc/cli.py +822 -0
- tpyc/codegen_cpp/__init__.py +18 -0
- tpyc/codegen_cpp/builtins.py +484 -0
- tpyc/codegen_cpp/context.py +2064 -0
- tpyc/codegen_cpp/expressions.py +5940 -0
- tpyc/codegen_cpp/functions.py +1913 -0
- tpyc/codegen_cpp/gen_async.py +3258 -0
- tpyc/codegen_cpp/gen_generators.py +657 -0
- tpyc/codegen_cpp/generator.py +2258 -0
- tpyc/codegen_cpp/match.py +1997 -0
- tpyc/codegen_cpp/param_const.py +172 -0
- tpyc/codegen_cpp/protocols.py +907 -0
- tpyc/codegen_cpp/records.py +1654 -0
- tpyc/codegen_cpp/resumable_cfg.py +1651 -0
- tpyc/codegen_cpp/statements.py +4963 -0
- tpyc/codegen_cpp/string_dispatch.py +76 -0
- tpyc/codegen_cpp/test_context.py +46 -0
- tpyc/codegen_cpp/test_param_const.py +113 -0
- tpyc/codegen_cpp/test_resumable_cfg.py +182 -0
- tpyc/codegen_cpp/type_resolution.py +53 -0
- tpyc/codegen_cpp/types.py +436 -0
- tpyc/codegen_cpp/variant_access.py +135 -0
- tpyc/coercions.py +749 -0
- tpyc/compilation_context.py +57 -0
- tpyc/compiler.py +3945 -0
- tpyc/cycle_detection.py +358 -0
- tpyc/diagnostics.py +135 -0
- tpyc/dump_types.py +353 -0
- tpyc/frontend_diagnostics.py +47 -0
- tpyc/frontend_ir/__init__.py +140 -0
- tpyc/frontend_ir/lower.py +1098 -0
- tpyc/frontend_ir/nodes.py +718 -0
- tpyc/frontend_ir/resolver_adapter.py +151 -0
- tpyc/frontend_plugin.py +209 -0
- tpyc/install_docs.py +81 -0
- tpyc/liveness.py +756 -0
- tpyc/macro_api.py +1724 -0
- tpyc/macro_loader.py +497 -0
- tpyc/module_names.py +64 -0
- tpyc/modules/__init__.py +31 -0
- tpyc/modules/defs.py +89 -0
- tpyc/modules/registry.py +36 -0
- tpyc/modules/resolver.py +192 -0
- tpyc/modules/type_resolution.py +629 -0
- tpyc/namespace.py +172 -0
- tpyc/parse/__init__.py +84 -0
- tpyc/parse/imports.py +490 -0
- tpyc/parse/nodes.py +1732 -0
- tpyc/parse/parser.py +4043 -0
- tpyc/parse/resolve_refs.py +466 -0
- tpyc/parse/type_resolver.py +1060 -0
- tpyc/prescan.py +254 -0
- tpyc/qnames.py +149 -0
- tpyc/repl.py +529 -0
- tpyc/repl_backends.py +848 -0
- tpyc/sema/__init__.py +21 -0
- tpyc/sema/analyzer.py +3625 -0
- tpyc/sema/bound_check.py +72 -0
- tpyc/sema/builder_trace.py +684 -0
- tpyc/sema/calls.py +5406 -0
- tpyc/sema/compatibility.py +2107 -0
- tpyc/sema/context.py +1243 -0
- tpyc/sema/expressions.py +3737 -0
- tpyc/sema/flow_facts.py +199 -0
- tpyc/sema/init_tracker.py +150 -0
- tpyc/sema/list_literals.py +69 -0
- tpyc/sema/literal_utils.py +27 -0
- tpyc/sema/local_deduction.py +1088 -0
- tpyc/sema/macros.py +179 -0
- tpyc/sema/match.py +1177 -0
- tpyc/sema/method_expansion.py +347 -0
- tpyc/sema/methods.py +2197 -0
- tpyc/sema/mutation_propagation.py +268 -0
- tpyc/sema/narrowing.py +857 -0
- tpyc/sema/numeric_lattice.py +160 -0
- tpyc/sema/operators.py +402 -0
- tpyc/sema/overloads.py +841 -0
- tpyc/sema/protocols.py +1209 -0
- tpyc/sema/reach_analysis.py +202 -0
- tpyc/sema/registration.py +3156 -0
- tpyc/sema/scope_tracker.py +193 -0
- tpyc/sema/statements.py +4426 -0
- tpyc/sema/type_ops.py +1879 -0
- tpyc/sema/value_range.py +181 -0
- tpyc/symbol_binding.py +259 -0
- tpyc/test_c3_mro.py +208 -0
- tpyc/test_cli_argv.py +52 -0
- tpyc/test_compiler.py +559 -0
- tpyc/test_contains_type_param.py +101 -0
- tpyc/test_cycle_detection.py +221 -0
- tpyc/test_dump_types.py +225 -0
- tpyc/test_install_docs.py +65 -0
- tpyc/test_local_cpp_form.py +135 -0
- tpyc/test_macro_loader.py +76 -0
- tpyc/test_method_expansion.py +254 -0
- tpyc/test_nominal_identity.py +182 -0
- tpyc/test_overloads.py +410 -0
- tpyc/test_parse.py +303 -0
- tpyc/test_parse_type_ref.py +506 -0
- tpyc/test_parse_version_info.py +58 -0
- tpyc/test_reach_analysis.py +72 -0
- tpyc/test_ref_type.py +216 -0
- tpyc/test_send_sync_substitution.py +276 -0
- tpyc/test_tuple_mutation_propagation.py +206 -0
- tpyc/test_type_def_registry.py +1729 -0
- tpyc/test_union_types.py +195 -0
- tpyc/type_def_registry.py +975 -0
- tpyc/typesys.py +5104 -0
|
@@ -0,0 +1,750 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TurboPython Runtime - Dunder Free Functions
|
|
3
|
+
*
|
|
4
|
+
* Protocol free functions (__len__, __getitem__, __setitem__) that bridge
|
|
5
|
+
* Python dunder methods to C++ types. Overloads handle index normalization
|
|
6
|
+
* and bounds checking (Python semantics). Default templates forward to the
|
|
7
|
+
* user type's own dunder method.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
#pragma once
|
|
11
|
+
|
|
12
|
+
#include <array>
|
|
13
|
+
#include <cstddef>
|
|
14
|
+
#include <cstdint>
|
|
15
|
+
#include <cstring>
|
|
16
|
+
#include <expected>
|
|
17
|
+
#include <format>
|
|
18
|
+
#include <functional>
|
|
19
|
+
#include <ranges>
|
|
20
|
+
#include <span>
|
|
21
|
+
#include <sstream>
|
|
22
|
+
#include <string>
|
|
23
|
+
#include <string_view>
|
|
24
|
+
#include <tuple>
|
|
25
|
+
#include <type_traits>
|
|
26
|
+
#include <vector>
|
|
27
|
+
|
|
28
|
+
#include "bigint.hpp"
|
|
29
|
+
#include "enum.hpp"
|
|
30
|
+
#include "format.hpp"
|
|
31
|
+
#include "container_ops.hpp"
|
|
32
|
+
#include "next_iter.hpp"
|
|
33
|
+
#include "ordered_map.hpp"
|
|
34
|
+
#include "span_iter.hpp"
|
|
35
|
+
|
|
36
|
+
namespace tpy {
|
|
37
|
+
|
|
38
|
+
// =============================================
|
|
39
|
+
// tpy::__len__
|
|
40
|
+
// =============================================
|
|
41
|
+
|
|
42
|
+
// Overload: std::vector (most specific, checked first)
|
|
43
|
+
template<typename T>
|
|
44
|
+
int32_t __len__(const std::vector<T>& x) {
|
|
45
|
+
return static_cast<int32_t>(x.size());
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Overload: std::array
|
|
49
|
+
template<typename T, std::size_t N>
|
|
50
|
+
int32_t __len__(const std::array<T, N>& x) {
|
|
51
|
+
return static_cast<int32_t>(x.size());
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Overload: std::span (const and non-const)
|
|
55
|
+
template<typename T>
|
|
56
|
+
int32_t __len__(std::span<const T> x) {
|
|
57
|
+
return static_cast<int32_t>(x.size());
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
template<typename T>
|
|
61
|
+
int32_t __len__(std::span<T> x) {
|
|
62
|
+
return static_cast<int32_t>(x.size());
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Overload: std::string
|
|
66
|
+
inline int32_t __len__(const std::string& x) {
|
|
67
|
+
return static_cast<int32_t>(x.size());
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Overload: std::string_view
|
|
71
|
+
inline int32_t __len__(std::string_view x) {
|
|
72
|
+
return static_cast<int32_t>(x.size());
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Overload: const char* (string literals)
|
|
76
|
+
inline int32_t __len__(const char* x) {
|
|
77
|
+
return static_cast<int32_t>(std::string_view(x).size());
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Overload: char (Char type -- always length 1)
|
|
81
|
+
inline int32_t __len__(char) {
|
|
82
|
+
return 1;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Overload: ordered_map (dict)
|
|
86
|
+
template<typename K, typename V>
|
|
87
|
+
int32_t __len__(const ordered_map<K, V>& x) {
|
|
88
|
+
return x.size();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Default template: user types that define __len__() method
|
|
92
|
+
// This is checked last due to the requires clause
|
|
93
|
+
template<typename T>
|
|
94
|
+
requires requires(const T& t) { { t.__len__() } -> std::convertible_to<int32_t>; }
|
|
95
|
+
int32_t __len__(const T& x) {
|
|
96
|
+
return x.__len__();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// User types returning BigInt from __len__()
|
|
100
|
+
template<typename T>
|
|
101
|
+
requires (requires(const T& t) { { t.__len__() } -> std::same_as<BigInt>; }
|
|
102
|
+
&& !requires(const T& t) { { t.__len__() } -> std::convertible_to<int32_t>; })
|
|
103
|
+
int32_t __len__(const T& x) {
|
|
104
|
+
return x.__len__().template to_fixed_check<int32_t>();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// =============================================
|
|
108
|
+
// tpy::__getitem__
|
|
109
|
+
// =============================================
|
|
110
|
+
|
|
111
|
+
// Overload: std::vector
|
|
112
|
+
template<typename T>
|
|
113
|
+
decltype(auto) __getitem__(const std::vector<T>& x, int32_t i) {
|
|
114
|
+
auto idx = normalize_index(x, i, "list index out of range");
|
|
115
|
+
return x[idx];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
template<typename T>
|
|
119
|
+
decltype(auto) __getitem__(std::vector<T>& x, int32_t i) {
|
|
120
|
+
auto idx = normalize_index(x, i, "list index out of range");
|
|
121
|
+
return x[idx];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Overload: std::array
|
|
125
|
+
template<typename T, std::size_t N>
|
|
126
|
+
decltype(auto) __getitem__(const std::array<T, N>& x, int32_t i) {
|
|
127
|
+
auto idx = normalize_index(x, i, "array index out of range");
|
|
128
|
+
return x[idx];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
template<typename T, std::size_t N>
|
|
132
|
+
decltype(auto) __getitem__(std::array<T, N>& x, int32_t i) {
|
|
133
|
+
auto idx = normalize_index(x, i, "array index out of range");
|
|
134
|
+
return x[idx];
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Overload: std::span (const)
|
|
138
|
+
template<typename T>
|
|
139
|
+
decltype(auto) __getitem__(std::span<const T> x, int32_t i) {
|
|
140
|
+
auto idx = normalize_index(x, i, "span index out of range");
|
|
141
|
+
return x[idx];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Overload: std::span (mutable)
|
|
145
|
+
template<typename T>
|
|
146
|
+
T& __getitem__(std::span<T> x, int32_t i) {
|
|
147
|
+
auto idx = normalize_index(x, i, "span index out of range");
|
|
148
|
+
return x[idx];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Overload: std::string
|
|
152
|
+
inline char __getitem__(const std::string& x, int32_t i) {
|
|
153
|
+
auto idx = normalize_index(x, i, "string index out of range");
|
|
154
|
+
return x[idx];
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Overload: std::string_view
|
|
158
|
+
inline char __getitem__(std::string_view x, int32_t i) {
|
|
159
|
+
auto idx = normalize_index(x, i, "string index out of range");
|
|
160
|
+
return x[idx];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Overload: ordered_map (dict) -- key can be any compatible type
|
|
164
|
+
template<typename K, typename V, typename KeyArg>
|
|
165
|
+
const V& __getitem__(const ordered_map<K, V>& m, const KeyArg& key) {
|
|
166
|
+
auto it = m.find(K(key));
|
|
167
|
+
if (it == m.items_end()) raise_key_error("KeyError");
|
|
168
|
+
return (*it).second;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
template<typename K, typename V, typename KeyArg>
|
|
172
|
+
V& __getitem__(ordered_map<K, V>& m, const KeyArg& key) {
|
|
173
|
+
auto it = m.find(K(key));
|
|
174
|
+
if (it == m.items_end()) raise_key_error("KeyError");
|
|
175
|
+
return (*it).second;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Default template: user types that define __getitem__() method
|
|
179
|
+
template<typename T>
|
|
180
|
+
requires requires(const T& t, int32_t i) { t.__getitem__(i); }
|
|
181
|
+
decltype(auto) __getitem__(const T& x, int32_t i) {
|
|
182
|
+
return x.__getitem__(i);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
template<typename T>
|
|
186
|
+
requires requires(T& t, int32_t i) { t.__getitem__(i); }
|
|
187
|
+
decltype(auto) __getitem__(T& x, int32_t i) {
|
|
188
|
+
return x.__getitem__(i);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// =============================================
|
|
192
|
+
// tpy::__setitem__
|
|
193
|
+
// =============================================
|
|
194
|
+
|
|
195
|
+
// Overload: std::vector
|
|
196
|
+
template<typename T, typename V>
|
|
197
|
+
void __setitem__(std::vector<T>& x, int32_t i, V&& v) {
|
|
198
|
+
auto idx = normalize_index(x, i, "list assignment index out of range");
|
|
199
|
+
x[idx] = std::forward<V>(v);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Overload: std::array
|
|
203
|
+
template<typename T, std::size_t N, typename V>
|
|
204
|
+
void __setitem__(std::array<T, N>& x, int32_t i, V&& v) {
|
|
205
|
+
auto idx = normalize_index(x, i, "array index out of range");
|
|
206
|
+
x[idx] = std::forward<V>(v);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Overload: std::span (mutable)
|
|
210
|
+
template<typename T, typename V>
|
|
211
|
+
void __setitem__(std::span<T> x, int32_t i, V&& v) {
|
|
212
|
+
auto idx = normalize_index(x, i, "span index out of range");
|
|
213
|
+
x[idx] = std::forward<V>(v);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Overload: ordered_map (dict)
|
|
217
|
+
template<typename K, typename V, typename KeyArg, typename ValArg>
|
|
218
|
+
void __setitem__(ordered_map<K, V>& m, const KeyArg& key, ValArg&& value) {
|
|
219
|
+
// K(key) avoids double-conversion (find takes const K&); value is
|
|
220
|
+
// forwarded raw into insert_or_assign's universal-ref VV.
|
|
221
|
+
m.insert_or_assign(K(key), std::forward<ValArg>(value));
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Default template: user types that define __setitem__() method
|
|
225
|
+
template<typename T, typename V>
|
|
226
|
+
requires requires(T& t, int32_t i, V&& val) { t.__setitem__(i, std::forward<V>(val)); }
|
|
227
|
+
void __setitem__(T& x, int32_t i, V&& v) {
|
|
228
|
+
x.__setitem__(i, std::forward<V>(v));
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// =============================================
|
|
232
|
+
// tpy::__delitem__
|
|
233
|
+
// =============================================
|
|
234
|
+
|
|
235
|
+
// Overload: std::vector (list)
|
|
236
|
+
template<typename T>
|
|
237
|
+
void __delitem__(std::vector<T>& x, int32_t i) {
|
|
238
|
+
auto idx = normalize_index(x, i, "list assignment index out of range");
|
|
239
|
+
x.erase(x.begin() + static_cast<std::ptrdiff_t>(idx));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Overload: ordered_map (dict) -- throws KeyError on missing key
|
|
243
|
+
template<typename K, typename V, typename KeyArg>
|
|
244
|
+
void __delitem__(ordered_map<K, V>& m, const KeyArg& key) {
|
|
245
|
+
if (!m.erase(K(key))) {
|
|
246
|
+
raise_key_error("KeyError");
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Default template: user types that define __delitem__() method
|
|
251
|
+
template<typename T>
|
|
252
|
+
requires requires(T& t, int32_t i) { t.__delitem__(i); }
|
|
253
|
+
void __delitem__(T& x, int32_t i) {
|
|
254
|
+
x.__delitem__(i);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// =============================================
|
|
258
|
+
// tpy::__bool__
|
|
259
|
+
// =============================================
|
|
260
|
+
|
|
261
|
+
// Overload: ordered_map (dict)
|
|
262
|
+
template<typename K, typename V>
|
|
263
|
+
bool __bool__(const ordered_map<K, V>& m) {
|
|
264
|
+
return !m.empty();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Default template: user types that define __bool__() method
|
|
268
|
+
template<typename T>
|
|
269
|
+
requires requires(const T& t) { { t.__bool__() } -> std::convertible_to<bool>; }
|
|
270
|
+
bool __bool__(const T& x) {
|
|
271
|
+
return x.__bool__();
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// =============================================
|
|
275
|
+
// tpy::__str__
|
|
276
|
+
// =============================================
|
|
277
|
+
|
|
278
|
+
// Builtin type overloads (needed for generic T contexts)
|
|
279
|
+
inline std::string __str__(bool x) { return x ? "True" : "False"; }
|
|
280
|
+
inline std::string __str__(std::nullptr_t) { return "None"; }
|
|
281
|
+
inline std::string __str__(std::monostate) { return "None"; }
|
|
282
|
+
inline std::string __str__(char x) { return std::string(1, x); }
|
|
283
|
+
inline std::string __str__(int8_t x) { return std::to_string(x); }
|
|
284
|
+
inline std::string __str__(int16_t x) { return std::to_string(x); }
|
|
285
|
+
inline std::string __str__(int32_t x) { return std::to_string(x); }
|
|
286
|
+
inline std::string __str__(int64_t x) { return std::to_string(x); }
|
|
287
|
+
inline std::string __str__(uint8_t x) { return std::to_string(x); }
|
|
288
|
+
inline std::string __str__(uint16_t x) { return std::to_string(x); }
|
|
289
|
+
inline std::string __str__(uint32_t x) { return std::to_string(x); }
|
|
290
|
+
inline std::string __str__(uint64_t x) { return std::to_string(x); }
|
|
291
|
+
inline std::string __str__(double x) { return format_float(x); }
|
|
292
|
+
inline std::string __str__(float x) { return format_float(static_cast<double>(x)); }
|
|
293
|
+
inline std::string __str__(const std::string& x) { return x; }
|
|
294
|
+
inline std::string __str__(std::string_view x) { return std::string(x); }
|
|
295
|
+
inline std::string __str__(const BigInt& x) { return x.to_string(); }
|
|
296
|
+
|
|
297
|
+
// Default template: user types that define __str__() method
|
|
298
|
+
template<typename T>
|
|
299
|
+
requires requires(const T& t) { t.__str__(); }
|
|
300
|
+
auto __str__(const T& x) {
|
|
301
|
+
return x.__str__();
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Fallback: types with __repr__ but no __str__ (matches Python behavior)
|
|
305
|
+
template<typename T>
|
|
306
|
+
requires (!requires(const T& t) { t.__str__(); })
|
|
307
|
+
&& requires(const T& t) { t.__repr__(); }
|
|
308
|
+
auto __str__(const T& x) {
|
|
309
|
+
return x.__repr__();
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Fallback for formattable types without __str__/__repr__ (e.g. int, double).
|
|
313
|
+
template<typename T>
|
|
314
|
+
requires (!requires(const T& t) { t.__str__(); })
|
|
315
|
+
&& (!requires(const T& t) { t.__repr__(); })
|
|
316
|
+
&& std::formattable<T, char>
|
|
317
|
+
auto __str__(const T& x) {
|
|
318
|
+
return std::format("{}", x);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Enum str: same shape as enum __repr__ above. Python prints str(e) and
|
|
322
|
+
// repr(e) identically for enums ("TypeName.MEMBER"), so delegate.
|
|
323
|
+
template<typename T>
|
|
324
|
+
requires std::is_enum_v<T>
|
|
325
|
+
&& requires(T x) { ::tpy::EnumUtil<T>::name(x); }
|
|
326
|
+
inline std::string __str__(T x) {
|
|
327
|
+
return ::tpy::detail::enum_repr_string(x);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Fallback for types with operator<< but no __str__/__repr__/formattable.
|
|
331
|
+
// Excludes enums for the same reason as the __repr__ fallback above.
|
|
332
|
+
template<typename T>
|
|
333
|
+
requires (!requires(const T& t) { t.__str__(); })
|
|
334
|
+
&& (!requires(const T& t) { t.__repr__(); })
|
|
335
|
+
&& (!std::is_enum_v<T>)
|
|
336
|
+
&& (!std::formattable<T, char>)
|
|
337
|
+
&& requires(std::ostream& os, const T& t) { os << t; }
|
|
338
|
+
std::string __str__(const T& x) {
|
|
339
|
+
std::ostringstream ss;
|
|
340
|
+
ss << x;
|
|
341
|
+
return ss.str();
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Union (std::variant): visit the active alternative and recurse. Pointer
|
|
345
|
+
// alternatives (T*) are dereffed before dispatch (matches the variant
|
|
346
|
+
// repr overload below).
|
|
347
|
+
template<typename... Ts>
|
|
348
|
+
std::string __str__(const std::variant<Ts...>& v) {
|
|
349
|
+
return std::visit([](auto&& a) -> std::string {
|
|
350
|
+
using A = std::remove_cvref_t<decltype(a)>;
|
|
351
|
+
if constexpr (std::is_pointer_v<A>) {
|
|
352
|
+
return std::string(::tpy::__str__(*a));
|
|
353
|
+
} else {
|
|
354
|
+
return std::string(::tpy::__str__(a));
|
|
355
|
+
}
|
|
356
|
+
}, v);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// =============================================
|
|
360
|
+
// tpy::__repr__
|
|
361
|
+
// =============================================
|
|
362
|
+
|
|
363
|
+
// Forward decl: repr_of is the user-facing dispatch helper, defined in
|
|
364
|
+
// tpy.hpp after every header that contributes __repr__ overloads (notably
|
|
365
|
+
// bytes_ops.hpp which adds __repr__ for raw Bytes). Optional/variant repr
|
|
366
|
+
// templates above use it for ADL into per-record __repr__ overrides;
|
|
367
|
+
// qualified lookup of `::tpy::repr_of` from a template body needs the
|
|
368
|
+
// name visible at parse time, so the forward declaration precedes those
|
|
369
|
+
// template bodies.
|
|
370
|
+
template<typename T> auto repr_of(const T& x);
|
|
371
|
+
|
|
372
|
+
// Default template: user types that define __repr__() method
|
|
373
|
+
template<typename T>
|
|
374
|
+
requires requires(const T& t) { t.__repr__(); }
|
|
375
|
+
auto __repr__(const T& x) {
|
|
376
|
+
return x.__repr__();
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// User records without __repr__: emit the Python default
|
|
380
|
+
// `<ClassName object at 0xADDR>` form. The class name comes from a
|
|
381
|
+
// `static constexpr __tpy_class_name__` member emitted by codegen.
|
|
382
|
+
template<typename T>
|
|
383
|
+
requires (!requires(const T& t) { t.__repr__(); })
|
|
384
|
+
&& requires { T::__tpy_class_name__; }
|
|
385
|
+
inline std::string __repr__(const T& x) {
|
|
386
|
+
std::ostringstream ss;
|
|
387
|
+
::tpy::print_object_default(ss, T::__tpy_class_name__, x);
|
|
388
|
+
return ss.str();
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Bool: Python repr uses True/False (not C++ true/false)
|
|
392
|
+
inline std::string_view __repr__(bool x) {
|
|
393
|
+
return x ? "True" : "False";
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// None: repr matches str ("None")
|
|
397
|
+
inline std::string_view __repr__(std::nullptr_t) {
|
|
398
|
+
return "None";
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// std::monostate is the TPy unit type at value-bearing positions
|
|
402
|
+
// (Future[None], list[None], ...). Mirror the nullptr_t overload so
|
|
403
|
+
// any_repr_capable<monostate> matches and Any cells holding None
|
|
404
|
+
// route to "None" rather than the typeid fallback.
|
|
405
|
+
inline std::string_view __repr__(std::monostate) {
|
|
406
|
+
return "None";
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Strings: Python repr quotes and escapes control chars / quote / backslash.
|
|
410
|
+
// The const char* overload steals string-literal calls before the templated
|
|
411
|
+
// formattable fallback (which would otherwise emit raw bytes via std::format).
|
|
412
|
+
inline std::string __repr__(const std::string& x) {
|
|
413
|
+
return repr_quote_string(x);
|
|
414
|
+
}
|
|
415
|
+
inline std::string __repr__(std::string_view x) {
|
|
416
|
+
return repr_quote_string(x);
|
|
417
|
+
}
|
|
418
|
+
inline std::string __repr__(const char* x) {
|
|
419
|
+
return repr_quote_string(std::string_view(x));
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Optional: None or repr(value).
|
|
423
|
+
template<typename T>
|
|
424
|
+
std::string __repr__(const std::optional<T>& x) {
|
|
425
|
+
if (!x.has_value()) return "None";
|
|
426
|
+
if constexpr (std::same_as<T, std::string> || std::same_as<T, std::string_view>) {
|
|
427
|
+
return repr_quote_string(*x);
|
|
428
|
+
} else if constexpr (std::same_as<T, bool>) {
|
|
429
|
+
return *x ? "True" : "False";
|
|
430
|
+
} else if constexpr (std::floating_point<T>) {
|
|
431
|
+
return format_float(static_cast<double>(*x));
|
|
432
|
+
} else {
|
|
433
|
+
// repr_of (not direct ::tpy::__repr__) so ADL into T's namespace
|
|
434
|
+
// can reach per-record overrides; a qualified call from a runtime
|
|
435
|
+
// template body would freeze the candidate set at definition.
|
|
436
|
+
return std::string(::tpy::repr_of(*x));
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Python-faithful repr for floating point: always shows trailing .0
|
|
441
|
+
inline std::string __repr__(double x) { return format_float(x); }
|
|
442
|
+
inline std::string __repr__(float x) { return format_float(static_cast<double>(x)); }
|
|
443
|
+
|
|
444
|
+
// Fallback for formattable types without __repr__ (e.g. int).
|
|
445
|
+
template<typename T>
|
|
446
|
+
requires (!requires(const T& t) { t.__repr__(); })
|
|
447
|
+
&& (!std::same_as<T, std::string>)
|
|
448
|
+
&& (!std::same_as<T, std::string_view>)
|
|
449
|
+
&& (!std::floating_point<T>)
|
|
450
|
+
&& std::formattable<T, char>
|
|
451
|
+
auto __repr__(const T& x) {
|
|
452
|
+
return std::format("{}", x);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Enum repr: any enum type with an EnumUtil specialization renders as
|
|
456
|
+
// "TypeName.MEMBER". The operator<<-fallback below explicitly excludes
|
|
457
|
+
// enums via `!std::is_enum_v<T>`, so this template is the only candidate
|
|
458
|
+
// for enum types (partitioning, not partial ordering -- the constraint
|
|
459
|
+
// sets are disjoint, not subsumption-related). For @native enums there
|
|
460
|
+
// is no operator<< at all, so this is the only repr path; for tpy-defined
|
|
461
|
+
// enums it produces the same "TypeName.MEMBER" output that the operator<<
|
|
462
|
+
// body would have generated.
|
|
463
|
+
template<typename T>
|
|
464
|
+
requires std::is_enum_v<T>
|
|
465
|
+
&& requires(T x) { ::tpy::EnumUtil<T>::name(x); }
|
|
466
|
+
inline std::string __repr__(T x) {
|
|
467
|
+
return ::tpy::detail::enum_repr_string(x);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// Fallback for types with operator<< but no __repr__/formattable.
|
|
471
|
+
// Excludes TPy records (`__tpy_class_name__`-tagged) so the default-repr
|
|
472
|
+
// template above wins unambiguously -- otherwise both templates match
|
|
473
|
+
// for records without __repr__. Also excludes enums so the
|
|
474
|
+
// EnumUtil-driven template above wins for enum types (constraint sets
|
|
475
|
+
// don't subsume, so we disambiguate by partitioning).
|
|
476
|
+
template<typename T>
|
|
477
|
+
requires (!requires(const T& t) { t.__repr__(); })
|
|
478
|
+
&& (!requires { T::__tpy_class_name__; })
|
|
479
|
+
&& (!std::is_enum_v<T>)
|
|
480
|
+
&& (!std::formattable<T, char>)
|
|
481
|
+
&& requires(std::ostream& os, const T& t) { os << t; }
|
|
482
|
+
std::string __repr__(const T& x) {
|
|
483
|
+
std::ostringstream ss;
|
|
484
|
+
ss << x;
|
|
485
|
+
return ss.str();
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// Union (std::variant): visit the active alternative and recurse. Each
|
|
489
|
+
// alternative type must have its own __repr__ overload reachable above;
|
|
490
|
+
// pointer-variant alternatives (T*) are dereffed before dispatch. Goes
|
|
491
|
+
// through repr_of so ADL on the alternative type finds per-record
|
|
492
|
+
// overrides emitted alongside user records.
|
|
493
|
+
template<typename... Ts>
|
|
494
|
+
std::string __repr__(const std::variant<Ts...>& v) {
|
|
495
|
+
return std::visit([](auto&& a) -> std::string {
|
|
496
|
+
using A = std::remove_cvref_t<decltype(a)>;
|
|
497
|
+
if constexpr (std::is_pointer_v<A>) {
|
|
498
|
+
return std::string(::tpy::repr_of(*a));
|
|
499
|
+
} else {
|
|
500
|
+
return std::string(::tpy::repr_of(a));
|
|
501
|
+
}
|
|
502
|
+
}, v);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// =============================================
|
|
506
|
+
// tpy::__hash__
|
|
507
|
+
// =============================================
|
|
508
|
+
|
|
509
|
+
// Integral types (int8_t through uint64_t, bool, char)
|
|
510
|
+
template<typename T>
|
|
511
|
+
requires std::integral<T>
|
|
512
|
+
uint64_t __hash__(T x) {
|
|
513
|
+
return static_cast<uint64_t>(std::hash<T>{}(x));
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Floating-point
|
|
517
|
+
inline uint64_t __hash__(double x) {
|
|
518
|
+
return static_cast<uint64_t>(std::hash<double>{}(x));
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// std::monostate is the TPy unit type at value-bearing positions; map
|
|
522
|
+
// to Python's hash(None) (== 0 on most CPython builds, but the only
|
|
523
|
+
// requirement is stability + matching None==None equality).
|
|
524
|
+
inline uint64_t __hash__(std::monostate) {
|
|
525
|
+
return 0;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// Strings
|
|
529
|
+
inline uint64_t __hash__(const std::string& x) {
|
|
530
|
+
return static_cast<uint64_t>(std::hash<std::string>{}(x));
|
|
531
|
+
}
|
|
532
|
+
inline uint64_t __hash__(std::string_view x) {
|
|
533
|
+
return static_cast<uint64_t>(std::hash<std::string_view>{}(x));
|
|
534
|
+
}
|
|
535
|
+
inline uint64_t __hash__(const char* x) {
|
|
536
|
+
return static_cast<uint64_t>(std::hash<std::string_view>{}(std::string_view(x)));
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// Bytes (std::vector<uint8_t>) and BytesView (std::span<const uint8_t>)
|
|
540
|
+
inline uint64_t __hash__(const std::vector<uint8_t>& x) {
|
|
541
|
+
return static_cast<uint64_t>(std::hash<std::string_view>{}(
|
|
542
|
+
std::string_view(reinterpret_cast<const char*>(x.data()), x.size())));
|
|
543
|
+
}
|
|
544
|
+
inline uint64_t __hash__(std::span<const uint8_t> x) {
|
|
545
|
+
return static_cast<uint64_t>(std::hash<std::string_view>{}(
|
|
546
|
+
std::string_view(reinterpret_cast<const char*>(x.data()), x.size())));
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// Enum types
|
|
550
|
+
template<typename T>
|
|
551
|
+
requires std::is_enum_v<T>
|
|
552
|
+
uint64_t __hash__(T x) {
|
|
553
|
+
return static_cast<uint64_t>(std::hash<std::underlying_type_t<T>>{}(
|
|
554
|
+
static_cast<std::underlying_type_t<T>>(x)));
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// Default: user types with __hash__() method
|
|
558
|
+
template<typename T>
|
|
559
|
+
requires requires(const T& t) { { t.__hash__() } -> std::convertible_to<uint64_t>; }
|
|
560
|
+
uint64_t __hash__(const T& x) {
|
|
561
|
+
return static_cast<uint64_t>(x.__hash__());
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// User types with __hash__() returning BigInt
|
|
565
|
+
template<typename T>
|
|
566
|
+
requires (requires(const T& t) { { t.__hash__() } -> std::same_as<BigInt>; }
|
|
567
|
+
&& !requires(const T& t) { { t.__hash__() } -> std::convertible_to<uint64_t>; })
|
|
568
|
+
uint64_t __hash__(const T& x) {
|
|
569
|
+
return x.__hash__().hash();
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// =============================================
|
|
573
|
+
// tpy::hash_combine -- Boost-style hash combining for dataclass __hash__
|
|
574
|
+
// =============================================
|
|
575
|
+
|
|
576
|
+
inline uint64_t hash_combine(uint64_t seed) {
|
|
577
|
+
return seed;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
template<typename T, typename... Rest>
|
|
581
|
+
uint64_t hash_combine(uint64_t seed, const T& val, const Rest&... rest) {
|
|
582
|
+
seed ^= __hash__(val) + 0x9e3779b97f4a7c15ULL + (seed << 6) + (seed >> 2);
|
|
583
|
+
return hash_combine(seed, rest...);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// Tuple types
|
|
587
|
+
template<typename... Ts>
|
|
588
|
+
uint64_t __hash__(const std::tuple<Ts...>& t) {
|
|
589
|
+
return std::apply([](const auto&... elems) {
|
|
590
|
+
return hash_combine(0, elems...);
|
|
591
|
+
}, t);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// =============================================
|
|
595
|
+
// native_iterator: wraps C++ begin/end into __next__() / __iter__()
|
|
596
|
+
// Inherits begin()/end() from next_iter_mixin so the result of
|
|
597
|
+
// tpy::__iter__() can also be used in C++ range-for loops.
|
|
598
|
+
//
|
|
599
|
+
// __next__() returns val_or_ref<deref_type> to preserve reference
|
|
600
|
+
// semantics: value types are copied, non-value types are returned
|
|
601
|
+
// as pointers (transparent via .get()). This allows protocol-typed
|
|
602
|
+
// iteration (Iterable[T], Iterator[T]) to mutate container elements.
|
|
603
|
+
// =============================================
|
|
604
|
+
|
|
605
|
+
template<typename Iter, typename T>
|
|
606
|
+
struct native_iterator
|
|
607
|
+
: next_iter_mixin<native_iterator<Iter, T>, val_or_ref<std::remove_reference_t<decltype(*std::declval<Iter&>())>>> {
|
|
608
|
+
using deref_type = std::remove_reference_t<decltype(*std::declval<Iter&>())>;
|
|
609
|
+
using next_type = val_or_ref<deref_type>;
|
|
610
|
+
|
|
611
|
+
Iter current_;
|
|
612
|
+
Iter end_;
|
|
613
|
+
|
|
614
|
+
native_iterator(Iter begin, Iter end) : current_(begin), end_(end) {}
|
|
615
|
+
|
|
616
|
+
std::expected<next_type, StopIteration> __next__() {
|
|
617
|
+
if (current_ == end_) return tpy::make_unexpected(StopIteration{});
|
|
618
|
+
return next_type(*current_++);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
native_iterator& __iter__() { return *this; }
|
|
622
|
+
|
|
623
|
+
// Opaque repr, matching CPython's behavior for iterator objects.
|
|
624
|
+
friend std::ostream& operator<<(std::ostream& os, const native_iterator&) {
|
|
625
|
+
return os << "<iterator>";
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
// =============================================
|
|
630
|
+
// tpy::__iter__
|
|
631
|
+
// =============================================
|
|
632
|
+
|
|
633
|
+
// Overload: std::vector (mutable -- preserves element references)
|
|
634
|
+
template<typename T>
|
|
635
|
+
auto __iter__(std::vector<T>& x) {
|
|
636
|
+
return native_iterator<typename std::vector<T>::iterator, T>{x.begin(), x.end()};
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// Overload: std::vector (const)
|
|
640
|
+
template<typename T>
|
|
641
|
+
auto __iter__(const std::vector<T>& x) {
|
|
642
|
+
return native_iterator<typename std::vector<T>::const_iterator, T>{x.begin(), x.end()};
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
// Overload: std::array (mutable)
|
|
646
|
+
template<typename T, std::size_t N>
|
|
647
|
+
auto __iter__(std::array<T, N>& x) {
|
|
648
|
+
return native_iterator<typename std::array<T, N>::iterator, T>{x.begin(), x.end()};
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// Overload: std::array (const)
|
|
652
|
+
template<typename T, std::size_t N>
|
|
653
|
+
auto __iter__(const std::array<T, N>& x) {
|
|
654
|
+
return native_iterator<typename std::array<T, N>::const_iterator, T>{x.begin(), x.end()};
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// Overload: std::span (const)
|
|
658
|
+
template<typename T>
|
|
659
|
+
auto __iter__(std::span<const T> x) {
|
|
660
|
+
return native_iterator<typename std::span<const T>::iterator, T>{x.begin(), x.end()};
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// Overload: std::span (mutable)
|
|
664
|
+
template<typename T>
|
|
665
|
+
auto __iter__(std::span<T> x) {
|
|
666
|
+
return native_iterator<typename std::span<T>::iterator, T>{x.begin(), x.end()};
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
// Overload: std::string
|
|
670
|
+
inline auto __iter__(const std::string& x) {
|
|
671
|
+
return native_iterator<std::string::const_iterator, char>{x.begin(), x.end()};
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// Overload: std::string_view
|
|
675
|
+
inline auto __iter__(std::string_view x) {
|
|
676
|
+
return native_iterator<std::string_view::const_iterator, char>{x.begin(), x.end()};
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// Overload: const char* (string literals)
|
|
680
|
+
inline auto __iter__(const char* x) {
|
|
681
|
+
return __iter__(std::string_view(x));
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// Generic overload: any C++ range type not covered above (e.g., tpy::Range<T>)
|
|
685
|
+
// Constrained to types without __iter__() to avoid ambiguity with user types.
|
|
686
|
+
template<typename T>
|
|
687
|
+
requires std::ranges::input_range<const T>
|
|
688
|
+
&& (!requires(const T& t) { t.__iter__(); })
|
|
689
|
+
auto __iter__(const T& x) {
|
|
690
|
+
using ElemT = std::remove_cvref_t<decltype(*x.begin())>;
|
|
691
|
+
return native_iterator<decltype(x.begin()), ElemT>{x.begin(), x.end()};
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// Default template: user types that define __iter__() method
|
|
695
|
+
// decltype(auto) preserves reference returns (e.g. OwnIterSet& __iter__())
|
|
696
|
+
// to avoid copying move-only iterator types.
|
|
697
|
+
template<typename T>
|
|
698
|
+
requires requires(T& t) { t.__iter__(); }
|
|
699
|
+
decltype(auto) __iter__(T& x) {
|
|
700
|
+
return x.__iter__();
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// Const overload for user types
|
|
704
|
+
template<typename T>
|
|
705
|
+
requires requires(const T& t) { t.__iter__(); }
|
|
706
|
+
decltype(auto) __iter__(const T& x) {
|
|
707
|
+
return x.__iter__();
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
} // namespace tpy
|
|
711
|
+
|
|
712
|
+
// std::hash specialization for bytes (needed by std::unordered_map/set)
|
|
713
|
+
template<>
|
|
714
|
+
struct std::hash<std::vector<uint8_t>> {
|
|
715
|
+
size_t operator()(const std::vector<uint8_t>& v) const noexcept {
|
|
716
|
+
return std::hash<std::string_view>{}(
|
|
717
|
+
std::string_view(reinterpret_cast<const char*>(v.data()), v.size()));
|
|
718
|
+
}
|
|
719
|
+
};
|
|
720
|
+
|
|
721
|
+
// std::hash + std::equal_to specializations for BytesView (std::span<const uint8_t>).
|
|
722
|
+
// std::span has no built-in operator==, so unordered_map/set need an explicit
|
|
723
|
+
// equality comparator alongside the hash.
|
|
724
|
+
template<>
|
|
725
|
+
struct std::hash<std::span<const uint8_t>> {
|
|
726
|
+
size_t operator()(std::span<const uint8_t> v) const noexcept {
|
|
727
|
+
// Empty span may hold (nullptr, 0); string_view's hash on a null
|
|
728
|
+
// pointer is implementation-defined. Match equal_to's empty short-circuit.
|
|
729
|
+
if (v.empty()) return 0;
|
|
730
|
+
return std::hash<std::string_view>{}(
|
|
731
|
+
std::string_view(reinterpret_cast<const char*>(v.data()), v.size()));
|
|
732
|
+
}
|
|
733
|
+
};
|
|
734
|
+
template<>
|
|
735
|
+
struct std::equal_to<std::span<const uint8_t>> {
|
|
736
|
+
bool operator()(std::span<const uint8_t> a, std::span<const uint8_t> b) const noexcept {
|
|
737
|
+
if (a.size() != b.size()) return false;
|
|
738
|
+
// memcmp on null pointers is UB even with size 0; std::span is
|
|
739
|
+
// allowed to hold (nullptr, 0) for an empty span.
|
|
740
|
+
return a.empty() || std::memcmp(a.data(), b.data(), a.size()) == 0;
|
|
741
|
+
}
|
|
742
|
+
};
|
|
743
|
+
|
|
744
|
+
// std::hash specialization for tuples (needed by std::unordered_map/set)
|
|
745
|
+
template<typename... Ts>
|
|
746
|
+
struct std::hash<std::tuple<Ts...>> {
|
|
747
|
+
size_t operator()(const std::tuple<Ts...>& t) const noexcept {
|
|
748
|
+
return static_cast<size_t>(tpy::__hash__(t));
|
|
749
|
+
}
|
|
750
|
+
};
|