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,76 @@
|
|
|
1
|
+
"""String dispatch optimization for match/case and enum lookup.
|
|
2
|
+
|
|
3
|
+
Analyzes a set of string literals to find the best single discriminator
|
|
4
|
+
(string length or character at a fixed position) that partitions the
|
|
5
|
+
strings into the smallest possible buckets for switch-based dispatch.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
# Minimum number of unguarded string literal cases to trigger switch dispatch
|
|
11
|
+
STRING_SWITCH_THRESHOLD = 5
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def find_best_discriminator(
|
|
15
|
+
strings: list[str],
|
|
16
|
+
) -> tuple[str, int | None, dict[int, list[str]]]:
|
|
17
|
+
"""Find the best discriminator for switch-based string dispatch.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
strings: List of distinct string literals to dispatch on.
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
(kind, param, buckets) where:
|
|
24
|
+
- kind: "length" or "char_at"
|
|
25
|
+
- param: None for length, character position index for char_at
|
|
26
|
+
- buckets: maps discriminator value -> list of strings
|
|
27
|
+
For "length": value is string length.
|
|
28
|
+
For "char_at": value is ord(char) at the given position.
|
|
29
|
+
"""
|
|
30
|
+
if not strings:
|
|
31
|
+
return ("length", None, {})
|
|
32
|
+
|
|
33
|
+
# Candidate 1: string length
|
|
34
|
+
best_kind = "length"
|
|
35
|
+
best_param: int | None = None
|
|
36
|
+
best_buckets = _group_by_length(strings)
|
|
37
|
+
best_max = _max_bucket(best_buckets)
|
|
38
|
+
|
|
39
|
+
if best_max <= 1:
|
|
40
|
+
return (best_kind, best_param, best_buckets)
|
|
41
|
+
|
|
42
|
+
# Candidate 2: character at position i (only positions reachable by all strings)
|
|
43
|
+
min_len = min(len(s) for s in strings)
|
|
44
|
+
for i in range(min_len):
|
|
45
|
+
buckets = _group_by_char_at(strings, i)
|
|
46
|
+
max_b = _max_bucket(buckets)
|
|
47
|
+
if max_b < best_max:
|
|
48
|
+
best_kind = "char_at"
|
|
49
|
+
best_param = i
|
|
50
|
+
best_buckets = buckets
|
|
51
|
+
best_max = max_b
|
|
52
|
+
if best_max <= 1:
|
|
53
|
+
break
|
|
54
|
+
|
|
55
|
+
return (best_kind, best_param, best_buckets)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _group_by_length(strings: list[str]) -> dict[int, list[str]]:
|
|
59
|
+
buckets: dict[int, list[str]] = {}
|
|
60
|
+
for s in strings:
|
|
61
|
+
buckets.setdefault(len(s), []).append(s)
|
|
62
|
+
return buckets
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _group_by_char_at(strings: list[str], pos: int) -> dict[int, list[str]]:
|
|
66
|
+
buckets: dict[int, list[str]] = {}
|
|
67
|
+
for s in strings:
|
|
68
|
+
key = ord(s[pos])
|
|
69
|
+
buckets.setdefault(key, []).append(s)
|
|
70
|
+
return buckets
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _max_bucket(buckets: dict[int, list[str]]) -> int:
|
|
74
|
+
if not buckets:
|
|
75
|
+
return 0
|
|
76
|
+
return max(len(v) for v in buckets.values())
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Tests for codegen C++ context utilities."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from .context import expand_cpp_template, CodeGenError
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestExpandCppTemplate:
|
|
9
|
+
def test_self_only(self):
|
|
10
|
+
assert expand_cpp_template("{self}.size()", "v") == "v.size()"
|
|
11
|
+
|
|
12
|
+
def test_self_and_positional(self):
|
|
13
|
+
result = expand_cpp_template("{self}.push_back({0})", "vec", "42")
|
|
14
|
+
assert result == "vec.push_back(42)"
|
|
15
|
+
|
|
16
|
+
def test_multiple_positional(self):
|
|
17
|
+
result = expand_cpp_template("{self}[{0}] = {1}", "arr", "i", "val")
|
|
18
|
+
assert result == "arr[i] = val"
|
|
19
|
+
|
|
20
|
+
def test_no_placeholders(self):
|
|
21
|
+
assert expand_cpp_template("std::sort()", "x") == "std::sort()"
|
|
22
|
+
|
|
23
|
+
def test_repeated_placeholder(self):
|
|
24
|
+
result = expand_cpp_template("{self} + {self}", "a")
|
|
25
|
+
assert result == "a + a"
|
|
26
|
+
|
|
27
|
+
def test_unreplaced_self_raises(self):
|
|
28
|
+
with pytest.raises(CodeGenError, match=r"\{self\}"):
|
|
29
|
+
expand_cpp_template("{self}.set({0})", "obj")
|
|
30
|
+
|
|
31
|
+
def test_unreplaced_positional_raises(self):
|
|
32
|
+
with pytest.raises(CodeGenError, match=r"\{1\}"):
|
|
33
|
+
expand_cpp_template("{self}.f({0}, {1})", "obj", "a")
|
|
34
|
+
|
|
35
|
+
def test_extra_args_ok(self):
|
|
36
|
+
result = expand_cpp_template("{self}.f({0})", "obj", "a", "unused")
|
|
37
|
+
assert result == "obj.f(a)"
|
|
38
|
+
|
|
39
|
+
def test_cpp_braces_in_substituted_value(self):
|
|
40
|
+
"""C++ initializer braces in substituted values must not trigger false positives."""
|
|
41
|
+
result = expand_cpp_template(
|
|
42
|
+
"::tpy::list_concat({self}, {0})",
|
|
43
|
+
"v",
|
|
44
|
+
"std::vector<int>{30}",
|
|
45
|
+
)
|
|
46
|
+
assert result == "::tpy::list_concat(v, std::vector<int>{30})"
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""Unit tests for the centralized const decision helper."""
|
|
2
|
+
|
|
3
|
+
from ..typesys import (
|
|
4
|
+
INT32, BOOL, STR, BIGINT,
|
|
5
|
+
NominalType, OptionalType, TupleType, OwnType, ReadonlyType, RefType,
|
|
6
|
+
TypeParamRef, TypeParamKind,
|
|
7
|
+
)
|
|
8
|
+
from .param_const import decide_param_const, ParamConstDecision
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
T = NominalType("T")
|
|
12
|
+
TUPLE_T_T = TupleType((T, T))
|
|
13
|
+
TUPLE_OPT_T = TupleType((OptionalType(T), OptionalType(T)))
|
|
14
|
+
OPT_T = OptionalType(T)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _decide(ptype, **kwargs):
|
|
18
|
+
"""decide_param_const helper that defaults common args."""
|
|
19
|
+
kwargs.setdefault("index", 0)
|
|
20
|
+
kwargs.setdefault("pname", "p")
|
|
21
|
+
kwargs.setdefault("mutated_params", frozenset())
|
|
22
|
+
return decide_param_const(ptype, **kwargs)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class TestSingleRecord:
|
|
26
|
+
def test_unmutated_borrow_is_const(self):
|
|
27
|
+
d = _decide(T)
|
|
28
|
+
assert d == ParamConstDecision(True, True)
|
|
29
|
+
|
|
30
|
+
def test_mutated_borrow_is_not_const(self):
|
|
31
|
+
d = _decide(T, mutated_params=frozenset({0}))
|
|
32
|
+
assert d == ParamConstDecision(False, False)
|
|
33
|
+
|
|
34
|
+
def test_unanalyzed_is_not_const(self):
|
|
35
|
+
d = _decide(T, mutated_params=None)
|
|
36
|
+
assert d == ParamConstDecision(False, False)
|
|
37
|
+
|
|
38
|
+
def test_addr_escape_is_not_const(self):
|
|
39
|
+
d = _decide(T, addr_escapes_params=frozenset({0}))
|
|
40
|
+
assert d == ParamConstDecision(False, False)
|
|
41
|
+
|
|
42
|
+
def test_explicit_readonly_is_const(self):
|
|
43
|
+
d = _decide(ReadonlyType(T), mutated_params=None)
|
|
44
|
+
assert d == ParamConstDecision(True, True)
|
|
45
|
+
|
|
46
|
+
def test_const_params_forces_const(self):
|
|
47
|
+
d = _decide(T, mutated_params=None, const_params=True)
|
|
48
|
+
assert d == ParamConstDecision(True, True)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class TestSingleOptional:
|
|
52
|
+
def test_unmutated_pointer_optional_is_const(self):
|
|
53
|
+
d = _decide(OPT_T)
|
|
54
|
+
assert d == ParamConstDecision(True, True)
|
|
55
|
+
|
|
56
|
+
def test_mutated_pointer_optional_is_not_const(self):
|
|
57
|
+
d = _decide(OPT_T, mutated_params=frozenset({0}))
|
|
58
|
+
assert d == ParamConstDecision(False, False)
|
|
59
|
+
|
|
60
|
+
def test_value_optional_is_not_const(self):
|
|
61
|
+
# Optional[int] uses std::optional<int>, not pointer repr.
|
|
62
|
+
opt_int = OptionalType(INT32)
|
|
63
|
+
d = _decide(opt_int)
|
|
64
|
+
assert d == _NOT_CONST
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class TestTupleParam:
|
|
68
|
+
def test_unmutated_tuple_of_records_is_deep_const(self):
|
|
69
|
+
d = _decide(TUPLE_T_T)
|
|
70
|
+
assert d == ParamConstDecision(True, True)
|
|
71
|
+
|
|
72
|
+
def test_unmutated_tuple_of_optional_records_is_deep_const(self):
|
|
73
|
+
d = _decide(TUPLE_OPT_T)
|
|
74
|
+
assert d == ParamConstDecision(True, True)
|
|
75
|
+
|
|
76
|
+
def test_mutated_tuple_is_not_const(self):
|
|
77
|
+
d = _decide(TUPLE_T_T, mutated_params=frozenset({0}))
|
|
78
|
+
assert d == ParamConstDecision(False, False)
|
|
79
|
+
|
|
80
|
+
def test_value_only_tuple_is_not_const(self):
|
|
81
|
+
# tuple[int, int] -- no borrowed surface.
|
|
82
|
+
d = _decide(TupleType((INT32, BOOL)))
|
|
83
|
+
assert d == _NOT_CONST
|
|
84
|
+
|
|
85
|
+
def test_generic_slot_tuple_is_not_inferred(self):
|
|
86
|
+
# tuple[T, T] where T is unbounded -- mutation surface is unknowable
|
|
87
|
+
# at the template level. Inference must default to not-const.
|
|
88
|
+
T_param = TypeParamRef(name="T", kind=TypeParamKind.TYPE)
|
|
89
|
+
d = _decide(TupleType((T_param, T_param)))
|
|
90
|
+
assert d == _NOT_CONST
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class TestTypeParamTopLevel:
|
|
94
|
+
def test_top_level_typeparam_is_not_inferred(self):
|
|
95
|
+
# def f[T](x: T): ... -- spelling decided at instantiation, not now.
|
|
96
|
+
T_param = TypeParamRef(name="T", kind=TypeParamKind.TYPE)
|
|
97
|
+
d = _decide(T_param)
|
|
98
|
+
assert d == _NOT_CONST
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class TestReassignedParams:
|
|
102
|
+
def test_reassigned_str_is_not_const(self):
|
|
103
|
+
# str needs copy-for-reassign.
|
|
104
|
+
d = _decide(STR, reassigned_params={"p"})
|
|
105
|
+
assert d == _NOT_CONST
|
|
106
|
+
|
|
107
|
+
def test_reassigned_record_can_still_be_const(self):
|
|
108
|
+
# Records don't need copy-for-reassign; can rebind a const ref.
|
|
109
|
+
d = _decide(T, reassigned_params={"p"})
|
|
110
|
+
assert d.signature_const
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
_NOT_CONST = ParamConstDecision(False, False)
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"""Unit tests for the resumable-frame CFG builder.
|
|
2
|
+
|
|
3
|
+
Phase A of the generator -> resumable-frame migration makes the CFG
|
|
4
|
+
builder suspension-generic: a `yield` statement is now a suspension
|
|
5
|
+
point alongside `await`, the lazy-decomposition predicate
|
|
6
|
+
(`_stmt_has_any_suspension`) treats both uniformly, and a top-level
|
|
7
|
+
`yield` lowers to a `Yield` terminator carrying a `YieldPayload`. These
|
|
8
|
+
tests exercise that wiring at the CFG level, before any generator emit
|
|
9
|
+
exists (the builder runs on raw parsed `TpyStmt` bodies, no sema/codegen
|
|
10
|
+
needed).
|
|
11
|
+
"""
|
|
12
|
+
import pytest
|
|
13
|
+
|
|
14
|
+
from ..parse import Parser
|
|
15
|
+
from .resumable_cfg import (
|
|
16
|
+
CFGBuilder, YieldPayload, AwaitPayload, MatchDispatch,
|
|
17
|
+
_stmt_has_any_suspension,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _gen_body(src: str):
|
|
22
|
+
"""Parse `src` and return the body (list of TpyStmt) of its first
|
|
23
|
+
function."""
|
|
24
|
+
module = Parser().parse(src, module_name="t")
|
|
25
|
+
assert module.functions, "expected at least one function"
|
|
26
|
+
return module.functions[0].body
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _build(src: str):
|
|
30
|
+
return CFGBuilder().build(_gen_body(src))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class TestYieldDispatch:
|
|
34
|
+
def test_top_level_yields_produce_yield_payloads(self):
|
|
35
|
+
cfg = _build(
|
|
36
|
+
"from typing import Iterator\n"
|
|
37
|
+
"from tpy import Int32\n"
|
|
38
|
+
"def g() -> Iterator[Int32]:\n"
|
|
39
|
+
" yield 1\n"
|
|
40
|
+
" yield 2\n"
|
|
41
|
+
)
|
|
42
|
+
assert len(cfg.yield_sites) == 2
|
|
43
|
+
for y in cfg.yield_sites:
|
|
44
|
+
assert isinstance(y.payload, YieldPayload)
|
|
45
|
+
assert not isinstance(y.payload, AwaitPayload)
|
|
46
|
+
# A non-bare yield always carries its value expression.
|
|
47
|
+
assert y.payload.value_expr is not None
|
|
48
|
+
# Suspension indices are assigned in source order.
|
|
49
|
+
assert [y.suspension_index for y in cfg.yield_sites] == [0, 1]
|
|
50
|
+
|
|
51
|
+
def test_yield_in_while_decomposes_loop(self):
|
|
52
|
+
# A yield inside a while body must force the loop into a CFG
|
|
53
|
+
# region (multiple BBs), driven by the generic suspension
|
|
54
|
+
# predicate -- not left as a single leaf statement.
|
|
55
|
+
cfg = _build(
|
|
56
|
+
"from typing import Iterator\n"
|
|
57
|
+
"from tpy import Int32\n"
|
|
58
|
+
"def g(n: Int32) -> Iterator[Int32]:\n"
|
|
59
|
+
" i = 0\n"
|
|
60
|
+
" while i < n:\n"
|
|
61
|
+
" yield i\n"
|
|
62
|
+
" i += 1\n"
|
|
63
|
+
)
|
|
64
|
+
assert len(cfg.yield_sites) == 1
|
|
65
|
+
assert isinstance(cfg.yield_sites[0].payload, YieldPayload)
|
|
66
|
+
# Loop decomposition produces several BBs (check/body/exit + ...),
|
|
67
|
+
# not the single block a non-decomposed leaf body would yield.
|
|
68
|
+
assert len(cfg.blocks) > 1
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class TestSuspensionPredicate:
|
|
72
|
+
def test_detects_nested_yield(self):
|
|
73
|
+
body = _gen_body(
|
|
74
|
+
"from typing import Iterator\n"
|
|
75
|
+
"from tpy import Int32\n"
|
|
76
|
+
"def g(n: Int32) -> Iterator[Int32]:\n"
|
|
77
|
+
" while n > 0:\n"
|
|
78
|
+
" yield n\n"
|
|
79
|
+
)
|
|
80
|
+
# body[-1] is the while-loop; it nests a yield.
|
|
81
|
+
assert _stmt_has_any_suspension(body[-1]) is True
|
|
82
|
+
|
|
83
|
+
def test_plain_loop_without_yield_is_not_a_suspension(self):
|
|
84
|
+
body = _gen_body(
|
|
85
|
+
"from tpy import Int32\n"
|
|
86
|
+
"def f(n: Int32) -> Int32:\n"
|
|
87
|
+
" total = 0\n"
|
|
88
|
+
" while n > 0:\n"
|
|
89
|
+
" total += n\n"
|
|
90
|
+
" n -= 1\n"
|
|
91
|
+
" return total\n"
|
|
92
|
+
)
|
|
93
|
+
# The while loop has no suspension; predicate must say so.
|
|
94
|
+
whiles = [s for s in body if type(s).__name__ == "TpyWhile"]
|
|
95
|
+
assert whiles and _stmt_has_any_suspension(whiles[0]) is False
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class TestLoopElseSupported:
|
|
99
|
+
# Phase D3: the CFG now models break-vs-normal-exit via distinct edges
|
|
100
|
+
# (else runs on the normal-exit edge; `break` targets a separate
|
|
101
|
+
# after-BB that skips it), so a suspension inside a loop `else` is
|
|
102
|
+
# supported instead of rejected. These build the CFG and assert both
|
|
103
|
+
# the body and else yields are recorded.
|
|
104
|
+
def test_yield_in_while_else_builds(self):
|
|
105
|
+
cfg = _build(
|
|
106
|
+
"from typing import Iterator\n"
|
|
107
|
+
"from tpy import Int32\n"
|
|
108
|
+
"def g(n: Int32) -> Iterator[Int32]:\n"
|
|
109
|
+
" while n > 0:\n"
|
|
110
|
+
" yield n\n"
|
|
111
|
+
" n -= 1\n"
|
|
112
|
+
" else:\n"
|
|
113
|
+
" yield -1\n"
|
|
114
|
+
)
|
|
115
|
+
# one yield in the body, one in the else clause.
|
|
116
|
+
assert len(cfg.yield_sites) == 2
|
|
117
|
+
|
|
118
|
+
def test_yield_in_for_else_builds(self):
|
|
119
|
+
# for-loops need a registered uid (normally from the gen_async
|
|
120
|
+
# pre-scan); supply one so the builder reaches the else handling.
|
|
121
|
+
body = _gen_body(
|
|
122
|
+
"from typing import Iterator\n"
|
|
123
|
+
"from tpy import Int32\n"
|
|
124
|
+
"def g(xs: list[Int32]) -> Iterator[Int32]:\n"
|
|
125
|
+
" for x in xs:\n"
|
|
126
|
+
" yield x\n"
|
|
127
|
+
" else:\n"
|
|
128
|
+
" yield -1\n"
|
|
129
|
+
)
|
|
130
|
+
for_stmt = body[0]
|
|
131
|
+
cfg = CFGBuilder(for_uid_map={id(for_stmt): 0}).build(body)
|
|
132
|
+
assert len(cfg.yield_sites) == 2
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class TestMatchDecomposition:
|
|
136
|
+
# H1: a `match` carrying a suspension is decomposed by the builder into
|
|
137
|
+
# a single `MatchDispatch` terminator (the suspension-free, type-aware
|
|
138
|
+
# dispatch is reused at emit) plus one BB per arm body, so the nested
|
|
139
|
+
# yields are real CFG yield sites rather than silently-dropped leaves.
|
|
140
|
+
def test_yield_in_match_decomposes(self):
|
|
141
|
+
cfg = _build(
|
|
142
|
+
"from typing import Iterator\n"
|
|
143
|
+
"from tpy import Int32\n"
|
|
144
|
+
"def g() -> Iterator[Int32]:\n"
|
|
145
|
+
" yield 1\n"
|
|
146
|
+
" sel = 2\n"
|
|
147
|
+
" match sel:\n"
|
|
148
|
+
" case 2:\n"
|
|
149
|
+
" yield 99\n"
|
|
150
|
+
" case _:\n"
|
|
151
|
+
" yield 0\n"
|
|
152
|
+
" yield 3\n"
|
|
153
|
+
)
|
|
154
|
+
# yield 1 / yield 99 / yield 0 / yield 3 are all real suspensions.
|
|
155
|
+
assert len(cfg.yield_sites) == 4
|
|
156
|
+
dispatches = [bb.terminator for bb in cfg.blocks.values()
|
|
157
|
+
if isinstance(bb.terminator, MatchDispatch)]
|
|
158
|
+
assert len(dispatches) == 1
|
|
159
|
+
# One arm BB per case; a reachable join (the trailing `yield 3`).
|
|
160
|
+
assert len(dispatches[0].arm_bbs) == 2
|
|
161
|
+
assert dispatches[0].join_bb is not None
|
|
162
|
+
|
|
163
|
+
def test_match_without_suspension_is_plain_leaf(self):
|
|
164
|
+
# A `match` with no `yield` inside is ordinary straight-line code
|
|
165
|
+
# between suspensions -- the builder appends it as a leaf and the
|
|
166
|
+
# CFG builds cleanly.
|
|
167
|
+
cfg = _build(
|
|
168
|
+
"from typing import Iterator\n"
|
|
169
|
+
"from tpy import Int32\n"
|
|
170
|
+
"def g(sel: Int32) -> Iterator[Int32]:\n"
|
|
171
|
+
" yield 1\n"
|
|
172
|
+
" match sel:\n"
|
|
173
|
+
" case 2:\n"
|
|
174
|
+
" print(99)\n"
|
|
175
|
+
" case _:\n"
|
|
176
|
+
" print(0)\n"
|
|
177
|
+
" yield 3\n"
|
|
178
|
+
)
|
|
179
|
+
assert len(cfg.yield_sites) == 2
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Shared type-resolution helpers for codegen."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from ..typesys import PendingViewType, TpyType
|
|
6
|
+
from ..sema.context import PENDING_CONTAINER_TYPES
|
|
7
|
+
from ..sema import SemanticAnalyzer
|
|
8
|
+
from ..parse import TpyVarDecl
|
|
9
|
+
from .types import TypeResolver
|
|
10
|
+
|
|
11
|
+
# Types that indicate an unresolved intermediate sema state.
|
|
12
|
+
_PENDING_TYPES = (*PENDING_CONTAINER_TYPES, PendingViewType)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def resolve_stmt_binding_type(
|
|
16
|
+
stmt: TpyVarDecl,
|
|
17
|
+
analyzer: SemanticAnalyzer,
|
|
18
|
+
include_global_binding: bool = True,
|
|
19
|
+
) -> TpyType | None:
|
|
20
|
+
"""Resolve variable type via var_types -> global binding.
|
|
21
|
+
|
|
22
|
+
Keeps lookup logic consistent across codegen paths and skips unresolved
|
|
23
|
+
pending types from intermediate sema state.
|
|
24
|
+
"""
|
|
25
|
+
var_type = stmt.type
|
|
26
|
+
if var_type is not None or stmt.init is None:
|
|
27
|
+
return var_type
|
|
28
|
+
|
|
29
|
+
var_type = analyzer.var_types.get(id(stmt))
|
|
30
|
+
if var_type is None or isinstance(var_type, _PENDING_TYPES):
|
|
31
|
+
if include_global_binding:
|
|
32
|
+
binding = analyzer.global_ns.lookup_local(stmt.name)
|
|
33
|
+
if binding and binding.type is not None:
|
|
34
|
+
var_type = binding.type
|
|
35
|
+
return var_type
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def resolve_stmt_type_cascade(
|
|
39
|
+
stmt: TpyVarDecl,
|
|
40
|
+
analyzer: SemanticAnalyzer,
|
|
41
|
+
types: TypeResolver,
|
|
42
|
+
include_global_binding: bool = True,
|
|
43
|
+
) -> TpyType | None:
|
|
44
|
+
"""Resolve variable type via var_types -> global binding -> expr type."""
|
|
45
|
+
var_type = resolve_stmt_binding_type(
|
|
46
|
+
stmt,
|
|
47
|
+
analyzer,
|
|
48
|
+
include_global_binding=include_global_binding,
|
|
49
|
+
)
|
|
50
|
+
if var_type is None or isinstance(var_type, _PENDING_TYPES):
|
|
51
|
+
assert stmt.init is not None
|
|
52
|
+
var_type = types.get_resolved_type(stmt.init)
|
|
53
|
+
return var_type
|