diff --git a/Cargo.lock b/Cargo.lock index 300752a8a..028058eae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,7 +15,7 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -29,22 +29,13 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "argon2rs" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "arr_macro" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arr_macro_impl 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -52,11 +43,16 @@ name = "arr_macro_impl" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayref" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "arrayvec" version = "0.4.11" @@ -78,7 +74,7 @@ name = "atty" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -89,13 +85,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -103,8 +99,16 @@ name = "backtrace-sys" version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "base64" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -114,7 +118,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -143,14 +147,15 @@ dependencies = [ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "blake2-rfc" -version = "0.2.18" +name = "blake2b_simd" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -199,13 +204,13 @@ name = "caseless" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.37" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -255,7 +260,7 @@ name = "cpython" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "python3-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -281,6 +286,15 @@ name = "crossbeam-utils" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "crossbeam-utils" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crypto-mac" version = "0.7.0" @@ -308,8 +322,8 @@ name = "dirs" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -319,8 +333,8 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -334,7 +348,7 @@ name = "ena" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -344,8 +358,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -354,7 +368,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -365,7 +379,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -385,8 +399,8 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -398,7 +412,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "flame 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -408,19 +422,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "flame 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "flate2" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide_c_api 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -451,7 +465,7 @@ name = "gethostname" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -501,10 +515,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "js-sys" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "wasm-bindgen 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -535,10 +549,10 @@ dependencies = [ "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "lalrpop-util 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -562,29 +576,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lexical" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "lexical-core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lexical-core 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "lexical-core" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "stackvector 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "libc" -version = "0.2.60" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -592,8 +606,8 @@ name = "libz-sys" version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -603,12 +617,12 @@ name = "log" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "log" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -631,7 +645,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -647,17 +661,6 @@ dependencies = [ "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "miniz_oxide_c_api" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "new_debug_unreachable" version = "1.0.3" @@ -669,9 +672,9 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -681,9 +684,9 @@ version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -708,7 +711,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -717,7 +720,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -748,12 +751,12 @@ name = "num_cpus" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "opaque-debug" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -799,12 +802,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro-hack" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -815,13 +818,21 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pwd" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -829,8 +840,8 @@ name = "python3-sys" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -846,6 +857,14 @@ dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quote" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand" version = "0.5.6" @@ -853,7 +872,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -864,9 +883,9 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -890,12 +909,12 @@ name = "rand_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -919,8 +938,8 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -931,8 +950,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -943,7 +962,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -969,13 +988,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "redox_users" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -987,19 +1006,18 @@ dependencies = [ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.1.9" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1007,20 +1025,27 @@ name = "regex-syntax" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.8" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rust-argon2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1049,7 +1074,7 @@ dependencies = [ "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "flame 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "flamescope 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustpython-compiler 0.1.0", "rustpython-parser 0.1.0", "rustpython-vm 0.1.0", @@ -1064,7 +1089,7 @@ dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1085,12 +1110,12 @@ version = "0.1.0" dependencies = [ "bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "rustpython-bytecode 0.1.0", "rustpython-compiler 0.1.0", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1099,7 +1124,7 @@ version = "0.1.0" dependencies = [ "lalrpop 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)", "lalrpop-util 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1125,15 +1150,16 @@ dependencies = [ "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "flame 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "flamer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "gethostname 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hexf-parse 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lexical 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "lexical 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1145,16 +1171,16 @@ dependencies = [ "num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "pwd 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version_runtime 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustpython-bytecode 0.1.0", "rustpython-compiler 0.1.0", "rustpython-derive 0.1.0", "rustpython-parser 0.1.0", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1176,16 +1202,16 @@ version = "0.1.0-pre-alpha.2" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustpython-compiler 0.1.0", "rustpython-parser 0.1.0", "rustpython-vm 0.1.0", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", "serde-wasm-bindgen 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-futures 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-futures 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1194,8 +1220,8 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1204,21 +1230,11 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ryu" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "ryu" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "scoped_threadpool" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "semver" version = "0.9.0" @@ -1234,10 +1250,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1246,19 +1262,19 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1268,7 +1284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1279,7 +1295,7 @@ dependencies = [ "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1290,7 +1306,7 @@ dependencies = [ "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1302,7 +1318,7 @@ dependencies = [ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1331,7 +1347,7 @@ dependencies = [ [[package]] name = "static_assertions" -version = "0.2.5" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1351,7 +1367,7 @@ dependencies = [ "new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1389,7 +1405,7 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1400,7 +1416,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.39" +version = "0.15.44" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1408,6 +1424,16 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "synstructure" version = "0.10.2" @@ -1415,7 +1441,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1449,7 +1475,7 @@ name = "thread-id" version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1467,7 +1493,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1479,7 +1505,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ucd-util" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1778,6 +1804,11 @@ name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode_categories" version = "0.1.1" @@ -1798,7 +1829,7 @@ dependencies = [ [[package]] name = "utf8-ranges" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1828,87 +1859,90 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wasm-bindgen" -version = "0.2.48" +version = "0.2.49" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "wasm-bindgen-macro 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.48" +version = "0.2.49" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bumpalo 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-futures" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.48" +version = "0.2.49" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro-support 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro-support 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.48" +version = "0.2.49" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-backend 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.48" +version = "0.2.49" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wasm-bindgen-webidl" -version = "0.2.48" +version = "0.2.49" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-backend 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "web-sys" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "js-sys 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", "sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-webidl 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-webidl 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1978,23 +2012,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" -"checksum aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b7aa1ccb7d7ea3f437cf025a2ab1c47cc6c1bc9fc84918ff449def12f5e282" +"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" "checksum arr_macro 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d262b83f2f573121554ad6e764cd444303df85d86e5fcebc81903ddcf8dd3a97" "checksum arr_macro_impl 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8decbe97ffec939e44228d91e5d0829ceb1616c6ed0984c09df164b1e7ebaafc" +"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" "checksum ascii-canvas 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b385d69402821a1c254533a011a312531cbcc0e3e24f19bbb4747a5a2daf37e2" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "checksum autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "22130e92352b948e7e82a49cdb0aa94f2211761117f29e052dd397c1ac33542b" -"checksum backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)" = "88fb679bc9af8fa639198790a77f52d345fe13656c08b43afa9424c206b731c6" +"checksum backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)" = "b5164d292487f037ece34ec0de2fcede2faa162f085dd96d2385ab81b12765ba" "checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" +"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9f04a5e50dc80b3d5d35320889053637d15011aed5e66b66b37ae798c65da6f7" "checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80" "checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb" "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" "checksum blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91721a6330935673395a0607df4d49a9cb90ae12d259f1b3e0a3f6e1d486872e" -"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +"checksum blake2b_simd 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "461f4b879a8eb70c1debf7d0788a9a5ff15f1ea9d25925fea264ef4258bed6b2" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" @@ -2002,7 +2037,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum caseless 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "808dab3318747be122cb31d36de18d4d1c81277a76f8332a02b81a3d73463d7f" -"checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d" +"checksum cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "b548a4ee81fccb95919d4e22cfea83c7693ebfd78f0495493178db20b3139da7" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" @@ -2012,6 +2047,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" +"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" "checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" @@ -2027,7 +2063,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum flame 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1fc2706461e1ee94f55cab2ed2e3d34ae9536cfa830358ef80acff1a3dacab30" "checksum flamer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f2add1a5e84b1ed7b5d00cdc21789a28e0a8f4e427b677313c773880ba3c4dac" "checksum flamescope 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e3e6aee625a28b97be4308bccc2eb5f81d9ec606b3f29e13c0f459ce20dd136" -"checksum flate2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "550934ad4808d5d39365e5d61727309bf18b3b02c6c56b729cb92e7dd84bc3d8" +"checksum flate2 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "2adaffba6388640136149e18ed080b77a78611c1e1d6de75aedcdf78df5d4682" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" @@ -2040,25 +2076,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -"checksum js-sys 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)" = "da3ea71161651a4cd97d999b2da139109c537b15ab33abc8ae4ead38deac8a03" +"checksum js-sys 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)" = "6d8b890eaeb07a808716d52cf7bbac692ba94ddfc5834071f5c73ce30fecf946" "checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lalrpop 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4e2e80bee40b22bca46665b4ef1f3cd88ed0fb043c971407eac17a0712c02572" "checksum lalrpop-util 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)" = "33b27d8490dbe1f9704b0088d61e8d46edc10d5673a8829836c6ded26a9912c7" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum lexical 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93de1b2ed9c7f01aac327bf84542a053b6cd15761defdcfaceb27e1d1b871e74" -"checksum lexical-core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3f8673fab7063c2cac37d299c8a1a7beb720e78f71500098e4a3c137fdf025bf" -"checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb" +"checksum lexical 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e0d09e60c187a6d0a3fa418aec8587c6a4ae9de872f6126f2134f319b5ed10d" +"checksum lexical-core 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b0f90c979adde96d19eb10eb6431ba0c441e2f9e9bdff868b2f6f5114ff519" +"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" "checksum libz-sys 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -"checksum log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c275b6ad54070ac2d665eef9197db647b32239c9d244bfb6f041a766d00da5b3" +"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum md-5 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a18af3dcaf2b0219366cdb4e2af65a6101457b415c3d1a5c71dd9c2b7c77b9c8" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum miniz_oxide 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7108aff85b876d06f22503dcce091e29f76733b2bfdd91eebce81f5e68203a10" -"checksum miniz_oxide_c_api 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6c675792957b0d19933816c4e1d56663c341dd9bfa31cb2140ff2267c1d8ecf4" "checksum new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30" "checksum nix 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4dbdc256eaac2e3bd236d93ad999d3479ef775c863dbda3068c4006a92eec51b" "checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce" @@ -2070,24 +2105,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" -"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" +"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" "checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" "checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" "checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -"checksum proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "982a35d1194084ba319d65c4a68d24ca28f5fdb5b8bc20899e4eef8641ea5178" +"checksum proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e688f31d92ffd7c1ddc57a1b4e6d773c0f2a14ee437a4b0a4f5a69c80eb221c8" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum proc-macro2 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "19f287c234c9b2d0308d692dee5c449c1a171167a6f8150f7cf2a49d8fd96967" "checksum pwd 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5dd32d8bece608e144ca20251e714ed107cdecdabb20c2d383cfc687825106a5" "checksum python3-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "61e4aac43f833fd637e429506cb2ac9d7df672c4b68f2eaaa163649b7fdc0444" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +"checksum quote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ab938ebe6f1c82426b5fb82eaf10c3e3028c53deaa3fbe38f5904b37cf4d767" "checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" @@ -2096,23 +2133,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -"checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" +"checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d" "checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" -"checksum regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d9d8297cc20bbb6184f8b45ff61c8ee6a9ac56c156cec8e38c3e5084773c44ad" +"checksum regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88c3d9193984285d544df4a30c23a4e62ead42edf70a4452ceb76dac1ce05c26" "checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" -"checksum regex-syntax 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9b01330cce219c1c6b2e209e5ed64ccd587ae5c67bed91c0b49eecf02ae40e21" -"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" +"checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f" +"checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" +"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum rustc_version_runtime 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6de8ecd7fad7731f306f69b6e10ec5a3178c61e464dcc06979427aa4cc891145" "checksum rustyline 4.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f47ea1ceb347d2deae482d655dc8eef4bd82363d3329baffa3818bd76fea48b" -"checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f" "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" -"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)" = "d46b3dfedb19360a74316866cef04687cd4d6a70df8e6a506c63512790769b72" +"checksum serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5626ac617da2f2d9c48af5515a21d5a480dbd151e01bb1c355e26a3e68113" "checksum serde-wasm-bindgen 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7ee6f12f7ed0e7ad2e55200da37dbabc2cadeb942355c5b629aa3771f5ac5636" -"checksum serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)" = "c22a0820adfe2f257b098714323563dd06426502abbbce4f51b72ef544c5027f" +"checksum serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "01e69e1b8a631f245467ee275b8c757b818653c6d704cdbcaeb56b56767b529c" "checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" @@ -2121,7 +2157,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" "checksum stackvector 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4725650978235083241fab0fdc8e694c3de37821524e7534a1a9061d1068af" -"checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" +"checksum static_assertions 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7f3eb36b47e512f8f1c9e3d10c2c1965bc992bd9cdb024fa581e2194501c83d3" "checksum statrs 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "10102ac8d55e35db2b3fafc26f81ba8647da2e15879ab686a67e6d19af2685e8" "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" "checksum string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eea1eee654ef80933142157fdad9dd8bc43cf7c74e999e369263496f04ff4da" @@ -2130,7 +2166,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "032c03039aae92b350aad2e3779c352e104d919cb192ba2fabbd7b831ce4f0f6" "checksum subprocess 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "28fc0f40f0c0da73339d347aa7d6d2b90341a95683a47722bc4eebed71ff3c00" "checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" -"checksum syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d960b829a55e56db167e861ddb43602c003c7be0bee1d345021703fac2fb7c" +"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +"checksum syn 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "863ecbce06044c8380458360b4146d7372edadfedd77f120ba8c193da427b708" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" @@ -2139,7 +2176,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" -"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" +"checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874" "checksum unic 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e31748f3e294dc6a9243a44686e8155a162af9a11cd56e07c0ebbc530b2a8a87" "checksum unic-bidi 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1356b759fb6a82050666f11dce4b6fe3571781f1449f3ef78074e408d468ec09" "checksum unic-char 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "af25df79bd134107f088ba725d9c470600f16263205d0be36c75e75b020bac0a" @@ -2173,23 +2210,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" "checksum unicode_names2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dc6c5da0c8d7200f9488cc346bd30ba62bcd9f79ef937ea6573132e3d507df9" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9d50aa7650df78abf942826607c62468ce18d9019673d4a2ebe1865dbb96ffde" +"checksum utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" "checksum utf8parse 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d" "checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum wasm-bindgen 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "4de97fa1806bb1a99904216f6ac5e0c050dc4f8c676dc98775047c38e5c01b55" -"checksum wasm-bindgen-backend 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "5d82c170ef9f5b2c63ad4460dfcee93f3ec04a9a36a4cc20bc973c39e59ab8e3" -"checksum wasm-bindgen-futures 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)" = "73c25810ee684c909488c214f55abcbc560beb62146d352b9588519e73c2fed9" -"checksum wasm-bindgen-macro 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "f07d50f74bf7a738304f6b8157f4a581e1512cd9e9cdb5baad8c31bbe8ffd81d" -"checksum wasm-bindgen-macro-support 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "95cf8fe77e45ba5f91bc8f3da0c3aa5d464b3d8ed85d84f4d4c7cc106436b1d7" -"checksum wasm-bindgen-shared 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "d9c2d4d4756b2e46d3a5422e06277d02e4d3e1d62d138b76a4c681e925743623" -"checksum wasm-bindgen-webidl 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "24e47859b4eba3d3b9a5c2c299f9d6f8d0b613671315f6f0c5c7f835e524b36a" -"checksum web-sys 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)" = "86d515d2f713d3a6ab198031d2181b7540f8e319e4637ec2d4a41a208335ef29" +"checksum wasm-bindgen 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "220f01bcb6b306c063e3283f97dd974bcab4e5affed2b654bae1a22d0d99c3aa" +"checksum wasm-bindgen-backend 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "8894c95e23cc5082786192ebbd2ac0e31e9f77a022132ba03e8b8de32a2323c6" +"checksum wasm-bindgen-futures 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)" = "8fe2e3e8dfd437dd655c4afb3669ebb0c1578589b1398e4c1290510bf2d0dcc2" +"checksum wasm-bindgen-macro 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "ec031a3190c51dda28c9f3623e2674e58c79f6d88c020c2157417fcf62298a3f" +"checksum wasm-bindgen-macro-support 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "3b7cad0ab0bb5fefbb770279f522dcebb6433585174d93ea648390f61db57401" +"checksum wasm-bindgen-shared 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "9142625bbb0d70710b3f2a6b20924c80fa182b05888b6bd21600ab9075673563" +"checksum wasm-bindgen-webidl 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "dee8bd6c81fece9e27f2760c9dc4d77f6ba2cbccd08c61f0809978eaadf437c9" +"checksum web-sys 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)" = "8ac9f9c7ecae816e16e92a8c646ff78d5314b1c94e838f7b8d1a7e06b6cefefc" "checksum weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 9fd818536..7ddf53fc6 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -1,9 +1,91 @@ # RustPython Development Guide and Tips +RustPython attracts developers with interest and experience in Rust, Python, +or WebAssembly. Whether you are familiar with Rust, Python, or +WebAssembly, the goal of this Development Guide is to give you the basics to +get set up for developing RustPython and contributing to this project. + +The contents of the Development Guide include: + +- [Setting up a development environment](#setting-up-a-development-environment) +- [Code style](#code-style) +- [Testing](#testing) +- [Profiling](#profiling) +- [Code organization](#code-organization) +- [Understanding internals](#understanding-internals) +- [Questions](#questions) + +## Setting up a development environment + +RustPython requires the following: + +- Rust 1.36 or higher + - To check Rust version: `rustc --version` + - If you have `rustup` on your system, enter to update to the latest + stable version: `rustup update stable` + - If you do not have Rust installed, use [rustup](https://rustup.rs/) to + do so. +- CPython version 3.7.4 or higher + - CPython can be installed by your operating system's package manager, + from the [Python website](https://www.python.org/downloads/), or + using a third-party distribution, such as + [Anaconda](https://www.anaconda.com/distribution/). +- [Optional] The Python package, `pytest`, is used for testing Python code + snippets. To install, enter `python3 -m pip install pytest`. + +## Code style + +The Rust code style used is the default +[rustfmt](https://github.com/rust-lang/rustfmt) codestyle. Please format your +code accordingly. We also use [clippy](https://github.com/rust-lang/rust-clippy) +to detect rust code issues. + +Python code should follow the +[PEP 8](https://www.python.org/dev/peps/pep-0008/) style. We also use +[flake8](http://flake8.pycqa.org/en/latest/) to check Python code style. + +## Testing + +To test RustPython's functionality, a collection of Python snippets is located +in the `tests/snippets` directory and can be run using `pytest`: + +```shell +$ cd tests +$ pytest -v +``` + +Rust unit tests can be run with `cargo`: + +```shell +$ cargo test --all +``` + +## Profiling + +To profile RustPython, build it in `release` mode with the `flame-it` feature. +This will generate a file `flamescope.json`, which can be viewed at +https://speedscope.app. + +```shell +$ cargo run --release --features flame-it script.py +$ cat flamescope.json +{} +``` + +You can specify another file name other than the default by using the +`--output-file` option to specify a file name (or `stdout` if you specify `-`). +The `--output-format` option determines the format of the output file. +The speedscope json format (default), text, or raw html can be passed. There +exists a raw html viewer which is currently broken, and we welcome a PR to fix it. + ## Code organization +Understanding a new codebase takes time. Here's a brief view of the +repository's structure: + - `bytecode/src`: python bytecode representation in rust structures - `compiler/src`: python compilation to bytecode +- `derive/src`: Rust language extensions and macros specific to rustpython - `parser/src`: python lexing, parsing and ast - `Lib`: Carefully selected / copied files from CPython sourcecode. This is the python side of the standard library. @@ -19,42 +101,67 @@ - `wasm`: Binary crate and resources for WebAssembly build - `tests`: integration test snippets -## Code style +## Understanding Internals -The code style used is the default -[rustfmt](https://github.com/rust-lang/rustfmt) codestyle. Please format your -code accordingly. We also use [clippy](https://github.com/rust-lang/rust-clippy) -to detect rust code issues. +The RustPython workspace includes the `rustpython` top-level crate. The `Cargo.toml` +file in the root of the repo provide configuration of the crate and the +implementation is found in the `src` directory (specifically, +`src/main.rs`). -## Testing +The top-level `rustpython` binary depends on several lower-level crates including: -To test rustpython, there is a collection of python snippets located in the -`tests/snippets` directory. To run those tests do the following: +- `rustpython-parser` (implementation in `parser/src`) +- `rustpython-compiler` (implementation in `compiler/src`) +- `rustpython-vm` (implementation in `vm/src`) -```shell -$ cd tests -$ pytest -v -``` +Together, these crates provide the functions of a programming language and +enable a line of code to go through a series of steps: -There also are some unit tests, you can run those with cargo: +- parse the line of source code into tokens +- determine if the tokens are valid syntax +- create an Abstract Syntax Tree (AST) +- compile the AST into bytecode +- execute the bytecode in the virtual machine (VM). -```shell -$ cargo test --all -``` +### rustpython-parser -## Profiling +This crate contains the lexer and parser to convert a line of code to +an Abstract Syntax Tree (AST): -To profile rustpython, simply build in release mode with the `flame-it` feature. -This will generate a file `flamescope.json`, which you can then view at -https://speedscope.app. +- Lexer: `parser/lexer.rs` converts Python source code into tokens +- Parser: `parser/parser.rs` takes the tokens generated by the lexer and parses + the tokens into an AST (Abstract Syntax Tree) where the nodes of the syntax + tree are Rust structs and enums. + - The Parser relies on `LALRPOP`, a Rust parser generator framework. + - More information on parsers and a tutorial can be found in the + [LALRPOP book](https://lalrpop.github.io/lalrpop/README.html). +- AST: `parser/ast.rs` implements in Rust the Python types and expressions + represented by the AST nodes. -```sh -$ cargo run --release --features flame-it script.py -$ cat flamescope.json -{} -``` +### rustpython-compiler -You can also pass the `--output-file` option to choose which file to output to -(or stdout if you specify `-`), and the `--output-format` option to choose if -you want to output in the speedscope json format (default), text, or a raw html -viewer (currently broken). +The `rustpython-compiler` crate's purpose is to transform the AST (Abstract Syntax +Tree) to bytecode. The implementation of the compiler is found in the +`compiler/src` directory. The compiler implements Python's peephole optimizer +implementation, Symbol table, and streams in Rust. + +Implementation of bytecode structure in Rust is found in the `bytecode/src` +directory. The `bytecode/src/bytecode.rs` contains the representation of +instructions and operations in Rust. Further information about Python's +bytecode instructions can be found in the +[Python documentation](https://docs.python.org/3/library/dis.html#bytecodes). + +### rustpython-vm + +The `rustpython-vm` crate has the important job of running the virtual machine that +executes Python's instructions. The `vm/src` directory contains code to +implement the read and evaluation loop that fetches and dispatches +instructions. This directory also contains the implementation of the +Python Standard Library modules in Rust (`vm/src/stdlib`). In Python +everything can be represented as an Object. `vm/src/obj` directory holds +the Rust code used to represent a Python Object and its methods. + +## Questions + +Have you tried these steps and have a question, please chat with us on +[gitter](https://gitter.im/rustpython/Lobby). diff --git a/Lib/unittest/__main__.py b/Lib/unittest/__main__.py index 711653832..e5876f569 100644 --- a/Lib/unittest/__main__.py +++ b/Lib/unittest/__main__.py @@ -2,8 +2,7 @@ import sys if sys.argv[0].endswith("__main__.py"): - # FIXME change to `import os.path` as it was for cpython once `import os.path` works - import os + import os.path # We change sys.argv[0] to make help message more useful # use executable without path, unquoted # (it's just a hint anyway) diff --git a/bytecode/src/bytecode.rs b/bytecode/src/bytecode.rs index 2946954da..3802429b8 100644 --- a/bytecode/src/bytecode.rs +++ b/bytecode/src/bytecode.rs @@ -84,10 +84,7 @@ pub enum Instruction { symbols: Vec, level: usize, }, - ImportStar { - name: Option, - level: usize, - }, + ImportStar, ImportFrom { name: String, }, @@ -429,7 +426,7 @@ impl Instruction { format!("{:?}", symbols), level ), - ImportStar { name, level } => w!(ImportStar, format!("{:?}", name), level), + ImportStar => w!(ImportStar), ImportFrom { name } => w!(ImportFrom, name), LoadName { name, scope } => w!(LoadName, name, format!("{:?}", scope)), StoreName { name, scope } => w!(StoreName, name, format!("{:?}", scope)), diff --git a/compiler/src/compile.rs b/compiler/src/compile.rs index baa838fea..23b46f1b9 100644 --- a/compiler/src/compile.rs +++ b/compiler/src/compile.rs @@ -188,7 +188,19 @@ impl Compiler { ) -> Result<(), CompileError> { let size_before = self.output_stack.len(); self.symbol_table_stack.push(symbol_table); - self.compile_statements(&program.statements)?; + + let (statements, doc) = get_doc(&program.statements); + if let Some(value) = doc { + self.emit(Instruction::LoadConst { + value: bytecode::Constant::String { value }, + }); + self.emit(Instruction::StoreName { + name: "__doc__".to_owned(), + scope: bytecode::NameScope::Global, + }); + } + self.compile_statements(statements)?; + assert_eq!(self.output_stack.len(), size_before); // Emit None at end: @@ -305,11 +317,15 @@ impl Compiler { symbols: vec![], level: 0, }); - if let Some(alias) = &name.alias { + for part in name.symbol.split('.').skip(1) { + self.emit(Instruction::LoadAttr { + name: part.to_owned(), + }); + } self.store_name(alias); } else { - self.store_name(&name.symbol); + self.store_name(name.symbol.split('.').next().unwrap()); } } } @@ -322,10 +338,12 @@ impl Compiler { if import_star { // from .... import * - self.emit(Instruction::ImportStar { + self.emit(Instruction::Import { name: module.clone(), + symbols: vec!["*".to_owned()], level: *level, }); + self.emit(Instruction::ImportStar); } else { // from mod import a, b as c // First, determine the fromlist (for import lib): @@ -1891,30 +1909,36 @@ impl Compiler { } fn compile_string(&mut self, string: &ast::StringGroup) -> Result<(), CompileError> { - match string { - ast::StringGroup::Joined { values } => { - for value in values { - self.compile_string(value)?; + if let Some(value) = try_get_constant_string(string) { + self.emit(Instruction::LoadConst { + value: bytecode::Constant::String { value }, + }); + } else { + match string { + ast::StringGroup::Joined { values } => { + for value in values { + self.compile_string(value)?; + } + self.emit(Instruction::BuildString { size: values.len() }) + } + ast::StringGroup::Constant { value } => { + self.emit(Instruction::LoadConst { + value: bytecode::Constant::String { + value: value.to_string(), + }, + }); + } + ast::StringGroup::FormattedValue { + value, + conversion, + spec, + } => { + self.compile_expression(value)?; + self.emit(Instruction::FormatValue { + conversion: conversion.map(compile_conversion_flag), + spec: spec.clone(), + }); } - self.emit(Instruction::BuildString { size: values.len() }) - } - ast::StringGroup::Constant { value } => { - self.emit(Instruction::LoadConst { - value: bytecode::Constant::String { - value: value.to_string(), - }, - }); - } - ast::StringGroup::FormattedValue { - value, - conversion, - spec, - } => { - self.compile_expression(value)?; - self.emit(Instruction::FormatValue { - conversion: conversion.map(compile_conversion_flag), - spec: spec.clone(), - }); } } Ok(()) @@ -1994,13 +2018,11 @@ impl Compiler { } fn get_doc(body: &[ast::Statement]) -> (&[ast::Statement], Option) { - if let Some(val) = body.get(0) { + if let Some((val, body_rest)) = body.split_first() { if let ast::StatementType::Expression { ref expression } = val.node { if let ast::ExpressionType::String { value } = &expression.node { - if let ast::StringGroup::Constant { ref value } = value { - if let Some((_, body_rest)) = body.split_first() { - return (body_rest, Some(value.to_string())); - } + if let Some(value) = try_get_constant_string(value) { + return (body_rest, Some(value.to_string())); } } } @@ -2008,6 +2030,27 @@ fn get_doc(body: &[ast::Statement]) -> (&[ast::Statement], Option) { (body, None) } +fn try_get_constant_string(string: &ast::StringGroup) -> Option { + fn get_constant_string_inner(out_string: &mut String, string: &ast::StringGroup) -> bool { + match string { + ast::StringGroup::Constant { value } => { + out_string.push_str(&value); + true + } + ast::StringGroup::Joined { values } => values + .iter() + .all(|value| get_constant_string_inner(out_string, value)), + ast::StringGroup::FormattedValue { .. } => false, + } + } + let mut out_string = String::new(); + if get_constant_string_inner(&mut out_string, string) { + Some(out_string) + } else { + None + } +} + fn compile_location(location: &ast::Location) -> bytecode::Location { bytecode::Location::new(location.row(), location.column()) } diff --git a/compiler/src/symboltable.rs b/compiler/src/symboltable.rs index d91f32dc7..8e44bc755 100644 --- a/compiler/src/symboltable.rs +++ b/compiler/src/symboltable.rs @@ -388,7 +388,10 @@ impl SymbolTableBuilder { self.register_name(alias, SymbolUsage::Assigned)?; } else { // `import module` - self.register_name(&name.symbol, SymbolUsage::Assigned)?; + self.register_name( + name.symbol.split('.').next().unwrap(), + SymbolUsage::Assigned, + )?; } } } diff --git a/src/main.rs b/src/main.rs index 42d0462b6..5e2d7c60c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -312,7 +312,7 @@ fn run_rustpython(vm: &VirtualMachine, matches: &ArgMatches) -> PyResult<()> { } let scope = vm.new_scope_with_builtins(); - let main_module = vm.ctx.new_module("__main__", scope.globals.clone()); + let main_module = vm.new_module("__main__", scope.globals.clone()); vm.get_attribute(vm.sys_module.clone(), "modules")? .set_item("__main__", main_module, vm)?; @@ -359,7 +359,7 @@ fn run_module(vm: &VirtualMachine, module: &str) -> PyResult<()> { debug!("Running module {}", module); let runpy = vm.import("runpy", &vm.ctx.new_tuple(vec![]), 0)?; let run_module_as_main = vm.get_attribute(runpy, "_run_module_as_main")?; - vm.invoke(run_module_as_main, vec![vm.new_str(module.to_owned())])?; + vm.invoke(&run_module_as_main, vec![vm.new_str(module.to_owned())])?; Ok(()) } diff --git a/tests/snippets/builtin_complex.py b/tests/snippets/builtin_complex.py index 64b4570c1..f751a95a5 100644 --- a/tests/snippets/builtin_complex.py +++ b/tests/snippets/builtin_complex.py @@ -145,3 +145,7 @@ assert '(1+1j)' == str(1+1j) assert '(1-1j)' == str(1-1j) assert '(1+1j)' == repr(1+1j) assert '(1-1j)' == repr(1-1j) + +# __getnewargs__ +assert (3 + 5j).__getnewargs__() == (3.0, 5.0) +assert (5j).__getnewargs__() == (0.0, 5.0) \ No newline at end of file diff --git a/tests/snippets/builtin_round.py b/tests/snippets/builtin_round.py new file mode 100644 index 000000000..6d116b307 --- /dev/null +++ b/tests/snippets/builtin_round.py @@ -0,0 +1,21 @@ +from testutils import assertRaises + +assert round(0) == 0 +assert isinstance(round(0), int) +assert round(0.0) == 0 +assert isinstance(round(0.0), int) + +assert round(0, None) == 0 +assert isinstance(round(0, None), int) +assert round(0.0, None) == 0 +assert isinstance(round(0, None), int) + +assert round(0, 0) == 0 +assert isinstance(round(0, 0), int) +assert round(0.0, 0) == 0.0 # Cannot check the type +assert isinstance(round(0.0, 0), float) + +with assertRaises(TypeError): + round(0, 0.0) +with assertRaises(TypeError): + round(0.0, 0.0) diff --git a/tests/snippets/ellipsis.py b/tests/snippets/ellipsis.py index 20bb3a33c..5316b9f86 100644 --- a/tests/snippets/ellipsis.py +++ b/tests/snippets/ellipsis.py @@ -11,6 +11,23 @@ assert b is c assert b is d assert d is e +assert Ellipsis.__repr__() == 'Ellipsis' +assert Ellipsis.__reduce__() == 'Ellipsis' +assert type(Ellipsis).__new__(type(Ellipsis)) == Ellipsis +assert type(Ellipsis).__reduce__(Ellipsis) == 'Ellipsis' +try: + type(Ellipsis).__new__(type(1)) +except TypeError: + pass +else: + assert False, '`Ellipsis.__new__` should only accept `type(Ellipsis)` as argument' +try: + type(Ellipsis).__reduce__(1) +except TypeError: + pass +else: + assert False, '`Ellipsis.__reduce__` should only accept `Ellipsis` as argument' + assert Ellipsis is ... Ellipsis = 2 assert Ellipsis is not ... diff --git a/tests/snippets/floats.py b/tests/snippets/floats.py index 0200e5a36..6139295f4 100644 --- a/tests/snippets/floats.py +++ b/tests/snippets/floats.py @@ -151,12 +151,20 @@ assert float(1.2) == 1.2 assert math.trunc(1.2) == 1 assert_raises(OverflowError, float('inf').__trunc__) assert_raises(ValueError, float('nan').__trunc__) -assert 0.5.__round__() == 0.0 -assert 1.5.__round__() == 2.0 +assert isinstance(0.5.__round__(), int) +assert isinstance(1.5.__round__(), int) +assert 0.5.__round__() == 0 +assert 1.5.__round__() == 2 +assert isinstance(0.5.__round__(0), float) +assert isinstance(1.5.__round__(0), float) assert 0.5.__round__(0) == 0.0 assert 1.5.__round__(0) == 2.0 -assert 0.5.__round__(None) == 0.0 -assert 1.5.__round__(None) == 2.0 +assert isinstance(0.5.__round__(None), int) +assert isinstance(1.5.__round__(None), int) +assert 0.5.__round__(None) == 0 +assert 1.5.__round__(None) == 2 +assert_raises(TypeError, lambda: 0.5.__round__(0.0)) +assert_raises(TypeError, lambda: 1.5.__round__(0.0)) assert_raises(OverflowError, float('inf').__round__) assert_raises(ValueError, float('nan').__round__) diff --git a/tests/snippets/ints.py b/tests/snippets/ints.py index d05848361..0e89d44f3 100644 --- a/tests/snippets/ints.py +++ b/tests/snippets/ints.py @@ -167,3 +167,16 @@ class F(float): return 3 assert int(F(1.2)) == 3 + +assert isinstance((0).__round__(), int) +assert isinstance((1).__round__(), int) +assert (0).__round__() == 0 +assert (1).__round__() == 1 +assert isinstance((0).__round__(0), int) +assert isinstance((1).__round__(0), int) +assert (0).__round__(0) == 0 +assert (1).__round__(0) == 1 +assert_raises(TypeError, lambda: (0).__round__(None)) +assert_raises(TypeError, lambda: (1).__round__(None)) +assert_raises(TypeError, lambda: (0).__round__(0.0)) +assert_raises(TypeError, lambda: (1).__round__(0.0)) \ No newline at end of file diff --git a/tests/snippets/json_snippet.py b/tests/snippets/json_snippet.py index 15866ab86..d47266b58 100644 --- a/tests/snippets/json_snippet.py +++ b/tests/snippets/json_snippet.py @@ -1,5 +1,6 @@ from testutils import assert_raises import json +from io import StringIO def round_trip_test(obj): # serde_json and Python's json module produce slightly differently spaced @@ -7,63 +8,129 @@ def round_trip_test(obj): # proxy return obj == json.loads(json.dumps(obj)) +def json_dump(obj): + f = StringIO() + json.dump(obj, f) + f.seek(0) + return f.getvalue() + +def json_load(obj): + f = StringIO(obj) + return json.load(f) + assert '"string"' == json.dumps("string") +assert '"string"' == json_dump("string") + assert "1" == json.dumps(1) +assert "1" == json_dump(1) + assert "1.0" == json.dumps(1.0) +assert "1.0" == json_dump(1.0) + assert "true" == json.dumps(True) +assert "true" == json_dump(True) + assert "false" == json.dumps(False) +assert "false" == json_dump(False) + assert 'null' == json.dumps(None) +assert 'null' == json_dump(None) assert '[]' == json.dumps([]) +assert '[]' == json_dump([]) + assert '[1]' == json.dumps([1]) +assert '[1]' == json_dump([1]) + assert '[[1]]' == json.dumps([[1]]) +assert '[[1]]' == json_dump([[1]]) + assert round_trip_test([1, "string", 1.0, True]) assert '[]' == json.dumps(()) +assert '[]' == json_dump(()) + assert '[1]' == json.dumps((1,)) +assert '[1]' == json_dump((1,)) + assert '[[1]]' == json.dumps(((1,),)) +assert '[[1]]' == json_dump(((1,),)) # tuples don't round-trip through json assert [1, "string", 1.0, True] == json.loads(json.dumps((1, "string", 1.0, True))) assert '{}' == json.dumps({}) +assert '{}' == json_dump({}) assert round_trip_test({'a': 'b'}) # should reject non-str keys in jsons assert_raises(json.JSONDecodeError, lambda: json.loads('{3: "abc"}')) +assert_raises(json.JSONDecodeError, lambda: json_load('{3: "abc"}')) # should serialize non-str keys as strings assert json.dumps({'3': 'abc'}) == json.dumps({3: 'abc'}) assert 1 == json.loads("1") +assert 1 == json_load("1") + assert -1 == json.loads("-1") +assert -1 == json_load("-1") + assert 1.0 == json.loads("1.0") +assert 1.0 == json_load("1.0") + assert -1.0 == json.loads("-1.0") +assert -1.0 == json_load("-1.0") + assert "str" == json.loads('"str"') +assert "str" == json_load('"str"') + assert True is json.loads('true') +assert True is json_load('true') + assert False is json.loads('false') +assert False is json_load('false') + assert None is json.loads('null') +assert None is json_load('null') + assert [] == json.loads('[]') +assert [] == json_load('[]') + assert ['a'] == json.loads('["a"]') +assert ['a'] == json_load('["a"]') + assert [['a'], 'b'] == json.loads('[["a"], "b"]') +assert [['a'], 'b'] == json_load('[["a"], "b"]') class String(str): pass assert "string" == json.loads(String('"string"')) +assert "string" == json_load(String('"string"')) + assert '"string"' == json.dumps(String("string")) +assert '"string"' == json_dump(String("string")) class Int(int): pass class Float(float): pass assert '1' == json.dumps(Int(1)) +assert '1' == json_dump(Int(1)) + assert '0.5' == json.dumps(Float(0.5)) +assert '0.5' == json_dump(Float(0.5)) class List(list): pass class Tuple(tuple): pass class Dict(dict): pass assert '[1]' == json.dumps(List([1])) +assert '[1]' == json_dump(List([1])) + assert json.dumps((1, "string", 1.0, True)) == json.dumps(Tuple((1, "string", 1.0, True))) +assert json_dump((1, "string", 1.0, True)) == json_dump(Tuple((1, "string", 1.0, True))) + assert json.dumps({'a': 'b'}) == json.dumps(Dict({'a': 'b'})) +assert json_dump({'a': 'b'}) == json_dump(Dict({'a': 'b'})) # big ints should not crash VM # TODO: test for correct output when actual serialization implemented and doesn’t throw diff --git a/tests/snippets/object.py b/tests/snippets/object.py index 6845a0b3e..663a2cd76 100644 --- a/tests/snippets/object.py +++ b/tests/snippets/object.py @@ -7,6 +7,10 @@ myobj = MyObject() assert myobj == myobj assert not myobj != myobj +object.__subclasshook__() == NotImplemented +object.__subclasshook__(1) == NotImplemented +object.__subclasshook__(1, 2) == NotImplemented + assert MyObject().__eq__(MyObject()) == NotImplemented assert MyObject().__ne__(MyObject()) == NotImplemented assert MyObject().__lt__(MyObject()) == NotImplemented diff --git a/tests/snippets/stdlib_functools.py b/tests/snippets/stdlib_functools.py new file mode 100644 index 000000000..bd95f0e81 --- /dev/null +++ b/tests/snippets/stdlib_functools.py @@ -0,0 +1,79 @@ +from functools import reduce +from testutils import assertRaises + +class Squares: + def __init__(self, max): + self.max = max + self.sofar = [] + + def __len__(self): + return len(self.sofar) + + def __getitem__(self, i): + if not 0 <= i < self.max: raise IndexError + n = len(self.sofar) + while n <= i: + self.sofar.append(n*n) + n += 1 + return self.sofar[i] + +def add(a, b): + return a + b + +assert reduce(add, ['a', 'b', 'c']) == 'abc' +assert reduce(add, ['a', 'b', 'c'], str(42)) == '42abc' +assert reduce(add, [['a', 'c'], [], ['d', 'w']], []) == ['a','c','d','w'] +assert reduce(add, [['a', 'c'], [], ['d', 'w']], []) == ['a','c','d','w'] +assert reduce(lambda x, y: x*y, range(2, 21), 1) == 2432902008176640000 +assert reduce(add, Squares(10)) == 285 +assert reduce(add, Squares(10), 0) == 285 +assert reduce(add, Squares(0), 0) == 0 +assert reduce(42, "1") == "1" +assert reduce(42, "", "1") == "1" + +with assertRaises(TypeError): + reduce() + +with assertRaises(TypeError): + reduce(42, 42) + +with assertRaises(TypeError): + reduce(42, 42, 42) + +class TestFailingIter: + def __iter__(self): + raise RuntimeError + +with assertRaises(RuntimeError): + reduce(add, TestFailingIter()) + +assert reduce(add, [], None) == None +assert reduce(add, [], 42) == 42 + +class BadSeq: + def __getitem__(self, index): + raise ValueError +with assertRaises(ValueError): + reduce(42, BadSeq()) + +# Test reduce()'s use of iterators. +class SequenceClass: + def __init__(self, n): + self.n = n + def __getitem__(self, i): + if 0 <= i < self.n: + return i + else: + raise IndexError + +assert reduce(add, SequenceClass(5)) == 10 +assert reduce(add, SequenceClass(5), 42) == 52 +with assertRaises(TypeError): + reduce(add, SequenceClass(0)) + +assert reduce(add, SequenceClass(0), 42) == 42 +assert reduce(add, SequenceClass(1)) == 0 +assert reduce(add, SequenceClass(1), 42) == 42 + +d = {"one": 1, "two": 2, "three": 3} +assert reduce(add, d) == "".join(d.keys()) diff --git a/tests/snippets/stdlib_io.py b/tests/snippets/stdlib_io.py index 184146081..78f1287a9 100644 --- a/tests/snippets/stdlib_io.py +++ b/tests/snippets/stdlib_io.py @@ -1,5 +1,6 @@ from io import BufferedReader, FileIO, StringIO, BytesIO import os +from testutils import assertRaises fi = FileIO('README.md') assert fi.seekable() @@ -23,3 +24,9 @@ fd = os.open('README.md', os.O_RDONLY) with FileIO(fd) as fio: res2 = fio.read() assert res == res2 + +fi = FileIO('README.md') +fi.read() +fi.close() +with assertRaises(ValueError): + fi.read() diff --git a/tests/snippets/stdlib_socket.py b/tests/snippets/stdlib_socket.py index 581100c58..f34c83e47 100644 --- a/tests/snippets/stdlib_socket.py +++ b/tests/snippets/stdlib_socket.py @@ -119,6 +119,12 @@ with assertRaises(OSError): with assertRaises(OSError): socket.inet_aton("test") +with assertRaises(OverflowError): + socket.htonl(-1) + +assert socket.htonl(0)==0 +assert socket.htonl(10)==167772160 + assert socket.inet_aton("127.0.0.1")==b"\x7f\x00\x00\x01" assert socket.inet_aton("255.255.255.255")==b"\xff\xff\xff\xff" diff --git a/vm/Cargo.toml b/vm/Cargo.toml index 64160547a..b1f1873f2 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -79,3 +79,6 @@ libz-sys = "1.0.25" gethostname = "0.2.0" subprocess = "0.1.18" num_cpus = "1.0" + +[target."cfg(windows)".dependencies] +kernel32-sys = "0.2.2" diff --git a/vm/Lib/_bootstrap_external.py b/vm/Lib/_bootstrap_external.py index 124948ef4..c1ceac96c 100644 --- a/vm/Lib/_bootstrap_external.py +++ b/vm/Lib/_bootstrap_external.py @@ -26,6 +26,16 @@ _CASE_INSENSITIVE_PLATFORMS = (_CASE_INSENSITIVE_PLATFORMS_BYTES_KEY + _CASE_INSENSITIVE_PLATFORMS_STR_KEY) +def _w_long(x): + """Convert a 32-bit integer to little-endian.""" + return (int(x) & 0xFFFFFFFF).to_bytes(4, 'little') + + +def _r_long(int_bytes): + """Convert 4 bytes in little-endian to an integer.""" + return int.from_bytes(int_bytes, 'little') + + def _make_relax_case(): if sys.platform.startswith(_CASE_INSENSITIVE_PLATFORMS): if sys.platform.startswith(_CASE_INSENSITIVE_PLATFORMS_STR_KEY): diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index b3b901e8a..33ad00044 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -37,7 +37,7 @@ fn builtin_abs(x: PyObjectRef, vm: &VirtualMachine) -> PyResult { let method = vm.get_method_or_type_error(x.clone(), "__abs__", || { format!("bad operand type for abs(): '{}'", x.class().name) })?; - vm.invoke(method, PyFuncArgs::new(vec![], vec![])) + vm.invoke(&method, PyFuncArgs::new(vec![], vec![])) } fn builtin_all(iterable: PyIterable, vm: &VirtualMachine) -> PyResult { @@ -395,7 +395,7 @@ fn builtin_len(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { let method = vm.get_method_or_type_error(obj.clone(), "__len__", || { format!("object of type '{}' has no len()", obj.class().name) })?; - vm.invoke(method, PyFuncArgs::default()) + vm.invoke(&method, PyFuncArgs::default()) } fn builtin_locals(vm: &VirtualMachine) -> PyDictRef { @@ -428,15 +428,15 @@ fn builtin_max(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { let mut x = candidates_iter.next().unwrap(); // TODO: this key function looks pretty duplicate. Maybe we can create // a local function? - let mut x_key = if let Some(f) = &key_func { - vm.invoke(f.clone(), vec![x.clone()])? + let mut x_key = if let Some(ref f) = &key_func { + vm.invoke(f, vec![x.clone()])? } else { x.clone() }; for y in candidates_iter { - let y_key = if let Some(f) = &key_func { - vm.invoke(f.clone(), vec![y.clone()])? + let y_key = if let Some(ref f) = &key_func { + vm.invoke(f, vec![y.clone()])? } else { y.clone() }; @@ -476,15 +476,15 @@ fn builtin_min(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { let mut x = candidates_iter.next().unwrap(); // TODO: this key function looks pretty duplicate. Maybe we can create // a local function? - let mut x_key = if let Some(f) = &key_func { - vm.invoke(f.clone(), vec![x.clone()])? + let mut x_key = if let Some(ref f) = &key_func { + vm.invoke(f, vec![x.clone()])? } else { x.clone() }; for y in candidates_iter { - let y_key = if let Some(f) = &key_func { - vm.invoke(f.clone(), vec![y.clone()])? + let y_key = if let Some(ref f) = &key_func { + vm.invoke(f, vec![y.clone()])? } else { y.clone() }; @@ -711,7 +711,7 @@ fn builtin_reversed(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(obj, None)]); if let Some(reversed_method) = vm.get_method(obj.clone(), "__reversed__") { - vm.invoke(reversed_method?, PyFuncArgs::default()) + vm.invoke(&reversed_method?, PyFuncArgs::default()) } else { vm.get_method_or_type_error(obj.clone(), "__getitem__", || { "argument to reversed() must be a sequence".to_string() @@ -734,9 +734,19 @@ fn builtin_round(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { optional = [(ndigits, None)] ); if let Some(ndigits) = ndigits { - let ndigits = vm.call_method(ndigits, "__int__", vec![])?; - let rounded = vm.call_method(number, "__round__", vec![ndigits])?; - Ok(rounded) + if objtype::isinstance(ndigits, &vm.ctx.int_type()) { + let ndigits = vm.call_method(ndigits, "__int__", vec![])?; + let rounded = vm.call_method(number, "__round__", vec![ndigits])?; + Ok(rounded) + } else if vm.ctx.none().is(ndigits) { + let rounded = &vm.call_method(number, "__round__", vec![])?; + Ok(vm.ctx.new_int(objint::get_value(rounded).clone())) + } else { + Err(vm.new_type_error(format!( + "'{}' object cannot be interpreted as an integer", + ndigits.class().name + ))) + } } else { // without a parameter, the result type is coerced to int let rounded = &vm.call_method(number, "__round__", vec![])?; @@ -777,7 +787,7 @@ fn builtin_sum(iterable: PyIterable, start: OptionalArg, vm: &VirtualMachine) -> // Should be renamed to builtin___import__? fn builtin_import(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { - vm.invoke(vm.import_func.borrow().clone(), args) + vm.invoke(&vm.import_func.borrow(), args) } fn builtin_vars(obj: OptionalArg, vm: &VirtualMachine) -> PyResult { @@ -964,13 +974,13 @@ pub fn builtin_build_class_( // Prepare uses full __getattribute__ resolution chain. let prepare = vm.get_attribute(metaclass.clone().into_object(), "__prepare__")?; - let namespace = vm.invoke(prepare, vec![name_obj.clone(), bases.clone()])?; + let namespace = vm.invoke(&prepare, vec![name_obj.clone(), bases.clone()])?; let namespace: PyDictRef = TryFromObject::try_from_object(vm, namespace)?; let cells = vm.ctx.new_dict(); - vm.invoke_with_locals(function, cells.clone(), namespace.clone())?; + vm.invoke_with_locals(&function, cells.clone(), namespace.clone())?; namespace.set_item("__name__", name_obj.clone(), vm)?; namespace.set_item("__qualname__", qualified_name.into_object(), vm)?; diff --git a/vm/src/exceptions.rs b/vm/src/exceptions.rs index 48fa0ce7a..a78a286b8 100644 --- a/vm/src/exceptions.rs +++ b/vm/src/exceptions.rs @@ -3,7 +3,8 @@ use crate::obj::objsequence; use crate::obj::objtuple::{PyTuple, PyTupleRef}; use crate::obj::objtype; use crate::obj::objtype::PyClassRef; -use crate::pyobject::{create_type, IdProtocol, PyContext, PyObjectRef, PyResult, TypeProtocol}; +use crate::pyobject::{IdProtocol, PyContext, PyObjectRef, PyResult, TypeProtocol}; +use crate::types::create_type; use crate::vm::VirtualMachine; use itertools::Itertools; use std::fs::File; diff --git a/vm/src/frame.rs b/vm/src/frame.rs index f338b6413..0f56596ee 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -198,10 +198,7 @@ impl Frame { ref symbols, ref level, } => self.import(vm, name, symbols, *level), - bytecode::Instruction::ImportStar { - ref name, - ref level, - } => self.import_star(vm, name, *level), + bytecode::Instruction::ImportStar => self.import_star(vm), bytecode::Instruction::ImportFrom { ref name } => self.import_from(vm, name), bytecode::Instruction::LoadName { ref name, @@ -488,7 +485,7 @@ impl Frame { // Call function: let func_ref = self.pop_value(); - let value = vm.invoke(func_ref, args)?; + let value = vm.invoke(&func_ref, args)?; self.push_value(value); Ok(None) } @@ -599,7 +596,7 @@ impl Frame { if !expr.is(&vm.get_none()) { let repr = vm.to_repr(&expr)?; // TODO: implement sys.displayhook - if let Ok(print) = vm.get_attribute(vm.builtins.clone(), "print") { + if let Ok(ref print) = vm.get_attribute(vm.builtins.clone(), "print") { vm.invoke(print, vec![repr.into_object()])?; } } @@ -740,25 +737,23 @@ impl Frame { // Load attribute, and transform any error into import error. let obj = vm .get_attribute(module, name) - .map_err(|_| vm.new_import_error(format!("cannot import name '{}'", name))); - self.push_value(obj?); + .map_err(|_| vm.new_import_error(format!("cannot import name '{}'", name)))?; + self.push_value(obj); Ok(None) } #[cfg_attr(feature = "flame-it", flame("Frame"))] - fn import_star( - &self, - vm: &VirtualMachine, - module: &Option, - level: usize, - ) -> FrameResult { - let module = module.clone().unwrap_or_default(); - let module = vm.import(&module, &vm.ctx.new_tuple(vec![]), level)?; + fn import_star(&self, vm: &VirtualMachine) -> FrameResult { + let module = self.pop_value(); // Grab all the names from the module and put them in the context if let Some(dict) = &module.dict { for (k, v) in dict { - self.scope.store_name(&vm, &objstr::get_value(&k), v); + let k = vm.to_str(&k)?; + let k = k.as_str(); + if !k.starts_with('_') { + self.scope.store_name(&vm, k, v); + } } } Ok(None) diff --git a/vm/src/function.rs b/vm/src/function.rs index d199860b1..9874309fc 100644 --- a/vm/src/function.rs +++ b/vm/src/function.rs @@ -393,6 +393,18 @@ impl OptionalArg { } } +pub type OptionalOption = OptionalArg>; + +impl OptionalOption { + #[inline] + pub fn flat_option(self) -> Option { + match self { + Present(Some(value)) => Some(value), + _ => None, + } + } +} + impl FromArgs for OptionalArg where T: TryFromObject, diff --git a/vm/src/import.rs b/vm/src/import.rs index 2caaeda53..267adfc86 100644 --- a/vm/src/import.rs +++ b/vm/src/import.rs @@ -17,14 +17,14 @@ pub fn init_importlib(vm: &VirtualMachine, external: bool) -> PyResult { let importlib = import_frozen(vm, "_frozen_importlib")?; let impmod = import_builtin(vm, "_imp")?; let install = vm.get_attribute(importlib.clone(), "_install")?; - vm.invoke(install, vec![vm.sys_module.clone(), impmod])?; + vm.invoke(&install, vec![vm.sys_module.clone(), impmod])?; vm.import_func .replace(vm.get_attribute(importlib.clone(), "__import__")?); if external && cfg!(feature = "rustpython-compiler") { flame_guard!("install_external"); let install_external = vm.get_attribute(importlib.clone(), "_install_external_importers")?; - vm.invoke(install_external, vec![])?; + vm.invoke(&install_external, vec![])?; // Set pyc magic number to commit hash. Should be changed when bytecode will be more stable. let importlib_external = vm.import("_frozen_importlib_external", &vm.ctx.new_tuple(vec![]), 0)?; @@ -87,7 +87,7 @@ pub fn import_codeobj( if set_file_attr { attrs.set_item("__file__", vm.new_str(code_obj.source_path.to_owned()), vm)?; } - let module = vm.ctx.new_module(module_name, attrs.clone()); + let module = vm.new_module(module_name, attrs.clone()); // Store module in cache to prevent infinite loop with mutual importing libs: let sys_modules = vm.get_attribute(vm.sys_module.clone(), "modules")?; diff --git a/vm/src/lib.rs b/vm/src/lib.rs index 766ece06f..0f66f7f8b 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -68,6 +68,7 @@ pub mod scope; pub mod stdlib; mod sysmodule; mod traceback; +pub mod types; pub mod util; mod version; mod vm; diff --git a/vm/src/macros.rs b/vm/src/macros.rs index 5ae975d8e..ea10abfdc 100644 --- a/vm/src/macros.rs +++ b/vm/src/macros.rs @@ -117,7 +117,7 @@ macro_rules! no_kwargs { #[macro_export] macro_rules! py_module { ( $vm:expr, $module_name:expr, { $($name:expr => $value:expr),* $(,)* }) => {{ - let module = $vm.ctx.new_module($module_name, $vm.ctx.new_dict()); + let module = $vm.new_module($module_name, $vm.ctx.new_dict()); $vm.set_attr(&module, "__name__", $vm.ctx.new_str($module_name.to_string())).unwrap(); $( $vm.set_attr(&module, $name, $value).unwrap(); diff --git a/vm/src/obj/objbool.rs b/vm/src/obj/objbool.rs index 6988028ea..19d95889f 100644 --- a/vm/src/obj/objbool.rs +++ b/vm/src/obj/objbool.rs @@ -28,7 +28,7 @@ pub fn boolval(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { Some(method_or_err) => { // If descriptor returns Error, propagate it further let method = method_or_err?; - let bool_obj = vm.invoke(method, PyFuncArgs::default())?; + let bool_obj = vm.invoke(&method, PyFuncArgs::default())?; match bool_obj.payload::() { Some(int_obj) => !int_obj.as_bigint().is_zero(), None => { @@ -42,7 +42,7 @@ pub fn boolval(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult { None => match vm.get_method(obj.clone(), "__len__") { Some(method_or_err) => { let method = method_or_err?; - let bool_obj = vm.invoke(method, PyFuncArgs::default())?; + let bool_obj = vm.invoke(&method, PyFuncArgs::default())?; match bool_obj.payload::() { Some(int_obj) => !int_obj.as_bigint().is_zero(), None => { @@ -66,7 +66,7 @@ Returns True when the argument x is true, False otherwise. The builtins True and False are the only two instances of the class bool. The class bool is a subclass of the class int, and cannot be subclassed."; - let bool_type = &context.bool_type; + let bool_type = &context.types.bool_type; extend_class!(context, bool_type, { "__new__" => context.new_rustfunc(bool_new), "__repr__" => context.new_rustfunc(bool_repr), diff --git a/vm/src/obj/objbytearray.rs b/vm/src/obj/objbytearray.rs index 51d608b09..c3d722ea7 100644 --- a/vm/src/obj/objbytearray.rs +++ b/vm/src/obj/objbytearray.rs @@ -78,14 +78,14 @@ impl PyValue for PyByteArray { /// Fill bytearray class methods dictionary. pub fn init(context: &PyContext) { - PyByteArrayRef::extend_class(context, &context.bytearray_type); - let bytearray_type = &context.bytearray_type; + PyByteArrayRef::extend_class(context, &context.types.bytearray_type); + let bytearray_type = &context.types.bytearray_type; extend_class!(context, bytearray_type, { "fromhex" => context.new_rustfunc(PyByteArrayRef::fromhex), "maketrans" => context.new_rustfunc(PyByteInner::maketrans), }); - PyByteArrayIterator::extend_class(context, &context.bytearrayiterator_type); + PyByteArrayIterator::extend_class(context, &context.types.bytearrayiterator_type); } #[pyimpl] diff --git a/vm/src/obj/objbytes.rs b/vm/src/obj/objbytes.rs index c67a044b2..c39b3203d 100644 --- a/vm/src/obj/objbytes.rs +++ b/vm/src/obj/objbytes.rs @@ -85,14 +85,14 @@ pub fn get_value<'a>(obj: &'a PyObjectRef) -> impl Deref> + 'a } pub fn init(context: &PyContext) { - PyBytesRef::extend_class(context, &context.bytes_type); - let bytes_type = &context.bytes_type; + PyBytesRef::extend_class(context, &context.types.bytes_type); + let bytes_type = &context.types.bytes_type; extend_class!(context, bytes_type, { "fromhex" => context.new_rustfunc(PyBytesRef::fromhex), "maketrans" => context.new_rustfunc(PyByteInner::maketrans), }); - PyBytesIterator::extend_class(context, &context.bytesiterator_type); + PyBytesIterator::extend_class(context, &context.types.bytesiterator_type); } #[pyimpl] diff --git a/vm/src/obj/objclassmethod.rs b/vm/src/obj/objclassmethod.rs index 10b3106ec..38ef47d9e 100644 --- a/vm/src/obj/objclassmethod.rs +++ b/vm/src/obj/objclassmethod.rs @@ -65,5 +65,5 @@ impl PyClassMethod { } pub fn init(context: &PyContext) { - PyClassMethod::extend_class(context, &context.classmethod_type); + PyClassMethod::extend_class(context, &context.types.classmethod_type); } diff --git a/vm/src/obj/objcode.rs b/vm/src/obj/objcode.rs index 51a73d614..a1671d0ef 100644 --- a/vm/src/obj/objcode.rs +++ b/vm/src/obj/objcode.rs @@ -81,7 +81,7 @@ impl PyCodeRef { } pub fn init(context: &PyContext) { - extend_class!(context, &context.code_type, { + extend_class!(context, &context.types.code_type, { "__new__" => context.new_rustfunc(PyCodeRef::new), "__repr__" => context.new_rustfunc(PyCodeRef::repr), diff --git a/vm/src/obj/objcomplex.rs b/vm/src/obj/objcomplex.rs index b32fd8f74..c20431d00 100644 --- a/vm/src/obj/objcomplex.rs +++ b/vm/src/obj/objcomplex.rs @@ -41,7 +41,7 @@ impl From for PyComplex { } pub fn init(context: &PyContext) { - PyComplex::extend_class(context, &context.complex_type); + PyComplex::extend_class(context, &context.types.complex_type); } pub fn get_value(obj: &PyObjectRef) -> Complex64 { @@ -258,4 +258,12 @@ impl PyComplex { let ret = Wrapping(re_hash) + Wrapping(im_hash) * Wrapping(pyhash::IMAG); ret.0 } + + #[pymethod(name = "__getnewargs__")] + fn complex_getnewargs(&self, vm: &VirtualMachine) -> PyResult { + let Complex64 { re, im } = self.value; + Ok(vm + .ctx + .new_tuple(vec![vm.ctx.new_float(re), vm.ctx.new_float(im)])) + } } diff --git a/vm/src/obj/objdict.rs b/vm/src/obj/objdict.rs index e68c6b6a4..09fc08a96 100644 --- a/vm/src/obj/objdict.rs +++ b/vm/src/obj/objdict.rs @@ -210,7 +210,7 @@ impl PyDictRef { } if let Some(method_or_err) = vm.get_method(self.clone().into_object(), "__missing__") { let method = method_or_err?; - return vm.invoke(method, vec![key]); + return vm.invoke(&method, vec![key]); } Err(vm.new_key_error(key.clone())) } @@ -423,7 +423,7 @@ macro_rules! dict_iterator { impl PyValue for $name { fn class(vm: &VirtualMachine) -> PyClassRef { - vm.ctx.$class.clone() + vm.ctx.types.$class.clone() } } @@ -473,7 +473,7 @@ macro_rules! dict_iterator { impl PyValue for $iter_name { fn class(vm: &VirtualMachine) -> PyClassRef { - vm.ctx.$iter_class.clone() + vm.ctx.types.$iter_class.clone() } } }; @@ -511,7 +511,7 @@ dict_iterator! { } pub fn init(context: &PyContext) { - extend_class!(context, &context.dict_type, { + extend_class!(context, &context.types.dict_type, { "__bool__" => context.new_rustfunc(PyDictRef::bool), "__len__" => context.new_rustfunc(PyDictRef::len), "__contains__" => context.new_rustfunc(PyDictRef::contains), @@ -536,10 +536,10 @@ pub fn init(context: &PyContext) { "popitem" => context.new_rustfunc(PyDictRef::popitem), }); - PyDictKeys::extend_class(context, &context.dictkeys_type); - PyDictKeyIterator::extend_class(context, &context.dictkeyiterator_type); - PyDictValues::extend_class(context, &context.dictvalues_type); - PyDictValueIterator::extend_class(context, &context.dictvalueiterator_type); - PyDictItems::extend_class(context, &context.dictitems_type); - PyDictItemIterator::extend_class(context, &context.dictitemiterator_type); + PyDictKeys::extend_class(context, &context.types.dictkeys_type); + PyDictKeyIterator::extend_class(context, &context.types.dictkeyiterator_type); + PyDictValues::extend_class(context, &context.types.dictvalues_type); + PyDictValueIterator::extend_class(context, &context.types.dictvalueiterator_type); + PyDictItems::extend_class(context, &context.types.dictitems_type); + PyDictItemIterator::extend_class(context, &context.types.dictitemiterator_type); } diff --git a/vm/src/obj/objellipsis.rs b/vm/src/obj/objellipsis.rs index cb188e1f1..3b2b6d8bf 100644 --- a/vm/src/obj/objellipsis.rs +++ b/vm/src/obj/objellipsis.rs @@ -1,20 +1,30 @@ -use crate::function::PyFuncArgs; -use crate::pyobject::{PyContext, PyResult}; +use crate::obj::objtype::{issubclass, PyClassRef}; +use crate::pyobject::{PyContext, PyEllipsisRef, PyResult}; use crate::vm::VirtualMachine; pub fn init(context: &PyContext) { extend_class!(context, &context.ellipsis_type, { "__new__" => context.new_rustfunc(ellipsis_new), - "__repr__" => context.new_rustfunc(ellipsis_repr) + "__repr__" => context.new_rustfunc(ellipsis_repr), + "__reduce__" => context.new_rustfunc(ellipsis_reduce), }); } -fn ellipsis_new(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(_cls, None)]); - Ok(vm.ctx.ellipsis()) +fn ellipsis_new(cls: PyClassRef, vm: &VirtualMachine) -> PyResult { + if issubclass(&cls, &vm.ctx.ellipsis_type) { + Ok(vm.ctx.ellipsis()) + } else { + Err(vm.new_type_error(format!( + "ellipsis.__new__({ty}): {ty} is not a subtype of ellipsis", + ty = cls, + ))) + } } -fn ellipsis_repr(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { - arg_check!(vm, args, required = [(_cls, None)]); - Ok(vm.new_str("Ellipsis".to_string())) +fn ellipsis_repr(_self: PyEllipsisRef, _vm: &VirtualMachine) -> String { + "Ellipsis".to_string() +} + +fn ellipsis_reduce(_self: PyEllipsisRef, _vm: &VirtualMachine) -> String { + "Ellipsis".to_string() } diff --git a/vm/src/obj/objenumerate.rs b/vm/src/obj/objenumerate.rs index 56d232272..0ce34c689 100644 --- a/vm/src/obj/objenumerate.rs +++ b/vm/src/obj/objenumerate.rs @@ -68,8 +68,8 @@ impl PyEnumerate { } pub fn init(context: &PyContext) { - PyEnumerate::extend_class(context, &context.enumerate_type); - extend_class!(context, &context.enumerate_type, { + PyEnumerate::extend_class(context, &context.types.enumerate_type); + extend_class!(context, &context.types.enumerate_type, { "__new__" => context.new_rustfunc(enumerate_new), }); } diff --git a/vm/src/obj/objfilter.rs b/vm/src/obj/objfilter.rs index 24800d6aa..8fa3fef3c 100644 --- a/vm/src/obj/objfilter.rs +++ b/vm/src/obj/objfilter.rs @@ -52,7 +52,7 @@ impl PyFilter { } else { // the predicate itself can raise StopIteration which does stop the filter // iteration - vm.invoke(predicate.clone(), vec![next_obj.clone()])? + vm.invoke(&predicate, vec![next_obj.clone()])? }; if objbool::boolval(vm, predicate_value)? { return Ok(next_obj); @@ -67,8 +67,8 @@ impl PyFilter { } pub fn init(context: &PyContext) { - PyFilter::extend_class(context, &context.filter_type); - extend_class!(context, &context.filter_type, { + PyFilter::extend_class(context, &context.types.filter_type); + extend_class!(context, &context.types.filter_type, { "__new__" => context.new_rustfunc(filter_new), }); } diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index cfac52aa9..b0dbaebe2 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -440,25 +440,38 @@ impl PyFloat { OptionalArg::Missing => None, OptionalArg::Present(ref value) => { if !vm.get_none().is(value) { - let ndigits = if objtype::isinstance(value, &vm.ctx.int_type()) { - objint::get_value(value) - } else { + if !objtype::isinstance(value, &vm.ctx.int_type()) { return Err(vm.new_type_error(format!( - "TypeError: '{}' object cannot be interpreted as an integer", + "'{}' object cannot be interpreted as an integer", value.class().name ))); }; - if ndigits.is_zero() { - None - } else { - Some(ndigits) - } + // Only accept int type ndigits + let ndigits = objint::get_value(value); + Some(ndigits) } else { None } } }; - if ndigits.is_none() { + + if let Some(ndigits) = ndigits { + if ndigits.is_zero() { + let fract = self.value.fract(); + let value = if (fract.abs() - 0.5).abs() < std::f64::EPSILON { + if self.value.trunc() % 2.0 == 0.0 { + self.value - fract + } else { + self.value + fract + } + } else { + self.value.round() + }; + Ok(vm.ctx.new_float(value)) + } else { + Ok(vm.ctx.not_implemented()) + } + } else { let fract = self.value.fract(); let value = if (fract.abs() - 0.5).abs() < std::f64::EPSILON { if self.value.trunc() % 2.0 == 0.0 { @@ -471,8 +484,6 @@ impl PyFloat { }; let int = try_to_bigint(value, vm)?; Ok(vm.ctx.new_int(int)) - } else { - Ok(vm.ctx.not_implemented()) } } @@ -612,12 +623,12 @@ pub fn make_float(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult { obj.class().name ) })?; - let result = vm.invoke(method, vec![])?; + let result = vm.invoke(&method, vec![])?; Ok(get_value(&result)) } } #[rustfmt::skip] // to avoid line splitting pub fn init(context: &PyContext) { - PyFloat::extend_class(context, &context.float_type); + PyFloat::extend_class(context, &context.types.float_type); } diff --git a/vm/src/obj/objframe.rs b/vm/src/obj/objframe.rs index 73f4e9b91..efc833270 100644 --- a/vm/src/obj/objframe.rs +++ b/vm/src/obj/objframe.rs @@ -9,7 +9,7 @@ use crate::pyobject::{PyContext, PyObjectRef, PyResult}; use crate::vm::VirtualMachine; pub fn init(context: &PyContext) { - extend_class!(context, &context.frame_type, { + extend_class!(context, &context.types.frame_type, { "__new__" => context.new_rustfunc(FrameRef::new), "__repr__" => context.new_rustfunc(FrameRef::repr), "f_locals" => context.new_property(FrameRef::flocals), diff --git a/vm/src/obj/objfunction.rs b/vm/src/obj/objfunction.rs index 1c7ff642a..d33ec97fe 100644 --- a/vm/src/obj/objfunction.rs +++ b/vm/src/obj/objfunction.rs @@ -42,7 +42,7 @@ impl PyValue for PyFunction { impl PyFunctionRef { fn call(self, args: Args, kwargs: KwArgs, vm: &VirtualMachine) -> PyResult { - vm.invoke(self.into_object(), (&args, &kwargs)) + vm.invoke(&self.into_object(), (&args, &kwargs)) } fn code(self, _vm: &VirtualMachine) -> PyCodeRef { @@ -78,7 +78,7 @@ impl PyValue for PyMethod { } pub fn init(context: &PyContext) { - let function_type = &context.function_type; + let function_type = &context.types.function_type; extend_class!(context, function_type, { "__get__" => context.new_rustfunc(bind_method), "__call__" => context.new_rustfunc(PyFunctionRef::call), @@ -87,7 +87,7 @@ pub fn init(context: &PyContext) { "__kwdefaults__" => context.new_property(PyFunctionRef::kwdefaults), }); - let builtin_function_or_method_type = &context.builtin_function_or_method_type; + let builtin_function_or_method_type = &context.types.builtin_function_or_method_type; extend_class!(context, builtin_function_or_method_type, { "__get__" => context.new_rustfunc(bind_method) }); diff --git a/vm/src/obj/objgenerator.rs b/vm/src/obj/objgenerator.rs index 2c51778fd..a26be543d 100644 --- a/vm/src/obj/objgenerator.rs +++ b/vm/src/obj/objgenerator.rs @@ -75,5 +75,5 @@ fn handle_execution_result(result: ExecutionResult, vm: &VirtualMachine) -> PyRe } pub fn init(ctx: &PyContext) { - PyGenerator::extend_class(ctx, &ctx.generator_type); + PyGenerator::extend_class(ctx, &ctx.types.generator_type); } diff --git a/vm/src/obj/objint.rs b/vm/src/obj/objint.rs index e7533752a..41fb1a9bd 100644 --- a/vm/src/obj/objint.rs +++ b/vm/src/obj/objint.rs @@ -9,13 +9,14 @@ use crate::function::{KwArgs, OptionalArg, PyFuncArgs}; use crate::obj::objtype::PyClassRef; use crate::pyhash; use crate::pyobject::{ - IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, - TypeProtocol, + IdProtocol, IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, + TryFromObject, TypeProtocol, }; use crate::vm::VirtualMachine; use super::objbyteinner::PyByteInner; use super::objbytes::PyBytes; +use super::objint; use super::objstr::{PyString, PyStringRef}; use super::objtype; @@ -468,8 +469,29 @@ impl PyInt { zelf: PyRef, _precision: OptionalArg, _vm: &VirtualMachine, - ) -> PyIntRef { - zelf + ) -> PyResult { + let _ndigits = match _precision { + OptionalArg::Missing => None, + OptionalArg::Present(ref value) => { + if !_vm.get_none().is(value) { + if !objtype::isinstance(value, &_vm.ctx.int_type()) { + return Err(_vm.new_type_error(format!( + "'{}' object cannot be interpreted as an integer", + value.class().name + ))); + }; + // Only accept int type _ndigits + let _ndigits = objint::get_value(value); + Some(_ndigits) + } else { + return Err(_vm.new_type_error(format!( + "'{}' object cannot be interpreted as an integer", + value.class().name + ))); + } + } + }; + Ok(zelf) } #[pymethod(name = "__int__")] @@ -681,7 +703,7 @@ impl IntOptions { fn get_int_value(self, vm: &VirtualMachine) -> PyResult { if let OptionalArg::Present(val) = self.val_options { let base = if let OptionalArg::Present(base) = self.base { - if !objtype::isinstance(&val, &vm.ctx.str_type) { + if !objtype::isinstance(&val, &vm.ctx.str_type()) { return Err(vm.new_type_error( "int() can't convert non-string with explicit base".to_string(), )); @@ -724,7 +746,7 @@ pub fn to_int(vm: &VirtualMachine, obj: &PyObjectRef, mut base: u32) -> PyResult let method = vm.get_method_or_type_error(obj.clone(), "__int__", || { format!("int() argument must be a string or a number, not '{}'", obj.class().name) })?; - let result = vm.invoke(method, PyFuncArgs::default())?; + let result = vm.invoke(&method, PyFuncArgs::default())?; match result.payload::() { Some(int_obj) => Ok(int_obj.as_bigint().clone()), None => Err(vm.new_type_error(format!( @@ -776,8 +798,8 @@ fn div_ints(vm: &VirtualMachine, i1: &BigInt, i2: &BigInt) -> PyResult { } pub fn init(context: &PyContext) { - PyInt::extend_class(context, &context.int_type); - extend_class!(context, &context.int_type, { + PyInt::extend_class(context, &context.types.int_type); + extend_class!(context, &context.types.int_type, { "__new__" => context.new_rustfunc(int_new), }); } diff --git a/vm/src/obj/objiter.rs b/vm/src/obj/objiter.rs index 0fcd078c7..53460acfa 100644 --- a/vm/src/obj/objiter.rs +++ b/vm/src/obj/objiter.rs @@ -20,7 +20,7 @@ use super::objtype::PyClassRef; pub fn get_iter(vm: &VirtualMachine, iter_target: &PyObjectRef) -> PyResult { if let Some(method_or_err) = vm.get_method(iter_target.clone(), "__iter__") { let method = method_or_err?; - vm.invoke(method, vec![]) + vm.invoke(&method, vec![]) } else { vm.get_method_or_type_error(iter_target.clone(), "__getitem__", || { format!("Cannot iterate over {}", iter_target.class().name) @@ -122,5 +122,5 @@ impl PySequenceIterator { } pub fn init(context: &PyContext) { - PySequenceIterator::extend_class(context, &context.iter_type); + PySequenceIterator::extend_class(context, &context.types.iter_type); } diff --git a/vm/src/obj/objlist.rs b/vm/src/obj/objlist.rs index e9b4b40d5..419cdb45d 100644 --- a/vm/src/obj/objlist.rs +++ b/vm/src/obj/objlist.rs @@ -755,7 +755,7 @@ fn do_sort( for x in values.iter() { keys.push(match &key_func { None => x.clone(), - Some(ref func) => vm.invoke((*func).clone(), vec![x.clone()])?, + Some(ref func) => vm.invoke(func, vec![x.clone()])?, }); } @@ -859,7 +859,7 @@ impl PyListReverseIterator { #[rustfmt::skip] // to avoid line splitting pub fn init(context: &PyContext) { - let list_type = &context.list_type; + let list_type = &context.types.list_type; let list_doc = "Built-in mutable sequence.\n\n\ If no argument is given, the constructor creates a new empty list.\n\ @@ -901,6 +901,6 @@ pub fn init(context: &PyContext) { "remove" => context.new_rustfunc(PyListRef::remove) }); - PyListIterator::extend_class(context, &context.listiterator_type); - PyListReverseIterator::extend_class(context, &context.listreverseiterator_type); + PyListIterator::extend_class(context, &context.types.listiterator_type); + PyListReverseIterator::extend_class(context, &context.types.listreverseiterator_type); } diff --git a/vm/src/obj/objmap.rs b/vm/src/obj/objmap.rs index 61fe67c0d..a27b56e8b 100644 --- a/vm/src/obj/objmap.rs +++ b/vm/src/obj/objmap.rs @@ -51,7 +51,7 @@ impl PyMap { .collect::, _>>()?; // the mapper itself can raise StopIteration which does stop the map iteration - vm.invoke(self.mapper.clone(), next_objs) + vm.invoke(&self.mapper, next_objs) } #[pymethod(name = "__iter__")] @@ -61,8 +61,8 @@ impl PyMap { } pub fn init(context: &PyContext) { - PyMap::extend_class(context, &context.map_type); - extend_class!(context, &context.map_type, { + PyMap::extend_class(context, &context.types.map_type); + extend_class!(context, &context.types.map_type, { "__new__" => context.new_rustfunc(map_new), }); } diff --git a/vm/src/obj/objmappingproxy.rs b/vm/src/obj/objmappingproxy.rs index 243a8c89c..b38e9d1ef 100644 --- a/vm/src/obj/objmappingproxy.rs +++ b/vm/src/obj/objmappingproxy.rs @@ -13,7 +13,7 @@ pub type PyMappingProxyRef = PyRef; impl PyValue for PyMappingProxy { fn class(vm: &VirtualMachine) -> PyClassRef { - vm.ctx.mappingproxy_type.clone() + vm.ctx.types.mappingproxy_type.clone() } } @@ -38,5 +38,5 @@ impl PyMappingProxy { } pub fn init(context: &PyContext) { - PyMappingProxy::extend_class(context, &context.mappingproxy_type) + PyMappingProxy::extend_class(context, &context.types.mappingproxy_type) } diff --git a/vm/src/obj/objmemory.rs b/vm/src/obj/objmemory.rs index 7e1628d13..ed4687032 100644 --- a/vm/src/obj/objmemory.rs +++ b/vm/src/obj/objmemory.rs @@ -47,5 +47,5 @@ impl PyValue for PyMemoryView { } pub fn init(ctx: &PyContext) { - PyMemoryView::extend_class(ctx, &ctx.memoryview_type) + PyMemoryView::extend_class(ctx, &ctx.types.memoryview_type) } diff --git a/vm/src/obj/objmodule.rs b/vm/src/obj/objmodule.rs index 99dff3b26..902418498 100644 --- a/vm/src/obj/objmodule.rs +++ b/vm/src/obj/objmodule.rs @@ -1,6 +1,8 @@ +use crate::function::OptionalOption; +use crate::obj::objdict::PyDictRef; use crate::obj::objstr::PyStringRef; use crate::obj::objtype::PyClassRef; -use crate::pyobject::{PyContext, PyRef, PyResult, PyValue}; +use crate::pyobject::{ItemProtocol, PyContext, PyObjectRef, PyRef, PyResult, PyValue}; use crate::vm::VirtualMachine; #[derive(Debug)] @@ -17,15 +19,71 @@ impl PyValue for PyModule { } } +pub fn init_module_dict( + vm: &VirtualMachine, + module_dict: &PyDictRef, + name: PyObjectRef, + doc: PyObjectRef, +) { + module_dict + .set_item("__name__", name, vm) + .expect("Failed to set __name__ on module"); + module_dict + .set_item("__doc__", doc, vm) + .expect("Failed to set __doc__ on module"); + module_dict + .set_item("__package__", vm.get_none(), vm) + .expect("Failed to set __package__ on module"); + module_dict + .set_item("__loader__", vm.get_none(), vm) + .expect("Failed to set __loader__ on module"); + module_dict + .set_item("__spec__", vm.get_none(), vm) + .expect("Failed to set __spec__ on module"); +} + impl PyModuleRef { - fn init(self, name: PyStringRef, vm: &VirtualMachine) -> PyResult { - vm.set_attr(&self.into_object(), "__name__", name)?; - Ok(vm.get_none()) + fn new( + cls: PyClassRef, + name: PyStringRef, + doc: OptionalOption, + vm: &VirtualMachine, + ) -> PyResult { + let zelf = PyModule { + name: name.as_str().to_owned(), + } + .into_ref_with_type(vm, cls)?; + init_module_dict( + vm, + zelf.as_object().dict.as_ref().unwrap(), + name.into_object(), + doc.flat_option() + .map_or_else(|| vm.get_none(), PyRef::into_object), + ); + Ok(zelf) + } + + fn getattribute(self, name: PyStringRef, vm: &VirtualMachine) -> PyResult { + vm.generic_getattribute(self.as_object().clone(), name.clone())? + .ok_or_else(|| { + vm.new_attribute_error(format!( + "module '{}' has no attribute '{}'", + self.name, name, + )) + }) + } + + fn repr(self, vm: &VirtualMachine) -> PyResult { + let importlib = vm.import("_frozen_importlib", &vm.ctx.new_tuple(vec![]), 0)?; + let module_repr = vm.get_attribute(importlib, "_module_repr")?; + vm.invoke(&module_repr, vec![self.into_object()]) } } pub fn init(context: &PyContext) { - extend_class!(&context, &context.module_type, { - "__init__" => context.new_rustfunc(PyModuleRef::init), + extend_class!(&context, &context.types.module_type, { + "__new__" => context.new_rustfunc(PyModuleRef::new), + "__getattribute__" => context.new_rustfunc(PyModuleRef::getattribute), + "__repr__" => context.new_rustfunc(PyModuleRef::repr), }); } diff --git a/vm/src/obj/objnamespace.rs b/vm/src/obj/objnamespace.rs index f8bfc9369..7ef304c1e 100644 --- a/vm/src/obj/objnamespace.rs +++ b/vm/src/obj/objnamespace.rs @@ -28,5 +28,5 @@ impl PyNamespace { } pub fn init(context: &PyContext) { - PyNamespace::extend_class(context, &context.namespace_type); + PyNamespace::extend_class(context, &context.types.namespace_type); } diff --git a/vm/src/obj/objnone.rs b/vm/src/obj/objnone.rs index fa23ca1b0..cf1b4d3a5 100644 --- a/vm/src/obj/objnone.rs +++ b/vm/src/obj/objnone.rs @@ -64,7 +64,7 @@ impl PyNoneRef { if let Ok(property) = PyPropertyRef::try_from_object(vm, descriptor.clone()) { property.instance_binding_get(obj, vm) } else { - vm.invoke(get_func, vec![descriptor, obj, cls]) + vm.invoke(&get_func, vec![descriptor, obj, cls]) } } @@ -95,7 +95,7 @@ impl PyNoneRef { Ok(attr) } } else if let Some(getter) = class_get_attr(&cls, "__getattr__") { - vm.invoke(getter, vec![self.into_object(), name.into_object()]) + vm.invoke(&getter, vec![self.into_object(), name.into_object()]) } else { Err(vm.new_attribute_error(format!("{} has no attribute '{}'", self.as_object(), name))) } diff --git a/vm/src/obj/objobject.rs b/vm/src/obj/objobject.rs index 8f2408dba..87b1da34a 100644 --- a/vm/src/obj/objobject.rs +++ b/vm/src/obj/objobject.rs @@ -24,7 +24,7 @@ impl PyValue for PyInstance { pub fn new_instance(vm: &VirtualMachine, mut args: PyFuncArgs) -> PyResult { // more or less __new__ operator let cls = PyClassRef::try_from_object(vm, args.shift())?; - let dict = if cls.is(&vm.ctx.object) { + let dict = if cls.is(&vm.ctx.object()) { None } else { Some(vm.ctx.new_dict()) @@ -72,7 +72,7 @@ fn object_setattr( if let Some(attr) = objtype::class_get_attr(&cls, &attr_name.value) { if let Some(descriptor) = objtype::class_get_attr(&attr.class(), "__set__") { return vm - .invoke(descriptor, vec![attr, obj.clone(), value]) + .invoke(&descriptor, vec![attr, obj.clone(), value]) .map(|_| ()); } } @@ -94,7 +94,7 @@ fn object_delattr(obj: PyObjectRef, attr_name: PyStringRef, vm: &VirtualMachine) if let Some(attr) = objtype::class_get_attr(&cls, &attr_name.value) { if let Some(descriptor) = objtype::class_get_attr(&attr.class(), "__delete__") { - return vm.invoke(descriptor, vec![attr, obj.clone()]).map(|_| ()); + return vm.invoke(&descriptor, vec![attr, obj.clone()]).map(|_| ()); } } @@ -118,6 +118,10 @@ fn object_repr(zelf: PyObjectRef, _vm: &VirtualMachine) -> String { format!("<{} object at 0x{:x}>", zelf.class().name, zelf.get_id()) } +fn object_subclasshook(vm: &VirtualMachine, _args: PyFuncArgs) -> PyResult { + Ok(vm.ctx.not_implemented()) +} + pub fn object_dir(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult { let attributes: PyAttributes = objtype::get_attributes(obj.class()); @@ -126,7 +130,7 @@ pub fn object_dir(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult { // Get instance attributes: if let Some(object_dict) = &obj.dict { vm.invoke( - vm.get_attribute(dict.clone().into_object(), "update")?, + &vm.get_attribute(dict.clone().into_object(), "update")?, object_dict.clone().into_object(), )?; } @@ -149,7 +153,7 @@ fn object_format( } pub fn init(context: &PyContext) { - let object = &context.object; + let object = &context.types.object_type; let object_doc = "The most base type"; extend_class!(context, object, { @@ -179,7 +183,8 @@ pub fn init(context: &PyContext) { "__repr__" => context.new_rustfunc(object_repr), "__format__" => context.new_rustfunc(object_format), "__getattribute__" => context.new_rustfunc(object_getattribute), - "__doc__" => context.new_str(object_doc.to_string()) + "__subclasshook__" => context.new_classmethod(object_subclasshook), + "__doc__" => context.new_str(object_doc.to_string()), }); } @@ -218,39 +223,8 @@ fn object_dict_setter( )) } -fn object_getattribute(obj: PyObjectRef, name_str: PyStringRef, vm: &VirtualMachine) -> PyResult { - let name = &name_str.value; +fn object_getattribute(obj: PyObjectRef, name: PyStringRef, vm: &VirtualMachine) -> PyResult { vm_trace!("object.__getattribute__({:?}, {:?})", obj, name); - let cls = obj.class(); - - if let Some(attr) = objtype::class_get_attr(&cls, &name) { - let attr_class = attr.class(); - if objtype::class_has_attr(&attr_class, "__set__") { - if let Some(descriptor) = objtype::class_get_attr(&attr_class, "__get__") { - return vm.invoke(descriptor, vec![attr, obj, cls.into_object()]); - } - } - } - - if let Some(obj_attr) = object_getattr(&obj, &name, &vm)? { - Ok(obj_attr) - } else if let Some(attr) = objtype::class_get_attr(&cls, &name) { - vm.call_get_descriptor(attr, obj) - } else if let Some(getter) = objtype::class_get_attr(&cls, "__getattr__") { - vm.invoke(getter, vec![obj, name_str.into_object()]) - } else { - Err(vm.new_attribute_error(format!("{} has no attribute '{}'", obj, name))) - } -} - -fn object_getattr( - obj: &PyObjectRef, - attr_name: &str, - vm: &VirtualMachine, -) -> PyResult> { - if let Some(ref dict) = obj.dict { - dict.get_item_option(attr_name, vm) - } else { - Ok(None) - } + vm.generic_getattribute(obj.clone(), name.clone())? + .ok_or_else(|| vm.new_attribute_error(format!("{} has no attribute '{}'", obj, name))) } diff --git a/vm/src/obj/objproperty.rs b/vm/src/obj/objproperty.rs index 9bf213076..a6d5bcfa1 100644 --- a/vm/src/obj/objproperty.rs +++ b/vm/src/obj/objproperty.rs @@ -37,7 +37,7 @@ impl PyReadOnlyProperty { if obj.is(vm.ctx.none.as_object()) { Ok(zelf.into_object()) } else { - vm.invoke(zelf.getter.clone(), obj) + vm.invoke(&zelf.getter, obj) } } } @@ -123,8 +123,8 @@ impl PyProperty { // specialised version that doesn't check for None pub(crate) fn instance_binding_get(&self, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult { - if let Some(getter) = self.getter.as_ref() { - vm.invoke(getter.clone(), obj) + if let Some(ref getter) = self.getter.as_ref() { + vm.invoke(getter, obj) } else { Err(vm.new_attribute_error("unreadable attribute".to_string())) } @@ -141,7 +141,7 @@ impl PyProperty { if obj.is(vm.ctx.none.as_object()) { Ok(zelf.into_object()) } else { - vm.invoke(getter.clone(), obj) + vm.invoke(&getter, obj) } } else { Err(vm.new_attribute_error("unreadable attribute".to_string())) @@ -150,8 +150,8 @@ impl PyProperty { #[pymethod(name = "__set__")] fn set(&self, obj: PyObjectRef, value: PyObjectRef, vm: &VirtualMachine) -> PyResult { - if let Some(setter) = self.setter.as_ref() { - vm.invoke(setter.clone(), vec![obj, value]) + if let Some(ref setter) = self.setter.as_ref() { + vm.invoke(setter, vec![obj, value]) } else { Err(vm.new_attribute_error("can't set attribute".to_string())) } @@ -159,8 +159,8 @@ impl PyProperty { #[pymethod(name = "__delete__")] fn delete(&self, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult { - if let Some(deleter) = self.deleter.as_ref() { - vm.invoke(deleter.clone(), obj) + if let Some(ref deleter) = self.deleter.as_ref() { + vm.invoke(deleter, obj) } else { Err(vm.new_attribute_error("can't delete attribute".to_string())) } @@ -305,12 +305,12 @@ impl<'a> PropertyBuilder<'a> { } pub fn init(context: &PyContext) { - PyReadOnlyProperty::extend_class(context, &context.readonly_property_type); - PyProperty::extend_class(context, &context.property_type); + PyReadOnlyProperty::extend_class(context, &context.types.readonly_property_type); + PyProperty::extend_class(context, &context.types.property_type); // This is a bit unfortunate, but this instance attribute overlaps with the // class __doc__ string.. - extend_class!(context, &context.property_type, { + extend_class!(context, &context.types.property_type, { "__doc__" => PropertyBuilder::new(context) .add_getter(PyProperty::doc_getter) diff --git a/vm/src/obj/objrange.rs b/vm/src/obj/objrange.rs index 905550f50..99584a292 100644 --- a/vm/src/obj/objrange.rs +++ b/vm/src/obj/objrange.rs @@ -105,8 +105,8 @@ pub fn get_value(obj: &PyObjectRef) -> PyRange { } pub fn init(context: &PyContext) { - PyRange::extend_class(context, &context.range_type); - PyRangeIterator::extend_class(context, &context.rangeiterator_type); + PyRange::extend_class(context, &context.types.range_type); + PyRangeIterator::extend_class(context, &context.types.rangeiterator_type); } type PyRangeRef = PyRef; diff --git a/vm/src/obj/objset.rs b/vm/src/obj/objset.rs index cfa8e1701..dc4a3ca95 100644 --- a/vm/src/obj/objset.rs +++ b/vm/src/obj/objset.rs @@ -748,6 +748,6 @@ impl TryFromObject for SetIterable { } pub fn init(context: &PyContext) { - PySet::extend_class(context, &context.set_type); - PyFrozenSet::extend_class(context, &context.frozenset_type); + PySet::extend_class(context, &context.types.set_type); + PyFrozenSet::extend_class(context, &context.types.frozenset_type); } diff --git a/vm/src/obj/objslice.rs b/vm/src/obj/objslice.rs index 82e4cef8c..0de224d36 100644 --- a/vm/src/obj/objslice.rs +++ b/vm/src/obj/objslice.rs @@ -114,7 +114,7 @@ fn to_index_value(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult context.new_rustfunc(slice_new), diff --git a/vm/src/obj/objstaticmethod.rs b/vm/src/obj/objstaticmethod.rs index a33acf176..e330652a5 100644 --- a/vm/src/obj/objstaticmethod.rs +++ b/vm/src/obj/objstaticmethod.rs @@ -32,7 +32,7 @@ impl PyStaticMethodRef { } pub fn init(context: &PyContext) { - let staticmethod_type = &context.staticmethod_type; + let staticmethod_type = &context.types.staticmethod_type; extend_class!(context, staticmethod_type, { "__get__" => context.new_rustfunc(PyStaticMethodRef::get), "__new__" => context.new_rustfunc(PyStaticMethodRef::new), diff --git a/vm/src/obj/objstr.rs b/vm/src/obj/objstr.rs index 13e26ffd9..8f69fa749 100644 --- a/vm/src/obj/objstr.rs +++ b/vm/src/obj/objstr.rs @@ -1146,10 +1146,10 @@ impl IntoPyObject for &String { } pub fn init(ctx: &PyContext) { - PyString::extend_class(ctx, &ctx.str_type); + PyString::extend_class(ctx, &ctx.types.str_type); - PyStringIterator::extend_class(ctx, &ctx.striterator_type); - PyStringReverseIterator::extend_class(ctx, &ctx.strreverseiterator_type); + PyStringIterator::extend_class(ctx, &ctx.types.striterator_type); + PyStringReverseIterator::extend_class(ctx, &ctx.types.strreverseiterator_type); } pub fn get_value(obj: &PyObjectRef) -> String { @@ -1328,9 +1328,9 @@ fn do_cformat( } else { // check for only literal parts, in which case only dict or empty tuple is allowed if num_specifiers == 0 - && !(objtype::isinstance(&values_obj, &vm.ctx.tuple_type) + && !(objtype::isinstance(&values_obj, &vm.ctx.types.tuple_type) && objtuple::get_value(&values_obj).is_empty()) - && !objtype::isinstance(&values_obj, &vm.ctx.dict_type) + && !objtype::isinstance(&values_obj, &vm.ctx.types.dict_type) { return Err(vm.new_type_error( "not all arguments converted during string formatting".to_string(), @@ -1396,7 +1396,7 @@ fn do_cformat( .into_iter() .nth(tuple_index) .is_some()) - && !objtype::isinstance(&values_obj, &vm.ctx.dict_type) + && !objtype::isinstance(&values_obj, &vm.ctx.types.dict_type) { return Err( vm.new_type_error("not all arguments converted during string formatting".to_string()) diff --git a/vm/src/obj/objsuper.rs b/vm/src/obj/objsuper.rs index a9fb668cb..754fe93d5 100644 --- a/vm/src/obj/objsuper.rs +++ b/vm/src/obj/objsuper.rs @@ -33,7 +33,7 @@ impl PyValue for PySuper { } pub fn init(context: &PyContext) { - let super_type = &context.super_type; + let super_type = &context.types.super_type; let super_doc = "super() -> same as super(__class__, )\n\ super(type) -> unbound super object\n\ diff --git a/vm/src/obj/objtuple.rs b/vm/src/obj/objtuple.rs index 5be1232c0..459f0e9bc 100644 --- a/vm/src/obj/objtuple.rs +++ b/vm/src/obj/objtuple.rs @@ -276,7 +276,7 @@ impl PyTupleIterator { #[rustfmt::skip] // to avoid line splitting pub fn init(context: &PyContext) { - let tuple_type = &context.tuple_type; + let tuple_type = &context.types.tuple_type; let tuple_doc = "tuple() -> empty tuple tuple(iterable) -> tuple initialized from iterable's items @@ -303,5 +303,5 @@ If the argument is a tuple, the return value is the same object."; "index" => context.new_rustfunc(PyTupleRef::index) }); - PyTupleIterator::extend_class(context, &context.tupleiterator_type); + PyTupleIterator::extend_class(context, &context.types.tupleiterator_type); } diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index 9df1a829f..68b2feba6 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -137,7 +137,7 @@ impl PyClassRef { if let Some(attr) = class_get_attr(&mcl, &name) { let attr_class = attr.class(); if class_has_attr(&attr_class, "__set__") { - if let Some(descriptor) = class_get_attr(&attr_class, "__get__") { + if let Some(ref descriptor) = class_get_attr(&attr_class, "__get__") { return vm.invoke( descriptor, vec![attr, self.into_object(), mcl.into_object()], @@ -148,7 +148,7 @@ impl PyClassRef { if let Some(attr) = class_get_attr(&self, &name) { let attr_class = attr.class(); - if let Some(descriptor) = class_get_attr(&attr_class, "__get__") { + if let Some(ref descriptor) = class_get_attr(&attr_class, "__get__") { let none = vm.get_none(); return vm.invoke(descriptor, vec![attr, none, self.into_object()]); } @@ -158,7 +158,7 @@ impl PyClassRef { Ok(cls_attr) } else if let Some(attr) = class_get_attr(&mcl, &name) { vm.call_get_descriptor(attr, self.into_object()) - } else if let Some(getter) = class_get_attr(&self, "__getattr__") { + } else if let Some(ref getter) = class_get_attr(&self, "__getattr__") { vm.invoke(getter, vec![mcl.into_object(), name_ref.into_object()]) } else { Err(vm.new_attribute_error(format!("{} has no attribute '{}'", self, name))) @@ -172,7 +172,7 @@ impl PyClassRef { vm: &VirtualMachine, ) -> PyResult<()> { if let Some(attr) = class_get_attr(&self.class(), &attr_name.value) { - if let Some(descriptor) = class_get_attr(&attr.class(), "__set__") { + if let Some(ref descriptor) = class_get_attr(&attr.class(), "__set__") { vm.invoke(descriptor, vec![attr, self.into_object(), value])?; return Ok(()); } @@ -212,7 +212,7 @@ pub fn init(ctx: &PyContext) { type(object) -> the object's type\n\ type(name, bases, dict) -> a new type"; - extend_class!(&ctx, &ctx.type_type, { + extend_class!(&ctx, &ctx.types.type_type, { "__call__" => ctx.new_rustfunc(type_call), "__dict__" => PropertyBuilder::new(ctx) @@ -288,11 +288,11 @@ pub fn type_call(class: PyClassRef, args: Args, kwargs: KwArgs, vm: &VirtualMach vm_trace!("type_call: {:?}", class); let new = class_get_attr(&class, "__new__").expect("All types should have a __new__."); let new_wrapped = vm.call_get_descriptor(new, class.into_object())?; - let obj = vm.invoke(new_wrapped, (&args, &kwargs))?; + let obj = vm.invoke(&new_wrapped, (&args, &kwargs))?; if let Some(init_method_or_err) = vm.get_method(obj.clone(), "__init__") { let init_method = init_method_or_err?; - let res = vm.invoke(init_method, (&args, &kwargs))?; + let res = vm.invoke(&init_method, (&args, &kwargs))?; if !res.is(&vm.get_none()) { return Err(vm.new_type_error("__init__ must return None".to_string())); } @@ -433,8 +433,8 @@ mod tests { #[test] fn test_linearise() { let context = PyContext::new(); - let object: PyClassRef = context.object.clone(); - let type_type = &context.type_type; + let object: PyClassRef = context.object(); + let type_type = &context.types.type_type; let a = new(type_type.clone(), "A", vec![object.clone()], HashMap::new()).unwrap(); let b = new(type_type.clone(), "B", vec![object.clone()], HashMap::new()).unwrap(); diff --git a/vm/src/obj/objweakproxy.rs b/vm/src/obj/objweakproxy.rs index 5d4f68d9d..f510a03ef 100644 --- a/vm/src/obj/objweakproxy.rs +++ b/vm/src/obj/objweakproxy.rs @@ -61,5 +61,5 @@ impl PyWeakProxy { } pub fn init(context: &PyContext) { - PyWeakProxy::extend_class(&context, &context.weakproxy_type); + PyWeakProxy::extend_class(&context, &context.types.weakproxy_type); } diff --git a/vm/src/obj/objweakref.rs b/vm/src/obj/objweakref.rs index b3b7e03c9..ae4375cd0 100644 --- a/vm/src/obj/objweakref.rs +++ b/vm/src/obj/objweakref.rs @@ -48,7 +48,7 @@ impl PyWeakRef { } pub fn init(context: &PyContext) { - extend_class!(context, &context.weakref_type, { + extend_class!(context, &context.types.weakref_type, { "__new__" => context.new_rustfunc(PyWeakRef::create), "__call__" => context.new_rustfunc(PyWeakRef::call) }); diff --git a/vm/src/obj/objzip.rs b/vm/src/obj/objzip.rs index d9c577aa0..0223b8bf2 100644 --- a/vm/src/obj/objzip.rs +++ b/vm/src/obj/objzip.rs @@ -51,8 +51,8 @@ impl PyZip { } pub fn init(context: &PyContext) { - PyZip::extend_class(context, &context.zip_type); - extend_class!(context, &context.zip_type, { + PyZip::extend_class(context, &context.types.zip_type); + extend_class!(context, &context.types.zip_type, { "__new__" => context.new_rustfunc(zip_new), }); } diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index ba40d5473..05049528c 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -1,12 +1,9 @@ use std::any::Any; use std::cell::Cell; -use std::cell::RefCell; use std::collections::HashMap; use std::fmt; use std::marker::PhantomData; -use std::mem; use std::ops::Deref; -use std::ptr; use std::rc::Rc; use num_bigint::BigInt; @@ -16,46 +13,30 @@ use num_traits::{One, Zero}; use crate::bytecode; use crate::exceptions; use crate::function::{IntoPyNativeFunc, PyFuncArgs}; -use crate::obj::objbool; use crate::obj::objbuiltinfunc::PyBuiltinFunction; use crate::obj::objbytearray; use crate::obj::objbytes; -use crate::obj::objclassmethod::{self, PyClassMethod}; +use crate::obj::objclassmethod::PyClassMethod; use crate::obj::objcode; use crate::obj::objcode::PyCodeRef; -use crate::obj::objcomplex::{self, PyComplex}; -use crate::obj::objdict::{self, PyDict, PyDictRef}; -use crate::obj::objellipsis; -use crate::obj::objenumerate; -use crate::obj::objfilter; -use crate::obj::objfloat::{self, PyFloat}; -use crate::obj::objframe; -use crate::obj::objfunction::{self, PyFunction, PyMethod}; -use crate::obj::objgenerator; -use crate::obj::objint::{self, PyInt, PyIntRef}; +use crate::obj::objcomplex::PyComplex; +use crate::obj::objdict::{PyDict, PyDictRef}; +use crate::obj::objfloat::PyFloat; +use crate::obj::objfunction::{PyFunction, PyMethod}; +use crate::obj::objint::{PyInt, PyIntRef}; use crate::obj::objiter; -use crate::obj::objlist::{self, PyList}; -use crate::obj::objmap; -use crate::obj::objmappingproxy; -use crate::obj::objmemory; -use crate::obj::objmodule::{self, PyModule}; -use crate::obj::objnamespace::{self, PyNamespace}; -use crate::obj::objnone::{self, PyNone, PyNoneRef}; +use crate::obj::objlist::PyList; +use crate::obj::objmodule::PyModule; +use crate::obj::objnamespace::PyNamespace; +use crate::obj::objnone::{PyNone, PyNoneRef}; use crate::obj::objobject; -use crate::obj::objproperty; use crate::obj::objproperty::PropertyBuilder; -use crate::obj::objrange; -use crate::obj::objset::{self, PySet}; -use crate::obj::objslice; -use crate::obj::objstaticmethod; +use crate::obj::objset::PySet; use crate::obj::objstr; -use crate::obj::objsuper; -use crate::obj::objtuple::{self, PyTuple, PyTupleRef}; +use crate::obj::objtuple::{PyTuple, PyTupleRef}; use crate::obj::objtype::{self, PyClass, PyClassRef}; -use crate::obj::objweakproxy; -use crate::obj::objweakref; -use crate::obj::objzip; use crate::scope::Scope; +use crate::types::{create_type, initialize_types, TypeZoo}; use crate::vm::VirtualMachine; use indexmap::IndexMap; @@ -112,71 +93,16 @@ impl fmt::Display for PyObject { #[derive(Debug)] pub struct PyContext { - pub bytes_type: PyClassRef, - pub bytesiterator_type: PyClassRef, - pub bytearray_type: PyClassRef, - pub bytearrayiterator_type: PyClassRef, - pub bool_type: PyClassRef, - pub classmethod_type: PyClassRef, - pub code_type: PyClassRef, - pub dict_type: PyClassRef, - pub ellipsis_type: PyClassRef, - pub enumerate_type: PyClassRef, - pub filter_type: PyClassRef, - pub float_type: PyClassRef, - pub frame_type: PyClassRef, - pub frozenset_type: PyClassRef, - pub generator_type: PyClassRef, - pub int_type: PyClassRef, - pub iter_type: PyClassRef, - pub complex_type: PyClassRef, pub true_value: PyIntRef, pub false_value: PyIntRef, - pub list_type: PyClassRef, - pub listiterator_type: PyClassRef, - pub listreverseiterator_type: PyClassRef, - pub striterator_type: PyClassRef, - pub strreverseiterator_type: PyClassRef, - pub dictkeyiterator_type: PyClassRef, - pub dictvalueiterator_type: PyClassRef, - pub dictitemiterator_type: PyClassRef, - pub dictkeys_type: PyClassRef, - pub dictvalues_type: PyClassRef, - pub dictitems_type: PyClassRef, - pub map_type: PyClassRef, - pub memoryview_type: PyClassRef, pub none: PyNoneRef, + pub empty_tuple: PyTupleRef, + pub ellipsis_type: PyClassRef, pub ellipsis: PyEllipsisRef, pub not_implemented: PyNotImplementedRef, - pub empty_tuple: PyTupleRef, - pub tuple_type: PyClassRef, - pub tupleiterator_type: PyClassRef, - pub set_type: PyClassRef, - pub staticmethod_type: PyClassRef, - pub super_type: PyClassRef, - pub str_type: PyClassRef, - pub range_type: PyClassRef, - pub rangeiterator_type: PyClassRef, - pub slice_type: PyClassRef, - pub type_type: PyClassRef, - pub zip_type: PyClassRef, - pub function_type: PyClassRef, - pub builtin_function_or_method_type: PyClassRef, - pub property_type: PyClassRef, - pub readonly_property_type: PyClassRef, - pub module_type: PyClassRef, - pub namespace_type: PyClassRef, - pub bound_method_type: PyClassRef, - pub weakref_type: PyClassRef, - pub weakproxy_type: PyClassRef, - pub mappingproxy_type: PyClassRef, - pub object: PyClassRef, - pub exceptions: exceptions::ExceptionZoo, -} -pub fn create_type(name: &str, type_type: &PyClassRef, base: &PyClassRef) -> PyClassRef { - let dict = PyAttributes::new(); - objtype::new(type_type.clone(), name, vec![base.clone()], dict).unwrap() + pub types: TypeZoo, + pub exceptions: exceptions::ExceptionZoo, } pub type PyNotImplementedRef = PyRef; @@ -201,115 +127,12 @@ impl PyValue for PyEllipsis { } } -fn init_type_hierarchy() -> (PyClassRef, PyClassRef) { - // `type` inherits from `object` - // and both `type` and `object are instances of `type`. - // to produce this circular dependency, we need an unsafe block. - // (and yes, this will never get dropped. TODO?) - let (type_type, object_type) = unsafe { - let object_type = PyObject { - typ: mem::uninitialized(), // ! - dict: None, - payload: PyClass { - name: String::from("object"), - mro: vec![], - subclasses: RefCell::new(vec![]), - attributes: RefCell::new(PyAttributes::new()), - }, - } - .into_ref(); - - let type_type = PyObject { - typ: mem::uninitialized(), // ! - dict: None, - payload: PyClass { - name: String::from("type"), - mro: vec![object_type.clone().downcast().unwrap()], - subclasses: RefCell::new(vec![]), - attributes: RefCell::new(PyAttributes::new()), - }, - } - .into_ref(); - - let object_type_ptr = PyObjectRef::into_raw(object_type.clone()) as *mut PyObject; - let type_type_ptr = PyObjectRef::into_raw(type_type.clone()) as *mut PyObject; - - let type_type: PyClassRef = type_type.downcast().unwrap(); - let object_type: PyClassRef = object_type.downcast().unwrap(); - - ptr::write(&mut (*object_type_ptr).typ, type_type.clone()); - ptr::write(&mut (*type_type_ptr).typ, type_type.clone()); - - (type_type, object_type) - }; - - object_type - .subclasses - .borrow_mut() - .push(objweakref::PyWeak::downgrade(&type_type.as_object())); - - (type_type, object_type) -} - // Basic objects: impl PyContext { pub fn new() -> Self { flame_guard!("init PyContext"); - let (type_type, object_type) = init_type_hierarchy(); - - let dict_type = create_type("dict", &type_type, &object_type); - let module_type = create_type("module", &type_type, &object_type); - let namespace_type = create_type("SimpleNamespace", &type_type, &object_type); - let classmethod_type = create_type("classmethod", &type_type, &object_type); - let staticmethod_type = create_type("staticmethod", &type_type, &object_type); - let function_type = create_type("function", &type_type, &object_type); - let builtin_function_or_method_type = - create_type("builtin_function_or_method", &type_type, &object_type); - let property_type = create_type("property", &type_type, &object_type); - let readonly_property_type = create_type("readonly_property", &type_type, &object_type); - let super_type = create_type("super", &type_type, &object_type); - let weakref_type = create_type("ref", &type_type, &object_type); - let weakproxy_type = create_type("weakproxy", &type_type, &object_type); - let generator_type = create_type("generator", &type_type, &object_type); - let bound_method_type = create_type("method", &type_type, &object_type); - let str_type = create_type("str", &type_type, &object_type); - let list_type = create_type("list", &type_type, &object_type); - let listiterator_type = create_type("list_iterator", &type_type, &object_type); - let listreverseiterator_type = - create_type("list_reverseiterator", &type_type, &object_type); - let striterator_type = create_type("str_iterator", &type_type, &object_type); - let strreverseiterator_type = create_type("str_reverseiterator", &type_type, &object_type); - let dictkeys_type = create_type("dict_keys", &type_type, &object_type); - let dictvalues_type = create_type("dict_values", &type_type, &object_type); - let dictitems_type = create_type("dict_items", &type_type, &object_type); - let dictkeyiterator_type = create_type("dict_keyiterator", &type_type, &object_type); - let dictvalueiterator_type = create_type("dict_valueiterator", &type_type, &object_type); - let dictitemiterator_type = create_type("dict_itemiterator", &type_type, &object_type); - let set_type = create_type("set", &type_type, &object_type); - let frozenset_type = create_type("frozenset", &type_type, &object_type); - let int_type = create_type("int", &type_type, &object_type); - let float_type = create_type("float", &type_type, &object_type); - let frame_type = create_type("frame", &type_type, &object_type); - let complex_type = create_type("complex", &type_type, &object_type); - let bytes_type = create_type("bytes", &type_type, &object_type); - let bytesiterator_type = create_type("bytes_iterator", &type_type, &object_type); - let bytearray_type = create_type("bytearray", &type_type, &object_type); - let bytearrayiterator_type = create_type("bytearray_iterator", &type_type, &object_type); - let tuple_type = create_type("tuple", &type_type, &object_type); - let tupleiterator_type = create_type("tuple_iterator", &type_type, &object_type); - let iter_type = create_type("iter", &type_type, &object_type); - let enumerate_type = create_type("enumerate", &type_type, &object_type); - let filter_type = create_type("filter", &type_type, &object_type); - let map_type = create_type("map", &type_type, &object_type); - let zip_type = create_type("zip", &type_type, &object_type); - let bool_type = create_type("bool", &type_type, &int_type); - let memoryview_type = create_type("memoryview", &type_type, &object_type); - let code_type = create_type("code", &type_type, &object_type); - let range_type = create_type("range", &type_type, &object_type); - let rangeiterator_type = create_type("range_iterator", &type_type, &object_type); - let slice_type = create_type("slice", &type_type, &object_type); - let mappingproxy_type = create_type("mappingproxy", &type_type, &object_type); - let exceptions = exceptions::ExceptionZoo::new(&type_type, &object_type); + let types = TypeZoo::new(); + let exceptions = exceptions::ExceptionZoo::new(&types.type_type, &types.object_type); fn create_object(payload: T, cls: &PyClassRef) -> PyRef { PyRef { @@ -318,297 +141,213 @@ impl PyContext { } } - let none_type = create_type("NoneType", &type_type, &object_type); + let none_type = create_type("NoneType", &types.type_type, &types.object_type); let none = create_object(PyNone, &none_type); - let ellipsis_type = create_type("EllipsisType", &type_type, &object_type); + let ellipsis_type = create_type("EllipsisType", &types.type_type, &types.object_type); let ellipsis = create_object(PyEllipsis, &ellipsis_type); - let not_implemented_type = create_type("NotImplementedType", &type_type, &object_type); + let not_implemented_type = + create_type("NotImplementedType", &types.type_type, &types.object_type); let not_implemented = create_object(PyNotImplemented, ¬_implemented_type); - let true_value = create_object(PyInt::new(BigInt::one()), &bool_type); - let false_value = create_object(PyInt::new(BigInt::zero()), &bool_type); + let true_value = create_object(PyInt::new(BigInt::one()), &types.bool_type); + let false_value = create_object(PyInt::new(BigInt::zero()), &types.bool_type); - let empty_tuple = create_object(PyTuple::from(vec![]), &tuple_type); + let empty_tuple = create_object(PyTuple::from(vec![]), &types.tuple_type); let context = PyContext { - bool_type, - memoryview_type, - bytearray_type, - bytearrayiterator_type, - bytes_type, - bytesiterator_type, - code_type, - complex_type, - classmethod_type, - int_type, - float_type, - frame_type, - staticmethod_type, - list_type, - listiterator_type, - listreverseiterator_type, - striterator_type, - strreverseiterator_type, - dictkeys_type, - dictvalues_type, - dictitems_type, - dictkeyiterator_type, - dictvalueiterator_type, - dictitemiterator_type, - set_type, - frozenset_type, true_value, false_value, - tuple_type, - tupleiterator_type, - iter_type, - ellipsis_type, - enumerate_type, - filter_type, - map_type, - zip_type, - dict_type, + not_implemented, none, ellipsis, - not_implemented, - str_type, - range_type, - rangeiterator_type, - slice_type, - object: object_type, - function_type, - builtin_function_or_method_type, - super_type, - mappingproxy_type, - property_type, - readonly_property_type, - generator_type, - module_type, - namespace_type, - bound_method_type, - weakref_type, - weakproxy_type, - type_type, + ellipsis_type, + + types, exceptions, empty_tuple, }; - objtype::init(&context); - objlist::init(&context); - objset::init(&context); - objtuple::init(&context); - objobject::init(&context); - objdict::init(&context); - objfunction::init(&context); - objstaticmethod::init(&context); - objclassmethod::init(&context); - objgenerator::init(&context); - objint::init(&context); - objfloat::init(&context); - objcomplex::init(&context); - objbytes::init(&context); - objbytearray::init(&context); - objproperty::init(&context); - objmemory::init(&context); - objstr::init(&context); - objrange::init(&context); - objslice::init(&context); - objsuper::init(&context); - objtuple::init(&context); - objiter::init(&context); - objellipsis::init(&context); - objenumerate::init(&context); - objfilter::init(&context); - objmap::init(&context); - objzip::init(&context); - objbool::init(&context); - objcode::init(&context); - objframe::init(&context); - objweakref::init(&context); - objweakproxy::init(&context); - objnone::init(&context); - objmodule::init(&context); - objnamespace::init(&context); - objmappingproxy::init(&context); + initialize_types(&context); + exceptions::init(&context); context } pub fn bytearray_type(&self) -> PyClassRef { - self.bytearray_type.clone() + self.types.bytearray_type.clone() } pub fn bytearrayiterator_type(&self) -> PyClassRef { - self.bytearrayiterator_type.clone() + self.types.bytearrayiterator_type.clone() } pub fn bytes_type(&self) -> PyClassRef { - self.bytes_type.clone() + self.types.bytes_type.clone() } pub fn bytesiterator_type(&self) -> PyClassRef { - self.bytesiterator_type.clone() + self.types.bytesiterator_type.clone() } pub fn code_type(&self) -> PyClassRef { - self.code_type.clone() + self.types.code_type.clone() } pub fn complex_type(&self) -> PyClassRef { - self.complex_type.clone() + self.types.complex_type.clone() } pub fn dict_type(&self) -> PyClassRef { - self.dict_type.clone() + self.types.dict_type.clone() } pub fn float_type(&self) -> PyClassRef { - self.float_type.clone() + self.types.float_type.clone() } pub fn frame_type(&self) -> PyClassRef { - self.frame_type.clone() + self.types.frame_type.clone() } pub fn int_type(&self) -> PyClassRef { - self.int_type.clone() + self.types.int_type.clone() } pub fn list_type(&self) -> PyClassRef { - self.list_type.clone() + self.types.list_type.clone() } pub fn listiterator_type(&self) -> PyClassRef { - self.listiterator_type.clone() + self.types.listiterator_type.clone() } pub fn listreverseiterator_type(&self) -> PyClassRef { - self.listreverseiterator_type.clone() + self.types.listreverseiterator_type.clone() } pub fn striterator_type(&self) -> PyClassRef { - self.striterator_type.clone() + self.types.striterator_type.clone() } pub fn strreverseiterator_type(&self) -> PyClassRef { - self.strreverseiterator_type.clone() + self.types.strreverseiterator_type.clone() } pub fn module_type(&self) -> PyClassRef { - self.module_type.clone() + self.types.module_type.clone() } pub fn namespace_type(&self) -> PyClassRef { - self.namespace_type.clone() + self.types.namespace_type.clone() } pub fn set_type(&self) -> PyClassRef { - self.set_type.clone() + self.types.set_type.clone() } pub fn range_type(&self) -> PyClassRef { - self.range_type.clone() + self.types.range_type.clone() } pub fn rangeiterator_type(&self) -> PyClassRef { - self.rangeiterator_type.clone() + self.types.rangeiterator_type.clone() } pub fn slice_type(&self) -> PyClassRef { - self.slice_type.clone() + self.types.slice_type.clone() } pub fn frozenset_type(&self) -> PyClassRef { - self.frozenset_type.clone() + self.types.frozenset_type.clone() } pub fn bool_type(&self) -> PyClassRef { - self.bool_type.clone() + self.types.bool_type.clone() } pub fn memoryview_type(&self) -> PyClassRef { - self.memoryview_type.clone() + self.types.memoryview_type.clone() } pub fn tuple_type(&self) -> PyClassRef { - self.tuple_type.clone() + self.types.tuple_type.clone() } pub fn tupleiterator_type(&self) -> PyClassRef { - self.tupleiterator_type.clone() + self.types.tupleiterator_type.clone() } pub fn iter_type(&self) -> PyClassRef { - self.iter_type.clone() + self.types.iter_type.clone() } pub fn enumerate_type(&self) -> PyClassRef { - self.enumerate_type.clone() + self.types.enumerate_type.clone() } pub fn filter_type(&self) -> PyClassRef { - self.filter_type.clone() + self.types.filter_type.clone() } pub fn map_type(&self) -> PyClassRef { - self.map_type.clone() + self.types.map_type.clone() } pub fn zip_type(&self) -> PyClassRef { - self.zip_type.clone() + self.types.zip_type.clone() } pub fn str_type(&self) -> PyClassRef { - self.str_type.clone() + self.types.str_type.clone() } pub fn super_type(&self) -> PyClassRef { - self.super_type.clone() + self.types.super_type.clone() } pub fn function_type(&self) -> PyClassRef { - self.function_type.clone() + self.types.function_type.clone() } pub fn builtin_function_or_method_type(&self) -> PyClassRef { - self.builtin_function_or_method_type.clone() + self.types.builtin_function_or_method_type.clone() } pub fn property_type(&self) -> PyClassRef { - self.property_type.clone() + self.types.property_type.clone() } pub fn readonly_property_type(&self) -> PyClassRef { - self.readonly_property_type.clone() + self.types.readonly_property_type.clone() } pub fn classmethod_type(&self) -> PyClassRef { - self.classmethod_type.clone() + self.types.classmethod_type.clone() } pub fn staticmethod_type(&self) -> PyClassRef { - self.staticmethod_type.clone() + self.types.staticmethod_type.clone() } pub fn generator_type(&self) -> PyClassRef { - self.generator_type.clone() + self.types.generator_type.clone() } pub fn bound_method_type(&self) -> PyClassRef { - self.bound_method_type.clone() + self.types.bound_method_type.clone() } pub fn weakref_type(&self) -> PyClassRef { - self.weakref_type.clone() + self.types.weakref_type.clone() } pub fn weakproxy_type(&self) -> PyClassRef { - self.weakproxy_type.clone() + self.types.weakproxy_type.clone() } pub fn type_type(&self) -> PyClassRef { - self.type_type.clone() + self.types.type_type.clone() } pub fn none(&self) -> PyObjectRef { @@ -624,7 +363,7 @@ impl PyContext { } pub fn object(&self) -> PyClassRef { - self.object.clone() + self.types.object_type.clone() } pub fn new_int>(&self, i: T) -> PyObjectRef { @@ -691,16 +430,6 @@ impl PyContext { objtype::new(self.type_type(), name, vec![base], PyAttributes::new()).unwrap() } - pub fn new_module(&self, name: &str, dict: PyDictRef) -> PyObjectRef { - PyObject::new( - PyModule { - name: name.to_string(), - }, - self.module_type.clone(), - Some(dict), - ) - } - pub fn new_namespace(&self) -> PyObjectRef { PyObject::new(PyNamespace, self.namespace_type(), Some(self.new_dict())) } @@ -948,7 +677,7 @@ pub struct PyCallable { impl PyCallable { #[inline] pub fn invoke(&self, args: impl Into, vm: &VirtualMachine) -> PyResult { - vm.invoke(self.obj.clone(), args) + vm.invoke(&self.obj, args) } #[inline] @@ -1103,8 +832,9 @@ impl PyIterable { /// This operation may fail if an exception is raised while invoking the /// `__iter__` method of the iterable object. pub fn iter<'a>(&self, vm: &'a VirtualMachine) -> PyResult> { + let method = &self.method; let iter_obj = vm.invoke( - self.method.clone(), + method, PyFuncArgs { args: vec![], kwargs: IndexMap::new(), diff --git a/vm/src/stdlib/errno.rs b/vm/src/stdlib/errno.rs index 0a8587087..6f82351f2 100644 --- a/vm/src/stdlib/errno.rs +++ b/vm/src/stdlib/errno.rs @@ -149,6 +149,96 @@ const ERROR_CODES: &[(&str, i32)] = &[ ("ERFKILL", libc::ERFKILL), ]; +#[cfg(all(unix, not(target_os = "linux")))] +const ERROR_CODES: &[(&str, i32)] = &[ + ("ENODEV", libc::ENODEV), + ("EHOSTUNREACH", libc::EHOSTUNREACH), + ("ENOMSG", libc::ENOMSG), + ("ENODATA", libc::ENODATA), + ("ENOTBLK", libc::ENOTBLK), + ("ENOSYS", libc::ENOSYS), + ("EPIPE", libc::EPIPE), + ("EINVAL", libc::EINVAL), + ("EOVERFLOW", libc::EOVERFLOW), + ("EINTR", libc::EINTR), + ("EUSERS", libc::EUSERS), + ("ENOTEMPTY", libc::ENOTEMPTY), + ("ENOBUFS", libc::ENOBUFS), + ("EPROTO", libc::EPROTO), + ("EREMOTE", libc::EREMOTE), + ("ECHILD", libc::ECHILD), + ("ELOOP", libc::ELOOP), + ("EXDEV", libc::EXDEV), + ("E2BIG", libc::E2BIG), + ("ESRCH", libc::ESRCH), + ("EMSGSIZE", libc::EMSGSIZE), + ("EAFNOSUPPORT", libc::EAFNOSUPPORT), + ("EHOSTDOWN", libc::EHOSTDOWN), + ("EPFNOSUPPORT", libc::EPFNOSUPPORT), + ("ENOPROTOOPT", libc::ENOPROTOOPT), + ("EBUSY", libc::EBUSY), + ("EAGAIN", libc::EAGAIN), + ("EISCONN", libc::EISCONN), + ("ESHUTDOWN", libc::ESHUTDOWN), + ("EBADF", libc::EBADF), + ("EMULTIHOP", libc::EMULTIHOP), + ("EIO", libc::EIO), + ("EPROTOTYPE", libc::EPROTOTYPE), + ("ENOSPC", libc::ENOSPC), + ("ENOEXEC", libc::ENOEXEC), + ("EALREADY", libc::EALREADY), + ("ENETDOWN", libc::ENETDOWN), + ("EACCES", libc::EACCES), + ("EILSEQ", libc::EILSEQ), + ("ENOTDIR", libc::ENOTDIR), + ("EPERM", libc::EPERM), + ("EDOM", libc::EDOM), + ("ECONNREFUSED", libc::ECONNREFUSED), + ("EISDIR", libc::EISDIR), + ("EPROTONOSUPPORT", libc::EPROTONOSUPPORT), + ("EROFS", libc::EROFS), + ("EADDRNOTAVAIL", libc::EADDRNOTAVAIL), + ("EIDRM", libc::EIDRM), + ("EBADMSG", libc::EBADMSG), + ("ENFILE", libc::ENFILE), + ("ESPIPE", libc::ESPIPE), + ("ENOLINK", libc::ENOLINK), + ("ENETRESET", libc::ENETRESET), + ("ETIMEDOUT", libc::ETIMEDOUT), + ("ENOENT", libc::ENOENT), + ("EEXIST", libc::EEXIST), + ("EDQUOT", libc::EDQUOT), + ("ENOSTR", libc::ENOSTR), + ("EFAULT", libc::EFAULT), + ("EFBIG", libc::EFBIG), + ("ENOTCONN", libc::ENOTCONN), + ("EDESTADDRREQ", libc::EDESTADDRREQ), + ("ENOLCK", libc::ENOLCK), + ("ECONNABORTED", libc::ECONNABORTED), + ("ENETUNREACH", libc::ENETUNREACH), + ("ESTALE", libc::ESTALE), + ("ENOSR", libc::ENOSR), + ("ENOMEM", libc::ENOMEM), + ("ENOTSOCK", libc::ENOTSOCK), + ("EMLINK", libc::EMLINK), + ("ERANGE", libc::ERANGE), + ("ECONNRESET", libc::ECONNRESET), + ("EADDRINUSE", libc::EADDRINUSE), + ("ENOTSUP", libc::ENOTSUP), + ("ENAMETOOLONG", libc::ENAMETOOLONG), + ("ENOTTY", libc::ENOTTY), + ("ESOCKTNOSUPPORT", libc::ESOCKTNOSUPPORT), + ("ETIME", libc::ETIME), + ("ETOOMANYREFS", libc::ETOOMANYREFS), + ("EMFILE", libc::EMFILE), + ("ETXTBSY", libc::ETXTBSY), + ("EINPROGRESS", libc::EINPROGRESS), + ("ENXIO", libc::ENXIO), + ("ECANCELED", libc::ECANCELED), + ("EOWNERDEAD", libc::EOWNERDEAD), + ("ENOTRECOVERABLE", libc::ENOTRECOVERABLE), +]; + #[cfg(windows)] const ERROR_CODES: &[(&str, i32)] = &[ ("ENODEV", 19), @@ -254,5 +344,5 @@ const ERROR_CODES: &[(&str, i32)] = &[ ("ENOTSUP", 129), ]; -#[cfg(not(any(target_os = "linux", windows)))] +#[cfg(not(any(unix, windows)))] const ERROR_CODES: &[(&str, i32)] = &[]; diff --git a/vm/src/stdlib/functools.rs b/vm/src/stdlib/functools.rs new file mode 100644 index 000000000..a35bede73 --- /dev/null +++ b/vm/src/stdlib/functools.rs @@ -0,0 +1,46 @@ +use crate::function::OptionalArg; +use crate::obj::objiter; +use crate::obj::objtype; +use crate::pyobject::{PyObjectRef, PyResult}; +use crate::vm::VirtualMachine; + +pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { + let ctx = &vm.ctx; + + py_module!(vm, "_functools", { + "reduce" => ctx.new_rustfunc(functools_reduce), + }) +} + +fn functools_reduce( + function: PyObjectRef, + sequence: PyObjectRef, + start_value: OptionalArg, + vm: &VirtualMachine, +) -> PyResult { + let iterator = objiter::get_iter(vm, &sequence)?; + + let start_value = if let OptionalArg::Present(val) = start_value { + val + } else { + objiter::call_next(vm, &iterator).map_err(|err| { + if objtype::isinstance(&err, &vm.ctx.exceptions.stop_iteration) { + let exc_type = vm.ctx.exceptions.type_error.clone(); + vm.new_exception( + exc_type, + "reduce() of empty sequence with no initial value".to_string(), + ) + } else { + err + } + })? + }; + + let mut accumulator = start_value; + + while let Ok(next_obj) = objiter::call_next(vm, &iterator) { + accumulator = vm.invoke(&function, vec![accumulator, next_obj])? + } + + Ok(accumulator) +} diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index 41c451f79..1178724f4 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -431,6 +431,31 @@ fn file_io_write(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { } } +#[cfg(windows)] +fn file_io_close(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { + use std::os::windows::io::IntoRawHandle; + arg_check!(vm, args, required = [(file_io, None)]); + let file_no = vm.get_attribute(file_io.clone(), "fileno")?; + let raw_fd = objint::get_value(&file_no).to_i64().unwrap(); + let handle = os::rust_file(raw_fd); + let raw_handle = handle.into_raw_handle(); + unsafe { + kernel32::CloseHandle(raw_handle); + } + Ok(vm.ctx.none()) +} + +#[cfg(unix)] +fn file_io_close(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { + arg_check!(vm, args, required = [(file_io, None)]); + let file_no = vm.get_attribute(file_io.clone(), "fileno")?; + let raw_fd = objint::get_value(&file_no).to_i32().unwrap(); + unsafe { + libc::close(raw_fd); + } + Ok(vm.ctx.none()) +} + fn file_io_seekable(vm: &VirtualMachine, _args: PyFuncArgs) -> PyResult { Ok(vm.ctx.new_bool(true)) } @@ -607,7 +632,7 @@ pub fn io_open(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { // This is subsequently consumed by a Buffered Class. let file_io_class = vm.get_attribute(io_module.clone(), "FileIO").unwrap(); let file_io_obj = vm.invoke( - file_io_class, + &file_io_class, vec![file.clone(), vm.ctx.new_str(mode.clone())], )?; @@ -620,13 +645,13 @@ pub fn io_open(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { let buffered_writer_class = vm .get_attribute(io_module.clone(), "BufferedWriter") .unwrap(); - vm.invoke(buffered_writer_class, vec![file_io_obj.clone()]) + vm.invoke(&buffered_writer_class, vec![file_io_obj.clone()]) } 'r' => { let buffered_reader_class = vm .get_attribute(io_module.clone(), "BufferedReader") .unwrap(); - vm.invoke(buffered_reader_class, vec![file_io_obj.clone()]) + vm.invoke(&buffered_reader_class, vec![file_io_obj.clone()]) } //TODO: updating => PyBufferedRandom _ => unimplemented!("'a' mode is not yet implemented"), @@ -637,7 +662,7 @@ pub fn io_open(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { // a TextIOWrapper which is subsequently returned. 't' => { let text_io_wrapper_class = vm.get_attribute(io_module, "TextIOWrapper").unwrap(); - vm.invoke(text_io_wrapper_class, vec![buffered.unwrap()]) + vm.invoke(&text_io_wrapper_class, vec![buffered.unwrap()]) } // If the mode is binary this Buffered class is returned directly at // this point. @@ -678,6 +703,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { "read" => ctx.new_rustfunc(file_io_read), "readinto" => ctx.new_rustfunc(file_io_readinto), "write" => ctx.new_rustfunc(file_io_write), + "close" => ctx.new_rustfunc(file_io_close), "seekable" => ctx.new_rustfunc(file_io_seekable) }); diff --git a/vm/src/stdlib/itertools.rs b/vm/src/stdlib/itertools.rs index 732020480..6039c178a 100644 --- a/vm/src/stdlib/itertools.rs +++ b/vm/src/stdlib/itertools.rs @@ -218,8 +218,9 @@ impl PyItertoolsStarmap { #[pymethod(name = "__next__")] fn next(&self, vm: &VirtualMachine) -> PyResult { let obj = call_next(vm, &self.iter)?; + let function = &self.function; - vm.invoke(self.function.clone(), vm.extract_elements(&obj)?) + vm.invoke(function, vm.extract_elements(&obj)?) } #[pymethod(name = "__iter__")] @@ -271,8 +272,9 @@ impl PyItertoolsTakewhile { // might be StopIteration or anything else, which is propaged upwwards let obj = call_next(vm, &self.iterable)?; + let predicate = &self.predicate; - let verdict = vm.invoke(self.predicate.clone(), vec![obj.clone()])?; + let verdict = vm.invoke(predicate, vec![obj.clone()])?; let verdict = objbool::boolval(vm, verdict)?; if verdict { Ok(obj) diff --git a/vm/src/stdlib/json.rs b/vm/src/stdlib/json.rs index 8b5d21b75..aa3fb8157 100644 --- a/vm/src/stdlib/json.rs +++ b/vm/src/stdlib/json.rs @@ -1,6 +1,7 @@ use crate::obj::objstr::PyStringRef; use crate::py_serde; -use crate::pyobject::{create_type, ItemProtocol, PyObjectRef, PyResult}; +use crate::pyobject::{ItemProtocol, PyObjectRef, PyResult}; +use crate::types::create_type; use crate::VirtualMachine; use serde_json; @@ -10,6 +11,12 @@ pub fn json_dumps(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult { serde_json::to_string(&serializer).map_err(|err| vm.new_type_error(err.to_string())) } +pub fn json_dump(obj: PyObjectRef, fs: PyObjectRef, vm: &VirtualMachine) -> PyResult { + let result = json_dumps(obj, vm)?; + vm.call_method(&fs, "write", vec![vm.new_str(result)])?; + Ok(vm.get_none()) +} + /// Implement json.loads pub fn json_loads(string: PyStringRef, vm: &VirtualMachine) -> PyResult { // TODO: Implement non-trivial deserialization case @@ -33,19 +40,26 @@ pub fn json_loads(string: PyStringRef, vm: &VirtualMachine) -> PyResult { }) } +pub fn json_load(fp: PyObjectRef, vm: &VirtualMachine) -> PyResult { + let result = vm.call_method(&fp, "read", vec![])?; + json_loads(result.downcast()?, vm) +} + pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; // TODO: Make this a proper type with a constructor let json_decode_error = create_type( "JSONDecodeError", - &ctx.type_type, + &ctx.types.type_type, &ctx.exceptions.exception_type, ); py_module!(vm, "json", { "dumps" => ctx.new_rustfunc(json_dumps), + "dump" => ctx.new_rustfunc(json_dump), "loads" => ctx.new_rustfunc(json_loads), + "load" => ctx.new_rustfunc(json_load), "JSONDecodeError" => json_decode_error }) } diff --git a/vm/src/stdlib/marshal.rs b/vm/src/stdlib/marshal.rs index e7afc86d2..86f542ff6 100644 --- a/vm/src/stdlib/marshal.rs +++ b/vm/src/stdlib/marshal.rs @@ -1,17 +1,17 @@ use crate::bytecode; use crate::obj::objbytes::{PyBytes, PyBytesRef}; use crate::obj::objcode::{PyCode, PyCodeRef}; -use crate::pyobject::{IntoPyObject, PyObjectRef, PyResult}; +use crate::pyobject::{PyObjectRef, PyResult}; use crate::vm::VirtualMachine; -fn marshal_dumps(co: PyCodeRef, vm: &VirtualMachine) -> PyResult { - PyBytes::new(bincode::serialize(&co.code).unwrap()).into_pyobject(vm) +fn marshal_dumps(co: PyCodeRef, _vm: &VirtualMachine) -> PyBytes { + PyBytes::new(bincode::serialize(&co.code).unwrap()) } -fn marshal_loads(code_bytes: PyBytesRef, vm: &VirtualMachine) -> PyResult { - let code = bincode::deserialize::(&code_bytes).unwrap(); - let pycode = PyCode { code }; - pycode.into_pyobject(vm) +fn marshal_loads(code_bytes: PyBytesRef, vm: &VirtualMachine) -> PyResult { + let code = bincode::deserialize::(&code_bytes) + .map_err(|_| vm.new_value_error("Couldn't deserialize python bytecode".to_owned()))?; + Ok(PyCode { code }) } pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { @@ -19,6 +19,6 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { py_module!(vm, "marshal", { "loads" => ctx.new_rustfunc(marshal_loads), - "dumps" => ctx.new_rustfunc(marshal_dumps) + "dumps" => ctx.new_rustfunc(marshal_dumps), }) } diff --git a/vm/src/stdlib/math.rs b/vm/src/stdlib/math.rs index 36dad8bca..3c2779f1e 100644 --- a/vm/src/stdlib/math.rs +++ b/vm/src/stdlib/math.rs @@ -181,7 +181,7 @@ fn try_magic_method(func_name: &str, vm: &VirtualMachine, value: &PyObjectRef) - func_name, ) })?; - vm.invoke(method, vec![]) + vm.invoke(&method, vec![]) } fn math_trunc(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { @@ -191,7 +191,7 @@ fn math_trunc(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { fn math_ceil(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(value, None)]); - if objtype::isinstance(value, &vm.ctx.float_type) { + if objtype::isinstance(value, &vm.ctx.float_type()) { let v = objfloat::get_value(value); Ok(vm.ctx.new_float(v.ceil())) } else { @@ -201,7 +201,7 @@ fn math_ceil(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { fn math_floor(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(value, None)]); - if objtype::isinstance(value, &vm.ctx.float_type) { + if objtype::isinstance(value, &vm.ctx.float_type()) { let v = objfloat::get_value(value); Ok(vm.ctx.new_float(v.floor())) } else { diff --git a/vm/src/stdlib/mod.rs b/vm/src/stdlib/mod.rs index 51ab96e52..076274dc3 100644 --- a/vm/src/stdlib/mod.rs +++ b/vm/src/stdlib/mod.rs @@ -5,6 +5,7 @@ mod codecs; mod collections; mod dis; mod errno; +mod functools; mod hashlib; mod imp; mod itertools; @@ -57,6 +58,7 @@ pub fn get_module_inits() -> HashMap { "dis".to_string() => Box::new(dis::make_module), "_codecs".to_string() => Box::new(codecs::make_module), "_collections".to_string() => Box::new(collections::make_module), + "_functools".to_string() => Box::new(functools::make_module), "errno".to_string() => Box::new(errno::make_module), "hashlib".to_string() => Box::new(hashlib::make_module), "itertools".to_string() => Box::new(itertools::make_module), diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index aec771841..d0f1c4fe6 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -316,6 +316,15 @@ fn _os_environ(vm: &VirtualMachine) -> PyDictRef { environ } +fn os_readlink(path: PyStringRef, dir_fd: DirFd, vm: &VirtualMachine) -> PyResult { + let path = make_path(vm, path, &dir_fd); + let path = fs::read_link(path.as_str()).map_err(|err| convert_io_error(vm, err))?; + let path = path.into_os_string().into_string().map_err(|_osstr| { + vm.new_unicode_decode_error("Can't convert OS path to valid UTF-8 string".into()) + })?; + Ok(vm.ctx.new_str(path)) +} + #[derive(Debug)] struct DirEntry { entry: fs::DirEntry, @@ -964,7 +973,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { // mkfifo Some Some None // mknod Some Some None // pathconf Some None None - // readlink Some Some None + SupportFunc::new(vm, "readlink", os_readlink, Some(false), Some(false), None), SupportFunc::new(vm, "remove", os_remove, Some(false), Some(false), None), SupportFunc::new(vm, "rename", os_rename, Some(false), Some(false), None), SupportFunc::new(vm, "replace", os_rename, Some(false), Some(false), None), // TODO: Fix replace diff --git a/vm/src/stdlib/signal.rs b/vm/src/stdlib/signal.rs index d72085ea0..2950282b1 100644 --- a/vm/src/stdlib/signal.rs +++ b/vm/src/stdlib/signal.rs @@ -92,7 +92,7 @@ pub fn check_signals(vm: &VirtualMachine) { .get(&(signum as i32)) .expect("Handler should be set") .clone(); - vm.invoke(handler, vec![vm.new_int(signum), vm.get_none()]) + vm.invoke(&handler, vec![vm.new_int(signum), vm.get_none()]) .expect("Test"); } } diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index 9040c14ff..1a111d7ea 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -21,6 +21,7 @@ use crate::vm::VirtualMachine; use crate::obj::objtype::PyClassRef; #[cfg(unix)] use crate::stdlib::os::convert_nix_error; +use num_bigint::Sign; use num_traits::ToPrimitive; #[derive(Debug, Copy, Clone)] @@ -409,6 +410,17 @@ fn socket_inet_ntoa(packed_ip: PyBytesRef, vm: &VirtualMachine) -> PyResult { Ok(vm.new_str(Ipv4Addr::from(ip_num).to_string())) } +fn socket_htonl(host: PyIntRef, vm: &VirtualMachine) -> PyResult { + if host.as_bigint().sign() == Sign::Minus { + return Err( + vm.new_overflow_error("can't convert negative value to unsigned int".to_string()) + ); + } + + let host = host.as_bigint().to_u32().unwrap(); + Ok(vm.new_int(host.to_be())) +} + pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; @@ -435,6 +447,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { "inet_aton" => ctx.new_rustfunc(socket_inet_aton), "inet_ntoa" => ctx.new_rustfunc(socket_inet_ntoa), "gethostname" => ctx.new_rustfunc(socket_gethostname), + "htonl" => ctx.new_rustfunc(socket_htonl), }); extend_module_platform_specific(vm, module) diff --git a/vm/src/stdlib/thread.rs b/vm/src/stdlib/thread.rs index 414e7d72e..225001c4d 100644 --- a/vm/src/stdlib/thread.rs +++ b/vm/src/stdlib/thread.rs @@ -37,7 +37,7 @@ fn get_ident(_vm: &VirtualMachine) -> u32 { fn allocate_lock(vm: &VirtualMachine) -> PyResult { let lock_class = vm.class("_thread", "RLock"); - vm.invoke(lock_class.into_object(), vec![]) + vm.invoke(&lock_class.into_object(), vec![]) } pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { diff --git a/vm/src/stdlib/zlib.rs b/vm/src/stdlib/zlib.rs index b54d82425..59ccf0b8e 100644 --- a/vm/src/stdlib/zlib.rs +++ b/vm/src/stdlib/zlib.rs @@ -1,6 +1,7 @@ use crate::function::OptionalArg; use crate::obj::{objbytes::PyBytesRef, objint::PyIntRef}; -use crate::pyobject::{create_type, ItemProtocol, PyObjectRef, PyResult}; +use crate::pyobject::{ItemProtocol, PyObjectRef, PyResult}; +use crate::types::create_type; use crate::vm::VirtualMachine; use adler32::RollingAdler32 as Adler32; @@ -18,7 +19,11 @@ const DEF_BUF_SIZE: usize = 16 * 1024; pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; - let zlib_error = create_type("error", &ctx.type_type, &ctx.exceptions.exception_type); + let zlib_error = create_type( + "error", + &ctx.types.type_type, + &ctx.exceptions.exception_type, + ); py_module!(vm, "zlib", { "crc32" => ctx.new_rustfunc(zlib_crc32), diff --git a/vm/src/types.rs b/vm/src/types.rs new file mode 100644 index 000000000..048b3d8ad --- /dev/null +++ b/vm/src/types.rs @@ -0,0 +1,313 @@ +use crate::obj::objbool; +use crate::obj::objbytearray; +use crate::obj::objbytes; +use crate::obj::objclassmethod; +use crate::obj::objcode; +use crate::obj::objcomplex; +use crate::obj::objdict; +use crate::obj::objellipsis; +use crate::obj::objenumerate; +use crate::obj::objfilter; +use crate::obj::objfloat; +use crate::obj::objframe; +use crate::obj::objfunction; +use crate::obj::objgenerator; +use crate::obj::objint; +use crate::obj::objiter; +use crate::obj::objlist; +use crate::obj::objmap; +use crate::obj::objmappingproxy; +use crate::obj::objmemory; +use crate::obj::objmodule; +use crate::obj::objnamespace; +use crate::obj::objnone; +use crate::obj::objobject; +use crate::obj::objproperty; +use crate::obj::objrange; +use crate::obj::objset; +use crate::obj::objslice; +use crate::obj::objstaticmethod; +use crate::obj::objstr; +use crate::obj::objsuper; +use crate::obj::objtuple; +use crate::obj::objtype::{self, PyClass, PyClassRef}; +use crate::obj::objweakproxy; +use crate::obj::objweakref; +use crate::obj::objzip; +use crate::pyobject::{PyAttributes, PyContext, PyObject, PyObjectRef}; +use std::cell::RefCell; +use std::mem; +use std::ptr; + +/// Holder of references to builtin types. +#[derive(Debug)] +pub struct TypeZoo { + pub bytes_type: PyClassRef, + pub bytesiterator_type: PyClassRef, + pub bytearray_type: PyClassRef, + pub bytearrayiterator_type: PyClassRef, + pub bool_type: PyClassRef, + pub classmethod_type: PyClassRef, + pub code_type: PyClassRef, + pub dict_type: PyClassRef, + pub enumerate_type: PyClassRef, + pub filter_type: PyClassRef, + pub float_type: PyClassRef, + pub frame_type: PyClassRef, + pub frozenset_type: PyClassRef, + pub generator_type: PyClassRef, + pub int_type: PyClassRef, + pub iter_type: PyClassRef, + pub complex_type: PyClassRef, + pub list_type: PyClassRef, + pub listiterator_type: PyClassRef, + pub listreverseiterator_type: PyClassRef, + pub striterator_type: PyClassRef, + pub strreverseiterator_type: PyClassRef, + pub dictkeyiterator_type: PyClassRef, + pub dictvalueiterator_type: PyClassRef, + pub dictitemiterator_type: PyClassRef, + pub dictkeys_type: PyClassRef, + pub dictvalues_type: PyClassRef, + pub dictitems_type: PyClassRef, + pub map_type: PyClassRef, + pub memoryview_type: PyClassRef, + pub tuple_type: PyClassRef, + pub tupleiterator_type: PyClassRef, + pub set_type: PyClassRef, + pub staticmethod_type: PyClassRef, + pub super_type: PyClassRef, + pub str_type: PyClassRef, + pub range_type: PyClassRef, + pub rangeiterator_type: PyClassRef, + pub slice_type: PyClassRef, + pub type_type: PyClassRef, + pub zip_type: PyClassRef, + pub function_type: PyClassRef, + pub builtin_function_or_method_type: PyClassRef, + pub property_type: PyClassRef, + pub readonly_property_type: PyClassRef, + pub module_type: PyClassRef, + pub namespace_type: PyClassRef, + pub bound_method_type: PyClassRef, + pub weakref_type: PyClassRef, + pub weakproxy_type: PyClassRef, + pub mappingproxy_type: PyClassRef, + pub object_type: PyClassRef, +} + +impl Default for TypeZoo { + fn default() -> Self { + Self::new() + } +} + +impl TypeZoo { + pub fn new() -> Self { + let (type_type, object_type) = init_type_hierarchy(); + + let dict_type = create_type("dict", &type_type, &object_type); + let module_type = create_type("module", &type_type, &object_type); + let namespace_type = create_type("SimpleNamespace", &type_type, &object_type); + let classmethod_type = create_type("classmethod", &type_type, &object_type); + let staticmethod_type = create_type("staticmethod", &type_type, &object_type); + let function_type = create_type("function", &type_type, &object_type); + let builtin_function_or_method_type = + create_type("builtin_function_or_method", &type_type, &object_type); + let property_type = create_type("property", &type_type, &object_type); + let readonly_property_type = create_type("readonly_property", &type_type, &object_type); + let super_type = create_type("super", &type_type, &object_type); + let weakref_type = create_type("ref", &type_type, &object_type); + let weakproxy_type = create_type("weakproxy", &type_type, &object_type); + let generator_type = create_type("generator", &type_type, &object_type); + let bound_method_type = create_type("method", &type_type, &object_type); + let str_type = create_type("str", &type_type, &object_type); + let list_type = create_type("list", &type_type, &object_type); + let listiterator_type = create_type("list_iterator", &type_type, &object_type); + let listreverseiterator_type = + create_type("list_reverseiterator", &type_type, &object_type); + let striterator_type = create_type("str_iterator", &type_type, &object_type); + let strreverseiterator_type = create_type("str_reverseiterator", &type_type, &object_type); + let dictkeys_type = create_type("dict_keys", &type_type, &object_type); + let dictvalues_type = create_type("dict_values", &type_type, &object_type); + let dictitems_type = create_type("dict_items", &type_type, &object_type); + let dictkeyiterator_type = create_type("dict_keyiterator", &type_type, &object_type); + let dictvalueiterator_type = create_type("dict_valueiterator", &type_type, &object_type); + let dictitemiterator_type = create_type("dict_itemiterator", &type_type, &object_type); + let set_type = create_type("set", &type_type, &object_type); + let frozenset_type = create_type("frozenset", &type_type, &object_type); + let int_type = create_type("int", &type_type, &object_type); + let float_type = create_type("float", &type_type, &object_type); + let frame_type = create_type("frame", &type_type, &object_type); + let complex_type = create_type("complex", &type_type, &object_type); + let bytes_type = create_type("bytes", &type_type, &object_type); + let bytesiterator_type = create_type("bytes_iterator", &type_type, &object_type); + let bytearray_type = create_type("bytearray", &type_type, &object_type); + let bytearrayiterator_type = create_type("bytearray_iterator", &type_type, &object_type); + let tuple_type = create_type("tuple", &type_type, &object_type); + let tupleiterator_type = create_type("tuple_iterator", &type_type, &object_type); + let iter_type = create_type("iter", &type_type, &object_type); + let enumerate_type = create_type("enumerate", &type_type, &object_type); + let filter_type = create_type("filter", &type_type, &object_type); + let map_type = create_type("map", &type_type, &object_type); + let zip_type = create_type("zip", &type_type, &object_type); + let bool_type = create_type("bool", &type_type, &int_type); + let memoryview_type = create_type("memoryview", &type_type, &object_type); + let code_type = create_type("code", &type_type, &object_type); + let range_type = create_type("range", &type_type, &object_type); + let rangeiterator_type = create_type("range_iterator", &type_type, &object_type); + let slice_type = create_type("slice", &type_type, &object_type); + let mappingproxy_type = create_type("mappingproxy", &type_type, &object_type); + + Self { + bool_type, + memoryview_type, + bytearray_type, + bytearrayiterator_type, + bytes_type, + bytesiterator_type, + code_type, + complex_type, + classmethod_type, + int_type, + float_type, + frame_type, + staticmethod_type, + list_type, + listiterator_type, + listreverseiterator_type, + striterator_type, + strreverseiterator_type, + dictkeys_type, + dictvalues_type, + dictitems_type, + dictkeyiterator_type, + dictvalueiterator_type, + dictitemiterator_type, + set_type, + frozenset_type, + tuple_type, + tupleiterator_type, + iter_type, + enumerate_type, + filter_type, + map_type, + zip_type, + dict_type, + str_type, + range_type, + rangeiterator_type, + slice_type, + object_type, + function_type, + builtin_function_or_method_type, + super_type, + mappingproxy_type, + property_type, + readonly_property_type, + generator_type, + module_type, + namespace_type, + bound_method_type, + weakref_type, + weakproxy_type, + type_type, + } + } +} + +pub fn create_type(name: &str, type_type: &PyClassRef, base: &PyClassRef) -> PyClassRef { + let dict = PyAttributes::new(); + objtype::new(type_type.clone(), name, vec![base.clone()], dict).unwrap() +} + +fn init_type_hierarchy() -> (PyClassRef, PyClassRef) { + // `type` inherits from `object` + // and both `type` and `object are instances of `type`. + // to produce this circular dependency, we need an unsafe block. + // (and yes, this will never get dropped. TODO?) + let (type_type, object_type) = unsafe { + let object_type = PyObject { + typ: mem::uninitialized(), // ! + dict: None, + payload: PyClass { + name: String::from("object"), + mro: vec![], + subclasses: RefCell::new(vec![]), + attributes: RefCell::new(PyAttributes::new()), + }, + } + .into_ref(); + + let type_type = PyObject { + typ: mem::uninitialized(), // ! + dict: None, + payload: PyClass { + name: String::from("type"), + mro: vec![object_type.clone().downcast().unwrap()], + subclasses: RefCell::new(vec![]), + attributes: RefCell::new(PyAttributes::new()), + }, + } + .into_ref(); + + let object_type_ptr = PyObjectRef::into_raw(object_type.clone()) as *mut PyObject; + let type_type_ptr = PyObjectRef::into_raw(type_type.clone()) as *mut PyObject; + + let type_type: PyClassRef = type_type.downcast().unwrap(); + let object_type: PyClassRef = object_type.downcast().unwrap(); + + ptr::write(&mut (*object_type_ptr).typ, type_type.clone()); + ptr::write(&mut (*type_type_ptr).typ, type_type.clone()); + + (type_type, object_type) + }; + + object_type + .subclasses + .borrow_mut() + .push(objweakref::PyWeak::downgrade(&type_type.as_object())); + + (type_type, object_type) +} + +/// Fill attributes of builtin types. +pub fn initialize_types(context: &PyContext) { + objtype::init(&context); + objlist::init(&context); + objset::init(&context); + objtuple::init(&context); + objobject::init(&context); + objdict::init(&context); + objfunction::init(&context); + objstaticmethod::init(&context); + objclassmethod::init(&context); + objgenerator::init(&context); + objint::init(&context); + objfloat::init(&context); + objcomplex::init(&context); + objbytes::init(&context); + objbytearray::init(&context); + objproperty::init(&context); + objmemory::init(&context); + objstr::init(&context); + objrange::init(&context); + objslice::init(&context); + objsuper::init(&context); + objtuple::init(&context); + objiter::init(&context); + objellipsis::init(&context); + objenumerate::init(&context); + objfilter::init(&context); + objmap::init(&context); + objzip::init(&context); + objbool::init(&context); + objcode::init(&context); + objframe::init(&context); + objweakref::init(&context); + objweakproxy::init(&context); + objnone::init(&context); + objmodule::init(&context); + objnamespace::init(&context); + objmappingproxy::init(&context); +} diff --git a/vm/src/vm.rs b/vm/src/vm.rs index da3348924..ce9382eaf 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -25,6 +25,7 @@ use crate::obj::objfunction::{PyFunction, PyMethod}; use crate::obj::objgenerator::PyGenerator; use crate::obj::objint::PyInt; use crate::obj::objiter; +use crate::obj::objmodule::{self, PyModule}; use crate::obj::objsequence; use crate::obj::objstr::{PyString, PyStringRef}; use crate::obj::objtuple::PyTupleRef; @@ -32,8 +33,8 @@ use crate::obj::objtype; use crate::obj::objtype::PyClassRef; use crate::pyhash; use crate::pyobject::{ - IdProtocol, ItemProtocol, PyContext, PyObjectRef, PyResult, PyValue, TryFromObject, TryIntoRef, - TypeProtocol, + IdProtocol, ItemProtocol, PyContext, PyObject, PyObjectRef, PyResult, PyValue, TryFromObject, + TryIntoRef, TypeProtocol, }; use crate::scope::Scope; use crate::stdlib; @@ -142,9 +143,23 @@ impl VirtualMachine { flame_guard!("init VirtualMachine"); let ctx = PyContext::new(); + // make a new module without access to the vm; doesn't + // set __spec__, __loader__, etc. attributes + let new_module = |name: &str, dict| { + PyObject::new( + PyModule { + name: name.to_owned(), + }, + ctx.types.module_type.clone(), + Some(dict), + ) + }; + // Hard-core modules: - let builtins = ctx.new_module("builtins", ctx.new_dict()); - let sysmod = ctx.new_module("sys", ctx.new_dict()); + let builtins_dict = ctx.new_dict(); + let builtins = new_module("builtins", builtins_dict.clone()); + let sysmod_dict = ctx.new_dict(); + let sysmod = new_module("sys", sysmod_dict.clone()); let stdlib_inits = RefCell::new(stdlib::get_module_inits()); let frozen = RefCell::new(frozen::get_module_inits()); @@ -168,6 +183,19 @@ impl VirtualMachine { signal_handlers: Default::default(), }; + objmodule::init_module_dict( + &vm, + &builtins_dict, + vm.new_str("builtins".to_owned()), + vm.get_none(), + ); + objmodule::init_module_dict( + &vm, + &sysmod_dict, + vm.new_str("sys".to_owned()), + vm.get_none(), + ); + builtins::make_module(&vm, builtins.clone()); sysmodule::make_module(&vm, sysmod, builtins); vm @@ -254,11 +282,22 @@ impl VirtualMachine { self.ctx.new_bool(b) } + pub fn new_module(&self, name: &str, dict: PyDictRef) -> PyObjectRef { + objmodule::init_module_dict(self, &dict, self.new_str(name.to_owned()), self.get_none()); + PyObject::new( + PyModule { + name: name.to_owned(), + }, + self.ctx.types.module_type.clone(), + Some(dict), + ) + } + #[cfg_attr(feature = "flame-it", flame("VirtualMachine"))] fn new_exception_obj(&self, exc_type: PyClassRef, args: Vec) -> PyResult { // TODO: add repr of args into logging? vm_trace!("New exception created: {}", exc_type.name); - self.invoke(exc_type.into_object(), args) + self.invoke(&exc_type.into_object(), args) } pub fn new_empty_exception(&self, exc_type: PyClassRef) -> PyResult { @@ -407,10 +446,23 @@ impl VirtualMachine { } pub fn import(&self, module: &str, from_list: &PyObjectRef, level: usize) -> PyResult { - let sys_modules = self.get_attribute(self.sys_module.clone(), "modules")?; - sys_modules - .get_item(module.to_string(), self) - .or_else(|_| { + // if the import inputs seem weird, e.g a package import or something, rather than just + // a straight `import ident` + let weird = module.contains('.') + || level != 0 + || objbool::boolval(self, from_list.clone()).unwrap_or(true); + + let module = self.new_str(module.to_owned()); + + let cached_module = if weird { + None + } else { + let sys_modules = self.get_attribute(self.sys_module.clone(), "modules")?; + sys_modules.get_item(module.clone(), self).ok() + }; + match cached_module { + Some(module) => Ok(module), + None => { let import_func = self .get_attribute(self.builtins.clone(), "__import__") .map_err(|_| self.new_import_error("__import__ not found".to_string()))?; @@ -424,17 +476,18 @@ impl VirtualMachine { (self.get_none(), self.get_none()) }; self.invoke( - import_func, + &import_func, vec![ - self.ctx.new_str(module.to_string()), + module, globals, locals, from_list.clone(), self.ctx.new_int(level), ], ) - }) - .map_err(|exc| import::remove_importlib_frames(self, &exc)) + .map_err(|exc| import::remove_importlib_frames(self, &exc)) + } + } } /// Determines if `obj` is an instance of `cls`, either directly, indirectly or virtually via @@ -463,7 +516,7 @@ impl VirtualMachine { pub fn call_get_descriptor(&self, attr: PyObjectRef, obj: PyObjectRef) -> PyResult { let attr_class = attr.class(); - if let Some(descriptor) = objtype::class_get_attr(&attr_class, "__get__") { + if let Some(ref descriptor) = objtype::class_get_attr(&attr_class, "__get__") { let cls = obj.class(); self.invoke(descriptor, vec![attr, obj.clone(), cls.into_object()]) } else { @@ -487,14 +540,14 @@ impl VirtualMachine { func ); let wrapped = self.call_get_descriptor(func, obj.clone())?; - self.invoke(wrapped, args) + self.invoke(&wrapped, args) } None => Err(self.new_type_error(format!("Unsupported method: {}", method_name))), } } #[cfg_attr(feature = "flame-it", flame("VirtualMachine"))] - fn _invoke(&self, func_ref: PyObjectRef, args: PyFuncArgs) -> PyResult { + fn _invoke(&self, func_ref: &PyObjectRef, args: PyFuncArgs) -> PyResult { vm_trace!("Invoke: {:?} {:?}", func_ref, args); if let Some(PyFunction { @@ -513,7 +566,7 @@ impl VirtualMachine { ref object, }) = func_ref.payload() { - self.invoke(function.clone(), args.insert(object.clone())) + self.invoke(&function, args.insert(object.clone())) } else if let Some(PyBuiltinFunction { ref value }) = func_ref.payload() { value(self, args) } else { @@ -523,9 +576,8 @@ impl VirtualMachine { } } - // TODO: make func_ref an &PyObjectRef #[inline] - pub fn invoke(&self, func_ref: PyObjectRef, args: T) -> PyResult + pub fn invoke(&self, func_ref: &PyObjectRef, args: T) -> PyResult where T: Into, { @@ -546,7 +598,7 @@ impl VirtualMachine { let trace_func = self.trace_func.borrow().clone(); if !self.is_none(&trace_func) { self.use_tracing.replace(false); - let res = self.invoke(trace_func, args.clone()); + let res = self.invoke(&trace_func, args.clone()); self.use_tracing.replace(true); res?; } @@ -554,7 +606,7 @@ impl VirtualMachine { let profile_func = self.profile_func.borrow().clone(); if !self.is_none(&profile_func) { self.use_tracing.replace(false); - let res = self.invoke(profile_func, args); + let res = self.invoke(&profile_func, args); self.use_tracing.replace(true); res?; } @@ -592,7 +644,7 @@ impl VirtualMachine { pub fn invoke_with_locals( &self, - function: PyObjectRef, + function: &PyObjectRef, cells: PyDictRef, locals: PyDictRef, ) -> PyResult { @@ -605,7 +657,7 @@ impl VirtualMachine { } panic!( "invoke_with_locals: expected python function, got: {:?}", - function + *function ); } @@ -831,7 +883,7 @@ impl VirtualMachine { { if let Some(method_or_err) = self.get_method(obj.clone(), method) { let method = method_or_err?; - let result = self.invoke(method, vec![arg.clone()])?; + let result = self.invoke(&method, vec![arg.clone()])?; if !result.is(&self.ctx.not_implemented()) { return Ok(result); } @@ -864,6 +916,43 @@ impl VirtualMachine { }) } + pub fn generic_getattribute( + &self, + obj: PyObjectRef, + name_str: PyStringRef, + ) -> PyResult> { + let name = name_str.as_str(); + let cls = obj.class(); + + if let Some(attr) = objtype::class_get_attr(&cls, &name) { + let attr_class = attr.class(); + if objtype::class_has_attr(&attr_class, "__set__") { + if let Some(descriptor) = objtype::class_get_attr(&attr_class, "__get__") { + return self + .invoke(&descriptor, vec![attr, obj, cls.into_object()]) + .map(Some); + } + } + } + + let attr = if let Some(ref dict) = obj.dict { + dict.get_item_option(name_str.clone(), self)? + } else { + None + }; + + if let Some(obj_attr) = attr { + Ok(Some(obj_attr)) + } else if let Some(attr) = objtype::class_get_attr(&cls, &name) { + self.call_get_descriptor(attr, obj).map(Some) + } else if let Some(getter) = objtype::class_get_attr(&cls, "__getattr__") { + self.invoke(&getter, vec![obj, name_str.into_object()]) + .map(Some) + } else { + Ok(None) + } + } + pub fn is_callable(&self, obj: &PyObjectRef) -> bool { match_class!(obj, PyFunction => true, @@ -1132,7 +1221,7 @@ impl VirtualMachine { pub fn _membership(&self, haystack: PyObjectRef, needle: PyObjectRef) -> PyResult { if let Some(method_or_err) = self.get_method(haystack.clone(), "__contains__") { let method = method_or_err?; - self.invoke(method, vec![needle]) + self.invoke(&method, vec![needle]) } else { self._membership_iter_search(haystack, needle) } diff --git a/wasm/lib/src/browser_module.rs b/wasm/lib/src/browser_module.rs index fed4fcbdc..abfdc2b53 100644 --- a/wasm/lib/src/browser_module.rs +++ b/wasm/lib/src/browser_module.rs @@ -133,7 +133,7 @@ fn browser_request_animation_frame(func: PyCallable, vm: &VirtualMachine) -> PyR let vm = &stored_vm.vm; let func = func.clone(); let args = vec![vm.ctx.new_float(time)]; - let _ = vm.invoke(func.into_object(), args); + let _ = vm.invoke(&func.into_object(), args); let closure = f.borrow_mut().take(); drop(closure); @@ -212,12 +212,12 @@ impl PyPromise { } else { vec![convert::js_to_py(vm, val)] }; - vm.invoke(on_fulfill.into_object(), PyFuncArgs::new(args, vec![])) + vm.invoke(&on_fulfill.into_object(), PyFuncArgs::new(args, vec![])) } Err(err) => { if let OptionalArg::Present(on_reject) = on_reject { let err = convert::js_to_py(vm, err); - vm.invoke(on_reject.into_object(), PyFuncArgs::new(vec![err], vec![])) + vm.invoke(&on_reject.into_object(), PyFuncArgs::new(vec![err], vec![])) } else { return Err(err); } @@ -240,7 +240,7 @@ impl PyPromise { .expect("that the vm is valid when the promise resolves"); let vm = &stored_vm.vm; let err = convert::js_to_py(vm, err); - let res = vm.invoke(on_reject.into_object(), PyFuncArgs::new(vec![err], vec![])); + let res = vm.invoke(&on_reject.into_object(), PyFuncArgs::new(vec![err], vec![])); convert::pyresult_to_jsresult(vm, res) }) }); diff --git a/wasm/lib/src/convert.rs b/wasm/lib/src/convert.rs index f4c71e60d..16b7fe3f7 100644 --- a/wasm/lib/src/convert.rs +++ b/wasm/lib/src/convert.rs @@ -94,7 +94,7 @@ pub fn py_to_js(vm: &VirtualMachine, py_obj: PyObjectRef) -> JsValue { .insert(js_sys::JsString::from(key).into(), js_to_py(vm, val)); } } - let result = vm.invoke(py_obj.clone(), py_func_args); + let result = vm.invoke(&py_obj, py_func_args); pyresult_to_jsresult(vm, result) }; let closure = Closure::wrap(Box::new(closure) diff --git a/wasm/lib/src/js_module.rs b/wasm/lib/src/js_module.rs index 9468aa416..9622613f7 100644 --- a/wasm/lib/src/js_module.rs +++ b/wasm/lib/src/js_module.rs @@ -1,9 +1,8 @@ use js_sys::{Array, Object, Reflect}; use rustpython_vm::function::Args; use rustpython_vm::obj::{objfloat::PyFloatRef, objstr::PyStringRef, objtype::PyClassRef}; -use rustpython_vm::pyobject::{ - create_type, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, -}; +use rustpython_vm::pyobject::{PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject}; +use rustpython_vm::types::create_type; use rustpython_vm::VirtualMachine; use wasm_bindgen::{prelude::*, JsCast}; @@ -244,7 +243,7 @@ fn new_js_error(vm: &VirtualMachine, err: JsValue) -> PyObjectRef { pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; py_module!(vm, "_js", { - "JsError" => create_type("JsError", &ctx.type_type, &ctx.exceptions.exception_type), + "JsError" => create_type("JsError", &ctx.type_type(), &ctx.exceptions.exception_type), "JsValue" => PyJsValue::make_class(ctx), }) } diff --git a/wasm/lib/src/vm_class.rs b/wasm/lib/src/vm_class.rs index 5015c3925..1f2584f0a 100644 --- a/wasm/lib/src/vm_class.rs +++ b/wasm/lib/src/vm_class.rs @@ -256,7 +256,7 @@ impl WASMVirtualMachine { let mod_name = name.clone(); let stdlib_init_fn = move |vm: &VirtualMachine| { - let module = vm.ctx.new_module(&name, vm.ctx.new_dict()); + let module = vm.new_module(&name, vm.ctx.new_dict()); for (key, value) in module_items.clone() { vm.set_attr(&module, key, value).unwrap(); }