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,173 @@
|
|
|
1
|
+
# tpy: cpp_namespace("tpystd::_bindings::pcre2")
|
|
2
|
+
# tpy: include("<tpy/stdlib/pcre2_h.hpp>")
|
|
3
|
+
# tpy: link("pcre2", managed=True)
|
|
4
|
+
"""Raw PCRE2 C bindings.
|
|
5
|
+
|
|
6
|
+
One @native declaration per pcre2_*_8 primitive, matching the upstream C
|
|
7
|
+
ABI 1:1. No Python semantics.
|
|
8
|
+
Consumers (the public `re` facade) build user-visible Pattern / Match
|
|
9
|
+
classes on top of these raw handles, using __del__ for RAII over the
|
|
10
|
+
opaque pcre2_code* / pcre2_match_data* lifetimes.
|
|
11
|
+
|
|
12
|
+
Naming:
|
|
13
|
+
- Opaque type markers: `Code`, `MatchData`, `MatchContext`. The TPy-level
|
|
14
|
+
handle is `Ptr[Code]` etc., which codegens to `pcre2_code_8*`.
|
|
15
|
+
- All function names mirror the PCRE2 C names with the `_8` suffix dropped.
|
|
16
|
+
|
|
17
|
+
Constants are hardcoded UInt32 values matching pcre2.h. PCRE2's flag values
|
|
18
|
+
are part of its public ABI and don't change between versions.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from typing import Final
|
|
22
|
+
from tpy import Ptr, UInt8, UInt32, UInt64, Int32, readonly
|
|
23
|
+
from tpy.extern import native
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# ---------- Opaque type markers ----------
|
|
27
|
+
# Never instantiated directly; only passed/returned as `Ptr[X]`. The empty
|
|
28
|
+
# native class binds the C struct name so `Ptr[Code]` becomes `pcre2_code_8*`
|
|
29
|
+
# -- declared as a global-scope forward struct + alias in
|
|
30
|
+
# `runtime/cpp/include/tpy/stdlib/pcre2_h.hpp` (matches upstream pcre2.h
|
|
31
|
+
# layout; the real struct definitions live in PCRE2's own .c files).
|
|
32
|
+
|
|
33
|
+
@native("::pcre2_code_8")
|
|
34
|
+
class Code: ...
|
|
35
|
+
|
|
36
|
+
@native("::pcre2_match_data_8")
|
|
37
|
+
class MatchData: ...
|
|
38
|
+
|
|
39
|
+
@native("::pcre2_match_context_8")
|
|
40
|
+
class MatchContext: ...
|
|
41
|
+
|
|
42
|
+
# Context types we never construct -- passed as bare `Ptr[...]` to the
|
|
43
|
+
# PCRE2 functions that accept an optional context override. Caller always
|
|
44
|
+
# passes `None` (= default contexts; `Ptr[T]` is already nullable).
|
|
45
|
+
@native("::pcre2_compile_context_8")
|
|
46
|
+
class CompileContext: ...
|
|
47
|
+
|
|
48
|
+
@native("::pcre2_general_context_8")
|
|
49
|
+
class GeneralContext: ...
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# ---------- Compile / match flags (subset we actually use) ----------
|
|
53
|
+
# Names mirror upstream pcre2.h exactly. Safe because pcre2.h is never
|
|
54
|
+
# included in our generated TUs (see runtime/cpp/include/tpy/stdlib/pcre2_h.hpp
|
|
55
|
+
# header comment) -- the preprocessor never sees a `#define PCRE2_CASELESS`
|
|
56
|
+
# in the same TU as our constant declaration. Values are part of PCRE2's
|
|
57
|
+
# stable ABI.
|
|
58
|
+
|
|
59
|
+
PCRE2_CASELESS: Final[UInt32] = 0x00000008
|
|
60
|
+
PCRE2_MULTILINE: Final[UInt32] = 0x00000400
|
|
61
|
+
PCRE2_DOTALL: Final[UInt32] = 0x00000020
|
|
62
|
+
PCRE2_EXTENDED: Final[UInt32] = 0x00000080
|
|
63
|
+
PCRE2_UTF: Final[UInt32] = 0x00080000
|
|
64
|
+
PCRE2_UCP: Final[UInt32] = 0x00020000
|
|
65
|
+
PCRE2_ANCHORED: Final[UInt32] = 0x80000000
|
|
66
|
+
PCRE2_ENDANCHORED: Final[UInt32] = 0x20000000
|
|
67
|
+
|
|
68
|
+
# Match-step option for pcre2_substitute.
|
|
69
|
+
PCRE2_SUBSTITUTE_GLOBAL: Final[UInt32] = 0x00000100
|
|
70
|
+
PCRE2_SUBSTITUTE_OVERFLOW_LENGTH: Final[UInt32] = 0x00001000
|
|
71
|
+
|
|
72
|
+
# pcre2_jit_compile selector: full JIT for normal matching.
|
|
73
|
+
PCRE2_JIT_COMPLETE: Final[UInt32] = 0x00000001
|
|
74
|
+
|
|
75
|
+
# Pattern-info selectors for pcre2_pattern_info.
|
|
76
|
+
PCRE2_INFO_CAPTURECOUNT: Final[UInt32] = 4
|
|
77
|
+
|
|
78
|
+
# pcre2_match return codes. NOMATCH means "no match" (not an error);
|
|
79
|
+
# NOMEMORY is returned by pcre2_substitute when the output buffer is
|
|
80
|
+
# too small AND PCRE2_SUBSTITUTE_OVERFLOW_LENGTH is set.
|
|
81
|
+
PCRE2_ERROR_NOMATCH: Final[Int32] = -1
|
|
82
|
+
PCRE2_ERROR_NOMEMORY: Final[Int32] = -48
|
|
83
|
+
|
|
84
|
+
# Sentinel meaning "this group did not participate". PCRE2_UNSET is
|
|
85
|
+
# (PCRE2_SIZE)~0u = SIZE_MAX in C; we compare against it via raw uint64.
|
|
86
|
+
PCRE2_UNSET: Final[UInt64] = 0xFFFFFFFFFFFFFFFF
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# ---------- Compile / free ----------
|
|
90
|
+
# Every binding below is a pure `@native` 1:1 mirror of PCRE2's C ABI.
|
|
91
|
+
# Arguments match pcre2.h exactly. Context-pointer args
|
|
92
|
+
# (pcre2_compile_context*, pcre2_general_context*, etc.) are typed as
|
|
93
|
+
# bare `Ptr[X]`; callers pass `None` (codegens to `nullptr`).
|
|
94
|
+
|
|
95
|
+
@native("::pcre2_compile_8")
|
|
96
|
+
def compile(pattern_data: Ptr[readonly[UInt8]], pattern_len: UInt64,
|
|
97
|
+
flags: UInt32,
|
|
98
|
+
errcode_out: Ptr[Int32], erroff_out: Ptr[UInt64],
|
|
99
|
+
ccontext: Ptr[CompileContext]) -> Ptr[Code]: ...
|
|
100
|
+
|
|
101
|
+
@native("::pcre2_code_free_8")
|
|
102
|
+
def code_free(code: Ptr[Code]) -> None: ...
|
|
103
|
+
|
|
104
|
+
@native("::pcre2_jit_compile_8")
|
|
105
|
+
def jit_compile(code: Ptr[Code], opts: UInt32) -> Int32: ...
|
|
106
|
+
|
|
107
|
+
# Render a PCRE2 numeric error into a human-readable message. Writes into
|
|
108
|
+
# the caller-provided buffer and returns the number of bytes written
|
|
109
|
+
# (negative on error). `PCRE2_UCHAR8` is `uint8_t` -- same as `Ptr[UInt8]`'s
|
|
110
|
+
# underlying C type, so no cast needed.
|
|
111
|
+
@native("::pcre2_get_error_message_8")
|
|
112
|
+
def get_error_message(errcode: Int32, buf: Ptr[UInt8], buflen: UInt64) -> Int32: ...
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
# ---------- Match contexts and match-data blocks ----------
|
|
116
|
+
|
|
117
|
+
@native("::pcre2_match_context_create_8")
|
|
118
|
+
def match_context_create(
|
|
119
|
+
gcontext: Ptr[GeneralContext]) -> Ptr[MatchContext]: ...
|
|
120
|
+
|
|
121
|
+
@native("::pcre2_match_context_free_8")
|
|
122
|
+
def match_context_free(mctx: Ptr[MatchContext]) -> None: ...
|
|
123
|
+
|
|
124
|
+
@native("::pcre2_match_data_create_from_pattern_8")
|
|
125
|
+
def match_data_create_from_pattern(
|
|
126
|
+
code: Ptr[Code],
|
|
127
|
+
gcontext: Ptr[GeneralContext]) -> Ptr[MatchData]: ...
|
|
128
|
+
|
|
129
|
+
@native("::pcre2_match_data_free_8")
|
|
130
|
+
def match_data_free(md: Ptr[MatchData]) -> None: ...
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# ---------- Matching ----------
|
|
134
|
+
|
|
135
|
+
# pcre2_match returns >0 on success (count of matched groups including
|
|
136
|
+
# group 0), 0 if the ovector was too small (we always size correctly via
|
|
137
|
+
# match_data_create_from_pattern), or negative on no-match / error.
|
|
138
|
+
@native("::pcre2_match_8")
|
|
139
|
+
def match(code: Ptr[Code],
|
|
140
|
+
subject_data: Ptr[readonly[UInt8]], subject_len: UInt64,
|
|
141
|
+
start_offset: UInt64, opts: UInt32,
|
|
142
|
+
md: Ptr[MatchData], mctx: Ptr[MatchContext]) -> Int32: ...
|
|
143
|
+
|
|
144
|
+
# Returns Ptr[UInt64] -- pointer into the match-data block holding the
|
|
145
|
+
# ovector (pairs of (start, end) byte offsets, length 2*group_count).
|
|
146
|
+
@native("::pcre2_get_ovector_pointer_8")
|
|
147
|
+
def get_ovector_pointer(md: Ptr[MatchData]) -> Ptr[readonly[UInt64]]: ...
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
# ---------- Pattern info ----------
|
|
151
|
+
|
|
152
|
+
# pcre2_pattern_info(code, what, where) -- writes the requested info into
|
|
153
|
+
# `where` (typed appropriately for the selector). We only use it to fetch
|
|
154
|
+
# the capture count (uint32_t).
|
|
155
|
+
@native("::pcre2_pattern_info_8")
|
|
156
|
+
def pattern_info_u32(code: Ptr[Code], what: UInt32, out: Ptr[UInt32]) -> Int32: ...
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
# ---------- Substitution ----------
|
|
160
|
+
|
|
161
|
+
# pcre2_substitute writes the result into a caller-provided UCHAR buffer.
|
|
162
|
+
# If the buffer is too small AND PCRE2_SUBSTITUTE_OVERFLOW_LENGTH is set,
|
|
163
|
+
# *outlen is updated to the size needed and PCRE2_ERROR_NOMEMORY returned;
|
|
164
|
+
# the caller can resize and retry. `mcache` is an optional match_data cache
|
|
165
|
+
# we don't use -- pass None.
|
|
166
|
+
@native("::pcre2_substitute_8")
|
|
167
|
+
def substitute(code: Ptr[Code],
|
|
168
|
+
subject_data: Ptr[readonly[UInt8]], subject_len: UInt64,
|
|
169
|
+
start_offset: UInt64, opts: UInt32,
|
|
170
|
+
mcache: Ptr[MatchData],
|
|
171
|
+
mctx: Ptr[MatchContext],
|
|
172
|
+
repl_data: Ptr[readonly[UInt8]], repl_len: UInt64,
|
|
173
|
+
outbuf: Ptr[UInt8], outlen_inout: Ptr[UInt64]) -> Int32: ...
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# tpy: native_module
|
|
2
|
+
# tpy: cpp_namespace("tpystd::_bindings::posix_socket")
|
|
3
|
+
# tpy: include("<tpy/stdlib/socket_h.hpp>")
|
|
4
|
+
"""Raw POSIX-sockets C bindings.
|
|
5
|
+
|
|
6
|
+
Thin @native layer over libc's `socket`, `bind`, `connect`, ..., plus
|
|
7
|
+
three out-of-line helpers from runtime/cpp/src/stdlib/socket_impl.cpp
|
|
8
|
+
(DNS resolution, errno access, last-resolve-error). One declaration per
|
|
9
|
+
primitive, matching the C ABI 1:1 -- no Python semantics.
|
|
10
|
+
|
|
11
|
+
Consumers (the public `socket` facade) build Socket / SocketError classes
|
|
12
|
+
on top of these raw handles, using __del__ for RAII over file descriptors.
|
|
13
|
+
|
|
14
|
+
Naming:
|
|
15
|
+
* `SockaddrIn` -- @native(binding="C") struct aliased to `sockaddr_in`.
|
|
16
|
+
Fields match POSIX layout (16 bytes total); safe across Linux, *BSD,
|
|
17
|
+
macOS. IPv6 (`sockaddr_in6`) is a separate struct, deferred.
|
|
18
|
+
* All function names mirror their libc counterparts.
|
|
19
|
+
* Wire values (AF_INET etc.) live in the public `socket` facade, not
|
|
20
|
+
here -- posix_socket.py is declaration-only.
|
|
21
|
+
|
|
22
|
+
The `# tpy: native_module` directive means no .cpp/.hpp is generated for
|
|
23
|
+
this module itself; its @native bindings resolve at link time to symbols
|
|
24
|
+
in libc (for the socket/bind/... set) and in socket_impl.cpp (for the
|
|
25
|
+
tpy_* set).
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from tpy import Int32, UInt8, UInt16, UInt32, UInt64, Int64, Ptr, readonly
|
|
29
|
+
from tpy.extern import native
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# ---------- sockaddr_in (POSIX-stable 16-byte layout) ----------
|
|
33
|
+
# Mirror of the `struct sockaddr_in` declaration in socket_h.hpp. TPy-side
|
|
34
|
+
# field access codegens to normal C struct field access; no unsafe_load
|
|
35
|
+
# is needed. Constants for sin_family / sin_port / sin_addr are built by
|
|
36
|
+
# the caller using htons() + tpy_resolve_ipv4() + the AF_* values in the
|
|
37
|
+
# public `socket` facade.
|
|
38
|
+
@native("sockaddr_in", binding="C")
|
|
39
|
+
class SockaddrIn:
|
|
40
|
+
sin_family: UInt16
|
|
41
|
+
sin_port: UInt16
|
|
42
|
+
sin_addr: UInt32
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# ---------- Socket lifecycle ----------
|
|
46
|
+
|
|
47
|
+
# All @native names below use a leading `::` to bind to libc's global
|
|
48
|
+
# symbols (`::socket`, `::bind`, ...). Without the `::` prefix, the rename
|
|
49
|
+
# would be treated as relative to this module's `cpp_namespace` and emit
|
|
50
|
+
# `::tpystd::_bindings::posix_socket::socket` -- no such symbol. Absolute
|
|
51
|
+
# renames (containing `::` anywhere in the string) opt out of the
|
|
52
|
+
# namespace prefix, which is what we want for libc bindings.
|
|
53
|
+
|
|
54
|
+
@native("::socket")
|
|
55
|
+
def socket(domain: Int32, type_: Int32, protocol: Int32) -> Int32: ...
|
|
56
|
+
|
|
57
|
+
@native("::close")
|
|
58
|
+
def close(fd: Int32) -> Int32: ...
|
|
59
|
+
|
|
60
|
+
@native("::shutdown")
|
|
61
|
+
def shutdown(fd: Int32, how: Int32) -> Int32: ...
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# ---------- Address binding + connection setup ----------
|
|
65
|
+
|
|
66
|
+
@native("::bind")
|
|
67
|
+
def bind(fd: Int32, addr: Ptr[SockaddrIn], addrlen: UInt32) -> Int32: ...
|
|
68
|
+
|
|
69
|
+
@native("::connect")
|
|
70
|
+
def connect(fd: Int32, addr: Ptr[SockaddrIn], addrlen: UInt32) -> Int32: ...
|
|
71
|
+
|
|
72
|
+
@native("::listen")
|
|
73
|
+
def listen(fd: Int32, backlog: Int32) -> Int32: ...
|
|
74
|
+
|
|
75
|
+
@native("::accept")
|
|
76
|
+
def accept(fd: Int32, addr: Ptr[SockaddrIn], addrlen: Ptr[UInt32]) -> Int32: ...
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# ---------- Data transfer ----------
|
|
80
|
+
# send/recv return ssize_t (= long on 64-bit *nix). Negative means error;
|
|
81
|
+
# 0 from recv means peer closed (orderly shutdown).
|
|
82
|
+
|
|
83
|
+
@native("::send")
|
|
84
|
+
def send(fd: Int32, buf: Ptr[readonly[UInt8]], len_: UInt64, flags: Int32) -> Int64: ...
|
|
85
|
+
|
|
86
|
+
@native("::recv")
|
|
87
|
+
def recv(fd: Int32, buf: Ptr[UInt8], len_: UInt64, flags: Int32) -> Int64: ...
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
# ---------- Options + introspection ----------
|
|
91
|
+
# setsockopt's `optval` is polymorphic (int* for boolean-style opts,
|
|
92
|
+
# struct timeval* for timeouts, etc.). Phase 1 only exposes int-valued
|
|
93
|
+
# options; broader shapes arrive with SO_RCVTIMEO / SO_LINGER support.
|
|
94
|
+
|
|
95
|
+
@native("::setsockopt")
|
|
96
|
+
def setsockopt(fd: Int32, level: Int32, optname: Int32,
|
|
97
|
+
optval: Ptr[readonly[Int32]], optlen: UInt32) -> Int32: ...
|
|
98
|
+
|
|
99
|
+
@native("::getsockname")
|
|
100
|
+
def getsockname(fd: Int32, addr: Ptr[SockaddrIn], addrlen: Ptr[UInt32]) -> Int32: ...
|
|
101
|
+
|
|
102
|
+
@native("::getpeername")
|
|
103
|
+
def getpeername(fd: Int32, addr: Ptr[SockaddrIn], addrlen: Ptr[UInt32]) -> Int32: ...
|
|
104
|
+
|
|
105
|
+
@native("::socketpair")
|
|
106
|
+
def socketpair(domain: Int32, type_: Int32, protocol: Int32,
|
|
107
|
+
sv: Ptr[Int32]) -> Int32: ...
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
# ---------- Byte-order + address conversion ----------
|
|
111
|
+
|
|
112
|
+
@native("::htons")
|
|
113
|
+
def htons(hostshort: UInt16) -> UInt16: ...
|
|
114
|
+
|
|
115
|
+
@native("::ntohs")
|
|
116
|
+
def ntohs(netshort: UInt16) -> UInt16: ...
|
|
117
|
+
|
|
118
|
+
# inet_pton writes the binary form (4 bytes for AF_INET) into `dst`.
|
|
119
|
+
# Returns 1 on success, 0 for bad format, -1 for unsupported family.
|
|
120
|
+
@native("::inet_pton")
|
|
121
|
+
def inet_pton(af: Int32, src: Ptr[readonly[UInt8]], dst: Ptr[UInt8]) -> Int32: ...
|
|
122
|
+
|
|
123
|
+
# inet_ntop writes the text form into `dst` and returns a pointer into it
|
|
124
|
+
# on success, NULL on error. We accept the non-null-terminated return
|
|
125
|
+
# semantics implicitly by copying via dst's span.
|
|
126
|
+
@native("::inet_ntop")
|
|
127
|
+
def inet_ntop(af: Int32, src: Ptr[readonly[UInt8]],
|
|
128
|
+
dst: Ptr[UInt8], size: UInt32) -> Ptr[UInt8]: ...
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# ---------- TPy runtime helpers (socket_impl.cpp) ----------
|
|
132
|
+
|
|
133
|
+
# Resolve `host` (first `host_len` bytes, not required null-terminated) to
|
|
134
|
+
# a single IPv4 address via getaddrinfo. Writes 4 network-byte-order bytes
|
|
135
|
+
# to `out`. Returns 0 on success, -1 on failure; caller reads
|
|
136
|
+
# tpy_last_resolve_error for a human message on failure.
|
|
137
|
+
@native("::tpy_resolve_ipv4")
|
|
138
|
+
def tpy_resolve_ipv4(host: Ptr[readonly[UInt8]], host_len: UInt64,
|
|
139
|
+
out: Ptr[UInt8]) -> Int32: ...
|
|
140
|
+
|
|
141
|
+
# errno at the point of call. Indirection for platform portability
|
|
142
|
+
# (glibc uses __errno_location, macOS uses __error).
|
|
143
|
+
@native("::tpy_errno")
|
|
144
|
+
def tpy_errno() -> Int32: ...
|
|
145
|
+
|
|
146
|
+
# Last DNS-resolution error message (thread-local, C string, valid until
|
|
147
|
+
# the next tpy_resolve_ipv4 call on this thread). readonly because the
|
|
148
|
+
# C signature is `const char*` -- callers must not mutate the buffer.
|
|
149
|
+
@native("::tpy_last_resolve_error")
|
|
150
|
+
def tpy_last_resolve_error() -> Ptr[readonly[UInt8]]: ...
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
# ---------- Raw libc strerror ----------
|
|
154
|
+
# Returns a human-readable description of `errnum`. Null-terminated C
|
|
155
|
+
# string; caller wraps it in a TPy `str` via the usual ptr+length walk.
|
|
156
|
+
# No `# tpy: include` needed for this -- <cstring> is transitively pulled
|
|
157
|
+
# in via tpy.hpp, which declares `char* strerror(int)`. uint8_t* return
|
|
158
|
+
# matches TPy's byte-buffer convention; ABI is identical. readonly because
|
|
159
|
+
# libc's strerror buffer is thread-local / shared and must not be written.
|
|
160
|
+
@native("::strerror")
|
|
161
|
+
def strerror(errnum: Int32) -> Ptr[readonly[UInt8]]: ...
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# tpy: macro_module
|
|
2
|
+
"""Compile-time class macros for `functools`.
|
|
3
|
+
|
|
4
|
+
Hosts `@total_ordering`; the runtime helpers (`reduce`, etc.) live
|
|
5
|
+
in `lib/tpy/functools.py`. The split exists because TPy modules
|
|
6
|
+
cannot mix `# tpy: macro_module` with runtime functions that
|
|
7
|
+
compile to C++.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from tpyc.macro_api import ClassInfo, MacroError, class_macro, ast, types
|
|
11
|
+
from _macro_helpers import ORDER_DUNDERS, ORDER_DUNDER_OPS
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
_ANCHOR_TO_OP = dict(zip(ORDER_DUNDERS, ORDER_DUNDER_OPS))
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# (anchor, missing_op) -> builder taking `(sa, eq)` where
|
|
18
|
+
# `sa = self <anchor_op> other` and `eq = self == other`.
|
|
19
|
+
# Each pair has one canonical derivation; `__lt__` and `__gt__`
|
|
20
|
+
# (likewise `__le__` and `__ge__`) share formulas because each
|
|
21
|
+
# strict / weak inequality lets us derive its mirror identically.
|
|
22
|
+
_DERIVATIONS = {
|
|
23
|
+
("__lt__", "__gt__"): lambda sa, eq: ast.unary("!", ast.binop(sa, "||", eq)),
|
|
24
|
+
("__lt__", "__le__"): lambda sa, eq: ast.binop(sa, "||", eq),
|
|
25
|
+
("__lt__", "__ge__"): lambda sa, eq: ast.unary("!", sa),
|
|
26
|
+
("__le__", "__ge__"): lambda sa, eq: ast.binop(ast.unary("!", sa), "||", eq),
|
|
27
|
+
("__le__", "__lt__"): lambda sa, eq: ast.binop(sa, "&&", ast.unary("!", eq)),
|
|
28
|
+
("__le__", "__gt__"): lambda sa, eq: ast.unary("!", sa),
|
|
29
|
+
("__gt__", "__lt__"): lambda sa, eq: ast.unary("!", ast.binop(sa, "||", eq)),
|
|
30
|
+
("__gt__", "__ge__"): lambda sa, eq: ast.binop(sa, "||", eq),
|
|
31
|
+
("__gt__", "__le__"): lambda sa, eq: ast.unary("!", sa),
|
|
32
|
+
("__ge__", "__le__"): lambda sa, eq: ast.binop(ast.unary("!", sa), "||", eq),
|
|
33
|
+
("__ge__", "__gt__"): lambda sa, eq: ast.binop(sa, "&&", ast.unary("!", eq)),
|
|
34
|
+
("__ge__", "__lt__"): lambda sa, eq: ast.unary("!", sa),
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _build_body(anchor: str, op_name: str):
|
|
39
|
+
s = ast.name("self")
|
|
40
|
+
o = ast.name("other")
|
|
41
|
+
sa = ast.binop(s, _ANCHOR_TO_OP[anchor], o)
|
|
42
|
+
eq = ast.binop(s, "==", o)
|
|
43
|
+
return _DERIVATIONS[(anchor, op_name)](sa, eq)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@class_macro
|
|
47
|
+
def total_ordering(cls: ClassInfo) -> None:
|
|
48
|
+
"""Synthesize the missing rich-comparison operators on `cls`.
|
|
49
|
+
|
|
50
|
+
Requires `__eq__` plus at least one of `__lt__` / `__le__` /
|
|
51
|
+
`__gt__` / `__ge__`. The first defined ordering op (in that
|
|
52
|
+
order) is the "anchor"; the remaining three are derived from it
|
|
53
|
+
and `__eq__`. Defers the actual synthesis so peer macros like
|
|
54
|
+
`@dataclass` (which adds `__eq__`) compose regardless of
|
|
55
|
+
decorator order.
|
|
56
|
+
"""
|
|
57
|
+
cls.defer_until_macros_complete(_apply_total_ordering)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _apply_total_ordering(cls: ClassInfo) -> None:
|
|
61
|
+
if not cls.has_method_or_inherited("__eq__"):
|
|
62
|
+
raise MacroError(
|
|
63
|
+
f"@total_ordering requires {cls.name!r} to define __eq__"
|
|
64
|
+
)
|
|
65
|
+
defined = [name for name in ORDER_DUNDERS if cls.has_method_or_inherited(name)]
|
|
66
|
+
if not defined:
|
|
67
|
+
raise MacroError(
|
|
68
|
+
f"@total_ordering requires {cls.name!r} to define one of "
|
|
69
|
+
f"__lt__, __le__, __gt__, __ge__"
|
|
70
|
+
)
|
|
71
|
+
anchor = defined[0]
|
|
72
|
+
other_type = types.named(cls.name)
|
|
73
|
+
for op_name in ORDER_DUNDERS:
|
|
74
|
+
if op_name == anchor or cls.has_method_or_inherited(op_name):
|
|
75
|
+
continue
|
|
76
|
+
cls.add_method(ast.function(
|
|
77
|
+
op_name, [("other", other_type)], types.bool,
|
|
78
|
+
[ast.return_(_build_body(anchor, op_name))],
|
|
79
|
+
is_method=True, is_readonly=True,
|
|
80
|
+
))
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# tpy: macro_module
|
|
2
|
+
"""Shared helpers for TurboPython macro modules.
|
|
3
|
+
|
|
4
|
+
Provides build_* functions for synthesizing common dunder methods
|
|
5
|
+
(__init__, __eq__, __repr__, __hash__, ordering). Used by @dataclass,
|
|
6
|
+
@model, and other class macros.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from tpyc.macro_api import (
|
|
10
|
+
ClassInfo, FieldInfo, ast, types, Expr, Stmt, Function, Type,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Rich-comparison dunders in CPython's documented anchor-priority
|
|
15
|
+
# order, paired with the corresponding binary operator. Used by
|
|
16
|
+
# `build_order` (synthesize all four for `@dataclass(order=True)`)
|
|
17
|
+
# and `@total_ordering` (pick the first defined op as anchor).
|
|
18
|
+
ORDER_DUNDERS = ("__lt__", "__le__", "__gt__", "__ge__")
|
|
19
|
+
ORDER_DUNDER_OPS = ("<", "<=", ">", ">=")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def build_init(
|
|
23
|
+
cls: ClassInfo,
|
|
24
|
+
parent_fields: list[FieldInfo],
|
|
25
|
+
own_fields: list[FieldInfo],
|
|
26
|
+
) -> Function:
|
|
27
|
+
"""Build a synthetic __init__ method from field lists."""
|
|
28
|
+
params: list[tuple[str, Type]] = []
|
|
29
|
+
defaults: list[Expr | None] = []
|
|
30
|
+
body: list[Stmt] = []
|
|
31
|
+
|
|
32
|
+
# Parent fields come first; forwarded via super().__init__()
|
|
33
|
+
for fld in parent_fields:
|
|
34
|
+
param_type = fld.type.raw_type
|
|
35
|
+
if not param_type.is_value_type():
|
|
36
|
+
param_type = types.own(param_type)
|
|
37
|
+
params.append((fld.name, param_type))
|
|
38
|
+
defaults.append(fld.default_expr)
|
|
39
|
+
|
|
40
|
+
if parent_fields:
|
|
41
|
+
super_args = [ast.name(fld.name) for fld in parent_fields]
|
|
42
|
+
super_call = ast.method_call(
|
|
43
|
+
ast.call("super"), "__init__", super_args,
|
|
44
|
+
)
|
|
45
|
+
body.append(ast.expr_stmt(super_call))
|
|
46
|
+
|
|
47
|
+
# Own fields
|
|
48
|
+
for fld in own_fields:
|
|
49
|
+
param_type = fld.type.raw_type
|
|
50
|
+
if not param_type.is_value_type():
|
|
51
|
+
param_type = types.own(param_type)
|
|
52
|
+
params.append((fld.name, param_type))
|
|
53
|
+
defaults.append(fld.default_expr)
|
|
54
|
+
body.append(ast.assign(
|
|
55
|
+
ast.field_access(ast.name("self"), fld.name),
|
|
56
|
+
ast.name(fld.name),
|
|
57
|
+
))
|
|
58
|
+
|
|
59
|
+
return ast.function(
|
|
60
|
+
"__init__", params, types.void, body,
|
|
61
|
+
is_method=True, defaults=defaults,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def build_eq(cls: ClassInfo, all_fields: list[FieldInfo]) -> Function:
|
|
66
|
+
"""Build a synthetic __eq__ method from field list."""
|
|
67
|
+
other_type = types.named(cls.name)
|
|
68
|
+
comparisons = [
|
|
69
|
+
ast.binop(
|
|
70
|
+
ast.field_access(ast.name("self"), fld.name),
|
|
71
|
+
"==",
|
|
72
|
+
ast.field_access(ast.name("other"), fld.name),
|
|
73
|
+
)
|
|
74
|
+
for fld in all_fields
|
|
75
|
+
]
|
|
76
|
+
if not comparisons:
|
|
77
|
+
return ast.function(
|
|
78
|
+
"__eq__", [("other", other_type)], types.bool, [ast.return_(ast.bool_lit(True))],
|
|
79
|
+
is_method=True,
|
|
80
|
+
)
|
|
81
|
+
eq_expr: Expr = comparisons[0]
|
|
82
|
+
for cmp in comparisons[1:]:
|
|
83
|
+
eq_expr = ast.binop(eq_expr, "&&", cmp)
|
|
84
|
+
|
|
85
|
+
return ast.function(
|
|
86
|
+
"__eq__", [("other", other_type)], types.bool, [ast.return_(eq_expr)],
|
|
87
|
+
is_method=True,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def build_repr(cls: ClassInfo, all_fields: list[FieldInfo]) -> Function:
|
|
92
|
+
"""Build a synthetic __repr__ method from field list.
|
|
93
|
+
|
|
94
|
+
Generates: f"ClassName(field1={repr(self.field1)}, field2={repr(self.field2)})"
|
|
95
|
+
"""
|
|
96
|
+
parts = ", ".join(
|
|
97
|
+
f"{fld.name}={{repr(self.{fld.name})}}" for fld in all_fields
|
|
98
|
+
)
|
|
99
|
+
source = f'f"{cls.name}({parts})"'
|
|
100
|
+
return ast.function(
|
|
101
|
+
"__repr__", [], types.str,
|
|
102
|
+
[ast.return_(ast.quote_expr(source))],
|
|
103
|
+
is_method=True, is_readonly=True,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def build_hash(cls: ClassInfo, all_fields: list[FieldInfo]) -> Function:
|
|
108
|
+
"""Build a synthetic __hash__ method from field list.
|
|
109
|
+
|
|
110
|
+
XORs hash(field) values. Simple but has known weaknesses (symmetric
|
|
111
|
+
collisions, self-cancellation). Good enough until tuple hashing lands,
|
|
112
|
+
at which point this becomes hash((self.f1, self.f2, ...)).
|
|
113
|
+
"""
|
|
114
|
+
body: list[Stmt] = []
|
|
115
|
+
|
|
116
|
+
first = all_fields[0]
|
|
117
|
+
body.append(ast.var_decl(
|
|
118
|
+
"h", types.uint64,
|
|
119
|
+
ast.call("hash", [ast.field_access(ast.name("self"), first.name)]),
|
|
120
|
+
))
|
|
121
|
+
|
|
122
|
+
for fld in all_fields[1:]:
|
|
123
|
+
hash_call = ast.call("hash", [ast.field_access(ast.name("self"), fld.name)])
|
|
124
|
+
body.append(ast.assign(
|
|
125
|
+
ast.name("h"),
|
|
126
|
+
ast.binop(ast.name("h"), "^", hash_call),
|
|
127
|
+
))
|
|
128
|
+
|
|
129
|
+
body.append(ast.return_(ast.name("h")))
|
|
130
|
+
return ast.function(
|
|
131
|
+
"__hash__", [], types.uint64, body,
|
|
132
|
+
is_method=True, is_readonly=True,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def build_order(cls: ClassInfo, all_fields: list[FieldInfo]) -> list[Function]:
|
|
137
|
+
"""Build synthetic ordering methods (__lt__, __le__, __gt__, __ge__).
|
|
138
|
+
|
|
139
|
+
Uses field-by-field chained comparison (lexicographic order).
|
|
140
|
+
"""
|
|
141
|
+
other_type = types.named(cls.name)
|
|
142
|
+
results: list[Function] = []
|
|
143
|
+
for dunder, op in zip(ORDER_DUNDERS, ORDER_DUNDER_OPS):
|
|
144
|
+
body: list[Stmt] = []
|
|
145
|
+
for fld in all_fields[:-1]:
|
|
146
|
+
sf = ast.field_access(ast.name("self"), fld.name)
|
|
147
|
+
of = ast.field_access(ast.name("other"), fld.name)
|
|
148
|
+
body.append(ast.if_(
|
|
149
|
+
ast.binop(sf, "!=", of),
|
|
150
|
+
[ast.return_(ast.binop(sf, op, of))],
|
|
151
|
+
))
|
|
152
|
+
last = all_fields[-1]
|
|
153
|
+
sf = ast.field_access(ast.name("self"), last.name)
|
|
154
|
+
of = ast.field_access(ast.name("other"), last.name)
|
|
155
|
+
body.append(ast.return_(ast.binop(sf, op, of)))
|
|
156
|
+
|
|
157
|
+
results.append(ast.function(
|
|
158
|
+
dunder, [("other", other_type)], types.bool, body,
|
|
159
|
+
is_method=True, is_readonly=True,
|
|
160
|
+
))
|
|
161
|
+
return results
|