Refactoring

This commit is contained in:
Jeong YunWon
2023-05-10 02:38:05 +09:00
parent 5337dedadf
commit dc569e9921
47 changed files with 2565 additions and 576 deletions

2
.gitattributes vendored
View File

@@ -1,8 +1,6 @@
Lib/** linguist-vendored
Cargo.lock linguist-generated -merge
*.snap linguist-generated -merge
ast/src/ast_gen.rs linguist-generated -merge
vm/src/stdlib/ast/gen.rs linguist-generated -merge
compiler/parser/python.lalrpop text eol=LF
Lib/*.py text working-tree-encoding=UTF-8 eol=LF
**/*.rs text working-tree-encoding=UTF-8 eol=LF

361
Cargo.lock generated
View File

@@ -85,15 +85,6 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
[[package]]
name = "ascii-canvas"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6"
dependencies = [
"term",
]
[[package]]
name = "atomic"
version = "0.5.1"
@@ -126,21 +117,6 @@ version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "bit-set"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
dependencies = [
"bit-vec",
]
[[package]]
name = "bit-vec"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
[[package]]
name = "bitflags"
version = "1.3.2"
@@ -638,12 +614,6 @@ dependencies = [
"syn",
]
[[package]]
name = "diff"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]]
name = "digest"
version = "0.10.6"
@@ -700,15 +670,6 @@ version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "ena"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3"
dependencies = [
"log",
]
[[package]]
name = "encode_unicode"
version = "0.3.6"
@@ -780,12 +741,6 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "fixedbitset"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flame"
version = "0.2.2"
@@ -885,9 +840,9 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.9"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"js-sys",
@@ -1036,18 +991,6 @@ dependencies = [
"syn",
]
[[package]]
name = "is-terminal"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
dependencies = [
"hermit-abi 0.3.1",
"io-lifetimes",
"rustix",
"windows-sys 0.48.0",
]
[[package]]
name = "itertools"
version = "0.10.5"
@@ -1081,59 +1024,6 @@ dependencies = [
"cpufeatures",
]
[[package]]
name = "lalrpop"
version = "0.19.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a1cbf952127589f2851ab2046af368fd20645491bb4b376f04b7f94d7a9837b"
dependencies = [
"ascii-canvas",
"bit-set",
"diff",
"ena",
"is-terminal",
"itertools",
"lalrpop-util 0.19.12",
"petgraph",
"regex",
"regex-syntax 0.6.28",
"string_cache",
"term",
"tiny-keccak",
"unicode-xid",
]
[[package]]
name = "lalrpop"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da4081d44f4611b66c6dd725e6de3169f9f63905421e8626fcb86b6a898998b8"
dependencies = [
"ascii-canvas",
"bit-set",
"diff",
"ena",
"is-terminal",
"itertools",
"lalrpop-util 0.20.0",
"petgraph",
"regex",
"regex-syntax 0.7.1",
"string_cache",
"term",
"tiny-keccak",
"unicode-xid",
]
[[package]]
name = "lalrpop-util"
version = "0.19.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3c48237b9604c5a4702de6b824e02006c3214327564636aef27c1028a8fa0ed"
dependencies = [
"regex",
]
[[package]]
name = "lalrpop-util"
version = "0.20.0"
@@ -1370,12 +1260,6 @@ dependencies = [
"rand_core",
]
[[package]]
name = "new_debug_unreachable"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
[[package]]
name = "nibble_vec"
version = "0.1.0"
@@ -1615,23 +1499,13 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba"
[[package]]
name = "petgraph"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
dependencies = [
"fixedbitset",
"indexmap",
]
[[package]]
name = "phf"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c"
dependencies = [
"phf_shared 0.11.1",
"phf_shared",
]
[[package]]
@@ -1641,7 +1515,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770"
dependencies = [
"phf_generator",
"phf_shared 0.11.1",
"phf_shared",
]
[[package]]
@@ -1650,19 +1524,10 @@ version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf"
dependencies = [
"phf_shared 0.11.1",
"phf_shared",
"rand",
]
[[package]]
name = "phf_shared"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
dependencies = [
"siphasher",
]
[[package]]
name = "phf_shared"
version = "0.11.1"
@@ -1729,12 +1594,6 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "precomputed-hash"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]]
name = "proc-macro-crate"
version = "1.3.0"
@@ -1893,7 +1752,7 @@ checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax 0.6.28",
"regex-syntax",
]
[[package]]
@@ -1908,12 +1767,6 @@ version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "regex-syntax"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
[[package]]
name = "region"
version = "2.2.0"
@@ -1949,48 +1802,19 @@ dependencies = [
]
[[package]]
name = "ruff_python_ast"
name = "ruff_source_location"
version = "0.0.0"
source = "git+https://github.com/youknowone/ruff.git?rev=583df5c1fa43b2732896219f8ab425116c140c80#583df5c1fa43b2732896219f8ab425116c140c80"
source = "git+https://github.com/youknowone/RustPython-parser.git?rev=6fa3d0f90a5115680ded1ed1606918b4b26251de#6fa3d0f90a5115680ded1ed1606918b4b26251de"
dependencies = [
"anyhow",
"bitflags 2.2.1",
"is-macro",
"itertools",
"log",
"memchr",
"num-bigint",
"num-traits",
"once_cell",
"regex",
"ruff_rustpython",
"ruff_text_size 0.0.0 (git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a)",
"rustc-hash",
"rustpython-common 0.2.0 (git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a)",
"rustpython-parser 0.2.0 (git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a)",
"smallvec",
]
[[package]]
name = "ruff_rustpython"
version = "0.0.0"
source = "git+https://github.com/youknowone/ruff.git?rev=583df5c1fa43b2732896219f8ab425116c140c80#583df5c1fa43b2732896219f8ab425116c140c80"
dependencies = [
"anyhow",
"once_cell",
"rustpython-common 0.2.0 (git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a)",
"rustpython-parser 0.2.0 (git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a)",
"ruff_text_size",
]
[[package]]
name = "ruff_text_size"
version = "0.0.0"
source = "git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d#09a6afdd04587ccc8841a88e34890c9409d8649d"
[[package]]
name = "ruff_text_size"
version = "0.0.0"
source = "git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a#c3147d2c1524ebd0e90cf1c2938d770314fd5a5a"
source = "git+https://github.com/youknowone/RustPython-parser.git?rev=6fa3d0f90a5115680ded1ed1606918b4b26251de#6fa3d0f90a5115680ded1ed1606918b4b26251de"
dependencies = [
"serde",
]
@@ -2041,7 +1865,7 @@ dependencies = [
"log",
"python3-sys",
"rustpython-compiler",
"rustpython-parser 0.2.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d)",
"rustpython-parser",
"rustpython-pylib",
"rustpython-stdlib",
"rustpython-vm",
@@ -2051,20 +1875,11 @@ dependencies = [
[[package]]
name = "rustpython-ast"
version = "0.2.0"
source = "git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d#09a6afdd04587ccc8841a88e34890c9409d8649d"
source = "git+https://github.com/youknowone/RustPython-parser.git?rev=6fa3d0f90a5115680ded1ed1606918b4b26251de#6fa3d0f90a5115680ded1ed1606918b4b26251de"
dependencies = [
"num-bigint",
"rustpython-compiler-core 0.2.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d)",
"rustpython-literal",
]
[[package]]
name = "rustpython-ast"
version = "0.2.0"
source = "git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a#c3147d2c1524ebd0e90cf1c2938d770314fd5a5a"
dependencies = [
"num-bigint",
"ruff_text_size 0.0.0 (git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a)",
"rustpython-parser-core",
]
[[package]]
@@ -2072,16 +1887,17 @@ name = "rustpython-codegen"
version = "0.2.0"
dependencies = [
"ahash",
"bitflags 1.3.2",
"bitflags 2.2.1",
"indexmap",
"insta",
"itertools",
"log",
"num-complex",
"num-traits",
"rustpython-ast 0.2.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d)",
"rustpython-compiler-core 0.2.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d)",
"rustpython-parser 0.2.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d)",
"rustpython-ast",
"rustpython-compiler-core",
"rustpython-parser",
"rustpython-parser-core",
]
[[package]]
@@ -2089,7 +1905,7 @@ name = "rustpython-common"
version = "0.2.0"
dependencies = [
"ascii",
"bitflags 1.3.2",
"bitflags 2.2.1",
"bstr",
"cfg-if",
"itertools",
@@ -2108,66 +1924,26 @@ dependencies = [
"widestring",
]
[[package]]
name = "rustpython-common"
version = "0.2.0"
source = "git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a#c3147d2c1524ebd0e90cf1c2938d770314fd5a5a"
dependencies = [
"ascii",
"bitflags 1.3.2",
"bstr",
"cfg-if",
"getrandom",
"hexf-parse",
"itertools",
"lexical-parse-float",
"libc",
"lock_api",
"num-bigint",
"num-traits",
"once_cell",
"radium",
"rand",
"siphasher",
"unic-ucd-category",
"volatile",
"widestring",
]
[[package]]
name = "rustpython-compiler"
version = "0.2.0"
dependencies = [
"rustpython-codegen",
"rustpython-compiler-core 0.2.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d)",
"rustpython-parser 0.2.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d)",
"rustpython-compiler-core",
"rustpython-parser",
]
[[package]]
name = "rustpython-compiler-core"
version = "0.2.0"
source = "git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d#09a6afdd04587ccc8841a88e34890c9409d8649d"
dependencies = [
"bitflags 1.3.2",
"bitflags 2.2.1",
"itertools",
"lz4_flex",
"num-bigint",
"num-complex",
"ruff_python_ast",
"ruff_text_size 0.0.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d)",
]
[[package]]
name = "rustpython-compiler-core"
version = "0.2.0"
source = "git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a#c3147d2c1524ebd0e90cf1c2938d770314fd5a5a"
dependencies = [
"bitflags 1.3.2",
"itertools",
"lz4_flex",
"num-bigint",
"num-complex",
"ruff_text_size 0.0.0 (git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a)",
"rustpython-parser-core",
"serde",
]
[[package]]
@@ -2189,8 +1965,9 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"rustpython-compiler-core 0.2.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d)",
"rustpython-compiler-core",
"rustpython-doc",
"rustpython-parser-core",
"syn",
"syn-ext",
"textwrap 0.15.2",
@@ -2214,7 +1991,7 @@ dependencies = [
"cranelift-module",
"libffi",
"num-traits",
"rustpython-compiler-core 0.2.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d)",
"rustpython-compiler-core",
"rustpython-derive",
"thiserror",
]
@@ -2222,7 +1999,7 @@ dependencies = [
[[package]]
name = "rustpython-literal"
version = "0.2.0"
source = "git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d#09a6afdd04587ccc8841a88e34890c9409d8649d"
source = "git+https://github.com/youknowone/RustPython-parser.git?rev=6fa3d0f90a5115680ded1ed1606918b4b26251de#6fa3d0f90a5115680ded1ed1606918b4b26251de"
dependencies = [
"hexf-parse",
"lexical-parse-float",
@@ -2233,21 +2010,19 @@ dependencies = [
[[package]]
name = "rustpython-parser"
version = "0.2.0"
source = "git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d#09a6afdd04587ccc8841a88e34890c9409d8649d"
source = "git+https://github.com/youknowone/RustPython-parser.git?rev=6fa3d0f90a5115680ded1ed1606918b4b26251de#6fa3d0f90a5115680ded1ed1606918b4b26251de"
dependencies = [
"ahash",
"anyhow",
"itertools",
"lalrpop 0.20.0",
"lalrpop-util 0.20.0",
"lalrpop-util",
"log",
"num-bigint",
"num-traits",
"phf",
"phf_codegen",
"rustc-hash",
"rustpython-ast 0.2.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d)",
"rustpython-compiler-core 0.2.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d)",
"rustpython-ast",
"rustpython-parser-core",
"tiny-keccak",
"unic-emoji-char",
"unic-ucd-ident",
@@ -2255,27 +2030,16 @@ dependencies = [
]
[[package]]
name = "rustpython-parser"
name = "rustpython-parser-core"
version = "0.2.0"
source = "git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a#c3147d2c1524ebd0e90cf1c2938d770314fd5a5a"
source = "git+https://github.com/youknowone/RustPython-parser.git?rev=6fa3d0f90a5115680ded1ed1606918b4b26251de#6fa3d0f90a5115680ded1ed1606918b4b26251de"
dependencies = [
"anyhow",
"itertools",
"lalrpop 0.19.12",
"lalrpop-util 0.19.12",
"log",
"lz4_flex",
"num-bigint",
"num-traits",
"phf",
"phf_codegen",
"ruff_text_size 0.0.0 (git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a)",
"rustc-hash",
"rustpython-ast 0.2.0 (git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a)",
"rustpython-compiler-core 0.2.0 (git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a)",
"tiny-keccak",
"unic-emoji-char",
"unic-ucd-ident",
"unicode_names2",
"num-complex",
"ruff_source_location",
"ruff_text_size",
]
[[package]]
@@ -2283,7 +2047,7 @@ name = "rustpython-pylib"
version = "0.2.0"
dependencies = [
"glob",
"rustpython-compiler-core 0.2.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d)",
"rustpython-compiler-core",
"rustpython-derive",
]
@@ -2335,7 +2099,7 @@ dependencies = [
"puruspe",
"rand",
"rand_core",
"rustpython-common 0.2.0",
"rustpython-common",
"rustpython-derive",
"rustpython-vm",
"schannel",
@@ -2367,7 +2131,7 @@ dependencies = [
"ahash",
"ascii",
"atty",
"bitflags 1.3.2",
"bitflags 2.2.1",
"bstr",
"caseless",
"cfg-if",
@@ -2402,15 +2166,16 @@ dependencies = [
"rand",
"result-like",
"rustc_version",
"rustpython-ast 0.2.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d)",
"rustpython-ast",
"rustpython-codegen",
"rustpython-common 0.2.0",
"rustpython-common",
"rustpython-compiler",
"rustpython-compiler-core 0.2.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d)",
"rustpython-compiler-core",
"rustpython-derive",
"rustpython-jit",
"rustpython-literal",
"rustpython-parser 0.2.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d)",
"rustpython-parser",
"rustpython-parser-core",
"rustyline",
"schannel",
"serde",
@@ -2441,8 +2206,8 @@ version = "0.2.0"
dependencies = [
"console_error_panic_hook",
"js-sys",
"rustpython-common 0.2.0",
"rustpython-parser 0.2.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=09a6afdd04587ccc8841a88e34890c9409d8649d)",
"rustpython-common",
"rustpython-parser",
"rustpython-pylib",
"rustpython-stdlib",
"rustpython-vm",
@@ -2666,19 +2431,6 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0"
[[package]]
name = "string_cache"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08"
dependencies = [
"new_debug_unreachable",
"once_cell",
"parking_lot",
"phf_shared 0.10.0",
"precomputed-hash",
]
[[package]]
name = "strsim"
version = "0.8.0"
@@ -2757,17 +2509,6 @@ version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ae9980cab1db3fceee2f6c6f643d5d8de2997c58ee8d25fb0cc8a9e9e7348e5"
[[package]]
name = "term"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
dependencies = [
"dirs-next",
"rustversion",
"winapi",
]
[[package]]
name = "termcolor"
version = "1.2.0"
@@ -3090,12 +2831,6 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "unicode-xid"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "unicode_names2"
version = "0.6.0"

View File

@@ -12,17 +12,29 @@ include = ["LICENSE", "Cargo.toml", "src/**/*.rs"]
[workspace]
resolver = "2"
members = [
"compiler", "compiler/codegen",
"compiler", "compiler/core", "compiler/codegen",
".", "common", "derive", "jit", "vm", "pylib", "stdlib", "wasm/lib", "derive-impl",
]
[workspace.dependencies]
rustpython-literal = { git = "https://github.com/youknowone/RustPython-parser.git", rev = "09a6afdd04587ccc8841a88e34890c9409d8649d" }
rustpython-compiler-core = { git = "https://github.com/youknowone/RustPython-parser.git", rev = "09a6afdd04587ccc8841a88e34890c9409d8649d" }
rustpython-parser = { git = "https://github.com/youknowone/RustPython-parser.git", rev = "09a6afdd04587ccc8841a88e34890c9409d8649d" }
rustpython-ast = { git = "https://github.com/youknowone/RustPython-parser.git", rev = "09a6afdd04587ccc8841a88e34890c9409d8649d" }
rustpython-compiler-core = { path = "compiler/core" }
rustpython-compiler = { path = "compiler" }
rustpython-codegen = { path = "compiler/codegen" }
rustpython-common = { path = "common" }
rustpython-derive = { path = "derive" }
rustpython-derive-impl = { path = "derive-impl" }
rustpython-jit = { path = "jit" }
rustpython-vm = { path = "vm" }
rustpython-pylib = { path = "pylib" }
rustpython-stdlib = { path = "stdlib" }
rustpython-doc = { git = "https://github.com/RustPython/__doc__", branch = "main" }
rustpython-literal = { git = "https://github.com/youknowone/RustPython-parser.git", rev = "6fa3d0f90a5115680ded1ed1606918b4b26251de" }
rustpython-parser-core = { git = "https://github.com/youknowone/RustPython-parser.git", rev = "6fa3d0f90a5115680ded1ed1606918b4b26251de" }
rustpython-parser = { git = "https://github.com/youknowone/RustPython-parser.git", rev = "6fa3d0f90a5115680ded1ed1606918b4b26251de" }
rustpython-ast = { git = "https://github.com/youknowone/RustPython-parser.git", rev = "6fa3d0f90a5115680ded1ed1606918b4b26251de" }
# rustpython-literal = { path = "../RustPython-parser/literal" }
# rustpython-compiler-core = { path = "../RustPython-parser/core" }
# rustpython-parser-core = { path = "../RustPython-parser/core" }
# rustpython-parser = { path = "../RustPython-parser/parser" }
# rustpython-ast = { path = "../RustPython-parser/ast" }
@@ -30,7 +42,7 @@ ahash = "0.7.6"
anyhow = "1.0.45"
ascii = "1.0"
atty = "0.2.14"
bitflags = "1.3.2"
bitflags = "2.2.1"
bstr = "0.2.17"
cfg-if = "1.0"
chrono = "0.4.19"
@@ -65,7 +77,7 @@ unicode_names2 = { version = "0.6.0", git = "https://github.com/youknowone/unico
widestring = "0.5.1"
[features]
default = ["threading", "stdlib", "zlib", "importlib", "encodings", "rustpython-parser/lalrpop"]
default = ["threading", "stdlib", "zlib", "importlib", "encodings"]
importlib = ["rustpython-vm/importlib"]
encodings = ["rustpython-vm/encodings"]
stdlib = ["rustpython-stdlib", "rustpython-pylib"]

View File

@@ -21,8 +21,6 @@ class OpcodeTest(unittest.TestCase):
if n != 90:
self.fail('try inside for')
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_setup_annotations_line(self):
# check that SETUP_ANNOTATIONS does not create spurious line numbers
try:

View File

@@ -2092,8 +2092,6 @@ def func2():
"""
self._check_error(code, "expected ':'")
# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_invalid_line_continuation_error_position(self):
self._check_error(r"a = 3 \ 4",
"unexpected character after line continuation character",

View File

@@ -83,6 +83,7 @@ impl From<CFormatQuantity> for CFormatPrecision {
}
bitflags! {
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct CConversionFlags: u32 {
const ALTERNATE_FORM = 0b0000_0001;
const ZERO_PAD = 0b0000_0010;

View File

@@ -6,6 +6,6 @@ authors = ["RustPython Team"]
edition = "2021"
[dependencies]
rustpython-codegen = { path = "codegen" }
rustpython-codegen = { workspace = true }
rustpython-compiler-core = { workspace = true }
rustpython-parser = { workspace = true }

View File

@@ -8,7 +8,8 @@ license = "MIT"
edition = "2021"
[dependencies]
rustpython-ast = { workspace = true, features=["unparse"] }
rustpython-ast = { workspace = true, features=["unparse", "constant-optimization"] }
rustpython-parser-core = { workspace = true }
rustpython-compiler-core = { workspace = true }
ahash = { workspace = true }

View File

@@ -18,13 +18,15 @@ use num_complex::Complex64;
use num_traits::ToPrimitive;
use rustpython_ast as ast;
use rustpython_compiler_core::{
self as bytecode, source_code::SourceLocation, Arg as OpArgMarker, CodeObject, ConstantData,
Instruction, LineNumber, OpArg, OpArgType,
bytecode::{self, Arg as OpArgMarker, CodeObject, ConstantData, Instruction, OpArg, OpArgType},
Mode,
};
use rustpython_parser_core::{
source_code::{LineNumber, SourceLocation},
ConversionFlag,
};
use std::borrow::Cow;
pub use rustpython_compiler_core::Mode;
type CompileResult<T> = Result<T, CodegenError>;
#[derive(PartialEq, Eq, Clone, Copy)]
@@ -225,7 +227,7 @@ impl Compiler {
code_stack: vec![module_code],
symbol_table_stack: Vec::new(),
source_path,
current_source_location: SourceLocation::MIN,
current_source_location: SourceLocation::default(),
qualified_path: Vec::new(),
done_with_future_stmts: false,
future_annotations: false,
@@ -2228,7 +2230,7 @@ impl Compiler {
emit!(
self,
Instruction::FormatValue {
conversion: bytecode::ConversionFlag::try_from(*conversion)
conversion: ConversionFlag::from_op_arg(*conversion)
.expect("invalid conversion flag"),
},
);
@@ -2898,15 +2900,18 @@ impl ToU32 for usize {
mod tests {
use super::*;
use rustpython_parser as parser;
use rustpython_parser_core::source_code::SourceLocator;
fn compile_exec(source: &str) -> CodeObject {
let mut locator = SourceLocator::new(source);
use rustpython_parser::ast::fold::Fold;
let mut compiler: Compiler = Compiler::new(
CompileOpts::default(),
"source_path".to_owned(),
"<module>".to_owned(),
source,
);
let ast = parser::parse_program(source, "<test>").unwrap();
let ast = locator.fold(ast).unwrap();
let symbol_scope = SymbolTable::scan_program(&ast).unwrap();
compiler.compile_program(&ast, symbol_scope).unwrap();
compiler.pop_code_object()

View File

@@ -1,6 +1,6 @@
use std::fmt;
pub type CodegenError = rustpython_compiler_core::LocatedError<CodegenErrorType>;
pub type CodegenError = rustpython_parser_core::source_code::LocatedError<CodegenErrorType>;
#[derive(Debug)]
#[non_exhaustive]

View File

@@ -1,10 +1,10 @@
use std::ops;
use crate::IndexSet;
use rustpython_compiler_core::{
source_code::SourceLocation, CodeFlags, CodeObject, CodeUnit, ConstantData,
InstrDisplayContext, Instruction, Label, LineNumber, OpArg,
use rustpython_compiler_core::bytecode::{
CodeFlags, CodeObject, CodeUnit, ConstantData, InstrDisplayContext, Instruction, Label, OpArg,
};
use rustpython_parser_core::source_code::{LineNumber, SourceLocation};
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct BlockIdx(pub u32);
@@ -158,7 +158,7 @@ impl CodeInfo {
arg_count,
kwonlyarg_count,
source_path,
first_line_number,
first_line_number: Some(first_line_number),
obj_name,
max_stackdepth,

View File

@@ -13,10 +13,7 @@ use crate::{
};
use bitflags::bitflags;
use rustpython_ast as ast;
use rustpython_compiler_core::{
source_code::{OneIndexed, SourceLocation},
LineNumber,
};
use rustpython_parser_core::source_code::{LineNumber, SourceLocation};
use std::{borrow::Cow, fmt};
/// Captures all symbols in the current scope, and has a list of sub-scopes in this scope.
@@ -29,7 +26,7 @@ pub struct SymbolTable {
pub typ: SymbolTableType,
/// The line number in the source code where this symboltable begins.
pub line_number: LineNumber,
pub line_number: u32,
// Return True if the block is a nested class or function
pub is_nested: bool,
@@ -43,7 +40,7 @@ pub struct SymbolTable {
}
impl SymbolTable {
fn new(name: String, typ: SymbolTableType, line_number: LineNumber, is_nested: bool) -> Self {
fn new(name: String, typ: SymbolTableType, line_number: u32, is_nested: bool) -> Self {
SymbolTable {
name,
typ,
@@ -99,6 +96,7 @@ pub enum SymbolScope {
}
bitflags! {
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct SymbolFlags: u16 {
const REFERENCED = 0x001;
const ASSIGNED = 0x002;
@@ -121,7 +119,7 @@ bitflags! {
/// return x // is_free_class
/// ```
const FREE_CLASS = 0x100;
const BOUND = Self::ASSIGNED.bits | Self::PARAMETER.bits | Self::IMPORTED.bits | Self::ITER.bits;
const BOUND = Self::ASSIGNED.bits() | Self::PARAMETER.bits() | Self::IMPORTED.bits() | Self::ITER.bits();
}
}
@@ -172,7 +170,7 @@ impl SymbolTableError {
error: CodegenErrorType::SyntaxError(self.error),
location: self.location.map(|l| SourceLocation {
row: l.row,
column: OneIndexed::MIN,
column: l.column,
}),
source_path,
}
@@ -565,7 +563,7 @@ impl SymbolTableBuilder {
tables: vec![],
future_annotations: false,
};
this.enter_scope("top", SymbolTableType::Module, LineNumber::MIN);
this.enter_scope("top", SymbolTableType::Module, 0);
this
}
}
@@ -578,7 +576,7 @@ impl SymbolTableBuilder {
Ok(symbol_table)
}
fn enter_scope(&mut self, name: &str, typ: SymbolTableType, line_number: LineNumber) {
fn enter_scope(&mut self, name: &str, typ: SymbolTableType, line_number: u32) {
let is_nested = self
.tables
.last()
@@ -697,7 +695,7 @@ impl SymbolTableBuilder {
keywords,
decorator_list,
}) => {
self.enter_scope(name, SymbolTableType::Class, location.row);
self.enter_scope(name, SymbolTableType::Class, location.row.get());
let prev_class = std::mem::replace(&mut self.class_name, Some(name.to_owned()));
self.register_name("__module__", SymbolUsage::Assigned, location)?;
self.register_name("__qualname__", SymbolUsage::Assigned, location)?;
@@ -1080,7 +1078,11 @@ impl SymbolTableBuilder {
location: SourceLocation,
) -> SymbolTableResult {
// Comprehensions are compiled as functions, so create a scope for them:
self.enter_scope(scope_name, SymbolTableType::Comprehension, location.row);
self.enter_scope(
scope_name,
SymbolTableType::Comprehension,
location.row.get(),
);
// Register the passed argument to the generator function as the name ".0"
self.register_name(".0", SymbolUsage::Parameter, location)?;
@@ -1136,7 +1138,7 @@ impl SymbolTableBuilder {
self.scan_parameter_annotation(name)?;
}
self.enter_scope(name, SymbolTableType::Function, line_number);
self.enter_scope(name, SymbolTableType::Function, line_number.get());
// Fill scope with parameter names:
self.scan_parameters(&args.posonlyargs)?;

20
compiler/core/Cargo.toml Normal file
View File

@@ -0,0 +1,20 @@
[package]
name = "rustpython-compiler-core"
description = "RustPython specific bytecode."
version = "0.2.0"
authors = ["RustPython Team"]
edition = "2021"
repository = "https://github.com/RustPython/RustPython"
license = "MIT"
[dependencies]
rustpython-parser-core = { workspace = true }
bitflags = { workspace = true }
itertools = { workspace = true }
num-bigint = { workspace = true }
num-complex = { workspace = true }
serde = { version = "1.0.133", optional = true, default-features = false, features = ["derive"] }
lz4_flex = "0.9.2"

File diff suppressed because it is too large Load Diff

129
compiler/core/src/frozen.rs Normal file
View File

@@ -0,0 +1,129 @@
use crate::bytecode::*;
use crate::marshal::{self, Read, ReadBorrowed, Write};
/// A frozen module. Holds a frozen code object and whether it is part of a package
#[derive(Copy, Clone)]
pub struct FrozenModule<B = &'static [u8]> {
pub code: FrozenCodeObject<B>,
pub package: bool,
}
#[derive(Copy, Clone)]
pub struct FrozenCodeObject<B> {
pub bytes: B,
}
impl<B: AsRef<[u8]>> FrozenCodeObject<B> {
/// Decode a frozen code object
#[inline]
pub fn decode<Bag: AsBag>(&self, bag: Bag) -> CodeObject<<Bag::Bag as ConstantBag>::Constant> {
Self::_decode(self.bytes.as_ref(), bag.as_bag())
}
fn _decode<Bag: ConstantBag>(data: &[u8], bag: Bag) -> CodeObject<Bag::Constant> {
let decompressed = lz4_flex::decompress_size_prepended(data)
.expect("deserialize frozen CodeObject failed");
marshal::deserialize_code(&mut &decompressed[..], bag)
.expect("deserializing frozen CodeObject failed")
}
}
impl FrozenCodeObject<Vec<u8>> {
pub fn encode<C: Constant>(code: &CodeObject<C>) -> Self {
let mut data = Vec::new();
marshal::serialize_code(&mut data, code);
let bytes = lz4_flex::compress_prepend_size(&data);
FrozenCodeObject { bytes }
}
}
#[repr(transparent)]
pub struct FrozenLib<B: ?Sized = [u8]> {
pub bytes: B,
}
impl<B: AsRef<[u8]> + ?Sized> FrozenLib<B> {
pub const fn from_ref(b: &B) -> &FrozenLib<B> {
unsafe { &*(b as *const B as *const FrozenLib<B>) }
}
/// Decode a library to a iterable of frozen modules
pub fn decode(&self) -> FrozenModulesIter<'_> {
let mut data = self.bytes.as_ref();
let remaining = data.read_u32().unwrap();
FrozenModulesIter { remaining, data }
}
}
impl<'a, B: AsRef<[u8]> + ?Sized> IntoIterator for &'a FrozenLib<B> {
type Item = (&'a str, FrozenModule<&'a [u8]>);
type IntoIter = FrozenModulesIter<'a>;
fn into_iter(self) -> Self::IntoIter {
self.decode()
}
}
pub struct FrozenModulesIter<'a> {
remaining: u32,
data: &'a [u8],
}
impl<'a> Iterator for FrozenModulesIter<'a> {
type Item = (&'a str, FrozenModule<&'a [u8]>);
fn next(&mut self) -> Option<Self::Item> {
if self.remaining > 0 {
let entry = read_entry(&mut self.data).unwrap();
self.remaining -= 1;
Some(entry)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining as usize, Some(self.remaining as usize))
}
}
impl ExactSizeIterator for FrozenModulesIter<'_> {}
fn read_entry<'a>(
rdr: &mut &'a [u8],
) -> Result<(&'a str, FrozenModule<&'a [u8]>), marshal::MarshalError> {
let len = rdr.read_u32()?;
let name = rdr.read_str_borrow(len)?;
let len = rdr.read_u32()?;
let code_slice = rdr.read_slice_borrow(len)?;
let code = FrozenCodeObject { bytes: code_slice };
let package = rdr.read_u8()? != 0;
Ok((name, FrozenModule { code, package }))
}
impl FrozenLib<Vec<u8>> {
/// Encode the given iterator of frozen modules into a compressed vector of bytes
pub fn encode<'a, I, B: AsRef<[u8]>>(lib: I) -> FrozenLib<Vec<u8>>
where
I: IntoIterator<Item = (&'a str, FrozenModule<B>)>,
I::IntoIter: ExactSizeIterator + Clone,
{
let iter = lib.into_iter();
let mut bytes = Vec::new();
write_lib(&mut bytes, iter);
Self { bytes }
}
}
fn write_lib<'a, B: AsRef<[u8]>>(
buf: &mut Vec<u8>,
lib: impl ExactSizeIterator<Item = (&'a str, FrozenModule<B>)>,
) {
marshal::write_len(buf, lib.len());
for (name, module) in lib {
write_entry(buf, name, module);
}
}
fn write_entry(buf: &mut Vec<u8>, name: &str, module: FrozenModule<impl AsRef<[u8]>>) {
marshal::write_vec(buf, name.as_bytes());
marshal::write_vec(buf, module.code.bytes.as_ref());
buf.write_u8(module.package as u8);
}

9
compiler/core/src/lib.rs Normal file
View File

@@ -0,0 +1,9 @@
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/main/logo.png")]
#![doc(html_root_url = "https://docs.rs/rustpython-compiler-core/")]
pub mod bytecode;
pub mod frozen;
pub mod marshal;
mod mode;
pub use mode::Mode;

View File

@@ -0,0 +1,629 @@
use crate::bytecode::*;
use num_bigint::{BigInt, Sign};
use num_complex::Complex64;
use rustpython_parser_core::source_code::{OneIndexed, SourceLocation};
use std::convert::Infallible;
pub const FORMAT_VERSION: u32 = 4;
#[derive(Debug)]
pub enum MarshalError {
/// Unexpected End Of File
Eof,
/// Invalid Bytecode
InvalidBytecode,
/// Invalid utf8 in string
InvalidUtf8,
/// Invalid source location
InvalidLocation,
/// Bad type marker
BadType,
}
impl std::fmt::Display for MarshalError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::Eof => f.write_str("unexpected end of data"),
Self::InvalidBytecode => f.write_str("invalid bytecode"),
Self::InvalidUtf8 => f.write_str("invalid utf8"),
Self::InvalidLocation => f.write_str("invalid source location"),
Self::BadType => f.write_str("bad type marker"),
}
}
}
impl From<std::str::Utf8Error> for MarshalError {
fn from(_: std::str::Utf8Error) -> Self {
Self::InvalidUtf8
}
}
impl std::error::Error for MarshalError {}
type Result<T, E = MarshalError> = std::result::Result<T, E>;
#[repr(u8)]
enum Type {
// Null = b'0',
None = b'N',
False = b'F',
True = b'T',
StopIter = b'S',
Ellipsis = b'.',
Int = b'i',
Float = b'g',
Complex = b'y',
// Long = b'l', // i32
Bytes = b's', // = TYPE_STRING
// Interned = b't',
// Ref = b'r',
Tuple = b'(',
List = b'[',
Dict = b'{',
Code = b'c',
Unicode = b'u',
// Unknown = b'?',
Set = b'<',
FrozenSet = b'>',
Ascii = b'a',
// AsciiInterned = b'A',
// SmallTuple = b')',
// ShortAscii = b'z',
// ShortAsciiInterned = b'Z',
}
// const FLAG_REF: u8 = b'\x80';
impl TryFrom<u8> for Type {
type Error = MarshalError;
fn try_from(value: u8) -> Result<Self> {
use Type::*;
Ok(match value {
// b'0' => Null,
b'N' => None,
b'F' => False,
b'T' => True,
b'S' => StopIter,
b'.' => Ellipsis,
b'i' => Int,
b'g' => Float,
b'y' => Complex,
// b'l' => Long,
b's' => Bytes,
// b't' => Interned,
// b'r' => Ref,
b'(' => Tuple,
b'[' => List,
b'{' => Dict,
b'c' => Code,
b'u' => Unicode,
// b'?' => Unknown,
b'<' => Set,
b'>' => FrozenSet,
b'a' => Ascii,
// b'A' => AsciiInterned,
// b')' => SmallTuple,
// b'z' => ShortAscii,
// b'Z' => ShortAsciiInterned,
_ => return Err(MarshalError::BadType),
})
}
}
pub trait Read {
fn read_slice(&mut self, n: u32) -> Result<&[u8]>;
fn read_array<const N: usize>(&mut self) -> Result<&[u8; N]> {
self.read_slice(N as u32).map(|s| s.try_into().unwrap())
}
fn read_str(&mut self, len: u32) -> Result<&str> {
Ok(std::str::from_utf8(self.read_slice(len)?)?)
}
fn read_u8(&mut self) -> Result<u8> {
Ok(u8::from_le_bytes(*self.read_array()?))
}
fn read_u16(&mut self) -> Result<u16> {
Ok(u16::from_le_bytes(*self.read_array()?))
}
fn read_u32(&mut self) -> Result<u32> {
Ok(u32::from_le_bytes(*self.read_array()?))
}
fn read_u64(&mut self) -> Result<u64> {
Ok(u64::from_le_bytes(*self.read_array()?))
}
}
pub(crate) trait ReadBorrowed<'a>: Read {
fn read_slice_borrow(&mut self, n: u32) -> Result<&'a [u8]>;
fn read_str_borrow(&mut self, len: u32) -> Result<&'a str> {
Ok(std::str::from_utf8(self.read_slice_borrow(len)?)?)
}
}
impl Read for &[u8] {
fn read_slice(&mut self, n: u32) -> Result<&[u8]> {
self.read_slice_borrow(n)
}
}
impl<'a> ReadBorrowed<'a> for &'a [u8] {
fn read_slice_borrow(&mut self, n: u32) -> Result<&'a [u8]> {
let data = self.get(..n as usize).ok_or(MarshalError::Eof)?;
*self = &self[n as usize..];
Ok(data)
}
}
pub struct Cursor<B> {
pub data: B,
pub position: usize,
}
impl<B: AsRef<[u8]>> Read for Cursor<B> {
fn read_slice(&mut self, n: u32) -> Result<&[u8]> {
let data = &self.data.as_ref()[self.position..];
let slice = data.get(..n as usize).ok_or(MarshalError::Eof)?;
self.position += n as usize;
Ok(slice)
}
}
pub fn deserialize_code<R: Read, Bag: ConstantBag>(
rdr: &mut R,
bag: Bag,
) -> Result<CodeObject<Bag::Constant>> {
let len = rdr.read_u32()?;
let instructions = rdr.read_slice(len * 2)?;
let instructions = instructions
.chunks_exact(2)
.map(|cu| {
let op = Instruction::try_from(cu[0])?;
let arg = OpArgByte(cu[1]);
Ok(CodeUnit { op, arg })
})
.collect::<Result<Box<[CodeUnit]>>>()?;
let len = rdr.read_u32()?;
let locations = (0..len)
.map(|_| {
Ok(SourceLocation {
row: OneIndexed::new(rdr.read_u32()?).ok_or(MarshalError::InvalidLocation)?,
column: OneIndexed::from_zero_indexed(rdr.read_u32()?),
})
})
.collect::<Result<Box<[SourceLocation]>>>()?;
let flags = CodeFlags::from_bits_truncate(rdr.read_u16()?);
let posonlyarg_count = rdr.read_u32()?;
let arg_count = rdr.read_u32()?;
let kwonlyarg_count = rdr.read_u32()?;
let len = rdr.read_u32()?;
let source_path = bag.make_name(rdr.read_str(len)?);
let first_line_number = OneIndexed::new(rdr.read_u32()?);
let max_stackdepth = rdr.read_u32()?;
let len = rdr.read_u32()?;
let obj_name = bag.make_name(rdr.read_str(len)?);
let len = rdr.read_u32()?;
let cell2arg = (len != 0)
.then(|| {
(0..len)
.map(|_| Ok(rdr.read_u32()? as i32))
.collect::<Result<Box<[i32]>>>()
})
.transpose()?;
let len = rdr.read_u32()?;
let constants = (0..len)
.map(|_| deserialize_value(rdr, bag))
.collect::<Result<Box<[_]>>>()?;
let mut read_names = || {
let len = rdr.read_u32()?;
(0..len)
.map(|_| {
let len = rdr.read_u32()?;
Ok(bag.make_name(rdr.read_str(len)?))
})
.collect::<Result<Box<[_]>>>()
};
let names = read_names()?;
let varnames = read_names()?;
let cellvars = read_names()?;
let freevars = read_names()?;
Ok(CodeObject {
instructions,
locations,
flags,
posonlyarg_count,
arg_count,
kwonlyarg_count,
source_path,
first_line_number,
max_stackdepth,
obj_name,
cell2arg,
constants,
names,
varnames,
cellvars,
freevars,
})
}
pub trait MarshalBag: Copy {
type Value;
fn make_bool(&self, value: bool) -> Self::Value;
fn make_none(&self) -> Self::Value;
fn make_ellipsis(&self) -> Self::Value;
fn make_float(&self, value: f64) -> Self::Value;
fn make_complex(&self, value: Complex64) -> Self::Value;
fn make_str(&self, value: &str) -> Self::Value;
fn make_bytes(&self, value: &[u8]) -> Self::Value;
fn make_int(&self, value: BigInt) -> Self::Value;
fn make_tuple(&self, elements: impl Iterator<Item = Self::Value>) -> Self::Value;
fn make_code(
&self,
code: CodeObject<<Self::ConstantBag as ConstantBag>::Constant>,
) -> Self::Value;
fn make_stop_iter(&self) -> Result<Self::Value>;
fn make_list(&self, it: impl Iterator<Item = Self::Value>) -> Result<Self::Value>;
fn make_set(&self, it: impl Iterator<Item = Self::Value>) -> Result<Self::Value>;
fn make_frozenset(&self, it: impl Iterator<Item = Self::Value>) -> Result<Self::Value>;
fn make_dict(
&self,
it: impl Iterator<Item = (Self::Value, Self::Value)>,
) -> Result<Self::Value>;
type ConstantBag: ConstantBag;
fn constant_bag(self) -> Self::ConstantBag;
}
impl<Bag: ConstantBag> MarshalBag for Bag {
type Value = Bag::Constant;
fn make_bool(&self, value: bool) -> Self::Value {
self.make_constant::<Bag::Constant>(BorrowedConstant::Boolean { value })
}
fn make_none(&self) -> Self::Value {
self.make_constant::<Bag::Constant>(BorrowedConstant::None)
}
fn make_ellipsis(&self) -> Self::Value {
self.make_constant::<Bag::Constant>(BorrowedConstant::Ellipsis)
}
fn make_float(&self, value: f64) -> Self::Value {
self.make_constant::<Bag::Constant>(BorrowedConstant::Float { value })
}
fn make_complex(&self, value: Complex64) -> Self::Value {
self.make_constant::<Bag::Constant>(BorrowedConstant::Complex { value })
}
fn make_str(&self, value: &str) -> Self::Value {
self.make_constant::<Bag::Constant>(BorrowedConstant::Str { value })
}
fn make_bytes(&self, value: &[u8]) -> Self::Value {
self.make_constant::<Bag::Constant>(BorrowedConstant::Bytes { value })
}
fn make_int(&self, value: BigInt) -> Self::Value {
self.make_int(value)
}
fn make_tuple(&self, elements: impl Iterator<Item = Self::Value>) -> Self::Value {
self.make_tuple(elements)
}
fn make_code(
&self,
code: CodeObject<<Self::ConstantBag as ConstantBag>::Constant>,
) -> Self::Value {
self.make_code(code)
}
fn make_stop_iter(&self) -> Result<Self::Value> {
Err(MarshalError::BadType)
}
fn make_list(&self, _: impl Iterator<Item = Self::Value>) -> Result<Self::Value> {
Err(MarshalError::BadType)
}
fn make_set(&self, _: impl Iterator<Item = Self::Value>) -> Result<Self::Value> {
Err(MarshalError::BadType)
}
fn make_frozenset(&self, _: impl Iterator<Item = Self::Value>) -> Result<Self::Value> {
Err(MarshalError::BadType)
}
fn make_dict(
&self,
_: impl Iterator<Item = (Self::Value, Self::Value)>,
) -> Result<Self::Value> {
Err(MarshalError::BadType)
}
type ConstantBag = Self;
fn constant_bag(self) -> Self::ConstantBag {
self
}
}
pub fn deserialize_value<R: Read, Bag: MarshalBag>(rdr: &mut R, bag: Bag) -> Result<Bag::Value> {
let typ = Type::try_from(rdr.read_u8()?)?;
let value = match typ {
Type::True => bag.make_bool(true),
Type::False => bag.make_bool(false),
Type::None => bag.make_none(),
Type::StopIter => bag.make_stop_iter()?,
Type::Ellipsis => bag.make_ellipsis(),
Type::Int => {
let len = rdr.read_u32()? as i32;
let sign = if len < 0 { Sign::Minus } else { Sign::Plus };
let bytes = rdr.read_slice(len.unsigned_abs())?;
let int = BigInt::from_bytes_le(sign, bytes);
bag.make_int(int)
}
Type::Float => {
let value = f64::from_bits(rdr.read_u64()?);
bag.make_float(value)
}
Type::Complex => {
let re = f64::from_bits(rdr.read_u64()?);
let im = f64::from_bits(rdr.read_u64()?);
let value = Complex64 { re, im };
bag.make_complex(value)
}
Type::Ascii | Type::Unicode => {
let len = rdr.read_u32()?;
let value = rdr.read_str(len)?;
bag.make_str(value)
}
Type::Tuple => {
let len = rdr.read_u32()?;
let it = (0..len).map(|_| deserialize_value(rdr, bag));
itertools::process_results(it, |it| bag.make_tuple(it))?
}
Type::List => {
let len = rdr.read_u32()?;
let it = (0..len).map(|_| deserialize_value(rdr, bag));
itertools::process_results(it, |it| bag.make_list(it))??
}
Type::Set => {
let len = rdr.read_u32()?;
let it = (0..len).map(|_| deserialize_value(rdr, bag));
itertools::process_results(it, |it| bag.make_set(it))??
}
Type::FrozenSet => {
let len = rdr.read_u32()?;
let it = (0..len).map(|_| deserialize_value(rdr, bag));
itertools::process_results(it, |it| bag.make_frozenset(it))??
}
Type::Dict => {
let len = rdr.read_u32()?;
let it = (0..len).map(|_| {
let k = deserialize_value(rdr, bag)?;
let v = deserialize_value(rdr, bag)?;
Ok::<_, MarshalError>((k, v))
});
itertools::process_results(it, |it| bag.make_dict(it))??
}
Type::Bytes => {
// Following CPython, after marshaling, byte arrays are converted into bytes.
let len = rdr.read_u32()?;
let value = rdr.read_slice(len)?;
bag.make_bytes(value)
}
Type::Code => bag.make_code(deserialize_code(rdr, bag.constant_bag())?),
};
Ok(value)
}
pub trait Dumpable: Sized {
type Error;
type Constant: Constant;
fn with_dump<R>(&self, f: impl FnOnce(DumpableValue<'_, Self>) -> R) -> Result<R, Self::Error>;
}
pub enum DumpableValue<'a, D: Dumpable> {
Integer(&'a BigInt),
Float(f64),
Complex(Complex64),
Boolean(bool),
Str(&'a str),
Bytes(&'a [u8]),
Code(&'a CodeObject<D::Constant>),
Tuple(&'a [D]),
None,
Ellipsis,
StopIter,
List(&'a [D]),
Set(&'a [D]),
Frozenset(&'a [D]),
Dict(&'a [(D, D)]),
}
impl<'a, C: Constant> From<BorrowedConstant<'a, C>> for DumpableValue<'a, C> {
fn from(c: BorrowedConstant<'a, C>) -> Self {
match c {
BorrowedConstant::Integer { value } => Self::Integer(value),
BorrowedConstant::Float { value } => Self::Float(value),
BorrowedConstant::Complex { value } => Self::Complex(value),
BorrowedConstant::Boolean { value } => Self::Boolean(value),
BorrowedConstant::Str { value } => Self::Str(value),
BorrowedConstant::Bytes { value } => Self::Bytes(value),
BorrowedConstant::Code { code } => Self::Code(code),
BorrowedConstant::Tuple { elements } => Self::Tuple(elements),
BorrowedConstant::None => Self::None,
BorrowedConstant::Ellipsis => Self::Ellipsis,
}
}
}
impl<C: Constant> Dumpable for C {
type Error = Infallible;
type Constant = Self;
#[inline(always)]
fn with_dump<R>(&self, f: impl FnOnce(DumpableValue<'_, Self>) -> R) -> Result<R, Self::Error> {
Ok(f(self.borrow_constant().into()))
}
}
pub trait Write {
fn write_slice(&mut self, slice: &[u8]);
fn write_u8(&mut self, v: u8) {
self.write_slice(&v.to_le_bytes())
}
fn write_u16(&mut self, v: u16) {
self.write_slice(&v.to_le_bytes())
}
fn write_u32(&mut self, v: u32) {
self.write_slice(&v.to_le_bytes())
}
fn write_u64(&mut self, v: u64) {
self.write_slice(&v.to_le_bytes())
}
}
impl Write for Vec<u8> {
fn write_slice(&mut self, slice: &[u8]) {
self.extend_from_slice(slice)
}
}
pub(crate) fn write_len<W: Write>(buf: &mut W, len: usize) {
let Ok(len) = len.try_into() else { panic!("too long to serialize") };
buf.write_u32(len);
}
pub(crate) fn write_vec<W: Write>(buf: &mut W, slice: &[u8]) {
write_len(buf, slice.len());
buf.write_slice(slice);
}
pub fn serialize_value<W: Write, D: Dumpable>(
buf: &mut W,
constant: DumpableValue<'_, D>,
) -> Result<(), D::Error> {
match constant {
DumpableValue::Integer(int) => {
buf.write_u8(Type::Int as u8);
let (sign, bytes) = int.to_bytes_le();
let len: i32 = bytes.len().try_into().expect("too long to serialize");
let len = if sign == Sign::Minus { -len } else { len };
buf.write_u32(len as u32);
buf.write_slice(&bytes);
}
DumpableValue::Float(f) => {
buf.write_u8(Type::Float as u8);
buf.write_u64(f.to_bits());
}
DumpableValue::Complex(c) => {
buf.write_u8(Type::Complex as u8);
buf.write_u64(c.re.to_bits());
buf.write_u64(c.im.to_bits());
}
DumpableValue::Boolean(b) => {
buf.write_u8(if b { Type::True } else { Type::False } as u8);
}
DumpableValue::Str(s) => {
buf.write_u8(Type::Unicode as u8);
write_vec(buf, s.as_bytes());
}
DumpableValue::Bytes(b) => {
buf.write_u8(Type::Bytes as u8);
write_vec(buf, b);
}
DumpableValue::Code(c) => {
buf.write_u8(Type::Code as u8);
serialize_code(buf, c);
}
DumpableValue::Tuple(tup) => {
buf.write_u8(Type::Tuple as u8);
write_len(buf, tup.len());
for val in tup {
val.with_dump(|val| serialize_value(buf, val))??
}
}
DumpableValue::None => {
buf.write_u8(Type::None as u8);
}
DumpableValue::Ellipsis => {
buf.write_u8(Type::Ellipsis as u8);
}
DumpableValue::StopIter => {
buf.write_u8(Type::StopIter as u8);
}
DumpableValue::List(l) => {
buf.write_u8(Type::List as u8);
write_len(buf, l.len());
for val in l {
val.with_dump(|val| serialize_value(buf, val))??
}
}
DumpableValue::Set(set) => {
buf.write_u8(Type::Set as u8);
write_len(buf, set.len());
for val in set {
val.with_dump(|val| serialize_value(buf, val))??
}
}
DumpableValue::Frozenset(set) => {
buf.write_u8(Type::FrozenSet as u8);
write_len(buf, set.len());
for val in set {
val.with_dump(|val| serialize_value(buf, val))??
}
}
DumpableValue::Dict(d) => {
buf.write_u8(Type::Dict as u8);
write_len(buf, d.len());
for (k, v) in d {
k.with_dump(|val| serialize_value(buf, val))??;
v.with_dump(|val| serialize_value(buf, val))??;
}
}
}
Ok(())
}
pub fn serialize_code<W: Write, C: Constant>(buf: &mut W, code: &CodeObject<C>) {
write_len(buf, code.instructions.len());
// SAFETY: it's ok to transmute CodeUnit to [u8; 2]
let (_, instructions_bytes, _) = unsafe { code.instructions.align_to() };
buf.write_slice(instructions_bytes);
write_len(buf, code.locations.len());
for loc in &*code.locations {
buf.write_u32(loc.row.get());
buf.write_u32(loc.column.to_zero_indexed());
}
buf.write_u16(code.flags.bits());
buf.write_u32(code.posonlyarg_count);
buf.write_u32(code.arg_count);
buf.write_u32(code.kwonlyarg_count);
write_vec(buf, code.source_path.as_ref().as_bytes());
buf.write_u32(code.first_line_number.map_or(0, |x| x.get()));
buf.write_u32(code.max_stackdepth);
write_vec(buf, code.obj_name.as_ref().as_bytes());
let cell2arg = code.cell2arg.as_deref().unwrap_or(&[]);
write_len(buf, cell2arg.len());
for &i in cell2arg {
buf.write_u32(i as u32)
}
write_len(buf, code.constants.len());
for constant in &*code.constants {
serialize_value(buf, constant.borrow_constant().into()).unwrap_or_else(|x| match x {})
}
let mut write_names = |names: &[C::Name]| {
write_len(buf, names.len());
for name in names {
write_vec(buf, name.as_ref().as_bytes());
}
};
write_names(&code.names);
write_names(&code.varnames);
write_names(&code.cellvars);
write_names(&code.freevars);
}

33
compiler/core/src/mode.rs Normal file
View File

@@ -0,0 +1,33 @@
pub use rustpython_parser_core::mode::ModeParseError;
#[derive(Clone, Copy)]
pub enum Mode {
Exec,
Eval,
Single,
BlockExpr,
}
impl std::str::FromStr for Mode {
type Err = ModeParseError;
// To support `builtins.compile()` `mode` argument
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"exec" => Ok(Mode::Exec),
"eval" => Ok(Mode::Eval),
"single" => Ok(Mode::Single),
_ => Err(ModeParseError),
}
}
}
impl From<Mode> for rustpython_parser_core::Mode {
fn from(mode: Mode) -> Self {
match mode {
Mode::Exec => Self::Module,
Mode::Eval => Self::Expression,
Mode::Single | Mode::BlockExpr => Self::Interactive,
}
}
}

View File

@@ -2,32 +2,30 @@ use rustpython_codegen::{compile, symboltable};
use rustpython_parser::ast::{fold::Fold, ConstantOptimizer};
pub use rustpython_codegen::compile::CompileOpts;
pub use rustpython_compiler_core::{CodeObject, Mode, SourceLocator};
pub use rustpython_compiler_core::{bytecode::CodeObject, Mode};
pub use rustpython_parser::source_code::SourceLocator;
// these modules are out of repository. re-exporting them here for convenience.
pub use rustpython_codegen as codegen;
pub use rustpython_compiler_core as core;
pub use rustpython_parser as parser;
use std::error::Error as StdError;
use std::fmt;
#[derive(Debug)]
pub enum CompileErrorType {
Codegen(rustpython_codegen::error::CodegenErrorType),
Parse(parser::ParseErrorType),
}
impl StdError for CompileErrorType {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
impl std::error::Error for CompileErrorType {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
CompileErrorType::Codegen(e) => e.source(),
CompileErrorType::Parse(e) => e.source(),
}
}
}
impl fmt::Display for CompileErrorType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
impl std::fmt::Display for CompileErrorType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
CompileErrorType::Codegen(e) => e.fmt(f),
CompileErrorType::Parse(e) => e.fmt(f),
@@ -45,19 +43,19 @@ impl From<parser::ParseErrorType> for CompileErrorType {
}
}
pub type CompileError = rustpython_compiler_core::LocatedError<CompileErrorType>;
pub type CompileError = rustpython_parser::source_code::LocatedError<CompileErrorType>;
/// Compile a given source code into a bytecode object.
pub fn compile(
source: &str,
mode: compile::Mode,
mode: Mode,
source_path: String,
opts: CompileOpts,
) -> Result<CodeObject, CompileError> {
let mut locator = SourceLocator::new(source);
let mut ast = match parser::parse(source, mode.into(), &source_path) {
Ok(x) => x,
Err(e) => return Err(e.into_located(&mut locator)),
Err(e) => return Err(locator.locate_error(e)),
};
if opts.optimize > 0 {
ast = ConstantOptimizer::new()
@@ -70,21 +68,21 @@ pub fn compile(
pub fn compile_symtable(
source: &str,
mode: compile::Mode,
mode: Mode,
source_path: &str,
) -> Result<symboltable::SymbolTable, CompileError> {
let mut locator = SourceLocator::new(source);
let res = match mode {
compile::Mode::Exec | compile::Mode::Single | compile::Mode::BlockExpr => {
let ast = parser::parse_program(source, source_path)
.map_err(|e| e.into_located(&mut locator))?;
let ast = rustpython_parser::ast::locate(&mut locator, ast);
Mode::Exec | Mode::Single | Mode::BlockExpr => {
let ast =
parser::parse_program(source, source_path).map_err(|e| locator.locate_error(e))?;
let ast = locator.fold(ast).unwrap();
symboltable::SymbolTable::scan_program(&ast)
}
compile::Mode::Eval => {
Mode::Eval => {
let expr = parser::parse_expression(source, source_path)
.map_err(|e| e.into_located(&mut locator))?;
let expr = rustpython_parser::ast::locate(&mut locator, expr);
.map_err(|e| locator.locate_error(e))?;
let expr = locator.fold(expr).unwrap();
symboltable::SymbolTable::scan_expr(&expr)
}
};

View File

@@ -5,7 +5,8 @@ edition = "2021"
[dependencies]
rustpython-compiler-core = { workspace = true }
rustpython-doc = { git = "https://github.com/RustPython/__doc__", branch = "main" }
rustpython-parser-core = { workspace = true }
rustpython-doc = { workspace = true }
indexmap = { workspace = true }
itertools = { workspace = true }

View File

@@ -17,7 +17,7 @@ use crate::{extract_spans, Diagnostic};
use once_cell::sync::Lazy;
use proc_macro2::{Span, TokenStream};
use quote::quote;
use rustpython_compiler_core::{frozen_lib, CodeObject, Mode};
use rustpython_compiler_core::{bytecode::CodeObject, frozen, Mode};
use std::{
collections::HashMap,
env, fs,
@@ -318,7 +318,7 @@ impl PyCompileInput {
source,
mode: mode.unwrap_or(Mode::Exec),
module_name: module_name.unwrap_or_else(|| "frozen".to_owned()),
crate_name: crate_name.unwrap_or_else(|| syn::parse_quote!(::rustpython_vm::bytecode)),
crate_name: crate_name.unwrap_or_else(|| syn::parse_quote!(::rustpython_vm)),
})
}
}
@@ -374,11 +374,11 @@ pub fn impl_py_compile(
.source
.compile_single(args.mode, args.module_name, compiler)?;
let frozen = frozen_lib::FrozenCodeObject::encode(&code);
let frozen = frozen::FrozenCodeObject::encode(&code);
let bytes = LitByteStr::new(&frozen.bytes, Span::call_site());
let output = quote! {
#crate_name::frozen_lib::FrozenCodeObject { bytes: &#bytes[..] }
#crate_name::frozen::FrozenCodeObject { bytes: &#bytes[..] }
};
Ok(output)
@@ -394,9 +394,9 @@ pub fn impl_py_freeze(
let crate_name = args.crate_name;
let code_map = args.source.compile(args.mode, args.module_name, compiler)?;
let data = frozen_lib::FrozenLib::encode(code_map.iter().map(|(k, v)| {
let v = frozen_lib::FrozenModule {
code: frozen_lib::FrozenCodeObject::encode(&v.code),
let data = frozen::FrozenLib::encode(code_map.iter().map(|(k, v)| {
let v = frozen::FrozenModule {
code: frozen::FrozenCodeObject::encode(&v.code),
package: v.package,
};
(&**k, v)
@@ -404,7 +404,7 @@ pub fn impl_py_freeze(
let bytes = LitByteStr::new(&data.bytes, Span::call_site());
let output = quote! {
#crate_name::frozen_lib::FrozenLib::from_ref(#bytes)
#crate_name::frozen::FrozenLib::from_ref(#bytes)
};
Ok(output)

View File

@@ -1,8 +1,8 @@
use cranelift::prelude::*;
use num_traits::cast::ToPrimitive;
use rustpython_compiler_core::{
self as bytecode, BinaryOperator, BorrowedConstant, CodeObject, ComparisonOperator,
Instruction, Label, OpArg, OpArgState, UnaryOperator,
use rustpython_compiler_core::bytecode::{
self, BinaryOperator, BorrowedConstant, CodeObject, ComparisonOperator, Instruction, Label,
OpArg, OpArgState, UnaryOperator,
};
use std::collections::HashMap;

View File

@@ -4,7 +4,7 @@ use cranelift::prelude::*;
use cranelift_jit::{JITBuilder, JITModule};
use cranelift_module::{FuncId, Linkage, Module, ModuleError};
use instructions::FunctionCompiler;
use rustpython_compiler_core as bytecode;
use rustpython_compiler_core::bytecode;
use std::{fmt, mem::ManuallyDrop};
#[derive(Debug, thiserror::Error)]

View File

@@ -1,4 +1,6 @@
use rustpython_compiler_core::{CodeObject, ConstantData, Instruction, OpArg, OpArgState};
use rustpython_compiler_core::bytecode::{
CodeObject, ConstantData, Instruction, OpArg, OpArgState,
};
use rustpython_jit::{CompiledCode, JitType};
use std::collections::HashMap;
use std::ops::ControlFlow;
@@ -165,7 +167,7 @@ macro_rules! jit_function {
crate_name = "rustpython_compiler_core",
source = $($t)*
);
let code = code.decode(rustpython_compiler_core::BasicBag);
let code = code.decode(rustpython_compiler_core::bytecode::BasicBag);
let mut machine = $crate::common::StackMachine::new();
machine.run(code);
machine.get_function(stringify!($func_name)).compile()

View File

@@ -10,5 +10,5 @@ pub const LIB_PATH: &str = match option_env!("win_lib_path") {
};
#[cfg(feature = "freeze-stdlib")]
pub const FROZEN_STDLIB: &rustpython_compiler_core::frozen_lib::FrozenLib =
pub const FROZEN_STDLIB: &rustpython_compiler_core::frozen::FrozenLib =
rustpython_derive::py_freeze!(dir = "./Lib", crate_name = "rustpython_compiler_core");

View File

@@ -10,7 +10,7 @@ mod decl {
stderr,
" File \"{}\", line {} in {}",
frame.code.source_path,
frame.current_location().row.to_one_indexed(),
frame.current_location().row.to_usize(),
frame.code.obj_name
)
}

View File

@@ -33,6 +33,7 @@ rustpython-jit = { path = "../jit", optional = true, version = "0.2.0" }
rustpython-ast = { workspace = true, optional = true }
rustpython-parser = { workspace = true, optional = true }
rustpython-compiler-core = { workspace = true }
rustpython-parser-core = { workspace = true }
rustpython-literal = { workspace = true }
ascii = { workspace = true }

View File

@@ -8,8 +8,9 @@ use crate::{
bytecode::{self, AsBag, BorrowedConstant, CodeFlags, Constant, ConstantBag},
class::{PyClassImpl, StaticType},
convert::ToPyObject,
frozen,
function::{FuncArgs, OptionalArg},
source::try_location_field,
source_code::OneIndexed,
types::Representable,
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyResult, VirtualMachine,
};
@@ -27,7 +28,7 @@ pub struct ReplaceArgs {
#[pyarg(named, optional)]
co_filename: OptionalArg<PyStrRef>,
#[pyarg(named, optional)]
co_firstlineno: OptionalArg<usize>,
co_firstlineno: OptionalArg<u32>,
#[pyarg(named, optional)]
co_consts: OptionalArg<Vec<PyObjectRef>>,
#[pyarg(named, optional)]
@@ -181,7 +182,7 @@ impl IntoCodeObject for bytecode::CodeObject {
}
}
impl<B: AsRef<[u8]>> IntoCodeObject for bytecode::frozen_lib::FrozenCodeObject<B> {
impl<B: AsRef<[u8]>> IntoCodeObject for frozen::FrozenCodeObject<B> {
fn into_code_object(self, ctx: &Context) -> CodeObject {
self.decode(ctx)
}
@@ -226,7 +227,7 @@ impl Representable for PyCode {
code.obj_name,
zelf.get_id(),
code.source_path.as_str(),
code.first_line_number
code.first_line_number.map_or(-1, |n| n.get() as i32)
))
}
}
@@ -276,8 +277,8 @@ impl PyCode {
}
#[pygetset]
fn co_firstlineno(&self) -> usize {
self.code.first_line_number.to_one_indexed()
fn co_firstlineno(&self) -> u32 {
self.code.first_line_number.map_or(0, |n| n.get())
}
#[pygetset]
@@ -349,7 +350,7 @@ impl PyCode {
};
let first_line_number = match args.co_firstlineno {
OptionalArg::Present(first_line_number) => try_location_field(first_line_number, vm)?,
OptionalArg::Present(first_line_number) => OneIndexed::new(first_line_number),
OptionalArg::Missing => self.code.first_line_number,
};

View File

@@ -60,7 +60,7 @@ impl Frame {
#[pygetset]
pub fn f_lineno(&self) -> usize {
self.current_location().row.to_one_indexed()
self.current_location().row.to_usize()
}
#[pygetset]

View File

@@ -1,8 +1,9 @@
use rustpython_common::lock::PyMutex;
use super::PyType;
use crate::{class::PyClassImpl, frame::FrameRef, Context, Py, PyPayload, PyRef};
use rustpython_compiler_core::LineNumber;
use crate::{
class::PyClassImpl, frame::FrameRef, source_code::LineNumber, Context, Py, PyPayload, PyRef,
};
#[pyclass(module = false, name = "traceback", traverse)]
#[derive(Debug)]
@@ -46,7 +47,7 @@ impl PyTraceback {
#[pygetset]
fn tb_lineno(&self) -> usize {
self.lineno.to_one_indexed()
self.lineno.to_usize()
}
#[pygetset]
@@ -77,7 +78,7 @@ impl serde::Serialize for PyTraceback {
let mut struc = s.serialize_struct("PyTraceback", 3)?;
struc.serialize_field("name", self.frame.code.obj_name.as_str())?;
struc.serialize_field("lineno", &self.lineno)?;
struc.serialize_field("lineno", &self.lineno.get())?;
struc.serialize_field("filename", self.frame.code.source_path.as_str())?;
struc.end()
}

View File

@@ -4,7 +4,12 @@ use crate::{builtins::PyBaseExceptionRef, convert::ToPyException, VirtualMachine
pub use rustpython_codegen::CompileOpts;
#[cfg(feature = "rustpython-compiler")]
pub use rustpython_compiler::*;
pub use rustpython_compiler_core::Mode;
#[cfg(not(feature = "rustpython-compiler"))]
pub use rustpython_compiler_core as core;
#[cfg(all(not(feature = "rustpython-compiler"), feature = "rustpython-parser"))]
pub use rustpython_parser_core as parser;
#[cfg(not(feature = "rustpython-compiler"))]
mod error {

View File

@@ -259,7 +259,7 @@ fn write_traceback_entry<W: Write>(
r##" File "{}", line {}, in {}"##,
filename, tb_entry.lineno, tb_entry.frame.code.obj_name
)?;
print_source_line(output, filename, tb_entry.lineno.to_one_indexed())?;
print_source_line(output, filename, tb_entry.lineno.to_usize())?;
Ok(())
}

View File

@@ -14,17 +14,16 @@ use crate::{
function::{ArgMapping, Either, FuncArgs},
protocol::{PyIter, PyIterReturn},
scope::Scope,
source_code::SourceLocation,
stdlib::builtins,
vm::{Context, PyMethod},
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
};
use indexmap::IndexMap;
use itertools::Itertools;
use rustpython_compiler_core::source_code::SourceLocation;
use std::fmt;
use std::iter::zip;
#[cfg(feature = "threading")]
use std::sync::atomic;
use std::{fmt, iter::zip};
#[derive(Clone, Debug)]
struct Block {

View File

@@ -1,37 +0,0 @@
use crate::bytecode::frozen_lib::FrozenModule;
pub fn core_frozen_inits() -> impl Iterator<Item = (&'static str, FrozenModule)> {
let iter = std::iter::empty();
macro_rules! ext_modules {
($iter:ident, $($t:tt)*) => {
let $iter = $iter.chain(py_freeze!($($t)*));
};
}
// keep as example but use file one now
// ext_modules!(
// iter,
// source = "initialized = True; print(\"Hello world!\")\n",
// module_name = "__hello__",
// );
// Python modules that the vm calls into, but are not actually part of the stdlib. They could
// in theory be implemented in Rust, but are easiest to do in Python for one reason or another.
// Includes _importlib_bootstrap and _importlib_bootstrap_external
ext_modules!(
iter,
dir = "./Lib/python_builtins",
crate_name = "rustpython_compiler_core"
);
// core stdlib Python modules that the vm calls into, but are still used in Python
// application code, e.g. copyreg
#[cfg(not(feature = "freeze-stdlib"))]
ext_modules!(
iter,
dir = "./Lib/core_modules",
crate_name = "rustpython_compiler_core"
);
iter
}

View File

@@ -10,6 +10,7 @@ use crate::{
bitflags::bitflags! {
// METH_XXX flags in CPython
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct PyMethodFlags: u32 {
// const VARARGS = 0x0001;
// const KEYWORDS = 0x0002;

View File

@@ -55,7 +55,6 @@ pub mod eval;
pub mod exceptions;
pub mod format;
pub mod frame;
mod frozen;
pub mod function;
pub mod import;
mod intern;
@@ -81,6 +80,7 @@ pub mod version;
pub mod vm;
pub mod warn;
pub use self::compiler::parser::source_code;
pub use self::convert::{TryFromBorrowedObject, TryFromObject};
pub use self::object::{
AsObject, Py, PyAtomicRef, PyExact, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact,
@@ -89,7 +89,7 @@ pub use self::object::{
pub use self::vm::{Context, Interpreter, Settings, VirtualMachine};
pub use rustpython_common as common;
pub use rustpython_compiler_core as bytecode;
pub use rustpython_compiler_core::{bytecode, frozen};
pub use rustpython_literal as literal;
#[doc(hidden)]

20
vm/src/source.rs Normal file
View File

@@ -0,0 +1,20 @@
use crate::source_code::SourceLocation;
// pub(crate) fn new_location_error(
// index: usize,
// field: &str,
// vm: &VirtualMachine,
// ) -> PyRef<PyBaseException> {
// vm.new_value_error(format!("value {index} is too large for location {field}"))
// }
pub(crate) struct AtLocation<'a>(pub Option<&'a SourceLocation>);
impl std::fmt::Display for AtLocation<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let (row, column) = self
.0
.map_or((0, 0), |l| (l.row.to_usize(), l.column.to_usize()));
write!(f, " at line {row} column {column}",)
}
}

View File

@@ -9,22 +9,20 @@ use crate::{
builtins::{self, PyModule, PyStrRef, PyType},
class::{PyClassImpl, StaticType},
compiler::CompileError,
compiler::{
core::bytecode::OpArgType,
parser::text_size::{TextRange, TextSize},
},
convert::ToPyException,
source::try_location_field,
source_code::{OneIndexed, SourceLocation, SourceLocator, SourceRange},
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
VirtualMachine,
};
use num_complex::Complex64;
use num_traits::{ToPrimitive, Zero};
use rustpython_ast::{
self as ast,
fold::Fold,
location::{SourceLocation, SourceRange},
SourceLocator,
};
use rustpython_ast::{self as ast, fold::Fold};
#[cfg(feature = "rustpython-codegen")]
use rustpython_codegen as codegen;
use rustpython_compiler_core::text_size::{TextRange, TextSize};
#[cfg(feature = "rustpython-parser")]
use rustpython_parser as parser;
@@ -161,13 +159,16 @@ impl<T: NamedNode> Node for ast::located::Located<T> {
}
fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult<Self> {
fn make_location(row: u32, column: u32) -> Option<SourceLocation> {
Some(SourceLocation {
row: OneIndexed::new(row)?,
column: OneIndexed::from_zero_indexed(column),
})
}
let row = Node::ast_from_object(vm, get_node_field(vm, &object, "lineno", T::NAME)?)?;
let column =
Node::ast_from_object(vm, get_node_field(vm, &object, "col_offset", T::NAME)?)?;
let location = SourceLocation {
row: try_location_field(row, vm)?,
column: try_location_field(column, vm)?,
};
let location = make_location(row, column);
let end_row = get_node_field_opt(vm, &object, "end_lineno")?
.map(|obj| Node::ast_from_object(vm, obj))
.transpose()?;
@@ -175,11 +176,7 @@ impl<T: NamedNode> Node for ast::located::Located<T> {
.map(|obj| Node::ast_from_object(vm, obj))
.transpose()?;
let end_location = if let (Some(row), Some(column)) = (end_row, end_column) {
let location = SourceLocation {
row: try_location_field(row, vm)?,
column: try_location_field(column, vm)?,
};
Some(location)
make_location(row, column)
} else {
None
};
@@ -187,7 +184,7 @@ impl<T: NamedNode> Node for ast::located::Located<T> {
Ok(ast::located::Located {
range: TextRange::empty(TextSize::new(0)),
custom: SourceRange {
start: location,
start: location.unwrap_or(SourceLocation::default()),
end: end_location,
},
node,
@@ -206,7 +203,7 @@ fn node_add_location(
.unwrap();
dict.set_item(
"col_offset",
vm.ctx.new_int(location.column.get()).into(),
vm.ctx.new_int(location.column.to_zero_indexed()).into(),
vm,
)
.unwrap();
@@ -219,7 +216,7 @@ fn node_add_location(
.unwrap();
dict.set_item(
"end_col_offset",
vm.ctx.new_int(end_location.column.get()).into(),
vm.ctx.new_int(end_location.column.to_zero_indexed()).into(),
vm,
)
.unwrap();
@@ -236,7 +233,7 @@ impl Node for String {
}
}
impl Node for usize {
impl Node for u32 {
fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef {
vm.ctx.new_int(self).into()
}
@@ -320,8 +317,8 @@ impl Node for ast::ConversionFlag {
fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult<Self> {
i32::try_from_object(vm, object)?
.to_usize()
.and_then(|f| f.try_into().ok())
.to_u32()
.and_then(ast::ConversionFlag::from_op_arg)
.ok_or_else(|| vm.new_value_error("invalid conversion flag".to_owned()))
}
}
@@ -333,7 +330,7 @@ pub(crate) fn parse(
mode: parser::Mode,
) -> Result<PyObjectRef, CompileError> {
let mut locator = SourceLocator::new(source);
let top = parser::parse(source, mode, "<unknown>").map_err(|e| e.into_located(&mut locator))?;
let top = parser::parse(source, mode, "<unknown>").map_err(|e| locator.locate_error(e))?;
let top = locator.fold_mod(top).unwrap();
Ok(top.ast_to_object(vm))
}
@@ -343,7 +340,7 @@ pub(crate) fn compile(
vm: &VirtualMachine,
object: PyObjectRef,
filename: &str,
mode: codegen::compile::Mode,
mode: crate::compiler::Mode,
) -> PyResult {
let opts = vm.compile_opts();
let ast = Node::ast_from_object(vm, object)?;

View File

@@ -2785,17 +2785,6 @@ impl Node for ast::located::StmtKind {
}
}
fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult<Self> {
let _location = {
let row = try_location_field(
Node::ast_from_object(_vm, get_node_field(_vm, &_object, "lineno", "stmt")?)?,
_vm,
)?;
let column = try_location_field(
Node::ast_from_object(_vm, get_node_field(_vm, &_object, "col_offset", "stmt")?)?,
_vm,
)?;
SourceLocation { row, column }
};
let _cls = _object.class();
Ok(if _cls.is(NodeFunctionDef::static_type()) {
ast::located::StmtKind::FunctionDef(ast::located::StmtFunctionDef {
@@ -3421,17 +3410,6 @@ impl Node for ast::located::ExprKind {
}
}
fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult<Self> {
let _location = {
let row = try_location_field(
Node::ast_from_object(_vm, get_node_field(_vm, &_object, "lineno", "expr")?)?,
_vm,
)?;
let column = try_location_field(
Node::ast_from_object(_vm, get_node_field(_vm, &_object, "col_offset", "expr")?)?,
_vm,
)?;
SourceLocation { row, column }
};
let _cls = _object.class();
Ok(if _cls.is(NodeBoolOp::static_type()) {
ast::located::ExprKind::BoolOp(ast::located::ExprBoolOp {
@@ -4052,23 +4030,6 @@ impl Node for ast::located::ExcepthandlerKind {
}
}
fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult<Self> {
let _location = {
let row = try_location_field(
Node::ast_from_object(
_vm,
get_node_field(_vm, &_object, "lineno", "excepthandler")?,
)?,
_vm,
)?;
let column = try_location_field(
Node::ast_from_object(
_vm,
get_node_field(_vm, &_object, "col_offset", "excepthandler")?,
)?,
_vm,
)?;
SourceLocation { row, column }
};
let _cls = _object.class();
Ok(if _cls.is(NodeExceptHandler::static_type()) {
ast::located::ExcepthandlerKind::ExceptHandler(
@@ -4186,17 +4147,6 @@ impl Node for ast::located::ArgData {
_node.into()
}
fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult<Self> {
let _location = {
let row = try_location_field(
Node::ast_from_object(_vm, get_node_field(_vm, &_object, "lineno", "arg")?)?,
_vm,
)?;
let column = try_location_field(
Node::ast_from_object(_vm, get_node_field(_vm, &_object, "col_offset", "arg")?)?,
_vm,
)?;
SourceLocation { row, column }
};
Ok(ast::located::ArgData {
arg: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "arg", "arg")?)?,
annotation: get_node_field_opt(_vm, &_object, "annotation")?
@@ -4225,20 +4175,6 @@ impl Node for ast::located::KeywordData {
_node.into()
}
fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult<Self> {
let _location = {
let row = try_location_field(
Node::ast_from_object(_vm, get_node_field(_vm, &_object, "lineno", "keyword")?)?,
_vm,
)?;
let column = try_location_field(
Node::ast_from_object(
_vm,
get_node_field(_vm, &_object, "col_offset", "keyword")?,
)?,
_vm,
)?;
SourceLocation { row, column }
};
Ok(ast::located::KeywordData {
arg: get_node_field_opt(_vm, &_object, "arg")?
.map(|obj| Node::ast_from_object(_vm, obj))
@@ -4266,17 +4202,6 @@ impl Node for ast::located::AliasData {
_node.into()
}
fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult<Self> {
let _location = {
let row = try_location_field(
Node::ast_from_object(_vm, get_node_field(_vm, &_object, "lineno", "alias")?)?,
_vm,
)?;
let column = try_location_field(
Node::ast_from_object(_vm, get_node_field(_vm, &_object, "col_offset", "alias")?)?,
_vm,
)?;
SourceLocation { row, column }
};
Ok(ast::located::AliasData {
name: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "name", "alias")?)?,
asname: get_node_field_opt(_vm, &_object, "asname")?
@@ -4474,20 +4399,6 @@ impl Node for ast::located::PatternKind {
}
}
fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult<Self> {
let _location = {
let row = try_location_field(
Node::ast_from_object(_vm, get_node_field(_vm, &_object, "lineno", "pattern")?)?,
_vm,
)?;
let column = try_location_field(
Node::ast_from_object(
_vm,
get_node_field(_vm, &_object, "col_offset", "pattern")?,
)?,
_vm,
)?;
SourceLocation { row, column }
};
let _cls = _object.class();
Ok(if _cls.is(NodeMatchValue::static_type()) {
ast::located::PatternKind::MatchValue(ast::located::PatternMatchValue {

View File

@@ -1,4 +1,4 @@
use crate::bytecode::frozen_lib::FrozenModule;
use crate::frozen::FrozenModule;
use crate::{builtins::PyBaseExceptionRef, VirtualMachine};
pub(crate) use _imp::make_module;

View File

@@ -722,7 +722,7 @@ mod _io {
}
bitflags::bitflags! {
#[derive(Default)]
#[derive(Copy, Clone, Debug, PartialEq, Default)]
struct BufferedFlags: u8 {
const DETACHED = 1 << 0;
const WRITABLE = 1 << 1;
@@ -3723,6 +3723,7 @@ mod fileio {
use std::io::{Read, Write};
bitflags::bitflags! {
#[derive(Copy, Clone, Debug, PartialEq)]
struct Mode: u8 {
const CREATED = 0b0001;
const READABLE = 0b0010;

View File

@@ -164,6 +164,7 @@ pub mod module {
// Flags for os_access
bitflags! {
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct AccessFlags: u8 {
const F_OK = _os::F_OK;
const R_OK = _os::R_OK;

View File

@@ -59,8 +59,8 @@ mod symtable {
}
#[pymethod]
fn get_lineno(&self) -> usize {
self.symtable.line_number.to_one_indexed()
fn get_lineno(&self) -> u32 {
self.symtable.line_number
}
#[pymethod]

View File

@@ -118,6 +118,7 @@ impl std::fmt::Debug for PyTypeSlots {
}
bitflags! {
#[derive(Copy, Clone, Debug, PartialEq)]
#[non_exhaustive]
pub struct PyTypeFlags: u64 {
const IMMUTABLETYPE = 1 << 8;
@@ -140,10 +141,10 @@ impl PyTypeFlags {
/// Used for types created in Python. Subclassable and are a
/// heaptype.
pub const fn heap_type_flags() -> Self {
unsafe {
Self::from_bits_unchecked(
Self::DEFAULT.bits | Self::HEAPTYPE.bits | Self::BASETYPE.bits,
)
match Self::from_bits(Self::DEFAULT.bits() | Self::HEAPTYPE.bits() | Self::BASETYPE.bits())
{
Some(flags) => flags,
None => unreachable!(),
}
}

View File

@@ -22,12 +22,11 @@ use crate::{
PyBaseExceptionRef, PyDictRef, PyInt, PyList, PyModule, PyStr, PyStrInterned, PyStrRef,
PyTypeRef,
},
bytecode::frozen_lib::FrozenModule,
codecs::CodecsRegistry,
common::{hash::HashSecret, lock::PyMutex, rc::PyRc},
convert::ToPyObject,
frame::{ExecutionResult, Frame, FrameRef},
frozen,
frozen::FrozenModule,
function::{ArgMapping, FuncArgs, PySetterValue},
import,
protocol::PyIterIter,
@@ -196,7 +195,7 @@ impl VirtualMachine {
panic!("Interpreters in same process must share the hash seed");
}
let frozen = frozen::core_frozen_inits().collect();
let frozen = core_frozen_inits().collect();
PyRc::get_mut(&mut vm.state).unwrap().frozen = frozen;
vm.builtins.init_dict(
@@ -837,6 +836,42 @@ impl AsRef<Context> for VirtualMachine {
}
}
fn core_frozen_inits() -> impl Iterator<Item = (&'static str, FrozenModule)> {
let iter = std::iter::empty();
macro_rules! ext_modules {
($iter:ident, $($t:tt)*) => {
let $iter = $iter.chain(py_freeze!($($t)*));
};
}
// keep as example but use file one now
// ext_modules!(
// iter,
// source = "initialized = True; print(\"Hello world!\")\n",
// module_name = "__hello__",
// );
// Python modules that the vm calls into, but are not actually part of the stdlib. They could
// in theory be implemented in Rust, but are easiest to do in Python for one reason or another.
// Includes _importlib_bootstrap and _importlib_bootstrap_external
ext_modules!(
iter,
dir = "./Lib/python_builtins",
crate_name = "rustpython_compiler_core"
);
// core stdlib Python modules that the vm calls into, but are still used in Python
// application code, e.g. copyreg
#[cfg(not(feature = "freeze-stdlib"))]
ext_modules!(
iter,
dir = "./Lib/core_modules",
crate_name = "rustpython_compiler_core"
);
iter
}
#[test]
fn test_nested_frozen() {
use rustpython_vm as vm;

View File

@@ -9,10 +9,10 @@ use crate::{
function::{IntoPyNativeFn, PyMethodFlags},
scope::Scope,
source::AtLocation,
source_code::SourceLocation,
vm::VirtualMachine,
AsObject, Py, PyObject, PyObjectRef, PyRef,
};
use rustpython_ast::location::SourceLocation;
/// Collection of object creation helpers
impl VirtualMachine {
@@ -272,7 +272,7 @@ impl VirtualMachine {
fn get_statement(source: &str, loc: Option<SourceLocation>) -> Option<String> {
let line = source
.split('\n')
.nth(loc?.row.to_zero_indexed())?
.nth(loc?.row.to_zero_indexed_usize())?
.to_owned();
Some(line + "\n")
}
@@ -296,7 +296,7 @@ impl VirtualMachine {
"{error}{at_location}\n{stmt}{arrow:>pad$}",
error = error.error,
at_location = AtLocation(loc.as_ref()),
pad = loc.map_or(0, |loc| loc.column.to_one_indexed()),
pad = loc.map_or(0, |loc| loc.column.to_usize()),
arrow = "^"
)
} else {

View File

@@ -246,11 +246,15 @@ pub fn js_to_py(vm: &VirtualMachine, js_val: JsValue) -> PyObjectRef {
pub fn syntax_err(err: CompileError) -> SyntaxError {
let js_err = SyntaxError::new(&format!("Error parsing Python code: {err}"));
let _ = Reflect::set(&js_err, &"row".into(), &(err.location.row() as u32).into());
let _ = Reflect::set(
&js_err,
&"row".into(),
&(err.location.unwrap().row.get()).into(),
);
let _ = Reflect::set(
&js_err,
&"col".into(),
&(err.location.column() as u32).into(),
&(err.location.unwrap().column.get()).into(),
);
let can_continue = matches!(&err.error, CompileErrorType::Parse(ParseErrorType::Eof));
let _ = Reflect::set(&js_err, &"canContinue".into(), &can_continue.into());