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,461 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TurboPython Runtime - Any (typing.Any)
|
|
3
|
+
*
|
|
4
|
+
* Type-erased value cell. Holds any concrete copyable value via std::any
|
|
5
|
+
* plus a per-type ops table for the universal operations (print, str,
|
|
6
|
+
* repr, bool, equals, hash) that the compiler dispatches on raw `Any`.
|
|
7
|
+
*
|
|
8
|
+
* v1 stores copyable contents only -- the std::any backing requires
|
|
9
|
+
* CopyConstructible. Move-only support is deferred (would require a
|
|
10
|
+
* custom wrapper with destroy/move slots replacing std::any).
|
|
11
|
+
*
|
|
12
|
+
* See docs/ANY_TYPE_DESIGN.md for the full design.
|
|
13
|
+
*
|
|
14
|
+
* Depends on: dunder.hpp (__str__, __repr__, __hash__), builtins.hpp
|
|
15
|
+
* (to_bool), core.hpp (raise<E>, tpy_panic, demangle_type_name),
|
|
16
|
+
* type_name.hpp (user-facing TPy type names).
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
#pragma once
|
|
20
|
+
|
|
21
|
+
#include <any>
|
|
22
|
+
#include <concepts>
|
|
23
|
+
#include <cstdint>
|
|
24
|
+
#include <format>
|
|
25
|
+
#include <ostream>
|
|
26
|
+
#include <string>
|
|
27
|
+
#include <string_view>
|
|
28
|
+
#include <type_traits>
|
|
29
|
+
#include <typeinfo>
|
|
30
|
+
#include <utility>
|
|
31
|
+
|
|
32
|
+
namespace tpy {
|
|
33
|
+
|
|
34
|
+
// Forward declarations from other tpy headers; these resolve via ADL when
|
|
35
|
+
// any.hpp is included after dunder.hpp / builtins.hpp / core.hpp via the
|
|
36
|
+
// umbrella tpy.hpp. We do not include them directly to keep this header
|
|
37
|
+
// self-contained when read in isolation.
|
|
38
|
+
|
|
39
|
+
struct AnyOps;
|
|
40
|
+
|
|
41
|
+
// ---------------------------------------------------------------------
|
|
42
|
+
// Any: std::any storage + per-type ops table
|
|
43
|
+
// ---------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
struct Any {
|
|
46
|
+
std::any value;
|
|
47
|
+
const AnyOps* ops;
|
|
48
|
+
|
|
49
|
+
// Default-constructed Any is the empty/moved-from state. TPy source
|
|
50
|
+
// does not allow this (no default-init for non-trivial types); it
|
|
51
|
+
// arises only from std::any moves. Operations on an empty Any panic
|
|
52
|
+
// -- see any_cast_or_panic / any_eq / any_hash below.
|
|
53
|
+
Any() noexcept : value(), ops(nullptr) {}
|
|
54
|
+
|
|
55
|
+
Any(std::any v, const AnyOps* o) noexcept
|
|
56
|
+
: value(std::move(v)), ops(o) {}
|
|
57
|
+
|
|
58
|
+
bool empty() const noexcept { return !value.has_value(); }
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// ---------------------------------------------------------------------
|
|
62
|
+
// AnyOps: dispatch table for universal operations
|
|
63
|
+
// ---------------------------------------------------------------------
|
|
64
|
+
//
|
|
65
|
+
// `equals` and `hash` are populated only for types that satisfy the
|
|
66
|
+
// corresponding compile-time concept (operator== / tpy::__hash__). When
|
|
67
|
+
// null, the runtime path panics or returns False per the design doc.
|
|
68
|
+
|
|
69
|
+
struct AnyOps {
|
|
70
|
+
void (*print)(std::ostream&, const std::any&);
|
|
71
|
+
void (*str)(std::string&, const std::any&);
|
|
72
|
+
void (*repr)(std::string&, const std::any&);
|
|
73
|
+
bool (*to_bool)(const std::any&);
|
|
74
|
+
bool (*equals)(const std::any&, const std::any&); // null if T not Eq
|
|
75
|
+
std::uint64_t (*hash)(const std::any&); // null if T not Hashable
|
|
76
|
+
// User-facing TPy type name of the cell's T (e.g. "int", "str",
|
|
77
|
+
// "module.MyClass"). Cold-path; only consulted by panic messages.
|
|
78
|
+
std::string (*type_name)();
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// ---------------------------------------------------------------------
|
|
82
|
+
// Per-T conditional slot generation
|
|
83
|
+
// ---------------------------------------------------------------------
|
|
84
|
+
|
|
85
|
+
namespace detail {
|
|
86
|
+
|
|
87
|
+
template <typename T>
|
|
88
|
+
concept any_str_capable = requires(const T& t) {
|
|
89
|
+
{ ::tpy::__str__(t) } -> std::convertible_to<std::string>;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// The concept stays on `::tpy::__repr__` rather than `::tpy::repr_of`
|
|
93
|
+
// because repr_of is a single template that always SFINAE-passes here
|
|
94
|
+
// (then hard-errors inside), so it can't act as a capability check.
|
|
95
|
+
// `::tpy::__repr__(t)` resolves against the explicit overload set: if no
|
|
96
|
+
// matching __repr__ exists for T (e.g. raw containers like
|
|
97
|
+
// std::vector<T>, ordered_set<T> -- they print via *Printer wrappers,
|
|
98
|
+
// not free __repr__), the requires-clause cleanly fails and the slot
|
|
99
|
+
// falls back to __str__/typeid. The actual call site uses repr_of so
|
|
100
|
+
// ADL into a user record's namespace still picks up per-record default
|
|
101
|
+
// overrides.
|
|
102
|
+
template <typename T>
|
|
103
|
+
concept any_repr_capable = requires(const T& t) {
|
|
104
|
+
{ ::tpy::__repr__(t) } -> std::convertible_to<std::string>;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// Mirror tpy::to_bool's acceptance criteria. Going through `tpy::to_bool`
|
|
108
|
+
// itself would instantiate its `static_assert(false, ...)` for
|
|
109
|
+
// non-capable T at concept-check time and break compilation.
|
|
110
|
+
template <typename T>
|
|
111
|
+
concept any_to_bool_capable =
|
|
112
|
+
std::is_same_v<T, std::monostate> ||
|
|
113
|
+
std::is_constructible_v<bool, T> ||
|
|
114
|
+
requires(const T& t) { { t.empty() } -> std::convertible_to<bool>; } ||
|
|
115
|
+
requires(const T& t) { { t.__bool__() } -> std::convertible_to<bool>; };
|
|
116
|
+
|
|
117
|
+
template <typename T>
|
|
118
|
+
concept any_eq_capable = requires(const T& a, const T& b) {
|
|
119
|
+
{ a == b } -> std::convertible_to<bool>;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
template <typename T>
|
|
123
|
+
concept any_hash_capable = requires(const T& t) {
|
|
124
|
+
{ ::tpy::__hash__(t) } -> std::convertible_to<std::uint64_t>;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// Mangled typeid name as the fallback for types without __str__/__repr__.
|
|
128
|
+
// Python's default is `<ClassName object at 0x...>`; TPy has no class-name
|
|
129
|
+
// registry, so the typeid's mangled name is the best we can do.
|
|
130
|
+
inline std::string fallback_object_repr(const std::any& a) {
|
|
131
|
+
std::string s = "<";
|
|
132
|
+
s += a.type().name();
|
|
133
|
+
s += " object>";
|
|
134
|
+
return s;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Resolve the per-T value of type T from std::any once, then pick a
|
|
138
|
+
// rendering: prefer_repr=false favours __str__ over __repr__ (str/print
|
|
139
|
+
// slots); prefer_repr=true inverts (repr slot). Sink can be either
|
|
140
|
+
// std::string& (append) or std::ostream& (operator<<); _emit_to is
|
|
141
|
+
// overloaded for both.
|
|
142
|
+
inline void _emit_to(std::string& buf, std::string_view s) { buf.append(s); }
|
|
143
|
+
inline void _emit_to(std::ostream& os, std::string_view s) { os << s; }
|
|
144
|
+
|
|
145
|
+
template <typename T, bool prefer_repr, typename Sink>
|
|
146
|
+
inline void _write_str_or_repr(Sink& sink, const std::any& a) {
|
|
147
|
+
if constexpr (prefer_repr) {
|
|
148
|
+
if constexpr (any_repr_capable<T>) {
|
|
149
|
+
_emit_to(sink, ::tpy::repr_of(std::any_cast<const T&>(a)));
|
|
150
|
+
return;
|
|
151
|
+
} else if constexpr (any_str_capable<T>) {
|
|
152
|
+
_emit_to(sink, ::tpy::__str__(std::any_cast<const T&>(a)));
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
} else {
|
|
156
|
+
if constexpr (any_str_capable<T>) {
|
|
157
|
+
_emit_to(sink, ::tpy::__str__(std::any_cast<const T&>(a)));
|
|
158
|
+
return;
|
|
159
|
+
} else if constexpr (any_repr_capable<T>) {
|
|
160
|
+
_emit_to(sink, ::tpy::repr_of(std::any_cast<const T&>(a)));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
_emit_to(sink, fallback_object_repr(a));
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
template <typename T>
|
|
168
|
+
constexpr void (*str_slot_for() noexcept)(std::string&, const std::any&) {
|
|
169
|
+
return +[](std::string& buf, const std::any& a) {
|
|
170
|
+
_write_str_or_repr<T, /*prefer_repr=*/false>(buf, a);
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
template <typename T>
|
|
175
|
+
constexpr void (*print_slot_for() noexcept)(std::ostream&, const std::any&) {
|
|
176
|
+
return +[](std::ostream& os, const std::any& a) {
|
|
177
|
+
_write_str_or_repr<T, /*prefer_repr=*/false>(os, a);
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
template <typename T>
|
|
182
|
+
constexpr void (*repr_slot_for() noexcept)(std::string&, const std::any&) {
|
|
183
|
+
return +[](std::string& buf, const std::any& a) {
|
|
184
|
+
_write_str_or_repr<T, /*prefer_repr=*/true>(buf, a);
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
template <typename T>
|
|
189
|
+
constexpr bool (*to_bool_slot_for() noexcept)(const std::any&) {
|
|
190
|
+
if constexpr (any_to_bool_capable<T>) {
|
|
191
|
+
return +[](const std::any& a) -> bool {
|
|
192
|
+
return ::tpy::to_bool(std::any_cast<const T&>(a));
|
|
193
|
+
};
|
|
194
|
+
} else {
|
|
195
|
+
// Python default: objects without __bool__/__len__ are truthy.
|
|
196
|
+
return +[](const std::any&) -> bool { return true; };
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
template <typename T>
|
|
201
|
+
constexpr bool (*equals_slot_for() noexcept)(const std::any&, const std::any&) {
|
|
202
|
+
if constexpr (any_eq_capable<T>) {
|
|
203
|
+
return +[](const std::any& a, const std::any& b) -> bool {
|
|
204
|
+
return std::any_cast<const T&>(a) == std::any_cast<const T&>(b);
|
|
205
|
+
};
|
|
206
|
+
} else {
|
|
207
|
+
return nullptr;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
template <typename T>
|
|
212
|
+
constexpr std::uint64_t (*hash_slot_for() noexcept)(const std::any&) {
|
|
213
|
+
if constexpr (any_hash_capable<T>) {
|
|
214
|
+
return +[](const std::any& a) -> std::uint64_t {
|
|
215
|
+
return ::tpy::__hash__(std::any_cast<const T&>(a));
|
|
216
|
+
};
|
|
217
|
+
} else {
|
|
218
|
+
return nullptr;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
template <typename T>
|
|
223
|
+
constexpr std::string (*type_name_slot_for() noexcept)() {
|
|
224
|
+
return +[]() -> std::string { return ::tpy::type_name<T>(); };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
} // namespace detail
|
|
228
|
+
|
|
229
|
+
// `inline constexpr` template variables guarantee a single instance per
|
|
230
|
+
// T across translation units in a single binary. Cross-shared-library
|
|
231
|
+
// identity is out of scope (TPy builds as one binary).
|
|
232
|
+
//
|
|
233
|
+
// Every slot is conditionally generated. Slots whose underlying op is
|
|
234
|
+
// missing fall back to a sensible default (Python-conformant where
|
|
235
|
+
// possible): str/print/repr render `<typeid object>`, to_bool returns
|
|
236
|
+
// true, equals/hash stay null and trigger the documented runtime
|
|
237
|
+
// behaviour (== returns False; hash() panics).
|
|
238
|
+
template <typename T>
|
|
239
|
+
inline constexpr AnyOps any_ops_for = {
|
|
240
|
+
/*print=*/detail::print_slot_for<T>(),
|
|
241
|
+
/*str=*/detail::str_slot_for<T>(),
|
|
242
|
+
/*repr=*/detail::repr_slot_for<T>(),
|
|
243
|
+
/*to_bool=*/detail::to_bool_slot_for<T>(),
|
|
244
|
+
/*equals=*/detail::equals_slot_for<T>(),
|
|
245
|
+
/*hash=*/detail::hash_slot_for<T>(),
|
|
246
|
+
/*type_name=*/detail::type_name_slot_for<T>(),
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// ---------------------------------------------------------------------
|
|
250
|
+
// make_any<T>: factory that wires the value to its per-T ops table
|
|
251
|
+
// ---------------------------------------------------------------------
|
|
252
|
+
//
|
|
253
|
+
// Codegen emits `::tpy::make_any(value)` and lets argument deduction
|
|
254
|
+
// pick T -- so the source is `make_any(BigInt(42))` rather than the
|
|
255
|
+
// hand-spelled `Any{std::any{BigInt(42)}, &any_ops_for<BigInt>}`.
|
|
256
|
+
// Callers must build `value` so its decayed C++ type *is* the desired
|
|
257
|
+
// storage typeid (e.g. `BigInt(42)` not `42`, `std::string("hi")` not
|
|
258
|
+
// `"hi"`); the codegen layer's _any_storage_form ensures that.
|
|
259
|
+
|
|
260
|
+
template <typename T>
|
|
261
|
+
inline Any make_any(T value) {
|
|
262
|
+
return Any{std::any{std::move(value)}, &any_ops_for<T>};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// ---------------------------------------------------------------------
|
|
266
|
+
// any_cast_or_panic<T>: checked extraction
|
|
267
|
+
// ---------------------------------------------------------------------
|
|
268
|
+
//
|
|
269
|
+
// const-ref overload copies the contents out (auto-coerce paths use
|
|
270
|
+
// this). The rvalue overload moves out at last use.
|
|
271
|
+
|
|
272
|
+
namespace detail {
|
|
273
|
+
|
|
274
|
+
template <typename T>
|
|
275
|
+
inline void check_any_cast(const Any& a) {
|
|
276
|
+
if (a.empty()) {
|
|
277
|
+
::tpy::tpy_panic("use of empty/moved-from Any");
|
|
278
|
+
}
|
|
279
|
+
if (a.value.type() != typeid(T)) {
|
|
280
|
+
::tpy::raise_type_error("Any holds {}, cannot cast to {}",
|
|
281
|
+
a.ops->type_name(),
|
|
282
|
+
::tpy::type_name<T>());
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
} // namespace detail
|
|
287
|
+
|
|
288
|
+
template <typename T>
|
|
289
|
+
T any_cast_or_panic(const Any& a) {
|
|
290
|
+
detail::check_any_cast<T>(a);
|
|
291
|
+
return std::any_cast<T>(a.value);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
template <typename T>
|
|
295
|
+
T any_cast_or_panic(Any&& a) {
|
|
296
|
+
detail::check_any_cast<T>(a);
|
|
297
|
+
T moved = std::any_cast<T>(std::move(a.value));
|
|
298
|
+
// Clear the source so the documented "use of empty/moved-from Any"
|
|
299
|
+
// panic fires on subsequent access. std::any_cast<T>(rvalue) does
|
|
300
|
+
// not necessarily empty the source.
|
|
301
|
+
a.value.reset();
|
|
302
|
+
a.ops = nullptr;
|
|
303
|
+
return moved;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// ---------------------------------------------------------------------
|
|
307
|
+
// any_eq / any_eq_concrete / any_hash
|
|
308
|
+
// ---------------------------------------------------------------------
|
|
309
|
+
//
|
|
310
|
+
// `==` semantics: type-mismatch returns False (Python behaviour for
|
|
311
|
+
// non-promotable types). When the equals slot is null (T isn't Eq),
|
|
312
|
+
// also False -- the only honest answer when T has no notion of equality.
|
|
313
|
+
// Empty/moved-from Any is never equal to anything (also returns False).
|
|
314
|
+
|
|
315
|
+
inline bool any_eq(const Any& a, const Any& b) {
|
|
316
|
+
if (a.empty() || b.empty()) return false;
|
|
317
|
+
if (a.value.type() != b.value.type()) return false;
|
|
318
|
+
if (a.ops == nullptr || a.ops->equals == nullptr) return false;
|
|
319
|
+
return a.ops->equals(a.value, b.value);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
template <typename U>
|
|
323
|
+
bool any_eq_concrete(const Any& a, const U& b) {
|
|
324
|
+
if (a.empty()) return false;
|
|
325
|
+
if (a.value.type() != typeid(U)) return false;
|
|
326
|
+
return std::any_cast<const U&>(a.value) == b;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
template <typename U>
|
|
330
|
+
bool any_eq_concrete(const U& a, const Any& b) {
|
|
331
|
+
return any_eq_concrete<U>(b, a);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Hashing: panics if the contained T is not Hashable, or if the cell
|
|
335
|
+
// is empty. Compile-time `hash(any_var)` cannot fail at type check
|
|
336
|
+
// because Any satisfies the Hashable concept at the type-system level
|
|
337
|
+
// -- the runtime check is the trade-off for accepting arbitrary T.
|
|
338
|
+
inline std::uint64_t any_hash(const Any& a) {
|
|
339
|
+
if (a.empty()) {
|
|
340
|
+
::tpy::tpy_panic("use of empty/moved-from Any");
|
|
341
|
+
}
|
|
342
|
+
if (a.ops == nullptr || a.ops->hash == nullptr) {
|
|
343
|
+
std::string name = (a.ops != nullptr)
|
|
344
|
+
? a.ops->type_name()
|
|
345
|
+
: ::tpy::demangle_type_name(a.value.type().name());
|
|
346
|
+
::tpy::raise_type_error("unhashable type: '{}'", name);
|
|
347
|
+
}
|
|
348
|
+
return a.ops->hash(a.value);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Container-element printing routes through `tpy::detail::print_element`,
|
|
352
|
+
// which renders strings as `'foo'` (repr-flavoured) so `print(d)` for
|
|
353
|
+
// `dict[str, str]` reads `{'k': 'v'}`. Any values inside containers
|
|
354
|
+
// follow the same convention -- route through the repr slot rather
|
|
355
|
+
// than the str slot used by top-level operator<<.
|
|
356
|
+
namespace detail {
|
|
357
|
+
inline void print_element(std::ostream& os, const ::tpy::Any& a) {
|
|
358
|
+
if (a.empty()) {
|
|
359
|
+
::tpy::tpy_panic("use of empty/moved-from Any");
|
|
360
|
+
}
|
|
361
|
+
std::string buf;
|
|
362
|
+
a.ops->repr(buf, a.value);
|
|
363
|
+
os << buf;
|
|
364
|
+
}
|
|
365
|
+
} // namespace detail
|
|
366
|
+
|
|
367
|
+
// ---------------------------------------------------------------------
|
|
368
|
+
// Integration with TPy runtime primitives
|
|
369
|
+
// ---------------------------------------------------------------------
|
|
370
|
+
//
|
|
371
|
+
// `__str__(Any)` falls through to `operator<<` via dunder.hpp's
|
|
372
|
+
// generic-fallback chain -- defining `operator<<` is enough.
|
|
373
|
+
// `__repr__(Any)` needs an explicit definition because the fallback
|
|
374
|
+
// would route through `operator<<` (which renders via the str slot,
|
|
375
|
+
// not the repr slot) and silently produce the str representation.
|
|
376
|
+
|
|
377
|
+
inline std::ostream& operator<<(std::ostream& os, const Any& a) {
|
|
378
|
+
if (a.empty()) {
|
|
379
|
+
::tpy::tpy_panic("use of empty/moved-from Any");
|
|
380
|
+
}
|
|
381
|
+
a.ops->print(os, a.value);
|
|
382
|
+
return os;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
inline std::string __repr__(const Any& a) {
|
|
386
|
+
if (a.empty()) {
|
|
387
|
+
::tpy::tpy_panic("use of empty/moved-from Any");
|
|
388
|
+
}
|
|
389
|
+
std::string buf;
|
|
390
|
+
a.ops->repr(buf, a.value);
|
|
391
|
+
return buf;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
inline std::uint64_t __hash__(const Any& a) {
|
|
395
|
+
return any_hash(a);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// `to_bool(const T&)` in builtins.hpp tests `requires { x.empty(); }`
|
|
399
|
+
// before `__bool__()`, so Any's empty() helper would otherwise hijack
|
|
400
|
+
// truthiness. This explicit overload routes through the to_bool slot.
|
|
401
|
+
inline bool to_bool(const Any& a) {
|
|
402
|
+
if (a.empty()) {
|
|
403
|
+
::tpy::tpy_panic("use of empty/moved-from Any");
|
|
404
|
+
}
|
|
405
|
+
return a.ops->to_bool(a.value);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Equality: typeid-checked. Type mismatch returns False (Python
|
|
409
|
+
// behaviour for incomparable types); null equals slot also False.
|
|
410
|
+
|
|
411
|
+
inline bool operator==(const Any& a, const Any& b) {
|
|
412
|
+
return any_eq(a, b);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
template <typename U>
|
|
416
|
+
requires (!std::same_as<U, Any>)
|
|
417
|
+
inline bool operator==(const Any& a, const U& b) {
|
|
418
|
+
return any_eq_concrete<U>(a, b);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
template <typename U>
|
|
422
|
+
requires (!std::same_as<U, Any>)
|
|
423
|
+
inline bool operator==(const U& a, const Any& b) {
|
|
424
|
+
return any_eq_concrete<U>(b, a);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
} // namespace tpy
|
|
428
|
+
|
|
429
|
+
// std::hash<tpy::Any> for use as a key in std::unordered_map / set
|
|
430
|
+
// based containers (TPy's ordered_map / ordered_set). Routes through
|
|
431
|
+
// the per-type hash slot; panics if the contained T isn't Hashable.
|
|
432
|
+
template <>
|
|
433
|
+
struct std::hash<::tpy::Any> {
|
|
434
|
+
std::size_t operator()(const ::tpy::Any& a) const {
|
|
435
|
+
return static_cast<std::size_t>(::tpy::any_hash(a));
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
// std::format / f-string support: route through the str slot. Format
|
|
440
|
+
// specs are not currently supported on Any (the design defers richer
|
|
441
|
+
// dispatch); only `{}` is accepted.
|
|
442
|
+
template <>
|
|
443
|
+
struct std::formatter<::tpy::Any> {
|
|
444
|
+
constexpr auto parse(std::format_parse_context& ctx) {
|
|
445
|
+
auto it = ctx.begin();
|
|
446
|
+
if (it != ctx.end() && *it != '}') {
|
|
447
|
+
throw std::format_error(
|
|
448
|
+
"format specs on Any are not supported -- narrow first");
|
|
449
|
+
}
|
|
450
|
+
return it;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
auto format(const ::tpy::Any& a, std::format_context& ctx) const {
|
|
454
|
+
if (a.empty()) {
|
|
455
|
+
::tpy::tpy_panic("use of empty/moved-from Any");
|
|
456
|
+
}
|
|
457
|
+
std::string buf;
|
|
458
|
+
a.ops->str(buf, a.value);
|
|
459
|
+
return std::format_to(ctx.out(), "{}", buf);
|
|
460
|
+
}
|
|
461
|
+
};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TurboPython Runtime - Output sink dispatch
|
|
3
|
+
*
|
|
4
|
+
* Resolves a print()-style file= target to a std::ostream& usable with
|
|
5
|
+
* the existing operator<< chain. Three concrete overloads bypass any
|
|
6
|
+
* adapter (cout/cerr via std::ostream&, sys.stdout/stderr via StdStream,
|
|
7
|
+
* open()-files via TextFile); a fallback template wraps any user type
|
|
8
|
+
* satisfying the Writable concept in a streambuf adapter.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
#pragma once
|
|
12
|
+
|
|
13
|
+
#include <cstdint>
|
|
14
|
+
#include <ostream>
|
|
15
|
+
#include <streambuf>
|
|
16
|
+
#include <string_view>
|
|
17
|
+
#include <type_traits>
|
|
18
|
+
|
|
19
|
+
#include "file.hpp"
|
|
20
|
+
#include "system.hpp"
|
|
21
|
+
|
|
22
|
+
namespace tpy {
|
|
23
|
+
|
|
24
|
+
template <typename W>
|
|
25
|
+
concept WritableSink = requires(W& w, std::string_view sv) {
|
|
26
|
+
{ w.write(sv) } -> std::convertible_to<int32_t>;
|
|
27
|
+
{ w.flush() } -> std::same_as<void>;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
namespace detail {
|
|
31
|
+
|
|
32
|
+
// Buffered streambuf forwarding to a Writable's write() / flush().
|
|
33
|
+
// sync() drains the buffer AND calls W::flush() (semantics for `<< std::flush`);
|
|
34
|
+
// the destructor only drains, matching std::ostream's no-flush-on-destroy.
|
|
35
|
+
template <typename W>
|
|
36
|
+
class WritableStreambuf final : public std::streambuf {
|
|
37
|
+
W* w_;
|
|
38
|
+
static constexpr std::size_t kBufSize = 256;
|
|
39
|
+
char buf_[kBufSize];
|
|
40
|
+
|
|
41
|
+
void drain() {
|
|
42
|
+
const auto n = pptr() - pbase();
|
|
43
|
+
if (n > 0) {
|
|
44
|
+
w_->write(std::string_view(pbase(), static_cast<std::size_t>(n)));
|
|
45
|
+
setp(buf_, buf_ + kBufSize);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
protected:
|
|
50
|
+
std::streamsize xsputn(const char* s, std::streamsize n) override {
|
|
51
|
+
if (n <= 0) return 0;
|
|
52
|
+
if (pptr() != pbase()) drain();
|
|
53
|
+
// Mirrors Python's io.IOBase.write: short-write / error returns from
|
|
54
|
+
// the user's write() are not propagated as a streambuf failure.
|
|
55
|
+
w_->write(std::string_view(s, static_cast<std::size_t>(n)));
|
|
56
|
+
return n;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
int_type overflow(int_type ch) override {
|
|
60
|
+
drain();
|
|
61
|
+
if (!traits_type::eq_int_type(ch, traits_type::eof())) {
|
|
62
|
+
*pptr() = traits_type::to_char_type(ch);
|
|
63
|
+
pbump(1);
|
|
64
|
+
}
|
|
65
|
+
return traits_type::not_eof(ch);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
int sync() override {
|
|
69
|
+
drain();
|
|
70
|
+
w_->flush();
|
|
71
|
+
return 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public:
|
|
75
|
+
explicit WritableStreambuf(W& w) : w_(&w) {
|
|
76
|
+
setp(buf_, buf_ + kBufSize);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
~WritableStreambuf() override { drain(); }
|
|
80
|
+
|
|
81
|
+
WritableStreambuf(const WritableStreambuf&) = delete;
|
|
82
|
+
WritableStreambuf(WritableStreambuf&&) = delete;
|
|
83
|
+
WritableStreambuf& operator=(const WritableStreambuf&) = delete;
|
|
84
|
+
WritableStreambuf& operator=(WritableStreambuf&&) = delete;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
template <typename W>
|
|
88
|
+
class WritableOstream final : public std::ostream {
|
|
89
|
+
WritableStreambuf<W> sb_;
|
|
90
|
+
|
|
91
|
+
public:
|
|
92
|
+
explicit WritableOstream(W& w) : std::ostream(nullptr), sb_(w) {
|
|
93
|
+
rdbuf(&sb_);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
WritableOstream(const WritableOstream&) = delete;
|
|
97
|
+
WritableOstream(WritableOstream&&) = delete;
|
|
98
|
+
WritableOstream& operator=(const WritableOstream&) = delete;
|
|
99
|
+
WritableOstream& operator=(WritableOstream&&) = delete;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
} // namespace detail
|
|
103
|
+
|
|
104
|
+
inline std::ostream& as_ostream(std::ostream& os) { return os; }
|
|
105
|
+
inline std::ostream& as_ostream(StdStream& s) { return s.sink(); }
|
|
106
|
+
inline std::ostream& as_ostream(TextFile& f) { return f.sink(); }
|
|
107
|
+
|
|
108
|
+
template <typename W>
|
|
109
|
+
requires WritableSink<W>
|
|
110
|
+
&& (!std::is_base_of_v<std::ostream, W>)
|
|
111
|
+
&& (!std::is_same_v<std::remove_cv_t<W>, StdStream>)
|
|
112
|
+
&& (!std::is_same_v<std::remove_cv_t<W>, TextFile>)
|
|
113
|
+
detail::WritableOstream<W> as_ostream(W& w) {
|
|
114
|
+
return detail::WritableOstream<W>(w);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
} // namespace tpy
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TurboPython Runtime - Async primitives
|
|
3
|
+
*
|
|
4
|
+
* The async surface lives in TPy; see `lib/tpy/tpy/coro/__init__.py`
|
|
5
|
+
* (Waker, Awaker) and `lib/tpy/asyncio/_executor.py` (Executor,
|
|
6
|
+
* _ExecutorScope, _current_executor). The C++ side carries two pieces:
|
|
7
|
+
* `CancelledError` (thrown into a coroutine at the resumed-await
|
|
8
|
+
* position when its task is cancelled) and `poll_with_cancel`, the
|
|
9
|
+
* resume-case helper template every async-def coro frame uses to
|
|
10
|
+
* propagate outer cancellation through to the in-flight sub-coro
|
|
11
|
+
* before polling.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
#pragma once
|
|
15
|
+
|
|
16
|
+
#include "core.hpp"
|
|
17
|
+
|
|
18
|
+
namespace tpy {
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* CancelledError -- thrown into a coroutine at the resumed-await position
|
|
22
|
+
* when its task is cancelled. Inherits BaseException (not Exception) so
|
|
23
|
+
* `except Exception:` does not silently swallow it.
|
|
24
|
+
*/
|
|
25
|
+
struct CancelledError : BaseException {
|
|
26
|
+
CancelledError() : BaseException("CancelledError") {}
|
|
27
|
+
using BaseException::BaseException;
|
|
28
|
+
TPY_THROWABLE_VIRTUALS(CancelledError)
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Resume-case helper: poll an async-def frame's sub-coroutine while
|
|
33
|
+
* propagating outer cancellation through to it.
|
|
34
|
+
*
|
|
35
|
+
* Called from every `S_AFTER_AWAIT_N` block emitted by the async-def
|
|
36
|
+
* codegen. If the outer's `__cancel_pending` flag is set on entry,
|
|
37
|
+
* the helper delivers the cancel by clearing the flag, calling
|
|
38
|
+
* `sub->cancel()`, then polling -- so the sub observes the cancel at
|
|
39
|
+
* its own next suspension point and can run `finally`-with-await
|
|
40
|
+
* cleanup. Three completion paths:
|
|
41
|
+
*
|
|
42
|
+
* - Sub returns Pending and cancel was being delivered: re-set the
|
|
43
|
+
* outer's flag so the cancel persists until the next poll attempt
|
|
44
|
+
* actually delivers it.
|
|
45
|
+
* - Sub raises (CancelledError or another exception): unwinds with
|
|
46
|
+
* a clean cancel_pending state -- nested `finally`-with-await
|
|
47
|
+
* bodies in the outer don't get re-cancelled at every new
|
|
48
|
+
* suspension.
|
|
49
|
+
* - Sub returns Ready synchronously while we were delivering cancel:
|
|
50
|
+
* the sub raced past the cancel signal. Outer cancel still wins;
|
|
51
|
+
* throw `CancelledError`. (The sub's Ready value is discarded as
|
|
52
|
+
* the returned Poll's storage unwinds.)
|
|
53
|
+
*
|
|
54
|
+
* `Sub` is duck-typed: an `std::optional<T>` or `T*` whose pointee
|
|
55
|
+
* provides `cancel()` and `__poll__(Waker) -> Poll<T>`. Both shapes
|
|
56
|
+
* use `->`, so the same template body works for INLINE/ERASED and
|
|
57
|
+
* BORROWED await modes. Inline so the compiler can fold the
|
|
58
|
+
* not-cancelling fast path back to a plain `sub->__poll__(waker)`.
|
|
59
|
+
*/
|
|
60
|
+
template <typename Sub, typename W>
|
|
61
|
+
inline auto poll_with_cancel(Sub&& sub, bool& cancel_pending, W&& waker) {
|
|
62
|
+
bool was_canceling = cancel_pending;
|
|
63
|
+
if (was_canceling) {
|
|
64
|
+
cancel_pending = false;
|
|
65
|
+
sub->cancel();
|
|
66
|
+
}
|
|
67
|
+
auto r = sub->__poll__(waker);
|
|
68
|
+
if (r.is_pending()) {
|
|
69
|
+
if (was_canceling) cancel_pending = true;
|
|
70
|
+
return r;
|
|
71
|
+
}
|
|
72
|
+
if (was_canceling) throw CancelledError();
|
|
73
|
+
return r;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
} // namespace tpy
|