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,18 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TurboPython C++ Code Generator Package
|
|
3
|
+
|
|
4
|
+
Generates C++ code from the analyzed TurboPython AST:
|
|
5
|
+
- Records -> structs with constructors
|
|
6
|
+
- Functions -> free functions
|
|
7
|
+
- Protocols -> C++20 concepts
|
|
8
|
+
- Pointer field access (.) -> arrow operator (->)
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from .context import CodeGenError, CodeGenOptions
|
|
12
|
+
from .generator import CodeGenerator
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
'CodeGenerator',
|
|
16
|
+
'CodeGenError',
|
|
17
|
+
'CodeGenOptions',
|
|
18
|
+
]
|
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TurboPython Builtin Code Generation
|
|
3
|
+
|
|
4
|
+
Code generation for builtin functions, type constructors, and print().
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
from typing import TYPE_CHECKING
|
|
9
|
+
|
|
10
|
+
from ..typesys import (
|
|
11
|
+
TpyType, IntLiteralType,
|
|
12
|
+
NominalType, OptionalType, NoneType, TypeParamRef, TypeParamKind, FunctionInfo, RecordInfo,
|
|
13
|
+
ListRepeatType,
|
|
14
|
+
TupleType, OwnType, is_protocol_type, unwrap_readonly, is_any_str_type, is_any_bytes_type,
|
|
15
|
+
make_ref,
|
|
16
|
+
is_float_type, is_integer_type,
|
|
17
|
+
)
|
|
18
|
+
from ..parse import (
|
|
19
|
+
TpyExpr, TpyCall, TpyStrLiteral, TpyArrayLiteral, TpyNoneLiteral, TpyCoerce,
|
|
20
|
+
TpyBoolLiteral, TpyFieldAccess,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
from .context import escape_cpp_string, CodeGenError, expand_cpp_template, qualify_native_name, cpp_string_literal_expr
|
|
24
|
+
from ..type_def_registry import (
|
|
25
|
+
is_dict_view, is_set, is_dict, is_array, is_span, is_list,
|
|
26
|
+
is_fixed_int_type, is_big_int_type, is_bool_type, is_float32_type, is_float64_type,
|
|
27
|
+
is_bytearray_type, int_traits_of, is_enum_type, enum_info_of,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
if TYPE_CHECKING:
|
|
31
|
+
from .context import CodeGenContext
|
|
32
|
+
from .types import TypeResolver
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# float(str) special-value tokens that fold to constexpr numeric_limits at
|
|
36
|
+
# codegen, bypassing the non-constexpr runtime tpy::float_from_str. Matches
|
|
37
|
+
# CPython's case-insensitive, whitespace-trimming semantics. Note: CPython
|
|
38
|
+
# preserves the sign bit for float("-nan"), so emitting -quiet_NaN() (IEEE 754
|
|
39
|
+
# sign-bit flip) is bit-for-bit equivalent, not just functionally-isnan.
|
|
40
|
+
_FLOAT_STR_CONSTANTS: dict[str, str] = {
|
|
41
|
+
"nan": "std::numeric_limits<double>::quiet_NaN()",
|
|
42
|
+
"+nan": "std::numeric_limits<double>::quiet_NaN()",
|
|
43
|
+
"-nan": "-std::numeric_limits<double>::quiet_NaN()",
|
|
44
|
+
"inf": "std::numeric_limits<double>::infinity()",
|
|
45
|
+
"+inf": "std::numeric_limits<double>::infinity()",
|
|
46
|
+
"-inf": "-std::numeric_limits<double>::infinity()",
|
|
47
|
+
"infinity": "std::numeric_limits<double>::infinity()",
|
|
48
|
+
"+infinity": "std::numeric_limits<double>::infinity()",
|
|
49
|
+
"-infinity": "-std::numeric_limits<double>::infinity()",
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class BuiltinGenerator:
|
|
54
|
+
"""Generates C++ code for builtin functions and type constructors."""
|
|
55
|
+
|
|
56
|
+
def __init__(self, ctx: CodeGenContext, types: TypeResolver):
|
|
57
|
+
self.ctx = ctx
|
|
58
|
+
self.types = types
|
|
59
|
+
# Will be set by expressions module to avoid circular import
|
|
60
|
+
self._gen_expr = None
|
|
61
|
+
self._gen_expr_deref = None
|
|
62
|
+
self._gen_call_arg = None
|
|
63
|
+
self._get_cpp_declared_type = None
|
|
64
|
+
|
|
65
|
+
def set_expr_generator(self, gen_expr, gen_expr_deref, gen_call_arg,
|
|
66
|
+
get_cpp_declared_type):
|
|
67
|
+
"""Set expression generator functions (to break circular dependency)."""
|
|
68
|
+
self._gen_expr = gen_expr
|
|
69
|
+
self._gen_expr_deref = gen_expr_deref
|
|
70
|
+
self._gen_call_arg = gen_call_arg
|
|
71
|
+
self._get_cpp_declared_type = get_cpp_declared_type
|
|
72
|
+
|
|
73
|
+
def gen_call_from_fi(self, fi: FunctionInfo, receiver: str | None,
|
|
74
|
+
gen_args: list[str], *,
|
|
75
|
+
self_type: TpyType | None = None,
|
|
76
|
+
type_args: tuple[TpyType, ...] | None = None) -> str:
|
|
77
|
+
"""Generate a call from a resolved FunctionInfo.
|
|
78
|
+
|
|
79
|
+
Unified entry point for cpp_template, native_function, and native member calls.
|
|
80
|
+
receiver is None for free function calls (no self).
|
|
81
|
+
self_type: receiver's TpyType (for {cpp} expansion in method templates).
|
|
82
|
+
type_args: inferred type arguments paired with fi.type_params by position.
|
|
83
|
+
"""
|
|
84
|
+
if fi.cpp_template:
|
|
85
|
+
template = fi.cpp_template
|
|
86
|
+
# Substitute method-level type params
|
|
87
|
+
effective_subst: dict[str, TpyType] | None = None
|
|
88
|
+
if type_args and fi.type_params:
|
|
89
|
+
effective_subst = dict(zip(fi.type_params, type_args))
|
|
90
|
+
if effective_subst:
|
|
91
|
+
for name, typ in effective_subst.items():
|
|
92
|
+
placeholder = f"{{{name}}}"
|
|
93
|
+
if placeholder in template and hasattr(typ, "to_cpp"):
|
|
94
|
+
template = template.replace(placeholder, typ.to_cpp_stored())
|
|
95
|
+
# {cpp} substitutes the (substituted) return-type spelling.
|
|
96
|
+
# Used by free functions whose template needs the full
|
|
97
|
+
# return-type C++ shape rather than just `{T}` -- e.g.
|
|
98
|
+
# `unsafe_cast[T] -> Ptr[T]` wants `Ptr[None]` to lower to
|
|
99
|
+
# `void*` (PtrType's special-case) rather than `std::monostate*`.
|
|
100
|
+
if "{cpp}" in template and fi.return_type is not None:
|
|
101
|
+
ret_type = fi.return_type
|
|
102
|
+
if effective_subst:
|
|
103
|
+
ret_type = self.types.substitute_type_params(ret_type, effective_subst)
|
|
104
|
+
template = template.replace("{cpp}", ret_type.to_cpp())
|
|
105
|
+
if receiver is not None:
|
|
106
|
+
return expand_cpp_template(template, receiver, *gen_args,
|
|
107
|
+
self_type=self_type)
|
|
108
|
+
return template.format(*gen_args)
|
|
109
|
+
if fi.native_function and fi.native_name:
|
|
110
|
+
all_args = [receiver] + gen_args if receiver is not None else gen_args
|
|
111
|
+
return f"{qualify_native_name(fi.native_name)}({', '.join(all_args)})"
|
|
112
|
+
if fi.native_name:
|
|
113
|
+
args_str = ", ".join(gen_args)
|
|
114
|
+
if receiver is not None:
|
|
115
|
+
return f"{receiver}.{fi.native_name}({args_str})"
|
|
116
|
+
return f"{qualify_native_name(fi.native_name)}({args_str})"
|
|
117
|
+
args_str = ", ".join(gen_args)
|
|
118
|
+
if receiver is not None:
|
|
119
|
+
return f"{receiver}.{fi.name}({args_str})"
|
|
120
|
+
return f"{fi.name}({args_str})"
|
|
121
|
+
|
|
122
|
+
def get_type_method_fi(self, tpy_type: TpyType, method_name: str) -> FunctionInfo | None:
|
|
123
|
+
"""Look up a single-overload method's FunctionInfo from the registry.
|
|
124
|
+
|
|
125
|
+
Returns None for multi-overload methods (use resolved_function_info instead).
|
|
126
|
+
Falls back to dunder protocol templates for protocol types.
|
|
127
|
+
"""
|
|
128
|
+
record_info = self.ctx.analyzer.registry.get_record_for_type(tpy_type)
|
|
129
|
+
if record_info:
|
|
130
|
+
overloads = record_info.get_method_overloads(method_name)
|
|
131
|
+
if len(overloads) > 1:
|
|
132
|
+
if method_name == "__getitem__":
|
|
133
|
+
# Multi-overload __getitem__: find the integer-index overload
|
|
134
|
+
for fi in overloads:
|
|
135
|
+
if (len(fi.params) == 1
|
|
136
|
+
and is_integer_type(fi.params[0].type)
|
|
137
|
+
and (fi.cpp_template or fi.native_function or fi.native_name)):
|
|
138
|
+
return fi
|
|
139
|
+
return None
|
|
140
|
+
if method_name == "__setitem__":
|
|
141
|
+
# Multi-overload __setitem__: find the integer-index overload
|
|
142
|
+
for fi in overloads:
|
|
143
|
+
if (len(fi.params) == 2
|
|
144
|
+
and is_integer_type(fi.params[0].type)
|
|
145
|
+
and (fi.cpp_template or fi.native_function or fi.native_name)):
|
|
146
|
+
return fi
|
|
147
|
+
return None
|
|
148
|
+
raise RuntimeError(
|
|
149
|
+
f"get_type_method_fi called for multi-overload method "
|
|
150
|
+
f"'{method_name}' on {tpy_type}; use resolved_function_info instead"
|
|
151
|
+
)
|
|
152
|
+
if overloads:
|
|
153
|
+
fi = overloads[0]
|
|
154
|
+
if fi.cpp_template or fi.native_function or fi.native_name:
|
|
155
|
+
return fi
|
|
156
|
+
# Dunder protocol templates (e.g., __getitem__ -> ::tpy::__getitem__)
|
|
157
|
+
if is_protocol_type(tpy_type):
|
|
158
|
+
from ..modules import get_dunder_cpp_template
|
|
159
|
+
tmpl = get_dunder_cpp_template(method_name)
|
|
160
|
+
if tmpl:
|
|
161
|
+
from ..typesys import VOID
|
|
162
|
+
return FunctionInfo(name=method_name, params=[], return_type=VOID,
|
|
163
|
+
cpp_template=tmpl)
|
|
164
|
+
return None
|
|
165
|
+
|
|
166
|
+
def gen_method_from_function_info(self, obj: str, args: list[TpyExpr],
|
|
167
|
+
method: FunctionInfo) -> str:
|
|
168
|
+
"""Generate method call code from a FunctionInfo with pre-generated args."""
|
|
169
|
+
gen_args = [self._gen_call_arg(arg, method.params[i].type if i < len(method.params) else None,
|
|
170
|
+
inline_template=True)
|
|
171
|
+
for i, arg in enumerate(args)]
|
|
172
|
+
return self.gen_call_from_fi(method, obj, gen_args)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def _match_overload_args(self, args: list[TpyExpr],
|
|
176
|
+
overloads: list[FunctionInfo]) -> tuple[FunctionInfo, list[str]]:
|
|
177
|
+
"""Match a builtin call to an overload and generate C++ arg expressions.
|
|
178
|
+
|
|
179
|
+
Returns (matched_overload, gen_args). Raises RuntimeError if no match.
|
|
180
|
+
"""
|
|
181
|
+
arg_types = [self.ctx.get_expr_type(arg) for arg in args]
|
|
182
|
+
|
|
183
|
+
for overload in overloads:
|
|
184
|
+
if len(overload.params) != len(args):
|
|
185
|
+
continue
|
|
186
|
+
if all(self._builtin_codegen_type_matches(arg, arg_t, ptype)
|
|
187
|
+
for arg, arg_t, (_, ptype) in zip(args, arg_types, overload.params)):
|
|
188
|
+
gen_args = [self._gen_call_arg(arg, ptype, inline_template=True)
|
|
189
|
+
for arg, (_, ptype) in zip(args, overload.params)]
|
|
190
|
+
return overload, gen_args
|
|
191
|
+
|
|
192
|
+
raise RuntimeError(f"No matching overload for {overloads[0].name if overloads else '?'}")
|
|
193
|
+
|
|
194
|
+
def gen_range_args(self, expr: TpyCall) -> list[str]:
|
|
195
|
+
"""Generate individual C++ arg expressions for range().
|
|
196
|
+
|
|
197
|
+
Returns the generated arg list (e.g. ["0", "10", "2"]) rather than
|
|
198
|
+
formatting into the full template string. Used by the counter-loop
|
|
199
|
+
optimisation in statements.py.
|
|
200
|
+
"""
|
|
201
|
+
fi = expr.resolved_function_info
|
|
202
|
+
return [self._gen_expr_deref(arg, ptype)
|
|
203
|
+
for arg, (_, ptype) in zip(expr.args, fi.params)]
|
|
204
|
+
|
|
205
|
+
@staticmethod
|
|
206
|
+
def _try_float_str_fold(fi: FunctionInfo, args: list[TpyExpr]) -> str | None:
|
|
207
|
+
"""Fold `float("nan"/"inf"/"-inf"/...)` to a constexpr numeric_limits.
|
|
208
|
+
|
|
209
|
+
Returns the C++ expression string if the call resolves to the builtin
|
|
210
|
+
`float.__init__(str)` with a recognized special-value literal arg;
|
|
211
|
+
otherwise None (caller proceeds with the normal native dispatch that
|
|
212
|
+
emits `tpy::float_from_str(...)`).
|
|
213
|
+
"""
|
|
214
|
+
if not (fi.is_method and fi.name == "__init__" and len(args) == 1):
|
|
215
|
+
return None
|
|
216
|
+
if fi.owning_type_qname != "builtins.float":
|
|
217
|
+
return None
|
|
218
|
+
arg = args[0]
|
|
219
|
+
if not isinstance(arg, TpyStrLiteral):
|
|
220
|
+
return None
|
|
221
|
+
return _FLOAT_STR_CONSTANTS.get(arg.value.strip().lower())
|
|
222
|
+
|
|
223
|
+
def gen_template_or_native_call(self, args: list[TpyExpr],
|
|
224
|
+
overloads: list[FunctionInfo], *,
|
|
225
|
+
fi: FunctionInfo | None = None,
|
|
226
|
+
type_args: tuple[TpyType, ...] | None = None) -> str:
|
|
227
|
+
"""Generate C++ for a @cpp_template or @native function call.
|
|
228
|
+
|
|
229
|
+
Generates arg expressions, then delegates to gen_call_from_fi.
|
|
230
|
+
fi: resolved FunctionInfo (when available from sema).
|
|
231
|
+
type_args: inferred type arguments for generic calls.
|
|
232
|
+
"""
|
|
233
|
+
if fi and (fi.cpp_template or fi.native_name):
|
|
234
|
+
# float("nan"/"inf"/"-inf"/aliases) -> constexpr numeric_limits fold.
|
|
235
|
+
# Defensive: gen_template_or_native_call is currently called for
|
|
236
|
+
# free functions / module functions, not record __init__, so this
|
|
237
|
+
# won't fire for float.__init__ today (that path goes through
|
|
238
|
+
# _gen_call / _gen_method_call direct calls to gen_call_from_fi,
|
|
239
|
+
# which have their own fold invocations). Kept here so a future
|
|
240
|
+
# caller that passes fi=float.__init__ through this entry point
|
|
241
|
+
# still folds correctly. Gated on fi.is_method + fi.owning_type_qname
|
|
242
|
+
# so user shadows of `float` don't fold.
|
|
243
|
+
folded = self._try_float_str_fold(fi, args)
|
|
244
|
+
if folded is not None:
|
|
245
|
+
return folded
|
|
246
|
+
# cpp_template substitutes the arg expression textually, so a
|
|
247
|
+
# bare lvalue arg is fine when it's not a last-use consume --
|
|
248
|
+
# skip gen_call_arg's lvalue->rvalue copy-temp in that case.
|
|
249
|
+
inline_template = bool(fi.cpp_template)
|
|
250
|
+
gen_args = [self._gen_call_arg(arg, ptype, inline_template=inline_template)
|
|
251
|
+
for arg, (_, ptype) in zip(args, fi.params)]
|
|
252
|
+
return self.gen_call_from_fi(fi, None, gen_args, type_args=type_args)
|
|
253
|
+
# Fallback: re-resolve (shouldn't normally be needed)
|
|
254
|
+
overload, gen_args = self._match_overload_args(args, overloads)
|
|
255
|
+
return self.gen_call_from_fi(overload, None, gen_args, type_args=type_args)
|
|
256
|
+
|
|
257
|
+
def _builtin_codegen_type_matches(self, arg: TpyExpr, arg_type: TpyType, param_type: TpyType) -> bool:
|
|
258
|
+
"""Check if an argument matches a parameter type for codegen purposes."""
|
|
259
|
+
# Direct type match
|
|
260
|
+
if isinstance(arg_type, type(param_type)) and arg_type == param_type:
|
|
261
|
+
return True
|
|
262
|
+
# Protocol parameter: sema already verified conformance, accept any arg
|
|
263
|
+
if is_protocol_type(param_type):
|
|
264
|
+
return True
|
|
265
|
+
# IntLiteral can match Int32 (if compile-time) or BigInt (if runtime)
|
|
266
|
+
if isinstance(arg_type, IntLiteralType):
|
|
267
|
+
if is_big_int_type(param_type):
|
|
268
|
+
return self.types.is_runtime_bigint(arg, arg_type)
|
|
269
|
+
if is_fixed_int_type(param_type):
|
|
270
|
+
return not self.types.is_runtime_bigint(arg, arg_type)
|
|
271
|
+
# INT TypeParamRef can match Int32 or BigInt (it's a compile-time constant)
|
|
272
|
+
if isinstance(arg_type, TypeParamRef) and arg_type.kind == TypeParamKind.INT:
|
|
273
|
+
return is_integer_type(param_type)
|
|
274
|
+
# TpyCoerce nodes match their expected type
|
|
275
|
+
if isinstance(arg, TpyCoerce):
|
|
276
|
+
return arg.expected_type == param_type
|
|
277
|
+
return False
|
|
278
|
+
|
|
279
|
+
def gen_print(self, args: list[TpyExpr], kwargs: dict[str, TpyExpr] = None) -> str:
|
|
280
|
+
"""Generate stream call for print().
|
|
281
|
+
|
|
282
|
+
Default sink is std::cout. With `file=`, uses ::tpy::as_ostream(<f>)
|
|
283
|
+
to dispatch on the static type (TextFile, StdStream, std::ostream&,
|
|
284
|
+
or generic Writable via streambuf adapter). With `flush=True`,
|
|
285
|
+
appends `<< std::flush` to the chain. sep= and end= accept literals
|
|
286
|
+
or runtime string expressions.
|
|
287
|
+
"""
|
|
288
|
+
kwargs = kwargs or {}
|
|
289
|
+
|
|
290
|
+
# sep / end resolve to a single ready-to-emit C++ token (or None to
|
|
291
|
+
# skip emission). Literals shorten to a quoted string; runtime exprs
|
|
292
|
+
# render via _gen_expr_deref. Empty literals are skipped entirely so
|
|
293
|
+
# `print(..., sep="")` doesn't emit a redundant `<< ""`.
|
|
294
|
+
def chain_token(kw_name: str, default_literal: str) -> str | None:
|
|
295
|
+
kw_expr = kwargs.get(kw_name)
|
|
296
|
+
if kw_expr is None:
|
|
297
|
+
return f'"{default_literal}"' if default_literal else None
|
|
298
|
+
if isinstance(kw_expr, TpyStrLiteral):
|
|
299
|
+
if not kw_expr.value:
|
|
300
|
+
return None
|
|
301
|
+
return cpp_string_literal_expr(kw_expr.value)
|
|
302
|
+
return self._gen_expr_deref(kw_expr)
|
|
303
|
+
|
|
304
|
+
end_token = chain_token("end", "\\n")
|
|
305
|
+
sep_token = chain_token("sep", " ")
|
|
306
|
+
|
|
307
|
+
# Sink: default cout, or as_ostream(file) when file= is provided.
|
|
308
|
+
if "file" in kwargs:
|
|
309
|
+
sink = f"::tpy::as_ostream({self._gen_expr_deref(kwargs['file'])})"
|
|
310
|
+
else:
|
|
311
|
+
sink = "std::cout"
|
|
312
|
+
|
|
313
|
+
# flush=True appends `<< std::flush` to the chain.
|
|
314
|
+
flush_expr = kwargs.get("flush")
|
|
315
|
+
flush_on = isinstance(flush_expr, TpyBoolLiteral) and flush_expr.value
|
|
316
|
+
|
|
317
|
+
if not args:
|
|
318
|
+
tail = []
|
|
319
|
+
if end_token is not None:
|
|
320
|
+
tail.append(end_token)
|
|
321
|
+
if flush_on:
|
|
322
|
+
tail.append("std::flush")
|
|
323
|
+
if not tail:
|
|
324
|
+
return ""
|
|
325
|
+
return f"{sink} << " + " << ".join(tail)
|
|
326
|
+
|
|
327
|
+
parts = []
|
|
328
|
+
for i, arg in enumerate(args):
|
|
329
|
+
if i > 0 and sep_token is not None:
|
|
330
|
+
parts.append(sep_token)
|
|
331
|
+
|
|
332
|
+
arg_type = unwrap_readonly(self.types.get_resolved_type(arg))
|
|
333
|
+
if isinstance(arg_type, OwnType):
|
|
334
|
+
arg_type = arg_type.wrapped
|
|
335
|
+
|
|
336
|
+
# When sema narrowed an optional field to its inner type,
|
|
337
|
+
# the C++ field is still std::optional<T> -- use the declared
|
|
338
|
+
# type for print formatting decisions.
|
|
339
|
+
if (not isinstance(arg_type, OptionalType)
|
|
340
|
+
and isinstance(arg, TpyFieldAccess)):
|
|
341
|
+
declared = self._get_cpp_declared_type(arg)
|
|
342
|
+
if isinstance(declared, OptionalType):
|
|
343
|
+
arg_type = declared
|
|
344
|
+
|
|
345
|
+
if isinstance(arg, TpyNoneLiteral):
|
|
346
|
+
parts.append('"None"')
|
|
347
|
+
elif isinstance(arg_type, NoneType):
|
|
348
|
+
# NoneType-typed expression (e.g. `x = await none_coro()`).
|
|
349
|
+
# std::monostate has no operator<<, so a direct `std::cout
|
|
350
|
+
# << x` won't compile; evaluate the expression for side
|
|
351
|
+
# effects, discard, then emit the literal.
|
|
352
|
+
expr_code = self._gen_expr_deref(arg)
|
|
353
|
+
parts.append(f'((void)({expr_code}), "None")')
|
|
354
|
+
elif isinstance(arg, TpyStrLiteral):
|
|
355
|
+
parts.append(cpp_string_literal_expr(arg.value))
|
|
356
|
+
elif self.types.is_runtime_bigint(arg, arg_type):
|
|
357
|
+
# BigInt has operator<< for std::ostream, no .to_string() needed
|
|
358
|
+
parts.append(self._gen_expr_deref(arg))
|
|
359
|
+
elif is_float64_type(arg_type):
|
|
360
|
+
parts.append(f'::tpy::print_float({self._gen_expr_deref(arg)})')
|
|
361
|
+
elif is_float32_type(arg_type):
|
|
362
|
+
parts.append(f'::tpy::print_float(static_cast<double>({self._gen_expr_deref(arg)}))')
|
|
363
|
+
elif is_bool_type(arg_type):
|
|
364
|
+
# Bool uses Python-style formatting via ::tpy::print_bool
|
|
365
|
+
parts.append(f'::tpy::print_bool({self._gen_expr_deref(arg)})')
|
|
366
|
+
elif isinstance(arg_type, OptionalType) and arg_type.uses_pointer_repr():
|
|
367
|
+
# Pointer-repr Optional source: container/dict/set/bytes inners
|
|
368
|
+
# need an explicit Formatter -- the underlying types lack a
|
|
369
|
+
# plain operator<<, so the default `os << *ptr` path fails to
|
|
370
|
+
# compile. Other inners stay on CTAD. Field access always uses
|
|
371
|
+
# print_optional_val (field storage is std::optional<T>).
|
|
372
|
+
inner = arg_type.inner
|
|
373
|
+
gen = self._gen_expr(arg)
|
|
374
|
+
inner_cpp = inner.to_cpp()
|
|
375
|
+
fmt = self._optional_container_formatter(inner, inner_cpp)
|
|
376
|
+
fn = "print_optional_val" if isinstance(arg, TpyFieldAccess) else "print_optional"
|
|
377
|
+
tmpl = f"<{fmt}, {inner_cpp}>" if fmt is not None else ""
|
|
378
|
+
parts.append(f'::tpy::{fn}{tmpl}({gen})')
|
|
379
|
+
elif isinstance(arg_type, OptionalType) and not arg_type.uses_pointer_repr():
|
|
380
|
+
# Optional value-type: use print_optional_val with inner-type-aware formatting.
|
|
381
|
+
# Render the bare optional storage here (NOT _gen_expr_deref) -- print_optional_val
|
|
382
|
+
# consumes the std::optional<T> directly to print "None" vs the value. _gen_expr_deref
|
|
383
|
+
# would unwrap narrowed value-Optional fields, forcing a redundant rewrap on the way
|
|
384
|
+
# into the function.
|
|
385
|
+
inner = arg_type.inner
|
|
386
|
+
gen = self._gen_expr(arg)
|
|
387
|
+
inner_cpp = inner.to_cpp()
|
|
388
|
+
if is_bool_type(inner):
|
|
389
|
+
parts.append(f'::tpy::print_optional_val<::tpy::print_bool, {inner_cpp}>({gen})')
|
|
390
|
+
elif is_float_type(inner):
|
|
391
|
+
parts.append(f'::tpy::print_optional_val<::tpy::print_float, {inner_cpp}>({gen})')
|
|
392
|
+
elif (fmt := self._optional_container_formatter(inner, inner_cpp)) is not None:
|
|
393
|
+
parts.append(f'::tpy::print_optional_val<{fmt}, {inner_cpp}>({gen})')
|
|
394
|
+
else:
|
|
395
|
+
parts.append(f'::tpy::print_optional_val({gen})')
|
|
396
|
+
elif isinstance(arg_type, TupleType):
|
|
397
|
+
parts.append(f'::tpy::TuplePrinter({self._gen_expr_deref(arg)})')
|
|
398
|
+
elif is_any_str_type(arg_type):
|
|
399
|
+
# Strings print as-is (not using ListPrinter)
|
|
400
|
+
parts.append(self._gen_expr_deref(arg))
|
|
401
|
+
elif is_bytearray_type(arg_type):
|
|
402
|
+
parts.append(f'::tpy::ByteArrayPrinter({self._gen_expr_deref(arg)})')
|
|
403
|
+
elif is_any_bytes_type(arg_type):
|
|
404
|
+
parts.append(f'::tpy::BytesPrinter({self._gen_expr_deref(arg)})')
|
|
405
|
+
elif is_dict(arg_type):
|
|
406
|
+
# Dict uses DictPrinter for {k: v, ...} formatting
|
|
407
|
+
parts.append(f'::tpy::DictPrinter({self._gen_expr_deref(arg)})')
|
|
408
|
+
elif is_set(arg_type):
|
|
409
|
+
# Set uses SetPrinter for {a, b, c} or set() formatting
|
|
410
|
+
parts.append(f'::tpy::SetPrinter({self._gen_expr_deref(arg)})')
|
|
411
|
+
elif is_dict_view(arg_type):
|
|
412
|
+
# Dict views use their own operator<< for printing
|
|
413
|
+
parts.append(self._gen_expr_deref(arg))
|
|
414
|
+
elif is_array(arg_type) or is_span(arg_type) or is_list(arg_type) or isinstance(arg_type, ListRepeatType):
|
|
415
|
+
# Sequence containers use ListPrinter for [a, b, c] formatting
|
|
416
|
+
if isinstance(arg, TpyArrayLiteral):
|
|
417
|
+
# Array literals need explicit type for ListPrinter CTAD
|
|
418
|
+
cpp_type = arg_type.to_cpp()
|
|
419
|
+
parts.append(f'::tpy::ListPrinter({cpp_type}{self._gen_expr(arg)})')
|
|
420
|
+
else:
|
|
421
|
+
parts.append(f'::tpy::ListPrinter({self._gen_expr_deref(arg)})')
|
|
422
|
+
elif isinstance(arg_type, TypeParamRef):
|
|
423
|
+
# Generic type parameter -- use ValuePrinter for runtime dispatch
|
|
424
|
+
parts.append(f'::tpy::ValuePrinter({self._gen_expr_deref(arg)})')
|
|
425
|
+
elif is_enum_type(arg_type) and (einfo := enum_info_of(arg_type)) is not None and einfo.is_native:
|
|
426
|
+
# @native enums: no operator<< is emitted (would conflict
|
|
427
|
+
# with user-provided one). Route through __repr__ which
|
|
428
|
+
# the runtime template resolves via EnumUtil. Tpy-defined
|
|
429
|
+
# enums keep the raw-emit path below (their operator<< is
|
|
430
|
+
# still emitted; preserves existing behavior).
|
|
431
|
+
parts.append(f'::tpy::__repr__({self._gen_expr_deref(arg)})')
|
|
432
|
+
else:
|
|
433
|
+
# FixedInt, Char, Bool, literals, etc. - direct output
|
|
434
|
+
expr_code = self._gen_expr_deref(arg)
|
|
435
|
+
# 8-bit integers need cast to avoid char interpretation in std::cout
|
|
436
|
+
arg_tr = int_traits_of(arg_type)
|
|
437
|
+
if arg_tr is not None and arg_tr.bits == 8:
|
|
438
|
+
expr_code = f"static_cast<int>({expr_code})"
|
|
439
|
+
parts.append(expr_code)
|
|
440
|
+
|
|
441
|
+
if end_token is not None:
|
|
442
|
+
parts.append(end_token)
|
|
443
|
+
|
|
444
|
+
if flush_on:
|
|
445
|
+
parts.append("std::flush")
|
|
446
|
+
|
|
447
|
+
return f"{sink} << " + " << ".join(parts)
|
|
448
|
+
|
|
449
|
+
def _optional_container_formatter(self, inner: TpyType, inner_cpp: str) -> str | None:
|
|
450
|
+
"""Pick a Formatter type for print_optional / print_optional_val when
|
|
451
|
+
the Optional inner is a container/tuple/bytes type whose underlying C++
|
|
452
|
+
representation lacks a plain `operator<<` (list/Array/Span ->
|
|
453
|
+
vector/array/span, dict -> ordered_map, set -> ordered_set, tuple ->
|
|
454
|
+
std::tuple, bytes/bytearray -> vector<uint8_t>). Returns the Formatter
|
|
455
|
+
type string or None when no wrapper is needed (dict_view types have
|
|
456
|
+
their own operator<<, so the default print_optional/_val path works).
|
|
457
|
+
"""
|
|
458
|
+
# bytearray is also "any bytes" per is_any_bytes_type, so check the
|
|
459
|
+
# narrower bytearray predicate first to keep the bytearray(b'...')
|
|
460
|
+
# repr distinct from bytes' b'...' repr.
|
|
461
|
+
if is_bytearray_type(inner):
|
|
462
|
+
return "::tpy::ByteArrayPrinter"
|
|
463
|
+
if is_any_bytes_type(inner):
|
|
464
|
+
return "::tpy::BytesPrinter"
|
|
465
|
+
if isinstance(inner, TupleType):
|
|
466
|
+
elem_cpps = ", ".join(et.to_cpp() for et in inner.element_types)
|
|
467
|
+
return f"::tpy::TuplePrinter<{elem_cpps}>"
|
|
468
|
+
if is_dict(inner):
|
|
469
|
+
type_args = inner.type_args
|
|
470
|
+
if type_args and len(type_args) >= 2:
|
|
471
|
+
key_cpp = type_args[0].to_cpp()
|
|
472
|
+
value_cpp = type_args[1].to_cpp()
|
|
473
|
+
return f"::tpy::DictPrinter<{key_cpp}, {value_cpp}>"
|
|
474
|
+
return None
|
|
475
|
+
if is_set(inner):
|
|
476
|
+
type_args = inner.type_args
|
|
477
|
+
if type_args:
|
|
478
|
+
elem_cpp = type_args[0].to_cpp()
|
|
479
|
+
return f"::tpy::SetPrinter<{elem_cpp}>"
|
|
480
|
+
return None
|
|
481
|
+
if (is_list(inner) or is_array(inner) or is_span(inner)
|
|
482
|
+
or isinstance(inner, ListRepeatType)):
|
|
483
|
+
return f"::tpy::ListPrinter<{inner_cpp}>"
|
|
484
|
+
return None
|