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,151 @@
|
|
|
1
|
+
"""Parser-shaped adapter so the real `TypeResolver` works on
|
|
2
|
+
plugin-lowered modules unchanged.
|
|
3
|
+
|
|
4
|
+
`TypeResolver` reads a handful of attributes off its owning `Parser`
|
|
5
|
+
(see the TypeResolver docstring for the contract): `registry`,
|
|
6
|
+
`_imports`, `_type_param_scope`, `_module_class_names`,
|
|
7
|
+
`_module_type_alias_names`, `_module_aliases`, `_reverse_module_aliases`,
|
|
8
|
+
`_nested_type_scope`, `_local_defs`, `_bare_module_imports`. Plus
|
|
9
|
+
three methods: `_resolve_type_name`, `_raise_unresolved_import_error`,
|
|
10
|
+
`_warn_at_loc`.
|
|
11
|
+
|
|
12
|
+
`_PluginParserAdapter` implements that contract for plugin modules
|
|
13
|
+
without instantiating a real `Parser`. Plugin lowering populates it
|
|
14
|
+
from the IR (imports, module name, directives); the rest of the
|
|
15
|
+
parser-internal bookkeeping is empty-but-correct frozensets/dicts.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
from typing import Iterable
|
|
21
|
+
|
|
22
|
+
from ..parse import SourceLocation
|
|
23
|
+
from ..parse.imports import (
|
|
24
|
+
ImportProcessor, get_builtins_exports, get_tpy_exports, get_typing_exports,
|
|
25
|
+
)
|
|
26
|
+
from ..parse.nodes import ParseError
|
|
27
|
+
from ..parse.type_resolver import TypeResolver
|
|
28
|
+
from ..typesys import TypeRegistry
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class _PluginParserAdapter:
|
|
32
|
+
"""Parser-shaped object consumed by `TypeResolver`.
|
|
33
|
+
|
|
34
|
+
Constructed once per plugin-lowered module. Lowering fills the
|
|
35
|
+
import-related attributes from the IR; the parser-only bookkeeping
|
|
36
|
+
fields stay at safe defaults (empty frozensets, empty dicts) because
|
|
37
|
+
plugin modules have no parse-time class scan, no Python `ast` to
|
|
38
|
+
consult, and no `# tpy:` directive scanning.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(
|
|
42
|
+
self,
|
|
43
|
+
module_name: str,
|
|
44
|
+
is_entry_point: bool,
|
|
45
|
+
shared_modules: 'dict | None' = None,
|
|
46
|
+
) -> None:
|
|
47
|
+
self.registry = TypeRegistry(shared_modules=shared_modules)
|
|
48
|
+
self._imports = ImportProcessor(self._warn, module_name=module_name)
|
|
49
|
+
self._imports.imports = {}
|
|
50
|
+
self._module_name = module_name
|
|
51
|
+
self._is_entry_point = is_entry_point
|
|
52
|
+
|
|
53
|
+
# Parser-only bookkeeping. Plugin lowering produces no `ast` to
|
|
54
|
+
# walk, so all of these stay empty -- TypeResolver still consults
|
|
55
|
+
# them but they correctly answer "nothing here" in every case.
|
|
56
|
+
self._local_defs: frozenset[str] = frozenset()
|
|
57
|
+
self._module_class_names: frozenset[str] = frozenset()
|
|
58
|
+
self._module_type_alias_names: frozenset[str] = frozenset()
|
|
59
|
+
self._module_aliases: dict[str, str] = {}
|
|
60
|
+
self._reverse_module_aliases: dict[str, str] = {}
|
|
61
|
+
self._bare_module_imports: set[str] = set()
|
|
62
|
+
self._nested_type_scope: dict[str, str] = {}
|
|
63
|
+
self._type_param_scope: dict[str, object] | None = None
|
|
64
|
+
|
|
65
|
+
# Parser-side warnings collected by `_warn_at_loc`. Plugin
|
|
66
|
+
# lowering does not currently surface these back, but holding
|
|
67
|
+
# them avoids reaching into a `None`.
|
|
68
|
+
self._warnings: list[tuple[str, SourceLocation | None]] = []
|
|
69
|
+
|
|
70
|
+
# ------------------------------------------------------------------
|
|
71
|
+
# Methods TypeResolver calls on the parser
|
|
72
|
+
|
|
73
|
+
def _resolve_type_name(self, local_name: str) -> tuple[str, str] | None:
|
|
74
|
+
"""Mirror `Parser._resolve_type_name` for plugin-lowered modules.
|
|
75
|
+
|
|
76
|
+
Plugin modules have no `_local_defs` (no Python ast to scan) and
|
|
77
|
+
no locally-registered builtins, so the parser version's first
|
|
78
|
+
branch and last branch are no-ops here. The remaining logic --
|
|
79
|
+
consult the import name index, fall back to ambient builtins --
|
|
80
|
+
applies unchanged.
|
|
81
|
+
"""
|
|
82
|
+
source = self._imports.get_import_source(local_name)
|
|
83
|
+
if source:
|
|
84
|
+
return source
|
|
85
|
+
# `get_builtins_exports` is the Python `builtins` surface (`int`,
|
|
86
|
+
# `str`, ...). Plugin modules can reference these without an
|
|
87
|
+
# explicit import, exactly as Python source can.
|
|
88
|
+
if local_name in get_builtins_exports():
|
|
89
|
+
return ("builtins", local_name)
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
def _raise_unresolved_import_error(
|
|
93
|
+
self,
|
|
94
|
+
raw_name: str,
|
|
95
|
+
node: object | None = None,
|
|
96
|
+
*,
|
|
97
|
+
loc: SourceLocation | None = None,
|
|
98
|
+
) -> None:
|
|
99
|
+
"""Mirror the parser's import-hint diagnostic."""
|
|
100
|
+
if raw_name in get_typing_exports():
|
|
101
|
+
raise ParseError(
|
|
102
|
+
f"'{raw_name}' requires: from typing import {raw_name}",
|
|
103
|
+
loc=loc,
|
|
104
|
+
)
|
|
105
|
+
if raw_name in get_tpy_exports():
|
|
106
|
+
raise ParseError(
|
|
107
|
+
f"'{raw_name}' requires: from tpy import {raw_name}",
|
|
108
|
+
loc=loc,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
def _warn_at_loc(self, message: str, loc: SourceLocation | None) -> None:
|
|
112
|
+
self._warnings.append((message, loc))
|
|
113
|
+
|
|
114
|
+
# Helper used as ImportProcessor's `warn_fn`.
|
|
115
|
+
def _warn(self, message: str, node: object | None = None,
|
|
116
|
+
*, loc: SourceLocation | None = None) -> None:
|
|
117
|
+
self._warnings.append((message, loc))
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def make_plugin_resolver(
|
|
121
|
+
module_name: str,
|
|
122
|
+
is_entry_point: bool = False,
|
|
123
|
+
shared_modules: 'dict | None' = None,
|
|
124
|
+
*,
|
|
125
|
+
imports: 'dict[str, set[tuple[str, str]] | None] | None' = None,
|
|
126
|
+
name_index: 'Iterable[tuple[str, str, str]]' = (),
|
|
127
|
+
) -> TypeResolver:
|
|
128
|
+
"""Build a `TypeResolver` for a plugin-lowered module.
|
|
129
|
+
|
|
130
|
+
`imports` and `name_index` mirror the parser's two-tier import
|
|
131
|
+
bookkeeping:
|
|
132
|
+
- `imports`: module-name -> set of `(original, local)` tuples
|
|
133
|
+
(or None for whole-module imports). Mirrors `TpyModule.imports`.
|
|
134
|
+
- `name_index`: each entry is `(local_name, source_module,
|
|
135
|
+
original_name)`. Mirrors what `ImportProcessor._index_import`
|
|
136
|
+
would have produced during parsing.
|
|
137
|
+
|
|
138
|
+
The two tables exist for distinct lookup needs in TypeResolver --
|
|
139
|
+
`imports` is consulted for whole-module imports while resolving
|
|
140
|
+
qualified names; `name_index` is consulted for the bare-name path.
|
|
141
|
+
"""
|
|
142
|
+
adapter = _PluginParserAdapter(
|
|
143
|
+
module_name=module_name,
|
|
144
|
+
is_entry_point=is_entry_point,
|
|
145
|
+
shared_modules=shared_modules,
|
|
146
|
+
)
|
|
147
|
+
if imports is not None:
|
|
148
|
+
adapter._imports.imports = imports
|
|
149
|
+
for local, src_mod, orig in name_index:
|
|
150
|
+
adapter._imports.index_imported_name(local, src_mod, orig)
|
|
151
|
+
return TypeResolver(adapter)
|
tpyc/frontend_plugin.py
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"""Frontend plugin contract + loader.
|
|
2
|
+
|
|
3
|
+
See `docs/FRONTEND_PLUGIN_DESIGN.md` for the contract specification.
|
|
4
|
+
|
|
5
|
+
M1 scope: plugin discovery + WorkspaceContext + registry. Decorator
|
|
6
|
+
manifests are accepted but unused (no registry yet). Subprocess-helper
|
|
7
|
+
SubprocessPlugin is future work.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import importlib
|
|
13
|
+
import importlib.util
|
|
14
|
+
from abc import ABC, abstractmethod
|
|
15
|
+
from dataclasses import dataclass, field
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import ClassVar, Iterable
|
|
18
|
+
|
|
19
|
+
from .diagnostics import Diagnostic, DiagnosticLevel
|
|
20
|
+
from .frontend_ir.nodes import API_VERSION, FrontendModule
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(frozen=True)
|
|
24
|
+
class WorkspaceContext:
|
|
25
|
+
"""Read-only view of the compile-time environment exposed to plugins.
|
|
26
|
+
|
|
27
|
+
M1 carries only the fields hello-world needs: `options` (routed
|
|
28
|
+
`--dsl-opt` values for this plugin), `no_stdlib` (mirror of the
|
|
29
|
+
compiler flag), and `read_file` for opening the entry source.
|
|
30
|
+
`find_files` and `resolve_module` from the design doc are deferred
|
|
31
|
+
until a plugin needs them.
|
|
32
|
+
|
|
33
|
+
`stdlib_search_dirs` is the subset of `search_dirs` that holds
|
|
34
|
+
TPy's implicit stdlib (`lib/tpy/`). Plugins that translate a
|
|
35
|
+
`uses`- or `import`-style directive in their source language can
|
|
36
|
+
consult this to keep stdlib invisible to bare imports while still
|
|
37
|
+
leaving an escape hatch (e.g. `uses py.math` in Pascal) that
|
|
38
|
+
routes through the full search path.
|
|
39
|
+
"""
|
|
40
|
+
api_version: int
|
|
41
|
+
entry_point: Path
|
|
42
|
+
search_dirs: tuple[Path, ...]
|
|
43
|
+
stdlib_search_dirs: tuple[Path, ...]
|
|
44
|
+
options: dict[str, str]
|
|
45
|
+
no_stdlib: bool
|
|
46
|
+
|
|
47
|
+
def read_file(self, path: Path) -> str:
|
|
48
|
+
return Path(path).read_text()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclass
|
|
52
|
+
class FrontendOutput:
|
|
53
|
+
"""Return value from `FrontendPlugin.parse()`."""
|
|
54
|
+
module: FrontendModule
|
|
55
|
+
diagnostics: list[Diagnostic] = field(default_factory=list)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class FrontendPluginError(Exception):
|
|
59
|
+
"""Fatal error raised by a plugin when it cannot produce IR.
|
|
60
|
+
|
|
61
|
+
Carries one `Diagnostic`; the compiler catches it and reports the
|
|
62
|
+
diagnostic as `PLUGIN_REPORTED`.
|
|
63
|
+
"""
|
|
64
|
+
def __init__(self, diagnostic: Diagnostic):
|
|
65
|
+
super().__init__(diagnostic.message)
|
|
66
|
+
self.diagnostic = diagnostic
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class FrontendPlugin(ABC):
|
|
70
|
+
"""Base class for frontend plugins.
|
|
71
|
+
|
|
72
|
+
Subclasses set the ClassVar metadata and implement `parse()`.
|
|
73
|
+
Plugin modules expose the subclass (not an instance) as the module
|
|
74
|
+
attribute `PLUGIN`; the compiler instantiates it once per `tpyc`
|
|
75
|
+
invocation with the routed options dict.
|
|
76
|
+
"""
|
|
77
|
+
api_version: ClassVar[int] = API_VERSION
|
|
78
|
+
name: ClassVar[str] = ""
|
|
79
|
+
extensions: ClassVar[tuple[str, ...]] = ()
|
|
80
|
+
decorator_manifest: ClassVar[tuple] = ()
|
|
81
|
+
|
|
82
|
+
def __init__(self, options: dict[str, str]) -> None:
|
|
83
|
+
self.options = options
|
|
84
|
+
|
|
85
|
+
@abstractmethod
|
|
86
|
+
def parse(self, ctx: WorkspaceContext,
|
|
87
|
+
module_name: str, file_path: Path) -> FrontendOutput:
|
|
88
|
+
...
|
|
89
|
+
|
|
90
|
+
def library_paths(self) -> tuple[Path, ...]:
|
|
91
|
+
"""Extra directories the plugin contributes to TPy's module
|
|
92
|
+
search path. The CLI prepends these to `lib_dirs` after the
|
|
93
|
+
user's `-L` so plugin-shipped libraries (e.g. the Pascal
|
|
94
|
+
stdlib under `pascal/lib/`) resolve without the user having
|
|
95
|
+
to pass `-L` for each one. Returns an empty tuple by default.
|
|
96
|
+
"""
|
|
97
|
+
return ()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@dataclass
|
|
101
|
+
class FrontendRegistry:
|
|
102
|
+
"""Maps file extensions to plugin instances."""
|
|
103
|
+
by_extension: dict[str, FrontendPlugin] = field(default_factory=dict)
|
|
104
|
+
plugins: list[FrontendPlugin] = field(default_factory=list)
|
|
105
|
+
|
|
106
|
+
def register(self, plugin: FrontendPlugin) -> None:
|
|
107
|
+
for ext in plugin.extensions:
|
|
108
|
+
if ext in self.by_extension:
|
|
109
|
+
existing = self.by_extension[ext]
|
|
110
|
+
raise FrontendPluginError(Diagnostic(
|
|
111
|
+
level=DiagnosticLevel.ERROR,
|
|
112
|
+
message=(f"extension {ext!r} claimed by both "
|
|
113
|
+
f"{existing.name!r} and {plugin.name!r}"),
|
|
114
|
+
))
|
|
115
|
+
self.by_extension[ext] = plugin
|
|
116
|
+
self.plugins.append(plugin)
|
|
117
|
+
|
|
118
|
+
def for_path(self, path: Path) -> FrontendPlugin | None:
|
|
119
|
+
return self.by_extension.get(path.suffix)
|
|
120
|
+
|
|
121
|
+
def claims_extension(self, ext: str) -> bool:
|
|
122
|
+
return ext in self.by_extension
|
|
123
|
+
|
|
124
|
+
def all_extensions(self) -> frozenset[str]:
|
|
125
|
+
return frozenset(self.by_extension.keys())
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def resolve_plugin_class(spec: str) -> type[FrontendPlugin]:
|
|
129
|
+
"""Load a plugin module and return its `PLUGIN` class without
|
|
130
|
+
instantiating it. Used when the caller needs to read `name` /
|
|
131
|
+
`extensions` / `api_version` ClassVars (e.g. to route
|
|
132
|
+
`--dsl-opt` values to the right plugin, or to learn which
|
|
133
|
+
source extensions a plugin claims) before deciding what
|
|
134
|
+
options dict to pass to `__init__`.
|
|
135
|
+
|
|
136
|
+
Steps follow `docs/FRONTEND_PLUGIN_DESIGN.md` "Loading and
|
|
137
|
+
registration":
|
|
138
|
+
1. If spec resolves to an existing .py file, import via spec_from_file_location.
|
|
139
|
+
2. Else, treat spec as an importable module name.
|
|
140
|
+
3. Fetch `PLUGIN`; validate it is a FrontendPlugin subclass.
|
|
141
|
+
4. Validate api_version is supported.
|
|
142
|
+
"""
|
|
143
|
+
spec_path = Path(spec)
|
|
144
|
+
module = None
|
|
145
|
+
if spec_path.suffix == ".py" and spec_path.exists():
|
|
146
|
+
module_name = f"_tpyc_plugin_{spec_path.stem}"
|
|
147
|
+
loader_spec = importlib.util.spec_from_file_location(module_name, spec_path)
|
|
148
|
+
if loader_spec is None or loader_spec.loader is None:
|
|
149
|
+
raise _plugin_load_error(
|
|
150
|
+
f"cannot load plugin file: {spec}")
|
|
151
|
+
module = importlib.util.module_from_spec(loader_spec)
|
|
152
|
+
loader_spec.loader.exec_module(module)
|
|
153
|
+
else:
|
|
154
|
+
try:
|
|
155
|
+
module = importlib.import_module(spec)
|
|
156
|
+
except ImportError as e:
|
|
157
|
+
raise _plugin_load_error(
|
|
158
|
+
f"cannot import plugin module {spec!r}: {e}")
|
|
159
|
+
|
|
160
|
+
plugin_cls = getattr(module, "PLUGIN", None)
|
|
161
|
+
if plugin_cls is None:
|
|
162
|
+
raise _plugin_load_error(
|
|
163
|
+
f"plugin module {spec!r} has no PLUGIN attribute")
|
|
164
|
+
if not (isinstance(plugin_cls, type) and issubclass(plugin_cls, FrontendPlugin)):
|
|
165
|
+
raise _plugin_load_error(
|
|
166
|
+
f"plugin module {spec!r}: PLUGIN must be a FrontendPlugin subclass, "
|
|
167
|
+
f"got {plugin_cls!r}")
|
|
168
|
+
if plugin_cls.api_version != API_VERSION:
|
|
169
|
+
raise _plugin_load_error(
|
|
170
|
+
f"plugin {plugin_cls.name!r} declares api_version="
|
|
171
|
+
f"{plugin_cls.api_version}; compiler supports {API_VERSION}")
|
|
172
|
+
return plugin_cls
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def load_plugin(spec: str, options: dict[str, str]) -> FrontendPlugin:
|
|
176
|
+
"""Resolve the plugin class and instantiate it with `options`.
|
|
177
|
+
Equivalent to `resolve_plugin_class(spec)(options)`; kept for
|
|
178
|
+
callers that don't need to inspect the class before
|
|
179
|
+
construction.
|
|
180
|
+
"""
|
|
181
|
+
return resolve_plugin_class(spec)(options)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def route_dsl_opts(
|
|
185
|
+
flags: Iterable[str], known_plugin_names: Iterable[str],
|
|
186
|
+
) -> dict[str, dict[str, str]]:
|
|
187
|
+
"""Split `--dsl-opt name.key=value` strings into per-plugin dicts.
|
|
188
|
+
|
|
189
|
+
Returns `{plugin_name: {key: value, ...}}`. Raises FrontendPluginError
|
|
190
|
+
when an option does not match `name.key=value` or `name` is not a
|
|
191
|
+
registered plugin.
|
|
192
|
+
"""
|
|
193
|
+
known = set(known_plugin_names)
|
|
194
|
+
out: dict[str, dict[str, str]] = {n: {} for n in known}
|
|
195
|
+
for raw in flags:
|
|
196
|
+
if "=" not in raw or "." not in raw.split("=", 1)[0]:
|
|
197
|
+
raise _plugin_load_error(
|
|
198
|
+
f"--dsl-opt must be 'name.key=value'; got {raw!r}")
|
|
199
|
+
head, value = raw.split("=", 1)
|
|
200
|
+
name, key = head.split(".", 1)
|
|
201
|
+
if name not in known:
|
|
202
|
+
raise _plugin_load_error(
|
|
203
|
+
f"--dsl-opt {raw!r}: no plugin named {name!r}")
|
|
204
|
+
out[name][key] = value
|
|
205
|
+
return out
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def _plugin_load_error(msg: str) -> FrontendPluginError:
|
|
209
|
+
return FrontendPluginError(Diagnostic(level=DiagnosticLevel.ERROR, message=msg))
|
tpyc/install_docs.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Install TurboPython agent docs into a target project."""
|
|
2
|
+
|
|
3
|
+
import io
|
|
4
|
+
from contextlib import redirect_stdout
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
import shutil
|
|
7
|
+
|
|
8
|
+
from . import get_docs_dir
|
|
9
|
+
from .dump_types import dump_builtin_types
|
|
10
|
+
|
|
11
|
+
# (source name in wheel/repo, target name in user project)
|
|
12
|
+
# In dev layout, get_docs_dir() resolves to the repo's docs/ which contains
|
|
13
|
+
# more files than we ship -- we iterate this explicit allowlist to avoid
|
|
14
|
+
# copying design docs.
|
|
15
|
+
_DOC_FILES: list[tuple[str, str]] = [
|
|
16
|
+
("TPY_FOR_AGENTS.md", "TPY_FOR_AGENTS.md"),
|
|
17
|
+
("LANGUAGE_FEATURES.md", "TPY_LANGUAGE_FEATURES.md"),
|
|
18
|
+
("STDLIB_ROADMAP.md", "TPY_STDLIB_ROADMAP.md"),
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
_API_REFERENCE_FILENAME = "TPY_API_REFERENCE.md"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def install_agent_docs(target_dir: Path) -> list[Path]:
|
|
25
|
+
"""Copy agent docs into target_dir, overwriting any existing copies.
|
|
26
|
+
|
|
27
|
+
Creates target_dir if missing. Returns the list of written paths.
|
|
28
|
+
Raises NotADirectoryError if target_dir exists as a regular file.
|
|
29
|
+
"""
|
|
30
|
+
if target_dir.exists() and not target_dir.is_dir():
|
|
31
|
+
raise NotADirectoryError(
|
|
32
|
+
f"Cannot install agent docs into {target_dir}: "
|
|
33
|
+
f"path exists and is not a directory"
|
|
34
|
+
)
|
|
35
|
+
target_dir.mkdir(parents=True, exist_ok=True)
|
|
36
|
+
src = get_docs_dir()
|
|
37
|
+
written: list[Path] = []
|
|
38
|
+
for src_name, dst_name in _DOC_FILES:
|
|
39
|
+
dst = target_dir / dst_name
|
|
40
|
+
shutil.copyfile(src / src_name, dst)
|
|
41
|
+
written.append(dst)
|
|
42
|
+
|
|
43
|
+
# Generated reference: API surface reflected from the installed stubs.
|
|
44
|
+
buf = io.StringIO()
|
|
45
|
+
with redirect_stdout(buf):
|
|
46
|
+
dump_builtin_types()
|
|
47
|
+
dst = target_dir / _API_REFERENCE_FILENAME
|
|
48
|
+
dst.write_text(buf.getvalue(), encoding="utf-8")
|
|
49
|
+
written.append(dst)
|
|
50
|
+
|
|
51
|
+
return written
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def agents_md_snippet(target_dir: Path) -> str:
|
|
55
|
+
"""Return the copy-pasteable section to append to AGENTS.md/CLAUDE.md.
|
|
56
|
+
|
|
57
|
+
target_dir should be the path as the user typed it (typically relative),
|
|
58
|
+
so the snippet references paths that make sense in the user's project.
|
|
59
|
+
"""
|
|
60
|
+
path_prefix = target_dir.as_posix().rstrip("/")
|
|
61
|
+
return f"""\
|
|
62
|
+
## TurboPython (TPy) documentation
|
|
63
|
+
|
|
64
|
+
This project uses TurboPython (tpyc) to compile Python source to C++.
|
|
65
|
+
When writing or modifying `.py` files compiled by tpyc:
|
|
66
|
+
|
|
67
|
+
- Start with `{path_prefix}/TPY_FOR_AGENTS.md` -- concise bootstrap
|
|
68
|
+
covering the Python-to-TPy delta, ownership rules, and idiomatic
|
|
69
|
+
patterns. Read this before writing TPy code.
|
|
70
|
+
- Consult `{path_prefix}/TPY_LANGUAGE_FEATURES.md` for depth on specific
|
|
71
|
+
features. Only sections marked **Working** are usable today.
|
|
72
|
+
- Check `{path_prefix}/TPY_STDLIB_ROADMAP.md` before using a Python stdlib
|
|
73
|
+
module -- coverage is partial and some modules are missing or blocked.
|
|
74
|
+
- Look up concrete API surface in `{path_prefix}/TPY_API_REFERENCE.md` --
|
|
75
|
+
auto-generated from the installed stubs (builtins, `tplib.*`, and
|
|
76
|
+
bundled stdlib modules). Reflects exactly what's callable in this
|
|
77
|
+
version, with signatures and methods.
|
|
78
|
+
|
|
79
|
+
These files are bundled from the installed tpyc toolchain. Refresh with
|
|
80
|
+
`tpyc --install-agent-docs {path_prefix}` after upgrading tpyc.
|
|
81
|
+
"""
|