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,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TurboPython Runtime - Ordered Set
|
|
3
|
+
*
|
|
4
|
+
* Hash set that preserves insertion order (matching Python's set implementation).
|
|
5
|
+
* Combines std::unordered_set for O(1) lookup with an intrusive doubly-linked
|
|
6
|
+
* list for insertion-order iteration.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#pragma once
|
|
10
|
+
|
|
11
|
+
#include <cstdint>
|
|
12
|
+
#include <expected>
|
|
13
|
+
#include <functional>
|
|
14
|
+
#include <initializer_list>
|
|
15
|
+
#include <unordered_map>
|
|
16
|
+
#include <utility>
|
|
17
|
+
|
|
18
|
+
#include "core.hpp"
|
|
19
|
+
|
|
20
|
+
namespace tpy {
|
|
21
|
+
|
|
22
|
+
template<typename T>
|
|
23
|
+
class ordered_set {
|
|
24
|
+
struct Node {
|
|
25
|
+
T value;
|
|
26
|
+
Node* prev = nullptr;
|
|
27
|
+
Node* next = nullptr;
|
|
28
|
+
|
|
29
|
+
template<typename U>
|
|
30
|
+
explicit Node(U&& v) : value(std::forward<U>(v)) {}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
public:
|
|
34
|
+
// -- Iterator (insertion order) ------------------------------------------
|
|
35
|
+
|
|
36
|
+
template<bool IsConst>
|
|
37
|
+
class iterator_impl {
|
|
38
|
+
friend class ordered_set;
|
|
39
|
+
using NodePtr = std::conditional_t<IsConst, const Node*, Node*>;
|
|
40
|
+
NodePtr node_;
|
|
41
|
+
|
|
42
|
+
explicit iterator_impl(NodePtr n) : node_(n) {}
|
|
43
|
+
|
|
44
|
+
public:
|
|
45
|
+
iterator_impl() : node_(nullptr) {}
|
|
46
|
+
|
|
47
|
+
using iterator_category = std::forward_iterator_tag;
|
|
48
|
+
using difference_type = std::ptrdiff_t;
|
|
49
|
+
using value_type = T;
|
|
50
|
+
using reference = const T&;
|
|
51
|
+
|
|
52
|
+
const T& operator*() const { return node_->value; }
|
|
53
|
+
|
|
54
|
+
iterator_impl& operator++() { node_ = node_->next; return *this; }
|
|
55
|
+
iterator_impl operator++(int) { auto tmp = *this; node_ = node_->next; return tmp; }
|
|
56
|
+
|
|
57
|
+
bool operator==(const iterator_impl& o) const { return node_ == o.node_; }
|
|
58
|
+
bool operator!=(const iterator_impl& o) const { return node_ != o.node_; }
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
using iterator = iterator_impl<false>;
|
|
62
|
+
using const_iterator = iterator_impl<true>;
|
|
63
|
+
|
|
64
|
+
// -- Construction --------------------------------------------------------
|
|
65
|
+
|
|
66
|
+
ordered_set() = default;
|
|
67
|
+
|
|
68
|
+
ordered_set(std::initializer_list<T> init) {
|
|
69
|
+
for (auto& v : init) {
|
|
70
|
+
insert(v);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
ordered_set(const ordered_set& other) {
|
|
75
|
+
for (auto* n = other.head_; n != nullptr; n = n->next) {
|
|
76
|
+
insert(n->value);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
ordered_set(ordered_set&& other) noexcept
|
|
81
|
+
: table_(std::move(other.table_))
|
|
82
|
+
, head_(other.head_)
|
|
83
|
+
, tail_(other.tail_)
|
|
84
|
+
{
|
|
85
|
+
other.head_ = nullptr;
|
|
86
|
+
other.tail_ = nullptr;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
ordered_set& operator=(const ordered_set& other) {
|
|
90
|
+
if (this != &other) {
|
|
91
|
+
clear();
|
|
92
|
+
for (auto* n = other.head_; n != nullptr; n = n->next) {
|
|
93
|
+
insert(n->value);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return *this;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
ordered_set& operator=(ordered_set&& other) noexcept {
|
|
100
|
+
if (this != &other) {
|
|
101
|
+
clear();
|
|
102
|
+
table_ = std::move(other.table_);
|
|
103
|
+
head_ = other.head_;
|
|
104
|
+
tail_ = other.tail_;
|
|
105
|
+
other.head_ = nullptr;
|
|
106
|
+
other.tail_ = nullptr;
|
|
107
|
+
}
|
|
108
|
+
return *this;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
~ordered_set() {
|
|
112
|
+
clear();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// -- Capacity ------------------------------------------------------------
|
|
116
|
+
|
|
117
|
+
int32_t size() const { return static_cast<int32_t>(table_.size()); }
|
|
118
|
+
bool empty() const { return table_.empty(); }
|
|
119
|
+
|
|
120
|
+
// -- Modifiers -----------------------------------------------------------
|
|
121
|
+
|
|
122
|
+
bool insert(const T& value) {
|
|
123
|
+
auto it = table_.find(value);
|
|
124
|
+
if (it != table_.end()) return false;
|
|
125
|
+
auto* node = new Node(value);
|
|
126
|
+
link_back(node);
|
|
127
|
+
table_.emplace(value, node);
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
bool insert(T&& value) {
|
|
132
|
+
auto it = table_.find(value);
|
|
133
|
+
if (it != table_.end()) return false;
|
|
134
|
+
auto* node = new Node(std::move(value));
|
|
135
|
+
link_back(node);
|
|
136
|
+
table_.emplace(node->value, node);
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
bool erase(const T& value) {
|
|
141
|
+
auto it = table_.find(value);
|
|
142
|
+
if (it == table_.end()) return false;
|
|
143
|
+
Node* node = it->second;
|
|
144
|
+
table_.erase(it);
|
|
145
|
+
unlink(node);
|
|
146
|
+
delete node;
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
void clear() {
|
|
151
|
+
auto* n = head_;
|
|
152
|
+
while (n != nullptr) {
|
|
153
|
+
auto* next = n->next;
|
|
154
|
+
delete n;
|
|
155
|
+
n = next;
|
|
156
|
+
}
|
|
157
|
+
table_.clear();
|
|
158
|
+
head_ = nullptr;
|
|
159
|
+
tail_ = nullptr;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// -- Lookup --------------------------------------------------------------
|
|
163
|
+
|
|
164
|
+
bool contains(const T& value) const {
|
|
165
|
+
return table_.find(value) != table_.end();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// -- Iteration (insertion order) -----------------------------------------
|
|
169
|
+
|
|
170
|
+
iterator begin() { return iterator(head_); }
|
|
171
|
+
iterator end() { return iterator(nullptr); }
|
|
172
|
+
const_iterator begin() const { return const_iterator(head_); }
|
|
173
|
+
const_iterator end() const { return const_iterator(nullptr); }
|
|
174
|
+
|
|
175
|
+
// -- Python __iter__() support -------------------------------------------
|
|
176
|
+
|
|
177
|
+
// Defined in set_ops.hpp (needs native_iterator template)
|
|
178
|
+
inline auto __iter__() const;
|
|
179
|
+
|
|
180
|
+
// -- Comparison (order-independent, matching Python) ---------------------
|
|
181
|
+
|
|
182
|
+
bool operator==(const ordered_set& other) const {
|
|
183
|
+
if (table_.size() != other.table_.size()) return false;
|
|
184
|
+
for (auto* n = head_; n != nullptr; n = n->next) {
|
|
185
|
+
if (!other.contains(n->value)) return false;
|
|
186
|
+
}
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
bool operator!=(const ordered_set& other) const {
|
|
191
|
+
return !(*this == other);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Python set comparison: <= means subset, < means strict subset, etc.
|
|
195
|
+
bool operator<=(const ordered_set& other) const {
|
|
196
|
+
if (table_.size() > other.table_.size()) return false;
|
|
197
|
+
for (auto* n = head_; n != nullptr; n = n->next) {
|
|
198
|
+
if (!other.contains(n->value)) return false;
|
|
199
|
+
}
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
bool operator<(const ordered_set& other) const {
|
|
204
|
+
return table_.size() < other.table_.size() && *this <= other;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
bool operator>=(const ordered_set& other) const {
|
|
208
|
+
return other <= *this;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
bool operator>(const ordered_set& other) const {
|
|
212
|
+
return other < *this;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// -- Front access (for pop) ----------------------------------------------
|
|
216
|
+
|
|
217
|
+
const T& front() const { return head_->value; }
|
|
218
|
+
|
|
219
|
+
void pop_front() {
|
|
220
|
+
Node* node = head_;
|
|
221
|
+
table_.erase(node->value);
|
|
222
|
+
unlink(node);
|
|
223
|
+
delete node;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private:
|
|
227
|
+
void link_back(Node* node) {
|
|
228
|
+
node->prev = tail_;
|
|
229
|
+
node->next = nullptr;
|
|
230
|
+
if (tail_) {
|
|
231
|
+
tail_->next = node;
|
|
232
|
+
} else {
|
|
233
|
+
head_ = node;
|
|
234
|
+
}
|
|
235
|
+
tail_ = node;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
void unlink(Node* node) {
|
|
239
|
+
if (node->prev) {
|
|
240
|
+
node->prev->next = node->next;
|
|
241
|
+
} else {
|
|
242
|
+
head_ = node->next;
|
|
243
|
+
}
|
|
244
|
+
if (node->next) {
|
|
245
|
+
node->next->prev = node->prev;
|
|
246
|
+
} else {
|
|
247
|
+
tail_ = node->prev;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
template<typename> friend struct OwnIterSet;
|
|
252
|
+
|
|
253
|
+
std::unordered_map<T, Node*, std::hash<T>> table_;
|
|
254
|
+
Node* head_ = nullptr;
|
|
255
|
+
Node* tail_ = nullptr;
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
// Construct an ordered_set from move-only T types. Mirrors make_vector /
|
|
259
|
+
// make_ordered_map: the initializer_list ctor stores elements as const,
|
|
260
|
+
// forcing a copy of T -- this helper forwards each element into insert
|
|
261
|
+
// so move-only values work in set literals once sema permits them.
|
|
262
|
+
template<typename T, typename... Args>
|
|
263
|
+
ordered_set<T> make_ordered_set(Args&&... args) {
|
|
264
|
+
ordered_set<T> s;
|
|
265
|
+
(s.insert(std::forward<Args>(args)), ...);
|
|
266
|
+
return s;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// ---------------------------------------------------------------------------
|
|
270
|
+
// OwnIterSet -- drain iterator for ordered_set
|
|
271
|
+
//
|
|
272
|
+
// Owns a moved ordered_set and yields elements by move. O(1) construction
|
|
273
|
+
// (hash table move is pointer swap). Implements both C++ range (begin/end
|
|
274
|
+
// with move iterators) and the TurboPython Iterator protocol (__next__).
|
|
275
|
+
// ---------------------------------------------------------------------------
|
|
276
|
+
|
|
277
|
+
template<typename T>
|
|
278
|
+
struct OwnIterSet {
|
|
279
|
+
ordered_set<T> data;
|
|
280
|
+
typename ordered_set<T>::Node* pos;
|
|
281
|
+
|
|
282
|
+
explicit OwnIterSet(ordered_set<T>&& s)
|
|
283
|
+
: data(std::move(s)), pos(data.head_) {}
|
|
284
|
+
|
|
285
|
+
OwnIterSet(const OwnIterSet&) = delete;
|
|
286
|
+
OwnIterSet& operator=(const OwnIterSet&) = delete;
|
|
287
|
+
OwnIterSet(OwnIterSet&&) = default;
|
|
288
|
+
OwnIterSet& operator=(OwnIterSet&&) = default;
|
|
289
|
+
|
|
290
|
+
// Move iterator: walks linked-list nodes, yields T&& (moved values).
|
|
291
|
+
// Single-pass: each dereference moves the value out of the node.
|
|
292
|
+
struct move_iter {
|
|
293
|
+
using Node = typename ordered_set<T>::Node;
|
|
294
|
+
Node* node_;
|
|
295
|
+
|
|
296
|
+
using iterator_category = std::input_iterator_tag;
|
|
297
|
+
using value_type = T;
|
|
298
|
+
using difference_type = std::ptrdiff_t;
|
|
299
|
+
using reference = T&&;
|
|
300
|
+
|
|
301
|
+
move_iter() : node_(nullptr) {}
|
|
302
|
+
explicit move_iter(Node* n) : node_(n) {}
|
|
303
|
+
|
|
304
|
+
T&& operator*() { return std::move(node_->value); }
|
|
305
|
+
move_iter& operator++() { node_ = node_->next; return *this; }
|
|
306
|
+
move_iter operator++(int) { auto tmp = *this; ++*this; return tmp; }
|
|
307
|
+
bool operator==(const move_iter& o) const { return node_ == o.node_; }
|
|
308
|
+
bool operator!=(const move_iter& o) const { return node_ != o.node_; }
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
// NativeIterable: range-based iteration with move semantics.
|
|
312
|
+
// Do not mix range-based (begin/end) and __next__-based iteration on the
|
|
313
|
+
// same instance -- both advance shared state and the result is undefined.
|
|
314
|
+
move_iter begin() { return move_iter(pos); }
|
|
315
|
+
move_iter end() { return move_iter(nullptr); }
|
|
316
|
+
|
|
317
|
+
// TPy Iterator protocol
|
|
318
|
+
std::expected<T, StopIteration> __next__() {
|
|
319
|
+
if (pos == nullptr) return tpy::make_unexpected(StopIteration{});
|
|
320
|
+
T value = std::move(pos->value);
|
|
321
|
+
pos = pos->next;
|
|
322
|
+
return value;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
OwnIterSet& __iter__() { return *this; }
|
|
326
|
+
|
|
327
|
+
friend std::ostream& operator<<(std::ostream& os, const OwnIterSet&) {
|
|
328
|
+
return os << "<own_iter_set>";
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
template<typename T>
|
|
333
|
+
OwnIterSet<T> own_iter_set(ordered_set<T>&& s) {
|
|
334
|
+
return OwnIterSet<T>{std::move(s)};
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
} // namespace tpy
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TurboPython Runtime - OwnIter
|
|
3
|
+
*
|
|
4
|
+
* Drain iterator for heap-backed containers (std::vector). Owns a moved
|
|
5
|
+
* vector and yields elements by move. O(1) construction (vector move is
|
|
6
|
+
* pointer swap). Unconsumed elements are destructed when OwnIter is dropped.
|
|
7
|
+
*
|
|
8
|
+
* Implements both C++ range (begin/end with move iterators) and the
|
|
9
|
+
* TurboPython Iterator protocol (__next__/__iter__).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
#pragma once
|
|
13
|
+
|
|
14
|
+
#include "core.hpp"
|
|
15
|
+
|
|
16
|
+
#include <expected>
|
|
17
|
+
#include <iterator>
|
|
18
|
+
#include <vector>
|
|
19
|
+
|
|
20
|
+
namespace tpy {
|
|
21
|
+
|
|
22
|
+
template<typename T>
|
|
23
|
+
struct OwnIter {
|
|
24
|
+
std::vector<T> data;
|
|
25
|
+
std::size_t pos = 0;
|
|
26
|
+
|
|
27
|
+
explicit OwnIter(std::vector<T>&& v) : data(std::move(v)) {}
|
|
28
|
+
|
|
29
|
+
// NativeIterable: range-based iteration with move semantics.
|
|
30
|
+
// Do not mix range-based (begin/end) and __next__-based iteration on the
|
|
31
|
+
// same instance -- both advance shared state and the result is undefined.
|
|
32
|
+
auto begin() { return std::make_move_iterator(data.begin() + static_cast<std::ptrdiff_t>(pos)); }
|
|
33
|
+
auto end() { return std::make_move_iterator(data.end()); }
|
|
34
|
+
|
|
35
|
+
// Iterator protocol
|
|
36
|
+
std::expected<T, StopIteration> __next__() {
|
|
37
|
+
if (pos >= data.size()) return tpy::make_unexpected(StopIteration{});
|
|
38
|
+
return std::move(data[pos++]);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
OwnIter& __iter__() { return *this; }
|
|
42
|
+
|
|
43
|
+
friend std::ostream& operator<<(std::ostream& os, const OwnIter&) {
|
|
44
|
+
return os << "<own_iter>";
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// Factory: create OwnIter from an rvalue vector.
|
|
49
|
+
template<typename T>
|
|
50
|
+
OwnIter<T> own_iter(std::vector<T>&& v) {
|
|
51
|
+
return OwnIter<T>{std::move(v)};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
} // namespace tpy
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// Pascal Graph SDL2 display layer.
|
|
2
|
+
//
|
|
3
|
+
// Optional companion to the pure-TPy Pascal Graph unit. Compiled in when
|
|
4
|
+
// `--dsl-opt pascal.sdl=on` (or `auto` finds libsdl2-dev). The frontend
|
|
5
|
+
// plugin injects calls to the entry points below around the Pascal source
|
|
6
|
+
// (initgraph -> open, delay/setvisualpage -> present, closegraph ->
|
|
7
|
+
// show_blocking + closegraph + close_window) so animated TP7 programs
|
|
8
|
+
// render live in a window rather than as one final snapshot.
|
|
9
|
+
//
|
|
10
|
+
// The Pascal Graph runtime owns the pixel buffer + does all drawing
|
|
11
|
+
// (Tier A/B/C primitives are pure TPy). This file is a thin display
|
|
12
|
+
// adapter -- window/renderer/texture creation, pixel upload, event
|
|
13
|
+
// pumping, teardown.
|
|
14
|
+
|
|
15
|
+
#pragma once
|
|
16
|
+
|
|
17
|
+
#include <SDL2/SDL.h>
|
|
18
|
+
|
|
19
|
+
#include <cstdint>
|
|
20
|
+
#include <vector>
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
namespace tpy::pascal {
|
|
24
|
+
|
|
25
|
+
// Module-level SDL handles. Held in a function-local static so we can
|
|
26
|
+
// keep the API as free functions matching the TPy `@native` shape. The
|
|
27
|
+
// program is single-threaded at the Pascal level, so a single global
|
|
28
|
+
// is fine; nested initgraph/closegraph cycles work because
|
|
29
|
+
// `sdl_close_window` resets everything.
|
|
30
|
+
struct SdlGfxState {
|
|
31
|
+
SDL_Window* win = nullptr;
|
|
32
|
+
SDL_Renderer* ren = nullptr;
|
|
33
|
+
SDL_Texture* tex = nullptr;
|
|
34
|
+
int width = 0;
|
|
35
|
+
int height = 0;
|
|
36
|
+
bool user_quit = false;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
inline SdlGfxState& sdl_gfx_state() {
|
|
40
|
+
static SdlGfxState s;
|
|
41
|
+
return s;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Pump any pending SDL events so the OS keeps treating the window as
|
|
45
|
+
// responsive. Sets `user_quit` if the user has tried to close the
|
|
46
|
+
// window or pressed any key. Non-blocking; safe to call from any
|
|
47
|
+
// hook.
|
|
48
|
+
inline void sdl_pump_events() {
|
|
49
|
+
SdlGfxState& s = sdl_gfx_state();
|
|
50
|
+
SDL_Event ev;
|
|
51
|
+
while (SDL_PollEvent(&ev) != 0) {
|
|
52
|
+
if (ev.type == SDL_QUIT) {
|
|
53
|
+
s.user_quit = true;
|
|
54
|
+
} else if (ev.type == SDL_KEYDOWN) {
|
|
55
|
+
s.user_quit = true;
|
|
56
|
+
} else if (ev.type == SDL_WINDOWEVENT
|
|
57
|
+
&& ev.window.event == SDL_WINDOWEVENT_CLOSE) {
|
|
58
|
+
s.user_quit = true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Open the SDL window for a `width`x`height` canvas. Idempotent --
|
|
64
|
+
// calling twice with the same dimensions is a no-op; calling with
|
|
65
|
+
// different dimensions reopens. Silent no-op on any SDL failure --
|
|
66
|
+
// the Pascal program's PPM snapshot fallback still gets written at
|
|
67
|
+
// CloseGraph, so users without a working SDL2 setup don't end up
|
|
68
|
+
// empty-handed.
|
|
69
|
+
inline void sdl_open_window(std::int32_t width, std::int32_t height) {
|
|
70
|
+
SdlGfxState& s = sdl_gfx_state();
|
|
71
|
+
if (width <= 0 || height <= 0) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (s.win != nullptr && s.width == width && s.height == height) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
// Different dimensions on a re-init -> tear down and reopen.
|
|
78
|
+
if (s.win != nullptr) {
|
|
79
|
+
if (s.tex != nullptr) { SDL_DestroyTexture(s.tex); }
|
|
80
|
+
if (s.ren != nullptr) { SDL_DestroyRenderer(s.ren); }
|
|
81
|
+
SDL_DestroyWindow(s.win);
|
|
82
|
+
s.tex = nullptr; s.ren = nullptr; s.win = nullptr;
|
|
83
|
+
}
|
|
84
|
+
if (SDL_WasInit(SDL_INIT_VIDEO) == 0) {
|
|
85
|
+
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Scale up by 2x so a 320x200 BGI canvas renders at 640x400
|
|
90
|
+
// (closer to readable on a modern display). The texture stays at
|
|
91
|
+
// the canvas size; SDL's RenderCopy stretches it to the window.
|
|
92
|
+
const int win_w = width * 2;
|
|
93
|
+
const int win_h = height * 2;
|
|
94
|
+
s.win = SDL_CreateWindow(
|
|
95
|
+
"TurboPython Pascal Graph",
|
|
96
|
+
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
|
97
|
+
win_w, win_h, SDL_WINDOW_SHOWN);
|
|
98
|
+
if (s.win == nullptr) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
s.ren = SDL_CreateRenderer(s.win, -1, 0);
|
|
102
|
+
if (s.ren == nullptr) {
|
|
103
|
+
SDL_DestroyWindow(s.win); s.win = nullptr;
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
s.tex = SDL_CreateTexture(
|
|
107
|
+
s.ren, SDL_PIXELFORMAT_RGB888,
|
|
108
|
+
SDL_TEXTUREACCESS_STREAMING, width, height);
|
|
109
|
+
if (s.tex == nullptr) {
|
|
110
|
+
SDL_DestroyRenderer(s.ren); s.ren = nullptr;
|
|
111
|
+
SDL_DestroyWindow(s.win); s.win = nullptr;
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
s.width = width;
|
|
115
|
+
s.height = height;
|
|
116
|
+
s.user_quit = false;
|
|
117
|
+
sdl_pump_events();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Upload the current pixel buffer and present it. Pumps SDL events so
|
|
121
|
+
// the OS keeps the window responsive. Non-blocking. Auto-opens the
|
|
122
|
+
// window if it isn't open yet (lets a program call `sdl_present`
|
|
123
|
+
// without an explicit `sdl_open_window` -- the frontend injects the
|
|
124
|
+
// open call after initgraph but a malformed sequence shouldn't
|
|
125
|
+
// silently drop frames).
|
|
126
|
+
inline void sdl_present(std::int32_t width, std::int32_t height,
|
|
127
|
+
const std::vector<std::int32_t>& pixels) {
|
|
128
|
+
SdlGfxState& s = sdl_gfx_state();
|
|
129
|
+
if (width <= 0 || height <= 0) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (static_cast<std::size_t>(width) * static_cast<std::size_t>(height)
|
|
133
|
+
!= pixels.size()) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (s.win == nullptr || s.width != width || s.height != height) {
|
|
137
|
+
sdl_open_window(width, height);
|
|
138
|
+
if (s.win == nullptr) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
SDL_UpdateTexture(s.tex, nullptr, pixels.data(),
|
|
143
|
+
static_cast<int>(width * sizeof(std::int32_t)));
|
|
144
|
+
SDL_RenderClear(s.ren);
|
|
145
|
+
SDL_RenderCopy(s.ren, s.tex, nullptr, nullptr);
|
|
146
|
+
SDL_RenderPresent(s.ren);
|
|
147
|
+
sdl_pump_events();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Present the final canvas and block until the user closes the
|
|
151
|
+
// window or presses any key. If the user already quit during an
|
|
152
|
+
// earlier present (`user_quit` set), returns immediately so the
|
|
153
|
+
// program can finish teardown without re-blocking.
|
|
154
|
+
inline void sdl_show_blocking(std::int32_t width, std::int32_t height,
|
|
155
|
+
const std::vector<std::int32_t>& pixels) {
|
|
156
|
+
sdl_present(width, height, pixels);
|
|
157
|
+
SdlGfxState& s = sdl_gfx_state();
|
|
158
|
+
if (s.win == nullptr) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (s.user_quit) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
SDL_Event ev;
|
|
165
|
+
while (SDL_WaitEvent(&ev) != 0) {
|
|
166
|
+
if (ev.type == SDL_QUIT
|
|
167
|
+
|| ev.type == SDL_KEYDOWN
|
|
168
|
+
|| (ev.type == SDL_WINDOWEVENT
|
|
169
|
+
&& ev.window.event == SDL_WINDOWEVENT_CLOSE)) {
|
|
170
|
+
s.user_quit = true;
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Destroy the window / renderer / texture and shut down SDL video.
|
|
177
|
+
// Idempotent -- safe to call from cleanup paths even when the window
|
|
178
|
+
// failed to open.
|
|
179
|
+
inline void sdl_close_window() {
|
|
180
|
+
SdlGfxState& s = sdl_gfx_state();
|
|
181
|
+
if (s.tex != nullptr) { SDL_DestroyTexture(s.tex); s.tex = nullptr; }
|
|
182
|
+
if (s.ren != nullptr) { SDL_DestroyRenderer(s.ren); s.ren = nullptr; }
|
|
183
|
+
if (s.win != nullptr) { SDL_DestroyWindow(s.win); s.win = nullptr; }
|
|
184
|
+
s.width = 0;
|
|
185
|
+
s.height = 0;
|
|
186
|
+
s.user_quit = false;
|
|
187
|
+
if (SDL_WasInit(SDL_INIT_VIDEO) != 0) {
|
|
188
|
+
SDL_Quit();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
} // namespace tpy::pascal
|