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/sema/flow_facts.py
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FlowFacts -- immutable snapshot of flow-sensitive analysis state.
|
|
3
|
+
|
|
4
|
+
Captures the flow-sensitive properties that must be saved, restored,
|
|
5
|
+
and merged at branch/loop boundaries: definite assignment, termination,
|
|
6
|
+
rvalue tracking, parameter provenance, safe-to-return locals, pointer
|
|
7
|
+
non-null status, type narrowing, and consumed-variable tracking.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from enum import Enum, auto
|
|
14
|
+
from typing import TYPE_CHECKING
|
|
15
|
+
|
|
16
|
+
from .context import BorrowKind, BORROW_KIND_RANK
|
|
17
|
+
from .value_range import ValueRange
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from ..typesys import TpyType
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class _MergePolicy(Enum):
|
|
24
|
+
INTERSECT = auto()
|
|
25
|
+
UNION = auto()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _merge_sets(
|
|
29
|
+
then_set: frozenset[str],
|
|
30
|
+
else_set: frozenset[str],
|
|
31
|
+
then_term: bool,
|
|
32
|
+
else_term: bool,
|
|
33
|
+
policy: _MergePolicy,
|
|
34
|
+
) -> frozenset[str]:
|
|
35
|
+
"""Merge two frozensets across branch endpoints.
|
|
36
|
+
|
|
37
|
+
When a branch terminates (return/break/raise), it cannot reach the
|
|
38
|
+
merge point, so only the other branch's set matters. When both are
|
|
39
|
+
live, ``policy`` decides: INTERSECT (conservative -- must hold on
|
|
40
|
+
both paths) or UNION (conservative -- may hold on either path).
|
|
41
|
+
"""
|
|
42
|
+
if then_term and else_term:
|
|
43
|
+
return then_set | else_set
|
|
44
|
+
if then_term:
|
|
45
|
+
return else_set
|
|
46
|
+
if else_term:
|
|
47
|
+
return then_set
|
|
48
|
+
if policy is _MergePolicy.INTERSECT:
|
|
49
|
+
return then_set & else_set
|
|
50
|
+
return then_set | else_set
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _merge_narrowed(
|
|
54
|
+
then_narrowed: frozenset[tuple[str, TpyType]],
|
|
55
|
+
else_narrowed: frozenset[tuple[str, TpyType]],
|
|
56
|
+
then_term: bool,
|
|
57
|
+
else_term: bool,
|
|
58
|
+
) -> frozenset[tuple[str, TpyType]]:
|
|
59
|
+
"""Merge narrowed-type mappings, represented as frozensets of (name, type) pairs.
|
|
60
|
+
|
|
61
|
+
When both branches are live, only narrowings that agree on both sides
|
|
62
|
+
survive (key present in both with equal type).
|
|
63
|
+
"""
|
|
64
|
+
if then_term and else_term:
|
|
65
|
+
then_dict = dict(then_narrowed)
|
|
66
|
+
then_dict.update(else_narrowed)
|
|
67
|
+
return frozenset(then_dict.items())
|
|
68
|
+
if then_term:
|
|
69
|
+
return else_narrowed
|
|
70
|
+
if else_term:
|
|
71
|
+
return then_narrowed
|
|
72
|
+
then_dict = dict(then_narrowed)
|
|
73
|
+
else_dict = dict(else_narrowed)
|
|
74
|
+
merged = {k: v for k, v in then_dict.items()
|
|
75
|
+
if k in else_dict and else_dict[k] == v}
|
|
76
|
+
return frozenset(merged.items())
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _merge_value_ranges(
|
|
80
|
+
then_ranges: frozenset[tuple[str, ValueRange]],
|
|
81
|
+
else_ranges: frozenset[tuple[str, ValueRange]],
|
|
82
|
+
then_term: bool,
|
|
83
|
+
else_term: bool,
|
|
84
|
+
) -> frozenset[tuple[str, ValueRange]]:
|
|
85
|
+
"""Merge value range mappings across branch endpoints.
|
|
86
|
+
|
|
87
|
+
When both branches are live, per-variable ranges are merged (widened)
|
|
88
|
+
using ValueRange.merge. Variables tracked on only one branch are dropped
|
|
89
|
+
(conservative -- we can only use a fact if it holds on all paths).
|
|
90
|
+
"""
|
|
91
|
+
if then_term and else_term:
|
|
92
|
+
then_dict = dict(then_ranges)
|
|
93
|
+
then_dict.update(else_ranges)
|
|
94
|
+
return frozenset(then_dict.items())
|
|
95
|
+
if then_term:
|
|
96
|
+
return else_ranges
|
|
97
|
+
if else_term:
|
|
98
|
+
return then_ranges
|
|
99
|
+
then_dict = dict(then_ranges)
|
|
100
|
+
else_dict = dict(else_ranges)
|
|
101
|
+
merged = {}
|
|
102
|
+
for k, v in then_dict.items():
|
|
103
|
+
if k in else_dict:
|
|
104
|
+
merged[k] = ValueRange.merge(v, else_dict[k])
|
|
105
|
+
return frozenset(merged.items())
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _merge_borrow_triples(
|
|
109
|
+
then_borrows: frozenset[tuple[str, str, BorrowKind]],
|
|
110
|
+
else_borrows: frozenset[tuple[str, str, BorrowKind]],
|
|
111
|
+
then_term: bool,
|
|
112
|
+
else_term: bool,
|
|
113
|
+
) -> frozenset[tuple[str, str, BorrowKind]]:
|
|
114
|
+
"""Merge borrow (storage, borrower, kind) triples across branch endpoints.
|
|
115
|
+
|
|
116
|
+
Uses UNION policy: a borrow exists after the merge if it exists in
|
|
117
|
+
either live branch (conservative -- may hold on either path).
|
|
118
|
+
When the same (storage, borrower) has different kinds on the two branches,
|
|
119
|
+
the more dangerous kind wins (element > alias, ptr > alias, iter > alias).
|
|
120
|
+
"""
|
|
121
|
+
if then_term and else_term:
|
|
122
|
+
combined = then_borrows | else_borrows
|
|
123
|
+
elif then_term:
|
|
124
|
+
combined = else_borrows
|
|
125
|
+
elif else_term:
|
|
126
|
+
combined = then_borrows
|
|
127
|
+
else:
|
|
128
|
+
combined = then_borrows | else_borrows
|
|
129
|
+
# Deduplicate (storage, borrower) pairs, keeping the more dangerous kind
|
|
130
|
+
best: dict[tuple[str, str], BorrowKind] = {}
|
|
131
|
+
for storage, borrower, kind in combined:
|
|
132
|
+
key = (storage, borrower)
|
|
133
|
+
prev = best.get(key)
|
|
134
|
+
if prev is None or BORROW_KIND_RANK[kind] > BORROW_KIND_RANK[prev]:
|
|
135
|
+
best[key] = kind
|
|
136
|
+
return frozenset((s, b, k) for (s, b), k in best.items())
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@dataclass(frozen=True, slots=True)
|
|
140
|
+
class FlowFacts:
|
|
141
|
+
"""Immutable snapshot of flow-sensitive analysis state."""
|
|
142
|
+
|
|
143
|
+
definitely_assigned: frozenset[str] = frozenset()
|
|
144
|
+
init_terminated: bool = False
|
|
145
|
+
rvalue_vars: frozenset[str] = frozenset()
|
|
146
|
+
param_provenance_vars: frozenset[str] = frozenset()
|
|
147
|
+
safe_to_return_vars: frozenset[str] = frozenset()
|
|
148
|
+
non_null_ptr_vars: frozenset[str] = frozenset()
|
|
149
|
+
narrowed_types: frozenset[tuple[str, TpyType]] = frozenset()
|
|
150
|
+
consumed_vars: frozenset[str] = frozenset()
|
|
151
|
+
# Borrow map: (storage_name, borrower_name, BorrowKind) triples.
|
|
152
|
+
# "__for_iter" is used as the borrower for implicit for-loop iterator borrows.
|
|
153
|
+
borrows: frozenset[tuple[str, str, BorrowKind]] = frozenset()
|
|
154
|
+
value_ranges: frozenset[tuple[str, ValueRange]] = frozenset()
|
|
155
|
+
|
|
156
|
+
@staticmethod
|
|
157
|
+
def merge(then: FlowFacts, else_: FlowFacts) -> FlowFacts:
|
|
158
|
+
"""Merge flow facts from then/else branches."""
|
|
159
|
+
then_term = then.init_terminated
|
|
160
|
+
else_term = else_.init_terminated
|
|
161
|
+
return FlowFacts(
|
|
162
|
+
definitely_assigned=_merge_sets(
|
|
163
|
+
then.definitely_assigned, else_.definitely_assigned,
|
|
164
|
+
then_term, else_term, _MergePolicy.INTERSECT,
|
|
165
|
+
),
|
|
166
|
+
init_terminated=then_term and else_term,
|
|
167
|
+
rvalue_vars=_merge_sets(
|
|
168
|
+
then.rvalue_vars, else_.rvalue_vars,
|
|
169
|
+
then_term, else_term, _MergePolicy.INTERSECT,
|
|
170
|
+
),
|
|
171
|
+
param_provenance_vars=_merge_sets(
|
|
172
|
+
then.param_provenance_vars, else_.param_provenance_vars,
|
|
173
|
+
then_term, else_term, _MergePolicy.INTERSECT,
|
|
174
|
+
),
|
|
175
|
+
safe_to_return_vars=_merge_sets(
|
|
176
|
+
then.safe_to_return_vars, else_.safe_to_return_vars,
|
|
177
|
+
then_term, else_term, _MergePolicy.INTERSECT,
|
|
178
|
+
),
|
|
179
|
+
non_null_ptr_vars=_merge_sets(
|
|
180
|
+
then.non_null_ptr_vars, else_.non_null_ptr_vars,
|
|
181
|
+
then_term, else_term, _MergePolicy.INTERSECT,
|
|
182
|
+
),
|
|
183
|
+
narrowed_types=_merge_narrowed(
|
|
184
|
+
then.narrowed_types, else_.narrowed_types,
|
|
185
|
+
then_term, else_term,
|
|
186
|
+
),
|
|
187
|
+
consumed_vars=_merge_sets(
|
|
188
|
+
then.consumed_vars, else_.consumed_vars,
|
|
189
|
+
then_term, else_term, _MergePolicy.UNION,
|
|
190
|
+
),
|
|
191
|
+
borrows=_merge_borrow_triples(
|
|
192
|
+
then.borrows, else_.borrows,
|
|
193
|
+
then_term, else_term,
|
|
194
|
+
),
|
|
195
|
+
value_ranges=_merge_value_ranges(
|
|
196
|
+
then.value_ranges, else_.value_ranges,
|
|
197
|
+
then_term, else_term,
|
|
198
|
+
),
|
|
199
|
+
)
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TurboPython Definite-Assignment Tracker
|
|
3
|
+
|
|
4
|
+
Tracks which variables are guaranteed to be initialized on all paths
|
|
5
|
+
reaching the current point. Prevents use-before-assignment errors that
|
|
6
|
+
would be undefined behavior in generated C++.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
from typing import TYPE_CHECKING
|
|
11
|
+
|
|
12
|
+
from .flow_facts import FlowFacts
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from ..typesys import TpyType
|
|
16
|
+
from .context import SemanticContext
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class InitTracker:
|
|
22
|
+
"""Definite-assignment and rvalue-vars flow analysis."""
|
|
23
|
+
|
|
24
|
+
def __init__(self, ctx: SemanticContext):
|
|
25
|
+
self.ctx = ctx
|
|
26
|
+
|
|
27
|
+
def save(self) -> FlowFacts:
|
|
28
|
+
return FlowFacts(
|
|
29
|
+
definitely_assigned=frozenset(self.ctx.func.definitely_assigned),
|
|
30
|
+
init_terminated=self.ctx.func.init_terminated,
|
|
31
|
+
rvalue_vars=frozenset(self.ctx.func.rvalue_vars),
|
|
32
|
+
param_provenance_vars=frozenset(self.ctx.func.param_provenance_vars),
|
|
33
|
+
safe_to_return_vars=frozenset(self.ctx.func.safe_to_return_vars),
|
|
34
|
+
non_null_ptr_vars=frozenset(self.ctx.func.non_null_ptr_vars),
|
|
35
|
+
narrowed_types=frozenset(self.ctx.func.narrowed_types.items()),
|
|
36
|
+
consumed_vars=frozenset(self.ctx.func.consumed_vars),
|
|
37
|
+
borrows=self.ctx.func.borrow_tracker.freeze(),
|
|
38
|
+
value_ranges=frozenset(self.ctx.func.value_ranges.items()),
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
def restore(self, state: FlowFacts) -> None:
|
|
42
|
+
self.ctx.func.definitely_assigned = set(state.definitely_assigned)
|
|
43
|
+
self.ctx.func.init_terminated = state.init_terminated
|
|
44
|
+
self.ctx.func.rvalue_vars = set(state.rvalue_vars)
|
|
45
|
+
self.ctx.func.param_provenance_vars = set(state.param_provenance_vars)
|
|
46
|
+
self.ctx.func.safe_to_return_vars = set(state.safe_to_return_vars)
|
|
47
|
+
self.ctx.func.non_null_ptr_vars = set(state.non_null_ptr_vars)
|
|
48
|
+
# Invariant: pending post-access ptr-narrowing flushes at statement
|
|
49
|
+
# boundary (see `analyze_stmt` try/finally). Any entries surviving a
|
|
50
|
+
# restore would leak into a branch they don't belong to.
|
|
51
|
+
self.ctx.func.pending_non_null_ptr_vars.clear()
|
|
52
|
+
self.ctx.func.narrowed_types = dict(state.narrowed_types)
|
|
53
|
+
self.ctx.func.consumed_vars = set(state.consumed_vars)
|
|
54
|
+
self.ctx.func.borrow_tracker.restore_from_frozen(state.borrows)
|
|
55
|
+
self.ctx.func.value_ranges = dict(state.value_ranges)
|
|
56
|
+
|
|
57
|
+
def mark_assigned(self, name: str) -> None:
|
|
58
|
+
self.ctx.func.definitely_assigned.add(name)
|
|
59
|
+
|
|
60
|
+
def mark_terminated(self) -> None:
|
|
61
|
+
self.ctx.func.init_terminated = True
|
|
62
|
+
|
|
63
|
+
def mark_provenance(self, name: str, is_param_derived: bool) -> None:
|
|
64
|
+
"""Track whether a variable's storage derives from parameters/globals."""
|
|
65
|
+
if is_param_derived:
|
|
66
|
+
self.ctx.func.param_provenance_vars.add(name)
|
|
67
|
+
else:
|
|
68
|
+
self.ctx.func.param_provenance_vars.discard(name)
|
|
69
|
+
|
|
70
|
+
def mark_safe_to_return(self, name: str, is_safe: bool) -> None:
|
|
71
|
+
"""Record that returning ``name`` after this binding is non-dangling.
|
|
72
|
+
|
|
73
|
+
Membership is what is_dangling_return consults for locals, so callers
|
|
74
|
+
must also keep this set a superset of param_provenance_vars (the
|
|
75
|
+
merge invariant relied on by FlowFacts.merge / apply_loop_exit_facts).
|
|
76
|
+
See is_safe_to_return_expr in compatibility.py for the source rule.
|
|
77
|
+
"""
|
|
78
|
+
if is_safe:
|
|
79
|
+
self.ctx.func.safe_to_return_vars.add(name)
|
|
80
|
+
else:
|
|
81
|
+
self.ctx.func.safe_to_return_vars.discard(name)
|
|
82
|
+
|
|
83
|
+
def mark_non_null_ptr(self, name: str, is_non_null: bool) -> None:
|
|
84
|
+
"""Track whether a pointer variable is provably non-null."""
|
|
85
|
+
if is_non_null:
|
|
86
|
+
self.ctx.func.non_null_ptr_vars.add(name)
|
|
87
|
+
else:
|
|
88
|
+
self.ctx.func.non_null_ptr_vars.discard(name)
|
|
89
|
+
|
|
90
|
+
def add_loop_var_provenance(self, name: str) -> None:
|
|
91
|
+
# Both sets must move together: leaving safe_to_return_vars empty
|
|
92
|
+
# while populating param_provenance_vars would let an intersecting
|
|
93
|
+
# merge drop the var from safe_to_return_vars while keeping it in
|
|
94
|
+
# param_provenance_vars, breaking the documented subset invariant.
|
|
95
|
+
self.ctx.func.param_provenance_vars.add(name)
|
|
96
|
+
self.ctx.func.safe_to_return_vars.add(name)
|
|
97
|
+
|
|
98
|
+
def remove_loop_var_provenance(self, name: str) -> None:
|
|
99
|
+
self.ctx.func.param_provenance_vars.discard(name)
|
|
100
|
+
self.ctx.func.safe_to_return_vars.discard(name)
|
|
101
|
+
|
|
102
|
+
def apply_loop_entry_facts(
|
|
103
|
+
self,
|
|
104
|
+
before: FlowFacts,
|
|
105
|
+
condition_type_facts: dict[str, TpyType] | None = None,
|
|
106
|
+
) -> None:
|
|
107
|
+
"""Apply flow facts at loop body entry.
|
|
108
|
+
|
|
109
|
+
Restores the state from just before the loop, so that outer
|
|
110
|
+
narrowing proven by enclosing if-blocks is preserved inside the
|
|
111
|
+
loop body. Any additional narrowing the loop condition itself
|
|
112
|
+
proves (e.g. ``while x is not None``) is layered on top.
|
|
113
|
+
"""
|
|
114
|
+
self.ctx.func.definitely_assigned = set(before.definitely_assigned)
|
|
115
|
+
self.ctx.func.init_terminated = False
|
|
116
|
+
self.ctx.func.rvalue_vars = set(before.rvalue_vars)
|
|
117
|
+
self.ctx.func.param_provenance_vars = set(before.param_provenance_vars)
|
|
118
|
+
self.ctx.func.safe_to_return_vars = set(before.safe_to_return_vars)
|
|
119
|
+
self.ctx.func.non_null_ptr_vars = set(before.non_null_ptr_vars)
|
|
120
|
+
self.ctx.func.narrowed_types = dict(before.narrowed_types)
|
|
121
|
+
self.ctx.func.consumed_vars = set(before.consumed_vars)
|
|
122
|
+
self.ctx.func.borrow_tracker.restore_from_frozen(before.borrows)
|
|
123
|
+
self.ctx.func.value_ranges = dict(before.value_ranges)
|
|
124
|
+
if condition_type_facts is not None:
|
|
125
|
+
self.ctx.func.narrowed_types.update(condition_type_facts)
|
|
126
|
+
|
|
127
|
+
def merge_branches(self, then_state: FlowFacts, else_state: FlowFacts) -> None:
|
|
128
|
+
self.restore(FlowFacts.merge(then_state, else_state))
|
|
129
|
+
|
|
130
|
+
def apply_loop_exit_facts(self, before: FlowFacts) -> None:
|
|
131
|
+
"""Apply post-loop state for a may-execute-zero-times loop.
|
|
132
|
+
|
|
133
|
+
Call with live post-body state still in ``ctx.func.*``. Monotone
|
|
134
|
+
kill-facts (pointer non-null, parameter provenance, safe-to-return,
|
|
135
|
+
type narrowing) survive iff they held both before the loop AND at
|
|
136
|
+
body exit, so a reassignment that cleared a fact is not undone by
|
|
137
|
+
``restore(before)``.
|
|
138
|
+
|
|
139
|
+
Single-pass conservative approximation -- proper fixpoint belongs
|
|
140
|
+
with the THIR/MIR migration (see ``docs/IR_DESIGN.md``).
|
|
141
|
+
"""
|
|
142
|
+
body_end_nn_ptr = frozenset(self.ctx.func.non_null_ptr_vars)
|
|
143
|
+
body_end_param_prov = frozenset(self.ctx.func.param_provenance_vars)
|
|
144
|
+
body_end_safe_return = frozenset(self.ctx.func.safe_to_return_vars)
|
|
145
|
+
body_end_narrowed = frozenset(self.ctx.func.narrowed_types.items())
|
|
146
|
+
self.restore(before)
|
|
147
|
+
self.ctx.func.non_null_ptr_vars &= body_end_nn_ptr
|
|
148
|
+
self.ctx.func.param_provenance_vars &= body_end_param_prov
|
|
149
|
+
self.ctx.func.safe_to_return_vars &= body_end_safe_return
|
|
150
|
+
self.ctx.func.narrowed_types = dict(body_end_narrowed & before.narrowed_types)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TurboPython Iterable Type Helpers
|
|
3
|
+
|
|
4
|
+
General-purpose iterable-type queries (is_type_iterable, get_iterable_element_type).
|
|
5
|
+
List literal deduction logic has moved to local_deduction.LocalTypeDeduction.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
from typing import TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
from ..typesys import (
|
|
12
|
+
TpyType, GenExprType,
|
|
13
|
+
is_protocol_type,
|
|
14
|
+
)
|
|
15
|
+
from ..diagnostics import SemanticError
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from ..parse import SourceLocation
|
|
19
|
+
from .context import SemanticContext
|
|
20
|
+
|
|
21
|
+
from tpyc import modules as builtin_modules
|
|
22
|
+
from ..type_def_registry import is_iterator_adapter
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class IterableHelper:
|
|
26
|
+
"""General-purpose iterable type queries."""
|
|
27
|
+
|
|
28
|
+
def __init__(self, ctx: SemanticContext):
|
|
29
|
+
self.ctx = ctx
|
|
30
|
+
|
|
31
|
+
def is_type_iterable(self, typ: TpyType) -> bool:
|
|
32
|
+
"""Check if a type is iterable.
|
|
33
|
+
|
|
34
|
+
A type is iterable if it:
|
|
35
|
+
- Is a NativeIterable[T], Iterator[T], Iterable[T], or
|
|
36
|
+
Spannable[T] protocol type (used as parameter type)
|
|
37
|
+
- Is a compiler-internal iterator adapter (CopyIter[T], OwnIter[T],
|
|
38
|
+
generator-expression type) or SpanIter[T] (stub-declared but its
|
|
39
|
+
__iter__(self) -> Self currently bypasses the unified lookup --
|
|
40
|
+
the parser doesn't resolve Self to SpanIter, so the adapter
|
|
41
|
+
allowlist covers it; low-priority follow-up)
|
|
42
|
+
- Has __next__() (Iterator conformance)
|
|
43
|
+
- Has __iter__() returning an iterator type
|
|
44
|
+
"""
|
|
45
|
+
if is_protocol_type(typ) and typ.qualified_name() in builtin_modules.ITERABLE_PROTOCOL_QNAMES:
|
|
46
|
+
return True
|
|
47
|
+
if is_iterator_adapter(typ) or isinstance(typ, GenExprType):
|
|
48
|
+
return True
|
|
49
|
+
if builtin_modules.get_iter_element_type(typ, registry=self.ctx.registry) is not None:
|
|
50
|
+
return True
|
|
51
|
+
if builtin_modules.get_error_return_next_element_type(typ, registry=self.ctx.registry) is not None:
|
|
52
|
+
return True
|
|
53
|
+
return False
|
|
54
|
+
|
|
55
|
+
def get_iterable_element_type_or_none(self, iterable_type: TpyType) -> TpyType | None:
|
|
56
|
+
"""Get the element type of an iterable, or None if not iterable."""
|
|
57
|
+
return builtin_modules.get_iterable_element_type(iterable_type, registry=self.ctx.registry)
|
|
58
|
+
|
|
59
|
+
def get_iterable_element_type(
|
|
60
|
+
self, iterable_type: TpyType, loc: SourceLocation | None = None,
|
|
61
|
+
) -> TpyType:
|
|
62
|
+
"""Get the element type of an iterable for for-each loops.
|
|
63
|
+
|
|
64
|
+
Raises SemanticError if type is not iterable.
|
|
65
|
+
"""
|
|
66
|
+
elem_type = self.get_iterable_element_type_or_none(iterable_type)
|
|
67
|
+
if elem_type is not None:
|
|
68
|
+
return elem_type
|
|
69
|
+
raise SemanticError(f"Cannot iterate over type {iterable_type}", loc)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Shared helpers for extracting literal values from AST expression nodes.
|
|
2
|
+
|
|
3
|
+
Handles bare `str` / `int` / `bool` literals plus the unary-minus form
|
|
4
|
+
`-<int_literal>` (CPython encodes `-1` as `TpyUnaryOp("-", TpyIntLiteral(1))`),
|
|
5
|
+
and peels a single `TpyCoerce` wrapper so callers don't have to.
|
|
6
|
+
"""
|
|
7
|
+
from ..parse import (
|
|
8
|
+
TpyExpr, TpyStrLiteral, TpyIntLiteral, TpyBoolLiteral, TpyUnaryOp, TpyCoerce,
|
|
9
|
+
)
|
|
10
|
+
from ..typesys import LiteralValue, LiteralTag
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def literal_value_from_expr(expr: TpyExpr | None) -> LiteralValue | None:
|
|
14
|
+
"""Return a tagged `LiteralValue` for a literal AST node, else None."""
|
|
15
|
+
if expr is None:
|
|
16
|
+
return None
|
|
17
|
+
inner = expr.expr if isinstance(expr, TpyCoerce) else expr
|
|
18
|
+
if isinstance(inner, TpyStrLiteral):
|
|
19
|
+
return LiteralValue(LiteralTag.STR, inner.value)
|
|
20
|
+
if isinstance(inner, TpyBoolLiteral):
|
|
21
|
+
return LiteralValue(LiteralTag.BOOL, inner.value)
|
|
22
|
+
if isinstance(inner, TpyIntLiteral):
|
|
23
|
+
return LiteralValue(LiteralTag.INT, inner.value)
|
|
24
|
+
if (isinstance(inner, TpyUnaryOp) and inner.op == "-"
|
|
25
|
+
and isinstance(inner.operand, TpyIntLiteral)):
|
|
26
|
+
return LiteralValue(LiteralTag.INT, -inner.operand.value)
|
|
27
|
+
return None
|