codecin 6.2.2__tar.gz → 6.4.0__tar.gz
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.
- {codecin-6.2.2 → codecin-6.4.0}/CHANGELOG.md +143 -0
- {codecin-6.2.2/codecin.egg-info → codecin-6.4.0}/PKG-INFO +16 -8
- {codecin-6.2.2 → codecin-6.4.0}/README.md +15 -7
- {codecin-6.2.2 → codecin-6.4.0}/codecin/__init__.py +1 -1
- {codecin-6.2.2 → codecin-6.4.0}/codecin/cin.py +292 -29
- {codecin-6.2.2 → codecin-6.4.0}/codecin/cli.py +25 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/cpu.py +20 -1
- {codecin-6.2.2 → codecin-6.4.0}/codecin/memory.py +1 -1
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/aot/aot.go +5 -1
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/keyboard.go +10 -1
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/keyboard_other.go +13 -9
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/keyboard_stub.go +3 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/keyboard_test.go +7 -7
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/keyboard_windows.go +30 -18
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/native.go +7 -1
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/version_gen.go +1 -1
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/vm.go +29 -24
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/main.go +14 -8
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native.py +6 -3
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native_codegen.py +1 -0
- codecin-6.4.0/codecin/packaging/spec.py +193 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/packaging/vcs.py +2 -2
- {codecin-6.2.2 → codecin-6.4.0}/codecin/pic.py +602 -81
- {codecin-6.2.2 → codecin-6.4.0}/codecin/pic_registry.py +133 -4
- {codecin-6.2.2 → codecin-6.4.0}/codecin/stdlib.py +2 -2
- {codecin-6.2.2 → codecin-6.4.0/codecin.egg-info}/PKG-INFO +16 -8
- {codecin-6.2.2 → codecin-6.4.0}/codecin.egg-info/SOURCES.txt +3 -0
- codecin-6.4.0/examples/terminal_cache_demo.cin +135 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_aggregate_and_const.py +1 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_cin_new_features.py +1 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_features_importloc.py +1 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_ffi_net.py +2 -4
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_lib_bigint.py +1 -2
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_lib_bitset.py +1 -2
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_lib_codec.py +0 -2
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_lib_combin.py +1 -2
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_lib_csv.py +1 -2
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_lib_dp.py +1 -2
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_lib_fmt.py +1 -2
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_lib_frac.py +1 -2
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_lib_graph.py +1 -2
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_lib_heap.py +1 -2
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_lib_path.py +1 -2
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_lib_set.py +1 -2
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_lib_text.py +1 -2
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_lib_token.py +1 -2
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_lib_tree.py +1 -2
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_lib_unionfind.py +1 -2
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_libs_ext.py +1 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_native_lib_lookup.py +1 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_sparse_memory.py +1 -2
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_struct_value_semantics.py +1 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_v620_pic.py +36 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_v620_pic_git.py +25 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_v620_pic_registry.py +45 -1
- codecin-6.4.0/tests/test_v640_pic_import.py +150 -0
- {codecin-6.2.2 → codecin-6.4.0}/LICENSE +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/MANIFEST.in +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/aot.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/assembler.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/config.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/console.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/crom.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/cvm.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/disasm.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/environment.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/errors.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/isa.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/array.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/bigint.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/bits.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/bitset.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/codec.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/combin.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/conv.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/cppstd.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/cstd.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/csv.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/dp.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/ffi.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/fmt.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/frac.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/gostd.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/graph.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/gui.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/hash.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/heap.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/io.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/json.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/key.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/math.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/matrix.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/net.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/path.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/queue.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/rand.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/set.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/sort.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/stat.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/str.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/termux.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/test.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/text.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/time.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/token.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/tree.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/unionfind.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/validate.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/lib/vec.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/logger.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/mkn.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/aot/stub_main.go.txt +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/build.ps1 +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/build.sh +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/compiler/codegen.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/compiler/compile_test.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/compiler/parser.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/compiler/syscalls.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/compiler/tokenizer.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/compiler/types.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/args.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/audio.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/audio_other.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/audio_test.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/audio_windows.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/canvas.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/console_other.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/console_windows.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/crom.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/encode.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/engine_test.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/ffi_nocgo.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/ffi_registry.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/ffi_unix.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/ffi_windows.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/gui.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/gui_stub.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/gui_test.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/gui_windows.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/gui_x11.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/host_test.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/hostcrypto.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/hostdesktop.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/hostnet.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/isa_gen.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/keyboard_termios_darwin.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/keyboard_termios_linux.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/keyboard_windows_test.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/lineedit.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/lineedit_test.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/lineint_unix.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/lineint_windows.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/mem_other.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/mem_windows.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/netsock.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/ops_ext.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/stdin.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/stdin_other.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/stdin_windows.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/system.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/termux.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/vkb_darwin.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/vkb_linux.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/engine/vkb_stub.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/go.mod +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/native/ir/ir.go +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/object.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/optimizer.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/packaging/__init__.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/packaging/archive.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/packaging/model.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/packaging/store.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/packaging/toml.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/pic_api.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/pic_login.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/registers.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/stats.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/toolkit.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin/version.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin.egg-info/dependency_links.txt +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin.egg-info/entry_points.txt +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin.egg-info/requires.txt +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/codecin.egg-info/top_level.txt +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/examples/args_demo.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/examples/asm_constants.asm +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/examples/bitwise_builtins.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/examples/control_flow.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/examples/enum_range_for.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/examples/gui_demo.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/examples/literals_types.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/examples/local_audio.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/examples/modules_demo.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/examples/stdlib_demo.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/examples/system_interaction.cin +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/misc/vim/ftdetect/codecin.vim +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/misc/vim/syntax/cin.vim +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/misc/vim/syntax/codecinasm.vim +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/misc/vscode-cin/.vscodeignore +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/misc/vscode-cin/README.md +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/misc/vscode-cin/build.bat +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/misc/vscode-cin/language-configuration.json +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/misc/vscode-cin/package.json +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/misc/vscode-cin/snippets/cin.json +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/misc/vscode-cin/syntaxes/cin.tmLanguage.json +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/pyproject.toml +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/script/bump_version.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/script/check_paths.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/script/gen_isa_docs.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/script/gen_native_isa.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/setup.cfg +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/setup.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_all_libs_together.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_aot.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_assembler_ext.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_bin_compat.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_cin_host.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_cin_host_ext.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_cin_syntax.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_cin_syntax_ext.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_cin_system.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_cli.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_compiler_errors.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_environment.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_examples.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_features_ab.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_features_import.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_gui.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_index_subscript_type.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_isa_single_source.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_issue_regress.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_keyboard.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_lib_compat.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_libs.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_literals_and_bom.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_native_codegen.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_native_hardening.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_nested_subscript_codegen.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_no_go_cli.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_object_link.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_p0_fixes.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_packaging.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_paths_consistency.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_switch_semantics.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_v620_cvm.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_v620_import.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_v620_mkn.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_v620_packaging.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_version.py +0 -0
- {codecin-6.2.2 → codecin-6.4.0}/tests/test_workflows.py +0 -0
|
@@ -5,6 +5,149 @@
|
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
+
## [6.4.0] - 2026-10-30
|
|
9
|
+
|
|
10
|
+
一次以「pic 搜索 / 版本管理 / 分块导入」为主题的发布:CIN 的 `import` 现在可以
|
|
11
|
+
按包、模块和版本选择(`rich:*` / `rich:table` / `rich::1.1.1:*`),不再只能
|
|
12
|
+
整包导入;`pic install` 默认安装最新版本;中央注册服务器补齐搜索、统计、
|
|
13
|
+
latest 指针、版本删除与浏览器后台管理页。
|
|
14
|
+
|
|
15
|
+
### 新增 (Added)
|
|
16
|
+
|
|
17
|
+
#### CIN 分块导入 (pic 包)
|
|
18
|
+
|
|
19
|
+
- `import` 新增包规格语法,与 `pic install` 共用
|
|
20
|
+
`codecin/packaging/spec.py`:
|
|
21
|
+
- `import "rich"` —— 包入口(兼容旧写法);
|
|
22
|
+
- `import "rich:*"` —— 入口 + 全部公开模块;
|
|
23
|
+
- `import "rich:table"` / `import "rich:table,markdown"` —— 指定模块;
|
|
24
|
+
- `import "rich::1.1.1:*"` / `import "rich::1.1.1:table"` —— 指定版本;
|
|
25
|
+
- `import "rich@1.1.1:table"` —— 旧式版本写法。
|
|
26
|
+
- 通配 `*` 跳过 `main.cin`、`test/`、`demo/`、`internal/` 等非公开模块;
|
|
27
|
+
显式选择私有模块时先展开入口,避免 `rich` 的 `internal/table.cin`
|
|
28
|
+
依赖 `style.cin` 符号而编译失败。
|
|
29
|
+
- 包版本解析支持全局存储 `$PIC_HOME/packages/<name>/<current>` 与显式
|
|
30
|
+
`::<版本>`;版本未安装时给出 `pic install <name>@<version>` 的可执行提示。
|
|
31
|
+
- 新增 `pic modules <name>`:列出已安装/远程包内可导入模块,并给出
|
|
32
|
+
`import "<name>:*"`、`import "<name>:<module>"` 示例。
|
|
33
|
+
|
|
34
|
+
#### pic 安装与搜索
|
|
35
|
+
|
|
36
|
+
- **默认安装最新版本**:`pic install <name>` 不写版本时按中央注册表的
|
|
37
|
+
`latest` 指针(无指针时取最高未撤回版本)解析,即使本地已安装旧版本
|
|
38
|
+
也会升级;`--project` 安装同样适用。`name@^1.2` / `name@1.2.3` 保持
|
|
39
|
+
“满足约束即可”的旧语义。
|
|
40
|
+
- `pic install` 支持 `name:*` / `name::<版本>:*` 规格;选择器只影响安装后
|
|
41
|
+
推荐的 `import` 写法,安装始终复制整个包。
|
|
42
|
+
- `pic search` 大幅增强:
|
|
43
|
+
- 搜索范围扩展为包名 / 仓库 / 描述 / 关键词;
|
|
44
|
+
- 相关度排序(精确 > 前缀 > 包含 > 关键词 > 描述 > 仓库);
|
|
45
|
+
- `--sort name|latest|updated|downloads|versions`、`--order asc|desc`、
|
|
46
|
+
`--limit` / `--offset` 分页、`--keyword` 过滤、`--json`;
|
|
47
|
+
- 输出 latest、版本数、下载量与描述。
|
|
48
|
+
- 新增 `pic versions <name>`(latest / yanked / installed 标记)、
|
|
49
|
+
`pic info <name>`(仓库、描述、关键词、许可证、入口、模块、下载量、
|
|
50
|
+
版本列表)。搜索、`versions`、`info`、`registry list` 改为公开只读,
|
|
51
|
+
无需登录。
|
|
52
|
+
|
|
53
|
+
#### pic 版本管理与后台
|
|
54
|
+
|
|
55
|
+
- 中央注册服务器新增:
|
|
56
|
+
- `latest` 指针与 `POST /api/v1/packages/{name}/{version}/latest`;
|
|
57
|
+
- 版本/整包删除 `DELETE /api/v1/packages/{name}[/{version}]`;
|
|
58
|
+
- 统计 `GET /api/v1/stats`、当前用户 `GET /api/v1/me`;
|
|
59
|
+
- 制品下载计数与包级/版本级 `downloads`;
|
|
60
|
+
- 发布时保存描述、关键词、许可证、入口、模块列表。
|
|
61
|
+
- 搜索 API 支持 `q` / `keyword` / `sort` / `order` / `limit` / `offset`,
|
|
62
|
+
返回 `total` / `count` / `offset` / `limit`,并包含描述、关键词、
|
|
63
|
+
下载量、已撤回版本数。
|
|
64
|
+
- 新增 `/admin` 浏览器后台管理页(零外部前端依赖):
|
|
65
|
+
- 统计卡片、包搜索/排序、包详情与版本表;
|
|
66
|
+
- 撤回/恢复版本、设置 latest、删除版本、删除整个包;
|
|
67
|
+
- 令牌保存在浏览器 `localStorage`,支持 URL fragment 传入;
|
|
68
|
+
- 管理员由 `PIC_ADMIN_EMAILS` / `PIC_ADMIN_IDS` 配置,未配置时发布者
|
|
69
|
+
仍可管理自己发布的包。
|
|
70
|
+
- 新增 `pic yank` / `pic unyank` / `pic latest` / `pic use` / `pic admin`
|
|
71
|
+
(`--no-browser` / `--print-token`)命令。
|
|
72
|
+
- latest 指向的版本被撤回时,解析自动回退到最高未撤回版本;
|
|
73
|
+
设置 latest 时拒绝已撤回版本。
|
|
74
|
+
|
|
75
|
+
### 变更 (Changed)
|
|
76
|
+
|
|
77
|
+
- 版本号提升至 **6.4.0**(`codecin/__init__.py` 单一真源,
|
|
78
|
+
`codecin/native/engine/version_gen.go` 同步;registry 服务端版本同步)。
|
|
79
|
+
- `pic install <name>` 不再优先复用本地任意已安装版本;默认 latest 会
|
|
80
|
+
升级到服务端最新版本。需要固定旧版本时显式写 `name@<版本>`。
|
|
81
|
+
- CIN `import "name"` / `import "name:*"` 默认选择**最高已安装版本**,
|
|
82
|
+
不再受 `$PIC_HOME/index.json` 的 `current` 指针影响(`current` 仍供
|
|
83
|
+
`pic show` / `pic use` 等本地命令使用);显式 `name::<版本>` 不变。
|
|
84
|
+
- 包记录新增可选字段 `latest` / `latest_pointer` / `description` /
|
|
85
|
+
`keywords` / `license` / `homepage` / `entry` / `modules` / `downloads`;
|
|
86
|
+
旧记录缺少这些字段时按默认值读取,向后兼容。
|
|
87
|
+
- `DELETE /api/v1/packages/{name}` 由 405 改为可删除(发布者或管理员);
|
|
88
|
+
删除不可恢复,后台页会二次确认。
|
|
89
|
+
- 服务端搜索默认按相关度/名称排序,`pic search` 输出列由 `REPO` 改为
|
|
90
|
+
`VERSIONS` / `DOWNLOADS` / `DESCRIPTION`。
|
|
91
|
+
|
|
92
|
+
### 修复 (Fixed)
|
|
93
|
+
|
|
94
|
+
- 修复 `pic install <name>` 在本地已安装旧版本时不会升级的问题。
|
|
95
|
+
- 修复 `pic search` 只能匹配包名/仓库、无法按描述/关键词搜索的问题。
|
|
96
|
+
- 修复 `pic` 缺少版本列表、latest、撤回恢复与后台管理入口的问题。
|
|
97
|
+
- 修复 `rich` 等包含私有模块的包在分块导入时缺少入口符号导致的
|
|
98
|
+
`Unknown function` 编译错误。
|
|
99
|
+
- 修复服务端统计中已撤回版本仍可能被当作 latest 的问题。
|
|
100
|
+
|
|
101
|
+
### 兼容性
|
|
102
|
+
|
|
103
|
+
- 既有 `import "./x.cin"`、`import "math.cin"`、`import "hello"`、
|
|
104
|
+
`import "hello/util.cin"` 写法全部保持;不带冒号的包名仍先查内置标准库。
|
|
105
|
+
- `pic install name@version`、`git+URL`、本地路径、`.cinpkg`、`mkn`
|
|
106
|
+
依赖解析行为不变;`mkn` 的空版本依赖同样默认最新。
|
|
107
|
+
- 服务端旧包记录可直接读取;`pic.lock` 格式不变。
|
|
108
|
+
|
|
109
|
+
## [6.3.1] - 2026-10-25
|
|
110
|
+
|
|
111
|
+
一次以「终端缓存与实时输出」为主题的小版本:新增终端缓存技术,启动/编译期间
|
|
112
|
+
提前键入的内容不再丢失,程序输出在执行过程中即可实时呈现,终端交互与动态特效
|
|
113
|
+
更加生动流畅;同时保留完整输出缓存,管道 / 重定向 / 测试捕获行为保持不变。
|
|
114
|
+
|
|
115
|
+
### 新增 (Added)
|
|
116
|
+
|
|
117
|
+
#### 终端缓存技术
|
|
118
|
+
|
|
119
|
+
- **输入缓存 (type-ahead)**:键盘监听 / 交互式行输入首次激活时,不再清空
|
|
120
|
+
终端里尚未被读取的残留输入,而是读入统一的键码队列 —— 用户在程序启动、
|
|
121
|
+
编译期间提前键入的字符不会丢失,`get_key` / `key_wait` / `input` /
|
|
122
|
+
`input_str` 可直接消费。
|
|
123
|
+
- Windows 端同时跳过鼠标、窗口、焦点与 key-up 事件继续读取,避免队列
|
|
124
|
+
被非按键事件卡住。
|
|
125
|
+
- 需要主动丢弃旧输入时调用 `key_flush()`:清空键码队列、解码中间态与
|
|
126
|
+
终端残留输入(Windows `FlushConsoleInputBuffer`,Unix 非阻塞排空)。
|
|
127
|
+
- **输出缓存**:实时输出模式下,程序输出在逐条写往终端的同时仍完整保留在
|
|
128
|
+
执行结果中(`Result.Output`),新增 `streamed` 标记告知宿主"已实时显示、
|
|
129
|
+
不要重复打印";API 调用方与测试仍可读取完整输出。
|
|
130
|
+
- **运行前状态实时显示**:真实终端下依次输出 `Loading <文件> ...` →
|
|
131
|
+
`Loaded N instructions in X ms` → `Running ...`,编译/装载阶段不再黑屏
|
|
132
|
+
等待;`--log-level ERROR` 与管道输出保持干净。
|
|
133
|
+
- **演示程序**:新增 `examples/terminal_cache_demo.cin`,覆盖打字机/旋转指示器/
|
|
134
|
+
进度条实时动画、动画期间提前输入的文字与原始键码读取,以及 `key_flush()`
|
|
135
|
+
显式清理;直接运行 `codecin examples/terminal_cache_demo.cin` 即可体验。
|
|
136
|
+
|
|
137
|
+
### 变更 (Changed)
|
|
138
|
+
|
|
139
|
+
- **执行与输出时效性优化**:Python CLI 与 AOT 产物(VM 后端及生成的原生
|
|
140
|
+
后端)在真实终端下改为边执行边写标准输出,`print` / 终端绘制类特效不再
|
|
141
|
+
等整个程序结束后一次性出现;管道 / 重定向 / 测试捕获仍保持"缓冲 + 结束
|
|
142
|
+
回传",输出字节与旧版本完全一致。
|
|
143
|
+
- **原生 ABI 扩展**:`codecin_run_v2` 的 `flags` 新增 bit1 = 实时输出请求;
|
|
144
|
+
结果缓冲 36 字节头中 `offset 2` 由保留字节改为 `streamed` 标志(`offset 3`
|
|
145
|
+
仍为保留字节),布局与长度不变。
|
|
146
|
+
- 版本号提升至 **6.3.1**(`codecin/__init__.py` 单一真源,
|
|
147
|
+
`codecin/native/engine/version_gen.go` 同步)。
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
8
151
|
## [6.2.2] - 2026-10-24
|
|
9
152
|
|
|
10
153
|
一次以「注册服务与输入设备」为主题的小版本:`registry` 服务端由 Go 迁移到
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codecin
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.4.0
|
|
4
4
|
Summary: Code CIN - 高级语言与运行时 (CIN/PL/ASM 工具链 + Go 原生 VM + ARM64/RISC-V/FP/Vector 指令集)
|
|
5
5
|
Author: ByUsi Studio, 北啊呢
|
|
6
6
|
License-Expression: MIT
|
|
@@ -34,14 +34,14 @@ Code CIN 是一门简洁的类 C 高级语言及其跨平台运行时(VM)。
|
|
|
34
34
|
|
|
35
35
|
模块化包结构(`codecin/`,Go 侧 `codecin/native/`),全线日志与错误输出基于 **rich**(彩色表格、面板、traceback),`--debug` / `--log-level DEBUG` 提供超详细诊断。
|
|
36
36
|
|
|
37
|
-
## v6.2.0 工具链:mkn / pic / cvm
|
|
37
|
+
## v6.2.0+ 工具链:mkn / pic / cvm
|
|
38
38
|
|
|
39
39
|
v6.2.0 在 `codecin` 之外提供三个独立命令,覆盖**构建 → 分发 → 运行**:
|
|
40
40
|
|
|
41
41
|
| 命令 | 类比 | 作用 |
|
|
42
42
|
|------|------|------|
|
|
43
43
|
| `mkn` | Maven | 项目清单、标准目录、生命周期、依赖解析、打包与本地仓库 |
|
|
44
|
-
| `pic` | pip | `package.codecin.org.cn` 中央注册/分发 + Cdifit 登录:发布登记标识名/Git 地址/版本列表/安全摘要并上传 `.cinpkg`,安装后可直接 `import` |
|
|
44
|
+
| `pic` | pip | `package.codecin.org.cn` 中央注册/分发 + Cdifit 登录:发布登记标识名/Git 地址/版本列表/安全摘要并上传 `.cinpkg`,安装后可直接 `import`;支持搜索、版本管理与 `/admin` 后台 |
|
|
45
45
|
| `cvm` | JVM | Code CIN 虚拟机:构建/校验/运行 `.cvm` 模块,支持模块路径;`CPU` 仅作为内部执行核 |
|
|
46
46
|
|
|
47
47
|
```bash
|
|
@@ -56,8 +56,14 @@ mkn package # target/demo-0.1.0.mkn
|
|
|
56
56
|
pic login
|
|
57
57
|
pic init hello
|
|
58
58
|
pic publish --repo https://github.com/you/cin-hello --name hello
|
|
59
|
+
pic install hello # 不写版本 -> 最新版本
|
|
59
60
|
pic install hello@^1.0 # 或 git+https://...、本地路径、.cinpkg
|
|
60
61
|
pic install hello --project # 安装到项目 pic_modules/,可直接 import
|
|
62
|
+
pic search hello --json # 搜索 (名称/描述/关键词, 分页/排序)
|
|
63
|
+
pic versions hello # 版本列表 (latest/yanked/installed)
|
|
64
|
+
pic info hello # 包详情
|
|
65
|
+
pic use hello 1.0.0 # 切换本地 current 版本
|
|
66
|
+
pic admin # 后台管理页 (版本/撤回/删除/latest)
|
|
61
67
|
pic whoami
|
|
62
68
|
pic logout
|
|
63
69
|
|
|
@@ -73,15 +79,17 @@ cvm env
|
|
|
73
79
|
登录和 Token 校验**。服务端实现见 [registry/README.md](registry/README.md),
|
|
74
80
|
客户端可用 `PIC_REGISTRY_URL` 覆盖服务器地址。
|
|
75
81
|
|
|
76
|
-
|
|
82
|
+
安装后的包无需修改源码即可导入,并支持按模块/版本分块导入
|
|
83
|
+
(不写版本时默认使用最高已安装版本):
|
|
77
84
|
|
|
78
85
|
```cin
|
|
79
|
-
import "hello"
|
|
80
|
-
import "hello/util.cin"
|
|
86
|
+
import "hello"
|
|
87
|
+
import "hello/util.cin"
|
|
88
|
+
import "hello:*" // 全部公开模块
|
|
89
|
+
import "hello:util" // 只导入 util 模块
|
|
90
|
+
import "hello::1.0.0:*" // 指定版本的全部公开模块
|
|
81
91
|
```
|
|
82
92
|
|
|
83
|
-
完整设计、格式与验收标准见 [V6.2.0-PLAN.md](V6.2.0-PLAN.md)。
|
|
84
|
-
|
|
85
93
|
## 文档
|
|
86
94
|
|
|
87
95
|
**官方文档站**位于独立仓库
|
|
@@ -16,14 +16,14 @@ Code CIN 是一门简洁的类 C 高级语言及其跨平台运行时(VM)。
|
|
|
16
16
|
|
|
17
17
|
模块化包结构(`codecin/`,Go 侧 `codecin/native/`),全线日志与错误输出基于 **rich**(彩色表格、面板、traceback),`--debug` / `--log-level DEBUG` 提供超详细诊断。
|
|
18
18
|
|
|
19
|
-
## v6.2.0 工具链:mkn / pic / cvm
|
|
19
|
+
## v6.2.0+ 工具链:mkn / pic / cvm
|
|
20
20
|
|
|
21
21
|
v6.2.0 在 `codecin` 之外提供三个独立命令,覆盖**构建 → 分发 → 运行**:
|
|
22
22
|
|
|
23
23
|
| 命令 | 类比 | 作用 |
|
|
24
24
|
|------|------|------|
|
|
25
25
|
| `mkn` | Maven | 项目清单、标准目录、生命周期、依赖解析、打包与本地仓库 |
|
|
26
|
-
| `pic` | pip | `package.codecin.org.cn` 中央注册/分发 + Cdifit 登录:发布登记标识名/Git 地址/版本列表/安全摘要并上传 `.cinpkg`,安装后可直接 `import` |
|
|
26
|
+
| `pic` | pip | `package.codecin.org.cn` 中央注册/分发 + Cdifit 登录:发布登记标识名/Git 地址/版本列表/安全摘要并上传 `.cinpkg`,安装后可直接 `import`;支持搜索、版本管理与 `/admin` 后台 |
|
|
27
27
|
| `cvm` | JVM | Code CIN 虚拟机:构建/校验/运行 `.cvm` 模块,支持模块路径;`CPU` 仅作为内部执行核 |
|
|
28
28
|
|
|
29
29
|
```bash
|
|
@@ -38,8 +38,14 @@ mkn package # target/demo-0.1.0.mkn
|
|
|
38
38
|
pic login
|
|
39
39
|
pic init hello
|
|
40
40
|
pic publish --repo https://github.com/you/cin-hello --name hello
|
|
41
|
+
pic install hello # 不写版本 -> 最新版本
|
|
41
42
|
pic install hello@^1.0 # 或 git+https://...、本地路径、.cinpkg
|
|
42
43
|
pic install hello --project # 安装到项目 pic_modules/,可直接 import
|
|
44
|
+
pic search hello --json # 搜索 (名称/描述/关键词, 分页/排序)
|
|
45
|
+
pic versions hello # 版本列表 (latest/yanked/installed)
|
|
46
|
+
pic info hello # 包详情
|
|
47
|
+
pic use hello 1.0.0 # 切换本地 current 版本
|
|
48
|
+
pic admin # 后台管理页 (版本/撤回/删除/latest)
|
|
43
49
|
pic whoami
|
|
44
50
|
pic logout
|
|
45
51
|
|
|
@@ -55,15 +61,17 @@ cvm env
|
|
|
55
61
|
登录和 Token 校验**。服务端实现见 [registry/README.md](registry/README.md),
|
|
56
62
|
客户端可用 `PIC_REGISTRY_URL` 覆盖服务器地址。
|
|
57
63
|
|
|
58
|
-
|
|
64
|
+
安装后的包无需修改源码即可导入,并支持按模块/版本分块导入
|
|
65
|
+
(不写版本时默认使用最高已安装版本):
|
|
59
66
|
|
|
60
67
|
```cin
|
|
61
|
-
import "hello"
|
|
62
|
-
import "hello/util.cin"
|
|
68
|
+
import "hello"
|
|
69
|
+
import "hello/util.cin"
|
|
70
|
+
import "hello:*" // 全部公开模块
|
|
71
|
+
import "hello:util" // 只导入 util 模块
|
|
72
|
+
import "hello::1.0.0:*" // 指定版本的全部公开模块
|
|
63
73
|
```
|
|
64
74
|
|
|
65
|
-
完整设计、格式与验收标准见 [V6.2.0-PLAN.md](V6.2.0-PLAN.md)。
|
|
66
|
-
|
|
67
75
|
## 文档
|
|
68
76
|
|
|
69
77
|
**官方文档站**位于独立仓库
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
- 定长数组就地存放 (数据段/栈帧); int[][] 为指向行指针数组的指针。
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
+
import fnmatch
|
|
22
23
|
import os
|
|
23
24
|
import re
|
|
24
25
|
import struct
|
|
@@ -656,7 +657,7 @@ def _package_roots(source_dir: str) -> List[str]:
|
|
|
656
657
|
os.path.expanduser('~'), '.pic')
|
|
657
658
|
packages = os.path.join(home, 'packages')
|
|
658
659
|
if os.path.isdir(packages):
|
|
659
|
-
# 全局存储是 <name>/<version>/;
|
|
660
|
+
# 全局存储是 <name>/<version>/; 默认选择最高已安装版本
|
|
660
661
|
roots.append(packages)
|
|
661
662
|
return roots
|
|
662
663
|
|
|
@@ -714,8 +715,27 @@ def _entry_from_package(pkg_dir: str, pkg: str,
|
|
|
714
715
|
return None
|
|
715
716
|
|
|
716
717
|
|
|
717
|
-
def
|
|
718
|
-
"""
|
|
718
|
+
def _semver_key(version: str) -> Tuple[int, int, int, int, str]:
|
|
719
|
+
"""版本排序键: 稳定版高于同号预发布版。"""
|
|
720
|
+
base = version.split('+', 1)[0]
|
|
721
|
+
core, _, pre = base.partition('-')
|
|
722
|
+
parts = core.split('.')
|
|
723
|
+
out: List[int] = []
|
|
724
|
+
for index in range(3):
|
|
725
|
+
try:
|
|
726
|
+
out.append(int(parts[index]))
|
|
727
|
+
except (IndexError, ValueError):
|
|
728
|
+
out.append(0)
|
|
729
|
+
return out[0], out[1], out[2], 0 if pre else 1, pre
|
|
730
|
+
|
|
731
|
+
|
|
732
|
+
def _version_dirs(pkg_dir: str) -> List[str]:
|
|
733
|
+
"""全局存储 ``<name>/<version>`` 下的版本目录。
|
|
734
|
+
|
|
735
|
+
v6.4.x 起 **最高版本优先**:CIN 的 ``import "pkg"`` 默认使用最新
|
|
736
|
+
已安装版本,而不是 ``index.json`` 里的 ``current`` 指针(``current``
|
|
737
|
+
仍供 ``pic show`` / ``pic use`` 等本地命令使用)。
|
|
738
|
+
"""
|
|
719
739
|
try:
|
|
720
740
|
versions = [
|
|
721
741
|
v for v in os.listdir(pkg_dir)
|
|
@@ -724,28 +744,253 @@ def _version_dirs(pkg_dir: str, root: str) -> List[str]:
|
|
|
724
744
|
]
|
|
725
745
|
except OSError:
|
|
726
746
|
return []
|
|
727
|
-
|
|
728
|
-
if os.path.basename(root) == 'packages':
|
|
729
|
-
index_path = os.path.join(os.path.dirname(root), 'index.json')
|
|
730
|
-
try:
|
|
731
|
-
import json
|
|
732
|
-
with open(index_path, encoding='utf-8') as f:
|
|
733
|
-
index = json.load(f)
|
|
734
|
-
record = (index.get('packages') or {}).get(
|
|
735
|
-
os.path.basename(pkg_dir)) or {}
|
|
736
|
-
current = record.get('current')
|
|
737
|
-
except (OSError, ValueError, TypeError):
|
|
738
|
-
current = None
|
|
739
|
-
versions.sort(reverse=True)
|
|
740
|
-
if current in versions:
|
|
741
|
-
versions.remove(current)
|
|
742
|
-
versions.insert(0, current)
|
|
747
|
+
versions.sort(key=lambda value: (_semver_key(value), value), reverse=True)
|
|
743
748
|
return [os.path.join(pkg_dir, v) for v in versions]
|
|
744
749
|
|
|
745
750
|
|
|
751
|
+
#: 分块导入 ``pkg:*`` 时跳过的目录: 测试/示例/私有模块不参与通配
|
|
752
|
+
_PACKAGE_WILDCARD_SKIP_DIRS = frozenset({
|
|
753
|
+
'internal', 'private', 'test', 'tests', '__tests__', 'demo', 'demos',
|
|
754
|
+
'example', 'examples', 'dist', 'build', 'target', 'node_modules',
|
|
755
|
+
'__pycache__', '.git', '.hg', '.svn', 'pic_modules', '.pic', '.mkn',
|
|
756
|
+
})
|
|
757
|
+
|
|
758
|
+
|
|
759
|
+
def _package_version(base: str) -> Optional[str]:
|
|
760
|
+
"""读取包目录 ``pic.toml`` / ``mkn.toml`` 的版本; 非包目录返回 None。"""
|
|
761
|
+
if not os.path.isdir(base):
|
|
762
|
+
return None
|
|
763
|
+
try:
|
|
764
|
+
from .packaging.model import load_mkn_manifest, load_package_manifest
|
|
765
|
+
if os.path.isfile(os.path.join(base, 'pic.toml')):
|
|
766
|
+
return load_package_manifest(base, require_entry=False).version
|
|
767
|
+
if os.path.isfile(os.path.join(base, 'mkn.toml')):
|
|
768
|
+
return load_mkn_manifest(base).version
|
|
769
|
+
except Exception: # noqa: BLE001 - 清单损坏时按"不是包"处理
|
|
770
|
+
return None
|
|
771
|
+
return None
|
|
772
|
+
|
|
773
|
+
|
|
774
|
+
def _package_bases(pkg_dir: str) -> List[str]:
|
|
775
|
+
"""一个包名目录下可用的包根 (项目目录本身 / 全局版本目录)。"""
|
|
776
|
+
bases: List[str] = []
|
|
777
|
+
if _package_version(pkg_dir) is not None:
|
|
778
|
+
bases.append(pkg_dir)
|
|
779
|
+
for version_dir in _version_dirs(pkg_dir):
|
|
780
|
+
if version_dir not in bases and _package_version(version_dir) is not None:
|
|
781
|
+
bases.append(version_dir)
|
|
782
|
+
return bases
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
def _iter_package_cin_files(base: str) -> List[Tuple[str, str]]:
|
|
786
|
+
"""返回包内全部 ``.cin`` (相对路径, 绝对路径), 按路径排序。"""
|
|
787
|
+
out: List[Tuple[str, str]] = []
|
|
788
|
+
for dirpath, dirnames, filenames in os.walk(base):
|
|
789
|
+
dirnames[:] = sorted(
|
|
790
|
+
d for d in dirnames
|
|
791
|
+
if d not in _PACKAGE_WILDCARD_SKIP_DIRS
|
|
792
|
+
and not d.startswith('.'))
|
|
793
|
+
for filename in sorted(filenames):
|
|
794
|
+
if not filename.endswith('.cin'):
|
|
795
|
+
continue
|
|
796
|
+
path = os.path.join(dirpath, filename)
|
|
797
|
+
rel = os.path.relpath(path, base).replace(os.sep, '/')
|
|
798
|
+
out.append((rel, path))
|
|
799
|
+
out.sort(key=lambda item: item[0])
|
|
800
|
+
return out
|
|
801
|
+
|
|
802
|
+
|
|
803
|
+
def _module_defines_main(path: str) -> bool:
|
|
804
|
+
try:
|
|
805
|
+
with open(path, encoding='utf-8-sig', errors='replace') as f:
|
|
806
|
+
text = f.read(1 << 20)
|
|
807
|
+
except OSError:
|
|
808
|
+
return False
|
|
809
|
+
return re.search(r'\bfunction\s+main\s*\(', text) is not None
|
|
810
|
+
|
|
811
|
+
|
|
812
|
+
def _module_is_internal(rel: str) -> bool:
|
|
813
|
+
lower = rel.lower()
|
|
814
|
+
return any(part in ('internal', 'private', 'test', 'tests', 'demo',
|
|
815
|
+
'demos', 'example', 'examples')
|
|
816
|
+
for part in lower.split('/')[:-1])
|
|
817
|
+
|
|
818
|
+
|
|
819
|
+
def _module_display(rel: str) -> str:
|
|
820
|
+
text = rel[:-4] if rel.endswith('.cin') else rel
|
|
821
|
+
return text[4:] if text.startswith('src/') else text
|
|
822
|
+
|
|
823
|
+
|
|
824
|
+
def _available_modules(base: str) -> List[str]:
|
|
825
|
+
return [_module_display(rel) for rel, _path in _iter_package_cin_files(base)
|
|
826
|
+
if os.path.basename(rel) not in ('main.cin', 'test.cin')]
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
def _match_module(base: str, selector: str) -> List[str]:
|
|
830
|
+
"""把 ``table`` / ``internal/table.cin`` / ``table*`` 解析为包内文件。"""
|
|
831
|
+
files = _iter_package_cin_files(base)
|
|
832
|
+
if not files:
|
|
833
|
+
return []
|
|
834
|
+
selector = selector.strip().replace('\\', '/')
|
|
835
|
+
if not selector:
|
|
836
|
+
return []
|
|
837
|
+
want = selector if selector.endswith('.cin') else selector + '.cin'
|
|
838
|
+
has_glob = any(ch in selector for ch in '*?[')
|
|
839
|
+
|
|
840
|
+
if has_glob:
|
|
841
|
+
matches = []
|
|
842
|
+
for rel, path in files:
|
|
843
|
+
stem = rel[:-4] if rel.endswith('.cin') else rel
|
|
844
|
+
display = _module_display(rel)
|
|
845
|
+
if fnmatch.fnmatch(rel, want) or fnmatch.fnmatch(stem, selector) \
|
|
846
|
+
or fnmatch.fnmatch(display, selector) \
|
|
847
|
+
or fnmatch.fnmatch(os.path.basename(stem), selector):
|
|
848
|
+
matches.append((_module_is_internal(rel), len(rel), rel, path))
|
|
849
|
+
matches.sort()
|
|
850
|
+
return [path for _internal, _size, _rel, path in matches]
|
|
851
|
+
|
|
852
|
+
# 快路径: 常见位置直接命中
|
|
853
|
+
for rel in (want, 'src/' + want, 'src/internal/' + want,
|
|
854
|
+
'internal/' + want, 'lib/' + want):
|
|
855
|
+
path = os.path.normpath(os.path.join(base, rel))
|
|
856
|
+
if os.path.isfile(path):
|
|
857
|
+
return [path]
|
|
858
|
+
|
|
859
|
+
fuzzy = []
|
|
860
|
+
for rel, path in files:
|
|
861
|
+
stem = rel[:-4] if rel.endswith('.cin') else rel
|
|
862
|
+
display = _module_display(rel)
|
|
863
|
+
if rel == want or rel.endswith('/' + want) or stem == selector \
|
|
864
|
+
or display == selector or display.endswith('/' + selector) \
|
|
865
|
+
or (('/' not in selector)
|
|
866
|
+
and os.path.basename(stem) == selector):
|
|
867
|
+
fuzzy.append((_module_is_internal(rel), len(rel), rel, path))
|
|
868
|
+
fuzzy.sort()
|
|
869
|
+
return [path for _internal, _size, _rel, path in fuzzy]
|
|
870
|
+
|
|
871
|
+
|
|
872
|
+
class _PackageModuleNotFound(CompilerError):
|
|
873
|
+
def __init__(self, base: str, selector: str):
|
|
874
|
+
self.base = base
|
|
875
|
+
self.selector = selector
|
|
876
|
+
available = ', '.join(_available_modules(base)) or '(无)'
|
|
877
|
+
super().__init__(
|
|
878
|
+
f"Import module not found: {selector!r} in {base}; "
|
|
879
|
+
f"可用模块: {available}")
|
|
880
|
+
|
|
881
|
+
|
|
882
|
+
def _path_is_internal(base: str, path: str) -> bool:
|
|
883
|
+
rel = os.path.relpath(path, base).replace(os.sep, '/')
|
|
884
|
+
return _module_is_internal(rel)
|
|
885
|
+
|
|
886
|
+
|
|
887
|
+
def _package_chunks(base: str, pkg: str,
|
|
888
|
+
spec) -> List[str]:
|
|
889
|
+
"""按规格收集包内文件; ``*`` 返回入口 + 全部公开模块。"""
|
|
890
|
+
entry = _entry_from_package(base, pkg)
|
|
891
|
+
if not spec.has_selector:
|
|
892
|
+
if entry is None:
|
|
893
|
+
raise _PackageModuleNotFound(base, '(entry)')
|
|
894
|
+
return [entry]
|
|
895
|
+
|
|
896
|
+
if spec.is_all:
|
|
897
|
+
targets: List[str] = []
|
|
898
|
+
seen: Set[str] = set()
|
|
899
|
+
|
|
900
|
+
def add(path: str) -> None:
|
|
901
|
+
real = os.path.realpath(path)
|
|
902
|
+
if real not in seen:
|
|
903
|
+
seen.add(real)
|
|
904
|
+
targets.append(path)
|
|
905
|
+
|
|
906
|
+
if entry:
|
|
907
|
+
add(entry)
|
|
908
|
+
for rel, path in _iter_package_cin_files(base):
|
|
909
|
+
if _module_is_internal(rel):
|
|
910
|
+
continue
|
|
911
|
+
if os.path.basename(rel) in ('main.cin', 'test.cin'):
|
|
912
|
+
continue
|
|
913
|
+
if _module_defines_main(path):
|
|
914
|
+
continue
|
|
915
|
+
add(path)
|
|
916
|
+
if not targets and entry is None:
|
|
917
|
+
raise _PackageModuleNotFound(base, '*')
|
|
918
|
+
return targets
|
|
919
|
+
|
|
920
|
+
targets = []
|
|
921
|
+
seen = set()
|
|
922
|
+
needs_entry = False
|
|
923
|
+
for module in spec.modules:
|
|
924
|
+
matches = _match_module(base, module)
|
|
925
|
+
if not matches:
|
|
926
|
+
raise _PackageModuleNotFound(base, module)
|
|
927
|
+
if any(_path_is_internal(base, path) for path in matches):
|
|
928
|
+
# 私有模块可能依赖入口统一导入的内部符号 (如 rich 的
|
|
929
|
+
# internal/table.cin 使用 style.cin 的 rich_markup); 先展开
|
|
930
|
+
# 入口保证符号完整, 再由 loaded 去重。
|
|
931
|
+
needs_entry = True
|
|
932
|
+
for path in matches:
|
|
933
|
+
real = os.path.realpath(path)
|
|
934
|
+
if real not in seen:
|
|
935
|
+
seen.add(real)
|
|
936
|
+
targets.append(path)
|
|
937
|
+
if needs_entry and entry:
|
|
938
|
+
real = os.path.realpath(entry)
|
|
939
|
+
if real not in seen:
|
|
940
|
+
targets.insert(0, entry)
|
|
941
|
+
return targets
|
|
942
|
+
|
|
943
|
+
|
|
944
|
+
def _resolve_package_chunks(spec, source_dir: str) -> Optional[List[str]]:
|
|
945
|
+
"""按包规格解析 import; 没有同名包时返回 None。"""
|
|
946
|
+
found = False
|
|
947
|
+
version_mismatch: List[str] = []
|
|
948
|
+
module_errors: List[_PackageModuleNotFound] = []
|
|
949
|
+
for root in _package_roots(source_dir):
|
|
950
|
+
pkg_dir = os.path.join(root, spec.name)
|
|
951
|
+
if not os.path.isdir(pkg_dir):
|
|
952
|
+
continue
|
|
953
|
+
bases = _package_bases(pkg_dir)
|
|
954
|
+
if not bases:
|
|
955
|
+
continue
|
|
956
|
+
found = True
|
|
957
|
+
if spec.version:
|
|
958
|
+
matching = [base for base in bases
|
|
959
|
+
if _package_version(base) == spec.version]
|
|
960
|
+
if not matching:
|
|
961
|
+
versions = sorted(
|
|
962
|
+
(v for v in (_package_version(b) for b in bases) if v),
|
|
963
|
+
reverse=True)
|
|
964
|
+
version_mismatch.append(
|
|
965
|
+
f'{spec.name}: 已安装 {", ".join(versions) or "(未知)"}')
|
|
966
|
+
continue
|
|
967
|
+
bases = matching
|
|
968
|
+
for base in bases:
|
|
969
|
+
try:
|
|
970
|
+
return _package_chunks(base, spec.name, spec)
|
|
971
|
+
except _PackageModuleNotFound as e:
|
|
972
|
+
module_errors.append(e)
|
|
973
|
+
|
|
974
|
+
if not found:
|
|
975
|
+
return None
|
|
976
|
+
if version_mismatch and not module_errors:
|
|
977
|
+
detail = '; '.join(dict.fromkeys(version_mismatch))
|
|
978
|
+
raise CompilerError(
|
|
979
|
+
f"Import file not found: {spec.display!r} (已安装版本不匹配: "
|
|
980
|
+
f"{detail})。可运行 `pic install {spec.name}@{spec.version}` 安装该版本。")
|
|
981
|
+
if module_errors:
|
|
982
|
+
error = module_errors[0]
|
|
983
|
+
raise CompilerError(
|
|
984
|
+
f"Import file not found: {spec.display!r} ({error}); "
|
|
985
|
+
f"先运行 `pic install {spec.name}`,再用 `pic modules {spec.name}` "
|
|
986
|
+
f"查看可导入的模块。")
|
|
987
|
+
raise CompilerError(
|
|
988
|
+
f"Import file not found: {spec.display!r} (包目录存在但无法读取入口文件)")
|
|
989
|
+
|
|
990
|
+
|
|
746
991
|
def _resolve_package_import(name: str,
|
|
747
992
|
source_dir: str) -> Optional[str]:
|
|
748
|
-
"""
|
|
993
|
+
"""按包名/相对包内路径解析 import (旧写法); 找不到返回 None。"""
|
|
749
994
|
normalized = name.replace('\\', '/')
|
|
750
995
|
parts = [p for p in normalized.split('/') if p]
|
|
751
996
|
if not parts:
|
|
@@ -765,7 +1010,7 @@ def _resolve_package_import(name: str,
|
|
|
765
1010
|
pkg_dir = os.path.join(root, pkg)
|
|
766
1011
|
if not os.path.isdir(pkg_dir):
|
|
767
1012
|
continue
|
|
768
|
-
version_dirs = _version_dirs(pkg_dir
|
|
1013
|
+
version_dirs = _version_dirs(pkg_dir)
|
|
769
1014
|
if sub:
|
|
770
1015
|
for base in [pkg_dir, os.path.join(pkg_dir, 'src'),
|
|
771
1016
|
*(os.path.join(v, 'src') for v in version_dirs),
|
|
@@ -785,11 +1030,13 @@ def _resolve_package_import(name: str,
|
|
|
785
1030
|
return None
|
|
786
1031
|
|
|
787
1032
|
|
|
788
|
-
def _resolve_import(name: str, source_dir: str) -> str:
|
|
789
|
-
"""解析 import
|
|
1033
|
+
def _resolve_import(name: str, source_dir: str) -> List[str]:
|
|
1034
|
+
"""解析 import 目标 (可能多个文件, 用于分块导入)。
|
|
790
1035
|
|
|
791
|
-
规则 (B3 + v6.2.
|
|
1036
|
+
规则 (B3 + v6.2.x 包导入):
|
|
792
1037
|
* ``import "./x.cin"`` / ``import "../x.cin"`` —— 相对**当前 .cin 文件**所在目录;
|
|
1038
|
+
* 包规格 ``rich`` / ``rich:*`` / ``rich:table`` / ``rich::1.1.1:*``
|
|
1039
|
+
按模块分块解析 (见 :mod:`codecin.packaging.spec`);
|
|
793
1040
|
* 其余形式先查 **codecin 内置标准库** ``codecin/lib/`` (``lib/`` 前缀保留
|
|
794
1041
|
为兼容写法), 保持 "裸名字不会命中兄弟文件" 的既有语义;
|
|
795
1042
|
* 再查项目依赖目录 (``pic_modules`` / ``.mkn/deps`` / ``.pic/packages``)、
|
|
@@ -799,20 +1046,35 @@ def _resolve_import(name: str, source_dir: str) -> str:
|
|
|
799
1046
|
if _is_relative_import(name):
|
|
800
1047
|
cand = os.path.normpath(os.path.join(source_dir, name))
|
|
801
1048
|
if os.path.isfile(cand):
|
|
802
|
-
return cand
|
|
1049
|
+
return [cand]
|
|
803
1050
|
raise CompilerError(
|
|
804
1051
|
f"Import file not found: {name!r} (相对引用, 已查找 {cand})")
|
|
805
1052
|
|
|
1053
|
+
if ':' in name:
|
|
1054
|
+
from .packaging.spec import SpecError, parse_package_spec
|
|
1055
|
+
try:
|
|
1056
|
+
spec = parse_package_spec(name)
|
|
1057
|
+
except SpecError:
|
|
1058
|
+
spec = None
|
|
1059
|
+
if spec is not None:
|
|
1060
|
+
targets = _resolve_package_chunks(spec, source_dir)
|
|
1061
|
+
if targets:
|
|
1062
|
+
return targets
|
|
1063
|
+
raise CompilerError(
|
|
1064
|
+
f"Import file not found: {name!r} (未找到包 {spec.name!r})。"
|
|
1065
|
+
f"先运行 `pic install {spec.name}`;指定版本用 "
|
|
1066
|
+
f"`import \"{spec.name}::<版本>:*\"`。")
|
|
1067
|
+
|
|
806
1068
|
candidates = [os.path.join(_LIB_DIR, name)]
|
|
807
1069
|
if name.startswith('lib/'):
|
|
808
1070
|
candidates.append(os.path.join(_LIB_DIR, name[len('lib/'):]))
|
|
809
1071
|
for cand in candidates:
|
|
810
1072
|
if os.path.isfile(cand):
|
|
811
|
-
return cand
|
|
1073
|
+
return [cand]
|
|
812
1074
|
|
|
813
1075
|
package = _resolve_package_import(name, source_dir)
|
|
814
1076
|
if package:
|
|
815
|
-
return package
|
|
1077
|
+
return [package]
|
|
816
1078
|
|
|
817
1079
|
raise CompilerError(
|
|
818
1080
|
f"Import file not found: {name!r} (内置标准库已查找 "
|
|
@@ -840,8 +1102,9 @@ def _collect_module_lines(path: str, loaded: set, active: set,
|
|
|
840
1102
|
for line in lines:
|
|
841
1103
|
m = _IMPORT_RE.match(line)
|
|
842
1104
|
if m:
|
|
843
|
-
|
|
844
|
-
|
|
1105
|
+
targets = _resolve_import(m.group(1), os.path.dirname(real))
|
|
1106
|
+
for target in targets:
|
|
1107
|
+
_collect_module_lines(target, loaded, active, out)
|
|
845
1108
|
continue
|
|
846
1109
|
out.append((real, line))
|
|
847
1110
|
active.discard(real)
|