forked from Rust-related/RustPython
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21e0ad6a2d | ||
|
|
8d510405f9 | ||
|
|
be42508cc6 | ||
|
|
f4c432b532 | ||
|
|
e0bfd18114 | ||
|
|
89d0e7f1e9 | ||
|
|
c8026f980e | ||
|
|
1929bc0953 |
5
.github/workflows/ci.yaml
vendored
5
.github/workflows/ci.yaml
vendored
@@ -161,11 +161,6 @@ jobs:
|
||||
run: python -m pip install flake8
|
||||
- name: run lint
|
||||
run: flake8 . --count --exclude=./.*,./Lib,./vm/Lib,./benches/ --select=E9,F63,F7,F82 --show-source --statistics
|
||||
- name: install prettier
|
||||
run: yarn global add prettier && echo "$(yarn global bin)" >>$GITHUB_PATH
|
||||
- name: check wasm code with prettier
|
||||
# prettier doesn't handle ignore files very well: https://github.com/prettier/prettier/issues/8506
|
||||
run: cd wasm && git ls-files -z | xargs -0 prettier --check -u
|
||||
miri:
|
||||
name: Run tests under miri
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
396
Cargo.lock
generated
396
Cargo.lock
generated
@@ -24,23 +24,6 @@ version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75b7e6a93ecd6dbd2c225154d0fa7f86205574ecaa6c87429fb5f66ee677c44"
|
||||
dependencies = [
|
||||
"getrandom 0.2.1",
|
||||
"lazy_static 1.4.0",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.15"
|
||||
@@ -74,6 +57,27 @@ dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arr_macro"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a105bfda48707cf19220129e78fca01e9639433ffaef4163546ed8fb04120a5"
|
||||
dependencies = [
|
||||
"arr_macro_impl",
|
||||
"proc-macro-hack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arr_macro_impl"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0609c78bd572f4edc74310dfb63a01f5609d53fa8b4dd7c4d98aef3b3e8d72d1"
|
||||
dependencies = [
|
||||
"proc-macro-hack",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.6"
|
||||
@@ -290,7 +294,7 @@ dependencies = [
|
||||
"ansi_term",
|
||||
"atty",
|
||||
"bitflags",
|
||||
"strsim",
|
||||
"strsim 0.8.0",
|
||||
"textwrap 0.11.0",
|
||||
"unicode-width",
|
||||
"vec_map",
|
||||
@@ -336,9 +340,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift"
|
||||
version = "0.69.0"
|
||||
version = "0.68.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "910322bd748b9b2450947659a48a928f35b8ba7212d80d719ff85e4b7cde62b7"
|
||||
checksum = "60686f89c5145bc9a961dabbb83954baa429bde4c5977a0a5d3f8552f2990273"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"cranelift-frontend",
|
||||
@@ -346,18 +350,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.69.0"
|
||||
version = "0.68.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4066fd63b502d73eb8c5fa6bcab9c7962b05cd580f6b149ee83a8e730d8ce7fb"
|
||||
checksum = "9221545c0507dc08a62b2d8b5ffe8e17ac580b0a74d1813b496b8d70b070fbd0"
|
||||
dependencies = [
|
||||
"cranelift-entity",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.69.0"
|
||||
version = "0.68.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a54e4beb833a3c873a18a8fe735d73d732044004c7539a072c8faa35ccb0c60"
|
||||
checksum = "7e9936ea608b6cd176f107037f6adbb4deac933466fc7231154f96598b2d3ab1"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"cranelift-bforest",
|
||||
@@ -373,9 +377,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.69.0"
|
||||
version = "0.68.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c54cac7cacb443658d8f0ff36a3545822613fa202c946c0891897843bc933810"
|
||||
checksum = "4ef2b2768568306540f4c8db3acce9105534d34c4a1e440529c1e702d7f8c8d7"
|
||||
dependencies = [
|
||||
"cranelift-codegen-shared",
|
||||
"cranelift-entity",
|
||||
@@ -383,21 +387,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.69.0"
|
||||
version = "0.68.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a109760aff76788b2cdaeefad6875a73c2b450be13906524f6c2a81e05b8d83c"
|
||||
checksum = "6759012d6d19c4caec95793f052613e9d4113e925e7f14154defbac0f1d4c938"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.69.0"
|
||||
version = "0.68.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b044234aa32531f89a08b487630ddc6744696ec04c8123a1ad388de837f5de3"
|
||||
checksum = "86badbce14e15f52a45b666b38abe47b204969dd7f8fb7488cb55dd46b361fa6"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.69.0"
|
||||
version = "0.68.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5452b3e4e97538ee5ef2cc071301c69a86c7adf2770916b9d04e9727096abd93"
|
||||
checksum = "b608bb7656c554d0a4cf8f50c7a10b857e80306f6ff829ad6d468a7e2323c8d8"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"log",
|
||||
@@ -405,30 +409,11 @@ dependencies = [
|
||||
"target-lexicon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-jit"
|
||||
version = "0.69.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ffd9b060436974c7e777630ad459f3609ff1b868f43419ad63297be6bbf61ad"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
"cranelift-entity",
|
||||
"cranelift-module",
|
||||
"cranelift-native",
|
||||
"errno",
|
||||
"libc",
|
||||
"log",
|
||||
"region",
|
||||
"target-lexicon",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-module"
|
||||
version = "0.69.0"
|
||||
version = "0.68.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b17bc01cb9f176156d5cbd47ece19292e04e05a91a837dcf0ef69cc1e0e97a5a"
|
||||
checksum = "fdaf0b5c93a610ff988fe5e2adbb7f6afa89cf702ca41acc3479dc35638d3a8d"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
@@ -439,15 +424,33 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-native"
|
||||
version = "0.69.0"
|
||||
version = "0.68.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f68035c10b2e80f26cc29c32fa824380877f38483504c2a47b54e7da311caaf3"
|
||||
checksum = "5246a1af14b7812ee4d94a3f0c4b295ec02c370c08b0ecc3dec512890fdad175"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"raw-cpuid",
|
||||
"target-lexicon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-simplejit"
|
||||
version = "0.68.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2522ebdff6ba637c0b5e75bc3d40cc990ac1128e13547b740f10fc7b16d3991"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"cranelift-entity",
|
||||
"cranelift-module",
|
||||
"cranelift-native",
|
||||
"errno",
|
||||
"libc",
|
||||
"log",
|
||||
"region",
|
||||
"target-lexicon",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc"
|
||||
version = "1.8.1"
|
||||
@@ -548,12 +551,6 @@ dependencies = [
|
||||
"lazy_static 1.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||
|
||||
[[package]]
|
||||
name = "crypto-mac"
|
||||
version = "0.7.0"
|
||||
@@ -673,6 +670,18 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "docopt"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969"
|
||||
dependencies = [
|
||||
"lazy_static 1.4.0",
|
||||
"regex",
|
||||
"serde",
|
||||
"strsim 0.9.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dtoa"
|
||||
version = "0.4.6"
|
||||
@@ -746,6 +755,26 @@ version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
|
||||
[[package]]
|
||||
name = "fehler"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5729fe49ba028cd550747b6e62cd3d841beccab5390aa398538c31a2d983635"
|
||||
dependencies = [
|
||||
"fehler-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fehler-macros"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccb5acb1045ebbfa222e2c50679e392a71dd77030b78fb0189f2d9c5974400f9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.2.0"
|
||||
@@ -856,18 +885,6 @@ dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"libc",
|
||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4060f4657be78b8e766215b02b18a2e862d83745545de804638e2b545e81aee6"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi 0.10.0+wasi-snapshot-preview1",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
@@ -882,9 +899,6 @@ name = "hashbrown"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
||||
dependencies = [
|
||||
"ahash 0.4.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
@@ -997,35 +1011,34 @@ checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7"
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop"
|
||||
version = "0.19.4"
|
||||
version = "0.19.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a71d75b267b3299da9ccff4dd80d73325b5d8adcd76fe97cf92725eb7c6f122"
|
||||
checksum = "60fb56191fb8ed5311597e5750debe6779c9fdb487dbaa5ff302592897d7a2c8"
|
||||
dependencies = [
|
||||
"ascii-canvas",
|
||||
"atty",
|
||||
"bit-set",
|
||||
"diff",
|
||||
"docopt",
|
||||
"ena",
|
||||
"itertools",
|
||||
"lalrpop-util",
|
||||
"petgraph",
|
||||
"pico-args",
|
||||
"regex",
|
||||
"regex-syntax",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"sha2",
|
||||
"string_cache",
|
||||
"term",
|
||||
"tiny-keccak",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop-util"
|
||||
version = "0.19.4"
|
||||
version = "0.19.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ebbd90154472db6267a7d28ca08fea7788e5619fef10f2398155cb74c08f77a"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
checksum = "6771161eff561647fad8bb7e745e002c304864fb8f436b52b30acda51fca4408"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
@@ -1054,9 +1067,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.81"
|
||||
version = "0.2.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
|
||||
checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
|
||||
|
||||
[[package]]
|
||||
name = "libffi"
|
||||
@@ -1116,10 +1129,17 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lz4_flex"
|
||||
version = "0.7.0"
|
||||
name = "lz-fear"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9025814971d70dd729afe3b93b02d653c905dadb9821d5578458e12dea5148f"
|
||||
checksum = "06aad1ce45e4ccf7a8d7d43e0c3ad38dc5d2255174a5f29a3c39d961fbc6181d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"fehler",
|
||||
"thiserror",
|
||||
"twox-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mach"
|
||||
@@ -1186,11 +1206,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mt19937"
|
||||
version = "2.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e6dd1b4462edbfbc0c4ad4c3205d94623bb94b4819aa0888936988d38834158"
|
||||
checksum = "c674293daac706360a8fa633c802ca15d27ee4a52394f12ecec2f6d2aa5508bf"
|
||||
dependencies = [
|
||||
"rand_core 0.6.0",
|
||||
"rand",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1422,41 +1443,6 @@ dependencies = [
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
|
||||
dependencies = [
|
||||
"phf_macros",
|
||||
"phf_shared",
|
||||
"proc-macro-hack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"rand 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_macros"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.8.0"
|
||||
@@ -1466,12 +1452,6 @@ dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pico-args"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28b9b4df73455c861d7cbf8be42f01d3b373ed7f02e378d55fa84eafc6f638b1"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.19"
|
||||
@@ -1537,12 +1517,6 @@ dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "puruspe"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96e65ac785a4b9fe1d1046da0a3b5fad0a2a1606c66e41f5bfb86be8851ea0c3"
|
||||
|
||||
[[package]]
|
||||
name = "python3-sys"
|
||||
version = "0.5.1"
|
||||
@@ -1574,24 +1548,11 @@ version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||
dependencies = [
|
||||
"getrandom 0.1.15",
|
||||
"getrandom",
|
||||
"libc",
|
||||
"rand_chacha 0.2.2",
|
||||
"rand_core 0.5.1",
|
||||
"rand_hc 0.2.0",
|
||||
"rand_pcg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a76330fb486679b4ace3670f117bbc9e16204005c4bde9c4bd372f45bed34f12"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha 0.3.0",
|
||||
"rand_core 0.6.0",
|
||||
"rand_hc 0.3.0",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_hc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1601,17 +1562,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core 0.6.0",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1620,16 +1571,7 @@ version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
dependencies = [
|
||||
"getrandom 0.1.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8b34ba8cfb21243bd8df91854c830ff0d785fff2e82ebd4434c2644cb9ada18"
|
||||
dependencies = [
|
||||
"getrandom 0.2.1",
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1638,32 +1580,14 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||
dependencies = [
|
||||
"rand_core 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
|
||||
dependencies = [
|
||||
"rand_core 0.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_pcg"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
|
||||
dependencies = [
|
||||
"rand_core 0.5.1",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw-cpuid"
|
||||
version = "8.1.2"
|
||||
version = "7.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fdf7d9dbd43f3d81d94a49c1c3df73cc2b3827995147e6cf7f89d4ec5483e73"
|
||||
checksum = "b4a349ca83373cfa5d6dbb66fd76e58b2cca08da71a5f6400de0a0a6a9bceeaf"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
@@ -1707,7 +1631,7 @@ version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d"
|
||||
dependencies = [
|
||||
"getrandom 0.1.15",
|
||||
"getrandom",
|
||||
"redox_syscall",
|
||||
"rust-argon2",
|
||||
]
|
||||
@@ -1845,7 +1769,7 @@ dependencies = [
|
||||
"bitflags",
|
||||
"bstr",
|
||||
"itertools",
|
||||
"lz4_flex",
|
||||
"lz-fear",
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
"serde",
|
||||
@@ -1865,7 +1789,7 @@ dependencies = [
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"rand 0.8.0",
|
||||
"rand",
|
||||
"siphasher",
|
||||
"volatile",
|
||||
]
|
||||
@@ -1884,17 +1808,15 @@ dependencies = [
|
||||
name = "rustpython-compiler-core"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"ahash 0.6.2",
|
||||
"arrayvec",
|
||||
"indexmap",
|
||||
"insta",
|
||||
"itertools",
|
||||
"log",
|
||||
"num-complex",
|
||||
"num-traits",
|
||||
"rustpython-ast",
|
||||
"rustpython-bytecode",
|
||||
"rustpython-parser",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1919,8 +1841,8 @@ version = "0.1.2"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"cranelift",
|
||||
"cranelift-jit",
|
||||
"cranelift-module",
|
||||
"cranelift-simplejit",
|
||||
"libffi",
|
||||
"num-traits",
|
||||
"rustpython-bytecode",
|
||||
@@ -1932,14 +1854,11 @@ dependencies = [
|
||||
name = "rustpython-parser"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"ahash 0.6.2",
|
||||
"hashbrown",
|
||||
"lalrpop",
|
||||
"lalrpop-util",
|
||||
"log",
|
||||
"num-bigint",
|
||||
"num-traits",
|
||||
"phf",
|
||||
"rustpython-ast",
|
||||
"unic-emoji-char",
|
||||
"unic-ucd-ident",
|
||||
@@ -1959,12 +1878,13 @@ name = "rustpython-vm"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"adler32",
|
||||
"ahash 0.6.2",
|
||||
"arr_macro",
|
||||
"atty",
|
||||
"base64",
|
||||
"bitflags",
|
||||
"blake2",
|
||||
"bstr",
|
||||
"byteorder",
|
||||
"caseless",
|
||||
"cfg-if 0.1.10",
|
||||
"chrono",
|
||||
@@ -1980,8 +1900,7 @@ dependencies = [
|
||||
"flate2",
|
||||
"foreign-types-shared",
|
||||
"gethostname",
|
||||
"getrandom 0.2.1",
|
||||
"half",
|
||||
"getrandom",
|
||||
"hex",
|
||||
"hexf-parse",
|
||||
"indexmap",
|
||||
@@ -1991,6 +1910,7 @@ dependencies = [
|
||||
"libc",
|
||||
"libz-sys",
|
||||
"log",
|
||||
"maplit",
|
||||
"md-5",
|
||||
"mt19937",
|
||||
"nix",
|
||||
@@ -2007,9 +1927,8 @@ dependencies = [
|
||||
"openssl-sys",
|
||||
"parking_lot",
|
||||
"paste",
|
||||
"puruspe",
|
||||
"rand 0.8.0",
|
||||
"rand_core 0.6.0",
|
||||
"rand",
|
||||
"rand_core",
|
||||
"regex",
|
||||
"result-like",
|
||||
"rustc_version_runtime",
|
||||
@@ -2029,6 +1948,7 @@ dependencies = [
|
||||
"sha3",
|
||||
"socket2",
|
||||
"static_assertions",
|
||||
"statrs",
|
||||
"thiserror",
|
||||
"thread_local",
|
||||
"timsort",
|
||||
@@ -2244,12 +2164,13 @@ checksum = "ae524f056d7d770e174287294f562e95044c68e88dec909a00d2094805db9d75"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.3.19"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e"
|
||||
checksum = "2c29947abdee2a218277abeca306f25789c938e500ea5a9d4b12a5a504466902"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
@@ -2259,6 +2180,15 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "statrs"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cce16f6de653e88beca7bd13780d08e09d4489dbca1f9210e041bc4852481382"
|
||||
dependencies = [
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "string_cache"
|
||||
version = "0.8.1"
|
||||
@@ -2269,6 +2199,7 @@ dependencies = [
|
||||
"new_debug_unreachable",
|
||||
"phf_shared",
|
||||
"precomputed-hash",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2277,6 +2208,12 @@ version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "1.0.0"
|
||||
@@ -2423,15 +2360,6 @@ version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3cb4fa83bb73adf1c7219f4fe4bf3c0ac5635e4e51e070fad5df745a41bedfb8"
|
||||
|
||||
[[package]]
|
||||
name = "tiny-keccak"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinytemplate"
|
||||
version = "1.1.0"
|
||||
@@ -2466,6 +2394,16 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "twox-hash"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04f8ab788026715fa63b31960869617cba39117e520eb415b0139543e325ab59"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.12.0"
|
||||
@@ -2664,12 +2602,6 @@ version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
|
||||
|
||||
[[package]]
|
||||
name = "volatile"
|
||||
version = "0.3.0"
|
||||
|
||||
@@ -68,5 +68,9 @@ opt-level = 3
|
||||
|
||||
[patch.crates-io]
|
||||
# REDOX START, Uncommment when you want to compile/check with redoxer
|
||||
# # following patches are just waiting on a new version to be released to crates.io
|
||||
# nix = { git = "https://github.com/nix-rust/nix" }
|
||||
# crossbeam-utils = { git = "https://github.com/crossbeam-rs/crossbeam" }
|
||||
# socket2 = { git = "https://github.com/alexcrichton/socket2-rs" }
|
||||
# REDOX END
|
||||
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: DES-EDE3-CBC,E74528136B90D2DD
|
||||
|
||||
WRHVD2PJXPqjFSHg92HURIsUzvsTE4a9oi0SC5yMBFKNWA5Z933gK3XTifp6jul5
|
||||
zpNYi8jBXZ2EqJJBxCuVcefmXSxL0q7CMej25TdIC4BVAFJVveeprHPUFkNB0IM1
|
||||
go5Lg4YofYqTCg3OE3k7WvfR3Zg1cRYxksDKO+WNZgWyKBex5X4vjOiyUqDl3GKt
|
||||
kQXnkg1VgPV2Vrx93S9XNdELNRTguwf+XG0fkhtYhp/zCto8uKTgy5elK2P/ulGp
|
||||
7fe6uj7h/uN9L7EOC6CjRkitywfeBUER739mOcGT4imSFJ9G27TCqPzj2ea3uuaf
|
||||
/v1xhkQ4M6lNY/gcRfgVpCXhW43aAQV8XXQRMJTqLmz5Y5hYTKn+Ugq5vJ/ngyRM
|
||||
lu1gUJnYYaemBTb4hbm6aBvnYK9mORa891Pmf+vxU9rYuQIdVAhvvXh4KBreSEBI
|
||||
1AFy6dFKXl8ZKs6Wrq5wPefmFFkRmZ8OBiiq0fp2ApCRGZw6LsjCgwrRM38JiY7d
|
||||
3OdsJpKvRYufgUyuuzUE0xA+E4yMvD48M9pPq2fC8O5giuGL1uEekQWXJuq+6ZRI
|
||||
XYKIeSkuQALbX3RAzCPXTUEMtCYXKm/gxrrwJ+Bet4ob2amf3MX0uvWwOuAq++Fk
|
||||
J0HFSBxrwvIWOhyQXOPuJdAN8PXA7dWOXfOgOMF0hQYqZCl3T4TiVZJbwVQtg1sN
|
||||
dO7oAD5ZPHiKzvveZuB6k1FlBG8j0TyAC+44ChxkPDD3jF4dd6zGe62sDf85p4/d
|
||||
W80gxJeD3xnDxG0ePPns+GuKUpUaWS7WvHtDpeFW1JEhvOqf8p1Li9a7RzWVo8ML
|
||||
mGTdQgBIYIf6/fk69pFKl0nKtBU75KaunZz4nAmd9bNED4naDurMBg44u5TvODbJ
|
||||
vgYIYXIYjNvONbskJatVrrTS8zch2NwVIjCi8L/hecwBXbIXzo1pECpc6BU7sQT8
|
||||
+i9sDKBeJcRipzfKZNHvnO19mUZaPCY8+a/f9c21DgKXz+bgLcJbohpSaeGM8Gfc
|
||||
aZd3Vp9n3OJ3g2zQR1++HO9v1vR/wLELu6MeydkvMduHLmOPCn54gZ9z51ZNPAwa
|
||||
qfFIsH+mLh9ks0H74ssF59uIlstkgB9zmZHv/Q0dK9ZfG/VEH6rSgdETWhZxhoMQ
|
||||
Z92jXBEFT0zhI3rrIPNY+XS7eJCQIc1wc84Ea3cRk7SP+S1og3JtAxX56ykUwtkM
|
||||
LQ/Dwwa6h1aqD0l2d5x1/BSdavtTuSegISRWQ4iOmSvEdlFP7H4g6RZk/okbLzMD
|
||||
Evq5gNc7vlXhVawoQU8JCanJ5ZbbWnIRZfiXxBQS4lpYPKvJt4ML9z/x+82XxcXv
|
||||
Z93N2Wep7wWW5OwS2LcQcOgZRDSIPompwo/0pMFGOS+5oort0ZDRHdmmGLjvBcCb
|
||||
1KQmKQ4+8brI/3rjRzts6uDLjTGNxSCieNsnqhwHUv9Mg9WDSWupcGa+x27L89x3
|
||||
rObf6+3umcFLSjIzU8wuv1hx/e/y98Kv7BDBNYpAr6kVMrLnzYjAfJbBmqlxkzkQ
|
||||
IgQzgrk2QZoTdgwR+S374NAMO0AE5IlO+/qa6qp2SORGTDX64I3UNw==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDWTCCAkGgAwIBAgIJAPm6B21bar2bMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV
|
||||
BAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEjMCEGA1UECgwaUHl0aG9u
|
||||
IFNvZnR3YXJlIEZvdW5kYXRpb24xEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xODAx
|
||||
MTkxOTA5MDZaFw0yODAxMTcxOTA5MDZaMF8xCzAJBgNVBAYTAlhZMRcwFQYDVQQH
|
||||
DA5DYXN0bGUgQW50aHJheDEjMCEGA1UECgwaUHl0aG9uIFNvZnR3YXJlIEZvdW5k
|
||||
YXRpb24xEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||
ADCCAQoCggEBAKvvsX2gEti4shve3iYMc+jE4Se7WHs1Bol2f21H8qNboDOFdeb1
|
||||
RKHjmq3exHpajywOUEgne9nKHJY/3f2phR4Y5klqG6liLgiSpVyRlcBGbeT2qEAj
|
||||
9oLiLFUXLGfGDds2mTwivQDLJBWi51j7ff5k2Pr58fN5ugYMn24T9FNyn0moT+qj
|
||||
SFoBNm58l9jrdkJSlgWfqPlbiMa+mqDn/SFtrwLF2Trbfzu42Sd9UdIzMaSSrzbN
|
||||
sGm53pNhCh8KndWUQ8GPP2IsLPoUU4qAtmZuTxCx2S1cXrN9EkmT69tlOH84YfSn
|
||||
96Ih9bWRc7M5y5bfVdEVM+fKQl3hBRf05qMCAwEAAaMYMBYwFAYDVR0RBA0wC4IJ
|
||||
bG9jYWxob3N0MA0GCSqGSIb3DQEBCwUAA4IBAQAtQ8f37cCEk7/rAcbYR53ce3iK
|
||||
Vpihb0U2ni1QjG9Tg9UIExkIGkwTiCm7kwQL+GEStBu9AG/QVrOjeTriRiddhWkk
|
||||
ze8kRaI3AC/63t6Vh9Q1x6PESgeE4OtAO9JpJCf4GILglA789Y/b/GF8zJZQxR13
|
||||
qpB4ZwWw7gCBhdEW59u6CFeBmfDa58hM8lWvuVoRrTi7bjUeC6PAn5HVMzZSykhu
|
||||
4HaUfBp6bKFjuym2+h/VvM1n8C3chjVSmutsLb6ELdD8IK0vPV/yf5+LN256zSsS
|
||||
dyUZYd8XwQaioEMKdbhLvnehyzHiWfQIUR3BdhONxoIJhHv/EAo8eCkHHYIF
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,48 +0,0 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCr77F9oBLYuLIb
|
||||
3t4mDHPoxOEnu1h7NQaJdn9tR/KjW6AzhXXm9USh45qt3sR6Wo8sDlBIJ3vZyhyW
|
||||
P939qYUeGOZJahupYi4IkqVckZXARm3k9qhAI/aC4ixVFyxnxg3bNpk8Ir0AyyQV
|
||||
oudY+33+ZNj6+fHzeboGDJ9uE/RTcp9JqE/qo0haATZufJfY63ZCUpYFn6j5W4jG
|
||||
vpqg5/0hba8Cxdk62387uNknfVHSMzGkkq82zbBpud6TYQofCp3VlEPBjz9iLCz6
|
||||
FFOKgLZmbk8QsdktXF6zfRJJk+vbZTh/OGH0p/eiIfW1kXOzOcuW31XRFTPnykJd
|
||||
4QUX9OajAgMBAAECggEAHppmXDbuw9Z0FVPg9KLIysioTtsgz6VLiZIm8juZK4x2
|
||||
glUh/D7xvWL2uDXrgN+3lh7iGUW13LkFx5SMncbbo9TIwI57Z/XKvcnkVwquve+L
|
||||
RfLFVc1Q5lD9lROv2rS86KTaN4LzYz3FKXi6dvMkpPAsUtfEQhMLkmISypQQq/1z
|
||||
EJaqo7r85OjN7e0wKazlKZpOzJEa5FQLMVRjTRFhLFNbHXX/tAet2jw+umATKbw8
|
||||
hYgiuZ44TwSEd9JeIV/oSYWfI/3HetuYW0ru3caiztRF2NySNu8lcsWgNC7fIku9
|
||||
mcHjtSNzs91QN1Qlu7GQvvhpt6OWDirNDCW+49WGaQKBgQDg9SDhfF0jRYslgYbH
|
||||
cqO4ggaFdHjrAAYpwnAgvanhFZL/zEqm5G1E7l/e2fCkJ9VOSFO0A208chvwMcr+
|
||||
dCjHE2tVdE81aQ2v/Eo83VdS1RcOV4Y75yPH48rMhxPaHvxWD/FFDbf0/P2mtPB7
|
||||
SZ3kIeZMkE1wxdaO3AKUbQoozwKBgQDDqYgg7kVtygyICE1mB8Hwp6nUxFTczG7y
|
||||
4XcsDqMIrKmw+PbQluvkoHoStxeVrsTloDhkTjIrpmYLyAiazg+PUJdkd6xrfLSj
|
||||
VV6X93W0S/1egEb1F1CGFxtk8v/PWH4K76EPL2vxXdxjywz3GWlrL9yDYaB2szzS
|
||||
DqgwVMqx7QKBgDCD7UF0Bsoyl13RX3XoPXLvZ+SkR+e2q52Z94C4JskKVBeiwX7Y
|
||||
yNAS8M4pBoMArDoj0xmBm69rlKbqtjLGbnzwrTdSzDpim7cWnBQgUFLm7gAD1Elb
|
||||
AhZ8BCK0Bw4FnLoa2hfga4oEfdfUMgEE0W5/+SEOBgWKRUmuHUhRc911AoGAY2EN
|
||||
YmSDYSM5wDIvVb5k9B3EtevOiqNPSw/XnsoEZtiEC/44JnQxdltIBY93bDBrk5IQ
|
||||
cmoBM4h91kgQjshQwOMXMhFSwvmBKmCm/hrTbvMVytTutXfVD3ZXFKwT4DW7N0TF
|
||||
ElhsxBh/YzRz7mG62JVjtFt2zDN3ld2Z8YpvtXUCgYEA4EJ4ObS5YyvcXAKHJFo6
|
||||
Fxmavyrf8LSm3MFA65uSnFvWukMVqqRMReQc5jvpxHKCis+XvnHzyOfL0gW9ZTi7
|
||||
tWGGbBi0TRJCa8BkvgngUZxOxUlMfg/7cVxOIB0TPoUSgxFd/+qVz4GZMvr0dPu7
|
||||
eAF7J/8ECVvb0wSPTUI1N3c=
|
||||
-----END PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDWTCCAkGgAwIBAgIJAPm6B21bar2bMA0GCSqGSIb3DQEBCwUAMF8xCzAJBgNV
|
||||
BAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEjMCEGA1UECgwaUHl0aG9u
|
||||
IFNvZnR3YXJlIEZvdW5kYXRpb24xEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xODAx
|
||||
MTkxOTA5MDZaFw0yODAxMTcxOTA5MDZaMF8xCzAJBgNVBAYTAlhZMRcwFQYDVQQH
|
||||
DA5DYXN0bGUgQW50aHJheDEjMCEGA1UECgwaUHl0aG9uIFNvZnR3YXJlIEZvdW5k
|
||||
YXRpb24xEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEP
|
||||
ADCCAQoCggEBAKvvsX2gEti4shve3iYMc+jE4Se7WHs1Bol2f21H8qNboDOFdeb1
|
||||
RKHjmq3exHpajywOUEgne9nKHJY/3f2phR4Y5klqG6liLgiSpVyRlcBGbeT2qEAj
|
||||
9oLiLFUXLGfGDds2mTwivQDLJBWi51j7ff5k2Pr58fN5ugYMn24T9FNyn0moT+qj
|
||||
SFoBNm58l9jrdkJSlgWfqPlbiMa+mqDn/SFtrwLF2Trbfzu42Sd9UdIzMaSSrzbN
|
||||
sGm53pNhCh8KndWUQ8GPP2IsLPoUU4qAtmZuTxCx2S1cXrN9EkmT69tlOH84YfSn
|
||||
96Ih9bWRc7M5y5bfVdEVM+fKQl3hBRf05qMCAwEAAaMYMBYwFAYDVR0RBA0wC4IJ
|
||||
bG9jYWxob3N0MA0GCSqGSIb3DQEBCwUAA4IBAQAtQ8f37cCEk7/rAcbYR53ce3iK
|
||||
Vpihb0U2ni1QjG9Tg9UIExkIGkwTiCm7kwQL+GEStBu9AG/QVrOjeTriRiddhWkk
|
||||
ze8kRaI3AC/63t6Vh9Q1x6PESgeE4OtAO9JpJCf4GILglA789Y/b/GF8zJZQxR13
|
||||
qpB4ZwWw7gCBhdEW59u6CFeBmfDa58hM8lWvuVoRrTi7bjUeC6PAn5HVMzZSykhu
|
||||
4HaUfBp6bKFjuym2+h/VvM1n8C3chjVSmutsLb6ELdD8IK0vPV/yf5+LN256zSsS
|
||||
dyUZYd8XwQaioEMKdbhLvnehyzHiWfQIUR3BdhONxoIJhHv/EAo8eCkHHYIF
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,49 +0,0 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC3ulRNfhbOAey/
|
||||
B+wIVYx+d5az7EV4riR6yi/qE6G+bxbTvay2pqySHtDweuaYSh2cVmcasBKKIFJm
|
||||
rCD1zR8UmLb5i2XFIina1t3eePCuBZMrvZZwkzlQUSM1AZtjGOO/W0I3FwO6y645
|
||||
9xA5PduKI7SMYkH/VL3zE5W1JwMovv6bvNiT+GU5l6mB9ylCTgLpmUqoQhRqz/35
|
||||
zCzVyoh+ppDvVcpWYfvXywsXsgQwbAF0QJm8SSFi0TZm5ykv4WE16afQp08yuZS0
|
||||
3U4K3MJCa4rxO58edcxBopWYfQ29K3iINM8enRfr5q+u5mAAbALAEEvyFjgLWl/u
|
||||
7arxn7bJAgMBAAECggEBAJfMt8KfHzBunrDnVrk8FayYGkfmOzAOkc1yKEx6k/TH
|
||||
zFB+Mqlm5MaF95P5t3S0J+r36JBAUdEWC38RUNpF9BwMYYGlDxzlsTdCuGYL/q+J
|
||||
o6NMLXQt7/jQUQqGnWAvPFzqhbcGqOo5R2ZVH25sEWv9PDuRI35XAepIkDTwWsfa
|
||||
P6UcJJoP+4v9B++fb3sSL4zNwp1BqS4wxR8YTR0t1zQqOxJ5BGPw1J8aBMs1sq5t
|
||||
qyosAQAT63kLrdqWotHaM26QxjqEQUMlh12XMWb5GdBXUxbvyGtEabsqskGa/f8B
|
||||
RdHE437J8D8l+jxb2mZLzrlaH3dq2tbFGCe1rT8qLRECgYEA5CWIvoD/YnQydLGA
|
||||
OlEhCSocqURuqcotg9Ev0nt/C60jkr/NHFLGppz9lhqjIDjixt3sIMGZMFzxRtwM
|
||||
pSYal3XiR7rZuHau9iM35yDhpuytEiGbYy1ADakJRzY5jq/Qa8RfPP9Atua5xAeP
|
||||
q6DiSnq9vhHv9G+O4MxzHBmrw9sCgYEAziiJWFthcwvuXn3Jv9xFYKEb/06puZAx
|
||||
EgQCz/3rPzv5fmGD/sKVo1U/K4z/eA82DNeKG8QRTFJCxT8TCNRxOmGV7HdCYo/B
|
||||
4BTNNvbKcdi3l0j75kKoADg+nt5CD5lz6gLG0GrUEnVO1y5HVfCTb3BEAfa36C85
|
||||
9i0sfQGiwysCgYEAuus9k8cgdct5oz3iLuVVSark/JGCkT2B+OOkaLChsDFUWeEm
|
||||
7TOsaclpwldkmvvAYOplkZjMJ2GelE2pVo1XcAw3LkmaI5WpVyQXoxe/iQGT8qzy
|
||||
IFlsh0Scw2lb0tmcyw6CcPk4TiHOxRrkzNrtS9QwLM+JZx0XVHptPPKTVc0CgYAu
|
||||
j/VFYY5G/8Dc0qhIjyWUR48dQNUQtkJ/ASzpcT46z/7vznKTjbtiYpSb74KbyUO5
|
||||
7sygrM4DYOj3x+Eys1jHiNbly6HQxQtS4x/edCsRP5NntfI+9XsgYZOzKhvdjhki
|
||||
F3J0DEzNxnUCIM+311hVaRPTJbgv1srOkTFlIoNydQKBgQC6/OHGaC/OewQqRlRK
|
||||
Mg5KZm01/pk4iKrpA5nG7OTAeoa70NzXNtG8J3WnaJ4mWanNwNUOyRMAMrsUAy9q
|
||||
EeGqHM5mMFpY4TeVuNLL21lu/x3KYw6mKL3Ctinn+JLAoYoqEy8deZnEA5/tjYlz
|
||||
YhFBchnUicjoUN1chdpM6SpV2Q==
|
||||
-----END PRIVATE KEY-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDYjCCAkqgAwIBAgIJALJXRr8qF6oIMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNV
|
||||
BAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEjMCEGA1UECgwaUHl0aG9u
|
||||
IFNvZnR3YXJlIEZvdW5kYXRpb24xFTATBgNVBAMMDGZha2Vob3N0bmFtZTAeFw0x
|
||||
ODAxMTkxOTA5MDZaFw0yODAxMTcxOTA5MDZaMGIxCzAJBgNVBAYTAlhZMRcwFQYD
|
||||
VQQHDA5DYXN0bGUgQW50aHJheDEjMCEGA1UECgwaUHl0aG9uIFNvZnR3YXJlIEZv
|
||||
dW5kYXRpb24xFTATBgNVBAMMDGZha2Vob3N0bmFtZTCCASIwDQYJKoZIhvcNAQEB
|
||||
BQADggEPADCCAQoCggEBALe6VE1+Fs4B7L8H7AhVjH53lrPsRXiuJHrKL+oTob5v
|
||||
FtO9rLamrJIe0PB65phKHZxWZxqwEoogUmasIPXNHxSYtvmLZcUiKdrW3d548K4F
|
||||
kyu9lnCTOVBRIzUBm2MY479bQjcXA7rLrjn3EDk924ojtIxiQf9UvfMTlbUnAyi+
|
||||
/pu82JP4ZTmXqYH3KUJOAumZSqhCFGrP/fnMLNXKiH6mkO9VylZh+9fLCxeyBDBs
|
||||
AXRAmbxJIWLRNmbnKS/hYTXpp9CnTzK5lLTdTgrcwkJrivE7nx51zEGilZh9Db0r
|
||||
eIg0zx6dF+vmr67mYABsAsAQS/IWOAtaX+7tqvGftskCAwEAAaMbMBkwFwYDVR0R
|
||||
BBAwDoIMZmFrZWhvc3RuYW1lMA0GCSqGSIb3DQEBCwUAA4IBAQCZhHhGItpkqhEq
|
||||
ntMRd6Hv0GoOJixNvgeMwK4NJSRT/no3OirtUTzccn46h+SWibSa2eVssAV+pAVJ
|
||||
HbzkN/DH27A1mMx1zJL1ekcOKA1AF6MXhUnrUGXMqW36YNtzHfXJLrwvpLJ13OQg
|
||||
/Kxo4Nw68bGzM+PyRtKU/mpgYyfcvwR+ZSeIDh1fvUZK/IEVCf8ub42GPVs5wPfv
|
||||
M+k5aHxWTxeif3K1byTRzxHupYNG2yWO4XEdnBGOuOwzzN4/iQyNcsuQKeuKHGrt
|
||||
YvIlG/ri04CQ7xISZCj74yjTZ+/A2bXre2mQXAHqKPumHL7cl34+erzbUaxYxbTE
|
||||
u5FcOmLQ
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,132 +0,0 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDgV4G+Zzf2DT5n
|
||||
oAisIGFhn/bz7Vn5WiXUqbDsxROJOh/7BtOlduZka0pPhFylGbnxS8l1kEWHRI2T
|
||||
6hOoWzumB6ItKiN+T5J30lAvSyo7iwdFoAQ/S5nPXQfhNARQe/NEOhRtpcuNdyx4
|
||||
BWdPdPuJQA1ASNJCLwcLOoRxaLbKLvb2V5T5FCAkeNPtRvPuT4gKQItMmiHfAhoV
|
||||
C8MZWF/GC0RukHINys5MwqeFexam8CznmQPMYrLdhmKTj3DTivCPoh97EDIFGlgZ
|
||||
SCaaYDVQA+aqlo/q2pi52PFwC1KzhNEA7EeOqSwC1NQjwjHuhcnf9WbxrgTq2zh3
|
||||
rv5YEW2ZAgMBAAECggEAPfSMtTumPcJskIumuXp7yk02EyliZrWZqwBuBwVqHsS5
|
||||
nkbFXnXWrLbgn9MrDsFrE5NdgKUmPnQVMVs8sIr5jyGejSCNCs4I4iRn1pfIgwcj
|
||||
K/xEEALd6GGF0pDd/CgvB5GOoLVf4KKf2kmLvWrOKJpSzoUN5A8+v8AaYYOMr4sC
|
||||
czbvfGomzEIewEG+Rw9zOVUDlmwyEKPQZ47E7PQ+EEA7oeFdR+1Zj6eT9ndegf8B
|
||||
54frySYCLRUCk/sHCpWhaJBtBrcpht7Y8CfY7hiH/7x866fvuLnYPz4YALtUb0wN
|
||||
7zUCNS9ol3n4LbjFFKfZtiRjKaCBRzMjK0rz6ydFcQKBgQDyLI3oGbnW73vqcDe/
|
||||
6eR0w++fiCAVhfMs3AO/gOaJi2la2JHlJ5u+cIHQIOFwEhn6Zq0AtdmnFx1TS5IQ
|
||||
C0MdXI0XoQQw7rEF8EJcvfe85Z0QxENVhzydtdb8QpJfnQGfBfLyQlaaRYzRRHB6
|
||||
VdYUHF3EIPVIhbjbghal+Qep/QKBgQDtJlRPHkWwTMevu0J0fYbWN1ywtVTFUR//
|
||||
k7VyORSf8yuuSnaQRop4cbcqONxmDKH6Or1fl3NYBsAxtXkkOK1E2OZNo2sfQdRa
|
||||
wpA7o7mPHRhztQFpT5vflp+8P6+PEFat8D04eBOhNwrwwfhiPjD4gv5KvN4XutRW
|
||||
VWv/2pnmzQKBgHPvHGg2mJ7quvm6ixXW1MWJX1eSBToIjCe3lBvDi5nhIaiZ8Q4w
|
||||
7gA3QA3xD7tlDwauzLeAVxgEmsdbcCs6GQEfY3QiYy1Bt4FOSZa4YrcNfSmfq1Rw
|
||||
j3Y4rRjKjeQz96i3YlzToT3tecJc7zPBj+DEy6au2H3Fdn+vQURneWHJAoGBANG7
|
||||
XES8mRVaUh/wlM1BVsaNH8SIGfiHzqzRjV7/bGYpQTBbWpAuUrhCmaMVtpXqBjav
|
||||
TFwGLVRkZAWSYRjPpy2ERenT5SE3rv61o6mbGrifGsj6A82HQmtzYsGx8SmtYXtj
|
||||
REF0sKebbmmOooUAS379GrguYJzL9o6D7YfRZNrhAoGAVfb/tiFU4S67DSpYpQey
|
||||
ULhgfsFpDByICY6Potsg67gVFf9jIaB83NPTx3u/r6sHFgxFw7lQsuZcgSuWMu7t
|
||||
glzOXVIP11Y5sl5CJ5OsfeK1/0umMZF5MWPyAQCx/qrPlZL86vXjt24Y/VaOxsAi
|
||||
CZYdyJsjgOrJrWoMbo5ta54=
|
||||
-----END PRIVATE KEY-----
|
||||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number:
|
||||
82:ed:bf:41:c8:80:91:9c
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Issuer: C=XY, O=Python Software Foundation CA, CN=our-ca-server
|
||||
Validity
|
||||
Not Before: Jan 19 19:09:06 2018 GMT
|
||||
Not After : Nov 28 19:09:06 2027 GMT
|
||||
Subject: C=XY, L=Castle Anthrax, O=Python Software Foundation, CN=localhost
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (2048 bit)
|
||||
Modulus:
|
||||
00:e0:57:81:be:67:37:f6:0d:3e:67:a0:08:ac:20:
|
||||
61:61:9f:f6:f3:ed:59:f9:5a:25:d4:a9:b0:ec:c5:
|
||||
13:89:3a:1f:fb:06:d3:a5:76:e6:64:6b:4a:4f:84:
|
||||
5c:a5:19:b9:f1:4b:c9:75:90:45:87:44:8d:93:ea:
|
||||
13:a8:5b:3b:a6:07:a2:2d:2a:23:7e:4f:92:77:d2:
|
||||
50:2f:4b:2a:3b:8b:07:45:a0:04:3f:4b:99:cf:5d:
|
||||
07:e1:34:04:50:7b:f3:44:3a:14:6d:a5:cb:8d:77:
|
||||
2c:78:05:67:4f:74:fb:89:40:0d:40:48:d2:42:2f:
|
||||
07:0b:3a:84:71:68:b6:ca:2e:f6:f6:57:94:f9:14:
|
||||
20:24:78:d3:ed:46:f3:ee:4f:88:0a:40:8b:4c:9a:
|
||||
21:df:02:1a:15:0b:c3:19:58:5f:c6:0b:44:6e:90:
|
||||
72:0d:ca:ce:4c:c2:a7:85:7b:16:a6:f0:2c:e7:99:
|
||||
03:cc:62:b2:dd:86:62:93:8f:70:d3:8a:f0:8f:a2:
|
||||
1f:7b:10:32:05:1a:58:19:48:26:9a:60:35:50:03:
|
||||
e6:aa:96:8f:ea:da:98:b9:d8:f1:70:0b:52:b3:84:
|
||||
d1:00:ec:47:8e:a9:2c:02:d4:d4:23:c2:31:ee:85:
|
||||
c9:df:f5:66:f1:ae:04:ea:db:38:77:ae:fe:58:11:
|
||||
6d:99
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Subject Alternative Name:
|
||||
DNS:localhost
|
||||
X509v3 Key Usage: critical
|
||||
Digital Signature, Key Encipherment
|
||||
X509v3 Extended Key Usage:
|
||||
TLS Web Server Authentication, TLS Web Client Authentication
|
||||
X509v3 Basic Constraints: critical
|
||||
CA:FALSE
|
||||
X509v3 Subject Key Identifier:
|
||||
85:11:BE:16:47:04:D1:30:EE:86:8A:18:70:BE:A8:28:6F:82:3D:CE
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:9A:CF:CF:6E:EB:71:3D:DB:3C:F1:AE:88:6B:56:72:03:CB:08:A7:48
|
||||
DirName:/C=XY/O=Python Software Foundation CA/CN=our-ca-server
|
||||
serial:82:ED:BF:41:C8:80:91:9B
|
||||
|
||||
Authority Information Access:
|
||||
CA Issuers - URI:http://testca.pythontest.net/testca/pycacert.cer
|
||||
OCSP - URI:http://testca.pythontest.net/testca/ocsp/
|
||||
|
||||
X509v3 CRL Distribution Points:
|
||||
|
||||
Full Name:
|
||||
URI:http://testca.pythontest.net/testca/revocation.crl
|
||||
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
7f:a1:7e:3e:68:01:b0:32:b8:57:b8:03:68:13:13:b3:e3:f4:
|
||||
70:2f:15:e5:0f:87:b9:fd:e0:12:e3:16:f2:91:53:c7:4e:25:
|
||||
af:ca:cb:a7:d9:9d:57:4d:bf:a2:80:d4:78:aa:04:31:fd:6d:
|
||||
cc:6d:82:43:e9:62:16:0d:0e:26:8b:e7:f1:3d:57:5c:68:02:
|
||||
9c:2b:b6:c9:fd:62:2f:10:85:88:cc:44:a5:e7:a2:3e:89:f2:
|
||||
1f:02:6a:3f:d0:3c:6c:24:2d:bc:51:62:7a:ec:25:c5:86:87:
|
||||
77:35:8f:f9:7e:d0:17:3d:77:56:bf:1a:0c:be:09:78:ee:ea:
|
||||
73:97:65:60:94:91:35:b3:5c:46:8a:5e:6d:94:52:de:48:b7:
|
||||
1f:6c:28:79:7f:ff:08:8d:e4:7d:d0:b9:0b:7c:ae:c4:1d:2a:
|
||||
a1:b3:50:11:82:03:5e:6c:e7:26:fa:05:32:39:07:83:49:b9:
|
||||
a2:fa:04:da:0d:e5:ff:4c:db:97:d0:c3:a7:43:37:4c:16:de:
|
||||
3c:b5:e9:7e:82:d4:b3:10:df:d1:c1:66:72:9c:15:67:19:3b:
|
||||
7b:91:0a:82:07:67:c5:06:03:5f:80:54:08:81:8a:b1:5c:7c:
|
||||
4c:d2:07:38:92:eb:12:f5:71:ae:de:05:15:c8:e1:33:f0:e4:
|
||||
96:0f:0f:1e
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE8TCCA9mgAwIBAgIJAILtv0HIgJGcMA0GCSqGSIb3DQEBBQUAME0xCzAJBgNV
|
||||
BAYTAlhZMSYwJAYDVQQKDB1QeXRob24gU29mdHdhcmUgRm91bmRhdGlvbiBDQTEW
|
||||
MBQGA1UEAwwNb3VyLWNhLXNlcnZlcjAeFw0xODAxMTkxOTA5MDZaFw0yNzExMjgx
|
||||
OTA5MDZaMF8xCzAJBgNVBAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEj
|
||||
MCEGA1UECgwaUHl0aG9uIFNvZnR3YXJlIEZvdW5kYXRpb24xEjAQBgNVBAMMCWxv
|
||||
Y2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOBXgb5nN/YN
|
||||
PmegCKwgYWGf9vPtWflaJdSpsOzFE4k6H/sG06V25mRrSk+EXKUZufFLyXWQRYdE
|
||||
jZPqE6hbO6YHoi0qI35PknfSUC9LKjuLB0WgBD9Lmc9dB+E0BFB780Q6FG2ly413
|
||||
LHgFZ090+4lADUBI0kIvBws6hHFotsou9vZXlPkUICR40+1G8+5PiApAi0yaId8C
|
||||
GhULwxlYX8YLRG6Qcg3KzkzCp4V7FqbwLOeZA8xist2GYpOPcNOK8I+iH3sQMgUa
|
||||
WBlIJppgNVAD5qqWj+ramLnY8XALUrOE0QDsR46pLALU1CPCMe6Fyd/1ZvGuBOrb
|
||||
OHeu/lgRbZkCAwEAAaOCAcAwggG8MBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAOBgNV
|
||||
HQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1Ud
|
||||
EwEB/wQCMAAwHQYDVR0OBBYEFIURvhZHBNEw7oaKGHC+qChvgj3OMH0GA1UdIwR2
|
||||
MHSAFJrPz27rcT3bPPGuiGtWcgPLCKdIoVGkTzBNMQswCQYDVQQGEwJYWTEmMCQG
|
||||
A1UECgwdUHl0aG9uIFNvZnR3YXJlIEZvdW5kYXRpb24gQ0ExFjAUBgNVBAMMDW91
|
||||
ci1jYS1zZXJ2ZXKCCQCC7b9ByICRmzCBgwYIKwYBBQUHAQEEdzB1MDwGCCsGAQUF
|
||||
BzAChjBodHRwOi8vdGVzdGNhLnB5dGhvbnRlc3QubmV0L3Rlc3RjYS9weWNhY2Vy
|
||||
dC5jZXIwNQYIKwYBBQUHMAGGKWh0dHA6Ly90ZXN0Y2EucHl0aG9udGVzdC5uZXQv
|
||||
dGVzdGNhL29jc3AvMEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly90ZXN0Y2EucHl0
|
||||
aG9udGVzdC5uZXQvdGVzdGNhL3Jldm9jYXRpb24uY3JsMA0GCSqGSIb3DQEBBQUA
|
||||
A4IBAQB/oX4+aAGwMrhXuANoExOz4/RwLxXlD4e5/eAS4xbykVPHTiWvysun2Z1X
|
||||
Tb+igNR4qgQx/W3MbYJD6WIWDQ4mi+fxPVdcaAKcK7bJ/WIvEIWIzESl56I+ifIf
|
||||
Amo/0DxsJC28UWJ67CXFhod3NY/5ftAXPXdWvxoMvgl47upzl2VglJE1s1xGil5t
|
||||
lFLeSLcfbCh5f/8IjeR90LkLfK7EHSqhs1ARggNebOcm+gUyOQeDSbmi+gTaDeX/
|
||||
TNuX0MOnQzdMFt48tel+gtSzEN/RwWZynBVnGTt7kQqCB2fFBgNfgFQIgYqxXHxM
|
||||
0gc4kusS9XGu3gUVyOEz8OSWDw8e
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,132 +0,0 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDH/76hZAZH4cSV
|
||||
CmVZa5HEqKCjCKrcPwBECs9BS+3ibwN4x9NnFNP+tCeFGgJXl7WGFoeXgg3oK+1p
|
||||
FsOWpsRHuF3BdqkCnShSydmT8bLaGHwKeL0cPxJP5T/uW7ezPKW2VWXGMwmwRaRJ
|
||||
9dj2VCUu20vDZWSGFr9zjnjoJczBtH3RsVUgpK7euEHuQ5pIM9QSOaCo+5FPR7s7
|
||||
1nU7YqbFWtd+NhC8Og1G497B31DQlHciF6BRm6/cNGAmHaAErKUGBFdkGtFPHBn4
|
||||
vktoEg9fwxJAZLvGpoTZWrB4HRsRwVTmFdGvK+JXK225xF23AXRXp/snhSuSFeLj
|
||||
E5cpyJJ7AgMBAAECggEAQOv527X2e/sDr0XSpHZQuT/r9UBpBlnFIlFH+fBF5k0X
|
||||
GWv0ae/O6U1dzs0kmX57xG0n0ry6+vTXeleTYiH8cTOd66EzN9AAOO+hG29IGZf9
|
||||
HAEZkkO/FARc/mjzdtFnEYsjIHWM3ZWdwQx3Q28JKu6w51rQiN51g3NqOCGdF/uF
|
||||
rE5XPKsKndn+nLHvsNuApFgUYZEwdrozgUueEgRaPTUCNhzotcA9eWoBdA24XNhk
|
||||
x8Cm/bZWabXm7gBO75zl3Cu2F21ay+EuwyOZTsx6lZi6YX9/zo1mkO81Zi3tQk50
|
||||
NMEI0feLNwsdxTbmOcVJadjOgd+QVghlFyr5HGBWMQKBgQD3AH3rhnAo6tOyNkGN
|
||||
+IzIU1MhUS452O7IavykUYO9sM24BVChpRtlI9Dpev4yE/q3BAO3+oWT3cJrN7/3
|
||||
iyo1dzAkpGvI65XWfElXFM4nLjEiZzx4W9fiPN91Oucpr0ED6+BZXTtz4gVm0TP/
|
||||
TUc2xvTB6EKvIyWmKOYEi0snxQKBgQDPSOjbz9jWOrC9XY7PmtLB6QJDDz7XSGVK
|
||||
wzD+gDAPpAwhk58BEokdOhBx2Lwl8zMJi0CRHgH2vNvkRyhvUQ4UFzisrqann/Tw
|
||||
klp5sw3iWC6ERC8z9zL7GfHs7sK3mOVeAdK6ffowPM3JrZ2vPusVBdr0MN3oZwki
|
||||
CtNXqbY1PwKBgGheQNbAW6wubX0kB9chavtKmhm937Z5v4vYCSC1gOEqUAKt3EAx
|
||||
L74wwBmn6rjmUE382EVpCgBM99WuHONQXmlxD1qsTw763LlgkuzE0cckcYaD8L06
|
||||
saHa7uDuHrcyYlpx1L5t8q0ol/e19i6uTKUMtGcq6OJwC3yGU4sgAIWxAoGBAMVq
|
||||
qiQXm2vFL+jafxYoXUvDMJ1PmskMsTP4HOR2j8+FrOwZnVk3HxGP6HOVOPRn4JbZ
|
||||
YiAT1Uj6a+7I+rCyINdvmlGUcTK6fFzW9oZryvBkjcD483/pkktmVWwTpa2YV/Ml
|
||||
h16IdsyUTGYlDUYHhXtbPUJOfDpIT4F1j/0wrFGfAoGAO82BcUsehEUQE0xvQLIn
|
||||
7QaFtUI5z19WW730jVuEobiYlh9Ka4DPbKMvka8MwyOxEwhk39gZQavmfG6+wZm+
|
||||
kjERU23LhHziJGWS2Um4yIhC7myKbWaLzjHEq72dszLpQku4BzE5fT60fxI7cURD
|
||||
WGm/Z3Q2weS3ZGIoMj1RNPI=
|
||||
-----END PRIVATE KEY-----
|
||||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number:
|
||||
82:ed:bf:41:c8:80:91:9d
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Issuer: C=XY, O=Python Software Foundation CA, CN=our-ca-server
|
||||
Validity
|
||||
Not Before: Jan 19 19:09:06 2018 GMT
|
||||
Not After : Nov 28 19:09:06 2027 GMT
|
||||
Subject: C=XY, L=Castle Anthrax, O=Python Software Foundation, CN=fakehostname
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (2048 bit)
|
||||
Modulus:
|
||||
00:c7:ff:be:a1:64:06:47:e1:c4:95:0a:65:59:6b:
|
||||
91:c4:a8:a0:a3:08:aa:dc:3f:00:44:0a:cf:41:4b:
|
||||
ed:e2:6f:03:78:c7:d3:67:14:d3:fe:b4:27:85:1a:
|
||||
02:57:97:b5:86:16:87:97:82:0d:e8:2b:ed:69:16:
|
||||
c3:96:a6:c4:47:b8:5d:c1:76:a9:02:9d:28:52:c9:
|
||||
d9:93:f1:b2:da:18:7c:0a:78:bd:1c:3f:12:4f:e5:
|
||||
3f:ee:5b:b7:b3:3c:a5:b6:55:65:c6:33:09:b0:45:
|
||||
a4:49:f5:d8:f6:54:25:2e:db:4b:c3:65:64:86:16:
|
||||
bf:73:8e:78:e8:25:cc:c1:b4:7d:d1:b1:55:20:a4:
|
||||
ae:de:b8:41:ee:43:9a:48:33:d4:12:39:a0:a8:fb:
|
||||
91:4f:47:bb:3b:d6:75:3b:62:a6:c5:5a:d7:7e:36:
|
||||
10:bc:3a:0d:46:e3:de:c1:df:50:d0:94:77:22:17:
|
||||
a0:51:9b:af:dc:34:60:26:1d:a0:04:ac:a5:06:04:
|
||||
57:64:1a:d1:4f:1c:19:f8:be:4b:68:12:0f:5f:c3:
|
||||
12:40:64:bb:c6:a6:84:d9:5a:b0:78:1d:1b:11:c1:
|
||||
54:e6:15:d1:af:2b:e2:57:2b:6d:b9:c4:5d:b7:01:
|
||||
74:57:a7:fb:27:85:2b:92:15:e2:e3:13:97:29:c8:
|
||||
92:7b
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Subject Alternative Name:
|
||||
DNS:fakehostname
|
||||
X509v3 Key Usage: critical
|
||||
Digital Signature, Key Encipherment
|
||||
X509v3 Extended Key Usage:
|
||||
TLS Web Server Authentication, TLS Web Client Authentication
|
||||
X509v3 Basic Constraints: critical
|
||||
CA:FALSE
|
||||
X509v3 Subject Key Identifier:
|
||||
F8:76:79:CB:11:85:F0:46:E5:95:E6:7E:69:CB:12:5E:4E:AA:EC:4D
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:9A:CF:CF:6E:EB:71:3D:DB:3C:F1:AE:88:6B:56:72:03:CB:08:A7:48
|
||||
DirName:/C=XY/O=Python Software Foundation CA/CN=our-ca-server
|
||||
serial:82:ED:BF:41:C8:80:91:9B
|
||||
|
||||
Authority Information Access:
|
||||
CA Issuers - URI:http://testca.pythontest.net/testca/pycacert.cer
|
||||
OCSP - URI:http://testca.pythontest.net/testca/ocsp/
|
||||
|
||||
X509v3 CRL Distribution Points:
|
||||
|
||||
Full Name:
|
||||
URI:http://testca.pythontest.net/testca/revocation.crl
|
||||
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
6d:50:8d:fb:ee:4e:93:8b:eb:47:56:ba:38:cc:80:e1:9d:c7:
|
||||
e1:9e:1f:9c:22:0c:d2:08:9b:ed:bf:31:d9:00:ee:af:8c:56:
|
||||
78:92:d1:7c:ba:4e:81:7f:82:1f:f4:68:99:86:91:c6:cb:57:
|
||||
d3:b9:41:12:fa:75:53:fd:22:32:21:50:af:6b:4c:b1:34:36:
|
||||
d1:a8:25:0a:d0:f0:f8:81:7d:69:58:6e:af:e3:d2:c4:32:87:
|
||||
79:d7:cd:ad:0c:56:f3:15:27:10:0c:f9:57:59:53:00:ed:af:
|
||||
5d:4d:07:86:7a:e5:f3:97:88:bc:86:b4:f1:17:46:33:55:28:
|
||||
66:7b:70:d3:a5:12:b9:4f:c7:ed:e6:13:20:2d:f0:9e:ec:17:
|
||||
64:cf:fd:13:14:1b:76:ba:64:ac:c5:51:b6:cd:13:0a:93:b1:
|
||||
fd:43:09:a0:0b:44:6c:77:45:43:0b:e5:ed:70:b2:76:dc:08:
|
||||
4a:5b:73:5f:c1:fc:7f:63:70:f8:b9:ca:3c:98:06:5f:fd:98:
|
||||
d1:e4:e6:61:5f:09:8f:6c:18:86:98:9c:cb:3f:73:7b:3f:38:
|
||||
f5:a7:09:20:ee:a5:63:1c:ff:8b:a6:d1:8c:e8:f4:84:3d:99:
|
||||
38:0f:cc:e0:52:03:f9:18:05:23:76:39:de:52:ce:8e:fb:a6:
|
||||
6e:f5:4f:c3
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE9zCCA9+gAwIBAgIJAILtv0HIgJGdMA0GCSqGSIb3DQEBBQUAME0xCzAJBgNV
|
||||
BAYTAlhZMSYwJAYDVQQKDB1QeXRob24gU29mdHdhcmUgRm91bmRhdGlvbiBDQTEW
|
||||
MBQGA1UEAwwNb3VyLWNhLXNlcnZlcjAeFw0xODAxMTkxOTA5MDZaFw0yNzExMjgx
|
||||
OTA5MDZaMGIxCzAJBgNVBAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEj
|
||||
MCEGA1UECgwaUHl0aG9uIFNvZnR3YXJlIEZvdW5kYXRpb24xFTATBgNVBAMMDGZh
|
||||
a2Vob3N0bmFtZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMf/vqFk
|
||||
BkfhxJUKZVlrkcSooKMIqtw/AEQKz0FL7eJvA3jH02cU0/60J4UaAleXtYYWh5eC
|
||||
Degr7WkWw5amxEe4XcF2qQKdKFLJ2ZPxstoYfAp4vRw/Ek/lP+5bt7M8pbZVZcYz
|
||||
CbBFpEn12PZUJS7bS8NlZIYWv3OOeOglzMG0fdGxVSCkrt64Qe5Dmkgz1BI5oKj7
|
||||
kU9HuzvWdTtipsVa1342ELw6DUbj3sHfUNCUdyIXoFGbr9w0YCYdoASspQYEV2Qa
|
||||
0U8cGfi+S2gSD1/DEkBku8amhNlasHgdGxHBVOYV0a8r4lcrbbnEXbcBdFen+yeF
|
||||
K5IV4uMTlynIknsCAwEAAaOCAcMwggG/MBcGA1UdEQQQMA6CDGZha2Vob3N0bmFt
|
||||
ZTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC
|
||||
MAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFPh2ecsRhfBG5ZXmfmnLEl5OquxNMH0G
|
||||
A1UdIwR2MHSAFJrPz27rcT3bPPGuiGtWcgPLCKdIoVGkTzBNMQswCQYDVQQGEwJY
|
||||
WTEmMCQGA1UECgwdUHl0aG9uIFNvZnR3YXJlIEZvdW5kYXRpb24gQ0ExFjAUBgNV
|
||||
BAMMDW91ci1jYS1zZXJ2ZXKCCQCC7b9ByICRmzCBgwYIKwYBBQUHAQEEdzB1MDwG
|
||||
CCsGAQUFBzAChjBodHRwOi8vdGVzdGNhLnB5dGhvbnRlc3QubmV0L3Rlc3RjYS9w
|
||||
eWNhY2VydC5jZXIwNQYIKwYBBQUHMAGGKWh0dHA6Ly90ZXN0Y2EucHl0aG9udGVz
|
||||
dC5uZXQvdGVzdGNhL29jc3AvMEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly90ZXN0
|
||||
Y2EucHl0aG9udGVzdC5uZXQvdGVzdGNhL3Jldm9jYXRpb24uY3JsMA0GCSqGSIb3
|
||||
DQEBBQUAA4IBAQBtUI377k6Ti+tHVro4zIDhncfhnh+cIgzSCJvtvzHZAO6vjFZ4
|
||||
ktF8uk6Bf4If9GiZhpHGy1fTuUES+nVT/SIyIVCva0yxNDbRqCUK0PD4gX1pWG6v
|
||||
49LEMod5182tDFbzFScQDPlXWVMA7a9dTQeGeuXzl4i8hrTxF0YzVShme3DTpRK5
|
||||
T8ft5hMgLfCe7Bdkz/0TFBt2umSsxVG2zRMKk7H9QwmgC0Rsd0VDC+XtcLJ23AhK
|
||||
W3Nfwfx/Y3D4uco8mAZf/ZjR5OZhXwmPbBiGmJzLP3N7Pzj1pwkg7qVjHP+LptGM
|
||||
6PSEPZk4D8zgUgP5GAUjdjneUs6O+6Zu9U/D
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,96 +0,0 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDDe3QWmhZX07HZbntz4
|
||||
CFqAOaoYMdYwD7Z3WPNIc2zR7p4D6BMOa7NAWjLV5A7CUw6hZANiAAQ5IVKzLLz4
|
||||
LCfcpy6fMOp+jk5KwywsU3upPtjA6E3UetxPcfnnv+gghRyDAYLN2OVqZgLMEmUo
|
||||
F1j1SM1QrbhHIuNcVxI9gPPMdumcNFSz/hqxrBRtA/8Z2gywczdNLjc=
|
||||
-----END PRIVATE KEY-----
|
||||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number:
|
||||
82:ed:bf:41:c8:80:91:9e
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
Issuer: C=XY, O=Python Software Foundation CA, CN=our-ca-server
|
||||
Validity
|
||||
Not Before: Jan 19 19:09:06 2018 GMT
|
||||
Not After : Nov 28 19:09:06 2027 GMT
|
||||
Subject: C=XY, L=Castle Anthrax, O=Python Software Foundation, CN=localhost-ecc
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: id-ecPublicKey
|
||||
Public-Key: (384 bit)
|
||||
pub:
|
||||
04:39:21:52:b3:2c:bc:f8:2c:27:dc:a7:2e:9f:30:
|
||||
ea:7e:8e:4e:4a:c3:2c:2c:53:7b:a9:3e:d8:c0:e8:
|
||||
4d:d4:7a:dc:4f:71:f9:e7:bf:e8:20:85:1c:83:01:
|
||||
82:cd:d8:e5:6a:66:02:cc:12:65:28:17:58:f5:48:
|
||||
cd:50:ad:b8:47:22:e3:5c:57:12:3d:80:f3:cc:76:
|
||||
e9:9c:34:54:b3:fe:1a:b1:ac:14:6d:03:ff:19:da:
|
||||
0c:b0:73:37:4d:2e:37
|
||||
ASN1 OID: secp384r1
|
||||
NIST CURVE: P-384
|
||||
X509v3 extensions:
|
||||
X509v3 Subject Alternative Name:
|
||||
DNS:localhost-ecc
|
||||
X509v3 Key Usage: critical
|
||||
Digital Signature, Key Encipherment
|
||||
X509v3 Extended Key Usage:
|
||||
TLS Web Server Authentication, TLS Web Client Authentication
|
||||
X509v3 Basic Constraints: critical
|
||||
CA:FALSE
|
||||
X509v3 Subject Key Identifier:
|
||||
33:23:0E:15:04:83:2E:3D:BF:DA:81:6D:10:38:80:C3:C2:B0:A4:74
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:9A:CF:CF:6E:EB:71:3D:DB:3C:F1:AE:88:6B:56:72:03:CB:08:A7:48
|
||||
DirName:/C=XY/O=Python Software Foundation CA/CN=our-ca-server
|
||||
serial:82:ED:BF:41:C8:80:91:9B
|
||||
|
||||
Authority Information Access:
|
||||
CA Issuers - URI:http://testca.pythontest.net/testca/pycacert.cer
|
||||
OCSP - URI:http://testca.pythontest.net/testca/ocsp/
|
||||
|
||||
X509v3 CRL Distribution Points:
|
||||
|
||||
Full Name:
|
||||
URI:http://testca.pythontest.net/testca/revocation.crl
|
||||
|
||||
Signature Algorithm: sha1WithRSAEncryption
|
||||
3b:6f:97:af:7e:5f:e0:14:34:ed:57:7e:de:ce:c4:85:1e:aa:
|
||||
84:52:94:7c:e5:ce:e9:9c:88:8b:ad:b5:4d:16:ac:af:81:ea:
|
||||
b8:a2:e2:50:2e:cb:e9:11:bd:1b:a6:3f:0c:a2:d7:7b:67:72:
|
||||
b3:43:16:ad:c6:87:ac:6e:ac:47:78:ef:2f:8c:86:e8:9b:d1:
|
||||
43:8c:c1:7a:91:30:e9:14:d6:9f:41:8b:9b:0b:24:9b:78:86:
|
||||
11:8a:fc:2b:cd:c9:13:ee:90:4f:14:33:51:a3:c4:9e:d6:06:
|
||||
48:f5:41:12:af:f0:f2:71:40:78:f5:96:c2:5d:cf:e1:38:ff:
|
||||
bf:10:eb:74:2f:c2:23:21:3e:27:f5:f1:f2:af:2c:62:82:31:
|
||||
00:c8:96:1b:c3:7e:8d:71:89:e7:40:b5:67:1a:33:fb:c0:8b:
|
||||
96:0c:36:78:25:27:82:d8:27:27:52:0f:f7:69:cd:ff:2b:92:
|
||||
10:d3:d2:0a:db:65:ed:af:90:eb:db:76:f3:8a:7a:13:9e:c6:
|
||||
33:57:15:42:06:13:d6:54:49:fa:84:a7:0e:1d:14:72:ca:19:
|
||||
8e:2b:aa:a4:02:54:3c:f6:1c:23:81:7a:59:54:b0:92:65:72:
|
||||
c8:e5:ba:9f:03:4e:30:f2:4d:45:85:e3:35:a8:b1:68:58:b9:
|
||||
3b:20:a3:eb
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIESzCCAzOgAwIBAgIJAILtv0HIgJGeMA0GCSqGSIb3DQEBBQUAME0xCzAJBgNV
|
||||
BAYTAlhZMSYwJAYDVQQKDB1QeXRob24gU29mdHdhcmUgRm91bmRhdGlvbiBDQTEW
|
||||
MBQGA1UEAwwNb3VyLWNhLXNlcnZlcjAeFw0xODAxMTkxOTA5MDZaFw0yNzExMjgx
|
||||
OTA5MDZaMGMxCzAJBgNVBAYTAlhZMRcwFQYDVQQHDA5DYXN0bGUgQW50aHJheDEj
|
||||
MCEGA1UECgwaUHl0aG9uIFNvZnR3YXJlIEZvdW5kYXRpb24xFjAUBgNVBAMMDWxv
|
||||
Y2FsaG9zdC1lY2MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQ5IVKzLLz4LCfcpy6f
|
||||
MOp+jk5KwywsU3upPtjA6E3UetxPcfnnv+gghRyDAYLN2OVqZgLMEmUoF1j1SM1Q
|
||||
rbhHIuNcVxI9gPPMdumcNFSz/hqxrBRtA/8Z2gywczdNLjejggHEMIIBwDAYBgNV
|
||||
HREEETAPgg1sb2NhbGhvc3QtZWNjMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAU
|
||||
BggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUMyMO
|
||||
FQSDLj2/2oFtEDiAw8KwpHQwfQYDVR0jBHYwdIAUms/PbutxPds88a6Ia1ZyA8sI
|
||||
p0ihUaRPME0xCzAJBgNVBAYTAlhZMSYwJAYDVQQKDB1QeXRob24gU29mdHdhcmUg
|
||||
Rm91bmRhdGlvbiBDQTEWMBQGA1UEAwwNb3VyLWNhLXNlcnZlcoIJAILtv0HIgJGb
|
||||
MIGDBggrBgEFBQcBAQR3MHUwPAYIKwYBBQUHMAKGMGh0dHA6Ly90ZXN0Y2EucHl0
|
||||
aG9udGVzdC5uZXQvdGVzdGNhL3B5Y2FjZXJ0LmNlcjA1BggrBgEFBQcwAYYpaHR0
|
||||
cDovL3Rlc3RjYS5weXRob250ZXN0Lm5ldC90ZXN0Y2Evb2NzcC8wQwYDVR0fBDww
|
||||
OjA4oDagNIYyaHR0cDovL3Rlc3RjYS5weXRob250ZXN0Lm5ldC90ZXN0Y2EvcmV2
|
||||
b2NhdGlvbi5jcmwwDQYJKoZIhvcNAQEFBQADggEBADtvl69+X+AUNO1Xft7OxIUe
|
||||
qoRSlHzlzumciIuttU0WrK+B6rii4lAuy+kRvRumPwyi13tncrNDFq3Gh6xurEd4
|
||||
7y+Mhuib0UOMwXqRMOkU1p9Bi5sLJJt4hhGK/CvNyRPukE8UM1GjxJ7WBkj1QRKv
|
||||
8PJxQHj1lsJdz+E4/78Q63QvwiMhPif18fKvLGKCMQDIlhvDfo1xiedAtWcaM/vA
|
||||
i5YMNnglJ4LYJydSD/dpzf8rkhDT0grbZe2vkOvbdvOKehOexjNXFUIGE9ZUSfqE
|
||||
pw4dFHLKGY4rqqQCVDz2HCOBellUsJJlcsjlup8DTjDyTUWF4zWosWhYuTsgo+s=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -41,6 +41,8 @@ class ExceptionTests(unittest.TestCase):
|
||||
self.assertEqual(buf1, buf2)
|
||||
self.assertEqual(exc.__name__, excname)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def testRaising(self):
|
||||
self.raise_catch(AttributeError, "AttributeError")
|
||||
self.assertRaises(AttributeError, getattr, sys, "undefined_attribute")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -599,101 +599,102 @@ class MathTests(unittest.TestCase):
|
||||
self.assertTrue(math.isnan(math.frexp(NAN)[0]))
|
||||
|
||||
|
||||
@requires_IEEE_754
|
||||
@unittest.skipIf(HAVE_DOUBLE_ROUNDING,
|
||||
"fsum is not exact on machines with double rounding")
|
||||
def testFsum(self):
|
||||
# math.fsum relies on exact rounding for correct operation.
|
||||
# There's a known problem with IA32 floating-point that causes
|
||||
# inexact rounding in some situations, and will cause the
|
||||
# math.fsum tests below to fail; see issue #2937. On non IEEE
|
||||
# 754 platforms, and on IEEE 754 platforms that exhibit the
|
||||
# problem described in issue #2937, we simply skip the whole
|
||||
# test.
|
||||
# TODO: RUSTPYTHON
|
||||
# @requires_IEEE_754
|
||||
# @unittest.skipIf(HAVE_DOUBLE_ROUNDING,
|
||||
# "fsum is not exact on machines with double rounding")
|
||||
# def testFsum(self):
|
||||
# # math.fsum relies on exact rounding for correct operation.
|
||||
# # There's a known problem with IA32 floating-point that causes
|
||||
# # inexact rounding in some situations, and will cause the
|
||||
# # math.fsum tests below to fail; see issue #2937. On non IEEE
|
||||
# # 754 platforms, and on IEEE 754 platforms that exhibit the
|
||||
# # problem described in issue #2937, we simply skip the whole
|
||||
# # test.
|
||||
|
||||
# Python version of math.fsum, for comparison. Uses a
|
||||
# different algorithm based on frexp, ldexp and integer
|
||||
# arithmetic.
|
||||
from sys import float_info
|
||||
mant_dig = float_info.mant_dig
|
||||
etiny = float_info.min_exp - mant_dig
|
||||
# # Python version of math.fsum, for comparison. Uses a
|
||||
# # different algorithm based on frexp, ldexp and integer
|
||||
# # arithmetic.
|
||||
# from sys import float_info
|
||||
# mant_dig = float_info.mant_dig
|
||||
# etiny = float_info.min_exp - mant_dig
|
||||
|
||||
def msum(iterable):
|
||||
"""Full precision summation. Compute sum(iterable) without any
|
||||
intermediate accumulation of error. Based on the 'lsum' function
|
||||
at http://code.activestate.com/recipes/393090/
|
||||
"""
|
||||
tmant, texp = 0, 0
|
||||
for x in iterable:
|
||||
mant, exp = math.frexp(x)
|
||||
mant, exp = int(math.ldexp(mant, mant_dig)), exp - mant_dig
|
||||
if texp > exp:
|
||||
tmant <<= texp-exp
|
||||
texp = exp
|
||||
else:
|
||||
mant <<= exp-texp
|
||||
tmant += mant
|
||||
# Round tmant * 2**texp to a float. The original recipe
|
||||
# used float(str(tmant)) * 2.0**texp for this, but that's
|
||||
# a little unsafe because str -> float conversion can't be
|
||||
# relied upon to do correct rounding on all platforms.
|
||||
tail = max(len(bin(abs(tmant)))-2 - mant_dig, etiny - texp)
|
||||
if tail > 0:
|
||||
h = 1 << (tail-1)
|
||||
tmant = tmant // (2*h) + bool(tmant & h and tmant & 3*h-1)
|
||||
texp += tail
|
||||
return math.ldexp(tmant, texp)
|
||||
# def msum(iterable):
|
||||
# """Full precision summation. Compute sum(iterable) without any
|
||||
# intermediate accumulation of error. Based on the 'lsum' function
|
||||
# at http://code.activestate.com/recipes/393090/
|
||||
# """
|
||||
# tmant, texp = 0, 0
|
||||
# for x in iterable:
|
||||
# mant, exp = math.frexp(x)
|
||||
# mant, exp = int(math.ldexp(mant, mant_dig)), exp - mant_dig
|
||||
# if texp > exp:
|
||||
# tmant <<= texp-exp
|
||||
# texp = exp
|
||||
# else:
|
||||
# mant <<= exp-texp
|
||||
# tmant += mant
|
||||
# # Round tmant * 2**texp to a float. The original recipe
|
||||
# # used float(str(tmant)) * 2.0**texp for this, but that's
|
||||
# # a little unsafe because str -> float conversion can't be
|
||||
# # relied upon to do correct rounding on all platforms.
|
||||
# tail = max(len(bin(abs(tmant)))-2 - mant_dig, etiny - texp)
|
||||
# if tail > 0:
|
||||
# h = 1 << (tail-1)
|
||||
# tmant = tmant // (2*h) + bool(tmant & h and tmant & 3*h-1)
|
||||
# texp += tail
|
||||
# return math.ldexp(tmant, texp)
|
||||
|
||||
test_values = [
|
||||
([], 0.0),
|
||||
([0.0], 0.0),
|
||||
([1e100, 1.0, -1e100, 1e-100, 1e50, -1.0, -1e50], 1e-100),
|
||||
([2.0**53, -0.5, -2.0**-54], 2.0**53-1.0),
|
||||
([2.0**53, 1.0, 2.0**-100], 2.0**53+2.0),
|
||||
([2.0**53+10.0, 1.0, 2.0**-100], 2.0**53+12.0),
|
||||
([2.0**53-4.0, 0.5, 2.0**-54], 2.0**53-3.0),
|
||||
([1./n for n in range(1, 1001)],
|
||||
float.fromhex('0x1.df11f45f4e61ap+2')),
|
||||
([(-1.)**n/n for n in range(1, 1001)],
|
||||
float.fromhex('-0x1.62a2af1bd3624p-1')),
|
||||
([1e16, 1., 1e-16], 10000000000000002.0),
|
||||
([1e16-2., 1.-2.**-53, -(1e16-2.), -(1.-2.**-53)], 0.0),
|
||||
# exercise code for resizing partials array
|
||||
([2.**n - 2.**(n+50) + 2.**(n+52) for n in range(-1074, 972, 2)] +
|
||||
[-2.**1022],
|
||||
float.fromhex('0x1.5555555555555p+970')),
|
||||
]
|
||||
# test_values = [
|
||||
# ([], 0.0),
|
||||
# ([0.0], 0.0),
|
||||
# ([1e100, 1.0, -1e100, 1e-100, 1e50, -1.0, -1e50], 1e-100),
|
||||
# ([2.0**53, -0.5, -2.0**-54], 2.0**53-1.0),
|
||||
# ([2.0**53, 1.0, 2.0**-100], 2.0**53+2.0),
|
||||
# ([2.0**53+10.0, 1.0, 2.0**-100], 2.0**53+12.0),
|
||||
# ([2.0**53-4.0, 0.5, 2.0**-54], 2.0**53-3.0),
|
||||
# ([1./n for n in range(1, 1001)],
|
||||
# float.fromhex('0x1.df11f45f4e61ap+2')),
|
||||
# ([(-1.)**n/n for n in range(1, 1001)],
|
||||
# float.fromhex('-0x1.62a2af1bd3624p-1')),
|
||||
# ([1e16, 1., 1e-16], 10000000000000002.0),
|
||||
# ([1e16-2., 1.-2.**-53, -(1e16-2.), -(1.-2.**-53)], 0.0),
|
||||
# # exercise code for resizing partials array
|
||||
# ([2.**n - 2.**(n+50) + 2.**(n+52) for n in range(-1074, 972, 2)] +
|
||||
# [-2.**1022],
|
||||
# float.fromhex('0x1.5555555555555p+970')),
|
||||
# ]
|
||||
|
||||
# Telescoping sum, with exact differences (due to Sterbenz)
|
||||
terms = [1.7**i for i in range(1001)]
|
||||
test_values.append((
|
||||
[terms[i+1] - terms[i] for i in range(1000)] + [-terms[1000]],
|
||||
-terms[0]
|
||||
))
|
||||
# # Telescoping sum, with exact differences (due to Sterbenz)
|
||||
# terms = [1.7**i for i in range(1001)]
|
||||
# test_values.append((
|
||||
# [terms[i+1] - terms[i] for i in range(1000)] + [-terms[1000]],
|
||||
# -terms[0]
|
||||
# ))
|
||||
|
||||
for i, (vals, expected) in enumerate(test_values):
|
||||
try:
|
||||
actual = math.fsum(vals)
|
||||
except OverflowError:
|
||||
self.fail("test %d failed: got OverflowError, expected %r "
|
||||
"for math.fsum(%.100r)" % (i, expected, vals))
|
||||
except ValueError:
|
||||
self.fail("test %d failed: got ValueError, expected %r "
|
||||
"for math.fsum(%.100r)" % (i, expected, vals))
|
||||
self.assertEqual(actual, expected)
|
||||
# for i, (vals, expected) in enumerate(test_values):
|
||||
# try:
|
||||
# actual = math.fsum(vals)
|
||||
# except OverflowError:
|
||||
# self.fail("test %d failed: got OverflowError, expected %r "
|
||||
# "for math.fsum(%.100r)" % (i, expected, vals))
|
||||
# except ValueError:
|
||||
# self.fail("test %d failed: got ValueError, expected %r "
|
||||
# "for math.fsum(%.100r)" % (i, expected, vals))
|
||||
# self.assertEqual(actual, expected)
|
||||
|
||||
from random import random, gauss, shuffle
|
||||
for j in range(1000):
|
||||
vals = [7, 1e100, -7, -1e100, -9e-20, 8e-20] * 10
|
||||
s = 0
|
||||
for i in range(200):
|
||||
v = gauss(0, random()) ** 7 - s
|
||||
s += v
|
||||
vals.append(v)
|
||||
shuffle(vals)
|
||||
# from random import random, gauss, shuffle
|
||||
# for j in range(1000):
|
||||
# vals = [7, 1e100, -7, -1e100, -9e-20, 8e-20] * 10
|
||||
# s = 0
|
||||
# for i in range(200):
|
||||
# v = gauss(0, random()) ** 7 - s
|
||||
# s += v
|
||||
# vals.append(v)
|
||||
# shuffle(vals)
|
||||
|
||||
s = msum(vals)
|
||||
self.assertEqual(msum(vals), math.fsum(vals))
|
||||
# s = msum(vals)
|
||||
# self.assertEqual(msum(vals), math.fsum(vals))
|
||||
|
||||
|
||||
# Python 3.9
|
||||
@@ -1557,12 +1558,13 @@ class MathTests(unittest.TestCase):
|
||||
# def test_nan_constant(self):
|
||||
# self.assertTrue(math.isnan(math.nan))
|
||||
|
||||
@requires_IEEE_754
|
||||
def test_inf_constant(self):
|
||||
self.assertTrue(math.isinf(math.inf))
|
||||
self.assertGreater(math.inf, 0.0)
|
||||
self.assertEqual(math.inf, float("inf"))
|
||||
self.assertEqual(-math.inf, float("-inf"))
|
||||
# TODO: RUSTPYTHON
|
||||
# @requires_IEEE_754
|
||||
# def test_inf_constant(self):
|
||||
# self.assertTrue(math.isinf(math.inf))
|
||||
# self.assertGreater(math.inf, 0.0)
|
||||
# self.assertEqual(math.inf, float("inf"))
|
||||
# self.assertEqual(-math.inf, float("-inf"))
|
||||
|
||||
# RED_FLAG 16-Oct-2000 Tim
|
||||
# While 2.0 is more consistent about exceptions than previous releases, it
|
||||
|
||||
@@ -384,6 +384,8 @@ class AbstractMemoryTests:
|
||||
mm.release()
|
||||
m.tolist()
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_issue22668(self):
|
||||
a = array.array('H', [256, 256, 256, 256])
|
||||
x = memoryview(a)
|
||||
|
||||
@@ -723,6 +723,8 @@ class UnpackIteratorTest(unittest.TestCase):
|
||||
self.assertRaises(StopIteration, next, it)
|
||||
self.assertRaises(StopIteration, next, it)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_half_float(self):
|
||||
# Little-endian examples from:
|
||||
# http://en.wikipedia.org/wiki/Half_precision_floating-point_format
|
||||
|
||||
@@ -5,4 +5,4 @@ authors = ["RustPython Team"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
num-bigint = { version = "0.3", default-features = false }
|
||||
num-bigint = "0.3"
|
||||
|
||||
251
ast/src/ast.rs
251
ast/src/ast.rs
@@ -5,21 +5,20 @@
|
||||
//! location of the node.
|
||||
|
||||
pub use crate::location::Location;
|
||||
use alloc::{boxed::Box, string::String, vec::Vec};
|
||||
use num_bigint::BigInt;
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Top<U = ()> {
|
||||
Program(Program<U>),
|
||||
Statement(Vec<Statement<U>>),
|
||||
Expression(Expression<U>),
|
||||
pub enum Top {
|
||||
Program(Program),
|
||||
Statement(Vec<Statement>),
|
||||
Expression(Expression),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
/// A full python program, it's a sequence of statements.
|
||||
pub struct Program<U = ()> {
|
||||
pub statements: Suite<U>,
|
||||
pub struct Program {
|
||||
pub statements: Suite,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@@ -29,18 +28,17 @@ pub struct ImportSymbol {
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Located<T, U = ()> {
|
||||
pub struct Located<T> {
|
||||
pub location: Location,
|
||||
pub node: T,
|
||||
pub custom: U,
|
||||
}
|
||||
|
||||
pub type Statement<U = ()> = Located<StatementType<U>, U>;
|
||||
pub type Suite<U = ()> = Vec<Statement<U>>;
|
||||
pub type Statement = Located<StatementType>;
|
||||
pub type Suite = Vec<Statement>;
|
||||
|
||||
/// Abstract syntax tree nodes for python statements.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum StatementType<U = ()> {
|
||||
pub enum StatementType {
|
||||
/// A [`break`](https://docs.python.org/3/reference/simple_stmts.html#the-break-statement) statement.
|
||||
Break,
|
||||
|
||||
@@ -49,7 +47,7 @@ pub enum StatementType<U = ()> {
|
||||
|
||||
/// A [`return`](https://docs.python.org/3/reference/simple_stmts.html#the-return-statement) statement.
|
||||
/// This is used to return from a function.
|
||||
Return { value: Option<Expression<U>> },
|
||||
Return { value: Option<Expression> },
|
||||
|
||||
/// An [`import`](https://docs.python.org/3/reference/simple_stmts.html#the-import-statement) statement.
|
||||
Import { names: Vec<ImportSymbol> },
|
||||
@@ -66,35 +64,35 @@ pub enum StatementType<U = ()> {
|
||||
|
||||
/// An [`assert`](https://docs.python.org/3/reference/simple_stmts.html#the-assert-statement) statement.
|
||||
Assert {
|
||||
test: Expression<U>,
|
||||
msg: Option<Expression<U>>,
|
||||
test: Expression,
|
||||
msg: Option<Expression>,
|
||||
},
|
||||
|
||||
/// A `del` statement, to delete some variables.
|
||||
Delete { targets: Vec<Expression<U>> },
|
||||
Delete { targets: Vec<Expression> },
|
||||
|
||||
/// Variable assignment. Note that we can assign to multiple targets.
|
||||
Assign {
|
||||
targets: Vec<Expression<U>>,
|
||||
value: Expression<U>,
|
||||
targets: Vec<Expression>,
|
||||
value: Expression,
|
||||
},
|
||||
|
||||
/// Augmented assignment.
|
||||
AugAssign {
|
||||
target: Box<Expression<U>>,
|
||||
target: Box<Expression>,
|
||||
op: Operator,
|
||||
value: Box<Expression<U>>,
|
||||
value: Box<Expression>,
|
||||
},
|
||||
|
||||
/// A type annotated assignment.
|
||||
AnnAssign {
|
||||
target: Box<Expression<U>>,
|
||||
annotation: Box<Expression<U>>,
|
||||
value: Option<Expression<U>>,
|
||||
target: Box<Expression>,
|
||||
annotation: Box<Expression>,
|
||||
value: Option<Expression>,
|
||||
},
|
||||
|
||||
/// An expression used as a statement.
|
||||
Expression { expression: Expression<U> },
|
||||
Expression { expression: Expression },
|
||||
|
||||
/// The [`global`](https://docs.python.org/3/reference/simple_stmts.html#the-global-statement) statement,
|
||||
/// to declare names as global variables.
|
||||
@@ -106,56 +104,56 @@ pub enum StatementType<U = ()> {
|
||||
|
||||
/// An [`if`](https://docs.python.org/3/reference/compound_stmts.html#the-if-statement) statement.
|
||||
If {
|
||||
test: Expression<U>,
|
||||
body: Suite<U>,
|
||||
orelse: Option<Suite<U>>,
|
||||
test: Expression,
|
||||
body: Suite,
|
||||
orelse: Option<Suite>,
|
||||
},
|
||||
|
||||
/// A [`while`](https://docs.python.org/3/reference/compound_stmts.html#the-while-statement) statement.
|
||||
While {
|
||||
test: Expression<U>,
|
||||
body: Suite<U>,
|
||||
orelse: Option<Suite<U>>,
|
||||
test: Expression,
|
||||
body: Suite,
|
||||
orelse: Option<Suite>,
|
||||
},
|
||||
|
||||
/// The [`with`](https://docs.python.org/3/reference/compound_stmts.html#the-with-statement) statement.
|
||||
With {
|
||||
is_async: bool,
|
||||
items: Vec<WithItem<U>>,
|
||||
body: Suite<U>,
|
||||
items: Vec<WithItem>,
|
||||
body: Suite,
|
||||
},
|
||||
|
||||
/// A [`for`](https://docs.python.org/3/reference/compound_stmts.html#the-for-statement) statement.
|
||||
/// Contains the body of the loop, and the `else` clause.
|
||||
For {
|
||||
is_async: bool,
|
||||
target: Box<Expression<U>>,
|
||||
iter: Box<Expression<U>>,
|
||||
body: Suite<U>,
|
||||
orelse: Option<Suite<U>>,
|
||||
target: Box<Expression>,
|
||||
iter: Box<Expression>,
|
||||
body: Suite,
|
||||
orelse: Option<Suite>,
|
||||
},
|
||||
|
||||
/// A `raise` statement.
|
||||
Raise {
|
||||
exception: Option<Expression<U>>,
|
||||
cause: Option<Expression<U>>,
|
||||
exception: Option<Expression>,
|
||||
cause: Option<Expression>,
|
||||
},
|
||||
|
||||
/// A [`try`](https://docs.python.org/3/reference/compound_stmts.html#the-try-statement) statement.
|
||||
Try {
|
||||
body: Suite<U>,
|
||||
handlers: Vec<ExceptHandler<U>>,
|
||||
orelse: Option<Suite<U>>,
|
||||
finalbody: Option<Suite<U>>,
|
||||
body: Suite,
|
||||
handlers: Vec<ExceptHandler>,
|
||||
orelse: Option<Suite>,
|
||||
finalbody: Option<Suite>,
|
||||
},
|
||||
|
||||
/// A [class definition](https://docs.python.org/3/reference/compound_stmts.html#class-definitions).
|
||||
ClassDef {
|
||||
name: String,
|
||||
body: Suite<U>,
|
||||
bases: Vec<Expression<U>>,
|
||||
keywords: Vec<Keyword<U>>,
|
||||
decorator_list: Vec<Expression<U>>,
|
||||
body: Suite,
|
||||
bases: Vec<Expression>,
|
||||
keywords: Vec<Keyword>,
|
||||
decorator_list: Vec<Expression>,
|
||||
},
|
||||
|
||||
/// A [function definition](https://docs.python.org/3/reference/compound_stmts.html#function-definitions).
|
||||
@@ -164,82 +162,82 @@ pub enum StatementType<U = ()> {
|
||||
FunctionDef {
|
||||
is_async: bool,
|
||||
name: String,
|
||||
args: Box<Parameters<U>>,
|
||||
body: Suite<U>,
|
||||
decorator_list: Vec<Expression<U>>,
|
||||
returns: Option<Expression<U>>,
|
||||
args: Box<Parameters>,
|
||||
body: Suite,
|
||||
decorator_list: Vec<Expression>,
|
||||
returns: Option<Expression>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct WithItem<U = ()> {
|
||||
pub context_expr: Expression<U>,
|
||||
pub optional_vars: Option<Expression<U>>,
|
||||
pub struct WithItem {
|
||||
pub context_expr: Expression,
|
||||
pub optional_vars: Option<Expression>,
|
||||
}
|
||||
|
||||
/// An expression at a given location in the sourcecode.
|
||||
pub type Expression<U = ()> = Located<ExpressionType<U>, U>;
|
||||
pub type Expression = Located<ExpressionType>;
|
||||
|
||||
/// A certain type of expression.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum ExpressionType<U = ()> {
|
||||
pub enum ExpressionType {
|
||||
BoolOp {
|
||||
op: BooleanOperator,
|
||||
values: Vec<Expression<U>>,
|
||||
values: Vec<Expression>,
|
||||
},
|
||||
|
||||
/// A binary operation on two operands.
|
||||
Binop {
|
||||
a: Box<Expression<U>>,
|
||||
a: Box<Expression>,
|
||||
op: Operator,
|
||||
b: Box<Expression<U>>,
|
||||
b: Box<Expression>,
|
||||
},
|
||||
|
||||
/// Subscript operation.
|
||||
Subscript {
|
||||
a: Box<Expression<U>>,
|
||||
b: Box<Expression<U>>,
|
||||
a: Box<Expression>,
|
||||
b: Box<Expression>,
|
||||
},
|
||||
|
||||
/// An unary operation.
|
||||
Unop {
|
||||
op: UnaryOperator,
|
||||
a: Box<Expression<U>>,
|
||||
a: Box<Expression>,
|
||||
},
|
||||
|
||||
/// An await expression.
|
||||
Await {
|
||||
value: Box<Expression<U>>,
|
||||
value: Box<Expression>,
|
||||
},
|
||||
|
||||
/// A yield expression.
|
||||
Yield {
|
||||
value: Option<Box<Expression<U>>>,
|
||||
value: Option<Box<Expression>>,
|
||||
},
|
||||
|
||||
// A yield from expression.
|
||||
YieldFrom {
|
||||
value: Box<Expression<U>>,
|
||||
value: Box<Expression>,
|
||||
},
|
||||
|
||||
/// A chained comparison. Note that in python you can use
|
||||
/// `1 < a < 10` for example.
|
||||
Compare {
|
||||
vals: Vec<Expression<U>>,
|
||||
vals: Vec<Expression>,
|
||||
ops: Vec<Comparison>,
|
||||
},
|
||||
|
||||
/// Attribute access in the form of `value.name`.
|
||||
Attribute {
|
||||
value: Box<Expression<U>>,
|
||||
value: Box<Expression>,
|
||||
name: String,
|
||||
},
|
||||
|
||||
/// A call expression.
|
||||
Call {
|
||||
function: Box<Expression<U>>,
|
||||
args: Vec<Expression<U>>,
|
||||
keywords: Vec<Keyword<U>>,
|
||||
function: Box<Expression>,
|
||||
args: Vec<Expression>,
|
||||
keywords: Vec<Keyword>,
|
||||
},
|
||||
|
||||
/// A numeric literal.
|
||||
@@ -249,43 +247,43 @@ pub enum ExpressionType<U = ()> {
|
||||
|
||||
/// A `list` literal value.
|
||||
List {
|
||||
elements: Vec<Expression<U>>,
|
||||
elements: Vec<Expression>,
|
||||
},
|
||||
|
||||
/// A `tuple` literal value.
|
||||
Tuple {
|
||||
elements: Vec<Expression<U>>,
|
||||
elements: Vec<Expression>,
|
||||
},
|
||||
|
||||
/// A `dict` literal value.
|
||||
/// For example: `{2: 'two', 3: 'three'}`
|
||||
Dict {
|
||||
elements: Vec<(Option<Expression<U>>, Expression<U>)>,
|
||||
elements: Vec<(Option<Expression>, Expression)>,
|
||||
},
|
||||
|
||||
/// A `set` literal.
|
||||
Set {
|
||||
elements: Vec<Expression<U>>,
|
||||
elements: Vec<Expression>,
|
||||
},
|
||||
|
||||
Comprehension {
|
||||
kind: Box<ComprehensionKind<U>>,
|
||||
generators: Vec<Comprehension<U>>,
|
||||
kind: Box<ComprehensionKind>,
|
||||
generators: Vec<Comprehension>,
|
||||
},
|
||||
|
||||
/// A starred expression.
|
||||
Starred {
|
||||
value: Box<Expression<U>>,
|
||||
value: Box<Expression>,
|
||||
},
|
||||
|
||||
/// A slice expression.
|
||||
Slice {
|
||||
elements: Vec<Expression<U>>,
|
||||
elements: Vec<Expression>,
|
||||
},
|
||||
|
||||
/// A string literal.
|
||||
String {
|
||||
value: StringGroup<U>,
|
||||
value: StringGroup,
|
||||
},
|
||||
|
||||
/// A bytes literal.
|
||||
@@ -300,21 +298,21 @@ pub enum ExpressionType<U = ()> {
|
||||
|
||||
/// A `lambda` function expression.
|
||||
Lambda {
|
||||
args: Box<Parameters<U>>,
|
||||
body: Box<Expression<U>>,
|
||||
args: Box<Parameters>,
|
||||
body: Box<Expression>,
|
||||
},
|
||||
|
||||
/// An if-expression.
|
||||
IfExpression {
|
||||
test: Box<Expression<U>>,
|
||||
body: Box<Expression<U>>,
|
||||
orelse: Box<Expression<U>>,
|
||||
test: Box<Expression>,
|
||||
body: Box<Expression>,
|
||||
orelse: Box<Expression>,
|
||||
},
|
||||
|
||||
// A named expression
|
||||
NamedExpression {
|
||||
left: Box<Expression<U>>,
|
||||
right: Box<Expression<U>>,
|
||||
left: Box<Expression>,
|
||||
right: Box<Expression>,
|
||||
},
|
||||
|
||||
/// The literal 'True'.
|
||||
@@ -330,7 +328,7 @@ pub enum ExpressionType<U = ()> {
|
||||
Ellipsis,
|
||||
}
|
||||
|
||||
impl<U> Expression<U> {
|
||||
impl Expression {
|
||||
/// Returns a short name for the node suitable for use in error messages.
|
||||
pub fn name(&self) -> &'static str {
|
||||
use self::ExpressionType::*;
|
||||
@@ -382,70 +380,61 @@ impl<U> Expression<U> {
|
||||
/// In cpython this is called arguments, but we choose parameters to
|
||||
/// distinguish between function parameters and actual call arguments.
|
||||
#[derive(Debug, PartialEq, Default)]
|
||||
pub struct Parameters<U = ()> {
|
||||
pub struct Parameters {
|
||||
pub posonlyargs_count: usize,
|
||||
pub args: Vec<Parameter<U>>,
|
||||
pub kwonlyargs: Vec<Parameter<U>>,
|
||||
pub vararg: Varargs<U>, // Optionally we handle optionally named '*args' or '*'
|
||||
pub kwarg: Varargs<U>,
|
||||
pub defaults: Vec<Expression<U>>,
|
||||
pub kw_defaults: Vec<Option<Expression<U>>>,
|
||||
pub args: Vec<Parameter>,
|
||||
pub kwonlyargs: Vec<Parameter>,
|
||||
pub vararg: Varargs, // Optionally we handle optionally named '*args' or '*'
|
||||
pub kwarg: Varargs,
|
||||
pub defaults: Vec<Expression>,
|
||||
pub kw_defaults: Vec<Option<Expression>>,
|
||||
}
|
||||
|
||||
/// A single formal parameter to a function.
|
||||
#[derive(Debug, PartialEq, Default)]
|
||||
pub struct Parameter<U = ()> {
|
||||
pub struct Parameter {
|
||||
pub location: Location,
|
||||
pub arg: String,
|
||||
pub annotation: Option<Box<Expression<U>>>,
|
||||
pub annotation: Option<Box<Expression>>,
|
||||
}
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum ComprehensionKind<U = ()> {
|
||||
GeneratorExpression {
|
||||
element: Expression<U>,
|
||||
},
|
||||
List {
|
||||
element: Expression<U>,
|
||||
},
|
||||
Set {
|
||||
element: Expression<U>,
|
||||
},
|
||||
Dict {
|
||||
key: Expression<U>,
|
||||
value: Expression<U>,
|
||||
},
|
||||
pub enum ComprehensionKind {
|
||||
GeneratorExpression { element: Expression },
|
||||
List { element: Expression },
|
||||
Set { element: Expression },
|
||||
Dict { key: Expression, value: Expression },
|
||||
}
|
||||
|
||||
/// A list/set/dict/generator compression.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Comprehension<U = ()> {
|
||||
pub struct Comprehension {
|
||||
pub location: Location,
|
||||
pub target: Expression<U>,
|
||||
pub iter: Expression<U>,
|
||||
pub ifs: Vec<Expression<U>>,
|
||||
pub target: Expression,
|
||||
pub iter: Expression,
|
||||
pub ifs: Vec<Expression>,
|
||||
pub is_async: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ArgumentList<U = ()> {
|
||||
pub args: Vec<Expression<U>>,
|
||||
pub keywords: Vec<Keyword<U>>,
|
||||
pub struct ArgumentList {
|
||||
pub args: Vec<Expression>,
|
||||
pub keywords: Vec<Keyword>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Keyword<U = ()> {
|
||||
pub struct Keyword {
|
||||
pub name: Option<String>,
|
||||
pub value: Expression<U>,
|
||||
pub value: Expression,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ExceptHandler<U = ()> {
|
||||
pub struct ExceptHandler {
|
||||
pub location: Location,
|
||||
pub typ: Option<Expression<U>>,
|
||||
pub typ: Option<Expression>,
|
||||
pub name: Option<String>,
|
||||
pub body: Suite<U>,
|
||||
pub body: Suite,
|
||||
}
|
||||
|
||||
/// An operator for a binary operation (an operation with two operands).
|
||||
@@ -517,35 +506,35 @@ pub enum ConversionFlag {
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum StringGroup<U = ()> {
|
||||
pub enum StringGroup {
|
||||
Constant {
|
||||
value: String,
|
||||
},
|
||||
FormattedValue {
|
||||
value: Box<Expression<U>>,
|
||||
value: Box<Expression>,
|
||||
conversion: Option<ConversionFlag>,
|
||||
spec: Option<Box<StringGroup<U>>>,
|
||||
spec: Option<Box<StringGroup>>,
|
||||
},
|
||||
Joined {
|
||||
values: Vec<StringGroup<U>>,
|
||||
values: Vec<StringGroup>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Varargs<U = ()> {
|
||||
pub enum Varargs {
|
||||
None,
|
||||
Unnamed,
|
||||
Named(Parameter<U>),
|
||||
Named(Parameter),
|
||||
}
|
||||
|
||||
impl<U> Default for Varargs<U> {
|
||||
fn default() -> Varargs<U> {
|
||||
impl Default for Varargs {
|
||||
fn default() -> Varargs {
|
||||
Varargs::None
|
||||
}
|
||||
}
|
||||
|
||||
impl<U> From<Option<Option<Parameter<U>>>> for Varargs<U> {
|
||||
fn from(opt: Option<Option<Parameter<U>>>) -> Varargs<U> {
|
||||
impl From<Option<Option<Parameter>>> for Varargs {
|
||||
fn from(opt: Option<Option<Parameter>>) -> Varargs {
|
||||
match opt {
|
||||
Some(inner_opt) => match inner_opt {
|
||||
Some(param) => Varargs::Named(param),
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
#![no_std]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
mod ast;
|
||||
mod location;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Datatypes to support source location information.
|
||||
|
||||
use core::fmt;
|
||||
use std::fmt;
|
||||
|
||||
/// A location somewhere in the sourcecode.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||
|
||||
@@ -7,16 +7,13 @@ edition = "2018"
|
||||
repository = "https://github.com/RustPython/RustPython"
|
||||
license = "MIT"
|
||||
|
||||
[features]
|
||||
std = ["bstr/std", "itertools/use_std", "lz4_flex/std"]
|
||||
default = ["std"]
|
||||
|
||||
[dependencies]
|
||||
bincode = "1.1"
|
||||
bitflags = "1.1"
|
||||
lz4_flex = { version = "0.7", default-features = false, features = ["safe-decode", "safe-encode"] }
|
||||
num-bigint = { version = "0.3", default-features = false, features = ["serde"] }
|
||||
num-complex = { version = "0.3", default-features = false, features = ["serde"] }
|
||||
lz-fear = "0.1"
|
||||
num-bigint = { version = "0.3", features = ["serde"] }
|
||||
num-complex = { version = "0.3", features = ["serde"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
itertools = { version = "0.9", default-features = false }
|
||||
bstr = { version = "0.2", default-features = false }
|
||||
itertools = "0.9"
|
||||
bstr = "0.2"
|
||||
|
||||
948
bytecode/src/bytecode.rs
Normal file
948
bytecode/src/bytecode.rs
Normal file
@@ -0,0 +1,948 @@
|
||||
//! Implement python as a virtual machine with bytecodes. This module
|
||||
//! implements bytecode structure.
|
||||
|
||||
use bitflags::bitflags;
|
||||
use bstr::ByteSlice;
|
||||
use itertools::Itertools;
|
||||
use num_bigint::BigInt;
|
||||
use num_complex::Complex64;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::BTreeSet;
|
||||
use std::fmt;
|
||||
|
||||
/// Sourcecode location.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Location {
|
||||
row: usize,
|
||||
column: usize,
|
||||
}
|
||||
|
||||
impl Location {
|
||||
pub fn new(row: usize, column: usize) -> Self {
|
||||
Location { row, column }
|
||||
}
|
||||
|
||||
pub fn row(&self) -> usize {
|
||||
self.row
|
||||
}
|
||||
|
||||
pub fn column(&self) -> usize {
|
||||
self.column
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Constant: Sized {
|
||||
type Name: AsRef<str>;
|
||||
fn borrow_constant(&self) -> BorrowedConstant<Self>;
|
||||
fn into_data(self) -> ConstantData {
|
||||
self.borrow_constant().into_data()
|
||||
}
|
||||
fn map_constant<Bag: ConstantBag>(self, bag: &Bag) -> Bag::Constant {
|
||||
bag.make_constant(self.into_data())
|
||||
}
|
||||
}
|
||||
impl Constant for ConstantData {
|
||||
type Name = String;
|
||||
fn borrow_constant(&self) -> BorrowedConstant<Self> {
|
||||
use BorrowedConstant::*;
|
||||
match self {
|
||||
ConstantData::Integer { value } => Integer { value },
|
||||
ConstantData::Float { value } => Float { value: *value },
|
||||
ConstantData::Complex { value } => Complex { value: *value },
|
||||
ConstantData::Boolean { value } => Boolean { value: *value },
|
||||
ConstantData::Str { value } => Str { value },
|
||||
ConstantData::Bytes { value } => Bytes { value },
|
||||
ConstantData::Code { code } => Code { code },
|
||||
ConstantData::Tuple { elements } => Tuple {
|
||||
elements: Box::new(elements.iter().map(|e| e.borrow_constant())),
|
||||
},
|
||||
ConstantData::None => None,
|
||||
ConstantData::Ellipsis => Ellipsis,
|
||||
}
|
||||
}
|
||||
fn into_data(self) -> ConstantData {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ConstantBag: Sized {
|
||||
type Constant: Constant;
|
||||
fn make_constant(&self, constant: ConstantData) -> Self::Constant;
|
||||
fn make_constant_borrowed<C: Constant>(&self, constant: BorrowedConstant<C>) -> Self::Constant {
|
||||
self.make_constant(constant.into_data())
|
||||
}
|
||||
fn make_name(&self, name: String) -> <Self::Constant as Constant>::Name;
|
||||
fn make_name_ref(&self, name: &str) -> <Self::Constant as Constant>::Name {
|
||||
self.make_name(name.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BasicBag;
|
||||
impl ConstantBag for BasicBag {
|
||||
type Constant = ConstantData;
|
||||
fn make_constant(&self, constant: ConstantData) -> Self::Constant {
|
||||
constant
|
||||
}
|
||||
fn make_name(&self, name: String) -> <Self::Constant as Constant>::Name {
|
||||
name
|
||||
}
|
||||
}
|
||||
|
||||
/// Primary container of a single code object. Each python function has
|
||||
/// a codeobject. Also a module has a codeobject.
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CodeObject<C: Constant = ConstantData> {
|
||||
pub instructions: Box<[Instruction]>,
|
||||
pub locations: Box<[Location]>,
|
||||
pub flags: CodeFlags,
|
||||
pub posonlyarg_count: usize, // Number of positional-only arguments
|
||||
pub arg_count: usize,
|
||||
pub kwonlyarg_count: usize,
|
||||
pub source_path: String,
|
||||
pub first_line_number: usize,
|
||||
pub obj_name: String, // Name of the object that created this code object
|
||||
pub cell2arg: Option<Box<[isize]>>,
|
||||
pub constants: Box<[C]>,
|
||||
#[serde(bound(
|
||||
deserialize = "C::Name: serde::Deserialize<'de>",
|
||||
serialize = "C::Name: serde::Serialize"
|
||||
))]
|
||||
pub names: Box<[C::Name]>,
|
||||
pub varnames: Box<[C::Name]>,
|
||||
pub cellvars: Box<[C::Name]>,
|
||||
pub freevars: Box<[C::Name]>,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct CodeFlags: u16 {
|
||||
const HAS_DEFAULTS = 0x01;
|
||||
const HAS_KW_ONLY_DEFAULTS = 0x02;
|
||||
const HAS_ANNOTATIONS = 0x04;
|
||||
const NEW_LOCALS = 0x08;
|
||||
const IS_GENERATOR = 0x10;
|
||||
const IS_COROUTINE = 0x20;
|
||||
const HAS_VARARGS = 0x40;
|
||||
const HAS_VARKEYWORDS = 0x80;
|
||||
const IS_OPTIMIZED = 0x0100;
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeFlags {
|
||||
pub const NAME_MAPPING: &'static [(&'static str, CodeFlags)] = &[
|
||||
("GENERATOR", CodeFlags::IS_GENERATOR),
|
||||
("COROUTINE", CodeFlags::IS_COROUTINE),
|
||||
(
|
||||
"ASYNC_GENERATOR",
|
||||
Self::from_bits_truncate(Self::IS_GENERATOR.bits | Self::IS_COROUTINE.bits),
|
||||
),
|
||||
("VARARGS", CodeFlags::HAS_VARARGS),
|
||||
("VARKEYWORDS", CodeFlags::HAS_VARKEYWORDS),
|
||||
];
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug, Deserialize, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||
#[repr(transparent)]
|
||||
// XXX: if you add a new instruction that stores a Label, make sure to add it in
|
||||
// compile::CodeInfo::finalize_code and CodeObject::label_targets
|
||||
pub struct Label(pub usize);
|
||||
impl fmt::Display for Label {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms a value prior to formatting it.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum ConversionFlag {
|
||||
/// Converts by calling `str(<value>)`.
|
||||
Str,
|
||||
/// Converts by calling `ascii(<value>)`.
|
||||
Ascii,
|
||||
/// Converts by calling `repr(<value>)`.
|
||||
Repr,
|
||||
}
|
||||
|
||||
pub type NameIdx = usize;
|
||||
|
||||
/// A Single bytecode instruction.
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum Instruction {
|
||||
Import {
|
||||
name_idx: Option<NameIdx>,
|
||||
symbols_idx: Vec<NameIdx>,
|
||||
level: usize,
|
||||
},
|
||||
ImportStar,
|
||||
ImportFrom {
|
||||
idx: NameIdx,
|
||||
},
|
||||
LoadFast(NameIdx),
|
||||
LoadNameAny(NameIdx),
|
||||
LoadGlobal(NameIdx),
|
||||
LoadDeref(NameIdx),
|
||||
LoadClassDeref(NameIdx),
|
||||
StoreFast(NameIdx),
|
||||
StoreLocal(NameIdx),
|
||||
StoreGlobal(NameIdx),
|
||||
StoreDeref(NameIdx),
|
||||
DeleteFast(NameIdx),
|
||||
DeleteLocal(NameIdx),
|
||||
DeleteGlobal(NameIdx),
|
||||
DeleteDeref(NameIdx),
|
||||
LoadClosure(NameIdx),
|
||||
Subscript,
|
||||
StoreSubscript,
|
||||
DeleteSubscript,
|
||||
StoreAttr {
|
||||
idx: NameIdx,
|
||||
},
|
||||
DeleteAttr {
|
||||
idx: NameIdx,
|
||||
},
|
||||
LoadConst {
|
||||
/// index into constants vec
|
||||
idx: usize,
|
||||
},
|
||||
UnaryOperation {
|
||||
op: UnaryOperator,
|
||||
},
|
||||
BinaryOperation {
|
||||
op: BinaryOperator,
|
||||
inplace: bool,
|
||||
},
|
||||
LoadAttr {
|
||||
idx: NameIdx,
|
||||
},
|
||||
CompareOperation {
|
||||
op: ComparisonOperator,
|
||||
},
|
||||
Pop,
|
||||
Rotate {
|
||||
amount: usize,
|
||||
},
|
||||
Duplicate,
|
||||
GetIter,
|
||||
Continue,
|
||||
Break,
|
||||
Jump {
|
||||
target: Label,
|
||||
},
|
||||
/// Pop the top of the stack, and jump if this value is true.
|
||||
JumpIfTrue {
|
||||
target: Label,
|
||||
},
|
||||
/// Pop the top of the stack, and jump if this value is false.
|
||||
JumpIfFalse {
|
||||
target: Label,
|
||||
},
|
||||
/// Peek at the top of the stack, and jump if this value is true.
|
||||
/// Otherwise, pop top of stack.
|
||||
JumpIfTrueOrPop {
|
||||
target: Label,
|
||||
},
|
||||
/// Peek at the top of the stack, and jump if this value is false.
|
||||
/// Otherwise, pop top of stack.
|
||||
JumpIfFalseOrPop {
|
||||
target: Label,
|
||||
},
|
||||
MakeFunction,
|
||||
CallFunction {
|
||||
typ: CallType,
|
||||
},
|
||||
ForIter {
|
||||
target: Label,
|
||||
},
|
||||
ReturnValue,
|
||||
YieldValue,
|
||||
YieldFrom,
|
||||
SetupAnnotation,
|
||||
SetupLoop {
|
||||
start: Label,
|
||||
end: Label,
|
||||
},
|
||||
|
||||
/// Setup a finally handler, which will be called whenever one of this events occurs:
|
||||
/// - the block is popped
|
||||
/// - the function returns
|
||||
/// - an exception is returned
|
||||
SetupFinally {
|
||||
handler: Label,
|
||||
},
|
||||
|
||||
/// Enter a finally block, without returning, excepting, just because we are there.
|
||||
EnterFinally,
|
||||
|
||||
/// Marker bytecode for the end of a finally sequence.
|
||||
/// When this bytecode is executed, the eval loop does one of those things:
|
||||
/// - Continue at a certain bytecode position
|
||||
/// - Propagate the exception
|
||||
/// - Return from a function
|
||||
/// - Do nothing at all, just continue
|
||||
EndFinally,
|
||||
|
||||
SetupExcept {
|
||||
handler: Label,
|
||||
},
|
||||
SetupWith {
|
||||
end: Label,
|
||||
},
|
||||
WithCleanupStart,
|
||||
WithCleanupFinish,
|
||||
PopBlock,
|
||||
Raise {
|
||||
argc: usize,
|
||||
},
|
||||
BuildString {
|
||||
size: usize,
|
||||
},
|
||||
BuildTuple {
|
||||
size: usize,
|
||||
unpack: bool,
|
||||
},
|
||||
BuildList {
|
||||
size: usize,
|
||||
unpack: bool,
|
||||
},
|
||||
BuildSet {
|
||||
size: usize,
|
||||
unpack: bool,
|
||||
},
|
||||
BuildMap {
|
||||
size: usize,
|
||||
unpack: bool,
|
||||
for_call: bool,
|
||||
},
|
||||
BuildSlice {
|
||||
size: usize,
|
||||
},
|
||||
ListAppend {
|
||||
i: usize,
|
||||
},
|
||||
SetAdd {
|
||||
i: usize,
|
||||
},
|
||||
MapAdd {
|
||||
i: usize,
|
||||
},
|
||||
|
||||
PrintExpr,
|
||||
LoadBuildClass,
|
||||
UnpackSequence {
|
||||
size: usize,
|
||||
},
|
||||
UnpackEx {
|
||||
before: usize,
|
||||
after: usize,
|
||||
},
|
||||
FormatValue {
|
||||
conversion: Option<ConversionFlag>,
|
||||
},
|
||||
PopException,
|
||||
Reverse {
|
||||
amount: usize,
|
||||
},
|
||||
GetAwaitable,
|
||||
BeforeAsyncWith,
|
||||
SetupAsyncWith {
|
||||
end: Label,
|
||||
},
|
||||
GetAIter,
|
||||
GetANext,
|
||||
|
||||
/// Reverse order evaluation in MapAdd
|
||||
/// required to support named expressions of Python 3.8 in dict comprehension
|
||||
/// today (including Py3.9) only required in dict comprehension.
|
||||
MapAddRev {
|
||||
i: usize,
|
||||
},
|
||||
}
|
||||
|
||||
use self::Instruction::*;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum CallType {
|
||||
Positional(usize),
|
||||
Keyword(usize),
|
||||
Ex(bool),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum ConstantData {
|
||||
Integer { value: BigInt },
|
||||
Float { value: f64 },
|
||||
Complex { value: Complex64 },
|
||||
Boolean { value: bool },
|
||||
Str { value: String },
|
||||
Bytes { value: Vec<u8> },
|
||||
Code { code: Box<CodeObject> },
|
||||
Tuple { elements: Vec<ConstantData> },
|
||||
None,
|
||||
Ellipsis,
|
||||
}
|
||||
|
||||
pub enum BorrowedConstant<'a, C: Constant> {
|
||||
Integer { value: &'a BigInt },
|
||||
Float { value: f64 },
|
||||
Complex { value: Complex64 },
|
||||
Boolean { value: bool },
|
||||
Str { value: &'a str },
|
||||
Bytes { value: &'a [u8] },
|
||||
Code { code: &'a CodeObject<C> },
|
||||
Tuple { elements: BorrowedTupleIter<'a, C> },
|
||||
None,
|
||||
Ellipsis,
|
||||
}
|
||||
type BorrowedTupleIter<'a, C> = Box<dyn Iterator<Item = BorrowedConstant<'a, C>> + 'a>;
|
||||
impl<C: Constant> BorrowedConstant<'_, C> {
|
||||
// takes `self` because we need to consume the iterator
|
||||
pub fn fmt_display(self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
BorrowedConstant::Integer { value } => write!(f, "{}", value),
|
||||
BorrowedConstant::Float { value } => write!(f, "{}", value),
|
||||
BorrowedConstant::Complex { value } => write!(f, "{}", value),
|
||||
BorrowedConstant::Boolean { value } => {
|
||||
write!(f, "{}", if value { "True" } else { "False" })
|
||||
}
|
||||
BorrowedConstant::Str { value } => write!(f, "{:?}", value),
|
||||
BorrowedConstant::Bytes { value } => write!(f, "b{:?}", value.as_bstr()),
|
||||
BorrowedConstant::Code { code } => write!(f, "{:?}", code),
|
||||
BorrowedConstant::Tuple { elements } => {
|
||||
write!(f, "(")?;
|
||||
let mut first = true;
|
||||
for c in elements {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
c.fmt_display(f)?;
|
||||
}
|
||||
write!(f, ")")
|
||||
}
|
||||
BorrowedConstant::None => write!(f, "None"),
|
||||
BorrowedConstant::Ellipsis => write!(f, "..."),
|
||||
}
|
||||
}
|
||||
pub fn into_data(self) -> ConstantData {
|
||||
use ConstantData::*;
|
||||
match self {
|
||||
BorrowedConstant::Integer { value } => Integer {
|
||||
value: value.clone(),
|
||||
},
|
||||
BorrowedConstant::Float { value } => Float { value },
|
||||
BorrowedConstant::Complex { value } => Complex { value },
|
||||
BorrowedConstant::Boolean { value } => Boolean { value },
|
||||
BorrowedConstant::Str { value } => Str {
|
||||
value: value.to_owned(),
|
||||
},
|
||||
BorrowedConstant::Bytes { value } => Bytes {
|
||||
value: value.to_owned(),
|
||||
},
|
||||
BorrowedConstant::Code { code } => Code {
|
||||
code: Box::new(code.map_clone_bag(&BasicBag)),
|
||||
},
|
||||
BorrowedConstant::Tuple { elements } => Tuple {
|
||||
elements: elements.map(BorrowedConstant::into_data).collect(),
|
||||
},
|
||||
BorrowedConstant::None => None,
|
||||
BorrowedConstant::Ellipsis => Ellipsis,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum ComparisonOperator {
|
||||
Greater,
|
||||
GreaterOrEqual,
|
||||
Less,
|
||||
LessOrEqual,
|
||||
Equal,
|
||||
NotEqual,
|
||||
In,
|
||||
NotIn,
|
||||
Is,
|
||||
IsNot,
|
||||
ExceptionMatch,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum BinaryOperator {
|
||||
Power,
|
||||
Multiply,
|
||||
MatrixMultiply,
|
||||
Divide,
|
||||
FloorDivide,
|
||||
Modulo,
|
||||
Add,
|
||||
Subtract,
|
||||
Lshift,
|
||||
Rshift,
|
||||
And,
|
||||
Xor,
|
||||
Or,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum UnaryOperator {
|
||||
Not,
|
||||
Invert,
|
||||
Minus,
|
||||
Plus,
|
||||
}
|
||||
|
||||
/*
|
||||
Maintain a stack of blocks on the VM.
|
||||
pub enum BlockType {
|
||||
Loop,
|
||||
Except,
|
||||
}
|
||||
*/
|
||||
|
||||
pub struct Arguments<'a, N: AsRef<str>> {
|
||||
pub posonlyargs: &'a [N],
|
||||
pub args: &'a [N],
|
||||
pub vararg: Option<&'a N>,
|
||||
pub kwonlyargs: &'a [N],
|
||||
pub varkwarg: Option<&'a N>,
|
||||
}
|
||||
|
||||
impl<N: AsRef<str>> fmt::Debug for Arguments<'_, N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
macro_rules! fmt_slice {
|
||||
($x:expr) => {
|
||||
format_args!("[{}]", $x.iter().map(AsRef::as_ref).format(", "))
|
||||
};
|
||||
}
|
||||
f.debug_struct("Arguments")
|
||||
.field("posonlyargs", &fmt_slice!(self.posonlyargs))
|
||||
.field("args", &fmt_slice!(self.posonlyargs))
|
||||
.field("vararg", &self.vararg.map(N::as_ref))
|
||||
.field("kwonlyargs", &fmt_slice!(self.kwonlyargs))
|
||||
.field("varkwarg", &self.varkwarg.map(N::as_ref))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Constant> CodeObject<C> {
|
||||
pub fn new(
|
||||
flags: CodeFlags,
|
||||
posonlyarg_count: usize,
|
||||
arg_count: usize,
|
||||
kwonlyarg_count: usize,
|
||||
source_path: String,
|
||||
first_line_number: usize,
|
||||
obj_name: String,
|
||||
) -> Self {
|
||||
CodeObject {
|
||||
instructions: Box::new([]),
|
||||
locations: Box::new([]),
|
||||
flags,
|
||||
posonlyarg_count,
|
||||
arg_count,
|
||||
kwonlyarg_count,
|
||||
source_path,
|
||||
first_line_number,
|
||||
obj_name,
|
||||
cell2arg: None,
|
||||
constants: Box::new([]),
|
||||
names: Box::new([]),
|
||||
varnames: Box::new([]),
|
||||
cellvars: Box::new([]),
|
||||
freevars: Box::new([]),
|
||||
}
|
||||
}
|
||||
|
||||
// like inspect.getargs
|
||||
pub fn arg_names(&self) -> Arguments<C::Name> {
|
||||
let nargs = self.arg_count;
|
||||
let nkwargs = self.kwonlyarg_count;
|
||||
let mut varargspos = nargs + nkwargs;
|
||||
let posonlyargs = &self.varnames[..self.posonlyarg_count];
|
||||
let args = &self.varnames[..nargs];
|
||||
let kwonlyargs = &self.varnames[nargs..varargspos];
|
||||
|
||||
let vararg = if self.flags.contains(CodeFlags::HAS_VARARGS) {
|
||||
let vararg = &self.varnames[varargspos];
|
||||
varargspos += 1;
|
||||
Some(vararg)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let varkwarg = if self.flags.contains(CodeFlags::HAS_VARKEYWORDS) {
|
||||
Some(&self.varnames[varargspos])
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Arguments {
|
||||
posonlyargs,
|
||||
args,
|
||||
vararg,
|
||||
kwonlyargs,
|
||||
varkwarg,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn label_targets(&self) -> BTreeSet<Label> {
|
||||
let mut label_targets = BTreeSet::new();
|
||||
for instruction in &*self.instructions {
|
||||
match instruction {
|
||||
Jump { target: l }
|
||||
| JumpIfTrue { target: l }
|
||||
| JumpIfFalse { target: l }
|
||||
| JumpIfTrueOrPop { target: l }
|
||||
| JumpIfFalseOrPop { target: l }
|
||||
| ForIter { target: l }
|
||||
| SetupFinally { handler: l }
|
||||
| SetupExcept { handler: l }
|
||||
| SetupWith { end: l }
|
||||
| SetupAsyncWith { end: l } => {
|
||||
label_targets.insert(*l);
|
||||
}
|
||||
SetupLoop { start, end } => {
|
||||
label_targets.insert(*start);
|
||||
label_targets.insert(*end);
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
Import { .. } | ImportStar | ImportFrom { .. } | LoadFast(_) | LoadNameAny(_)
|
||||
| LoadGlobal(_) | LoadDeref(_) | LoadClassDeref(_) | StoreFast(_) | StoreLocal(_)
|
||||
| StoreGlobal(_) | StoreDeref(_) | DeleteFast(_) | DeleteLocal(_) | DeleteGlobal(_)
|
||||
| DeleteDeref(_) | LoadClosure(_) | Subscript | StoreSubscript | DeleteSubscript
|
||||
| StoreAttr { .. } | DeleteAttr { .. } | LoadConst { .. } | UnaryOperation { .. }
|
||||
| BinaryOperation { .. } | LoadAttr { .. } | CompareOperation { .. } | Pop
|
||||
| Rotate { .. } | Duplicate | GetIter | Continue | Break | MakeFunction
|
||||
| CallFunction { .. } | ReturnValue | YieldValue | YieldFrom | SetupAnnotation
|
||||
| EnterFinally | EndFinally | WithCleanupStart | WithCleanupFinish | PopBlock
|
||||
| Raise { .. } | BuildString { .. } | BuildTuple { .. } | BuildList { .. }
|
||||
| BuildSet { .. } | BuildMap { .. } | BuildSlice { .. } | ListAppend { .. }
|
||||
| SetAdd { .. } | MapAdd { .. } | PrintExpr | LoadBuildClass | UnpackSequence { .. }
|
||||
| UnpackEx { .. } | FormatValue { .. } | PopException | Reverse { .. }
|
||||
| GetAwaitable | BeforeAsyncWith | GetAIter | GetANext | MapAddRev { .. } => {}
|
||||
}
|
||||
}
|
||||
label_targets
|
||||
}
|
||||
|
||||
fn display_inner(
|
||||
&self,
|
||||
f: &mut fmt::Formatter,
|
||||
expand_codeobjects: bool,
|
||||
level: usize,
|
||||
) -> fmt::Result {
|
||||
let label_targets = self.label_targets();
|
||||
|
||||
for (offset, instruction) in self.instructions.iter().enumerate() {
|
||||
let arrow = if label_targets.contains(&Label(offset)) {
|
||||
">>"
|
||||
} else {
|
||||
" "
|
||||
};
|
||||
for _ in 0..level {
|
||||
write!(f, " ")?;
|
||||
}
|
||||
write!(f, "{} {:5} ", arrow, offset)?;
|
||||
instruction.fmt_dis(
|
||||
f,
|
||||
&self.constants,
|
||||
&self.names,
|
||||
&self.varnames,
|
||||
&self.cellvars,
|
||||
&self.freevars,
|
||||
expand_codeobjects,
|
||||
level,
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn display_expand_codeobjects<'a>(&'a self) -> impl fmt::Display + 'a {
|
||||
struct Display<'a, C: Constant>(&'a CodeObject<C>);
|
||||
impl<C: Constant> fmt::Display for Display<'_, C> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.0.display_inner(f, true, 1)
|
||||
}
|
||||
}
|
||||
Display(self)
|
||||
}
|
||||
|
||||
pub fn map_bag<Bag: ConstantBag>(self, bag: &Bag) -> CodeObject<Bag::Constant> {
|
||||
let map_names = |names: Box<[C::Name]>| {
|
||||
names
|
||||
.into_vec()
|
||||
.into_iter()
|
||||
.map(|x| bag.make_name_ref(x.as_ref()))
|
||||
.collect::<Box<[_]>>()
|
||||
};
|
||||
CodeObject {
|
||||
constants: self
|
||||
.constants
|
||||
.into_vec()
|
||||
.into_iter()
|
||||
.map(|x| x.map_constant(bag))
|
||||
.collect(),
|
||||
names: map_names(self.names),
|
||||
varnames: map_names(self.varnames),
|
||||
cellvars: map_names(self.cellvars),
|
||||
freevars: map_names(self.freevars),
|
||||
|
||||
instructions: self.instructions,
|
||||
locations: self.locations,
|
||||
flags: self.flags,
|
||||
posonlyarg_count: self.posonlyarg_count,
|
||||
arg_count: self.arg_count,
|
||||
kwonlyarg_count: self.kwonlyarg_count,
|
||||
source_path: self.source_path,
|
||||
first_line_number: self.first_line_number,
|
||||
obj_name: self.obj_name,
|
||||
cell2arg: self.cell2arg,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_clone_bag<Bag: ConstantBag>(&self, bag: &Bag) -> CodeObject<Bag::Constant> {
|
||||
let map_names = |names: &[C::Name]| {
|
||||
names
|
||||
.iter()
|
||||
.map(|x| bag.make_name_ref(x.as_ref()))
|
||||
.collect()
|
||||
};
|
||||
CodeObject {
|
||||
constants: self
|
||||
.constants
|
||||
.iter()
|
||||
.map(|x| bag.make_constant_borrowed(x.borrow_constant()))
|
||||
.collect(),
|
||||
names: map_names(&self.names),
|
||||
varnames: map_names(&self.varnames),
|
||||
cellvars: map_names(&self.cellvars),
|
||||
freevars: map_names(&self.freevars),
|
||||
|
||||
instructions: self.instructions.clone(),
|
||||
locations: self.locations.clone(),
|
||||
flags: self.flags,
|
||||
posonlyarg_count: self.posonlyarg_count,
|
||||
arg_count: self.arg_count,
|
||||
kwonlyarg_count: self.kwonlyarg_count,
|
||||
source_path: self.source_path.clone(),
|
||||
first_line_number: self.first_line_number,
|
||||
obj_name: self.obj_name.clone(),
|
||||
cell2arg: self.cell2arg.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeObject<ConstantData> {
|
||||
/// Load a code object from bytes
|
||||
pub fn from_bytes(data: &[u8]) -> Result<Self, Box<dyn std::error::Error>> {
|
||||
let reader = lz_fear::framed::LZ4FrameReader::new(data)?;
|
||||
Ok(bincode::deserialize_from(reader.into_read())?)
|
||||
}
|
||||
|
||||
/// Serialize this bytecode to bytes.
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let data = bincode::serialize(&self).expect("CodeObject is not serializable");
|
||||
let mut out = Vec::new();
|
||||
lz_fear::framed::CompressionSettings::default()
|
||||
.compress_with_size_unchecked(data.as_slice(), &mut out, data.len() as u64)
|
||||
.unwrap();
|
||||
out
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Constant> fmt::Display for CodeObject<C> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.display_inner(f, false, 1)?;
|
||||
for constant in &*self.constants {
|
||||
if let BorrowedConstant::Code { code } = constant.borrow_constant() {
|
||||
write!(f, "\nDisassembly of {:?}\n", code)?;
|
||||
code.fmt(f)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Instruction {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn fmt_dis<C: Constant>(
|
||||
&self,
|
||||
f: &mut fmt::Formatter,
|
||||
constants: &[C],
|
||||
names: &[C::Name],
|
||||
varnames: &[C::Name],
|
||||
cellvars: &[C::Name],
|
||||
freevars: &[C::Name],
|
||||
expand_codeobjects: bool,
|
||||
level: usize,
|
||||
) -> fmt::Result {
|
||||
macro_rules! w {
|
||||
($variant:ident) => {
|
||||
writeln!(f, stringify!($variant))
|
||||
};
|
||||
($variant:ident, $var:expr) => {
|
||||
writeln!(f, "{:20} ({})", stringify!($variant), $var)
|
||||
};
|
||||
($variant:ident, $var1:expr, $var2:expr) => {
|
||||
writeln!(f, "{:20} ({}, {})", stringify!($variant), $var1, $var2)
|
||||
};
|
||||
($variant:ident, $var1:expr, $var2:expr, $var3:expr) => {
|
||||
writeln!(
|
||||
f,
|
||||
"{:20} ({}, {}, {})",
|
||||
stringify!($variant),
|
||||
$var1,
|
||||
$var2,
|
||||
$var3
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
let cellname = |i: usize| {
|
||||
cellvars
|
||||
.get(i)
|
||||
.unwrap_or_else(|| &freevars[i - cellvars.len()])
|
||||
.as_ref()
|
||||
};
|
||||
|
||||
match self {
|
||||
Import {
|
||||
name_idx,
|
||||
symbols_idx,
|
||||
level,
|
||||
} => w!(
|
||||
Import,
|
||||
format!("{:?}", name_idx.map(|idx| names[idx].as_ref())),
|
||||
format!(
|
||||
"({:?})",
|
||||
symbols_idx
|
||||
.iter()
|
||||
.map(|&idx| names[idx].as_ref())
|
||||
.format(", ")
|
||||
),
|
||||
level
|
||||
),
|
||||
ImportStar => w!(ImportStar),
|
||||
ImportFrom { idx } => w!(ImportFrom, names[*idx].as_ref()),
|
||||
LoadFast(idx) => w!(LoadFast, *idx, varnames[*idx].as_ref()),
|
||||
LoadNameAny(idx) => w!(LoadNameAny, *idx, names[*idx].as_ref()),
|
||||
LoadGlobal(idx) => w!(LoadGlobal, *idx, names[*idx].as_ref()),
|
||||
LoadDeref(idx) => w!(LoadDeref, *idx, cellname(*idx)),
|
||||
LoadClassDeref(idx) => w!(LoadClassDeref, *idx, cellname(*idx)),
|
||||
StoreFast(idx) => w!(StoreFast, *idx, varnames[*idx].as_ref()),
|
||||
StoreLocal(idx) => w!(StoreLocal, *idx, names[*idx].as_ref()),
|
||||
StoreGlobal(idx) => w!(StoreGlobal, *idx, names[*idx].as_ref()),
|
||||
StoreDeref(idx) => w!(StoreDeref, *idx, cellname(*idx)),
|
||||
DeleteFast(idx) => w!(DeleteFast, *idx, varnames[*idx].as_ref()),
|
||||
DeleteLocal(idx) => w!(DeleteLocal, *idx, names[*idx].as_ref()),
|
||||
DeleteGlobal(idx) => w!(DeleteGlobal, *idx, names[*idx].as_ref()),
|
||||
DeleteDeref(idx) => w!(DeleteDeref, *idx, cellname(*idx)),
|
||||
LoadClosure(i) => w!(LoadClosure, *i, cellname(*i)),
|
||||
Subscript => w!(Subscript),
|
||||
StoreSubscript => w!(StoreSubscript),
|
||||
DeleteSubscript => w!(DeleteSubscript),
|
||||
StoreAttr { idx } => w!(StoreAttr, names[*idx].as_ref()),
|
||||
DeleteAttr { idx } => w!(DeleteAttr, names[*idx].as_ref()),
|
||||
LoadConst { idx } => {
|
||||
let value = &constants[*idx];
|
||||
match value.borrow_constant() {
|
||||
BorrowedConstant::Code { code } if expand_codeobjects => {
|
||||
writeln!(f, "{:20} ({:?}):", "LoadConst", code)?;
|
||||
code.display_inner(f, true, level + 1)?;
|
||||
Ok(())
|
||||
}
|
||||
c => {
|
||||
write!(f, "{:20} (", "LoadConst")?;
|
||||
c.fmt_display(f)?;
|
||||
writeln!(f, ")")
|
||||
}
|
||||
}
|
||||
}
|
||||
UnaryOperation { op } => w!(UnaryOperation, format!("{:?}", op)),
|
||||
BinaryOperation { op, inplace } => w!(BinaryOperation, format!("{:?}", op), inplace),
|
||||
LoadAttr { idx } => w!(LoadAttr, names[*idx].as_ref()),
|
||||
CompareOperation { op } => w!(CompareOperation, format!("{:?}", op)),
|
||||
Pop => w!(Pop),
|
||||
Rotate { amount } => w!(Rotate, amount),
|
||||
Duplicate => w!(Duplicate),
|
||||
GetIter => w!(GetIter),
|
||||
Continue => w!(Continue),
|
||||
Break => w!(Break),
|
||||
Jump { target } => w!(Jump, target),
|
||||
JumpIfTrue { target } => w!(JumpIfTrue, target),
|
||||
JumpIfFalse { target } => w!(JumpIfFalse, target),
|
||||
JumpIfTrueOrPop { target } => w!(JumpIfTrueOrPop, target),
|
||||
JumpIfFalseOrPop { target } => w!(JumpIfFalseOrPop, target),
|
||||
MakeFunction => w!(MakeFunction),
|
||||
CallFunction { typ } => w!(CallFunction, format!("{:?}", typ)),
|
||||
ForIter { target } => w!(ForIter, target),
|
||||
ReturnValue => w!(ReturnValue),
|
||||
YieldValue => w!(YieldValue),
|
||||
YieldFrom => w!(YieldFrom),
|
||||
SetupAnnotation => w!(SetupAnnotation),
|
||||
SetupLoop { start, end } => w!(SetupLoop, start, end),
|
||||
SetupExcept { handler } => w!(SetupExcept, handler),
|
||||
SetupFinally { handler } => w!(SetupFinally, handler),
|
||||
EnterFinally => w!(EnterFinally),
|
||||
EndFinally => w!(EndFinally),
|
||||
SetupWith { end } => w!(SetupWith, end),
|
||||
WithCleanupStart => w!(WithCleanupStart),
|
||||
WithCleanupFinish => w!(WithCleanupFinish),
|
||||
BeforeAsyncWith => w!(BeforeAsyncWith),
|
||||
SetupAsyncWith { end } => w!(SetupAsyncWith, end),
|
||||
PopBlock => w!(PopBlock),
|
||||
Raise { argc } => w!(Raise, argc),
|
||||
BuildString { size } => w!(BuildString, size),
|
||||
BuildTuple { size, unpack } => w!(BuildTuple, size, unpack),
|
||||
BuildList { size, unpack } => w!(BuildList, size, unpack),
|
||||
BuildSet { size, unpack } => w!(BuildSet, size, unpack),
|
||||
BuildMap {
|
||||
size,
|
||||
unpack,
|
||||
for_call,
|
||||
} => w!(BuildMap, size, unpack, for_call),
|
||||
BuildSlice { size } => w!(BuildSlice, size),
|
||||
ListAppend { i } => w!(ListAppend, i),
|
||||
SetAdd { i } => w!(SetAdd, i),
|
||||
MapAddRev { i } => w!(MapAddRev, i),
|
||||
PrintExpr => w!(PrintExpr),
|
||||
LoadBuildClass => w!(LoadBuildClass),
|
||||
UnpackSequence { size } => w!(UnpackSequence, size),
|
||||
UnpackEx { before, after } => w!(UnpackEx, before, after),
|
||||
FormatValue { .. } => w!(FormatValue), // TODO: write conversion
|
||||
PopException => w!(PopException),
|
||||
Reverse { amount } => w!(Reverse, amount),
|
||||
GetAwaitable => w!(GetAwaitable),
|
||||
GetAIter => w!(GetAIter),
|
||||
GetANext => w!(GetANext),
|
||||
MapAdd { i } => w!(MapAdd, i),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ConstantData {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.borrow_constant().fmt_display(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: Constant> fmt::Debug for CodeObject<C> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"<code object {} at ??? file {:?}, line {}>",
|
||||
self.obj_name, self.source_path, self.first_line_number
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct FrozenModule<C: Constant = ConstantData> {
|
||||
#[serde(bound(
|
||||
deserialize = "C: serde::Deserialize<'de>, C::Name: serde::Deserialize<'de>",
|
||||
serialize = "C: serde::Serialize, C::Name: serde::Serialize"
|
||||
))]
|
||||
pub code: CodeObject<C>,
|
||||
pub package: bool,
|
||||
}
|
||||
1089
bytecode/src/lib.rs
1089
bytecode/src/lib.rs
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,6 @@ hexf-parse = "0.1.0"
|
||||
cfg-if = "0.1"
|
||||
once_cell = "1.4.1"
|
||||
siphasher = "0.3"
|
||||
rand = "0.8"
|
||||
rand = "0.7.3"
|
||||
derive_more = "0.99.9"
|
||||
volatile = "0.3"
|
||||
|
||||
@@ -1,714 +0,0 @@
|
||||
//! An unresizable vector backed by a `Box<[T]>`
|
||||
|
||||
use std::borrow::{Borrow, BorrowMut};
|
||||
use std::mem::{self, MaybeUninit};
|
||||
use std::ops::{Bound, Deref, DerefMut, RangeBounds};
|
||||
use std::{alloc, cmp, fmt, ptr, slice};
|
||||
|
||||
pub struct BoxVec<T> {
|
||||
xs: Box<[MaybeUninit<T>]>,
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl<T> Drop for BoxVec<T> {
|
||||
fn drop(&mut self) {
|
||||
self.clear();
|
||||
|
||||
// MaybeUninit inhibits array's drop
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! panic_oob {
|
||||
($method_name:expr, $index:expr, $len:expr) => {
|
||||
panic!(
|
||||
concat!(
|
||||
"BoxVec::",
|
||||
$method_name,
|
||||
": index {} is out of bounds in vector of length {}"
|
||||
),
|
||||
$index, $len
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
fn capacity_overflow() -> ! {
|
||||
panic!("capacity overflow")
|
||||
}
|
||||
|
||||
impl<T> BoxVec<T> {
|
||||
pub fn new(n: usize) -> BoxVec<T> {
|
||||
unsafe {
|
||||
let layout = match alloc::Layout::array::<T>(n) {
|
||||
Ok(l) => l,
|
||||
Err(_) => capacity_overflow(),
|
||||
};
|
||||
let ptr = if mem::size_of::<T>() == 0 {
|
||||
ptr::NonNull::<MaybeUninit<T>>::dangling().as_ptr()
|
||||
} else {
|
||||
let ptr = alloc::alloc(layout);
|
||||
if ptr.is_null() {
|
||||
alloc::handle_alloc_error(layout)
|
||||
}
|
||||
ptr as *mut MaybeUninit<T>
|
||||
};
|
||||
let ptr = ptr::slice_from_raw_parts_mut(ptr, n);
|
||||
let xs = Box::from_raw(ptr);
|
||||
BoxVec { xs, len: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.len
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn capacity(&self) -> usize {
|
||||
self.xs.len()
|
||||
}
|
||||
|
||||
pub fn is_full(&self) -> bool {
|
||||
self.len() == self.capacity()
|
||||
}
|
||||
|
||||
pub fn remaining_capacity(&self) -> usize {
|
||||
self.capacity() - self.len()
|
||||
}
|
||||
|
||||
pub fn push(&mut self, element: T) {
|
||||
self.try_push(element).unwrap()
|
||||
}
|
||||
|
||||
pub fn try_push(&mut self, element: T) -> Result<(), CapacityError<T>> {
|
||||
if self.len() < self.capacity() {
|
||||
unsafe {
|
||||
self.push_unchecked(element);
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err(CapacityError::new(element))
|
||||
}
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
/// Must ensure that self.len() < self.capacity()
|
||||
pub unsafe fn push_unchecked(&mut self, element: T) {
|
||||
let len = self.len();
|
||||
debug_assert!(len < self.capacity());
|
||||
ptr::write(self.get_unchecked_ptr(len), element);
|
||||
self.set_len(len + 1);
|
||||
}
|
||||
|
||||
/// Get pointer to where element at `index` would be
|
||||
unsafe fn get_unchecked_ptr(&mut self, index: usize) -> *mut T {
|
||||
self.xs.as_mut_ptr().add(index).cast()
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, index: usize, element: T) {
|
||||
self.try_insert(index, element).unwrap()
|
||||
}
|
||||
|
||||
pub fn try_insert(&mut self, index: usize, element: T) -> Result<(), CapacityError<T>> {
|
||||
if index > self.len() {
|
||||
panic_oob!("try_insert", index, self.len())
|
||||
}
|
||||
if self.len() == self.capacity() {
|
||||
return Err(CapacityError::new(element));
|
||||
}
|
||||
let len = self.len();
|
||||
|
||||
// follows is just like Vec<T>
|
||||
unsafe {
|
||||
// infallible
|
||||
// The spot to put the new value
|
||||
{
|
||||
let p: *mut _ = self.get_unchecked_ptr(index);
|
||||
// Shift everything over to make space. (Duplicating the
|
||||
// `index`th element into two consecutive places.)
|
||||
ptr::copy(p, p.offset(1), len - index);
|
||||
// Write it in, overwriting the first copy of the `index`th
|
||||
// element.
|
||||
ptr::write(p, element);
|
||||
}
|
||||
self.set_len(len + 1);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pop(&mut self) -> Option<T> {
|
||||
if self.is_empty() {
|
||||
return None;
|
||||
}
|
||||
unsafe {
|
||||
let new_len = self.len() - 1;
|
||||
self.set_len(new_len);
|
||||
Some(ptr::read(self.get_unchecked_ptr(new_len)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn swap_remove(&mut self, index: usize) -> T {
|
||||
self.swap_pop(index)
|
||||
.unwrap_or_else(|| panic_oob!("swap_remove", index, self.len()))
|
||||
}
|
||||
|
||||
pub fn swap_pop(&mut self, index: usize) -> Option<T> {
|
||||
let len = self.len();
|
||||
if index >= len {
|
||||
return None;
|
||||
}
|
||||
self.swap(index, len - 1);
|
||||
self.pop()
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, index: usize) -> T {
|
||||
self.pop_at(index)
|
||||
.unwrap_or_else(|| panic_oob!("remove", index, self.len()))
|
||||
}
|
||||
|
||||
pub fn pop_at(&mut self, index: usize) -> Option<T> {
|
||||
if index >= self.len() {
|
||||
None
|
||||
} else {
|
||||
self.drain(index..index + 1).next()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn truncate(&mut self, new_len: usize) {
|
||||
unsafe {
|
||||
if new_len < self.len() {
|
||||
let tail: *mut [_] = &mut self[new_len..];
|
||||
self.len = new_len;
|
||||
ptr::drop_in_place(tail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove all elements in the vector.
|
||||
pub fn clear(&mut self) {
|
||||
self.truncate(0)
|
||||
}
|
||||
|
||||
/// Retains only the elements specified by the predicate.
|
||||
///
|
||||
/// In other words, remove all elements `e` such that `f(&mut e)` returns false.
|
||||
/// This method operates in place and preserves the order of the retained
|
||||
/// elements.
|
||||
pub fn retain<F>(&mut self, mut f: F)
|
||||
where
|
||||
F: FnMut(&mut T) -> bool,
|
||||
{
|
||||
let len = self.len();
|
||||
let mut del = 0;
|
||||
{
|
||||
let v = &mut **self;
|
||||
|
||||
for i in 0..len {
|
||||
if !f(&mut v[i]) {
|
||||
del += 1;
|
||||
} else if del > 0 {
|
||||
v.swap(i - del, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
if del > 0 {
|
||||
self.drain(len - del..);
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the vector’s length without dropping or moving out elements
|
||||
///
|
||||
/// This method is `unsafe` because it changes the notion of the
|
||||
/// number of “valid” elements in the vector. Use with care.
|
||||
///
|
||||
/// This method uses *debug assertions* to check that `length` is
|
||||
/// not greater than the capacity.
|
||||
///
|
||||
/// # Safety
|
||||
/// Must ensure that length <= self.capacity()
|
||||
pub unsafe fn set_len(&mut self, length: usize) {
|
||||
debug_assert!(length <= self.capacity());
|
||||
self.len = length;
|
||||
}
|
||||
|
||||
/// Copy and appends all elements in a slice to the `BoxVec`.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method will return an error if the capacity left (see
|
||||
/// [`remaining_capacity`]) is smaller then the length of the provided
|
||||
/// slice.
|
||||
///
|
||||
/// [`remaining_capacity`]: #method.remaining_capacity
|
||||
pub fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), CapacityError>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
if self.remaining_capacity() < other.len() {
|
||||
return Err(CapacityError::new(()));
|
||||
}
|
||||
|
||||
let self_len = self.len();
|
||||
let other_len = other.len();
|
||||
|
||||
unsafe {
|
||||
let dst = self.as_mut_ptr().add(self_len);
|
||||
ptr::copy_nonoverlapping(other.as_ptr(), dst, other_len);
|
||||
self.set_len(self_len + other_len);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Create a draining iterator that removes the specified range in the vector
|
||||
/// and yields the removed items from start to end. The element range is
|
||||
/// removed even if the iterator is not consumed until the end.
|
||||
///
|
||||
/// Note: It is unspecified how many elements are removed from the vector,
|
||||
/// if the `Drain` value is leaked.
|
||||
///
|
||||
/// **Panics** if the starting point is greater than the end point or if
|
||||
/// the end point is greater than the length of the vector.
|
||||
pub fn drain<R>(&mut self, range: R) -> Drain<T>
|
||||
where
|
||||
R: RangeBounds<usize>,
|
||||
{
|
||||
// Memory safety
|
||||
//
|
||||
// When the Drain is first created, it shortens the length of
|
||||
// the source vector to make sure no uninitialized or moved-from elements
|
||||
// are accessible at all if the Drain's destructor never gets to run.
|
||||
//
|
||||
// Drain will ptr::read out the values to remove.
|
||||
// When finished, remaining tail of the vec is copied back to cover
|
||||
// the hole, and the vector length is restored to the new length.
|
||||
//
|
||||
let len = self.len();
|
||||
let start = match range.start_bound() {
|
||||
Bound::Unbounded => 0,
|
||||
Bound::Included(&i) => i,
|
||||
Bound::Excluded(&i) => i.saturating_add(1),
|
||||
};
|
||||
let end = match range.end_bound() {
|
||||
Bound::Excluded(&j) => j,
|
||||
Bound::Included(&j) => j.saturating_add(1),
|
||||
Bound::Unbounded => len,
|
||||
};
|
||||
self.drain_range(start, end)
|
||||
}
|
||||
|
||||
fn drain_range(&mut self, start: usize, end: usize) -> Drain<T> {
|
||||
let len = self.len();
|
||||
|
||||
// bounds check happens here (before length is changed!)
|
||||
let range_slice: *const _ = &self[start..end];
|
||||
|
||||
// Calling `set_len` creates a fresh and thus unique mutable references, making all
|
||||
// older aliases we created invalid. So we cannot call that function.
|
||||
self.len = start;
|
||||
|
||||
unsafe {
|
||||
Drain {
|
||||
tail_start: end,
|
||||
tail_len: len - end,
|
||||
iter: (*range_slice).iter(),
|
||||
vec: ptr::NonNull::from(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a slice containing all elements of the vector.
|
||||
pub fn as_slice(&self) -> &[T] {
|
||||
self
|
||||
}
|
||||
|
||||
/// Return a mutable slice containing all elements of the vector.
|
||||
pub fn as_mut_slice(&mut self) -> &mut [T] {
|
||||
self
|
||||
}
|
||||
|
||||
/// Return a raw pointer to the vector's buffer.
|
||||
#[inline]
|
||||
pub fn as_ptr(&self) -> *const T {
|
||||
self.xs.as_ptr().cast()
|
||||
}
|
||||
|
||||
/// Return a raw mutable pointer to the vector's buffer.
|
||||
#[inline]
|
||||
pub fn as_mut_ptr(&mut self) -> *mut T {
|
||||
self.xs.as_mut_ptr().cast()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for BoxVec<T> {
|
||||
type Target = [T];
|
||||
#[inline]
|
||||
fn deref(&self) -> &[T] {
|
||||
unsafe { slice::from_raw_parts(self.as_ptr(), self.len()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for BoxVec<T> {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut [T] {
|
||||
let len = self.len();
|
||||
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), len) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterate the `BoxVec` with references to each element.
|
||||
impl<'a, T> IntoIterator for &'a BoxVec<T> {
|
||||
type Item = &'a T;
|
||||
type IntoIter = slice::Iter<'a, T>;
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterate the `BoxVec` with mutable references to each element.
|
||||
impl<'a, T> IntoIterator for &'a mut BoxVec<T> {
|
||||
type Item = &'a mut T;
|
||||
type IntoIter = slice::IterMut<'a, T>;
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterate the `BoxVec` with each element by value.
|
||||
///
|
||||
/// The vector is consumed by this operation.
|
||||
impl<T> IntoIterator for BoxVec<T> {
|
||||
type Item = T;
|
||||
type IntoIter = IntoIter<T>;
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
IntoIter { index: 0, v: self }
|
||||
}
|
||||
}
|
||||
|
||||
/// By-value iterator for `BoxVec`.
|
||||
pub struct IntoIter<T> {
|
||||
index: usize,
|
||||
v: BoxVec<T>,
|
||||
}
|
||||
|
||||
impl<T> Iterator for IntoIter<T> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<T> {
|
||||
if self.index == self.v.len {
|
||||
None
|
||||
} else {
|
||||
unsafe {
|
||||
let index = self.index;
|
||||
self.index += 1;
|
||||
Some(ptr::read(self.v.get_unchecked_ptr(index)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let len = self.v.len() - self.index;
|
||||
(len, Some(len))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DoubleEndedIterator for IntoIter<T> {
|
||||
fn next_back(&mut self) -> Option<T> {
|
||||
if self.index == self.v.len {
|
||||
None
|
||||
} else {
|
||||
unsafe {
|
||||
let new_len = self.v.len() - 1;
|
||||
self.v.set_len(new_len);
|
||||
Some(ptr::read(self.v.get_unchecked_ptr(new_len)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ExactSizeIterator for IntoIter<T> {}
|
||||
|
||||
impl<T> Drop for IntoIter<T> {
|
||||
fn drop(&mut self) {
|
||||
// panic safety: Set length to 0 before dropping elements.
|
||||
let index = self.index;
|
||||
let len = self.v.len();
|
||||
unsafe {
|
||||
self.v.set_len(0);
|
||||
let elements = slice::from_raw_parts_mut(self.v.get_unchecked_ptr(index), len - index);
|
||||
ptr::drop_in_place(elements);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for IntoIter<T>
|
||||
where
|
||||
T: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_list().entries(&self.v[self.index..]).finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// A draining iterator for `BoxVec`.
|
||||
pub struct Drain<'a, T> {
|
||||
/// Index of tail to preserve
|
||||
tail_start: usize,
|
||||
/// Length of tail
|
||||
tail_len: usize,
|
||||
/// Current remaining range to remove
|
||||
iter: slice::Iter<'a, T>,
|
||||
vec: ptr::NonNull<BoxVec<T>>,
|
||||
}
|
||||
|
||||
unsafe impl<'a, T: Sync> Sync for Drain<'a, T> {}
|
||||
unsafe impl<'a, T: Send> Send for Drain<'a, T> {}
|
||||
|
||||
impl<T> Iterator for Drain<'_, T> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.iter
|
||||
.next()
|
||||
.map(|elt| unsafe { ptr::read(elt as *const _) })
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DoubleEndedIterator for Drain<'_, T> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
self.iter
|
||||
.next_back()
|
||||
.map(|elt| unsafe { ptr::read(elt as *const _) })
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ExactSizeIterator for Drain<'_, T> {}
|
||||
|
||||
impl<'a, T> Drain<'a, T> {
|
||||
pub fn as_slice(&self) -> &'a [T] {
|
||||
self.iter.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for Drain<'_, T> {
|
||||
fn drop(&mut self) {
|
||||
// len is currently 0 so panicking while dropping will not cause a double drop.
|
||||
|
||||
// exhaust self first
|
||||
while let Some(_) = self.next() {}
|
||||
|
||||
if self.tail_len > 0 {
|
||||
unsafe {
|
||||
let source_vec = self.vec.as_mut();
|
||||
// memmove back untouched tail, update to new length
|
||||
let start = source_vec.len();
|
||||
let tail = self.tail_start;
|
||||
let src = source_vec.as_ptr().add(tail);
|
||||
let dst = source_vec.as_mut_ptr().add(start);
|
||||
ptr::copy(src, dst, self.tail_len);
|
||||
source_vec.set_len(start + self.tail_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ScopeExitGuard<T, Data, F>
|
||||
where
|
||||
F: FnMut(&Data, &mut T),
|
||||
{
|
||||
value: T,
|
||||
data: Data,
|
||||
f: F,
|
||||
}
|
||||
|
||||
impl<T, Data, F> Drop for ScopeExitGuard<T, Data, F>
|
||||
where
|
||||
F: FnMut(&Data, &mut T),
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
(self.f)(&self.data, &mut self.value)
|
||||
}
|
||||
}
|
||||
|
||||
/// Extend the `BoxVec` with an iterator.
|
||||
///
|
||||
/// Does not extract more items than there is space for. No error
|
||||
/// occurs if there are more iterator elements.
|
||||
impl<T> Extend<T> for BoxVec<T> {
|
||||
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
|
||||
let take = self.capacity() - self.len();
|
||||
unsafe {
|
||||
let len = self.len();
|
||||
let mut ptr = raw_ptr_add(self.as_mut_ptr(), len);
|
||||
let end_ptr = raw_ptr_add(ptr, take);
|
||||
// Keep the length in a separate variable, write it back on scope
|
||||
// exit. To help the compiler with alias analysis and stuff.
|
||||
// We update the length to handle panic in the iteration of the
|
||||
// user's iterator, without dropping any elements on the floor.
|
||||
let mut guard = ScopeExitGuard {
|
||||
value: &mut self.len,
|
||||
data: len,
|
||||
f: move |&len, self_len| {
|
||||
**self_len = len;
|
||||
},
|
||||
};
|
||||
let mut iter = iter.into_iter();
|
||||
loop {
|
||||
if ptr == end_ptr {
|
||||
break;
|
||||
}
|
||||
if let Some(elt) = iter.next() {
|
||||
raw_ptr_write(ptr, elt);
|
||||
ptr = raw_ptr_add(ptr, 1);
|
||||
guard.data += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Rawptr add but uses arithmetic distance for ZST
|
||||
unsafe fn raw_ptr_add<T>(ptr: *mut T, offset: usize) -> *mut T {
|
||||
if mem::size_of::<T>() == 0 {
|
||||
// Special case for ZST
|
||||
(ptr as usize).wrapping_add(offset) as _
|
||||
} else {
|
||||
ptr.add(offset)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn raw_ptr_write<T>(ptr: *mut T, value: T) {
|
||||
if mem::size_of::<T>() == 0 {
|
||||
/* nothing */
|
||||
} else {
|
||||
ptr::write(ptr, value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for BoxVec<T>
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
let mut new = BoxVec::new(self.capacity());
|
||||
new.extend(self.iter().cloned());
|
||||
new
|
||||
}
|
||||
|
||||
fn clone_from(&mut self, rhs: &Self) {
|
||||
// recursive case for the common prefix
|
||||
let prefix = cmp::min(self.len(), rhs.len());
|
||||
self[..prefix].clone_from_slice(&rhs[..prefix]);
|
||||
|
||||
if prefix < self.len() {
|
||||
// rhs was shorter
|
||||
for _ in 0..self.len() - prefix {
|
||||
self.pop();
|
||||
}
|
||||
} else {
|
||||
let rhs_elems = rhs[self.len()..].iter().cloned();
|
||||
self.extend(rhs_elems);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PartialEq for BoxVec<T>
|
||||
where
|
||||
T: PartialEq,
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
**self == **other
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PartialEq<[T]> for BoxVec<T>
|
||||
where
|
||||
T: PartialEq,
|
||||
{
|
||||
fn eq(&self, other: &[T]) -> bool {
|
||||
**self == *other
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Eq for BoxVec<T> where T: Eq {}
|
||||
|
||||
impl<T> Borrow<[T]> for BoxVec<T> {
|
||||
fn borrow(&self) -> &[T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> BorrowMut<[T]> for BoxVec<T> {
|
||||
fn borrow_mut(&mut self) -> &mut [T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsRef<[T]> for BoxVec<T> {
|
||||
fn as_ref(&self) -> &[T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsMut<[T]> for BoxVec<T> {
|
||||
fn as_mut(&mut self) -> &mut [T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for BoxVec<T>
|
||||
where
|
||||
T: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
(**self).fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Error value indicating insufficient capacity
|
||||
#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub struct CapacityError<T = ()> {
|
||||
element: T,
|
||||
}
|
||||
|
||||
impl<T> CapacityError<T> {
|
||||
/// Create a new `CapacityError` from `element`.
|
||||
pub fn new(element: T) -> CapacityError<T> {
|
||||
CapacityError { element }
|
||||
}
|
||||
|
||||
/// Extract the overflowing element
|
||||
pub fn element(self) -> T {
|
||||
self.element
|
||||
}
|
||||
|
||||
/// Convert into a `CapacityError` that does not carry an element.
|
||||
pub fn simplify(self) -> CapacityError {
|
||||
CapacityError { element: () }
|
||||
}
|
||||
}
|
||||
|
||||
const CAPERROR: &str = "insufficient capacity";
|
||||
|
||||
impl<T> std::error::Error for CapacityError<T> {}
|
||||
|
||||
impl<T> fmt::Display for CapacityError<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", CAPERROR)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for CapacityError<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "capacity error: {}", CAPERROR)
|
||||
}
|
||||
}
|
||||
@@ -252,7 +252,7 @@ pub fn to_hex(value: f64) -> String {
|
||||
const BITS: i16 = 52;
|
||||
const FRACT_MASK: u64 = 0xf_ffff_ffff_ffff;
|
||||
format!(
|
||||
"{}{:#x}.{:013x}p{:+}",
|
||||
"{}0x{:x}.{:013x}p{:+}",
|
||||
sign_fmt,
|
||||
mantissa >> BITS,
|
||||
mantissa & FRACT_MASK,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//! A crate to hold types and functions common to all rustpython components.
|
||||
|
||||
pub mod borrow;
|
||||
pub mod boxvec;
|
||||
pub mod cmp;
|
||||
pub mod float_ops;
|
||||
pub mod hash;
|
||||
|
||||
@@ -7,20 +7,14 @@ repository = "https://github.com/RustPython/RustPython"
|
||||
license = "MIT"
|
||||
edition = "2018"
|
||||
|
||||
[features]
|
||||
std = ["rustpython-bytecode/std", "itertools/use_std"]
|
||||
default = ["std"]
|
||||
|
||||
[dependencies]
|
||||
indexmap = "1.0"
|
||||
itertools = { version = "0.9", default-features = false }
|
||||
rustpython-bytecode = { path = "../bytecode", version = "0.1.1", default-features = false }
|
||||
itertools = "0.9"
|
||||
rustpython-bytecode = { path = "../bytecode", version = "0.1.1" }
|
||||
rustpython-ast = { path = "../ast" }
|
||||
num-complex = { version = "0.3", features = ["serde"] }
|
||||
num-traits = "0.2"
|
||||
log = "0.4"
|
||||
ahash = "0.6"
|
||||
scopeguard = "1.1"
|
||||
arrayvec = "0.5"
|
||||
|
||||
[dev-dependencies]
|
||||
rustpython-parser = { path = "../parser" }
|
||||
|
||||
@@ -5,10 +5,6 @@ description = "A usability wrapper around rustpython-parser and rustpython-compi
|
||||
authors = ["RustPython Team"]
|
||||
edition = "2018"
|
||||
|
||||
[features]
|
||||
std = ["rustpython-compiler-core/std", "rustpython-bytecode/std", "rustpython-parser/std"]
|
||||
default = ["std"]
|
||||
|
||||
[dependencies]
|
||||
thiserror = "1.0"
|
||||
rustpython-compiler-core = { path = ".." }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use rustpython_bytecode::CodeObject;
|
||||
use rustpython_bytecode::bytecode::CodeObject;
|
||||
use rustpython_compiler_core::{compile, symboltable};
|
||||
use rustpython_parser::{ast::Location, parser};
|
||||
use std::fmt;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,7 @@
|
||||
use rustpython_ast::Location;
|
||||
|
||||
use alloc::string::String;
|
||||
use core::fmt;
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CompileError {
|
||||
@@ -39,7 +37,6 @@ pub enum CompileErrorType {
|
||||
InvalidFuturePlacement,
|
||||
InvalidFutureFeature(String),
|
||||
FunctionImportStar,
|
||||
TooManyStarUnpack,
|
||||
}
|
||||
|
||||
impl fmt::Display for CompileErrorType {
|
||||
@@ -73,14 +70,10 @@ impl fmt::Display for CompileErrorType {
|
||||
CompileErrorType::FunctionImportStar => {
|
||||
write!(f, "import * only allowed at module level")
|
||||
}
|
||||
CompileErrorType::TooManyStarUnpack => {
|
||||
write!(f, "too many expressions in star-unpacking assignment")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for CompileErrorType {}
|
||||
|
||||
impl fmt::Display for CompileError {
|
||||
@@ -89,5 +82,8 @@ impl fmt::Display for CompileError {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for CompileError {}
|
||||
impl Error for CompileError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
use crate::IndexSet;
|
||||
use rustpython_bytecode::{CodeFlags, CodeObject, ConstantData, Instruction, Label, Location};
|
||||
|
||||
pub type BlockIdx = Label;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InstructionInfo {
|
||||
/// If the instruction has a Label argument, it's actually a BlockIdx, not a code offset
|
||||
pub instr: Instruction,
|
||||
pub location: Location,
|
||||
}
|
||||
|
||||
// TODO: look into using petgraph for handling blocks and stuff? it's heavier than this, but it
|
||||
// might enable more analysis/optimizations
|
||||
#[derive(Debug)]
|
||||
pub struct Block {
|
||||
pub instructions: Vec<InstructionInfo>,
|
||||
pub next: BlockIdx,
|
||||
}
|
||||
impl Default for Block {
|
||||
fn default() -> Self {
|
||||
Block {
|
||||
instructions: Vec::new(),
|
||||
next: Label(u32::MAX),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CodeInfo {
|
||||
pub flags: CodeFlags,
|
||||
pub posonlyarg_count: usize, // Number of positional-only arguments
|
||||
pub arg_count: usize,
|
||||
pub kwonlyarg_count: usize,
|
||||
pub source_path: String,
|
||||
pub first_line_number: usize,
|
||||
pub obj_name: String, // Name of the object that created this code object
|
||||
|
||||
pub blocks: Vec<Block>,
|
||||
pub current_block: BlockIdx,
|
||||
pub constants: Vec<ConstantData>,
|
||||
pub name_cache: IndexSet<String>,
|
||||
pub varname_cache: IndexSet<String>,
|
||||
pub cellvar_cache: IndexSet<String>,
|
||||
pub freevar_cache: IndexSet<String>,
|
||||
}
|
||||
impl CodeInfo {
|
||||
pub fn finalize_code(mut self, optimize: u8) -> CodeObject {
|
||||
let max_stacksize = self.max_stacksize();
|
||||
let cell2arg = self.cell2arg();
|
||||
|
||||
if optimize > 0 {
|
||||
self.dce();
|
||||
}
|
||||
|
||||
let CodeInfo {
|
||||
flags,
|
||||
posonlyarg_count,
|
||||
arg_count,
|
||||
kwonlyarg_count,
|
||||
source_path,
|
||||
first_line_number,
|
||||
obj_name,
|
||||
|
||||
blocks,
|
||||
current_block: _,
|
||||
constants,
|
||||
name_cache,
|
||||
varname_cache,
|
||||
cellvar_cache,
|
||||
freevar_cache,
|
||||
} = self;
|
||||
|
||||
let mut num_instructions = 0;
|
||||
let mut block_to_offset = vec![Label(0); blocks.len()];
|
||||
|
||||
for (idx, block) in iter_blocks(&blocks) {
|
||||
block_to_offset[idx.0 as usize] = Label(num_instructions as u32);
|
||||
num_instructions += block.instructions.len();
|
||||
}
|
||||
|
||||
let mut instructions = Vec::with_capacity(num_instructions);
|
||||
let mut locations = Vec::with_capacity(num_instructions);
|
||||
|
||||
for (_, block) in iter_blocks(&blocks) {
|
||||
for info in &block.instructions {
|
||||
let mut instr = info.instr.clone();
|
||||
if let Some(l) = instr.label_arg_mut() {
|
||||
*l = block_to_offset[l.0 as usize];
|
||||
}
|
||||
instructions.push(instr);
|
||||
locations.push(info.location);
|
||||
}
|
||||
}
|
||||
|
||||
CodeObject {
|
||||
flags,
|
||||
posonlyarg_count,
|
||||
arg_count,
|
||||
kwonlyarg_count,
|
||||
source_path,
|
||||
first_line_number,
|
||||
obj_name,
|
||||
|
||||
max_stacksize,
|
||||
instructions: instructions.into_boxed_slice(),
|
||||
locations: locations.into_boxed_slice(),
|
||||
constants: constants.into(),
|
||||
names: name_cache.into_iter().collect(),
|
||||
varnames: varname_cache.into_iter().collect(),
|
||||
cellvars: cellvar_cache.into_iter().collect(),
|
||||
freevars: freevar_cache.into_iter().collect(),
|
||||
cell2arg,
|
||||
}
|
||||
}
|
||||
|
||||
fn cell2arg(&self) -> Option<Box<[isize]>> {
|
||||
if self.cellvar_cache.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let total_args = self.arg_count
|
||||
+ self.kwonlyarg_count
|
||||
+ self.flags.contains(CodeFlags::HAS_VARARGS) as usize
|
||||
+ self.flags.contains(CodeFlags::HAS_VARKEYWORDS) as usize;
|
||||
|
||||
let mut found_cellarg = false;
|
||||
let cell2arg = self
|
||||
.cellvar_cache
|
||||
.iter()
|
||||
.map(|var| {
|
||||
self.varname_cache
|
||||
.get_index_of(var)
|
||||
// check that it's actually an arg
|
||||
.filter(|i| *i < total_args)
|
||||
.map_or(-1, |i| {
|
||||
found_cellarg = true;
|
||||
i as isize
|
||||
})
|
||||
})
|
||||
.collect::<Box<[_]>>();
|
||||
|
||||
if found_cellarg {
|
||||
Some(cell2arg)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn dce(&mut self) {
|
||||
for block in &mut self.blocks {
|
||||
let mut last_instr = None;
|
||||
for (i, ins) in block.instructions.iter().enumerate() {
|
||||
if ins.instr.unconditional_branch() {
|
||||
last_instr = Some(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if let Some(i) = last_instr {
|
||||
block.instructions.truncate(i + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn max_stacksize(&self) -> u32 {
|
||||
let mut maxdepth = 0u32;
|
||||
let mut stack = Vec::with_capacity(self.blocks.len());
|
||||
let mut startdepths = vec![u32::MAX; self.blocks.len()];
|
||||
startdepths[0] = 0;
|
||||
stack.push(Label(0));
|
||||
'process_blocks: while let Some(block) = stack.pop() {
|
||||
let mut depth = startdepths[block.0 as usize];
|
||||
let block = &self.blocks[block.0 as usize];
|
||||
for i in &block.instructions {
|
||||
let instr = &i.instr;
|
||||
let effect = instr.stack_effect(false);
|
||||
let new_depth = add_ui(depth, effect);
|
||||
if new_depth > maxdepth {
|
||||
maxdepth = new_depth
|
||||
}
|
||||
// we don't want to worry about Continue or Break, they use unwinding to jump to
|
||||
// their targets and as such the stack size is taken care of in frame.rs by setting
|
||||
// it back to the level it was at when SetupLoop was run
|
||||
let jump_label = instr.label_arg().filter(
|
||||
|_| !matches!(instr, Instruction::Continue { .. } | Instruction::Break { .. }),
|
||||
);
|
||||
if let Some(&target_block) = jump_label {
|
||||
let effect = instr.stack_effect(true);
|
||||
let target_depth = add_ui(depth, effect);
|
||||
if target_depth > maxdepth {
|
||||
maxdepth = target_depth
|
||||
}
|
||||
stackdepth_push(&mut stack, &mut startdepths, target_block, target_depth);
|
||||
}
|
||||
depth = new_depth;
|
||||
if instr.unconditional_branch() {
|
||||
continue 'process_blocks;
|
||||
}
|
||||
}
|
||||
stackdepth_push(&mut stack, &mut startdepths, block.next, depth);
|
||||
}
|
||||
maxdepth
|
||||
}
|
||||
}
|
||||
|
||||
fn stackdepth_push(stack: &mut Vec<Label>, startdepths: &mut [u32], target: Label, depth: u32) {
|
||||
let block_depth = &mut startdepths[target.0 as usize];
|
||||
if *block_depth == u32::MAX || depth > *block_depth {
|
||||
*block_depth = depth;
|
||||
stack.push(target);
|
||||
}
|
||||
}
|
||||
|
||||
fn add_ui(a: u32, b: i32) -> u32 {
|
||||
if b < 0 {
|
||||
a - b.abs() as u32
|
||||
} else {
|
||||
a + b as u32
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_blocks(blocks: &[Block]) -> impl Iterator<Item = (BlockIdx, &Block)> + '_ {
|
||||
let get_idx = move |i: BlockIdx| blocks.get(i.0 as usize).map(|b| (i, b));
|
||||
std::iter::successors(get_idx(Label(0)), move |(_, b)| get_idx(b.next)) // if b.next is u32::MAX that's the end
|
||||
}
|
||||
@@ -1,18 +1,12 @@
|
||||
//! Compile a Python AST or source code into bytecode consumable by RustPython.
|
||||
//! Compile a Python AST or source code into bytecode consumable by RustPython or
|
||||
//! (eventually) CPython.
|
||||
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/master/logo.png")]
|
||||
#![doc(html_root_url = "https://docs.rs/rustpython-compiler/")]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
type IndexMap<K, V> = indexmap::IndexMap<K, V, ahash::RandomState>;
|
||||
type IndexSet<T> = indexmap::IndexSet<T, ahash::RandomState>;
|
||||
|
||||
pub mod compile;
|
||||
pub mod error;
|
||||
pub mod ir;
|
||||
pub mod mode;
|
||||
pub mod symboltable;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use core::fmt;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Mode {
|
||||
Exec,
|
||||
@@ -7,7 +5,7 @@ pub enum Mode {
|
||||
Single,
|
||||
}
|
||||
|
||||
impl core::str::FromStr for Mode {
|
||||
impl std::str::FromStr for Mode {
|
||||
type Err = ModeParseError;
|
||||
fn from_str(s: &str) -> Result<Self, ModeParseError> {
|
||||
match s {
|
||||
@@ -24,8 +22,8 @@ pub struct ModeParseError {
|
||||
_priv: (),
|
||||
}
|
||||
|
||||
impl fmt::Display for ModeParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
impl std::fmt::Display for ModeParseError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, r#"mode should be "exec", "eval", or "single""#)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,9 @@ Inspirational file: https://github.com/python/cpython/blob/master/Python/symtabl
|
||||
*/
|
||||
|
||||
use crate::error::{CompileError, CompileErrorType};
|
||||
use crate::IndexMap;
|
||||
use alloc::{borrow::ToOwned, format, string::String, vec, vec::Vec};
|
||||
use core::fmt;
|
||||
use indexmap::map::IndexMap;
|
||||
use rustpython_ast::{self as ast, Location};
|
||||
use std::fmt;
|
||||
|
||||
pub fn make_symbol_table(program: &ast::Program) -> Result<SymbolTable, SymbolTableError> {
|
||||
let mut builder = SymbolTableBuilder::default();
|
||||
@@ -59,7 +58,7 @@ impl SymbolTable {
|
||||
typ,
|
||||
line_number,
|
||||
is_nested,
|
||||
symbols: IndexMap::default(),
|
||||
symbols: IndexMap::new(),
|
||||
sub_tables: vec![],
|
||||
}
|
||||
}
|
||||
@@ -188,8 +187,8 @@ impl SymbolTable {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for SymbolTable {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
impl std::fmt::Debug for SymbolTable {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"SymbolTable({:?} symbols, {:?} sub scopes)",
|
||||
@@ -210,9 +209,8 @@ fn analyze_symbol_table(symbol_table: &mut SymbolTable) -> SymbolTableResult {
|
||||
type SymbolMap = IndexMap<String, Symbol>;
|
||||
|
||||
mod stack {
|
||||
use alloc::vec::Vec;
|
||||
use core::ptr::NonNull;
|
||||
|
||||
use std::panic;
|
||||
use std::ptr::NonNull;
|
||||
pub struct StackStack<T> {
|
||||
v: Vec<NonNull<T>>,
|
||||
}
|
||||
@@ -229,10 +227,9 @@ mod stack {
|
||||
F: FnOnce(&mut Self) -> R,
|
||||
{
|
||||
self.v.push(x.into());
|
||||
let mut this = scopeguard::guard(self, |this| {
|
||||
this.v.pop();
|
||||
});
|
||||
f(&mut this)
|
||||
let res = panic::catch_unwind(panic::AssertUnwindSafe(|| f(self)));
|
||||
self.v.pop();
|
||||
res.unwrap_or_else(|x| panic::resume_unwind(x))
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &T> + DoubleEndedIterator + '_ {
|
||||
@@ -276,7 +273,7 @@ struct SymbolTableAnalyzer {
|
||||
|
||||
impl SymbolTableAnalyzer {
|
||||
fn analyze_symbol_table(&mut self, symbol_table: &mut SymbolTable) -> SymbolTableResult {
|
||||
let symbols = core::mem::take(&mut symbol_table.symbols);
|
||||
let symbols = std::mem::take(&mut symbol_table.symbols);
|
||||
let sub_tables = &mut *symbol_table.sub_tables;
|
||||
|
||||
let mut info = (symbols, symbol_table.typ);
|
||||
@@ -472,7 +469,7 @@ impl SymbolTableAnalyzer {
|
||||
SymbolTableType::Class => {
|
||||
// named expressions are forbidden in comprehensions on class scope
|
||||
return Err(SymbolTableError {
|
||||
error: "assignment expression within a comprehension cannot be used in a class body".to_owned(),
|
||||
error: "assignment expression within a comprehension cannot be used in a class body".to_string(),
|
||||
// TODO: accurate location info, somehow
|
||||
location: Location::default(),
|
||||
});
|
||||
@@ -1002,7 +999,7 @@ impl SymbolTableBuilder {
|
||||
// comprehension iterator definitions
|
||||
if let ExpressionContext::IterDefinitionExp = context {
|
||||
return Err(SymbolTableError {
|
||||
error: "assignment expression cannot be used in a comprehension iterable expression".to_owned(),
|
||||
error: "assignment expression cannot be used in a comprehension iterable expression".to_string(),
|
||||
// TODO: accurate location info, somehow
|
||||
location: Location::default(),
|
||||
});
|
||||
@@ -1221,7 +1218,7 @@ impl SymbolTableBuilder {
|
||||
return Err(SymbolTableError {
|
||||
error:
|
||||
"assignment expression cannot be used in a comprehension iterable expression"
|
||||
.to_owned(),
|
||||
.to_string(),
|
||||
location,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ use crate::{extract_spans, Diagnostic};
|
||||
use once_cell::sync::Lazy;
|
||||
use proc_macro2::{Span, TokenStream as TokenStream2};
|
||||
use quote::quote;
|
||||
use rustpython_bytecode::{CodeObject, FrozenModule};
|
||||
use rustpython_bytecode::bytecode::{CodeObject, FrozenModule};
|
||||
use rustpython_compiler as compile;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
@@ -242,7 +242,7 @@ impl PyCompileInput {
|
||||
});
|
||||
} else if ident == "crate_name" {
|
||||
let name = match &name_value.lit {
|
||||
Lit::Str(s) => s.parse()?,
|
||||
Lit::Str(s) => syn::Ident::new(&s.value(), s.span()),
|
||||
_ => bail_span!(name_value.lit, "source must be a string"),
|
||||
};
|
||||
crate_name = Some(name);
|
||||
@@ -261,7 +261,7 @@ impl PyCompileInput {
|
||||
source,
|
||||
mode: mode.unwrap_or(compile::Mode::Exec),
|
||||
module_name: module_name.unwrap_or_else(|| "frozen".to_owned()),
|
||||
crate_name: crate_name.unwrap_or_else(|| syn::parse_quote!(::rustpython_vm::bytecode)),
|
||||
crate_name: crate_name.unwrap_or_else(|| syn::parse_quote!(rustpython_vm)),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -302,7 +302,7 @@ struct PyCompileArgs {
|
||||
source: CompilationSource,
|
||||
mode: compile::Mode,
|
||||
module_name: String,
|
||||
crate_name: syn::Path,
|
||||
crate_name: syn::Ident,
|
||||
}
|
||||
|
||||
pub fn impl_py_compile(input: TokenStream2) -> Result<TokenStream2, Diagnostic> {
|
||||
@@ -316,7 +316,7 @@ pub fn impl_py_compile(input: TokenStream2) -> Result<TokenStream2, Diagnostic>
|
||||
let bytes = LitByteStr::new(&bytes, Span::call_site());
|
||||
|
||||
let output = quote! {
|
||||
#crate_name::CodeObject::from_bytes(#bytes)
|
||||
::#crate_name::bytecode::CodeObject::from_bytes(#bytes)
|
||||
.expect("Deserializing CodeObject failed")
|
||||
};
|
||||
|
||||
@@ -339,8 +339,8 @@ pub fn impl_py_freeze(input: TokenStream2) -> Result<TokenStream2, Diagnostic> {
|
||||
let bytes = code.to_bytes();
|
||||
let bytes = LitByteStr::new(&bytes, Span::call_site());
|
||||
quote! {
|
||||
m.insert(#module_name.into(), #crate_name::FrozenModule {
|
||||
code: #crate_name::CodeObject::from_bytes(
|
||||
m.insert(#module_name.into(), ::#crate_name::bytecode::FrozenModule {
|
||||
code: ::#crate_name::bytecode::CodeObject::from_bytes(
|
||||
#bytes
|
||||
).expect("Deserializing CodeObject failed"),
|
||||
package: #package,
|
||||
|
||||
@@ -326,7 +326,7 @@ where
|
||||
quote! {
|
||||
class.set_str_attr(
|
||||
#py_name,
|
||||
ctx.make_funcdef(#py_name, Self::#ident)
|
||||
ctx.new_function_named(Self::#ident, #py_name.to_owned())
|
||||
#doc
|
||||
.#build_func(ctx),
|
||||
);
|
||||
|
||||
@@ -263,7 +263,7 @@ impl ModuleItem for FunctionItem {
|
||||
);
|
||||
let module = args.module_name();
|
||||
let new_func = quote_spanned!(ident.span()=>
|
||||
vm.ctx.make_funcdef(#py_name, #ident)
|
||||
vm.ctx.new_function_named(#ident, #py_name.to_owned())
|
||||
#doc
|
||||
.into_function()
|
||||
.with_module(vm.ctx.new_str(#module.to_owned()))
|
||||
|
||||
@@ -41,9 +41,7 @@ fn run(vm: &vm::VirtualMachine) -> vm::pyobject::PyResult<()> {
|
||||
let scope: vm::scope::Scope = vm.new_scope_with_builtins();
|
||||
|
||||
// typing `quit()` is too long, let's make `on(False)` work instead.
|
||||
scope
|
||||
.globals
|
||||
.set_item("on", vm.ctx.new_function("on", on), vm)?;
|
||||
scope.globals.set_item("on", vm.ctx.new_function(on), vm)?;
|
||||
|
||||
// let's include a fibonacci function, but let's be lazy and write it in Python
|
||||
add_python_function!(
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from testutils import assert_raises
|
||||
import pickle
|
||||
import sys
|
||||
|
||||
# new
|
||||
assert bytearray([1, 2, 3])
|
||||
@@ -754,8 +753,4 @@ b = pickle.loads(pickle.dumps(a, 4))
|
||||
assert type(a) == type(b)
|
||||
assert a.x == b.x
|
||||
assert a.y == b.y
|
||||
assert a == b
|
||||
|
||||
a = bytearray()
|
||||
for i in range(-1, 2, 1):
|
||||
assert_raises(IndexError, lambda: a[-sys.maxsize - i], _msg='bytearray index out of range')
|
||||
assert a == b
|
||||
@@ -10,9 +10,9 @@ edition = "2018"
|
||||
autotests = false
|
||||
|
||||
[dependencies]
|
||||
cranelift = "0.69.0"
|
||||
cranelift-module = "0.69.0"
|
||||
cranelift-jit = "0.69.0"
|
||||
cranelift = "0.68.0"
|
||||
cranelift-module = "0.68.0"
|
||||
cranelift-simplejit = "0.68.0"
|
||||
num-traits = "0.2"
|
||||
libffi = "1.0"
|
||||
rustpython-bytecode = { path = "../bytecode", version = "0.1.2" }
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use cranelift::prelude::*;
|
||||
use num_traits::cast::ToPrimitive;
|
||||
use rustpython_bytecode::{
|
||||
self as bytecode, BinaryOperator, BorrowedConstant, CodeObject, ComparisonOperator,
|
||||
Instruction, Label, UnaryOperator,
|
||||
use rustpython_bytecode::bytecode::{
|
||||
self, BinaryOperator, BorrowedConstant, CodeObject, ComparisonOperator, Instruction, Label,
|
||||
UnaryOperator,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -54,7 +54,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
|
||||
let params = compiler.builder.func.dfg.block_params(entry_block).to_vec();
|
||||
for (i, (ty, val)) in arg_types.iter().zip(params).enumerate() {
|
||||
compiler
|
||||
.store_variable(i as u32, JitValue::new(val, ty.clone()))
|
||||
.store_variable(i, JitValue::new(val, ty.clone()))
|
||||
.unwrap();
|
||||
}
|
||||
compiler
|
||||
@@ -66,8 +66,8 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
|
||||
val: JitValue,
|
||||
) -> Result<(), JitCompileError> {
|
||||
let builder = &mut self.builder;
|
||||
let local = self.variables[idx as usize].get_or_insert_with(|| {
|
||||
let var = Variable::new(idx as usize);
|
||||
let local = self.variables[idx].get_or_insert_with(|| {
|
||||
let var = Variable::new(idx);
|
||||
let local = Local {
|
||||
var,
|
||||
ty: val.ty.clone(),
|
||||
@@ -119,7 +119,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
|
||||
let label_targets = bytecode.label_targets();
|
||||
|
||||
for (offset, instruction) in bytecode.instructions.iter().enumerate() {
|
||||
let label = Label(offset as u32);
|
||||
let label = Label(offset);
|
||||
if label_targets.contains(&label) {
|
||||
let block = self.get_or_create_block(label);
|
||||
|
||||
@@ -219,7 +219,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
|
||||
Ok(())
|
||||
}
|
||||
Instruction::LoadFast(idx) => {
|
||||
let local = self.variables[*idx as usize]
|
||||
let local = self.variables[*idx]
|
||||
.as_ref()
|
||||
.ok_or(JitCompileError::BadBytecode)?;
|
||||
self.stack.push(JitValue {
|
||||
@@ -232,9 +232,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
|
||||
let val = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;
|
||||
self.store_variable(*idx, val)
|
||||
}
|
||||
Instruction::LoadConst { idx } => {
|
||||
self.load_const(constants[*idx as usize].borrow_constant())
|
||||
}
|
||||
Instruction::LoadConst { idx } => self.load_const(constants[*idx].borrow_constant()),
|
||||
Instruction::ReturnValue => {
|
||||
let val = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;
|
||||
if let Some(ref ty) = self.sig.ret {
|
||||
@@ -322,7 +320,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
|
||||
_ => Err(JitCompileError::NotSupported),
|
||||
}
|
||||
}
|
||||
Instruction::BinaryOperation { op } | Instruction::BinaryOperationInplace { op } => {
|
||||
Instruction::BinaryOperation { op, .. } => {
|
||||
// the rhs is popped off first
|
||||
let b = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;
|
||||
let a = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use std::fmt;
|
||||
|
||||
use cranelift::prelude::*;
|
||||
use cranelift_jit::{JITBuilder, JITModule};
|
||||
use cranelift_module::{FuncId, Linkage, Module, ModuleError};
|
||||
use cranelift_simplejit::{SimpleJITBuilder, SimpleJITModule, SimpleJITProduct};
|
||||
|
||||
use rustpython_bytecode as bytecode;
|
||||
use rustpython_bytecode::bytecode;
|
||||
|
||||
mod instructions;
|
||||
|
||||
@@ -32,13 +32,13 @@ pub enum JitArgumentError {
|
||||
struct Jit {
|
||||
builder_context: FunctionBuilderContext,
|
||||
ctx: codegen::Context,
|
||||
module: JITModule,
|
||||
module: SimpleJITModule,
|
||||
}
|
||||
|
||||
impl Jit {
|
||||
fn new() -> Self {
|
||||
let builder = JITBuilder::new(cranelift_module::default_libcall_names());
|
||||
let module = JITModule::new(builder);
|
||||
let builder = SimpleJITBuilder::new(cranelift_module::default_libcall_names());
|
||||
let module = SimpleJITModule::new(builder);
|
||||
Self {
|
||||
builder_context: FunctionBuilderContext::new(),
|
||||
ctx: module.make_context(),
|
||||
@@ -77,7 +77,7 @@ impl Jit {
|
||||
builder.finalize();
|
||||
|
||||
let id = self.module.declare_function(
|
||||
&format!("jit_{}", bytecode.obj_name.as_ref()),
|
||||
&format!("jit_{}", bytecode.obj_name),
|
||||
Linkage::Export,
|
||||
&self.ctx.func.signature,
|
||||
)?;
|
||||
@@ -105,14 +105,14 @@ pub fn compile<C: bytecode::Constant>(
|
||||
Ok(CompiledCode {
|
||||
sig,
|
||||
code,
|
||||
module: jit.module,
|
||||
memory: jit.module.finish(),
|
||||
})
|
||||
}
|
||||
|
||||
pub struct CompiledCode {
|
||||
sig: JitSig,
|
||||
code: *const u8,
|
||||
module: JITModule,
|
||||
memory: SimpleJITProduct,
|
||||
}
|
||||
|
||||
impl CompiledCode {
|
||||
@@ -287,7 +287,7 @@ unsafe impl Sync for CompiledCode {}
|
||||
impl Drop for CompiledCode {
|
||||
fn drop(&mut self) {
|
||||
// SAFETY: The only pointer that this memory will also be dropped now
|
||||
unsafe { self.module.free_memory() }
|
||||
unsafe { self.memory.free_memory() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use rustpython_bytecode::{CodeObject, ConstantData, Instruction};
|
||||
use rustpython_bytecode::bytecode::{CodeObject, ConstantData, Instruction};
|
||||
use rustpython_jit::{CompiledCode, JitType};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -78,15 +78,13 @@ impl StackMachine {
|
||||
names: &[String],
|
||||
) -> bool {
|
||||
match instruction {
|
||||
Instruction::LoadConst { idx } => {
|
||||
self.stack.push(constants[idx as usize].clone().into())
|
||||
Instruction::LoadConst { idx } => self.stack.push(constants[idx].clone().into()),
|
||||
Instruction::LoadNameAny(idx) => {
|
||||
self.stack.push(StackValue::String(names[idx].clone()))
|
||||
}
|
||||
Instruction::LoadNameAny(idx) => self
|
||||
.stack
|
||||
.push(StackValue::String(names[idx as usize].clone())),
|
||||
Instruction::StoreLocal(idx) => {
|
||||
self.locals
|
||||
.insert(names[idx as usize].clone(), self.stack.pop().unwrap());
|
||||
.insert(names[idx].clone(), self.stack.pop().unwrap());
|
||||
}
|
||||
Instruction::StoreAttr { .. } => {
|
||||
// Do nothing except throw away the stack values
|
||||
@@ -106,7 +104,7 @@ impl StackMachine {
|
||||
}
|
||||
self.stack.push(StackValue::Map(map));
|
||||
}
|
||||
Instruction::MakeFunction(_flags) => {
|
||||
Instruction::MakeFunction => {
|
||||
let name = if let Some(StackValue::String(name)) = self.stack.pop() {
|
||||
name
|
||||
} else {
|
||||
@@ -136,7 +134,7 @@ impl StackMachine {
|
||||
let mut values = Vec::new();
|
||||
|
||||
// Pop all values from stack:
|
||||
values.extend(self.stack.drain(self.stack.len() - amount as usize..));
|
||||
values.extend(self.stack.drain(self.stack.len() - amount..));
|
||||
|
||||
// Push top of stack back first:
|
||||
self.stack.push(values.pop().unwrap());
|
||||
|
||||
@@ -8,22 +8,15 @@ repository = "https://github.com/RustPython/RustPython"
|
||||
license = "MIT"
|
||||
edition = "2018"
|
||||
|
||||
[features]
|
||||
std = []
|
||||
default = ["std", "lalrpop-util/std", "num-bigint/std"]
|
||||
|
||||
[build-dependencies]
|
||||
lalrpop = "0.19.4"
|
||||
lalrpop = "0.19"
|
||||
|
||||
[dependencies]
|
||||
rustpython-ast = { path = "../ast" }
|
||||
lalrpop-util = { version = "0.19.4", default-features = false }
|
||||
lalrpop-util = "0.19.1"
|
||||
log = "0.4.1"
|
||||
num-bigint = { version = "0.3", default-features = false }
|
||||
num-traits = { version = "0.2", default-features = false }
|
||||
num-bigint = "0.3"
|
||||
num-traits = "0.2"
|
||||
unic-emoji-char = "0.9"
|
||||
unic-ucd-ident = "0.9"
|
||||
unicode_names2 = "0.4"
|
||||
phf = { version = "0.8", features = ["macros"] }
|
||||
ahash = "0.6"
|
||||
hashbrown = "0.9"
|
||||
|
||||
@@ -5,10 +5,8 @@ use lalrpop_util::ParseError as LalrpopError;
|
||||
use crate::ast::Location;
|
||||
use crate::token::Tok;
|
||||
|
||||
use alloc::{boxed::Box, string::String};
|
||||
use core::fmt;
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
/// Represents an error during lexical scanning.
|
||||
#[derive(Debug, PartialEq)]
|
||||
@@ -24,7 +22,6 @@ pub enum LexicalErrorType {
|
||||
NestingError,
|
||||
IndentationError,
|
||||
TabError,
|
||||
TabsAfterSpaces,
|
||||
DefaultArgumentError,
|
||||
PositionalArgumentError,
|
||||
DuplicateKeywordArgumentError,
|
||||
@@ -48,9 +45,6 @@ impl fmt::Display for LexicalErrorType {
|
||||
LexicalErrorType::TabError => {
|
||||
write!(f, "inconsistent use of tabs and spaces in indentation")
|
||||
}
|
||||
LexicalErrorType::TabsAfterSpaces => {
|
||||
write!(f, "Tabs not allowed as part of indentation after spaces")
|
||||
}
|
||||
LexicalErrorType::DefaultArgumentError => {
|
||||
write!(f, "non-default argument follows default argument")
|
||||
}
|
||||
@@ -72,16 +66,6 @@ impl fmt::Display for LexicalErrorType {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for LexicalErrorType {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
LexicalErrorType::FStringError(e) => Some(e),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: consolidate these with ParseError
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct FStringError {
|
||||
@@ -131,16 +115,6 @@ impl From<FStringError> for LalrpopError<Location, Tok, LexicalError> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for FStringErrorType {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
FStringErrorType::InvalidExpression(e) => Some(e.as_ref()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents an error during parsing
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ParseError {
|
||||
@@ -226,45 +200,32 @@ impl fmt::Display for ParseErrorType {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for ParseErrorType {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
ParseErrorType::Lexical(e) => Some(e),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Error for ParseErrorType {}
|
||||
|
||||
impl ParseErrorType {
|
||||
pub fn is_indentation_error(&self) -> bool {
|
||||
match self {
|
||||
ParseErrorType::Lexical(LexicalErrorType::IndentationError) => true,
|
||||
ParseErrorType::UnrecognizedToken(token, expected) => {
|
||||
*token == Tok::Indent || expected.as_ref().map_or(false, |s| s == "Indent")
|
||||
*token == Tok::Indent || expected.clone() == Some("Indent".to_owned())
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub fn is_tab_error(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
ParseErrorType::Lexical(LexicalErrorType::TabError)
|
||||
| ParseErrorType::Lexical(LexicalErrorType::TabsAfterSpaces)
|
||||
)
|
||||
matches!(self, ParseErrorType::Lexical(LexicalErrorType::TabError))
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::Deref for ParseError {
|
||||
impl std::ops::Deref for ParseError {
|
||||
type Target = ParseErrorType;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.error
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for ParseError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
self.error.source()
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use alloc::{borrow::ToOwned, boxed::Box, format, string::String, vec, vec::Vec};
|
||||
use core::{iter, mem, str};
|
||||
use std::iter;
|
||||
use std::mem;
|
||||
use std::str;
|
||||
|
||||
use crate::ast::{ConversionFlag, Expression, Location, StringGroup};
|
||||
use crate::error::{FStringError, FStringErrorType, ParseError};
|
||||
@@ -80,7 +81,7 @@ impl<'a> FStringParser<'a> {
|
||||
// match a python 3.8 self documenting expression
|
||||
// format '{' PYTHON_EXPRESSION '=' FORMAT_SPECIFIER? '}'
|
||||
'=' if self.chars.peek() != Some(&'=') && delims.is_empty() => {
|
||||
pred_expression_text = expression.to_owned(); // safe expression before = to print it
|
||||
pred_expression_text = expression.to_string(); // safe expression before = to print it
|
||||
}
|
||||
|
||||
':' if delims.is_empty() => {
|
||||
@@ -282,7 +283,6 @@ mod tests {
|
||||
fn mk_ident(name: &str, row: usize, col: usize) -> ast::Expression {
|
||||
ast::Expression {
|
||||
location: ast::Location::new(row, col),
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Identifier {
|
||||
name: name.to_owned(),
|
||||
},
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use alloc::{string::String, vec, vec::Vec};
|
||||
use hashbrown::HashSet;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use crate::ast;
|
||||
use crate::error::{LexicalError, LexicalErrorType};
|
||||
@@ -46,8 +45,7 @@ pub fn parse_args(func_args: Vec<FunctionArgument>) -> Result<ast::ArgumentList,
|
||||
let mut args = vec![];
|
||||
let mut keywords = vec![];
|
||||
|
||||
let mut keyword_names =
|
||||
HashSet::with_capacity_and_hasher(func_args.len(), ahash::RandomState::default());
|
||||
let mut keyword_names = HashSet::with_capacity(func_args.len());
|
||||
for (name, value) in func_args {
|
||||
match name {
|
||||
Some(n) => {
|
||||
|
||||
@@ -5,19 +5,13 @@
|
||||
pub use super::token::Tok;
|
||||
use crate::ast::Location;
|
||||
use crate::error::{LexicalError, LexicalErrorType};
|
||||
use alloc::{
|
||||
borrow::ToOwned,
|
||||
format,
|
||||
string::{String, ToString},
|
||||
vec,
|
||||
vec::Vec,
|
||||
};
|
||||
use core::char;
|
||||
use core::cmp::Ordering;
|
||||
use core::str::FromStr;
|
||||
use num_bigint::BigInt;
|
||||
use num_traits::identities::Zero;
|
||||
use num_traits::Num;
|
||||
use std::char;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use unic_emoji_char::is_emoji_presentation;
|
||||
use unic_ucd_ident::{is_xid_continue, is_xid_start};
|
||||
|
||||
@@ -72,53 +66,57 @@ pub struct Lexer<T: Iterator<Item = char>> {
|
||||
chr1: Option<char>,
|
||||
chr2: Option<char>,
|
||||
location: Location,
|
||||
keywords: HashMap<String, Tok>,
|
||||
}
|
||||
|
||||
pub static KEYWORDS: phf::Map<&'static str, Tok> = phf::phf_map! {
|
||||
// Alphabetical keywords:
|
||||
"..." => Tok::Ellipsis,
|
||||
"False" => Tok::False,
|
||||
"None" => Tok::None,
|
||||
"True" => Tok::True,
|
||||
pub fn get_keywords() -> HashMap<String, Tok> {
|
||||
let mut keywords: HashMap<String, Tok> = HashMap::new();
|
||||
|
||||
"and" => Tok::And,
|
||||
"as" => Tok::As,
|
||||
"assert" => Tok::Assert,
|
||||
"async" => Tok::Async,
|
||||
"await" => Tok::Await,
|
||||
"break" => Tok::Break,
|
||||
"class" => Tok::Class,
|
||||
"continue" => Tok::Continue,
|
||||
"def" => Tok::Def,
|
||||
"del" => Tok::Del,
|
||||
"elif" => Tok::Elif,
|
||||
"else" => Tok::Else,
|
||||
"except" => Tok::Except,
|
||||
"finally" => Tok::Finally,
|
||||
"for" => Tok::For,
|
||||
"from" => Tok::From,
|
||||
"global" => Tok::Global,
|
||||
"if" => Tok::If,
|
||||
"import" => Tok::Import,
|
||||
"in" => Tok::In,
|
||||
"is" => Tok::Is,
|
||||
"lambda" => Tok::Lambda,
|
||||
"nonlocal" => Tok::Nonlocal,
|
||||
"not" => Tok::Not,
|
||||
"or" => Tok::Or,
|
||||
"pass" => Tok::Pass,
|
||||
"raise" => Tok::Raise,
|
||||
"return" => Tok::Return,
|
||||
"try" => Tok::Try,
|
||||
"while" => Tok::While,
|
||||
"with" => Tok::With,
|
||||
"yield" => Tok::Yield,
|
||||
};
|
||||
// Alphabetical keywords:
|
||||
keywords.insert(String::from("..."), Tok::Ellipsis);
|
||||
keywords.insert(String::from("False"), Tok::False);
|
||||
keywords.insert(String::from("None"), Tok::None);
|
||||
keywords.insert(String::from("True"), Tok::True);
|
||||
|
||||
keywords.insert(String::from("and"), Tok::And);
|
||||
keywords.insert(String::from("as"), Tok::As);
|
||||
keywords.insert(String::from("assert"), Tok::Assert);
|
||||
keywords.insert(String::from("async"), Tok::Async);
|
||||
keywords.insert(String::from("await"), Tok::Await);
|
||||
keywords.insert(String::from("break"), Tok::Break);
|
||||
keywords.insert(String::from("class"), Tok::Class);
|
||||
keywords.insert(String::from("continue"), Tok::Continue);
|
||||
keywords.insert(String::from("def"), Tok::Def);
|
||||
keywords.insert(String::from("del"), Tok::Del);
|
||||
keywords.insert(String::from("elif"), Tok::Elif);
|
||||
keywords.insert(String::from("else"), Tok::Else);
|
||||
keywords.insert(String::from("except"), Tok::Except);
|
||||
keywords.insert(String::from("finally"), Tok::Finally);
|
||||
keywords.insert(String::from("for"), Tok::For);
|
||||
keywords.insert(String::from("from"), Tok::From);
|
||||
keywords.insert(String::from("global"), Tok::Global);
|
||||
keywords.insert(String::from("if"), Tok::If);
|
||||
keywords.insert(String::from("import"), Tok::Import);
|
||||
keywords.insert(String::from("in"), Tok::In);
|
||||
keywords.insert(String::from("is"), Tok::Is);
|
||||
keywords.insert(String::from("lambda"), Tok::Lambda);
|
||||
keywords.insert(String::from("nonlocal"), Tok::Nonlocal);
|
||||
keywords.insert(String::from("not"), Tok::Not);
|
||||
keywords.insert(String::from("or"), Tok::Or);
|
||||
keywords.insert(String::from("pass"), Tok::Pass);
|
||||
keywords.insert(String::from("raise"), Tok::Raise);
|
||||
keywords.insert(String::from("return"), Tok::Return);
|
||||
keywords.insert(String::from("try"), Tok::Try);
|
||||
keywords.insert(String::from("while"), Tok::While);
|
||||
keywords.insert(String::from("with"), Tok::With);
|
||||
keywords.insert(String::from("yield"), Tok::Yield);
|
||||
keywords
|
||||
}
|
||||
|
||||
pub type Spanned = (Location, Tok, Location);
|
||||
pub type LexResult = Result<Spanned, LexicalError>;
|
||||
|
||||
pub fn make_tokenizer(source: &str) -> impl Iterator<Item = LexResult> + '_ {
|
||||
pub fn make_tokenizer<'a>(source: &'a str) -> impl Iterator<Item = LexResult> + 'a {
|
||||
let nlh = NewlineHandler::new(source.chars());
|
||||
Lexer::new(nlh)
|
||||
}
|
||||
@@ -195,6 +193,7 @@ where
|
||||
location: Location::new(0, 0),
|
||||
chr1: None,
|
||||
chr2: None,
|
||||
keywords: get_keywords(),
|
||||
};
|
||||
lxr.next_char();
|
||||
lxr.next_char();
|
||||
@@ -246,8 +245,8 @@ where
|
||||
}
|
||||
let end_pos = self.get_pos();
|
||||
|
||||
if let Some(tok) = KEYWORDS.get(name.as_str()) {
|
||||
Ok((start_pos, tok.clone(), end_pos))
|
||||
if self.keywords.contains_key(&name) {
|
||||
Ok((start_pos, self.keywords[&name].clone(), end_pos))
|
||||
} else {
|
||||
Ok((start_pos, Tok::Name { name }, end_pos))
|
||||
}
|
||||
@@ -443,8 +442,8 @@ where
|
||||
}
|
||||
}
|
||||
match p {
|
||||
0xD800..=0xDFFF => Ok(char::REPLACEMENT_CHARACTER),
|
||||
_ => char::from_u32(p).ok_or(unicode_error),
|
||||
0xD800..=0xDFFF => Ok(std::char::REPLACEMENT_CHARACTER),
|
||||
_ => std::char::from_u32(p).ok_or(unicode_error),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -679,7 +678,9 @@ where
|
||||
// This is technically stricter than python3 but spaces before
|
||||
// tabs is even more insane than mixing spaces and tabs.
|
||||
return Err(LexicalError {
|
||||
error: LexicalErrorType::TabsAfterSpaces,
|
||||
error: LexicalErrorType::OtherError(
|
||||
"Tabs not allowed as part of indentation after spaces".to_owned(),
|
||||
),
|
||||
location: self.get_pos(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -17,13 +17,6 @@
|
||||
|
||||
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/master/logo.png")]
|
||||
#![doc(html_root_url = "https://docs.rs/rustpython-parser/")]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
// hack to get around lalrpop hardcoding ::std::* paths
|
||||
#[cfg(not(feature = "std"))]
|
||||
extern crate self as std;
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
use core::fmt;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Mode {
|
||||
Program,
|
||||
Statement,
|
||||
}
|
||||
|
||||
impl core::str::FromStr for Mode {
|
||||
impl std::str::FromStr for Mode {
|
||||
type Err = ModeParseError;
|
||||
fn from_str(s: &str) -> Result<Self, ModeParseError> {
|
||||
match s {
|
||||
@@ -22,8 +20,8 @@ pub struct ModeParseError {
|
||||
_priv: (),
|
||||
}
|
||||
|
||||
impl fmt::Display for ModeParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
impl std::fmt::Display for ModeParseError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, r#"mode should be "exec", "eval", or "single""#)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
//! parse a whole program, a single statement, or a single
|
||||
//! expression.
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use core::iter;
|
||||
use std::iter;
|
||||
|
||||
use crate::ast;
|
||||
use crate::error::ParseError;
|
||||
@@ -61,11 +60,9 @@ pub fn parse_statement(source: &str) -> Result<Vec<ast::Statement>, ParseError>
|
||||
///
|
||||
/// assert_eq!(ast::Expression {
|
||||
/// location: ast::Location::new(1, 3),
|
||||
/// custom: (),
|
||||
/// node: ast::ExpressionType::Binop {
|
||||
/// a: Box::new(ast::Expression {
|
||||
/// location: ast::Location::new(1, 1),
|
||||
/// custom: (),
|
||||
/// node: ast::ExpressionType::Number {
|
||||
/// value: ast::Number::Integer { value: BigInt::from(1) }
|
||||
/// }
|
||||
@@ -73,7 +70,6 @@ pub fn parse_statement(source: &str) -> Result<Vec<ast::Statement>, ParseError>
|
||||
/// op: ast::Operator::Add,
|
||||
/// b: Box::new(ast::Expression {
|
||||
/// location: ast::Location::new(1, 5),
|
||||
/// custom: (),
|
||||
/// node: ast::ExpressionType::Number {
|
||||
/// value: ast::Number::Integer { value: BigInt::from(2) }
|
||||
/// }
|
||||
@@ -107,13 +103,11 @@ mod tests {
|
||||
use super::parse_expression;
|
||||
use super::parse_program;
|
||||
use super::parse_statement;
|
||||
use alloc::borrow::ToOwned;
|
||||
use num_bigint::BigInt;
|
||||
|
||||
fn mk_ident(name: &str, row: usize, col: usize) -> ast::Expression {
|
||||
ast::Expression {
|
||||
location: ast::Location::new(row, col),
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Identifier {
|
||||
name: name.to_owned(),
|
||||
},
|
||||
@@ -123,7 +117,6 @@ mod tests {
|
||||
fn make_int(value: i32, row: usize, col: usize) -> ast::Expression {
|
||||
ast::Expression {
|
||||
location: ast::Location::new(row, col),
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Number {
|
||||
value: ast::Number::Integer {
|
||||
value: BigInt::from(value),
|
||||
@@ -135,10 +128,9 @@ mod tests {
|
||||
fn make_string(value: &str, row: usize, col: usize) -> ast::Expression {
|
||||
ast::Expression {
|
||||
location: ast::Location::new(row, col),
|
||||
custom: (),
|
||||
node: ast::ExpressionType::String {
|
||||
value: ast::StringGroup::Constant {
|
||||
value: value.to_owned(),
|
||||
value: String::from(value),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -147,7 +139,6 @@ mod tests {
|
||||
fn as_statement(expr: ast::Expression) -> ast::Statement {
|
||||
ast::Statement {
|
||||
location: expr.location,
|
||||
custom: (),
|
||||
node: ast::StatementType::Expression { expression: expr },
|
||||
}
|
||||
}
|
||||
@@ -160,17 +151,15 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_print_hello() {
|
||||
let source = "print('Hello world')";
|
||||
let parse_ast = parse_program(source).unwrap();
|
||||
let source = String::from("print('Hello world')");
|
||||
let parse_ast = parse_program(&source).unwrap();
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
ast::Program {
|
||||
statements: vec![ast::Statement {
|
||||
location: ast::Location::new(1, 1),
|
||||
custom: (),
|
||||
node: ast::StatementType::Expression {
|
||||
expression: ast::Expression {
|
||||
custom: (),
|
||||
location: ast::Location::new(1, 6),
|
||||
node: ast::ExpressionType::Call {
|
||||
function: Box::new(mk_ident("print", 1, 1)),
|
||||
@@ -186,18 +175,16 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_print_2() {
|
||||
let source = "print('Hello world', 2)";
|
||||
let parse_ast = parse_program(source).unwrap();
|
||||
let source = String::from("print('Hello world', 2)");
|
||||
let parse_ast = parse_program(&source).unwrap();
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
ast::Program {
|
||||
statements: vec![ast::Statement {
|
||||
location: ast::Location::new(1, 1),
|
||||
custom: (),
|
||||
node: ast::StatementType::Expression {
|
||||
expression: ast::Expression {
|
||||
location: ast::Location::new(1, 6),
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Call {
|
||||
function: Box::new(mk_ident("print", 1, 1)),
|
||||
args: vec![make_string("Hello world", 1, 8), make_int(2, 1, 22),],
|
||||
@@ -212,18 +199,16 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_kwargs() {
|
||||
let source = "my_func('positional', keyword=2)";
|
||||
let parse_ast = parse_program(source).unwrap();
|
||||
let source = String::from("my_func('positional', keyword=2)");
|
||||
let parse_ast = parse_program(&source).unwrap();
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
ast::Program {
|
||||
statements: vec![ast::Statement {
|
||||
location: ast::Location::new(1, 1),
|
||||
custom: (),
|
||||
node: ast::StatementType::Expression {
|
||||
expression: ast::Expression {
|
||||
location: ast::Location::new(1, 8),
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Call {
|
||||
function: Box::new(mk_ident("my_func", 1, 1)),
|
||||
args: vec![make_string("positional", 1, 10)],
|
||||
@@ -241,19 +226,17 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_if_elif_else() {
|
||||
let source = "if 1: 10\nelif 2: 20\nelse: 30";
|
||||
let parse_ast = parse_statement(source).unwrap();
|
||||
let source = String::from("if 1: 10\nelif 2: 20\nelse: 30");
|
||||
let parse_ast = parse_statement(&source).unwrap();
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
vec![ast::Statement {
|
||||
location: ast::Location::new(1, 1),
|
||||
custom: (),
|
||||
node: ast::StatementType::If {
|
||||
test: make_int(1, 1, 4),
|
||||
body: vec![as_statement(make_int(10, 1, 7))],
|
||||
orelse: Some(vec![ast::Statement {
|
||||
location: ast::Location::new(2, 1),
|
||||
custom: (),
|
||||
node: ast::StatementType::If {
|
||||
test: make_int(2, 2, 6),
|
||||
body: vec![as_statement(make_int(20, 2, 9))],
|
||||
@@ -267,25 +250,24 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_lambda() {
|
||||
let source = "lambda x, y: x * y"; // lambda(x, y): x * y");
|
||||
let parse_ast = parse_statement(source);
|
||||
let source = String::from("lambda x, y: x * y"); // lambda(x, y): x * y");
|
||||
let parse_ast = parse_statement(&source);
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
Ok(vec![as_statement(ast::Expression {
|
||||
location: ast::Location::new(1, 1),
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Lambda {
|
||||
args: Box::new(ast::Parameters {
|
||||
posonlyargs_count: 0,
|
||||
args: vec![
|
||||
ast::Parameter {
|
||||
location: ast::Location::new(1, 8),
|
||||
arg: "x".to_owned(),
|
||||
arg: String::from("x"),
|
||||
annotation: None,
|
||||
},
|
||||
ast::Parameter {
|
||||
location: ast::Location::new(1, 11),
|
||||
arg: "y".to_owned(),
|
||||
arg: String::from("y"),
|
||||
annotation: None,
|
||||
}
|
||||
],
|
||||
@@ -297,7 +279,6 @@ mod tests {
|
||||
}),
|
||||
body: Box::new(ast::Expression {
|
||||
location: ast::Location::new(1, 16),
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Binop {
|
||||
a: Box::new(mk_ident("x", 1, 14)),
|
||||
op: ast::Operator::Mult,
|
||||
@@ -311,16 +292,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_tuples() {
|
||||
let source = "a, b = 4, 5";
|
||||
let source = String::from("a, b = 4, 5");
|
||||
|
||||
assert_eq!(
|
||||
parse_statement(source),
|
||||
parse_statement(&source),
|
||||
Ok(vec![ast::Statement {
|
||||
location: ast::Location::new(1, 1),
|
||||
custom: (),
|
||||
node: ast::StatementType::Assign {
|
||||
targets: vec![ast::Expression {
|
||||
custom: (),
|
||||
location: ast::Location::new(1, 1),
|
||||
node: ast::ExpressionType::Tuple {
|
||||
elements: vec![mk_ident("a", 1, 1), mk_ident("b", 1, 4),]
|
||||
@@ -328,7 +307,6 @@ mod tests {
|
||||
}],
|
||||
value: ast::Expression {
|
||||
location: ast::Location::new(1, 8),
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Tuple {
|
||||
elements: vec![make_int(4, 1, 8), make_int(5, 1, 11),]
|
||||
}
|
||||
@@ -340,33 +318,28 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_parse_class() {
|
||||
let source = "\
|
||||
class Foo(A, B):
|
||||
def __init__(self):
|
||||
pass
|
||||
def method_with_default(self, arg='default'):
|
||||
pass";
|
||||
let source = String::from(
|
||||
"class Foo(A, B):\n def __init__(self):\n pass\n def method_with_default(self, arg='default'):\n pass",
|
||||
);
|
||||
assert_eq!(
|
||||
parse_statement(source),
|
||||
parse_statement(&source),
|
||||
Ok(vec![ast::Statement {
|
||||
location: ast::Location::new(1, 1),
|
||||
custom: (),
|
||||
node: ast::StatementType::ClassDef {
|
||||
name: "Foo".to_owned(),
|
||||
name: String::from("Foo"),
|
||||
bases: vec![mk_ident("A", 1, 11), mk_ident("B", 1, 14)],
|
||||
keywords: vec![],
|
||||
body: vec![
|
||||
ast::Statement {
|
||||
location: ast::Location::new(2, 2),
|
||||
custom: (),
|
||||
node: ast::StatementType::FunctionDef {
|
||||
is_async: false,
|
||||
name: "__init__".to_owned(),
|
||||
name: String::from("__init__"),
|
||||
args: Box::new(ast::Parameters {
|
||||
posonlyargs_count: 0,
|
||||
args: vec![ast::Parameter {
|
||||
location: ast::Location::new(2, 15),
|
||||
arg: "self".to_owned(),
|
||||
arg: String::from("self"),
|
||||
annotation: None,
|
||||
}],
|
||||
kwonlyargs: vec![],
|
||||
@@ -377,7 +350,6 @@ class Foo(A, B):
|
||||
}),
|
||||
body: vec![ast::Statement {
|
||||
location: ast::Location::new(3, 3),
|
||||
custom: (),
|
||||
node: ast::StatementType::Pass,
|
||||
}],
|
||||
decorator_list: vec![],
|
||||
@@ -386,21 +358,20 @@ class Foo(A, B):
|
||||
},
|
||||
ast::Statement {
|
||||
location: ast::Location::new(4, 2),
|
||||
custom: (),
|
||||
node: ast::StatementType::FunctionDef {
|
||||
is_async: false,
|
||||
name: "method_with_default".to_owned(),
|
||||
name: String::from("method_with_default"),
|
||||
args: Box::new(ast::Parameters {
|
||||
posonlyargs_count: 0,
|
||||
args: vec![
|
||||
ast::Parameter {
|
||||
location: ast::Location::new(4, 26),
|
||||
arg: "self".to_owned(),
|
||||
arg: String::from("self"),
|
||||
annotation: None,
|
||||
},
|
||||
ast::Parameter {
|
||||
location: ast::Location::new(4, 32),
|
||||
arg: "arg".to_owned(),
|
||||
arg: String::from("arg"),
|
||||
annotation: None,
|
||||
}
|
||||
],
|
||||
@@ -412,7 +383,6 @@ class Foo(A, B):
|
||||
}),
|
||||
body: vec![ast::Statement {
|
||||
location: ast::Location::new(5, 3),
|
||||
custom: (),
|
||||
node: ast::StatementType::Pass,
|
||||
}],
|
||||
decorator_list: vec![],
|
||||
@@ -428,13 +398,12 @@ class Foo(A, B):
|
||||
|
||||
#[test]
|
||||
fn test_parse_dict_comprehension() {
|
||||
let source = "{x1: x2 for y in z}";
|
||||
let parse_ast = parse_expression(source).unwrap();
|
||||
let source = String::from("{x1: x2 for y in z}");
|
||||
let parse_ast = parse_expression(&source).unwrap();
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
ast::Expression {
|
||||
location: ast::Location::new(1, 1),
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Comprehension {
|
||||
kind: Box::new(ast::ComprehensionKind::Dict {
|
||||
key: mk_ident("x1", 1, 2),
|
||||
@@ -454,12 +423,11 @@ class Foo(A, B):
|
||||
|
||||
#[test]
|
||||
fn test_parse_list_comprehension() {
|
||||
let source = "[x for y in z]";
|
||||
let parse_ast = parse_expression(source).unwrap();
|
||||
let source = String::from("[x for y in z]");
|
||||
let parse_ast = parse_expression(&source).unwrap();
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
ast::Expression {
|
||||
custom: (),
|
||||
location: ast::Location::new(1, 1),
|
||||
node: ast::ExpressionType::Comprehension {
|
||||
kind: Box::new(ast::ComprehensionKind::List {
|
||||
@@ -479,12 +447,11 @@ class Foo(A, B):
|
||||
|
||||
#[test]
|
||||
fn test_parse_double_list_comprehension() {
|
||||
let source = "[x for y, y2 in z for a in b if a < 5 if a > 10]";
|
||||
let parse_ast = parse_expression(source).unwrap();
|
||||
let source = String::from("[x for y, y2 in z for a in b if a < 5 if a > 10]");
|
||||
let parse_ast = parse_expression(&source).unwrap();
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
ast::Expression {
|
||||
custom: (),
|
||||
location: ast::Location::new(1, 1),
|
||||
node: ast::ExpressionType::Comprehension {
|
||||
kind: Box::new(ast::ComprehensionKind::List {
|
||||
@@ -494,7 +461,6 @@ class Foo(A, B):
|
||||
ast::Comprehension {
|
||||
location: ast::Location::new(1, 4),
|
||||
target: ast::Expression {
|
||||
custom: (),
|
||||
location: ast::Location::new(1, 8),
|
||||
node: ast::ExpressionType::Tuple {
|
||||
elements: vec![mk_ident("y", 1, 8), mk_ident("y2", 1, 11),],
|
||||
@@ -510,7 +476,6 @@ class Foo(A, B):
|
||||
iter: mk_ident("b", 1, 28),
|
||||
ifs: vec![
|
||||
ast::Expression {
|
||||
custom: (),
|
||||
location: ast::Location::new(1, 35),
|
||||
node: ast::ExpressionType::Compare {
|
||||
vals: vec![mk_ident("a", 1, 33), make_int(5, 1, 37),],
|
||||
@@ -518,7 +483,6 @@ class Foo(A, B):
|
||||
}
|
||||
},
|
||||
ast::Expression {
|
||||
custom: (),
|
||||
location: ast::Location::new(1, 44),
|
||||
node: ast::ExpressionType::Compare {
|
||||
vals: vec![mk_ident("a", 1, 42), make_int(10, 1, 46),],
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
// See also: file:///usr/share/doc/python/html/reference/compound_stmts.html#function-definitions
|
||||
// See also: https://greentreesnakes.readthedocs.io/en/latest/nodes.html#keyword
|
||||
|
||||
use std::iter::FromIterator;
|
||||
|
||||
use crate::ast;
|
||||
use crate::fstring::parse_located_fstring;
|
||||
use crate::function::{parse_args, parse_params};
|
||||
use crate::error::LexicalError;
|
||||
use crate::lexer;
|
||||
use alloc::{boxed::Box, string::{String, ToString}, vec, vec::Vec};
|
||||
|
||||
use num_bigint::BigInt;
|
||||
|
||||
@@ -25,7 +26,7 @@ pub Top: ast::Top = {
|
||||
|
||||
Program: ast::Program = {
|
||||
<lines:FileLine*> => ast::Program {
|
||||
statements: lines.into_iter().flatten().collect(),
|
||||
statements: Vec::from_iter(lines.into_iter().flatten())
|
||||
},
|
||||
};
|
||||
|
||||
@@ -68,7 +69,6 @@ PassStatement: ast::Statement = {
|
||||
<location:@L> "pass" => {
|
||||
ast::Statement {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::StatementType::Pass,
|
||||
}
|
||||
},
|
||||
@@ -78,7 +78,6 @@ DelStatement: ast::Statement = {
|
||||
<location:@L> "del" <targets:ExpressionList2> => {
|
||||
ast::Statement {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::StatementType::Delete { targets },
|
||||
}
|
||||
},
|
||||
@@ -89,7 +88,6 @@ ExpressionStatement: ast::Statement = {
|
||||
// Just an expression, no assignment:
|
||||
if suffix.is_empty() {
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::Expression { expression }
|
||||
}
|
||||
@@ -104,7 +102,6 @@ ExpressionStatement: ast::Statement = {
|
||||
let value = values.into_iter().next().unwrap();
|
||||
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::Assign { targets, value },
|
||||
}
|
||||
@@ -112,7 +109,6 @@ ExpressionStatement: ast::Statement = {
|
||||
},
|
||||
<location:@L> <target:TestOrStarExprList> <op:AugAssign> <rhs:TestListOrYieldExpr> => {
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::AugAssign {
|
||||
target: Box::new(target),
|
||||
@@ -123,7 +119,6 @@ ExpressionStatement: ast::Statement = {
|
||||
},
|
||||
<location:@L> <target:Test> ":" <annotation:Test> <rhs:AssignSuffix?> => {
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::AnnAssign {
|
||||
target: Box::new(target),
|
||||
@@ -150,7 +145,6 @@ TestOrStarExprList: ast::Expression = {
|
||||
} else {
|
||||
ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Tuple { elements }
|
||||
}
|
||||
}
|
||||
@@ -164,7 +158,6 @@ TestOrStarNamedExprList: ast::Expression = {
|
||||
} else {
|
||||
ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Tuple { elements }
|
||||
}
|
||||
}
|
||||
@@ -200,28 +193,24 @@ AugAssign: ast::Operator = {
|
||||
FlowStatement: ast::Statement = {
|
||||
<location:@L> "break" => {
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::Break,
|
||||
}
|
||||
},
|
||||
<location:@L> "continue" => {
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::Continue,
|
||||
}
|
||||
},
|
||||
<location:@L> "return" <value:TestList?> => {
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::Return { value },
|
||||
}
|
||||
},
|
||||
<location:@L> <expression:YieldExpr> => {
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::Expression { expression },
|
||||
}
|
||||
@@ -232,14 +221,12 @@ FlowStatement: ast::Statement = {
|
||||
RaiseStatement: ast::Statement = {
|
||||
<location:@L> "raise" => {
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::Raise { exception: None, cause: None },
|
||||
}
|
||||
},
|
||||
<location:@L> "raise" <t:Test> <c:("from" Test)?> => {
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::Raise { exception: Some(t), cause: c.map(|x| x.1) },
|
||||
}
|
||||
@@ -249,7 +236,6 @@ RaiseStatement: ast::Statement = {
|
||||
ImportStatement: ast::Statement = {
|
||||
<location:@L> "import" <names: OneOrMore<ImportAsAlias<DottedName>>> => {
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::Import { names },
|
||||
}
|
||||
@@ -257,7 +243,6 @@ ImportStatement: ast::Statement = {
|
||||
<location:@L> "from" <source:ImportFromLocation> "import" <names: ImportAsNames> => {
|
||||
let (level, module) = source;
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::ImportFrom {
|
||||
level,
|
||||
@@ -313,7 +298,6 @@ DottedName: String = {
|
||||
GlobalStatement: ast::Statement = {
|
||||
<location:@L> "global" <names:OneOrMore<Identifier>> => {
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::Global { names }
|
||||
}
|
||||
@@ -323,7 +307,6 @@ GlobalStatement: ast::Statement = {
|
||||
NonlocalStatement: ast::Statement = {
|
||||
<location:@L> "nonlocal" <names:OneOrMore<Identifier>> => {
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::Nonlocal { names }
|
||||
}
|
||||
@@ -333,7 +316,6 @@ NonlocalStatement: ast::Statement = {
|
||||
AssertStatement: ast::Statement = {
|
||||
<location:@L> "assert" <test:Test> <msg: ("," Test)?> => {
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::Assert {
|
||||
test, msg: msg.map(|e| e.1)
|
||||
@@ -360,7 +342,6 @@ IfStatement: ast::Statement = {
|
||||
// handle elif:
|
||||
for i in s2.into_iter().rev() {
|
||||
let x = ast::Statement {
|
||||
custom: (),
|
||||
location: i.0,
|
||||
node: ast::StatementType::If { test: i.2, body: i.4, orelse: last },
|
||||
};
|
||||
@@ -368,7 +349,6 @@ IfStatement: ast::Statement = {
|
||||
}
|
||||
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::If { test, body, orelse: last }
|
||||
}
|
||||
@@ -379,7 +359,6 @@ WhileStatement: ast::Statement = {
|
||||
<location:@L> "while" <test:NamedExpressionTest> ":" <body:Suite> <s2:("else" ":" Suite)?> => {
|
||||
let orelse = s2.map(|s| s.2);
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::While {
|
||||
test,
|
||||
@@ -395,7 +374,6 @@ ForStatement: ast::Statement = {
|
||||
let is_async = is_async.is_some();
|
||||
let orelse = s2.map(|s| s.2);
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::For {
|
||||
is_async,
|
||||
@@ -413,7 +391,6 @@ TryStatement: ast::Statement = {
|
||||
let orelse = else_suite.map(|s| s.2);
|
||||
let finalbody = finally.map(|s| s.2);
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::Try {
|
||||
body,
|
||||
@@ -428,7 +405,6 @@ TryStatement: ast::Statement = {
|
||||
let orelse = None;
|
||||
let finalbody = Some(finally.2);
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::Try {
|
||||
body,
|
||||
@@ -463,7 +439,6 @@ WithStatement: ast::Statement = {
|
||||
<location:@L> <is_async:"async"?> "with" <items:OneOrMore<WithItem>> ":" <body:Suite> => {
|
||||
let is_async = is_async.is_some();
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::With { is_async, items, body },
|
||||
}
|
||||
@@ -481,7 +456,6 @@ FuncDef: ast::Statement = {
|
||||
<decorator_list:Decorator*> <location:@L> <is_async:"async"?> "def" <name:Identifier> <args:Parameters> <r:("->" Test)?> ":" <body:Suite> => {
|
||||
let is_async = is_async.is_some();
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::FunctionDef {
|
||||
is_async,
|
||||
@@ -623,7 +597,6 @@ ClassDef: ast::Statement = {
|
||||
None => (vec![], vec![]),
|
||||
};
|
||||
ast::Statement {
|
||||
custom: (),
|
||||
location,
|
||||
node: ast::StatementType::ClassDef {
|
||||
name,
|
||||
@@ -639,13 +612,11 @@ ClassDef: ast::Statement = {
|
||||
Path: ast::Expression = {
|
||||
<location:@L> <n:Identifier> => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Identifier { name: n }
|
||||
},
|
||||
<p:Path> <location:@L> "." <n:name> => {
|
||||
ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Attribute {
|
||||
value: Box::new(p),
|
||||
name: n,
|
||||
@@ -664,12 +635,10 @@ Decorator: ast::Expression = {
|
||||
YieldExpr: ast::Expression = {
|
||||
<location:@L> "yield" <value:TestList?> => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Yield { value: value.map(Box::new) }
|
||||
},
|
||||
<location:@L> "yield" "from" <e:Test> => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::YieldFrom { value: Box::new(e) }
|
||||
},
|
||||
};
|
||||
@@ -679,7 +648,6 @@ Test: ast::Expression = {
|
||||
if let Some(c) = condition {
|
||||
ast::Expression {
|
||||
location: c.0,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::IfExpression {
|
||||
test: Box::new(c.2),
|
||||
body: Box::new(expr),
|
||||
@@ -698,12 +666,10 @@ NamedExpressionTest: ast::Expression = {
|
||||
if let Some(l) = left {
|
||||
ast::Expression {
|
||||
location: location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::NamedExpression {
|
||||
left: Box::new(
|
||||
ast::Expression {
|
||||
location: location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Identifier { name: l.0, },
|
||||
}),
|
||||
right: Box::new(right),
|
||||
@@ -719,7 +685,6 @@ LambdaDef: ast::Expression = {
|
||||
<location:@L> "lambda" <p:ParameterList<UntypedParameter>?> ":" <body:Test> =>
|
||||
ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Lambda {
|
||||
args: Box::new(p.unwrap_or_default()),
|
||||
body: Box::new(body)
|
||||
@@ -736,7 +701,6 @@ OrTest: ast::Expression = {
|
||||
values.extend(e2.into_iter().map(|e| e.1));
|
||||
ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::BoolOp { op: ast::BooleanOperator::Or, values }
|
||||
}
|
||||
}
|
||||
@@ -752,7 +716,6 @@ AndTest: ast::Expression = {
|
||||
values.extend(e2.into_iter().map(|e| e.1));
|
||||
ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::BoolOp { op: ast::BooleanOperator::And, values }
|
||||
}
|
||||
}
|
||||
@@ -762,7 +725,6 @@ AndTest: ast::Expression = {
|
||||
NotTest: ast::Expression = {
|
||||
<location:@L> "not" <e:NotTest> => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Unop { a: Box::new(e), op: ast::UnaryOperator::Not }
|
||||
},
|
||||
Comparison,
|
||||
@@ -778,7 +740,6 @@ Comparison: ast::Expression = {
|
||||
}
|
||||
ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Compare { vals, ops }
|
||||
}
|
||||
},
|
||||
@@ -801,7 +762,6 @@ CompOp: ast::Comparison = {
|
||||
Expression: ast::Expression = {
|
||||
<e1:Expression> <location:@L> "|" <e2:XorExpression> => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Binop { a: Box::new(e1), op: ast::Operator::BitOr, b: Box::new(e2) }
|
||||
},
|
||||
XorExpression,
|
||||
@@ -810,7 +770,6 @@ Expression: ast::Expression = {
|
||||
XorExpression: ast::Expression = {
|
||||
<e1:XorExpression> <location:@L> "^" <e2:AndExpression> => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Binop { a: Box::new(e1), op: ast::Operator::BitXor, b: Box::new(e2) }
|
||||
},
|
||||
AndExpression,
|
||||
@@ -819,7 +778,6 @@ XorExpression: ast::Expression = {
|
||||
AndExpression: ast::Expression = {
|
||||
<e1:AndExpression> <location:@L> "&" <e2:ShiftExpression> => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Binop { a: Box::new(e1), op: ast::Operator::BitAnd, b: Box::new(e2) }
|
||||
},
|
||||
ShiftExpression,
|
||||
@@ -828,7 +786,6 @@ AndExpression: ast::Expression = {
|
||||
ShiftExpression: ast::Expression = {
|
||||
<e1:ShiftExpression> <location:@L> <op:ShiftOp> <e2:ArithmaticExpression> => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Binop { a: Box::new(e1), op, b: Box::new(e2) }
|
||||
},
|
||||
ArithmaticExpression,
|
||||
@@ -842,7 +799,6 @@ ShiftOp: ast::Operator = {
|
||||
ArithmaticExpression: ast::Expression = {
|
||||
<a:ArithmaticExpression> <location:@L> <op:AddOp> <b:Term> => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Binop { a: Box::new(a), op, b: Box::new(b) }
|
||||
},
|
||||
Term,
|
||||
@@ -856,7 +812,6 @@ AddOp: ast::Operator = {
|
||||
Term: ast::Expression = {
|
||||
<a:Term> <location:@L> <op:MulOp> <b:Factor> => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Binop { a: Box::new(a), op, b: Box::new(b) }
|
||||
},
|
||||
Factor,
|
||||
@@ -873,7 +828,6 @@ MulOp: ast::Operator = {
|
||||
Factor: ast::Expression = {
|
||||
<location:@L> <op:UnOp> <e:Factor> => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Unop { a: Box::new(e), op }
|
||||
},
|
||||
Power,
|
||||
@@ -891,7 +845,6 @@ Power: ast::Expression = {
|
||||
None => e,
|
||||
Some((location, _, b)) => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Binop { a: Box::new(e), op: ast::Operator::Pow, b: Box::new(b) }
|
||||
},
|
||||
}
|
||||
@@ -903,7 +856,6 @@ AtomExpr: ast::Expression = {
|
||||
if is_await.is_some() {
|
||||
ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Await { value: Box::new(atom) }
|
||||
}
|
||||
} else {
|
||||
@@ -917,18 +869,15 @@ AtomExpr2: ast::Expression = {
|
||||
<f:AtomExpr2> <location:@L> "(" <a:ArgumentList> ")" => {
|
||||
ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Call { function: Box::new(f), args: a.args, keywords: a.keywords }
|
||||
}
|
||||
},
|
||||
<e:AtomExpr2> <location:@L> "[" <s:SubscriptList> "]" => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Subscript { a: Box::new(e), b: Box::new(s) }
|
||||
},
|
||||
<e:AtomExpr2> <location:@L> "." <name:Identifier> => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Attribute { value: Box::new(e), name }
|
||||
},
|
||||
};
|
||||
@@ -945,7 +894,6 @@ SubscriptList: ast::Expression = {
|
||||
|
||||
ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Tuple { elements: dims },
|
||||
}
|
||||
}
|
||||
@@ -955,54 +903,47 @@ SubscriptList: ast::Expression = {
|
||||
Subscript: ast::Expression = {
|
||||
Test,
|
||||
<e1:Test?> <location:@L> ":" <e2:Test?> <e3:SliceOp?> => {
|
||||
let s1 = e1.unwrap_or(ast::Expression { location, custom: (), node: ast::ExpressionType::None });
|
||||
let s2 = e2.unwrap_or(ast::Expression { location, custom: (), node: ast::ExpressionType::None });
|
||||
let s3 = e3.unwrap_or(ast::Expression { location, custom: (), node: ast::ExpressionType::None });
|
||||
let s1 = e1.unwrap_or(ast::Expression { location, node: ast::ExpressionType::None });
|
||||
let s2 = e2.unwrap_or(ast::Expression { location, node: ast::ExpressionType::None });
|
||||
let s3 = e3.unwrap_or(ast::Expression { location, node: ast::ExpressionType::None });
|
||||
ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Slice { elements: vec![s1, s2, s3] }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SliceOp: ast::Expression = {
|
||||
<location:@L> ":" <e:Test?> => e.unwrap_or(ast::Expression {location, custom: (), node: ast::ExpressionType::None})
|
||||
<location:@L> ":" <e:Test?> => e.unwrap_or(ast::Expression {location, node: ast::ExpressionType::None})
|
||||
}
|
||||
|
||||
Atom: ast::Expression = {
|
||||
<location:@L> <value:StringGroup> => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::String { value }
|
||||
},
|
||||
<location:@L> <value:Bytes> => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Bytes { value }
|
||||
},
|
||||
<location:@L> <value:Number> => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Number { value }
|
||||
},
|
||||
<location:@L> <name:Identifier> => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Identifier { name }
|
||||
},
|
||||
<location:@L> "[" <e:ListLiteralValues?> "]" => {
|
||||
let elements = e.unwrap_or_default();
|
||||
ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::List { elements }
|
||||
}
|
||||
},
|
||||
<location:@L> "[" <element:TestOrStarNamedExpr> <generators:CompFor> "]" => {
|
||||
ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Comprehension {
|
||||
kind: Box::new(ast::ComprehensionKind::List { element }),
|
||||
generators,
|
||||
@@ -1012,7 +953,6 @@ Atom: ast::Expression = {
|
||||
<location:@L> "(" <elements:TestOrStarNamedExprList?> ")" => {
|
||||
elements.unwrap_or(ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Tuple { elements: Vec::new() }
|
||||
})
|
||||
},
|
||||
@@ -1020,7 +960,6 @@ Atom: ast::Expression = {
|
||||
<location:@L> "(" <element:Test> <generators:CompFor> ")" => {
|
||||
ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Comprehension {
|
||||
kind: Box::new(ast::ComprehensionKind::GeneratorExpression { element }),
|
||||
generators,
|
||||
@@ -1029,13 +968,11 @@ Atom: ast::Expression = {
|
||||
},
|
||||
<location:@L> "{" <e:DictLiteralValues?> "}" => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Dict { elements: e.unwrap_or_default() }
|
||||
},
|
||||
<location:@L> "{" <e1:DictEntry> <generators:CompFor> "}" => {
|
||||
ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Comprehension {
|
||||
kind: Box::new(ast::ComprehensionKind::Dict { key: e1.0, value: e1.1 }),
|
||||
generators,
|
||||
@@ -1044,23 +981,21 @@ Atom: ast::Expression = {
|
||||
},
|
||||
<location:@L> "{" <elements:SetLiteralValues> "}" => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Set { elements }
|
||||
},
|
||||
<location:@L> "{" <element:Test> <generators:CompFor> "}" => {
|
||||
ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Comprehension {
|
||||
kind: Box::new(ast::ComprehensionKind::Set { element }),
|
||||
generators,
|
||||
}
|
||||
}
|
||||
},
|
||||
<location:@L> "True" => ast::Expression { location, custom: (), node: ast::ExpressionType::True },
|
||||
<location:@L> "False" => ast::Expression { location, custom: (), node: ast::ExpressionType::False },
|
||||
<location:@L> "None" => ast::Expression { location, custom: (), node: ast::ExpressionType::None },
|
||||
<location:@L> "..." => ast::Expression { location, custom: (), node: ast::ExpressionType::Ellipsis },
|
||||
<location:@L> "True" => ast::Expression { location, node: ast::ExpressionType::True },
|
||||
<location:@L> "False" => ast::Expression { location, node: ast::ExpressionType::False },
|
||||
<location:@L> "None" => ast::Expression { location, node: ast::ExpressionType::None },
|
||||
<location:@L> "..." => ast::Expression { location, node: ast::ExpressionType::Ellipsis },
|
||||
};
|
||||
|
||||
ListLiteralValues: Vec<ast::Expression> = {
|
||||
@@ -1096,7 +1031,6 @@ ExpressionList: ast::Expression = {
|
||||
} else {
|
||||
ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Tuple { elements },
|
||||
}
|
||||
}
|
||||
@@ -1118,7 +1052,6 @@ TestList: ast::Expression = {
|
||||
} else {
|
||||
ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Tuple { elements },
|
||||
}
|
||||
}
|
||||
@@ -1129,7 +1062,6 @@ TestList: ast::Expression = {
|
||||
StarExpr: ast::Expression = {
|
||||
<location:@L> "*" <e:Expression> => ast::Expression {
|
||||
location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Starred { value: Box::new(e) },
|
||||
}
|
||||
};
|
||||
@@ -1159,7 +1091,6 @@ FunctionArgument: (Option<Option<String>>, ast::Expression) = {
|
||||
let expr = match c {
|
||||
Some(c) => ast::Expression {
|
||||
location: e.location,
|
||||
custom: (),
|
||||
node: ast::ExpressionType::Comprehension {
|
||||
kind: Box::new(ast::ComprehensionKind::GeneratorExpression { element: e }),
|
||||
generators: c,
|
||||
@@ -1170,7 +1101,7 @@ FunctionArgument: (Option<Option<String>>, ast::Expression) = {
|
||||
(None, expr)
|
||||
},
|
||||
<i:Identifier> "=" <e:Test> => (Some(Some(i)), e),
|
||||
<location:@L> "*" <e:Test> => (None, ast::Expression { location, custom: (), node: ast::ExpressionType::Starred { value: Box::new(e) } }),
|
||||
<location:@L> "*" <e:Test> => (None, ast::Expression { location, node: ast::ExpressionType::Starred { value: Box::new(e) } }),
|
||||
"**" <e:Test> => (Some(None), e),
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
//! Different token definitions.
|
||||
//! Loosely based on token.h from CPython source:
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use core::fmt::{self, Write};
|
||||
use num_bigint::BigInt;
|
||||
use std::fmt::{self, Write};
|
||||
|
||||
/// Python source code can be tokenized in a sequence of these tokens.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
@@ -125,11 +124,13 @@ impl fmt::Display for Tok {
|
||||
write!(f, "b\"")?;
|
||||
for i in value {
|
||||
match i {
|
||||
0..=8 => write!(f, "\\x0{}", i)?,
|
||||
9 => f.write_str("\\t")?,
|
||||
10 => f.write_str("\\n")?,
|
||||
11 => write!(f, "\\x0{:x}", i)?,
|
||||
13 => f.write_str("\\r")?,
|
||||
32..=126 => f.write_char(*i as char)?,
|
||||
_ => write!(f, "\\x{:02x}", i)?,
|
||||
_ => write!(f, "\\x{:x}", i)?,
|
||||
}
|
||||
}
|
||||
f.write_str("\"")
|
||||
|
||||
25
src/lib.rs
25
src/lib.rs
@@ -297,18 +297,15 @@ fn parse_arguments<'a>(app: App<'a, '_>) -> ArgMatches<'a> {
|
||||
/// Create settings by examining command line arguments and environment
|
||||
/// variables.
|
||||
fn create_settings(matches: &ArgMatches) -> PySettings {
|
||||
let mut settings = PySettings {
|
||||
isolated: matches.is_present("isolate"),
|
||||
ignore_environment: matches.is_present("ignore-environment"),
|
||||
interactive: !matches.is_present("c")
|
||||
&& !matches.is_present("m")
|
||||
&& (!matches.is_present("script") || matches.is_present("inspect")),
|
||||
bytes_warning: matches.occurrences_of("bytes-warning"),
|
||||
no_site: matches.is_present("no-site"),
|
||||
..Default::default()
|
||||
};
|
||||
let mut settings = PySettings::default();
|
||||
settings.isolated = matches.is_present("isolate");
|
||||
settings.ignore_environment = matches.is_present("ignore-environment");
|
||||
let ignore_environment = settings.ignore_environment || settings.isolated;
|
||||
|
||||
settings.interactive = !matches.is_present("c")
|
||||
&& !matches.is_present("m")
|
||||
&& (!matches.is_present("script") || matches.is_present("inspect"));
|
||||
|
||||
// add the current directory to sys.path
|
||||
settings.path_list.push("".to_owned());
|
||||
|
||||
@@ -355,6 +352,10 @@ fn create_settings(matches: &ArgMatches) -> PySettings {
|
||||
}
|
||||
}
|
||||
|
||||
settings.bytes_warning = matches.occurrences_of("bytes-warning");
|
||||
|
||||
settings.no_site = matches.is_present("no-site");
|
||||
|
||||
if matches.is_present("no-user-site")
|
||||
|| matches.is_present("isolate")
|
||||
|| (!ignore_environment && env::var_os("PYTHONNOUSERSITE").is_some())
|
||||
@@ -509,7 +510,7 @@ fn run_rustpython(vm: &VirtualMachine, matches: &ArgMatches) -> PyResult<()> {
|
||||
vm.get_attribute(vm.sys_module.clone(), "modules")?
|
||||
.set_item("__main__", main_module, vm)?;
|
||||
|
||||
let site_result = vm.import("site", None, 0);
|
||||
let site_result = vm.import("site", &[], 0);
|
||||
|
||||
if site_result.is_err() {
|
||||
warn!(
|
||||
@@ -558,7 +559,7 @@ fn run_command(vm: &VirtualMachine, scope: Scope, source: String) -> PyResult<()
|
||||
|
||||
fn run_module(vm: &VirtualMachine, module: &str) -> PyResult<()> {
|
||||
debug!("Running module {}", module);
|
||||
let runpy = vm.import("runpy", None, 0)?;
|
||||
let runpy = vm.import("runpy", &[], 0)?;
|
||||
let run_module_as_main = vm.get_attribute(runpy, "_run_module_as_main")?;
|
||||
vm.invoke(&run_module_as_main, (module,))?;
|
||||
Ok(())
|
||||
|
||||
@@ -9,14 +9,13 @@ edition = "2018"
|
||||
include = ["src/**/*.rs", "Cargo.toml", "build.rs", "Lib/**/*.py"]
|
||||
|
||||
[features]
|
||||
default = ["compile-parse", "threading", "std"]
|
||||
default = ["compile-parse", "threading"]
|
||||
vm-tracing-logging = []
|
||||
flame-it = ["flame", "flamer"]
|
||||
freeze-stdlib = ["rustpython-pylib"]
|
||||
jit = ["rustpython-jit"]
|
||||
threading = ["rustpython-common/threading"]
|
||||
compile-parse = ["rustpython-parser", "rustpython-compiler"]
|
||||
std = ["rustpython-compiler/std"] # enables compiler-core/std, parser/std, etc
|
||||
|
||||
ssl = ["openssl", "openssl-sys", "openssl-probe"]
|
||||
|
||||
@@ -35,10 +34,10 @@ num-traits = "0.2.8"
|
||||
num-integer = "0.1.41"
|
||||
num-rational = "0.3"
|
||||
num-iter = "0.1.39"
|
||||
rand = "0.8"
|
||||
rand_core = "0.6"
|
||||
getrandom = { version = "0.2", features = ["js"] }
|
||||
mt19937 = "2.0"
|
||||
rand = { version = "0.7", features = ["wasm-bindgen"] }
|
||||
rand_core = "0.5"
|
||||
getrandom = { version = "0.1", features = ["wasm-bindgen"] }
|
||||
mt19937 = "1.0"
|
||||
log = "0.4"
|
||||
rustpython-derive = { path = "../derive", version = "0.1.2" }
|
||||
rustpython-parser = { path = "../parser", optional = true, version = "0.1.2" }
|
||||
@@ -48,9 +47,10 @@ rustpython-jit = { path = "../jit", optional = true, version = "0.1.2" }
|
||||
rustpython-pylib = { path = "pylib-crate", optional = true, version = "0.1.0" }
|
||||
serde = { version = "1.0.66", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
byteorder = "1.2.6"
|
||||
regex = "1"
|
||||
rustc_version_runtime = "0.1.*"
|
||||
puruspe = "0.1"
|
||||
statrs = "0.12.0"
|
||||
caseless = "0.2.1"
|
||||
chrono = { version = "0.4", features = ["wasmbind"] }
|
||||
lexical-core = "0.7"
|
||||
@@ -58,11 +58,12 @@ itertools = "0.9"
|
||||
hex = "0.4.0"
|
||||
hexf-parse = "0.1.0"
|
||||
indexmap = "1.0.2"
|
||||
ahash = "0.6"
|
||||
crc = "^1.0.0"
|
||||
maplit = "1.0"
|
||||
bitflags = "1.2.1"
|
||||
libc = "0.2"
|
||||
nix = "0.18"
|
||||
arr_macro = "0.1.2"
|
||||
csv = "1.1.1"
|
||||
paste = "0.1"
|
||||
base64 = "0.13"
|
||||
@@ -79,7 +80,6 @@ timsort = "0.1"
|
||||
thiserror = "1.0"
|
||||
atty = "0.2"
|
||||
static_assertions = "1.1"
|
||||
half = "1.6"
|
||||
|
||||
## unicode stuff
|
||||
unicode_names2 = "0.4"
|
||||
@@ -107,7 +107,7 @@ uname = "0.1.1"
|
||||
crc32fast = "1.2.0"
|
||||
adler32 = "1.0.3"
|
||||
gethostname = "0.2.0"
|
||||
socket2 = "0.3.19"
|
||||
socket2 = "0.3"
|
||||
rustyline = "6.0"
|
||||
openssl = { version = "0.10", features = ["vendored"], optional = true }
|
||||
openssl-sys = { version = "0.9", optional = true }
|
||||
|
||||
@@ -2,11 +2,16 @@
|
||||
//! common way to use this crate is to just add the `"freeze-stdlib"` feature to `rustpython-vm`,
|
||||
//! in order to automatically include the python part of the standard library into the binary.
|
||||
|
||||
extern crate self as rustpython_pylib;
|
||||
|
||||
pub const LIB_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/Lib");
|
||||
|
||||
#[cfg(feature = "compiled-bytecode")]
|
||||
use {rustpython_bytecode::FrozenModule, std::collections::HashMap};
|
||||
use {
|
||||
rustpython_bytecode::bytecode::{self, FrozenModule},
|
||||
std::collections::HashMap,
|
||||
};
|
||||
#[cfg(feature = "compiled-bytecode")]
|
||||
pub fn frozen_stdlib() -> HashMap<String, FrozenModule> {
|
||||
rustpython_derive::py_freeze!(dir = "Lib", crate_name = "rustpython_bytecode")
|
||||
rustpython_derive::py_freeze!(dir = "Lib", crate_name = "rustpython_pylib")
|
||||
}
|
||||
|
||||
@@ -9,15 +9,26 @@ use num_traits::{cast::ToPrimitive, sign::Signed};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(FromArgs)]
|
||||
pub struct SplitArgs<'s, T: TryFromObject + AnyStrWrapper<'s>> {
|
||||
pub struct SplitArgs<'a, T, S, E>
|
||||
where
|
||||
T: TryFromObject + AnyStrWrapper<S>,
|
||||
S: ?Sized + AnyStr<'a, E>,
|
||||
E: Copy,
|
||||
{
|
||||
#[pyarg(any, default)]
|
||||
sep: Option<T>,
|
||||
#[pyarg(any, default = "-1")]
|
||||
maxsplit: isize,
|
||||
_phantom: std::marker::PhantomData<&'s ()>,
|
||||
_phantom1: std::marker::PhantomData<&'a S>,
|
||||
_phantom2: std::marker::PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<'s, T: TryFromObject + AnyStrWrapper<'s>> SplitArgs<'s, T> {
|
||||
impl<'a, T, S, E> SplitArgs<'a, T, S, E>
|
||||
where
|
||||
T: TryFromObject + AnyStrWrapper<S>,
|
||||
S: ?Sized + AnyStr<'a, E>,
|
||||
E: Copy,
|
||||
{
|
||||
pub fn get_value(self, vm: &VirtualMachine) -> PyResult<(Option<T>, isize)> {
|
||||
let sep = if let Some(s) = self.sep {
|
||||
let sep = s.as_ref();
|
||||
@@ -113,9 +124,11 @@ impl StringRange for std::ops::Range<usize> {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AnyStrWrapper<'s> {
|
||||
type Str: ?Sized + AnyStr<'s>;
|
||||
fn as_ref(&self) -> &Self::Str;
|
||||
pub trait AnyStrWrapper<S>
|
||||
where
|
||||
S: ?Sized,
|
||||
{
|
||||
fn as_ref(&self) -> &S;
|
||||
}
|
||||
|
||||
pub trait AnyStrContainer<S>
|
||||
@@ -127,23 +140,28 @@ where
|
||||
fn push_str(&mut self, s: &S);
|
||||
}
|
||||
|
||||
// TODO: GATs for `'s` once stabilized
|
||||
pub trait AnyStr<'s>: 's {
|
||||
type Char: Copy;
|
||||
type Container: AnyStrContainer<Self> + Extend<Self::Char>;
|
||||
type CharIter: Iterator<Item = char> + 's;
|
||||
type ElementIter: Iterator<Item = Self::Char> + 's;
|
||||
pub trait AnyStr<'s, E>
|
||||
where
|
||||
E: Copy,
|
||||
Self: 's,
|
||||
Self::Container: AnyStrContainer<Self> + std::iter::Extend<E>,
|
||||
Self::CharIter: 's + std::iter::Iterator<Item = char>,
|
||||
Self::ElementIter: 's + std::iter::Iterator<Item = E>,
|
||||
{
|
||||
type Container;
|
||||
type CharIter;
|
||||
type ElementIter;
|
||||
|
||||
fn element_bytes_len(c: Self::Char) -> usize;
|
||||
fn element_bytes_len(c: E) -> usize;
|
||||
|
||||
fn to_container(&self) -> Self::Container;
|
||||
fn as_bytes(&self) -> &[u8];
|
||||
fn as_utf8_str(&self) -> Result<&str, std::str::Utf8Error>;
|
||||
fn chars(&'s self) -> Self::CharIter;
|
||||
fn elements(&'s self) -> Self::ElementIter;
|
||||
fn get_bytes(&self, range: std::ops::Range<usize>) -> &Self;
|
||||
fn get_bytes<'a>(&'a self, range: std::ops::Range<usize>) -> &'a Self;
|
||||
// FIXME: get_chars is expensive for str
|
||||
fn get_chars(&self, range: std::ops::Range<usize>) -> &Self;
|
||||
fn get_chars<'a>(&'a self, range: std::ops::Range<usize>) -> &'a Self;
|
||||
fn bytes_len(&self) -> usize;
|
||||
// fn chars_len(&self) -> usize; // cannot access to cache here
|
||||
fn is_empty(&self) -> bool;
|
||||
@@ -157,14 +175,14 @@ pub trait AnyStr<'s>: 's {
|
||||
|
||||
fn py_split<T, SP, SN, SW, R>(
|
||||
&self,
|
||||
args: SplitArgs<'s, T>,
|
||||
args: SplitArgs<'s, T, Self, E>,
|
||||
vm: &VirtualMachine,
|
||||
split: SP,
|
||||
splitn: SN,
|
||||
splitw: SW,
|
||||
) -> PyResult<Vec<R>>
|
||||
where
|
||||
T: TryFromObject + AnyStrWrapper<'s, Str = Self>,
|
||||
T: TryFromObject + AnyStrWrapper<Self>,
|
||||
SP: Fn(&Self, &Self, &VirtualMachine) -> Vec<R>,
|
||||
SN: Fn(&Self, &Self, usize, &VirtualMachine) -> Vec<R>,
|
||||
SW: Fn(&Self, isize, &VirtualMachine) -> Vec<R>,
|
||||
@@ -231,7 +249,7 @@ pub trait AnyStr<'s>: 's {
|
||||
func_default: FD,
|
||||
) -> &'a Self
|
||||
where
|
||||
S: AnyStrWrapper<'s, Str = Self>,
|
||||
S: AnyStrWrapper<Self>,
|
||||
FC: Fn(&'a Self, &Self) -> &'a Self,
|
||||
FD: Fn(&'a Self) -> &'a Self,
|
||||
{
|
||||
@@ -268,7 +286,7 @@ pub trait AnyStr<'s>: 's {
|
||||
}
|
||||
}
|
||||
|
||||
fn py_pad(&self, left: usize, right: usize, fillchar: Self::Char) -> Self::Container {
|
||||
fn py_pad(&self, left: usize, right: usize, fillchar: E) -> Self::Container {
|
||||
let mut u = Self::Container::with_capacity(
|
||||
(left + right) * Self::element_bytes_len(fillchar) + self.bytes_len(),
|
||||
);
|
||||
@@ -278,23 +296,23 @@ pub trait AnyStr<'s>: 's {
|
||||
u
|
||||
}
|
||||
|
||||
fn py_center(&self, width: usize, fillchar: Self::Char, len: usize) -> Self::Container {
|
||||
fn py_center(&self, width: usize, fillchar: E, len: usize) -> Self::Container {
|
||||
let marg = width - len;
|
||||
let left = marg / 2 + (marg & width & 1);
|
||||
self.py_pad(left, marg - left, fillchar)
|
||||
}
|
||||
|
||||
fn py_ljust(&self, width: usize, fillchar: Self::Char, len: usize) -> Self::Container {
|
||||
fn py_ljust(&self, width: usize, fillchar: E, len: usize) -> Self::Container {
|
||||
self.py_pad(0, width - len, fillchar)
|
||||
}
|
||||
|
||||
fn py_rjust(&self, width: usize, fillchar: Self::Char, len: usize) -> Self::Container {
|
||||
fn py_rjust(&self, width: usize, fillchar: E, len: usize) -> Self::Container {
|
||||
self.py_pad(width - len, 0, fillchar)
|
||||
}
|
||||
|
||||
fn py_join<'a>(
|
||||
&self,
|
||||
mut iter: PyIterator<'a, impl AnyStrWrapper<'s, Str = Self> + TryFromObject>,
|
||||
mut iter: PyIterator<'a, impl AnyStrWrapper<Self> + TryFromObject>,
|
||||
) -> PyResult<Self::Container> {
|
||||
let mut joined = if let Some(elem) = iter.next() {
|
||||
elem?.as_ref().to_container()
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
use super::code::PyCodeRef;
|
||||
use super::pystr::PyStrRef;
|
||||
use super::pytype::PyTypeRef;
|
||||
use crate::coroutine::{Coro, Variant};
|
||||
use crate::exceptions::PyBaseExceptionRef;
|
||||
use crate::frame::FrameRef;
|
||||
use crate::function::OptionalArg;
|
||||
use crate::pyobject::{
|
||||
IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
|
||||
PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
|
||||
};
|
||||
use crate::slots::PyIter;
|
||||
use crate::vm::VirtualMachine;
|
||||
@@ -33,27 +32,17 @@ impl PyAsyncGen {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
pub fn new(frame: FrameRef, name: PyStrRef) -> Self {
|
||||
pub fn new(frame: FrameRef, vm: &VirtualMachine) -> PyRef<Self> {
|
||||
PyAsyncGen {
|
||||
inner: Coro::new(frame, Variant::AsyncGen, name),
|
||||
inner: Coro::new(frame, Variant::AsyncGen),
|
||||
running_async: AtomicCell::new(false),
|
||||
}
|
||||
.into_ref(vm)
|
||||
}
|
||||
|
||||
// TODO: fix function names situation
|
||||
#[pyproperty(magic)]
|
||||
fn name(&self) -> PyStrRef {
|
||||
self.inner.name()
|
||||
}
|
||||
|
||||
#[pyproperty(magic, setter)]
|
||||
fn set_name(&self, name: PyStrRef) {
|
||||
self.inner.set_name(name)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn repr(zelf: PyRef<Self>) -> String {
|
||||
zelf.inner.repr(zelf.get_id())
|
||||
}
|
||||
fn name(&self) {}
|
||||
|
||||
#[pymethod(name = "__aiter__")]
|
||||
fn aiter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
|
||||
@@ -13,15 +13,15 @@ use crate::vm::VirtualMachine;
|
||||
|
||||
pub struct PyNativeFuncDef {
|
||||
pub func: PyNativeFunc,
|
||||
pub name: PyStrRef,
|
||||
pub name: Option<PyStrRef>,
|
||||
pub doc: Option<PyStrRef>,
|
||||
}
|
||||
|
||||
impl PyNativeFuncDef {
|
||||
pub fn new(func: PyNativeFunc, name: PyStrRef) -> Self {
|
||||
impl From<PyNativeFunc> for PyNativeFuncDef {
|
||||
fn from(func: PyNativeFunc) -> Self {
|
||||
Self {
|
||||
func,
|
||||
name,
|
||||
name: None,
|
||||
doc: None,
|
||||
}
|
||||
}
|
||||
@@ -70,10 +70,19 @@ impl PyValue for PyBuiltinFunction {
|
||||
|
||||
impl fmt::Debug for PyBuiltinFunction {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "builtin function {}", self.value.name.borrow_value())
|
||||
let name = match &self.value.name {
|
||||
Some(s) => s.borrow_value(),
|
||||
None => "<unknown name>",
|
||||
};
|
||||
write!(f, "builtin function {}", name)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PyNativeFunc> for PyBuiltinFunction {
|
||||
fn from(value: PyNativeFunc) -> Self {
|
||||
PyNativeFuncDef::from(value).into()
|
||||
}
|
||||
}
|
||||
impl From<PyNativeFuncDef> for PyBuiltinFunction {
|
||||
fn from(value: PyNativeFuncDef) -> Self {
|
||||
Self {
|
||||
@@ -115,7 +124,7 @@ impl PyBuiltinFunction {
|
||||
vm.unwrap_or_none(self.module.clone())
|
||||
}
|
||||
#[pyproperty(magic)]
|
||||
fn name(&self) -> PyStrRef {
|
||||
fn name(&self) -> Option<PyStrRef> {
|
||||
self.value.name.clone()
|
||||
}
|
||||
#[pyproperty(magic)]
|
||||
@@ -175,7 +184,7 @@ impl Callable for PyBuiltinMethod {
|
||||
#[pyimpl(with(SlotDescriptor, Callable))]
|
||||
impl PyBuiltinMethod {
|
||||
#[pyproperty(magic)]
|
||||
fn name(&self) -> PyStrRef {
|
||||
fn name(&self) -> Option<PyStrRef> {
|
||||
self.value.name.clone()
|
||||
}
|
||||
#[pyproperty(magic)]
|
||||
|
||||
@@ -93,7 +93,7 @@ pub(crate) fn init(context: &PyContext) {
|
||||
PyByteArray::extend_class(context, &context.types.bytearray_type);
|
||||
let bytearray_type = &context.types.bytearray_type;
|
||||
extend_class!(context, bytearray_type, {
|
||||
"maketrans" => context.new_method("maketrans", PyBytesInner::maketrans),
|
||||
"maketrans" => context.new_method(PyBytesInner::maketrans),
|
||||
});
|
||||
|
||||
PyByteArrayIterator::extend_class(context, &context.types.bytearray_iterator_type);
|
||||
@@ -545,11 +545,11 @@ impl PyByteArray {
|
||||
}
|
||||
|
||||
#[pymethod(name = "splitlines")]
|
||||
fn splitlines(&self, options: anystr::SplitLinesArgs, vm: &VirtualMachine) -> PyObjectRef {
|
||||
fn splitlines(&self, options: anystr::SplitLinesArgs, vm: &VirtualMachine) -> PyResult {
|
||||
let lines = self
|
||||
.borrow_value()
|
||||
.splitlines(options, |x| vm.ctx.new_bytearray(x.to_vec()));
|
||||
vm.ctx.new_list(lines)
|
||||
Ok(vm.ctx.new_list(lines))
|
||||
}
|
||||
|
||||
#[pymethod(name = "zfill")]
|
||||
@@ -607,8 +607,9 @@ impl PyByteArray {
|
||||
}
|
||||
|
||||
#[pymethod(name = "reverse")]
|
||||
fn reverse(&self) {
|
||||
fn reverse(&self) -> PyResult<()> {
|
||||
self.borrow_value_mut().elements.reverse();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
|
||||
@@ -91,7 +91,7 @@ pub(crate) fn init(context: &PyContext) {
|
||||
PyBytes::extend_class(context, &context.types.bytes_type);
|
||||
let bytes_type = &context.types.bytes_type;
|
||||
extend_class!(context, bytes_type, {
|
||||
"maketrans" => context.new_method("maketrans", PyBytesInner::maketrans),
|
||||
"maketrans" => context.new_method(PyBytesInner::maketrans),
|
||||
});
|
||||
PyBytesIterator::extend_class(context, &context.types.bytes_iterator_type);
|
||||
}
|
||||
@@ -118,8 +118,8 @@ impl PyBytes {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__sizeof__")]
|
||||
fn sizeof(&self) -> usize {
|
||||
size_of::<Self>() + self.inner.elements.len() * size_of::<u8>()
|
||||
fn sizeof(&self) -> PyResult<usize> {
|
||||
Ok(size_of::<Self>() + self.inner.elements.len() * size_of::<u8>())
|
||||
}
|
||||
|
||||
#[pymethod(name = "__add__")]
|
||||
@@ -387,11 +387,11 @@ impl PyBytes {
|
||||
}
|
||||
|
||||
#[pymethod(name = "splitlines")]
|
||||
fn splitlines(&self, options: anystr::SplitLinesArgs, vm: &VirtualMachine) -> PyObjectRef {
|
||||
fn splitlines(&self, options: anystr::SplitLinesArgs, vm: &VirtualMachine) -> PyResult {
|
||||
let lines = self
|
||||
.inner
|
||||
.splitlines(options, |x| vm.ctx.new_bytes(x.to_vec()));
|
||||
vm.ctx.new_list(lines)
|
||||
Ok(vm.ctx.new_list(lines))
|
||||
}
|
||||
|
||||
#[pymethod(name = "zfill")]
|
||||
|
||||
@@ -206,7 +206,7 @@ impl PyCodeRef {
|
||||
fn repr(self) -> String {
|
||||
let code = &self.code;
|
||||
format!(
|
||||
"<code object {} at {:#x} file {:?}, line {}>",
|
||||
"<code object {} at 0x{:x} file {:?}, line {}>",
|
||||
code.obj_name,
|
||||
self.get_id(),
|
||||
code.source_path,
|
||||
@@ -225,7 +225,7 @@ impl PyCodeRef {
|
||||
}
|
||||
|
||||
#[pyproperty]
|
||||
fn co_filename(self) -> PyStrRef {
|
||||
fn co_filename(self) -> String {
|
||||
self.code.source_path.clone()
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ impl PyCodeRef {
|
||||
}
|
||||
|
||||
#[pyproperty]
|
||||
fn co_name(self) -> PyStrRef {
|
||||
fn co_name(self) -> String {
|
||||
self.code.obj_name.clone()
|
||||
}
|
||||
|
||||
@@ -267,12 +267,6 @@ impl PyCodeRef {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PyCode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
(**self).fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(ctx: &PyContext) {
|
||||
PyCodeRef::extend_class(ctx, &ctx.types.code_type);
|
||||
}
|
||||
|
||||
@@ -435,7 +435,7 @@ fn try_complex(obj: &PyObjectRef, vm: &VirtualMachine) -> PyResult<Option<(Compl
|
||||
if let Some(complex) = obj.payload_if_subclass::<PyComplex>(vm) {
|
||||
return Ok(Some((complex.value, true)));
|
||||
}
|
||||
if let Some(float) = float::try_float_opt(obj, vm)? {
|
||||
if let Some(float) = float::try_float(obj, vm)? {
|
||||
return Ok(Some((Complex64::new(float, 0.0), false)));
|
||||
}
|
||||
Ok(None)
|
||||
|
||||
@@ -4,7 +4,7 @@ use super::pytype::PyTypeRef;
|
||||
use crate::coroutine::{Coro, Variant};
|
||||
use crate::frame::FrameRef;
|
||||
use crate::function::OptionalArg;
|
||||
use crate::pyobject::{IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
use crate::slots::PyIter;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
@@ -28,25 +28,17 @@ impl PyCoroutine {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
pub fn new(frame: FrameRef, name: PyStrRef) -> Self {
|
||||
pub fn new(frame: FrameRef, vm: &VirtualMachine) -> PyRef<Self> {
|
||||
PyCoroutine {
|
||||
inner: Coro::new(frame, Variant::Coroutine, name),
|
||||
inner: Coro::new(frame, Variant::Coroutine),
|
||||
}
|
||||
.into_ref(vm)
|
||||
}
|
||||
|
||||
// TODO: fix function names situation
|
||||
#[pyproperty(magic)]
|
||||
fn name(&self) -> PyStrRef {
|
||||
self.inner.name()
|
||||
}
|
||||
|
||||
#[pyproperty(magic, setter)]
|
||||
fn set_name(&self, name: PyStrRef) {
|
||||
self.inner.set_name(name)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn repr(zelf: PyRef<Self>) -> String {
|
||||
zelf.inner.repr(zelf.get_id())
|
||||
fn name(&self, vm: &VirtualMachine) -> PyObjectRef {
|
||||
vm.ctx.none()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
|
||||
@@ -450,7 +450,7 @@ impl PyDictRef {
|
||||
|
||||
/// Take a python dictionary and convert it to attributes.
|
||||
pub fn to_attributes(self) -> PyAttributes {
|
||||
let mut attrs = PyAttributes::default();
|
||||
let mut attrs = PyAttributes::new();
|
||||
for (key, value) in self {
|
||||
let key = pystr::clone_value(&key);
|
||||
attrs.insert(key, value);
|
||||
|
||||
@@ -55,7 +55,7 @@ impl From<f64> for PyFloat {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_float_opt(obj: &PyObjectRef, vm: &VirtualMachine) -> PyResult<Option<f64>> {
|
||||
pub(crate) fn try_float(obj: &PyObjectRef, vm: &VirtualMachine) -> PyResult<Option<f64>> {
|
||||
if let Some(float) = obj.payload_if_exact::<PyFloat>(vm) {
|
||||
return Ok(Some(float.value));
|
||||
}
|
||||
@@ -76,11 +76,6 @@ pub fn try_float_opt(obj: &PyObjectRef, vm: &VirtualMachine) -> PyResult<Option<
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub fn try_float(obj: &PyObjectRef, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
try_float_opt(obj, vm)?
|
||||
.ok_or_else(|| vm.new_type_error(format!("must be real number, not {}", obj.class().name)))
|
||||
}
|
||||
|
||||
pub(crate) fn to_op_float(obj: &PyObjectRef, vm: &VirtualMachine) -> PyResult<Option<f64>> {
|
||||
let v = if let Some(float) = obj.payload_if_subclass::<PyFloat>(vm) {
|
||||
Some(float.value)
|
||||
@@ -181,7 +176,7 @@ impl PyFloat {
|
||||
val
|
||||
};
|
||||
|
||||
if let Some(f) = try_float_opt(&val, vm)? {
|
||||
if let Some(f) = try_float(&val, vm)? {
|
||||
f
|
||||
} else if let Some(s) = val.payload_if_subclass::<PyStr>(vm) {
|
||||
float_ops::parse_str(s.borrow_value().trim()).ok_or_else(|| {
|
||||
@@ -560,7 +555,7 @@ impl Hashable for PyFloat {
|
||||
pub type PyFloatRef = PyRef<PyFloat>;
|
||||
|
||||
// Retrieve inner float value:
|
||||
pub(crate) fn get_value(obj: &PyObjectRef) -> f64 {
|
||||
pub fn get_value(obj: &PyObjectRef) -> f64 {
|
||||
obj.payload::<PyFloat>().unwrap().value
|
||||
}
|
||||
|
||||
@@ -586,7 +581,9 @@ impl IntoPyFloat {
|
||||
|
||||
impl TryFromObject for IntoPyFloat {
|
||||
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
|
||||
let value = try_float(&obj, vm)?;
|
||||
let value = try_float(&obj, vm)?.ok_or_else(|| {
|
||||
vm.new_type_error(format!("must be real number, not {}", obj.class().name))
|
||||
})?;
|
||||
Ok(IntoPyFloat { value })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ impl FrameRef {
|
||||
}
|
||||
|
||||
#[pyproperty]
|
||||
fn f_lasti(self) -> u32 {
|
||||
fn f_lasti(self) -> usize {
|
||||
self.lasti()
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,6 @@ pub struct PyFunction {
|
||||
closure: Option<PyTupleTyped<PyCellRef>>,
|
||||
defaults: Option<PyTupleRef>,
|
||||
kw_only_defaults: Option<PyDictRef>,
|
||||
name: PyMutex<PyStrRef>,
|
||||
}
|
||||
|
||||
impl PyFunction {
|
||||
@@ -51,7 +50,6 @@ impl PyFunction {
|
||||
defaults: Option<PyTupleRef>,
|
||||
kw_only_defaults: Option<PyDictRef>,
|
||||
) -> Self {
|
||||
let name = PyMutex::new(code.obj_name.clone());
|
||||
PyFunction {
|
||||
code,
|
||||
#[cfg(feature = "jit")]
|
||||
@@ -60,7 +58,6 @@ impl PyFunction {
|
||||
closure,
|
||||
defaults,
|
||||
kw_only_defaults,
|
||||
name,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,9 +281,9 @@ impl PyFunction {
|
||||
let is_gen = code.flags.contains(bytecode::CodeFlags::IS_GENERATOR);
|
||||
let is_coro = code.flags.contains(bytecode::CodeFlags::IS_COROUTINE);
|
||||
match (is_gen, is_coro) {
|
||||
(true, false) => Ok(PyGenerator::new(frame, self.name()).into_object(vm)),
|
||||
(false, true) => Ok(PyCoroutine::new(frame, self.name()).into_object(vm)),
|
||||
(true, true) => Ok(PyAsyncGen::new(frame, self.name()).into_object(vm)),
|
||||
(true, false) => Ok(PyGenerator::new(frame, vm).into_object()),
|
||||
(false, true) => Ok(PyCoroutine::new(frame, vm).into_object()),
|
||||
(true, true) => Ok(PyAsyncGen::new(frame, vm).into_object()),
|
||||
(false, false) => vm.run_frame_full(frame),
|
||||
}
|
||||
}
|
||||
@@ -324,21 +321,6 @@ impl PyFunction {
|
||||
self.globals.clone()
|
||||
}
|
||||
|
||||
#[pyproperty(magic)]
|
||||
fn name(&self) -> PyStrRef {
|
||||
self.name.lock().clone()
|
||||
}
|
||||
|
||||
#[pyproperty(magic, setter)]
|
||||
fn set_name(&self, name: PyStrRef) {
|
||||
*self.name.lock() = name;
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn repr(zelf: PyRef<Self>) -> String {
|
||||
format!("<function {} at {:#x}>", zelf.name.lock(), zelf.get_id())
|
||||
}
|
||||
|
||||
#[cfg(feature = "jit")]
|
||||
#[pymethod(magic)]
|
||||
fn jit(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<()> {
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
*/
|
||||
|
||||
use super::code::PyCodeRef;
|
||||
use super::pystr::PyStrRef;
|
||||
use super::pytype::PyTypeRef;
|
||||
use crate::coroutine::{Coro, Variant};
|
||||
use crate::frame::FrameRef;
|
||||
use crate::function::OptionalArg;
|
||||
use crate::pyobject::{IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
use crate::slots::PyIter;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
@@ -30,25 +29,17 @@ impl PyGenerator {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
pub fn new(frame: FrameRef, name: PyStrRef) -> Self {
|
||||
pub fn new(frame: FrameRef, vm: &VirtualMachine) -> PyRef<Self> {
|
||||
PyGenerator {
|
||||
inner: Coro::new(frame, Variant::Gen, name),
|
||||
inner: Coro::new(frame, Variant::Gen),
|
||||
}
|
||||
.into_ref(vm)
|
||||
}
|
||||
|
||||
// TODO: fix function names situation
|
||||
#[pyproperty(magic)]
|
||||
fn name(&self) -> PyStrRef {
|
||||
self.inner.name()
|
||||
}
|
||||
|
||||
#[pyproperty(magic, setter)]
|
||||
fn set_name(&self, name: PyStrRef) {
|
||||
self.inner.set_name(name)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn repr(zelf: PyRef<Self>) -> String {
|
||||
zelf.inner.repr(zelf.get_id())
|
||||
fn name(&self, vm: &VirtualMachine) -> PyObjectRef {
|
||||
vm.ctx.none()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
|
||||
@@ -570,8 +570,11 @@ impl PyInt {
|
||||
}
|
||||
|
||||
#[pymethod(name = "as_integer_ratio")]
|
||||
fn as_integer_ratio(&self, vm: &VirtualMachine) -> (PyObjectRef, BigInt) {
|
||||
(vm.ctx.new_bigint(&self.value), BigInt::one())
|
||||
fn as_integer_ratio(&self, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(vm.ctx.new_tuple(vec![
|
||||
vm.ctx.new_bigint(&self.value),
|
||||
vm.ctx.new_bigint(&BigInt::one()),
|
||||
]))
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -885,7 +888,7 @@ fn detect_base(c: &u8) -> Option<u32> {
|
||||
}
|
||||
|
||||
// Retrieve inner int value:
|
||||
pub(crate) fn get_value(obj: &PyObjectRef) -> &BigInt {
|
||||
pub fn get_value(obj: &PyObjectRef) -> &BigInt {
|
||||
&obj.payload::<PyInt>().unwrap().value
|
||||
}
|
||||
|
||||
@@ -908,7 +911,7 @@ pub(crate) fn try_int(obj: &PyObjectRef, vm: &VirtualMachine) -> PyResult<BigInt
|
||||
vm.to_repr(obj)?,
|
||||
))),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// test for strings and bytes
|
||||
if let Some(s) = obj.downcast_ref::<PyStr>() {
|
||||
|
||||
@@ -117,13 +117,13 @@ impl PyList {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iadd__")]
|
||||
fn iadd(zelf: PyRef<Self>, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
fn iadd(zelf: PyRef<Self>, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if let Ok(new_elements) = vm.extract_elements(&other) {
|
||||
let mut e = new_elements;
|
||||
zelf.borrow_value_mut().append(&mut e);
|
||||
zelf.into_object()
|
||||
Ok(zelf.into_object())
|
||||
} else {
|
||||
vm.ctx.not_implemented()
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -103,11 +103,11 @@ mod decl {
|
||||
#[derive(FromArgs)]
|
||||
#[allow(dead_code)]
|
||||
struct CompileArgs {
|
||||
#[pyarg(any)]
|
||||
#[pyarg(positional)]
|
||||
source: Either<PyStrRef, PyBytesRef>,
|
||||
#[pyarg(any)]
|
||||
#[pyarg(positional)]
|
||||
filename: PyStrRef,
|
||||
#[pyarg(any)]
|
||||
#[pyarg(positional)]
|
||||
mode: PyStrRef,
|
||||
#[pyarg(any, optional)]
|
||||
flags: OptionalArg<PyIntRef>,
|
||||
@@ -320,8 +320,8 @@ mod decl {
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn globals(vm: &VirtualMachine) -> PyDictRef {
|
||||
vm.current_globals().clone()
|
||||
fn globals(vm: &VirtualMachine) -> PyResult<PyDictRef> {
|
||||
Ok(vm.current_globals().clone())
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
@@ -341,9 +341,15 @@ mod decl {
|
||||
// builtin_help
|
||||
|
||||
#[pyfunction]
|
||||
fn hex(number: PyIntRef) -> String {
|
||||
fn hex(number: PyIntRef, vm: &VirtualMachine) -> PyResult {
|
||||
let n = number.borrow_value();
|
||||
format!("{:#x}", n)
|
||||
let s = if n.is_negative() {
|
||||
format!("-0x{:x}", -n)
|
||||
} else {
|
||||
format!("0x{:x}", n)
|
||||
};
|
||||
|
||||
Ok(vm.ctx.new_str(s))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
|
||||
@@ -23,7 +23,6 @@ use crossbeam_utils::atomic::AtomicCell;
|
||||
use itertools::Itertools;
|
||||
use num_bigint::BigInt;
|
||||
use num_traits::{One, Signed, ToPrimitive, Zero};
|
||||
use rustpython_common::borrow::BorrowValue;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BufferRef(Box<dyn Buffer>);
|
||||
@@ -500,7 +499,7 @@ impl PyMemoryView {
|
||||
.get_pos(i)
|
||||
.ok_or_else(|| vm.new_index_error("index out of range".to_owned()))?;
|
||||
let itemsize = zelf.options.itemsize;
|
||||
let data = zelf.format_spec.pack(vec![value], vm)?;
|
||||
let data = zelf.format_spec.pack(&[value], vm)?;
|
||||
zelf.obj_bytes_mut()[i..i + itemsize].copy_from_slice(&data);
|
||||
Ok(())
|
||||
}
|
||||
@@ -655,7 +654,6 @@ impl PyMemoryView {
|
||||
fn toreadonly(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
zelf.try_not_released(vm)?;
|
||||
let buffer = BufferRef(Box::new(zelf.clone()));
|
||||
zelf.exports.fetch_add(1);
|
||||
Ok(PyMemoryView {
|
||||
obj: zelf.obj.clone(),
|
||||
buffer,
|
||||
@@ -675,9 +673,9 @@ impl PyMemoryView {
|
||||
#[pymethod(magic)]
|
||||
fn repr(zelf: PyRef<Self>) -> String {
|
||||
if zelf.released.load() {
|
||||
format!("<released memory at {:#x}>", zelf.get_id())
|
||||
format!("<released memory at 0x{:x}>", zelf.get_id())
|
||||
} else {
|
||||
format!("<memory at {:#x}>", zelf.get_id())
|
||||
format!("<memory at 0x{:x}>", zelf.get_id())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -705,48 +703,6 @@ impl PyMemoryView {
|
||||
bytes_to_hex(bytes, sep, bytes_per_sep, vm)
|
||||
}
|
||||
|
||||
// TODO: support cast shape
|
||||
#[pymethod]
|
||||
fn cast(zelf: PyRef<Self>, format: PyStrRef, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
zelf.try_not_released(vm)?;
|
||||
if !zelf.options.contiguous {
|
||||
return Err(vm.new_type_error(
|
||||
"memoryview: casts are restricted to C-contiguous views".to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
let format_spec = Self::parse_format(format.borrow_value(), vm)?;
|
||||
let itemsize = format_spec.size();
|
||||
let bytelen = zelf.options.len * zelf.options.itemsize;
|
||||
|
||||
if bytelen % itemsize != 0 {
|
||||
return Err(
|
||||
vm.new_type_error("memoryview: length is not a multiple of itemsize".to_owned())
|
||||
);
|
||||
}
|
||||
|
||||
let buffer = BufferRef(Box::new(zelf.clone()));
|
||||
zelf.exports.fetch_add(1);
|
||||
|
||||
Ok(PyMemoryView {
|
||||
obj: zelf.obj.clone(),
|
||||
buffer,
|
||||
options: BufferOptions {
|
||||
itemsize,
|
||||
len: bytelen / itemsize,
|
||||
format: format.to_string().into(),
|
||||
..zelf.options.clone()
|
||||
},
|
||||
released: AtomicCell::new(false),
|
||||
stop: zelf.stop + itemsize - zelf.options.itemsize,
|
||||
exports: AtomicCell::new(0),
|
||||
format_spec,
|
||||
hash: OnceCell::new(),
|
||||
..*zelf
|
||||
}
|
||||
.into_ref(vm))
|
||||
}
|
||||
|
||||
fn eq(zelf: &PyRef<Self>, other: &PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
if zelf.is(other) {
|
||||
return Ok(true);
|
||||
|
||||
@@ -51,7 +51,12 @@ impl PyModule {
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn init(zelf: PyRef<Self>, name: PyStrRef, doc: OptionalOption<PyStrRef>, vm: &VirtualMachine) {
|
||||
fn init(
|
||||
zelf: PyRef<Self>,
|
||||
name: PyStrRef,
|
||||
doc: OptionalOption<PyStrRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
debug_assert!(crate::pyobject::TypeProtocol::class(zelf.as_object())
|
||||
.slots
|
||||
.flags
|
||||
@@ -62,6 +67,7 @@ impl PyModule {
|
||||
name.into_object(),
|
||||
doc.flatten().into_pyobject(vm),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(zelf: PyRef<Self>, vm: &VirtualMachine) -> Option<String> {
|
||||
@@ -76,7 +82,7 @@ impl PyModule {
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
let importlib = vm.import("_frozen_importlib", None, 0)?;
|
||||
let importlib = vm.import("_frozen_importlib", &[], 0)?;
|
||||
let module_repr = vm.get_attribute(importlib, "_module_repr")?;
|
||||
vm.invoke(&module_repr, (zelf,))
|
||||
}
|
||||
|
||||
@@ -168,12 +168,12 @@ impl PyBaseObject {
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn repr(zelf: PyObjectRef) -> String {
|
||||
format!("<{} object at {:#x}>", zelf.class().name, zelf.get_id())
|
||||
format!("<{} object at 0x{:x}>", zelf.class().name, zelf.get_id())
|
||||
}
|
||||
|
||||
#[pyclassmethod(magic)]
|
||||
fn subclasshook(_args: FuncArgs, vm: &VirtualMachine) -> PyObjectRef {
|
||||
vm.ctx.not_implemented()
|
||||
fn subclasshook(_args: FuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
|
||||
#[pyclassmethod(magic)]
|
||||
@@ -314,11 +314,11 @@ pub fn init(context: &PyContext) {
|
||||
|
||||
fn common_reduce(obj: PyObjectRef, proto: usize, vm: &VirtualMachine) -> PyResult {
|
||||
if proto >= 2 {
|
||||
let reducelib = vm.import("__reducelib", None, 0)?;
|
||||
let reducelib = vm.import("__reducelib", &[], 0)?;
|
||||
let reduce_2 = vm.get_attribute(reducelib, "reduce_2")?;
|
||||
vm.invoke(&reduce_2, (obj,))
|
||||
} else {
|
||||
let copyreg = vm.import("copyreg", None, 0)?;
|
||||
let copyreg = vm.import("copyreg", &[], 0)?;
|
||||
let reduce_ex = vm.get_attribute(copyreg, "_reduce_ex")?;
|
||||
vm.invoke(&reduce_ex, (obj, proto))
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ pub(crate) fn init(context: &PyContext) {
|
||||
// }
|
||||
|
||||
// Retrieve inner int value:
|
||||
pub(crate) fn get_value(obj: &PyObjectRef) -> bool {
|
||||
pub fn get_value(obj: &PyObjectRef) -> bool {
|
||||
!obj.payload::<PyInt>().unwrap().borrow_value().is_zero()
|
||||
}
|
||||
|
||||
|
||||
@@ -95,14 +95,12 @@ impl fmt::Display for PyStr {
|
||||
}
|
||||
|
||||
impl TryIntoRef<PyStr> for String {
|
||||
#[inline]
|
||||
fn try_into_ref(self, vm: &VirtualMachine) -> PyResult<PyRef<PyStr>> {
|
||||
Ok(PyStr::from(self).into_ref(vm))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryIntoRef<PyStr> for &str {
|
||||
#[inline]
|
||||
fn try_into_ref(self, vm: &VirtualMachine) -> PyResult<PyRef<PyStr>> {
|
||||
Ok(PyStr::from(self).into_ref(vm))
|
||||
}
|
||||
@@ -572,8 +570,8 @@ impl PyStr {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rmod__")]
|
||||
fn rmod(&self, _values: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
vm.ctx.not_implemented()
|
||||
fn rmod(&self, _values: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -876,7 +874,7 @@ impl PyStr {
|
||||
fillchar: OptionalArg<PyStrRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<String> {
|
||||
self._pad(width, fillchar, AnyStr::py_center, vm)
|
||||
self._pad(width, fillchar, AnyStr::<char>::py_center, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -886,7 +884,7 @@ impl PyStr {
|
||||
fillchar: OptionalArg<PyStrRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<String> {
|
||||
self._pad(width, fillchar, AnyStr::py_ljust, vm)
|
||||
self._pad(width, fillchar, AnyStr::<char>::py_ljust, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -896,7 +894,7 @@ impl PyStr {
|
||||
fillchar: OptionalArg<PyStrRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<String> {
|
||||
self._pad(width, fillchar, AnyStr::py_rjust, vm)
|
||||
self._pad(width, fillchar, AnyStr::<char>::py_rjust, vm)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -904,7 +902,7 @@ impl PyStr {
|
||||
let tab_stop = args.tabsize();
|
||||
let mut expanded_str = String::with_capacity(self.value.len());
|
||||
let mut tab_size = tab_stop;
|
||||
let mut col_count = 0usize;
|
||||
let mut col_count = 0 as usize;
|
||||
for ch in self.value.chars() {
|
||||
match ch {
|
||||
'\t' => {
|
||||
@@ -1157,7 +1155,7 @@ impl TryFromObject for std::ffi::OsString {
|
||||
}
|
||||
}
|
||||
|
||||
type SplitArgs<'a> = anystr::SplitArgs<'a, PyStrRef>;
|
||||
type SplitArgs<'a> = anystr::SplitArgs<'a, PyStrRef, str, char>;
|
||||
|
||||
#[derive(FromArgs)]
|
||||
pub struct FindArgs {
|
||||
@@ -1183,11 +1181,11 @@ pub fn init(ctx: &PyContext) {
|
||||
PyStrReverseIterator::extend_class(ctx, &ctx.types.str_reverseiterator_type);
|
||||
}
|
||||
|
||||
pub(crate) fn clone_value(obj: &PyObjectRef) -> String {
|
||||
pub fn clone_value(obj: &PyObjectRef) -> String {
|
||||
String::from(obj.payload::<PyStr>().unwrap().borrow_value())
|
||||
}
|
||||
|
||||
pub(crate) fn borrow_value(obj: &PyObjectRef) -> &str {
|
||||
pub fn borrow_value(obj: &PyObjectRef) -> &str {
|
||||
&obj.payload::<PyStr>().unwrap().value
|
||||
}
|
||||
|
||||
@@ -1338,8 +1336,7 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> AnyStrWrapper<'s> for PyStrRef {
|
||||
type Str = str;
|
||||
impl AnyStrWrapper<str> for PyStrRef {
|
||||
fn as_ref(&self) -> &str {
|
||||
&*self.value
|
||||
}
|
||||
@@ -1359,8 +1356,7 @@ impl AnyStrContainer<str> for String {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> AnyStr<'s> for str {
|
||||
type Char = char;
|
||||
impl<'s> AnyStr<'s, char> for str {
|
||||
type Container = String;
|
||||
type CharIter = std::str::Chars<'s>;
|
||||
type ElementIter = std::str::Chars<'s>;
|
||||
@@ -1389,11 +1385,11 @@ impl<'s> AnyStr<'s> for str {
|
||||
str::chars(self)
|
||||
}
|
||||
|
||||
fn get_bytes(&self, range: std::ops::Range<usize>) -> &Self {
|
||||
fn get_bytes<'a>(&'a self, range: std::ops::Range<usize>) -> &'a Self {
|
||||
&self[range]
|
||||
}
|
||||
|
||||
fn get_chars(&self, range: std::ops::Range<usize>) -> &Self {
|
||||
fn get_chars<'a>(&'a self, range: std::ops::Range<usize>) -> &'a Self {
|
||||
rustpython_common::str::get_chars(self, range)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::common::lock::{
|
||||
PyMappedRwLockReadGuard, PyRwLock, PyRwLockReadGuard, PyRwLockUpgradableReadGuard,
|
||||
PyRwLockWriteGuard,
|
||||
};
|
||||
use std::collections::HashSet;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt;
|
||||
|
||||
use super::classmethod::PyClassMethod;
|
||||
@@ -133,7 +133,7 @@ impl PyType {
|
||||
|
||||
pub fn get_attributes(&self) -> PyAttributes {
|
||||
// Gather all members here:
|
||||
let mut attributes = PyAttributes::default();
|
||||
let mut attributes = PyAttributes::new();
|
||||
|
||||
for bc in self.iter_mro().rev() {
|
||||
for (name, value) in bc.attributes.read().iter() {
|
||||
@@ -791,7 +791,7 @@ pub fn new(
|
||||
name: &str,
|
||||
base: PyTypeRef,
|
||||
bases: Vec<PyTypeRef>,
|
||||
attrs: PyAttributes,
|
||||
attrs: HashMap<String, PyObjectRef>,
|
||||
mut slots: PyTypeSlots,
|
||||
) -> Result<PyTypeRef, String> {
|
||||
// Check for duplicates in bases.
|
||||
@@ -864,7 +864,7 @@ fn calculate_meta_class(
|
||||
Ok(winner)
|
||||
}
|
||||
|
||||
fn best_base(bases: &[PyTypeRef], vm: &VirtualMachine) -> PyResult<PyTypeRef> {
|
||||
fn best_base<'a>(bases: &'a [PyTypeRef], vm: &VirtualMachine) -> PyResult<PyTypeRef> {
|
||||
// let mut base = None;
|
||||
// let mut winner = None;
|
||||
|
||||
@@ -914,7 +914,8 @@ fn best_base(bases: &[PyTypeRef], vm: &VirtualMachine) -> PyResult<PyTypeRef> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use super::{linearise_mro, new};
|
||||
use super::{HashMap, IdProtocol, PyContext, PyTypeRef};
|
||||
|
||||
fn map_ids(obj: Result<Vec<PyTypeRef>, String>) -> Result<Vec<usize>, String> {
|
||||
Ok(obj?.into_iter().map(|x| x.get_id()).collect())
|
||||
@@ -931,7 +932,7 @@ mod tests {
|
||||
"A",
|
||||
object.clone(),
|
||||
vec![object.clone()],
|
||||
PyAttributes::default(),
|
||||
HashMap::new(),
|
||||
Default::default(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -940,7 +941,7 @@ mod tests {
|
||||
"B",
|
||||
object.clone(),
|
||||
vec![object.clone()],
|
||||
PyAttributes::default(),
|
||||
HashMap::new(),
|
||||
Default::default(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::builtins::pytype::PyTypeRef;
|
||||
use crate::frame::FrameRef;
|
||||
use crate::pyobject::{BorrowValue, PyClassImpl, PyContext, PyRef, PyValue};
|
||||
use crate::pyobject::{PyClassImpl, PyContext, PyRef, PyValue};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
#[pyclass(module = false, name = "traceback")]
|
||||
@@ -8,7 +8,7 @@ use crate::vm::VirtualMachine;
|
||||
pub struct PyTraceback {
|
||||
pub next: Option<PyTracebackRef>, // TODO: Make mutable
|
||||
pub frame: FrameRef,
|
||||
pub lasti: u32,
|
||||
pub lasti: usize,
|
||||
pub lineno: usize,
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ impl PyValue for PyTraceback {
|
||||
|
||||
#[pyimpl]
|
||||
impl PyTraceback {
|
||||
pub fn new(next: Option<PyRef<Self>>, frame: FrameRef, lasti: u32, lineno: usize) -> Self {
|
||||
pub fn new(next: Option<PyRef<Self>>, frame: FrameRef, lasti: usize, lineno: usize) -> Self {
|
||||
PyTraceback {
|
||||
next,
|
||||
frame,
|
||||
@@ -37,7 +37,7 @@ impl PyTraceback {
|
||||
}
|
||||
|
||||
#[pyproperty(name = "tb_lasti")]
|
||||
fn lasti(&self) -> u32 {
|
||||
fn lasti(&self) -> usize {
|
||||
self.lasti
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ impl PyTraceback {
|
||||
}
|
||||
|
||||
impl PyTracebackRef {
|
||||
pub fn iter(&self) -> impl Iterator<Item = PyTracebackRef> {
|
||||
pub fn iter<'a>(&'a self) -> impl Iterator<Item = PyTracebackRef> + 'a {
|
||||
std::iter::successors(Some(self.clone()), |tb| tb.next.clone())
|
||||
}
|
||||
}
|
||||
@@ -67,9 +67,9 @@ impl serde::Serialize for PyTraceback {
|
||||
use serde::ser::SerializeStruct;
|
||||
|
||||
let mut struc = s.serialize_struct("PyTraceback", 3)?;
|
||||
struc.serialize_field("name", self.frame.code.obj_name.borrow_value())?;
|
||||
struc.serialize_field("name", &self.frame.code.obj_name)?;
|
||||
struc.serialize_field("lineno", &self.lineno)?;
|
||||
struc.serialize_field("filename", self.frame.code.source_path.borrow_value())?;
|
||||
struc.serialize_field("filename", &self.frame.code.source_path)?;
|
||||
struc.end()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,7 +317,6 @@ impl<T: TransmuteFromObject> TryFromObject for PyTupleTyped<T> {
|
||||
|
||||
impl<'a, T: TransmuteFromObject + 'a> BorrowValue<'a> for PyTupleTyped<T> {
|
||||
type Borrowed = &'a [T];
|
||||
#[inline]
|
||||
fn borrow_value(&'a self) -> Self::Borrowed {
|
||||
unsafe { &*(self.tuple.borrow_value() as *const [PyObjectRef] as *const [T]) }
|
||||
}
|
||||
@@ -328,17 +327,3 @@ impl<T: TransmuteFromObject + fmt::Debug> fmt::Debug for PyTupleTyped<T> {
|
||||
self.borrow_value().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: TransmuteFromObject> From<PyTupleTyped<T>> for PyTupleRef {
|
||||
#[inline]
|
||||
fn from(tup: PyTupleTyped<T>) -> Self {
|
||||
tup.tuple
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: TransmuteFromObject> IntoPyObject for PyTupleTyped<T> {
|
||||
#[inline]
|
||||
fn into_pyobject(self, _vm: &VirtualMachine) -> PyObjectRef {
|
||||
self.tuple.into_object()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ impl ByteInnerTranslateOptions {
|
||||
}
|
||||
}
|
||||
|
||||
pub type ByteInnerSplitOptions<'a> = anystr::SplitArgs<'a, PyBytesInner>;
|
||||
pub type ByteInnerSplitOptions<'a> = anystr::SplitArgs<'a, PyBytesInner, [u8], u8>;
|
||||
|
||||
#[allow(clippy::len_without_is_empty)]
|
||||
impl PyBytesInner {
|
||||
@@ -468,7 +468,7 @@ impl PyBytesInner {
|
||||
options: ByteInnerPaddingOptions,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<Vec<u8>> {
|
||||
self._pad(options, AnyStr::py_center, vm)
|
||||
self._pad(options, AnyStr::<u8>::py_center, vm)
|
||||
}
|
||||
|
||||
pub fn ljust(
|
||||
@@ -476,7 +476,7 @@ impl PyBytesInner {
|
||||
options: ByteInnerPaddingOptions,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<Vec<u8>> {
|
||||
self._pad(options, AnyStr::py_ljust, vm)
|
||||
self._pad(options, AnyStr::<u8>::py_ljust, vm)
|
||||
}
|
||||
|
||||
pub fn rjust(
|
||||
@@ -484,7 +484,7 @@ impl PyBytesInner {
|
||||
options: ByteInnerPaddingOptions,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<Vec<u8>> {
|
||||
self._pad(options, AnyStr::py_rjust, vm)
|
||||
self._pad(options, AnyStr::<u8>::py_rjust, vm)
|
||||
}
|
||||
|
||||
pub fn count(&self, options: ByteInnerFindOptions, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
@@ -938,8 +938,7 @@ pub trait ByteOr: ToPrimitive {
|
||||
|
||||
impl ByteOr for BigInt {}
|
||||
|
||||
impl<'s> AnyStrWrapper<'s> for PyBytesInner {
|
||||
type Str = [u8];
|
||||
impl AnyStrWrapper<[u8]> for PyBytesInner {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.elements
|
||||
}
|
||||
@@ -961,8 +960,7 @@ impl AnyStrContainer<[u8]> for Vec<u8> {
|
||||
|
||||
const ASCII_WHITESPACES: [u8; 6] = [0x20, 0x09, 0x0a, 0x0c, 0x0d, 0x0b];
|
||||
|
||||
impl<'s> AnyStr<'s> for [u8] {
|
||||
type Char = u8;
|
||||
impl<'s> AnyStr<'s, u8> for [u8] {
|
||||
type Container = Vec<u8>;
|
||||
type CharIter = bstr::Chars<'s>;
|
||||
type ElementIter = std::iter::Copied<std::slice::Iter<'s, u8>>;
|
||||
@@ -991,11 +989,11 @@ impl<'s> AnyStr<'s> for [u8] {
|
||||
self.iter().copied()
|
||||
}
|
||||
|
||||
fn get_bytes(&self, range: std::ops::Range<usize>) -> &Self {
|
||||
fn get_bytes<'a>(&'a self, range: std::ops::Range<usize>) -> &'a Self {
|
||||
&self[range]
|
||||
}
|
||||
|
||||
fn get_chars(&self, range: std::ops::Range<usize>) -> &Self {
|
||||
fn get_chars<'a>(&'a self, range: std::ops::Range<usize>) -> &'a Self {
|
||||
&self[range]
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use crate::builtins::{PyStrRef, PyTypeRef};
|
||||
use crate::builtins::pytype::PyTypeRef;
|
||||
use crate::exceptions::{self, PyBaseExceptionRef};
|
||||
use crate::frame::{ExecutionResult, FrameRef};
|
||||
use crate::pyobject::{PyObjectRef, PyResult, TypeProtocol};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
use crate::common::lock::PyMutex;
|
||||
use crate::common::lock::PyRwLock;
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
@@ -37,20 +37,20 @@ pub struct Coro {
|
||||
frame: FrameRef,
|
||||
pub closed: AtomicCell<bool>,
|
||||
running: AtomicCell<bool>,
|
||||
exceptions: PyMutex<Vec<PyBaseExceptionRef>>,
|
||||
exceptions: PyRwLock<Vec<PyBaseExceptionRef>>,
|
||||
started: AtomicCell<bool>,
|
||||
variant: Variant,
|
||||
name: PyMutex<PyStrRef>,
|
||||
}
|
||||
|
||||
impl Coro {
|
||||
pub fn new(frame: FrameRef, variant: Variant, name: PyStrRef) -> Self {
|
||||
pub fn new(frame: FrameRef, variant: Variant) -> Self {
|
||||
Coro {
|
||||
frame,
|
||||
closed: AtomicCell::new(false),
|
||||
running: AtomicCell::new(false),
|
||||
exceptions: PyMutex::new(vec![]),
|
||||
exceptions: PyRwLock::new(vec![]),
|
||||
started: AtomicCell::new(false),
|
||||
variant,
|
||||
name: PyMutex::new(name),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,20 +65,21 @@ impl Coro {
|
||||
where
|
||||
F: FnOnce(FrameRef) -> PyResult<ExecutionResult>,
|
||||
{
|
||||
if self.running.compare_exchange(false, true).is_err() {
|
||||
return Err(vm.new_value_error(format!("{} already executing", self.variant.name())));
|
||||
}
|
||||
let curr_exception_stack_len;
|
||||
{
|
||||
let mut vm_excs = vm.exceptions.borrow_mut();
|
||||
curr_exception_stack_len = vm_excs.len();
|
||||
vm_excs.append(&mut self.exceptions.lock());
|
||||
}
|
||||
self.running.store(true);
|
||||
let curr_exception_stack_len = vm.exceptions.borrow().len();
|
||||
vm.exceptions
|
||||
.borrow_mut()
|
||||
.append(&mut self.exceptions.write());
|
||||
let result = vm.with_frame(self.frame.clone(), func);
|
||||
self.exceptions
|
||||
.lock()
|
||||
.extend(vm.exceptions.borrow_mut().drain(curr_exception_stack_len..));
|
||||
std::mem::swap(
|
||||
&mut *self.exceptions.write(),
|
||||
&mut vm
|
||||
.exceptions
|
||||
.borrow_mut()
|
||||
.split_off(curr_exception_stack_len),
|
||||
);
|
||||
self.running.store(false);
|
||||
self.started.store(true);
|
||||
result
|
||||
}
|
||||
|
||||
@@ -86,16 +87,12 @@ impl Coro {
|
||||
if self.closed.load() {
|
||||
return Err(vm.new_exception_empty(self.variant.stop_iteration(vm)));
|
||||
}
|
||||
let value = if self.frame.lasti() > 0 {
|
||||
Some(value)
|
||||
} else if !vm.is_none(&value) {
|
||||
if !self.started.load() && !vm.is_none(&value) {
|
||||
return Err(vm.new_type_error(format!(
|
||||
"can't send non-None value to a just-started {}",
|
||||
self.variant.name()
|
||||
)));
|
||||
} else {
|
||||
None
|
||||
};
|
||||
}
|
||||
let result = self.run_with_context(vm, |f| f.resume(value, vm));
|
||||
self.maybe_close(&result);
|
||||
match result {
|
||||
@@ -156,6 +153,9 @@ impl Coro {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn started(&self) -> bool {
|
||||
self.started.load()
|
||||
}
|
||||
pub fn running(&self) -> bool {
|
||||
self.running.load()
|
||||
}
|
||||
@@ -165,19 +165,8 @@ impl Coro {
|
||||
pub fn frame(&self) -> FrameRef {
|
||||
self.frame.clone()
|
||||
}
|
||||
pub fn name(&self) -> PyStrRef {
|
||||
self.name.lock().clone()
|
||||
}
|
||||
pub fn set_name(&self, name: PyStrRef) {
|
||||
*self.name.lock() = name;
|
||||
}
|
||||
pub fn repr(&self, id: usize) -> String {
|
||||
format!(
|
||||
"<{} object {} at {:#x}>",
|
||||
self.variant.name(),
|
||||
self.name.lock(),
|
||||
id
|
||||
)
|
||||
pub fn name(&self) -> String {
|
||||
self.frame.code.obj_name.clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -240,13 +240,13 @@ fn write_traceback_entry<W: Write>(
|
||||
output: &mut W,
|
||||
tb_entry: &PyTracebackRef,
|
||||
) -> Result<(), W::Error> {
|
||||
let filename = tb_entry.frame.code.source_path.borrow_value();
|
||||
let filename = tb_entry.frame.code.source_path.to_owned();
|
||||
writeln!(
|
||||
output,
|
||||
r##" File "{}", line {}, in {}"##,
|
||||
filename, tb_entry.lineno, tb_entry.frame.code.obj_name
|
||||
)?;
|
||||
print_source_line(output, filename, tb_entry.lineno)?;
|
||||
print_source_line(output, &filename, tb_entry.lineno)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -660,7 +660,7 @@ impl ExceptionZoo {
|
||||
});
|
||||
|
||||
extend_class!(ctx, &excs.import_error, {
|
||||
"__init__" => ctx.new_method("__init__", import_error_init),
|
||||
"__init__" => ctx.new_method(import_error_init),
|
||||
"msg" => ctx.new_readonly_getset("msg", make_arg_getter(0)),
|
||||
});
|
||||
|
||||
@@ -669,7 +669,7 @@ impl ExceptionZoo {
|
||||
});
|
||||
|
||||
extend_class!(ctx, &excs.key_error, {
|
||||
"__str__" => ctx.new_method("__str__", key_error_str),
|
||||
"__str__" => ctx.new_method(key_error_str),
|
||||
});
|
||||
|
||||
extend_class!(ctx, &excs.unicode_decode_error, {
|
||||
|
||||
561
vm/src/frame.rs
561
vm/src/frame.rs
File diff suppressed because it is too large
Load Diff
@@ -19,10 +19,8 @@ pub fn map_frozen<'a>(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_module_inits(
|
||||
vm: &VirtualMachine,
|
||||
) -> HashMap<String, code::FrozenModule, ahash::RandomState> {
|
||||
let mut modules = HashMap::default();
|
||||
pub fn get_module_inits(vm: &VirtualMachine) -> HashMap<String, code::FrozenModule> {
|
||||
let mut modules = HashMap::new();
|
||||
|
||||
macro_rules! ext_modules {
|
||||
($($t:tt)*) => {
|
||||
|
||||
@@ -8,8 +8,8 @@ use crate::pyobject::{
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
use indexmap::IndexMap;
|
||||
use itertools::Itertools;
|
||||
use result_like::impl_option_like;
|
||||
use std::collections::HashMap;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
@@ -98,24 +98,15 @@ impl FuncArgs {
|
||||
Self { args, kwargs }
|
||||
}
|
||||
|
||||
pub fn with_kwargs_names<A, KW>(mut args: A, kwarg_names: KW) -> Self
|
||||
where
|
||||
A: ExactSizeIterator<Item = PyObjectRef>,
|
||||
KW: ExactSizeIterator<Item = String>,
|
||||
{
|
||||
pub fn with_kwargs_names(mut args: Vec<PyObjectRef>, kwarg_names: Vec<String>) -> Self {
|
||||
// last `kwarg_names.len()` elements of args in order of appearance in the call signature
|
||||
let total_argc = args.len();
|
||||
let kwargc = kwarg_names.len();
|
||||
let posargc = total_argc - kwargc;
|
||||
let kwarg_values = args.drain((args.len() - kwarg_names.len())..);
|
||||
|
||||
let posargs = args.by_ref().take(posargc).collect();
|
||||
|
||||
let kwargs = kwarg_names.zip_eq(args).collect::<IndexMap<_, _>>();
|
||||
|
||||
FuncArgs {
|
||||
args: posargs,
|
||||
kwargs,
|
||||
let mut kwargs = IndexMap::new();
|
||||
for (name, value) in kwarg_names.iter().zip(kwarg_values) {
|
||||
kwargs.insert(name.clone(), value);
|
||||
}
|
||||
FuncArgs { args, kwargs }
|
||||
}
|
||||
|
||||
pub fn prepend_arg(&mut self, item: PyObjectRef) {
|
||||
@@ -177,7 +168,9 @@ impl FuncArgs {
|
||||
self.kwargs.swap_remove(name)
|
||||
}
|
||||
|
||||
pub fn remaining_keywords(&mut self) -> impl Iterator<Item = (String, PyObjectRef)> + '_ {
|
||||
pub fn remaining_keywords<'a>(
|
||||
&'a mut self,
|
||||
) -> impl Iterator<Item = (String, PyObjectRef)> + 'a {
|
||||
self.kwargs.drain(..)
|
||||
}
|
||||
|
||||
@@ -324,9 +317,9 @@ impl<T> KwArgs<T> {
|
||||
self.0.remove(name)
|
||||
}
|
||||
}
|
||||
impl<T> std::iter::FromIterator<(String, T)> for KwArgs<T> {
|
||||
fn from_iter<I: IntoIterator<Item = (String, T)>>(iter: I) -> Self {
|
||||
KwArgs(iter.into_iter().collect())
|
||||
impl<T> From<HashMap<String, T>> for KwArgs<T> {
|
||||
fn from(kwargs: HashMap<String, T>) -> Self {
|
||||
KwArgs(kwargs.into_iter().collect())
|
||||
}
|
||||
}
|
||||
impl<T> Default for KwArgs<T> {
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::builtins::{code, list};
|
||||
#[cfg(feature = "rustpython-compiler")]
|
||||
use crate::compile;
|
||||
use crate::exceptions::PyBaseExceptionRef;
|
||||
use crate::pyobject::{BorrowValue, ItemProtocol, PyResult, PyValue, TryFromObject, TypeProtocol};
|
||||
use crate::pyobject::{ItemProtocol, PyResult, PyValue, TryFromObject, TypeProtocol};
|
||||
use crate::scope::Scope;
|
||||
use crate::version::get_git_revision;
|
||||
use crate::vm::{InitParameter, VirtualMachine};
|
||||
@@ -36,7 +36,7 @@ pub(crate) fn init_importlib(
|
||||
let install_external = vm.get_attribute(importlib, "_install_external_importers")?;
|
||||
vm.invoke(&install_external, ())?;
|
||||
// Set pyc magic number to commit hash. Should be changed when bytecode will be more stable.
|
||||
let importlib_external = vm.import("_frozen_importlib_external", None, 0)?;
|
||||
let importlib_external = vm.import("_frozen_importlib_external", &[], 0)?;
|
||||
let mut magic = get_git_revision().into_bytes();
|
||||
magic.truncate(4);
|
||||
if magic.len() != 4 {
|
||||
@@ -44,7 +44,7 @@ pub(crate) fn init_importlib(
|
||||
}
|
||||
vm.set_attr(&importlib_external, "MAGIC_NUMBER", vm.ctx.new_bytes(magic))?;
|
||||
let zipimport_res = (|| -> PyResult<()> {
|
||||
let zipimport = vm.import("zipimport", None, 0)?;
|
||||
let zipimport = vm.import("zipimport", &[], 0)?;
|
||||
let zipimporter = vm.get_attribute(zipimport, "zipimporter")?;
|
||||
let path_hooks = vm.get_attribute(vm.sys_module.clone(), "path_hooks")?;
|
||||
let path_hooks = list::PyListRef::try_from_object(vm, path_hooks)?;
|
||||
@@ -139,12 +139,12 @@ fn remove_importlib_frames_inner(
|
||||
return (None, false);
|
||||
};
|
||||
|
||||
let file_name = traceback.frame.code.source_path.borrow_value();
|
||||
let file_name = &traceback.frame.code.source_path;
|
||||
|
||||
let (inner_tb, mut now_in_importlib) =
|
||||
remove_importlib_frames_inner(vm, traceback.next.clone(), always_trim);
|
||||
if file_name == "_frozen_importlib" || file_name == "_frozen_importlib_external" {
|
||||
if traceback.frame.code.obj_name.borrow_value() == "_call_with_frames_removed" {
|
||||
if traceback.frame.code.obj_name == "_call_with_frames_removed" {
|
||||
now_in_importlib = true;
|
||||
}
|
||||
if always_trim || now_in_importlib {
|
||||
|
||||
@@ -12,7 +12,10 @@
|
||||
#![allow(clippy::module_inception)]
|
||||
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/master/logo.png")]
|
||||
#![doc(html_root_url = "https://docs.rs/rustpython-vm/")]
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![cfg_attr(
|
||||
target_os = "redox",
|
||||
feature(matches_macro, proc_macro_hygiene, result_map_or)
|
||||
)]
|
||||
|
||||
#[cfg(feature = "flame-it")]
|
||||
#[macro_use]
|
||||
@@ -22,6 +25,8 @@ extern crate flamer;
|
||||
extern crate bitflags;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
#[macro_use]
|
||||
extern crate maplit;
|
||||
// extern crate env_logger;
|
||||
|
||||
#[macro_use]
|
||||
@@ -72,7 +77,7 @@ mod vm;
|
||||
|
||||
// pub use self::pyobject::Executor;
|
||||
pub use self::vm::{InitParameter, Interpreter, PySettings, VirtualMachine};
|
||||
pub use rustpython_bytecode as bytecode;
|
||||
pub use rustpython_bytecode::*;
|
||||
pub use rustpython_common as common;
|
||||
#[cfg(feature = "rustpython-compiler")]
|
||||
pub use rustpython_compiler as compile;
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
#[macro_export]
|
||||
macro_rules! no_kwargs {
|
||||
( $vm: ident, $args:ident ) => {
|
||||
// Zero-arg case
|
||||
if $args.kwargs.len() != 0 {
|
||||
return Err($vm.new_type_error(format!(
|
||||
"Expected no keyword arguments (got: {})",
|
||||
$args.kwargs.len()
|
||||
)));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! py_module {
|
||||
( $vm:expr, $module_name:expr, { $($name:expr => $value:expr),* $(,)? }) => {{
|
||||
@@ -228,9 +241,9 @@ macro_rules! named_function {
|
||||
#[allow(unused_variables)] // weird lint, something to do with paste probably
|
||||
let ctx: &$crate::pyobject::PyContext = &$ctx;
|
||||
$crate::__exports::paste::expr! {
|
||||
ctx.make_funcdef(
|
||||
stringify!($module),
|
||||
ctx.new_function_named(
|
||||
[<$module _ $func>],
|
||||
stringify!($module).to_owned(),
|
||||
)
|
||||
.into_function()
|
||||
.with_module(ctx.new_str(stringify!($func).to_owned()))
|
||||
@@ -256,21 +269,3 @@ cfg_if::cfg_if! {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A modified version of the hashmap! macro from the maplit crate
|
||||
macro_rules! hashmap {
|
||||
(@single $($x:tt)*) => (());
|
||||
(@count $($rest:expr),*) => (<[()]>::len(&[$(hashmap!(@single $rest)),*]));
|
||||
|
||||
(hasher=$hasher:expr, $($key:expr => $value:expr,)+) => { hashmap!(hasher=$hasher, $($key => $value),+) };
|
||||
(hasher=$hasher:expr, $($key:expr => $value:expr),*) => {
|
||||
{
|
||||
let _cap = hashmap!(@count $($key),*);
|
||||
let mut _map = ::std::collections::HashMap::with_capacity_and_hasher(_cap, $hasher);
|
||||
$(
|
||||
let _ = _map.insert($key, $value);
|
||||
)*
|
||||
_map
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -30,25 +30,6 @@ impl Write for PyWriter<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_all(
|
||||
mut buf: &[u8],
|
||||
mut write: impl FnMut(&[u8]) -> io::Result<usize>,
|
||||
) -> io::Result<()> {
|
||||
while !buf.is_empty() {
|
||||
match write(buf) {
|
||||
Ok(0) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::WriteZero,
|
||||
"failed to write whole buffer",
|
||||
))
|
||||
}
|
||||
Ok(n) => buf = &buf[n..],
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn file_readline(obj: &PyObjectRef, size: Option<usize>, vm: &VirtualMachine) -> PyResult {
|
||||
let args = size.map_or_else(Vec::new, |size| vec![vm.ctx.new_int(size)]);
|
||||
let ret = vm.call_method(obj, "readline", args)?;
|
||||
|
||||
@@ -64,7 +64,7 @@ pub type PyResult<T = PyObjectRef> = Result<T, PyBaseExceptionRef>; // A valid v
|
||||
/// For attributes we do not use a dict, but a hashmap. This is probably
|
||||
/// faster, unordered, and only supports strings as keys.
|
||||
/// TODO: class attributes should maintain insertion order (use IndexMap here)
|
||||
pub type PyAttributes = HashMap<String, PyObjectRef, ahash::RandomState>;
|
||||
pub type PyAttributes = HashMap<String, PyObjectRef>;
|
||||
|
||||
// TODO: remove this impl
|
||||
impl fmt::Display for PyObjectRef {
|
||||
@@ -133,9 +133,8 @@ impl PyContext {
|
||||
|
||||
let string_cache = Dict::default();
|
||||
|
||||
let new_str = PyRef::new_ref(pystr::PyStr::from("__new__"), types.str_type.clone(), None);
|
||||
let tp_new_wrapper = create_object(
|
||||
PyNativeFuncDef::new(pytype::tp_new_wrapper.into_func(), new_str).into_function(),
|
||||
PyNativeFuncDef::from(pytype::tp_new_wrapper.into_func()).into_function(),
|
||||
&types.builtin_function_or_method_type,
|
||||
)
|
||||
.into_object();
|
||||
@@ -274,44 +273,45 @@ impl PyContext {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_function<F, FKind>(&self, f: F) -> PyObjectRef
|
||||
where
|
||||
F: IntoPyNativeFunc<FKind>,
|
||||
{
|
||||
PyNativeFuncDef::from(f.into_func()).build_function(self)
|
||||
}
|
||||
|
||||
pub(crate) fn new_stringref(&self, s: String) -> pystr::PyStrRef {
|
||||
PyRef::new_ref(pystr::PyStr::from(s), self.types.str_type.clone(), None)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn make_funcdef<F, FKind>(&self, name: impl Into<String>, f: F) -> PyNativeFuncDef
|
||||
pub fn new_function_named<F, FKind>(&self, f: F, name: String) -> PyNativeFuncDef
|
||||
where
|
||||
F: IntoPyNativeFunc<FKind>,
|
||||
{
|
||||
PyNativeFuncDef::new(f.into_func(), self.new_stringref(name.into()))
|
||||
let mut f = PyNativeFuncDef::from(f.into_func());
|
||||
f.name = Some(self.new_stringref(name));
|
||||
f
|
||||
}
|
||||
|
||||
pub fn new_function<F, FKind>(&self, name: impl Into<String>, f: F) -> PyObjectRef
|
||||
pub fn new_method<F, FKind>(&self, f: F) -> PyObjectRef
|
||||
where
|
||||
F: IntoPyNativeFunc<FKind>,
|
||||
{
|
||||
self.make_funcdef(name, f).build_function(self)
|
||||
PyNativeFuncDef::from(f.into_func()).build_method(self)
|
||||
}
|
||||
|
||||
pub fn new_method<F, FKind>(&self, name: impl Into<String>, f: F) -> PyObjectRef
|
||||
pub fn new_classmethod<F, FKind>(&self, f: F) -> PyObjectRef
|
||||
where
|
||||
F: IntoPyNativeFunc<FKind>,
|
||||
{
|
||||
self.make_funcdef(name, f).build_method(self)
|
||||
PyNativeFuncDef::from(f.into_func()).build_classmethod(self)
|
||||
}
|
||||
|
||||
pub fn new_classmethod<F, FKind>(&self, name: impl Into<String>, f: F) -> PyObjectRef
|
||||
where
|
||||
F: IntoPyNativeFunc<FKind>,
|
||||
{
|
||||
self.make_funcdef(name, f).build_classmethod(self)
|
||||
}
|
||||
pub fn new_staticmethod<F, FKind>(&self, name: impl Into<String>, f: F) -> PyObjectRef
|
||||
pub fn new_staticmethod<F, FKind>(&self, f: F) -> PyObjectRef
|
||||
where
|
||||
F: IntoPyNativeFunc<FKind>,
|
||||
{
|
||||
PyObject::new(
|
||||
PyStaticMethod::from(self.new_method(name, f)),
|
||||
PyStaticMethod::from(self.new_method(f)),
|
||||
self.types.staticmethod_type.clone(),
|
||||
None,
|
||||
)
|
||||
@@ -763,7 +763,6 @@ pub trait TryIntoRef<T: PyObjectPayload> {
|
||||
}
|
||||
|
||||
impl<T: PyObjectPayload> TryIntoRef<T> for PyRef<T> {
|
||||
#[inline]
|
||||
fn try_into_ref(self, _vm: &VirtualMachine) -> PyResult<PyRef<T>> {
|
||||
Ok(self)
|
||||
}
|
||||
@@ -1104,11 +1103,9 @@ pub trait PyClassImpl: PyClassDef {
|
||||
fn extend_slots(slots: &mut PyTypeSlots);
|
||||
|
||||
fn make_slots() -> PyTypeSlots {
|
||||
let mut slots = PyTypeSlots {
|
||||
flags: Self::TP_FLAGS,
|
||||
name: PyRwLock::new(Some(Self::TP_NAME.to_owned())),
|
||||
..Default::default()
|
||||
};
|
||||
let mut slots = PyTypeSlots::default();
|
||||
slots.flags = Self::TP_FLAGS;
|
||||
slots.name = PyRwLock::new(Some(Self::TP_NAME.to_owned()));
|
||||
Self::extend_slots(&mut slots);
|
||||
slots
|
||||
}
|
||||
|
||||
@@ -317,7 +317,7 @@ impl Drop for PyObjectRef {
|
||||
Ok(v) => println!("{}", v.to_string()),
|
||||
Err(_) => println!("{}", del_method.class().name),
|
||||
}
|
||||
let tb_module = vm.import("traceback", None, 0).unwrap();
|
||||
let tb_module = vm.import("traceback", &[], 0).unwrap();
|
||||
// TODO: set exc traceback
|
||||
let print_stack = vm.get_attribute(tb_module, "print_stack").unwrap();
|
||||
vm.invoke(&print_stack, ()).unwrap();
|
||||
@@ -489,7 +489,7 @@ pub(crate) fn init_type_hierarchy() -> (PyTypeRef, PyTypeRef) {
|
||||
bases: vec![],
|
||||
mro: vec![],
|
||||
subclasses: PyRwLock::default(),
|
||||
attributes: PyRwLock::new(PyAttributes::default()),
|
||||
attributes: PyRwLock::new(PyAttributes::new()),
|
||||
slots: PyType::make_slots(),
|
||||
};
|
||||
let object_payload = PyType {
|
||||
@@ -498,7 +498,7 @@ pub(crate) fn init_type_hierarchy() -> (PyTypeRef, PyTypeRef) {
|
||||
bases: vec![],
|
||||
mro: vec![],
|
||||
subclasses: PyRwLock::default(),
|
||||
attributes: PyRwLock::new(PyAttributes::default()),
|
||||
attributes: PyRwLock::new(PyAttributes::new()),
|
||||
slots: object::PyBaseObject::make_slots(),
|
||||
};
|
||||
let type_type = PyRc::new(partially_init!(
|
||||
|
||||
@@ -391,7 +391,7 @@ impl TryFromObject for SequenceIndex {
|
||||
// Use PySliceableSequence::wrap_index for implementors
|
||||
pub(crate) fn wrap_index(p: isize, len: usize) -> Option<usize> {
|
||||
let neg = p.is_negative();
|
||||
let p = p.wrapping_abs() as usize;
|
||||
let p = p.abs().to_usize()?;
|
||||
if neg {
|
||||
len.checked_sub(p)
|
||||
} else if p >= len {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use crate::builtins::bytes::PyBytesRef;
|
||||
use crate::builtins::code::PyCode;
|
||||
use crate::builtins::module::PyModuleRef;
|
||||
use crate::builtins::pystr::{self, PyStr, PyStrRef};
|
||||
use crate::builtins::pystr;
|
||||
use crate::builtins::pystr::PyStrRef;
|
||||
use crate::import;
|
||||
use crate::pyobject::{BorrowValue, ItemProtocol, PyObjectRef, PyResult, PyValue};
|
||||
use crate::pyobject::{BorrowValue, ItemProtocol, PyObjectRef, PyResult};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
#[cfg(feature = "threading")]
|
||||
@@ -81,7 +82,7 @@ fn _imp_get_frozen_object(name: PyStrRef, vm: &VirtualMachine) -> PyResult<PyCod
|
||||
.get(name.borrow_value())
|
||||
.map(|frozen| {
|
||||
let mut frozen = frozen.code.clone();
|
||||
frozen.source_path = PyStr::from(format!("frozen {}", name)).into_ref(vm);
|
||||
frozen.source_path = format!("frozen {}", name);
|
||||
PyCode::new(frozen)
|
||||
})
|
||||
.ok_or_else(|| vm.new_import_error(format!("No such frozen object named {}", name), name))
|
||||
|
||||
@@ -984,7 +984,10 @@ mod decl {
|
||||
args: ProductArgs,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<PyRef<Self>> {
|
||||
let repeat = args.repeat.unwrap_or(1);
|
||||
let repeat = match args.repeat.into_option() {
|
||||
Some(i) => i,
|
||||
None => 1,
|
||||
};
|
||||
|
||||
let mut pools = Vec::new();
|
||||
for arg in iterables.into_iter() {
|
||||
|
||||
@@ -39,7 +39,6 @@ static ESCAPE_CHARS: [&str; 0x20] = [
|
||||
// And which one need to be escaped (1)
|
||||
// The characters that need escaping are 0x00 to 0x1F, 0x22 ("), 0x5C (\), 0x7F (DEL)
|
||||
// Non-ASCII unicode characters can be safely included in a JSON string
|
||||
#[allow(clippy::unusual_byte_groupings)] // it's groups of 16, come on clippy
|
||||
static NEEDS_ESCAPING_BITSET: [u64; 4] = [
|
||||
//fedcba9876543210_fedcba9876543210_fedcba9876543210_fedcba9876543210
|
||||
0b0000000000000000_0000000000000100_1111111111111111_1111111111111111, // 3_2_1_0
|
||||
|
||||
@@ -6,18 +6,21 @@ mod decl {
|
||||
use rustpython_parser::lexer;
|
||||
|
||||
use crate::builtins::pystr::PyStrRef;
|
||||
use crate::pyobject::{BorrowValue, PyObjectRef};
|
||||
use crate::pyobject::{BorrowValue, PyObjectRef, PyResult};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
#[pyfunction]
|
||||
fn iskeyword(s: PyStrRef) -> bool {
|
||||
lexer::KEYWORDS.contains_key(s.borrow_value())
|
||||
fn iskeyword(s: PyStrRef, vm: &VirtualMachine) -> PyResult {
|
||||
let keywords = lexer::get_keywords();
|
||||
let value = keywords.contains_key(s.borrow_value());
|
||||
let value = vm.ctx.new_bool(value);
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
fn kwlist(vm: &VirtualMachine) -> PyObjectRef {
|
||||
vm.ctx.new_list(
|
||||
lexer::KEYWORDS
|
||||
lexer::get_keywords()
|
||||
.keys()
|
||||
.map(|k| vm.ctx.new_str(k.to_owned()))
|
||||
.collect(),
|
||||
|
||||
@@ -23,14 +23,8 @@ mod decl {
|
||||
|
||||
#[pyfunction]
|
||||
fn loads(code_bytes: PyBytesLike, vm: &VirtualMachine) -> PyResult<PyCode> {
|
||||
let code =
|
||||
bytecode::CodeObject::from_bytes(&*code_bytes.borrow_value()).map_err(|e| match e {
|
||||
bytecode::CodeDeserializeError::Eof => vm.new_exception_msg(
|
||||
vm.ctx.exceptions.eof_error.clone(),
|
||||
"end of file while deserializing bytecode".to_owned(),
|
||||
),
|
||||
_ => vm.new_value_error("Couldn't deserialize python bytecode".to_owned()),
|
||||
})?;
|
||||
let code = bytecode::CodeObject::from_bytes(&*code_bytes.borrow_value())
|
||||
.map_err(|_| vm.new_value_error("Couldn't deserialize python bytecode".to_owned()))?;
|
||||
Ok(PyCode {
|
||||
code: vm.map_codeobj(code),
|
||||
})
|
||||
|
||||
@@ -5,12 +5,13 @@
|
||||
|
||||
use num_bigint::BigInt;
|
||||
use num_traits::{One, Signed, Zero};
|
||||
use puruspe::{erf, erfc, gamma, ln_gamma};
|
||||
use statrs::function::erf::{erf, erfc};
|
||||
use statrs::function::gamma::{gamma, ln_gamma};
|
||||
|
||||
use crate::builtins::float::{self, IntoPyFloat, PyFloatRef};
|
||||
use crate::builtins::int::{self, PyInt, PyIntRef};
|
||||
use crate::function::{Args, OptionalArg};
|
||||
use crate::pyobject::{BorrowValue, Either, PyIterable, PyObjectRef, PyResult, TypeProtocol};
|
||||
use crate::pyobject::{BorrowValue, Either, PyObjectRef, PyResult, TypeProtocol};
|
||||
use crate::vm::VirtualMachine;
|
||||
use rustpython_common::float_ops;
|
||||
|
||||
@@ -371,104 +372,6 @@ fn math_lcm(args: Args<PyIntRef>) -> BigInt {
|
||||
math_perf_arb_len_int_op(args, |x, y| x.lcm(y.borrow_value()), BigInt::one())
|
||||
}
|
||||
|
||||
fn math_fsum(iter: PyIterable<IntoPyFloat>, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
let mut partials = vec![];
|
||||
let mut special_sum = 0.0;
|
||||
let mut inf_sum = 0.0;
|
||||
|
||||
for obj in iter.iter(vm)? {
|
||||
let mut x = obj?.to_f64();
|
||||
|
||||
let xsave = x;
|
||||
let mut j = 0;
|
||||
// This inner loop applies `hi`/`lo` summation to each
|
||||
// partial so that the list of partial sums remains exact.
|
||||
for i in 0..partials.len() {
|
||||
let mut y: f64 = partials[i];
|
||||
if x.abs() < y.abs() {
|
||||
std::mem::swap(&mut x, &mut y);
|
||||
}
|
||||
// Rounded `x+y` is stored in `hi` with round-off stored in
|
||||
// `lo`. Together `hi+lo` are exactly equal to `x+y`.
|
||||
let hi = x + y;
|
||||
let lo = y - (hi - x);
|
||||
if lo != 0.0 {
|
||||
partials[j] = lo;
|
||||
j += 1;
|
||||
}
|
||||
x = hi;
|
||||
}
|
||||
|
||||
if !x.is_finite() {
|
||||
// a nonfinite x could arise either as
|
||||
// a result of intermediate overflow, or
|
||||
// as a result of a nan or inf in the
|
||||
// summands
|
||||
if xsave.is_finite() {
|
||||
return Err(vm.new_overflow_error("intermediate overflow in fsum".to_owned()));
|
||||
}
|
||||
if xsave.is_infinite() {
|
||||
inf_sum += xsave;
|
||||
}
|
||||
special_sum += xsave;
|
||||
// reset partials
|
||||
partials.clear();
|
||||
}
|
||||
|
||||
if j >= partials.len() {
|
||||
partials.push(x);
|
||||
} else {
|
||||
partials[j] = x;
|
||||
partials.truncate(j + 1);
|
||||
}
|
||||
}
|
||||
if special_sum != 0.0 {
|
||||
return if inf_sum.is_nan() {
|
||||
Err(vm.new_overflow_error("-inf + inf in fsum".to_owned()))
|
||||
} else {
|
||||
Ok(special_sum)
|
||||
};
|
||||
}
|
||||
|
||||
let mut n = partials.len();
|
||||
if n > 0 {
|
||||
n -= 1;
|
||||
let mut hi = partials[n];
|
||||
|
||||
let mut lo = 0.0;
|
||||
while n > 0 {
|
||||
let x = hi;
|
||||
|
||||
n -= 1;
|
||||
let y = partials[n];
|
||||
|
||||
hi = x + y;
|
||||
lo = y - (hi - x);
|
||||
if lo != 0.0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if n > 0 && ((lo < 0.0 && partials[n - 1] < 0.0) || (lo > 0.0 && partials[n - 1] > 0.0)) {
|
||||
let y = lo + lo;
|
||||
let x = hi + y;
|
||||
|
||||
// Make half-even rounding work across multiple partials.
|
||||
// Needed so that sum([1e-16, 1, 1e16]) will round-up the last
|
||||
// digit to two instead of down to zero (the 1e-16 makes the 1
|
||||
// slightly closer to two). With a potential 1 ULP rounding
|
||||
// error fixed-up, math.fsum() can guarantee commutativity.
|
||||
#[allow(clippy::float_cmp)]
|
||||
if y == x - hi {
|
||||
hi = x;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(hi)
|
||||
} else {
|
||||
Ok(0.0)
|
||||
}
|
||||
}
|
||||
|
||||
fn math_factorial(value: PyIntRef, vm: &VirtualMachine) -> PyResult<BigInt> {
|
||||
let value = value.borrow_value();
|
||||
if value.is_negative() {
|
||||
@@ -613,7 +516,6 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
"ldexp" => named_function!(ctx, math, ldexp),
|
||||
"modf" => named_function!(ctx, math, modf),
|
||||
"fmod" => named_function!(ctx, math, fmod),
|
||||
"fsum" => named_function!(ctx, math, fsum),
|
||||
"remainder" => named_function!(ctx, math, remainder),
|
||||
|
||||
// Rounding functions:
|
||||
|
||||
@@ -71,10 +71,9 @@ mod zlib;
|
||||
|
||||
pub type StdlibInitFunc = Box<py_dyn_fn!(dyn Fn(&VirtualMachine) -> PyObjectRef)>;
|
||||
|
||||
pub fn get_module_inits() -> HashMap<String, StdlibInitFunc, ahash::RandomState> {
|
||||
pub fn get_module_inits() -> HashMap<String, StdlibInitFunc> {
|
||||
#[allow(unused_mut)]
|
||||
let mut modules = hashmap! {
|
||||
hasher = ahash::RandomState::default(),
|
||||
"array".to_owned() => Box::new(array::make_module) as StdlibInitFunc,
|
||||
"atexit".to_owned() => Box::new(atexit::make_module),
|
||||
"binascii".to_owned() => Box::new(binascii::make_module),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user