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/test_compiler.py
ADDED
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
"""Tests for compiler and build layout."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from . import get_lib_dir, get_runtime_dir
|
|
8
|
+
from .compiler import Compiler, BuildLayout
|
|
9
|
+
from .compilation_context import activate_compiler
|
|
10
|
+
from .diagnostics import SemanticError
|
|
11
|
+
from .typesys import (
|
|
12
|
+
INT32, INT64, BIGINT, BOOL, FLOAT, STR, STRVIEW, CHAR, VOID,
|
|
13
|
+
PtrType, make_span, make_list, make_dict, make_array, OptionalType,
|
|
14
|
+
TupleType, UnionType, OwnType, ReadonlyType, NominalType,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
# Stdlib path needed for from_source when code uses primitive type methods
|
|
18
|
+
_STDLIB_DIRS = [get_lib_dir() / "tpy"]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class TestCompilerFromSource:
|
|
22
|
+
def test_simple_program(self):
|
|
23
|
+
source = 'print("hello")'
|
|
24
|
+
compiler = Compiler.from_source(source)
|
|
25
|
+
modules = compiler.compile()
|
|
26
|
+
assert len(modules) == 1
|
|
27
|
+
assert modules[0].name == "main"
|
|
28
|
+
assert modules[0].is_entry_point
|
|
29
|
+
|
|
30
|
+
def test_custom_module_name(self):
|
|
31
|
+
source = 'x: int = 1\nprint(x)'
|
|
32
|
+
compiler = Compiler.from_source(source, module_name="test_mod")
|
|
33
|
+
modules = compiler.compile()
|
|
34
|
+
assert modules[0].name == "test_mod"
|
|
35
|
+
|
|
36
|
+
def test_matches_file_compilation(self, tmp_path):
|
|
37
|
+
"""Verify that from_source and file-based compilation produce the same AST structure."""
|
|
38
|
+
source = 'def add(a: int, b: int) -> int:\n return a + b\nprint(add(1, 2))'
|
|
39
|
+
src_file = tmp_path / "check.py"
|
|
40
|
+
src_file.write_text(source)
|
|
41
|
+
|
|
42
|
+
file_compiler = Compiler(src_file, lib_dirs=_STDLIB_DIRS)
|
|
43
|
+
file_modules = file_compiler.compile()
|
|
44
|
+
|
|
45
|
+
source_compiler = Compiler.from_source(source, lib_dirs=_STDLIB_DIRS)
|
|
46
|
+
source_modules = source_compiler.compile()
|
|
47
|
+
|
|
48
|
+
assert len(file_modules) == len(source_modules)
|
|
49
|
+
file_ast = file_modules[0].ast
|
|
50
|
+
source_ast = source_modules[0].ast
|
|
51
|
+
assert len(file_ast.functions) == len(source_ast.functions)
|
|
52
|
+
assert len(file_ast.top_level_stmts) == len(source_ast.top_level_stmts)
|
|
53
|
+
|
|
54
|
+
@pytest.mark.parametrize(
|
|
55
|
+
("default_int", "expected"),
|
|
56
|
+
[
|
|
57
|
+
("Int32", INT32),
|
|
58
|
+
("Int64", INT64),
|
|
59
|
+
("BigInt", BIGINT),
|
|
60
|
+
],
|
|
61
|
+
)
|
|
62
|
+
def test_default_int_setting_controls_unannotated_literals(self, default_int, expected):
|
|
63
|
+
source = "x = 1\n"
|
|
64
|
+
compiler = Compiler.from_source(source, default_int=default_int)
|
|
65
|
+
modules = compiler.compile()
|
|
66
|
+
hpp, _ = compiler.generate_code_to_strings(modules[0])
|
|
67
|
+
expected_cpp = expected.to_cpp()
|
|
68
|
+
assert f"extern {expected_cpp} x;" in hpp
|
|
69
|
+
|
|
70
|
+
def test_reassignment_from_bigint_widens_default_int(self):
|
|
71
|
+
source = "x = 0\nx = int(5)\n"
|
|
72
|
+
compiler = Compiler.from_source(source, default_int="Int32", lib_dirs=_STDLIB_DIRS)
|
|
73
|
+
modules = compiler.compile()
|
|
74
|
+
entry = [m for m in modules if m.is_entry_point][0]
|
|
75
|
+
hpp, _ = compiler.generate_code_to_strings(entry)
|
|
76
|
+
assert "extern ::tpy::BigInt x;" in hpp
|
|
77
|
+
|
|
78
|
+
def test_invalid_default_int_setting_rejected(self):
|
|
79
|
+
with pytest.raises(ValueError, match="Unsupported default int type"):
|
|
80
|
+
Compiler.from_source("x = 1\n", default_int="Int128")
|
|
81
|
+
|
|
82
|
+
def test_native_module_propagation(self):
|
|
83
|
+
"""builtins._list inherits native_module from builtins/__init__."""
|
|
84
|
+
lib_dir = get_lib_dir() / "tpy"
|
|
85
|
+
compiler = Compiler.from_source("x = [1]\n", lib_dirs=[lib_dir])
|
|
86
|
+
compiler.compile()
|
|
87
|
+
mod = compiler.modules.get("builtins._list")
|
|
88
|
+
if mod is not None:
|
|
89
|
+
assert mod.ast.directives.native_module
|
|
90
|
+
_, cpp = compiler.generate_code_to_strings(mod)
|
|
91
|
+
assert cpp == ""
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class TestCodegenRegression:
|
|
96
|
+
def test_generic_ctor_invalid_arg_rejected(self, tmp_path):
|
|
97
|
+
"""Invalid generic constructor arg (Int32 for Span[T] param) must be rejected by sema."""
|
|
98
|
+
source = (
|
|
99
|
+
'from tpy import Span, Int32\n'
|
|
100
|
+
'x: Span[Int32] = Span[Int32](Int32(1))\n'
|
|
101
|
+
)
|
|
102
|
+
src_file = tmp_path / "test.py"
|
|
103
|
+
src_file.write_text(source)
|
|
104
|
+
compiler = Compiler(src_file, lib_dirs=[get_lib_dir() / "tpy"])
|
|
105
|
+
with pytest.raises(SemanticError, match="cannot be constructed from"):
|
|
106
|
+
compiler.compile()
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class TestSendSync:
|
|
110
|
+
"""Test Send/Sync auto-derivation on built-in types."""
|
|
111
|
+
|
|
112
|
+
# -- Primitive value types: all Send + Sync --
|
|
113
|
+
|
|
114
|
+
@pytest.mark.parametrize("typ", [INT32, INT64, BIGINT, BOOL, FLOAT, STR, CHAR])
|
|
115
|
+
def test_primitives_are_send_and_sync(self, typ):
|
|
116
|
+
assert typ.is_send()
|
|
117
|
+
assert typ.is_sync()
|
|
118
|
+
|
|
119
|
+
# -- StrView: borrows, not Send, but Sync (read-only) --
|
|
120
|
+
|
|
121
|
+
def test_strview_not_send(self):
|
|
122
|
+
assert not STRVIEW.is_send()
|
|
123
|
+
|
|
124
|
+
def test_strview_is_sync(self):
|
|
125
|
+
assert STRVIEW.is_sync()
|
|
126
|
+
|
|
127
|
+
# -- Ptr: not Send; Sync only if readonly --
|
|
128
|
+
|
|
129
|
+
def test_ptr_not_send(self):
|
|
130
|
+
assert not PtrType(INT32).is_send()
|
|
131
|
+
assert not PtrType(INT32, is_readonly=True).is_send()
|
|
132
|
+
|
|
133
|
+
def test_mutable_ptr_not_sync(self):
|
|
134
|
+
assert not PtrType(INT32).is_sync()
|
|
135
|
+
|
|
136
|
+
def test_readonly_ptr_sync_if_pointee_sync(self):
|
|
137
|
+
assert PtrType(INT32, is_readonly=True).is_sync()
|
|
138
|
+
# Ptr[readonly[list[T]]]: list is not Sync
|
|
139
|
+
assert not PtrType(make_list(INT32), is_readonly=True).is_sync()
|
|
140
|
+
|
|
141
|
+
# -- Span: not Send; Sync only if readonly --
|
|
142
|
+
|
|
143
|
+
def test_span_not_send(self):
|
|
144
|
+
assert not make_span(INT32).is_send()
|
|
145
|
+
assert not make_span(INT32, is_readonly=True).is_send()
|
|
146
|
+
|
|
147
|
+
def test_mutable_span_not_sync(self):
|
|
148
|
+
assert not make_span(INT32).is_sync()
|
|
149
|
+
|
|
150
|
+
def test_readonly_span_sync_if_element_sync(self):
|
|
151
|
+
assert make_span(INT32, is_readonly=True).is_sync()
|
|
152
|
+
|
|
153
|
+
# -- list: Send if element Send, never Sync --
|
|
154
|
+
|
|
155
|
+
def test_list_send_if_element_send(self):
|
|
156
|
+
assert make_list(INT32).is_send()
|
|
157
|
+
assert not make_list(PtrType(INT32)).is_send()
|
|
158
|
+
|
|
159
|
+
def test_list_not_sync(self):
|
|
160
|
+
assert not make_list(INT32).is_sync()
|
|
161
|
+
|
|
162
|
+
# -- dict: Send if elements Send, never Sync --
|
|
163
|
+
|
|
164
|
+
def test_dict_send_if_elements_send(self):
|
|
165
|
+
assert make_dict(STR, INT32).is_send()
|
|
166
|
+
assert not make_dict(STR, PtrType(INT32)).is_send()
|
|
167
|
+
|
|
168
|
+
def test_dict_not_sync(self):
|
|
169
|
+
assert not make_dict(STR, INT32).is_sync()
|
|
170
|
+
|
|
171
|
+
# -- Array: Send/Sync based on element --
|
|
172
|
+
|
|
173
|
+
def test_array_send_sync_based_on_element(self):
|
|
174
|
+
assert make_array(INT32, 10).is_send()
|
|
175
|
+
assert make_array(INT32, 10).is_sync()
|
|
176
|
+
assert not make_array(PtrType(INT32), 10).is_send()
|
|
177
|
+
|
|
178
|
+
# -- Tuple: Send/Sync if all elements are --
|
|
179
|
+
|
|
180
|
+
def test_tuple_send_sync(self):
|
|
181
|
+
assert TupleType((INT32, STR)).is_send()
|
|
182
|
+
assert TupleType((INT32, STR)).is_sync()
|
|
183
|
+
assert not TupleType((INT32, PtrType(STR))).is_send()
|
|
184
|
+
|
|
185
|
+
# -- Optional: delegates to inner --
|
|
186
|
+
|
|
187
|
+
def test_optional_delegates(self):
|
|
188
|
+
assert OptionalType(INT32).is_send()
|
|
189
|
+
# OptionalType inner = NominalType (non-Send record) -- delegates through.
|
|
190
|
+
# We can't use OptionalType(PtrType(...)) here because the __new__ collapse
|
|
191
|
+
# would return a bare PtrType (Ptr[T] is already nullable), so the test
|
|
192
|
+
# would exercise PtrType, not OptionalType's delegation.
|
|
193
|
+
record = NominalType("R", (), _module_qname="__main__.R")
|
|
194
|
+
assert not OptionalType(record).is_send()
|
|
195
|
+
|
|
196
|
+
# -- Union: all members --
|
|
197
|
+
|
|
198
|
+
def test_union_all_members(self):
|
|
199
|
+
assert UnionType((INT32, STR)).is_send()
|
|
200
|
+
assert not UnionType((INT32, PtrType(STR))).is_send()
|
|
201
|
+
|
|
202
|
+
# -- Own: delegates to wrapped --
|
|
203
|
+
|
|
204
|
+
def test_own_delegates(self):
|
|
205
|
+
assert OwnType(make_list(INT32)).is_send()
|
|
206
|
+
assert not OwnType(make_list(INT32)).is_sync()
|
|
207
|
+
|
|
208
|
+
# -- readonly: makes mutable containers Sync --
|
|
209
|
+
|
|
210
|
+
def test_readonly_makes_sync(self):
|
|
211
|
+
assert not make_list(INT32).is_sync()
|
|
212
|
+
assert ReadonlyType(make_list(INT32)).is_sync()
|
|
213
|
+
|
|
214
|
+
def test_readonly_of_readonly_ptr_is_sync(self):
|
|
215
|
+
rop = PtrType(INT32, is_readonly=True)
|
|
216
|
+
assert not rop.is_send()
|
|
217
|
+
assert rop.is_sync()
|
|
218
|
+
assert ReadonlyType(rop).is_sync()
|
|
219
|
+
|
|
220
|
+
def test_readonly_of_non_send_not_sync(self):
|
|
221
|
+
# readonly[list[Ptr[T]]]: Ptr not Send, so list not Send, not Sync
|
|
222
|
+
assert not ReadonlyType(make_list(PtrType(INT32))).is_sync()
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
class TestSendSyncRecordDerivation:
|
|
226
|
+
"""Test Send/Sync auto-derivation on user-defined records."""
|
|
227
|
+
|
|
228
|
+
def test_record_with_value_fields_is_send_sync(self):
|
|
229
|
+
source = (
|
|
230
|
+
"from tpy import Int32\n"
|
|
231
|
+
"class Point:\n"
|
|
232
|
+
" x: Int32\n"
|
|
233
|
+
" y: Int32\n"
|
|
234
|
+
" def __init__(self, x: Int32, y: Int32) -> None:\n"
|
|
235
|
+
" self.x = x\n"
|
|
236
|
+
" self.y = y\n"
|
|
237
|
+
"def main() -> None:\n"
|
|
238
|
+
" p = Point(Int32(1), Int32(2))\n"
|
|
239
|
+
" print(p.x)\n"
|
|
240
|
+
"main()\n"
|
|
241
|
+
)
|
|
242
|
+
compiler = Compiler.from_source(source, lib_dirs=_STDLIB_DIRS)
|
|
243
|
+
compiler.compile()
|
|
244
|
+
point_type = NominalType("Point", (), _module_qname="__main__.Point")
|
|
245
|
+
with activate_compiler(compiler):
|
|
246
|
+
assert point_type.is_send()
|
|
247
|
+
assert point_type.is_sync()
|
|
248
|
+
|
|
249
|
+
def test_record_with_ptr_field_not_send(self, tmp_path):
|
|
250
|
+
source = (
|
|
251
|
+
"from tpy import Ptr, Int32, take_ptr\n"
|
|
252
|
+
"class Wrapper:\n"
|
|
253
|
+
" x: Int32\n"
|
|
254
|
+
" def __init__(self, x: Int32) -> None:\n"
|
|
255
|
+
" self.x = x\n"
|
|
256
|
+
"class Holder:\n"
|
|
257
|
+
" p: Ptr[Wrapper]\n"
|
|
258
|
+
" def __init__(self, p: Ptr[Wrapper]) -> None:\n"
|
|
259
|
+
" self.p = p\n"
|
|
260
|
+
"def main() -> None:\n"
|
|
261
|
+
" w = Wrapper(Int32(1))\n"
|
|
262
|
+
" h = Holder(take_ptr(w))\n"
|
|
263
|
+
" print(h.p.x)\n"
|
|
264
|
+
"main()\n"
|
|
265
|
+
)
|
|
266
|
+
src_file = tmp_path / "test.py"
|
|
267
|
+
src_file.write_text(source)
|
|
268
|
+
compiler = Compiler(src_file, lib_dirs=[get_lib_dir() / "tpy"])
|
|
269
|
+
compiler.compile()
|
|
270
|
+
holder_type = NominalType("Holder", (), _module_qname="__main__.Holder")
|
|
271
|
+
with activate_compiler(compiler):
|
|
272
|
+
assert not holder_type.is_send()
|
|
273
|
+
assert not holder_type.is_sync()
|
|
274
|
+
|
|
275
|
+
def test_record_with_list_field_send_not_sync(self):
|
|
276
|
+
source = (
|
|
277
|
+
"from tpy import Int32\n"
|
|
278
|
+
"class Container:\n"
|
|
279
|
+
" items: list[Int32]\n"
|
|
280
|
+
" def __init__(self) -> None:\n"
|
|
281
|
+
" self.items = [Int32(1)]\n"
|
|
282
|
+
"def main() -> None:\n"
|
|
283
|
+
" c = Container()\n"
|
|
284
|
+
" print(len(c.items))\n"
|
|
285
|
+
"main()\n"
|
|
286
|
+
)
|
|
287
|
+
from . import get_lib_dir
|
|
288
|
+
lib_dirs = [get_lib_dir() / "tpy"]
|
|
289
|
+
compiler = Compiler.from_source(source, lib_dirs=lib_dirs)
|
|
290
|
+
compiler.compile()
|
|
291
|
+
container_type = NominalType("Container", (), _module_qname="__main__.Container")
|
|
292
|
+
with activate_compiler(compiler):
|
|
293
|
+
assert container_type.is_send()
|
|
294
|
+
assert not container_type.is_sync()
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class TestBuildLayout:
|
|
298
|
+
def setup_method(self):
|
|
299
|
+
self.layout = BuildLayout(Path("/out"), "main")
|
|
300
|
+
|
|
301
|
+
def test_simple_module_hpp(self):
|
|
302
|
+
assert self.layout.hpp_path("main") == Path("/out/main.d/include/main.hpp")
|
|
303
|
+
|
|
304
|
+
def test_simple_module_cpp(self):
|
|
305
|
+
assert self.layout.cpp_path("main") == Path("/out/main.d/src/main.cpp")
|
|
306
|
+
|
|
307
|
+
def test_dotted_module_hpp(self):
|
|
308
|
+
assert self.layout.hpp_path("pkg.mod") == Path("/out/main.d/include/pkg/mod.hpp")
|
|
309
|
+
|
|
310
|
+
def test_dotted_module_cpp(self):
|
|
311
|
+
assert self.layout.cpp_path("pkg.mod") == Path("/out/main.d/src/pkg/mod.cpp")
|
|
312
|
+
|
|
313
|
+
def test_deeply_nested_hpp(self):
|
|
314
|
+
assert self.layout.hpp_path("a.b.c.d") == Path("/out/main.d/include/a/b/c/d.hpp")
|
|
315
|
+
|
|
316
|
+
def test_deeply_nested_cpp(self):
|
|
317
|
+
assert self.layout.cpp_path("a.b.c.d") == Path("/out/main.d/src/a/b/c/d.cpp")
|
|
318
|
+
|
|
319
|
+
def test_binary_path(self):
|
|
320
|
+
assert self.layout.binary_path() == Path("/out/main.d/main")
|
|
321
|
+
|
|
322
|
+
def test_binary_path_with_variant(self):
|
|
323
|
+
layout = BuildLayout(Path("/out"), "main", build_variant="debug")
|
|
324
|
+
assert layout.binary_path() == Path("/out/main.d/debug/main")
|
|
325
|
+
|
|
326
|
+
def test_binary_path_release_variant(self):
|
|
327
|
+
layout = BuildLayout(Path("/out"), "main", build_variant="release")
|
|
328
|
+
assert layout.binary_path() == Path("/out/main.d/release/main")
|
|
329
|
+
|
|
330
|
+
def test_build_dir_no_variant(self):
|
|
331
|
+
assert self.layout.build_dir == Path("/out/main.d")
|
|
332
|
+
|
|
333
|
+
def test_build_dir_with_variant(self):
|
|
334
|
+
layout = BuildLayout(Path("/out"), "main", build_variant="debug")
|
|
335
|
+
assert layout.build_dir == Path("/out/main.d/debug")
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
class TestGenerateCmake:
|
|
339
|
+
"""Tests for sources.cmake generation and runtime bundling."""
|
|
340
|
+
|
|
341
|
+
def _make_layout(self, tmp_path: Path) -> BuildLayout:
|
|
342
|
+
layout = BuildLayout(tmp_path, "app")
|
|
343
|
+
layout.include_dir.mkdir(parents=True)
|
|
344
|
+
layout.src_dir.mkdir(parents=True)
|
|
345
|
+
return layout
|
|
346
|
+
|
|
347
|
+
def _dummy_cpp(self, layout: BuildLayout) -> list[Path]:
|
|
348
|
+
cpp = layout.src_dir / "app.cpp"
|
|
349
|
+
cpp.write_text("// generated")
|
|
350
|
+
return [cpp]
|
|
351
|
+
|
|
352
|
+
def test_bundle_runtime_copies_headers(self, tmp_path: Path):
|
|
353
|
+
layout = self._make_layout(tmp_path)
|
|
354
|
+
runtime_inc = get_runtime_dir() / "cpp" / "include"
|
|
355
|
+
layout.generate_cmake(
|
|
356
|
+
runtime_include_dir=runtime_inc,
|
|
357
|
+
cpp_files=self._dummy_cpp(layout),
|
|
358
|
+
bundle_runtime=True,
|
|
359
|
+
)
|
|
360
|
+
bundled = layout.root_dir / "runtime" / "include" / "tpy"
|
|
361
|
+
assert bundled.is_dir()
|
|
362
|
+
assert (bundled / "tpy.hpp").is_file()
|
|
363
|
+
|
|
364
|
+
def test_bundle_runtime_cmake_uses_local_path(self, tmp_path: Path):
|
|
365
|
+
layout = self._make_layout(tmp_path)
|
|
366
|
+
runtime_inc = get_runtime_dir() / "cpp" / "include"
|
|
367
|
+
cmake_path = layout.generate_cmake(
|
|
368
|
+
runtime_include_dir=runtime_inc,
|
|
369
|
+
cpp_files=self._dummy_cpp(layout),
|
|
370
|
+
bundle_runtime=True,
|
|
371
|
+
)
|
|
372
|
+
content = cmake_path.read_text()
|
|
373
|
+
assert "${CMAKE_CURRENT_LIST_DIR}/runtime/include" in content
|
|
374
|
+
# No absolute or parent-traversal paths to the runtime
|
|
375
|
+
assert "../../" not in content.split("TPYC_INCLUDE_DIRS")[1].split(")")[0]
|
|
376
|
+
|
|
377
|
+
def test_no_bundle_runtime_uses_relative_path(self, tmp_path: Path):
|
|
378
|
+
layout = self._make_layout(tmp_path)
|
|
379
|
+
runtime_inc = get_runtime_dir() / "cpp" / "include"
|
|
380
|
+
cmake_path = layout.generate_cmake(
|
|
381
|
+
runtime_include_dir=runtime_inc,
|
|
382
|
+
cpp_files=self._dummy_cpp(layout),
|
|
383
|
+
bundle_runtime=False,
|
|
384
|
+
)
|
|
385
|
+
content = cmake_path.read_text()
|
|
386
|
+
bundled = layout.root_dir / "runtime" / "include"
|
|
387
|
+
assert not bundled.exists()
|
|
388
|
+
assert "runtime/include" not in content
|
|
389
|
+
# Should reference the runtime via a relative or absolute path
|
|
390
|
+
lines = content.splitlines()
|
|
391
|
+
inc_lines = []
|
|
392
|
+
in_inc = False
|
|
393
|
+
for line in lines:
|
|
394
|
+
if line.startswith("set(TPYC_INCLUDE_DIRS"):
|
|
395
|
+
in_inc = True
|
|
396
|
+
continue
|
|
397
|
+
if in_inc:
|
|
398
|
+
if line.strip() == ")":
|
|
399
|
+
break
|
|
400
|
+
inc_lines.append(line.strip())
|
|
401
|
+
assert len(inc_lines) == 2
|
|
402
|
+
assert "../" in inc_lines[1] or str(runtime_inc) in inc_lines[1]
|
|
403
|
+
|
|
404
|
+
def test_bundle_runtime_idempotent(self, tmp_path: Path):
|
|
405
|
+
"""Repeated calls with bundle_runtime=True succeed."""
|
|
406
|
+
layout = self._make_layout(tmp_path)
|
|
407
|
+
runtime_inc = get_runtime_dir() / "cpp" / "include"
|
|
408
|
+
cpp_files = self._dummy_cpp(layout)
|
|
409
|
+
layout.generate_cmake(
|
|
410
|
+
runtime_include_dir=runtime_inc,
|
|
411
|
+
cpp_files=cpp_files,
|
|
412
|
+
bundle_runtime=True,
|
|
413
|
+
)
|
|
414
|
+
cmake_path = layout.generate_cmake(
|
|
415
|
+
runtime_include_dir=runtime_inc,
|
|
416
|
+
cpp_files=cpp_files,
|
|
417
|
+
bundle_runtime=True,
|
|
418
|
+
)
|
|
419
|
+
content = cmake_path.read_text()
|
|
420
|
+
assert "${CMAKE_CURRENT_LIST_DIR}/runtime/include" in content
|
|
421
|
+
assert (layout.root_dir / "runtime" / "include" / "tpy" / "tpy.hpp").is_file()
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def _make_skeleton_module(records=(), protocols=(), functions=(), enums=()):
|
|
425
|
+
"""Build a minimal CompiledModule with given exports populated
|
|
426
|
+
and a matching `_skeleton_ids` snapshot, as if pre-populate had
|
|
427
|
+
just run on it. No sema needed -- the verifier only consults the
|
|
428
|
+
snapshot and the exports.
|
|
429
|
+
"""
|
|
430
|
+
from .compiler import CompiledModule, ModuleExports, _SkeletonSnapshot
|
|
431
|
+
from .parse import TpyModule
|
|
432
|
+
from .parse.nodes import ModuleDirectives
|
|
433
|
+
|
|
434
|
+
ast = TpyModule(
|
|
435
|
+
records=[], functions=[], protocols=[], enums=[],
|
|
436
|
+
top_level_stmts=[], source_lines=[], imports={},
|
|
437
|
+
tpy_star_import=False, star_imports=set(), user_module_imports={},
|
|
438
|
+
module_aliases={}, bare_module_imports=set(), type_aliases={},
|
|
439
|
+
directives=ModuleDirectives(),
|
|
440
|
+
)
|
|
441
|
+
exports = ModuleExports()
|
|
442
|
+
for r in records:
|
|
443
|
+
exports.records[r.name] = r
|
|
444
|
+
for p in protocols:
|
|
445
|
+
exports.protocols[p.name] = p
|
|
446
|
+
for name, fi_list in functions:
|
|
447
|
+
exports.functions[name] = list(fi_list)
|
|
448
|
+
for name, nominal in enums:
|
|
449
|
+
exports.enums[name] = nominal
|
|
450
|
+
|
|
451
|
+
snap = _SkeletonSnapshot(
|
|
452
|
+
records={n: id(o) for n, o in exports.records.items()},
|
|
453
|
+
protocols={n: id(o) for n, o in exports.protocols.items()},
|
|
454
|
+
functions={n: (id(lst), id(lst[0])) if lst else (0, 0)
|
|
455
|
+
for n, lst in exports.functions.items()},
|
|
456
|
+
)
|
|
457
|
+
return CompiledModule(
|
|
458
|
+
name="m", path=Path("<test>"), ast=ast, exports=exports,
|
|
459
|
+
is_entry_point=True, _skeleton_ids=snap,
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
class TestSkeletonAdoptionAssertion:
|
|
464
|
+
"""Pins the `_verify_skeleton_adoption` invariant: every
|
|
465
|
+
pre-populated skeleton object/list must be adopted in place by
|
|
466
|
+
its registration entrypoint, so peer registries that captured a
|
|
467
|
+
reference at bind_imports time see freshly-finalized data.
|
|
468
|
+
|
|
469
|
+
Five of these tests use `_make_skeleton_module` to hand-build a
|
|
470
|
+
minimal CompiledModule + matching snapshot and exercise the
|
|
471
|
+
verifier directly, with no sema involved. The first test does a
|
|
472
|
+
full real compile to confirm the production path passes the
|
|
473
|
+
assertion in normal use (no false positives).
|
|
474
|
+
"""
|
|
475
|
+
|
|
476
|
+
def test_correctly_adopted_real_compile(self):
|
|
477
|
+
"""A normal compile passes the assertion (smoke-test against
|
|
478
|
+
false positives in the production pipeline)."""
|
|
479
|
+
source = (
|
|
480
|
+
"class A:\n"
|
|
481
|
+
" val: int\n"
|
|
482
|
+
" def __init__(self, v: int) -> None:\n"
|
|
483
|
+
" self.val = v\n"
|
|
484
|
+
"def helper() -> int:\n"
|
|
485
|
+
" return 42\n"
|
|
486
|
+
)
|
|
487
|
+
Compiler.from_source(source).compile() # raises if violated
|
|
488
|
+
|
|
489
|
+
def test_record_identity_mismatch_fires(self):
|
|
490
|
+
from .typesys import RecordInfo
|
|
491
|
+
rec = RecordInfo(name="A", fields=[], module="m", defining_module="m")
|
|
492
|
+
compiled = _make_skeleton_module(records=[rec])
|
|
493
|
+
compiled.exports.records["A"] = RecordInfo(
|
|
494
|
+
name="A", fields=[], module="m", defining_module="m",
|
|
495
|
+
)
|
|
496
|
+
with pytest.raises(AssertionError, match=r"record 'A'"):
|
|
497
|
+
Compiler._verify_skeleton_adoption(compiled)
|
|
498
|
+
|
|
499
|
+
def test_protocol_identity_mismatch_fires(self):
|
|
500
|
+
from .typesys import ProtocolInfo
|
|
501
|
+
proto = ProtocolInfo(name="P", methods=[], type_params=[],
|
|
502
|
+
module="m", is_dynamic=False)
|
|
503
|
+
compiled = _make_skeleton_module(protocols=[proto])
|
|
504
|
+
compiled.exports.protocols["P"] = ProtocolInfo(
|
|
505
|
+
name="P", methods=[], type_params=[],
|
|
506
|
+
module="m", is_dynamic=False,
|
|
507
|
+
)
|
|
508
|
+
with pytest.raises(AssertionError, match=r"protocol 'P'"):
|
|
509
|
+
Compiler._verify_skeleton_adoption(compiled)
|
|
510
|
+
|
|
511
|
+
def test_function_with_neither_list_nor_fi_identity_fires(self):
|
|
512
|
+
from .typesys import FunctionInfo, VOID
|
|
513
|
+
original = FunctionInfo(name="f", params=[], return_type=VOID,
|
|
514
|
+
qualified_name="m.f", originating_module="m")
|
|
515
|
+
compiled = _make_skeleton_module(functions=[("f", [original])])
|
|
516
|
+
compiled.exports.functions["f"] = [
|
|
517
|
+
FunctionInfo(name="f", params=[], return_type=VOID,
|
|
518
|
+
qualified_name="m.f", originating_module="m"),
|
|
519
|
+
]
|
|
520
|
+
with pytest.raises(AssertionError, match=r"function 'f'"):
|
|
521
|
+
Compiler._verify_skeleton_adoption(compiled)
|
|
522
|
+
|
|
523
|
+
def test_function_inner_fi_preserved_passes(self):
|
|
524
|
+
# register_function adoption shape: fresh list, skeleton FI inside.
|
|
525
|
+
from .typesys import FunctionInfo, VOID
|
|
526
|
+
original = FunctionInfo(name="f", params=[], return_type=VOID,
|
|
527
|
+
qualified_name="m.f", originating_module="m")
|
|
528
|
+
compiled = _make_skeleton_module(functions=[("f", [original])])
|
|
529
|
+
compiled.exports.functions["f"] = [original]
|
|
530
|
+
Compiler._verify_skeleton_adoption(compiled)
|
|
531
|
+
|
|
532
|
+
def test_function_list_mutated_in_place_passes(self):
|
|
533
|
+
# register_overload_group adoption shape: skeleton list cleared
|
|
534
|
+
# and re-extended with fresh FIs; list identity preserved even
|
|
535
|
+
# though the inner FI identity is gone.
|
|
536
|
+
from .typesys import FunctionInfo, VOID
|
|
537
|
+
original = FunctionInfo(name="g", params=[], return_type=VOID,
|
|
538
|
+
qualified_name="m.g", originating_module="m")
|
|
539
|
+
compiled = _make_skeleton_module(functions=[("g", [original])])
|
|
540
|
+
skeleton_list = compiled.exports.functions["g"]
|
|
541
|
+
skeleton_list.clear()
|
|
542
|
+
skeleton_list.extend([
|
|
543
|
+
FunctionInfo(name="g", params=[], return_type=VOID,
|
|
544
|
+
qualified_name="m.g", originating_module="m"),
|
|
545
|
+
FunctionInfo(name="g", params=[], return_type=VOID,
|
|
546
|
+
qualified_name="m.g", originating_module="m"),
|
|
547
|
+
])
|
|
548
|
+
Compiler._verify_skeleton_adoption(compiled)
|
|
549
|
+
|
|
550
|
+
def test_enum_not_checked(self):
|
|
551
|
+
from .typesys import NominalType
|
|
552
|
+
compiled = _make_skeleton_module(
|
|
553
|
+
enums=[("Color", NominalType(name="Color", type_args=(),
|
|
554
|
+
_module_qname="m.Color"))],
|
|
555
|
+
)
|
|
556
|
+
compiled.exports.enums["Color"] = NominalType(
|
|
557
|
+
name="Color", type_args=(), _module_qname="m.Color",
|
|
558
|
+
)
|
|
559
|
+
Compiler._verify_skeleton_adoption(compiled)
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Unit tests for typesys.contains_type_param.
|
|
2
|
+
|
|
3
|
+
Canonical "does this type tree mention a type parameter" predicate used
|
|
4
|
+
at sema gates (overload resolution, protocol arg matching, value-type
|
|
5
|
+
field validation, generic method registration). Supports an optional
|
|
6
|
+
`names` filter.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .typesys import (
|
|
10
|
+
INT32, NominalType, OptionalType, PtrType, TupleType, TypeParamKind,
|
|
11
|
+
TypeParamRef, UnionType, contains_type_param, make_list,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class TestUnfiltered:
|
|
16
|
+
"""`names=None` -- any TypeParamRef counts."""
|
|
17
|
+
|
|
18
|
+
def test_bare_type_param(self) -> None:
|
|
19
|
+
assert contains_type_param(TypeParamRef("T")) is True
|
|
20
|
+
|
|
21
|
+
def test_concrete_type(self) -> None:
|
|
22
|
+
assert contains_type_param(INT32) is False
|
|
23
|
+
|
|
24
|
+
def test_nested_in_optional(self) -> None:
|
|
25
|
+
assert contains_type_param(OptionalType(TypeParamRef("T"))) is True
|
|
26
|
+
|
|
27
|
+
def test_nested_in_list(self) -> None:
|
|
28
|
+
assert contains_type_param(make_list(element_type=TypeParamRef("T"))) is True
|
|
29
|
+
|
|
30
|
+
def test_nested_in_tuple(self) -> None:
|
|
31
|
+
assert contains_type_param(TupleType((INT32, TypeParamRef("T")))) is True
|
|
32
|
+
|
|
33
|
+
def test_nested_in_union(self) -> None:
|
|
34
|
+
assert contains_type_param(UnionType((INT32, TypeParamRef("T")))) is True
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class TestNamesFilter:
|
|
38
|
+
"""`names={"T"}` -- only TypeParamRefs whose name is in the set count."""
|
|
39
|
+
|
|
40
|
+
def test_match_hit(self) -> None:
|
|
41
|
+
assert contains_type_param(TypeParamRef("T"), names={"T"}) is True
|
|
42
|
+
|
|
43
|
+
def test_match_miss(self) -> None:
|
|
44
|
+
assert contains_type_param(TypeParamRef("U"), names={"T"}) is False
|
|
45
|
+
|
|
46
|
+
def test_nested_match_hit(self) -> None:
|
|
47
|
+
assert contains_type_param(
|
|
48
|
+
OptionalType(TypeParamRef("T")), names={"T"},
|
|
49
|
+
) is True
|
|
50
|
+
|
|
51
|
+
def test_nested_match_miss(self) -> None:
|
|
52
|
+
assert contains_type_param(
|
|
53
|
+
OptionalType(TypeParamRef("U")), names={"T"},
|
|
54
|
+
) is False
|
|
55
|
+
|
|
56
|
+
def test_one_of_many(self) -> None:
|
|
57
|
+
# Type tree contains both T and U; filter on {"T"} matches via T.
|
|
58
|
+
assert contains_type_param(
|
|
59
|
+
TupleType((TypeParamRef("U"), TypeParamRef("T"))),
|
|
60
|
+
names={"T"},
|
|
61
|
+
) is True
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class TestIntKindHandling:
|
|
65
|
+
"""INT-kind TypeParamRefs (e.g. `N` in `Array[T, N: int]`) live in
|
|
66
|
+
`NominalType.type_args` but `inner_types()` filters them out for
|
|
67
|
+
substitution traversals. `contains_type_param` walks `type_args`
|
|
68
|
+
directly so INT-kind refs still count."""
|
|
69
|
+
|
|
70
|
+
def test_bare_int_kind_param(self) -> None:
|
|
71
|
+
n = TypeParamRef("N", kind=TypeParamKind.INT)
|
|
72
|
+
assert contains_type_param(n) is True
|
|
73
|
+
|
|
74
|
+
def test_int_kind_inside_nominal(self) -> None:
|
|
75
|
+
n = TypeParamRef("N", kind=TypeParamKind.INT)
|
|
76
|
+
# NominalType wrapping an INT-kind param. inner_types() would
|
|
77
|
+
# filter N out; type_args walk catches it.
|
|
78
|
+
wrapper = NominalType("SomeArr", type_args=(INT32, n))
|
|
79
|
+
assert contains_type_param(wrapper) is True
|
|
80
|
+
|
|
81
|
+
def test_int_kind_with_names_filter(self) -> None:
|
|
82
|
+
n = TypeParamRef("N", kind=TypeParamKind.INT)
|
|
83
|
+
wrapper = NominalType("SomeArr", type_args=(INT32, n))
|
|
84
|
+
assert contains_type_param(wrapper, names={"N"}) is True
|
|
85
|
+
assert contains_type_param(wrapper, names={"T"}) is False
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class TestCompositeWrappers:
|
|
89
|
+
"""Multi-level wrapper chains."""
|
|
90
|
+
|
|
91
|
+
def test_optional_of_list_of_param(self) -> None:
|
|
92
|
+
t = OptionalType(make_list(element_type=TypeParamRef("T")))
|
|
93
|
+
assert contains_type_param(t) is True
|
|
94
|
+
|
|
95
|
+
def test_ptr_of_optional_of_param(self) -> None:
|
|
96
|
+
t = PtrType(OptionalType(TypeParamRef("T")))
|
|
97
|
+
assert contains_type_param(t) is True
|
|
98
|
+
|
|
99
|
+
def test_deep_concrete(self) -> None:
|
|
100
|
+
t = PtrType(OptionalType(make_list(element_type=INT32)))
|
|
101
|
+
assert contains_type_param(t) is False
|