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
tpyc/coercions.py
ADDED
|
@@ -0,0 +1,749 @@
|
|
|
1
|
+
"""Type coercion registry for TurboPython."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from enum import Enum
|
|
7
|
+
from typing import Callable, Optional
|
|
8
|
+
|
|
9
|
+
from .typesys import (
|
|
10
|
+
TpyType, IntLiteralType, FloatLiteralType, LiteralType,
|
|
11
|
+
NominalType, PtrType, OptionalType, OwnType, is_readonly_ptr,
|
|
12
|
+
is_readonly_span, PendingListType, TypeParamRef, TypeParamKind, ReadonlyType,
|
|
13
|
+
is_integer_type, unwrap_readonly, AnyType,
|
|
14
|
+
)
|
|
15
|
+
from .type_def_registry import (
|
|
16
|
+
is_array, is_span, is_list, is_dict, is_set, int_traits_of,
|
|
17
|
+
is_fixed_int_type, is_big_int_type, is_float64_type, is_float32_type,
|
|
18
|
+
is_char_type, is_str_type, is_string_type, is_str_view_type,
|
|
19
|
+
is_bytes_type, is_bytearray_type, is_bytes_view_type,
|
|
20
|
+
is_basic_slice_type, is_slice_type,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class CoercionContext(Enum):
|
|
25
|
+
"""Context in which a type coercion is being applied."""
|
|
26
|
+
ASSIGN = "assign"
|
|
27
|
+
INIT = "init"
|
|
28
|
+
ARG = "arg"
|
|
29
|
+
RETURN = "return"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# A type-side matcher: predicate that identifies the actual/expected side.
|
|
33
|
+
# Used by `Coercion.from_type` / `Coercion.to_type` as a coarse pre-filter;
|
|
34
|
+
# finer discrimination (e.g. element equality, readonly-ness) belongs in
|
|
35
|
+
# `Coercion.type_match`.
|
|
36
|
+
TypeMatcher = Callable[[TpyType], bool]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _is(cls: type) -> TypeMatcher:
|
|
40
|
+
"""Build a TypeMatcher that checks isinstance against a class."""
|
|
41
|
+
return lambda t: isinstance(t, cls)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _match_any_side(_: TpyType) -> bool:
|
|
45
|
+
return True
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _match_any(_: TpyType, __: TpyType) -> bool:
|
|
49
|
+
return True
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _int_type_param_match(actual: TpyType, expected: TpyType) -> bool:
|
|
53
|
+
"""Check if actual is an INT TypeParamRef."""
|
|
54
|
+
return isinstance(actual, TypeParamRef) and actual.kind == TypeParamKind.INT
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _int_literal_fits_fixed_int(lit: TpyType, target: TpyType) -> bool:
|
|
58
|
+
"""check_range for int_literal_to_fixed_int: literal value (if known) must
|
|
59
|
+
fit in the target fixed-int's range."""
|
|
60
|
+
if not isinstance(lit, IntLiteralType):
|
|
61
|
+
return False
|
|
62
|
+
tr = int_traits_of(target)
|
|
63
|
+
if tr is None:
|
|
64
|
+
return False
|
|
65
|
+
return lit.value is None or (tr.min_value <= lit.value <= tr.max_value)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _is_safe_widening(actual: TpyType, expected: TpyType) -> bool:
|
|
69
|
+
"""Check if actual fixed-int can safely widen to expected fixed-int."""
|
|
70
|
+
a = int_traits_of(actual)
|
|
71
|
+
b = int_traits_of(expected)
|
|
72
|
+
if a is None or b is None:
|
|
73
|
+
return False
|
|
74
|
+
if a == b:
|
|
75
|
+
return False
|
|
76
|
+
if a.signed == b.signed:
|
|
77
|
+
return a.bits < b.bits
|
|
78
|
+
# Unsigned -> signed: need strictly more bits (e.g. UInt8 -> Int16)
|
|
79
|
+
if not a.signed and b.signed:
|
|
80
|
+
return a.bits < b.bits
|
|
81
|
+
return False
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _spanlike_to_span_match(actual: TpyType, expected: TpyType) -> bool:
|
|
85
|
+
"""Check if actual type (extending Spannable[T]) can coerce to Span[T]/ReadOnlySpan[T]."""
|
|
86
|
+
if not is_span(expected):
|
|
87
|
+
return False
|
|
88
|
+
# Span[readonly[T]] and readonly[container] cannot coerce to mutable Span (const violation)
|
|
89
|
+
expected_is_readonly = is_readonly_span(expected)
|
|
90
|
+
if is_span(actual) and is_readonly_span(actual) and not expected_is_readonly:
|
|
91
|
+
return False
|
|
92
|
+
if isinstance(actual, ReadonlyType) and not expected_is_readonly:
|
|
93
|
+
return False
|
|
94
|
+
actual_elem = actual.get_element_type()
|
|
95
|
+
if actual_elem is None:
|
|
96
|
+
return False
|
|
97
|
+
expected_elem = unwrap_readonly(expected.type_args[0])
|
|
98
|
+
|
|
99
|
+
# PendingListType is an internal compiler type that resolves to list (which extends Spannable).
|
|
100
|
+
# Handle it directly since it's not in the module system.
|
|
101
|
+
if isinstance(actual, PendingListType):
|
|
102
|
+
if actual_elem == expected_elem:
|
|
103
|
+
return True
|
|
104
|
+
# IntLiteral elements coerce to any fixed-width int or BigInt
|
|
105
|
+
if isinstance(actual_elem, IntLiteralType) and is_integer_type(expected_elem):
|
|
106
|
+
return True
|
|
107
|
+
return False
|
|
108
|
+
|
|
109
|
+
# Check if actual is a builtin type that implements Spannable[T].
|
|
110
|
+
# These are compiler-internal types with known span coercion support.
|
|
111
|
+
if not (is_array(actual) or is_list(actual)):
|
|
112
|
+
return False
|
|
113
|
+
if actual_elem == expected_elem:
|
|
114
|
+
return True
|
|
115
|
+
if isinstance(actual_elem, IntLiteralType) and is_integer_type(expected_elem):
|
|
116
|
+
return True
|
|
117
|
+
return False
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
# Convenience matchers for the Ptr-shape rules (kept readable as helpers).
|
|
121
|
+
def _is_user_record(t: TpyType) -> bool:
|
|
122
|
+
return isinstance(t, NominalType) and t.is_user_record
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _is_mutable_ptr(t: TpyType) -> bool:
|
|
126
|
+
return isinstance(t, PtrType) and not is_readonly_ptr(t)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _is_readonly_ptr_match(t: TpyType) -> bool:
|
|
130
|
+
return isinstance(t, PtrType) and is_readonly_ptr(t)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
@dataclass(frozen=True)
|
|
134
|
+
class Coercion:
|
|
135
|
+
"""A type coercion rule.
|
|
136
|
+
|
|
137
|
+
`from_type` / `to_type` are predicates on a single type (coarse pre-filter).
|
|
138
|
+
`type_match` is an optional finer two-sided predicate.
|
|
139
|
+
"""
|
|
140
|
+
name: str
|
|
141
|
+
from_type: TypeMatcher
|
|
142
|
+
to_type: TypeMatcher
|
|
143
|
+
type_match: Callable[[TpyType, TpyType], bool] = _match_any
|
|
144
|
+
contexts: Optional[set[CoercionContext]] = None
|
|
145
|
+
requires_lvalue: bool = False
|
|
146
|
+
requires_mutable_lvalue: bool = False
|
|
147
|
+
forbid_return_local: bool = False
|
|
148
|
+
# Lossless coercion safe for protocol return type matching.
|
|
149
|
+
protocol_safe: bool = False
|
|
150
|
+
# Lossless widening (actual->expected) at a container element position:
|
|
151
|
+
# iterating actual yields values that widen implicitly into expected.
|
|
152
|
+
# "Lossless" follows Python/CPython's informal notion: large fixed-ints
|
|
153
|
+
# to Float32 and BigInt to float/Float32 lose mantissa precision but are
|
|
154
|
+
# still considered widenings at this position (same as implicit int->float
|
|
155
|
+
# promotion in Python arithmetic).
|
|
156
|
+
widening_safe: bool = False
|
|
157
|
+
check_range: Optional[Callable[[TpyType, TpyType], bool]] = None
|
|
158
|
+
# Address-taking coercions (`&{expr}`) produce a Ptr that is unconditionally
|
|
159
|
+
# non-null. Consumers can elide the deref null-check, same as for `take_ptr`.
|
|
160
|
+
produces_non_null_ptr: bool = False
|
|
161
|
+
codegen: Callable[[str, TpyType, TpyType, CoercionContext], str] = lambda expr, _a, _e, _c: expr
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
# NOTE: Order matters; higher priority first for overlapping rules.
|
|
165
|
+
COERCIONS: list[Coercion] = [
|
|
166
|
+
# INT type parameter coercions (compile-time constants)
|
|
167
|
+
Coercion(
|
|
168
|
+
name="int_type_param_to_fixed_int",
|
|
169
|
+
from_type=_is(TypeParamRef),
|
|
170
|
+
to_type=is_fixed_int_type,
|
|
171
|
+
type_match=_int_type_param_match,
|
|
172
|
+
codegen=lambda e, _a, b, _c: f"static_cast<{b.to_cpp()}>({e})",
|
|
173
|
+
),
|
|
174
|
+
Coercion(
|
|
175
|
+
name="int_type_param_to_bigint",
|
|
176
|
+
from_type=_is(TypeParamRef),
|
|
177
|
+
to_type=is_big_int_type,
|
|
178
|
+
type_match=_int_type_param_match,
|
|
179
|
+
codegen=lambda e, _a, _b, _c: f"::tpy::BigInt(static_cast<int64_t>({e}))",
|
|
180
|
+
),
|
|
181
|
+
|
|
182
|
+
# Integer literal to any fixed-width integer (range-checked)
|
|
183
|
+
Coercion(
|
|
184
|
+
name="int_literal_to_fixed_int",
|
|
185
|
+
from_type=_is(IntLiteralType),
|
|
186
|
+
to_type=is_fixed_int_type,
|
|
187
|
+
check_range=_int_literal_fits_fixed_int,
|
|
188
|
+
),
|
|
189
|
+
|
|
190
|
+
# Integer literal to BigInt (always valid)
|
|
191
|
+
Coercion(
|
|
192
|
+
name="int_literal_to_bigint",
|
|
193
|
+
from_type=_is(IntLiteralType),
|
|
194
|
+
to_type=is_big_int_type,
|
|
195
|
+
),
|
|
196
|
+
|
|
197
|
+
# Widening between fixed-width integers (e.g. Int8 -> Int32, UInt8 -> Int16)
|
|
198
|
+
Coercion(
|
|
199
|
+
name="fixed_int_widening",
|
|
200
|
+
from_type=is_fixed_int_type,
|
|
201
|
+
to_type=is_fixed_int_type,
|
|
202
|
+
type_match=_is_safe_widening,
|
|
203
|
+
widening_safe=True,
|
|
204
|
+
codegen=lambda e, _a, b, _c: f"static_cast<{b.to_cpp()}>({e})",
|
|
205
|
+
),
|
|
206
|
+
|
|
207
|
+
# Fixed-width integer to BigInt
|
|
208
|
+
Coercion(
|
|
209
|
+
name="fixed_int_to_bigint",
|
|
210
|
+
from_type=is_fixed_int_type,
|
|
211
|
+
to_type=is_big_int_type,
|
|
212
|
+
widening_safe=True,
|
|
213
|
+
codegen=lambda e, _a, _b, _c: f"::tpy::BigInt({e})",
|
|
214
|
+
),
|
|
215
|
+
# BigInt to fixed-width integer (narrowing, runtime checked)
|
|
216
|
+
Coercion(
|
|
217
|
+
name="bigint_to_fixed_int",
|
|
218
|
+
from_type=is_big_int_type,
|
|
219
|
+
to_type=is_fixed_int_type,
|
|
220
|
+
codegen=lambda e, _a, b, _c: f"({e}).to_fixed_check<{b.to_cpp()}>()",
|
|
221
|
+
),
|
|
222
|
+
|
|
223
|
+
# Float coercions
|
|
224
|
+
Coercion(
|
|
225
|
+
name="int_literal_to_float",
|
|
226
|
+
from_type=_is(IntLiteralType),
|
|
227
|
+
to_type=is_float64_type,
|
|
228
|
+
codegen=lambda e, _a, _b, _c: f"static_cast<double>({e})",
|
|
229
|
+
),
|
|
230
|
+
Coercion(
|
|
231
|
+
name="fixed_int_to_float",
|
|
232
|
+
from_type=is_fixed_int_type,
|
|
233
|
+
to_type=is_float64_type,
|
|
234
|
+
widening_safe=True,
|
|
235
|
+
codegen=lambda e, _a, _b, _c: f"static_cast<double>({e})",
|
|
236
|
+
),
|
|
237
|
+
Coercion(
|
|
238
|
+
name="bigint_to_float",
|
|
239
|
+
from_type=is_big_int_type,
|
|
240
|
+
to_type=is_float64_type,
|
|
241
|
+
widening_safe=True,
|
|
242
|
+
codegen=lambda e, _a, _b, _c: f"static_cast<double>({e})",
|
|
243
|
+
),
|
|
244
|
+
|
|
245
|
+
# Float literal coercions (adapts to context)
|
|
246
|
+
Coercion(
|
|
247
|
+
name="float_literal_to_float",
|
|
248
|
+
from_type=_is(FloatLiteralType),
|
|
249
|
+
to_type=is_float64_type,
|
|
250
|
+
codegen=lambda e, _a, _b, _c: e,
|
|
251
|
+
),
|
|
252
|
+
Coercion(
|
|
253
|
+
name="float_literal_to_float32",
|
|
254
|
+
from_type=_is(FloatLiteralType),
|
|
255
|
+
to_type=is_float32_type,
|
|
256
|
+
codegen=lambda e, _a, _b, _c: e, # identity: gen_expr provides 'f' suffix
|
|
257
|
+
),
|
|
258
|
+
|
|
259
|
+
# Float32 coercions (widening to Float32)
|
|
260
|
+
Coercion(
|
|
261
|
+
name="int_literal_to_float32",
|
|
262
|
+
from_type=_is(IntLiteralType),
|
|
263
|
+
to_type=is_float32_type,
|
|
264
|
+
codegen=lambda e, _a, _b, _c: f"static_cast<float>({e})",
|
|
265
|
+
),
|
|
266
|
+
Coercion(
|
|
267
|
+
name="fixed_int_to_float32",
|
|
268
|
+
from_type=is_fixed_int_type,
|
|
269
|
+
to_type=is_float32_type,
|
|
270
|
+
widening_safe=True,
|
|
271
|
+
codegen=lambda e, _a, _b, _c: f"static_cast<float>({e})",
|
|
272
|
+
),
|
|
273
|
+
Coercion(
|
|
274
|
+
name="bigint_to_float32",
|
|
275
|
+
from_type=is_big_int_type,
|
|
276
|
+
to_type=is_float32_type,
|
|
277
|
+
widening_safe=True,
|
|
278
|
+
codegen=lambda e, _a, _b, _c: f"static_cast<float>({e})",
|
|
279
|
+
),
|
|
280
|
+
# Float32 -> float (widening, lossless)
|
|
281
|
+
Coercion(
|
|
282
|
+
name="float32_to_float",
|
|
283
|
+
from_type=is_float32_type,
|
|
284
|
+
to_type=is_float64_type,
|
|
285
|
+
widening_safe=True,
|
|
286
|
+
codegen=lambda e, _a, _b, _c: f"static_cast<double>({e})",
|
|
287
|
+
),
|
|
288
|
+
# float -> Float32 (narrowing, but allowed for convenience -- matches C++ behavior)
|
|
289
|
+
Coercion(
|
|
290
|
+
name="float_to_float32",
|
|
291
|
+
from_type=is_float64_type,
|
|
292
|
+
to_type=is_float32_type,
|
|
293
|
+
codegen=lambda e, _a, _b, _c: f"static_cast<float>({e})",
|
|
294
|
+
),
|
|
295
|
+
|
|
296
|
+
# Char to str coercion
|
|
297
|
+
Coercion(
|
|
298
|
+
name="char_to_str",
|
|
299
|
+
from_type=is_char_type,
|
|
300
|
+
to_type=is_str_type,
|
|
301
|
+
codegen=lambda e, _a, _b, _c: f"std::string(::tpy::char_to_str({e}))",
|
|
302
|
+
),
|
|
303
|
+
# Char to String coercion
|
|
304
|
+
Coercion(
|
|
305
|
+
name="char_to_string",
|
|
306
|
+
from_type=is_char_type,
|
|
307
|
+
to_type=is_string_type,
|
|
308
|
+
codegen=lambda e, _a, _b, _c: f"std::string(1, {e})",
|
|
309
|
+
),
|
|
310
|
+
# Char to StrView coercion
|
|
311
|
+
Coercion(
|
|
312
|
+
name="char_to_strview",
|
|
313
|
+
from_type=is_char_type,
|
|
314
|
+
to_type=is_str_view_type,
|
|
315
|
+
codegen=lambda e, _a, _b, _c: f"::tpy::char_to_str({e})",
|
|
316
|
+
),
|
|
317
|
+
|
|
318
|
+
# String <-> str (both lower to std::string in non-ARG contexts, but `str`
|
|
319
|
+
# params lower to std::string_view at ARG). string -> str is always safe
|
|
320
|
+
# (std::string implicitly converts to std::string_view). str -> String
|
|
321
|
+
# materializes at ARG (where str is string_view and String is const
|
|
322
|
+
# std::string& / std::string) and is identity elsewhere (both std::string).
|
|
323
|
+
# The ARG wrap skips plain string literals -- `"foo"` is const char* which
|
|
324
|
+
# binds to const std::string& directly, so `std::string("foo")` is only a
|
|
325
|
+
# cosmetic change. Non-literal sources (names, calls, slices) need the wrap.
|
|
326
|
+
Coercion(
|
|
327
|
+
name="string_to_str",
|
|
328
|
+
from_type=is_string_type,
|
|
329
|
+
to_type=is_str_type,
|
|
330
|
+
protocol_safe=True,
|
|
331
|
+
),
|
|
332
|
+
Coercion(
|
|
333
|
+
name="str_to_string",
|
|
334
|
+
from_type=is_str_type,
|
|
335
|
+
to_type=is_string_type,
|
|
336
|
+
codegen=lambda e, _a, _b, c: (
|
|
337
|
+
e if c != CoercionContext.ARG or (e.startswith('"') and e.endswith('"'))
|
|
338
|
+
else f"std::string({e})"
|
|
339
|
+
),
|
|
340
|
+
),
|
|
341
|
+
|
|
342
|
+
# String -> StrView (safe implicit, C++ handles std::string -> string_view)
|
|
343
|
+
Coercion(
|
|
344
|
+
name="string_to_strview",
|
|
345
|
+
from_type=is_string_type,
|
|
346
|
+
to_type=is_str_view_type,
|
|
347
|
+
),
|
|
348
|
+
# str -> StrView (safe implicit, C++ handles std::string -> string_view)
|
|
349
|
+
Coercion(
|
|
350
|
+
name="str_to_strview",
|
|
351
|
+
from_type=is_str_type,
|
|
352
|
+
to_type=is_str_view_type,
|
|
353
|
+
),
|
|
354
|
+
|
|
355
|
+
# StrView -> String (allocates)
|
|
356
|
+
Coercion(
|
|
357
|
+
name="strview_to_string",
|
|
358
|
+
from_type=is_str_view_type,
|
|
359
|
+
to_type=is_string_type,
|
|
360
|
+
codegen=lambda e, _a, _b, _c: f"std::string({e})",
|
|
361
|
+
protocol_safe=True,
|
|
362
|
+
),
|
|
363
|
+
# StrView -> str. At ARG position plain `str` params lower to
|
|
364
|
+
# std::string_view, so the transfer is identity; but `Own[str]` params
|
|
365
|
+
# (e.g. list[str].append's value) lower to std::string by value, and
|
|
366
|
+
# INIT/ASSIGN/RETURN targets are also owned std::string -- both need
|
|
367
|
+
# materialization.
|
|
368
|
+
Coercion(
|
|
369
|
+
name="strview_to_str",
|
|
370
|
+
from_type=is_str_view_type,
|
|
371
|
+
to_type=is_str_type,
|
|
372
|
+
codegen=lambda e, _a, b, c: (
|
|
373
|
+
e if c == CoercionContext.ARG and not isinstance(b, OwnType)
|
|
374
|
+
else f"std::string({e})"
|
|
375
|
+
),
|
|
376
|
+
protocol_safe=True,
|
|
377
|
+
),
|
|
378
|
+
# Optional[StrView] <-> Optional[str]: plain `Optional[str]` params at ARG
|
|
379
|
+
# lower to `std::optional<std::string_view>`, so the transfer is identity;
|
|
380
|
+
# but `Own[Optional[str]]` params (e.g. list[Optional[str]].append) and
|
|
381
|
+
# non-ARG contexts (INIT/ASSIGN/RETURN) target `std::optional<std::string>`
|
|
382
|
+
# and need per-element materialization. Statement-expression pattern hoists
|
|
383
|
+
# the source into a local so the conditional evaluates the expression
|
|
384
|
+
# exactly once.
|
|
385
|
+
Coercion(
|
|
386
|
+
name="optional_strview_to_str",
|
|
387
|
+
from_type=lambda t: isinstance(t, OptionalType) and is_str_view_type(t.inner),
|
|
388
|
+
to_type=lambda t: isinstance(t, OptionalType) and is_str_type(t.inner),
|
|
389
|
+
codegen=lambda e, _a, b, c: (
|
|
390
|
+
e if c == CoercionContext.ARG and not isinstance(b, OwnType)
|
|
391
|
+
else (f"({{ auto __ov = ({e}); "
|
|
392
|
+
f"__ov ? std::make_optional(std::string(*__ov)) : std::nullopt; }})")
|
|
393
|
+
),
|
|
394
|
+
),
|
|
395
|
+
Coercion(
|
|
396
|
+
name="optional_str_to_strview",
|
|
397
|
+
from_type=lambda t: isinstance(t, OptionalType) and is_str_type(t.inner),
|
|
398
|
+
to_type=lambda t: isinstance(t, OptionalType) and is_str_view_type(t.inner),
|
|
399
|
+
codegen=lambda e, _a, b, c: (
|
|
400
|
+
e if c == CoercionContext.ARG and not isinstance(b, OwnType)
|
|
401
|
+
else (f"({{ auto __ov = ({e}); "
|
|
402
|
+
f"__ov ? std::make_optional(std::string_view(*__ov)) : std::nullopt; }})")
|
|
403
|
+
),
|
|
404
|
+
),
|
|
405
|
+
|
|
406
|
+
# bytearray <-> bytes identity coercions (both map to std::vector<uint8_t>)
|
|
407
|
+
Coercion(
|
|
408
|
+
name="bytearray_to_bytes",
|
|
409
|
+
from_type=is_bytearray_type,
|
|
410
|
+
to_type=is_bytes_type,
|
|
411
|
+
protocol_safe=True,
|
|
412
|
+
),
|
|
413
|
+
Coercion(
|
|
414
|
+
name="bytes_to_bytearray",
|
|
415
|
+
from_type=is_bytes_type,
|
|
416
|
+
to_type=is_bytearray_type,
|
|
417
|
+
),
|
|
418
|
+
|
|
419
|
+
# bytes/bytearray -> BytesView (safe implicit, vector -> span)
|
|
420
|
+
Coercion(
|
|
421
|
+
name="bytes_to_bytesview",
|
|
422
|
+
from_type=is_bytes_type,
|
|
423
|
+
to_type=is_bytes_view_type,
|
|
424
|
+
),
|
|
425
|
+
Coercion(
|
|
426
|
+
name="bytearray_to_bytesview",
|
|
427
|
+
from_type=is_bytearray_type,
|
|
428
|
+
to_type=is_bytes_view_type,
|
|
429
|
+
),
|
|
430
|
+
|
|
431
|
+
# BytesView -> bytes/bytearray (allocates)
|
|
432
|
+
Coercion(
|
|
433
|
+
name="bytesview_to_bytes",
|
|
434
|
+
from_type=is_bytes_view_type,
|
|
435
|
+
to_type=is_bytes_type,
|
|
436
|
+
codegen=lambda e, _a, _b, _c: f"std::vector<uint8_t>({e}.begin(), {e}.end())",
|
|
437
|
+
protocol_safe=True,
|
|
438
|
+
),
|
|
439
|
+
Coercion(
|
|
440
|
+
name="bytesview_to_bytearray",
|
|
441
|
+
from_type=is_bytes_view_type,
|
|
442
|
+
to_type=is_bytearray_type,
|
|
443
|
+
codegen=lambda e, _a, _b, _c: f"std::vector<uint8_t>({e}.begin(), {e}.end())",
|
|
444
|
+
protocol_safe=True,
|
|
445
|
+
),
|
|
446
|
+
|
|
447
|
+
# Pointer coercions
|
|
448
|
+
Coercion(
|
|
449
|
+
name="record_to_ptr",
|
|
450
|
+
from_type=_is_user_record,
|
|
451
|
+
to_type=_is_mutable_ptr,
|
|
452
|
+
type_match=lambda rec, ptr: (
|
|
453
|
+
isinstance(ptr.pointee, NominalType) and ptr.pointee.is_user_record
|
|
454
|
+
and rec.name == ptr.pointee.name
|
|
455
|
+
),
|
|
456
|
+
requires_lvalue=True,
|
|
457
|
+
requires_mutable_lvalue=True,
|
|
458
|
+
forbid_return_local=True,
|
|
459
|
+
produces_non_null_ptr=True,
|
|
460
|
+
codegen=lambda e, _a, _b, _c: f"&{e}",
|
|
461
|
+
),
|
|
462
|
+
Coercion(
|
|
463
|
+
name="record_to_const_ptr",
|
|
464
|
+
from_type=_is_user_record,
|
|
465
|
+
to_type=_is_readonly_ptr_match,
|
|
466
|
+
type_match=lambda rec, ptr: (
|
|
467
|
+
isinstance(ptr.inner_pointee, NominalType) and ptr.inner_pointee.is_user_record
|
|
468
|
+
and rec.name == ptr.inner_pointee.name
|
|
469
|
+
),
|
|
470
|
+
requires_lvalue=True,
|
|
471
|
+
forbid_return_local=True,
|
|
472
|
+
produces_non_null_ptr=True,
|
|
473
|
+
codegen=lambda e, _a, _b, _c: f"&{e}",
|
|
474
|
+
),
|
|
475
|
+
Coercion(
|
|
476
|
+
name="ptr_to_const_ptr",
|
|
477
|
+
from_type=_is_mutable_ptr,
|
|
478
|
+
to_type=_is_readonly_ptr_match,
|
|
479
|
+
type_match=lambda p1, p2: p1.inner_pointee == p2.inner_pointee,
|
|
480
|
+
),
|
|
481
|
+
Coercion(
|
|
482
|
+
name="span_to_readonly_span",
|
|
483
|
+
from_type=_is(NominalType),
|
|
484
|
+
to_type=_is(NominalType),
|
|
485
|
+
type_match=lambda s1, s2: (
|
|
486
|
+
is_span(s1) and is_span(s2)
|
|
487
|
+
and not is_readonly_span(s1) and is_readonly_span(s2)
|
|
488
|
+
and unwrap_readonly(s1.type_args[0]) == unwrap_readonly(s2.type_args[0])
|
|
489
|
+
),
|
|
490
|
+
protocol_safe=True,
|
|
491
|
+
),
|
|
492
|
+
# basic_slice -> slice (adds step=nullopt). C++ implicit via Slice(BasicSlice) ctor.
|
|
493
|
+
Coercion(
|
|
494
|
+
name="basic_slice_to_slice",
|
|
495
|
+
from_type=is_basic_slice_type,
|
|
496
|
+
to_type=is_slice_type,
|
|
497
|
+
),
|
|
498
|
+
# Span coercions: any Spannable[T] type can coerce to Span[T]
|
|
499
|
+
# Arg context allows temporaries
|
|
500
|
+
Coercion(
|
|
501
|
+
name="spanlike_to_span_arg",
|
|
502
|
+
from_type=_match_any_side, # Matches any type; _spanlike_to_span_match filters by protocol
|
|
503
|
+
to_type=_is(NominalType),
|
|
504
|
+
type_match=_spanlike_to_span_match,
|
|
505
|
+
contexts={CoercionContext.ARG},
|
|
506
|
+
),
|
|
507
|
+
# Non-arg contexts require lvalue (can't take span of temporary)
|
|
508
|
+
Coercion(
|
|
509
|
+
name="spanlike_to_span",
|
|
510
|
+
from_type=_match_any_side, # Matches any type; _spanlike_to_span_match filters by protocol
|
|
511
|
+
to_type=_is(NominalType),
|
|
512
|
+
type_match=_spanlike_to_span_match,
|
|
513
|
+
contexts={CoercionContext.INIT, CoercionContext.ASSIGN, CoercionContext.RETURN},
|
|
514
|
+
requires_lvalue=True,
|
|
515
|
+
forbid_return_local=True,
|
|
516
|
+
),
|
|
517
|
+
]
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
def resolve_coercion(actual: TpyType, expected: TpyType, ctx: CoercionContext) -> Optional[Coercion]:
|
|
521
|
+
"""Find a coercion rule that converts actual to expected in the given context."""
|
|
522
|
+
# PERF TODO: linear scan over ~39 rules, each evaluating two Python-level
|
|
523
|
+
# predicates (from_type / to_type) plus an optional type_match. When primitive
|
|
524
|
+
# subclasses were collapsed to NominalType singletons, from_type / to_type
|
|
525
|
+
# changed from C-level isinstance checks to Python calls that do a
|
|
526
|
+
# type_def_of dict lookup. Most rules are indexable by (from_qname, to_qname) --
|
|
527
|
+
# a hash-table dispatch with a fallback linear scan for wildcard-side rules
|
|
528
|
+
# (spanlike_to_span_arg, DEREF_COERCION) would cut per-call cost >10x.
|
|
529
|
+
# Not worth doing until a profile shows dispatch in the top costs.
|
|
530
|
+
for coercion in COERCIONS:
|
|
531
|
+
if coercion.contexts is not None and ctx not in coercion.contexts:
|
|
532
|
+
continue
|
|
533
|
+
if coercion.from_type(actual) and coercion.to_type(expected):
|
|
534
|
+
if coercion.type_match(actual, expected):
|
|
535
|
+
return coercion
|
|
536
|
+
return None
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
def is_protocol_safe_coercion(actual: TpyType, expected: TpyType) -> bool:
|
|
540
|
+
"""Check if actual can coerce to expected in a protocol return type context.
|
|
541
|
+
|
|
542
|
+
Only lossless coercions marked protocol_safe=True are considered.
|
|
543
|
+
"""
|
|
544
|
+
for coercion in COERCIONS:
|
|
545
|
+
if not coercion.protocol_safe:
|
|
546
|
+
continue
|
|
547
|
+
if coercion.from_type(actual) and coercion.to_type(expected):
|
|
548
|
+
if coercion.type_match(actual, expected):
|
|
549
|
+
return True
|
|
550
|
+
return False
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
def is_protocol_type_arg_widening(
|
|
554
|
+
actual: TpyType, expected: TpyType, default_int_type: TpyType,
|
|
555
|
+
) -> bool:
|
|
556
|
+
"""Check if actual->expected is a lossless widening at a protocol type-arg position.
|
|
557
|
+
|
|
558
|
+
Used for container conformance (e.g. list[A] satisfies Iterable[B]) where
|
|
559
|
+
the caller iterates actual and each element implicitly widens into expected.
|
|
560
|
+
Narrowing is rejected (list[Int32] must NOT satisfy Iterable[UInt8]).
|
|
561
|
+
|
|
562
|
+
At this position `actual` is an element type of a container, never a scalar.
|
|
563
|
+
IntLiteralType's concrete value is therefore meaningless (it describes the
|
|
564
|
+
first element only, not the whole sequence), so we treat it as the compiler's
|
|
565
|
+
default int type and fall through to the standard int->int widening rules.
|
|
566
|
+
"""
|
|
567
|
+
# readonly is a container-level qualifier at element positions.
|
|
568
|
+
actual = unwrap_readonly(actual)
|
|
569
|
+
expected = unwrap_readonly(expected)
|
|
570
|
+
if isinstance(actual, IntLiteralType):
|
|
571
|
+
actual = default_int_type
|
|
572
|
+
elif isinstance(actual, FloatLiteralType):
|
|
573
|
+
# No default_float concept: any float target is a lossless widening
|
|
574
|
+
# of an abstract float literal.
|
|
575
|
+
return is_float64_type(expected) or is_float32_type(expected)
|
|
576
|
+
if actual == expected:
|
|
577
|
+
return True
|
|
578
|
+
for c in COERCIONS:
|
|
579
|
+
if (c.widening_safe and c.from_type(actual) and c.to_type(expected)
|
|
580
|
+
and c.type_match(actual, expected)):
|
|
581
|
+
return True
|
|
582
|
+
return False
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
def _deref_codegen(e: str, actual: TpyType, _expected: TpyType, _ctx: CoercionContext) -> str:
|
|
586
|
+
if isinstance(actual, PtrType):
|
|
587
|
+
return f"::tpy::deref_check({e})"
|
|
588
|
+
return f"{e}.__deref__()"
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
DEREF_COERCION = Coercion(
|
|
592
|
+
name="deref_to_target",
|
|
593
|
+
from_type=_match_any_side,
|
|
594
|
+
to_type=_match_any_side,
|
|
595
|
+
codegen=_deref_codegen,
|
|
596
|
+
)
|
|
597
|
+
|
|
598
|
+
# @value_ptr_coercion: T -> Ptr[T] coercion for any type (not in COERCIONS list).
|
|
599
|
+
# Applied explicitly by calls.py for functions with @value_ptr_coercion.
|
|
600
|
+
VALUE_TO_PTR = Coercion(
|
|
601
|
+
name="value_to_ptr",
|
|
602
|
+
from_type=_match_any_side,
|
|
603
|
+
to_type=_is(PtrType),
|
|
604
|
+
requires_lvalue=True,
|
|
605
|
+
requires_mutable_lvalue=True,
|
|
606
|
+
forbid_return_local=True,
|
|
607
|
+
produces_non_null_ptr=True,
|
|
608
|
+
codegen=lambda e, _a, _b, _c: f"&{e}",
|
|
609
|
+
)
|
|
610
|
+
|
|
611
|
+
# Pre-built coercions for inheritance-based upcasts (not in COERCIONS list --
|
|
612
|
+
# requires TypeRegistry access that type_match lambdas don't have).
|
|
613
|
+
# Used directly by compatibility.py.
|
|
614
|
+
UPCAST_TO_PTR = Coercion(
|
|
615
|
+
name="upcast_to_ptr",
|
|
616
|
+
from_type=_is(NominalType),
|
|
617
|
+
to_type=_is(PtrType),
|
|
618
|
+
requires_lvalue=True,
|
|
619
|
+
requires_mutable_lvalue=True,
|
|
620
|
+
forbid_return_local=True,
|
|
621
|
+
produces_non_null_ptr=True,
|
|
622
|
+
codegen=lambda e, _a, _b, _c: f"&{e}",
|
|
623
|
+
)
|
|
624
|
+
|
|
625
|
+
# Pre-built coercions for __span__() and Spannable[T] protocol coercion to ReadOnlySpan.
|
|
626
|
+
# Used directly by compatibility.py (not in COERCIONS list); from_type is not consulted.
|
|
627
|
+
# Codegen is handled in expressions.py _gen_span_coercion.
|
|
628
|
+
# Arg context: temporaries allowed.
|
|
629
|
+
SPAN_METHOD_TO_SPAN_ARG = Coercion(
|
|
630
|
+
name="span_method_to_span_arg",
|
|
631
|
+
from_type=_match_any_side,
|
|
632
|
+
to_type=_is(NominalType),
|
|
633
|
+
)
|
|
634
|
+
|
|
635
|
+
# Non-arg contexts: lvalue required, no returning locals.
|
|
636
|
+
SPAN_METHOD_TO_SPAN = Coercion(
|
|
637
|
+
name="span_method_to_span",
|
|
638
|
+
from_type=_match_any_side,
|
|
639
|
+
to_type=_is(NominalType),
|
|
640
|
+
requires_lvalue=True,
|
|
641
|
+
forbid_return_local=True,
|
|
642
|
+
)
|
|
643
|
+
|
|
644
|
+
UPCAST_TO_CONST_PTR = Coercion(
|
|
645
|
+
name="upcast_to_const_ptr",
|
|
646
|
+
from_type=_is(NominalType),
|
|
647
|
+
to_type=_is(PtrType),
|
|
648
|
+
requires_lvalue=True,
|
|
649
|
+
forbid_return_local=True,
|
|
650
|
+
produces_non_null_ptr=True,
|
|
651
|
+
codegen=lambda e, _a, _b, _c: f"&{e}",
|
|
652
|
+
)
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
# T -> Any: type-erased storage. View types are converted to their owning
|
|
656
|
+
# equivalent at the storage site so the Any cell owns its contents (the
|
|
657
|
+
# typeid stored in std::any is the owning type, not the view type). All
|
|
658
|
+
# other copyable types are stored as-is. Sema (compatibility.py) gates
|
|
659
|
+
# move-only sources before this coercion is reached.
|
|
660
|
+
def _any_storage_form(
|
|
661
|
+
e: str, actual: TpyType, c: CoercionContext,
|
|
662
|
+
) -> str:
|
|
663
|
+
"""Return the C++ expression to pass to `::tpy::make_any(...)` for
|
|
664
|
+
storing `e` (statically typed `actual`) inside a tpy::Any.
|
|
665
|
+
|
|
666
|
+
The expression must produce a value whose decayed C++ type is the
|
|
667
|
+
intended storage typeid -- argument deduction in `make_any<T>(value)`
|
|
668
|
+
picks T from this expression. Three flavours of conversion happen
|
|
669
|
+
here:
|
|
670
|
+
|
|
671
|
+
- Literal-typed sources (IntLiteralType / FloatLiteralType /
|
|
672
|
+
LiteralType) resolve to their canonical storage type so the typeid
|
|
673
|
+
is stable regardless of which literal value triggered the coercion
|
|
674
|
+
(`x: Any = 42` and `[42]: list[Any]` both store BigInt).
|
|
675
|
+
|
|
676
|
+
- str-like sources are always wrapped in `std::string{...}` because
|
|
677
|
+
string-literal expressions lower to `const char*`. Without this,
|
|
678
|
+
argument deduction would pick `const char*` and the cell's typeid
|
|
679
|
+
would mismatch the canonical `std::string`. The redundant
|
|
680
|
+
std::string copy when the source is already a std::string variable
|
|
681
|
+
is accepted; correctness over micro-efficiency.
|
|
682
|
+
|
|
683
|
+
- Bytes-like view/span sources are converted to the owning
|
|
684
|
+
`std::vector<uint8_t>`; bytes/bytearray at value positions are
|
|
685
|
+
already vectors and pass through.
|
|
686
|
+
|
|
687
|
+
- Container literals reach codegen as raw brace-init expressions
|
|
688
|
+
(`{1, 2, 3}`); make_any's argument deduction can't pick a type
|
|
689
|
+
from a braced-init, so we prefix with the explicit C++ container
|
|
690
|
+
type. For non-literal sources the same prefix is just a copy ctor.
|
|
691
|
+
"""
|
|
692
|
+
if isinstance(actual, IntLiteralType):
|
|
693
|
+
# TPy's `int` annotation is BigInt; storing IntLiteral sources as
|
|
694
|
+
# BigInt makes `cast(int, x)` work for the natural pattern
|
|
695
|
+
# `x: Any = 42; cast(int, x)`.
|
|
696
|
+
return f"::tpy::BigInt({e})"
|
|
697
|
+
if isinstance(actual, FloatLiteralType):
|
|
698
|
+
return f"static_cast<double>({e})"
|
|
699
|
+
if isinstance(actual, LiteralType):
|
|
700
|
+
return _any_storage_form(e, actual.base_type, c)
|
|
701
|
+
if is_str_view_type(actual) or is_str_type(actual) or is_string_type(actual):
|
|
702
|
+
return f"std::string({e})"
|
|
703
|
+
if is_bytes_view_type(actual):
|
|
704
|
+
return f"std::vector<uint8_t>({e}.begin(), {e}.end())"
|
|
705
|
+
if is_bytes_type(actual) or is_bytearray_type(actual):
|
|
706
|
+
if c == CoercionContext.ARG:
|
|
707
|
+
return f"std::vector<uint8_t>({e}.begin(), {e}.end())"
|
|
708
|
+
return e
|
|
709
|
+
if is_list(actual) or is_dict(actual) or is_set(actual):
|
|
710
|
+
cpp = actual.to_cpp()
|
|
711
|
+
return f"{cpp}{e}" if e.startswith("{") else f"{cpp}({e})"
|
|
712
|
+
return e
|
|
713
|
+
|
|
714
|
+
|
|
715
|
+
def wrap_into_any(
|
|
716
|
+
e: str, actual: TpyType,
|
|
717
|
+
ctx: CoercionContext = CoercionContext.INIT,
|
|
718
|
+
) -> str:
|
|
719
|
+
"""Build the C++ expression that wraps `e` (typed `actual`) as a tpy::Any.
|
|
720
|
+
Shared by the INTO_ANY coercion and by container-element codegen sites
|
|
721
|
+
where the element slot type is Any (list[Any], dict[K, Any], ...).
|
|
722
|
+
"""
|
|
723
|
+
return f"::tpy::make_any({_any_storage_form(e, actual, ctx)})"
|
|
724
|
+
|
|
725
|
+
|
|
726
|
+
def _into_any_codegen(
|
|
727
|
+
e: str, actual: TpyType, _expected: TpyType, c: CoercionContext,
|
|
728
|
+
) -> str:
|
|
729
|
+
return wrap_into_any(e, actual, c)
|
|
730
|
+
|
|
731
|
+
|
|
732
|
+
INTO_ANY = Coercion(
|
|
733
|
+
name="into_any",
|
|
734
|
+
from_type=_match_any_side,
|
|
735
|
+
to_type=_is(AnyType),
|
|
736
|
+
codegen=_into_any_codegen,
|
|
737
|
+
)
|
|
738
|
+
|
|
739
|
+
|
|
740
|
+
# Any -> T auto-coerce: runtime checked extraction. Target T must be a
|
|
741
|
+
# concrete type (sema gates Union / Optional / generic-type-param targets
|
|
742
|
+
# before reaching this codegen). When the typeid mismatches at runtime,
|
|
743
|
+
# any_cast_or_panic delivers the documented panic message.
|
|
744
|
+
FROM_ANY = Coercion(
|
|
745
|
+
name="from_any",
|
|
746
|
+
from_type=_is(AnyType),
|
|
747
|
+
to_type=_match_any_side,
|
|
748
|
+
codegen=lambda e, _a, b, _c: f"::tpy::any_cast_or_panic<{b.to_cpp()}>({e})",
|
|
749
|
+
)
|