mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Initial import from rspython repo
This commit is contained in:
1 parent
baf208be7a
commit
cb394ebdc4
16 files changed
+2876
No files matched your search
@@ -0,0 +1,6 @@
|
||||
|
||||
language: rust
|
||||
|
||||
rust:
|
||||
- stable
|
||||
- beta
|
||||
Generated
+740
@@ -0,0 +1,740 @@
|
||||
[[package]]
|
||||
name = "RustPython"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lalrpop 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lalrpop-util 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "ascii-canvas"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byte-tools"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.31.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "debug_unreachable"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diff"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "docopt"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "ena"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fake-simd"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-zircon"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-zircon-sys"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.7.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ascii-canvas 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ena 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lalrpop-snap 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lalrpop-util 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"string_cache 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop-snap"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ascii-canvas 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ena 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lalrpop-util 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"string_cache 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lalrpop-util"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ordermap"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.7.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.7.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "precomputed-hash"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "1.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "redox_termios"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.0.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.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "string_cache"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"phf_shared 0.7.22 (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.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "string_cache_codegen"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.5.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)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "string_cache_shared"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "term"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termion"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "ucd-util"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unreachable"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unreachable"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8-ranges"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-build"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "wincolor"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[metadata]
|
||||
"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
|
||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
"checksum arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0fd1479b7c29641adbd35ff3b5c293922d696a92f25c8c975da3e0acbc87258f"
|
||||
"checksum ascii-canvas 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b385d69402821a1c254533a011a312531cbcc0e3e24f19bbb4747a5a2daf37e2"
|
||||
"checksum atty 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d0fd4c0631f06448cc45a6bbb3b710ebb7ff8ccb96a0800c994afe23a70d5df2"
|
||||
"checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1"
|
||||
"checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
|
||||
"checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f"
|
||||
"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789"
|
||||
"checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"
|
||||
"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
|
||||
"checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18"
|
||||
"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
|
||||
"checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
|
||||
"checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
|
||||
"checksum digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "00a49051fef47a72c9623101b19bd71924a45cca838826caae3eaa4d00772603"
|
||||
"checksum docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d8acd393692c503b168471874953a2531df0e9ab77d0b6bbc582395743300a4a"
|
||||
"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
|
||||
"checksum ena 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cabe5a5078ac8c506d3e4430763b1ba9b609b1286913e7d08e581d1c2de9b7e5"
|
||||
"checksum env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0e6e40ebb0e66918a37b38c7acab4e10d299e0463fe2af5d29b9cc86710cfd2a"
|
||||
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
|
||||
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||
"checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
|
||||
"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e"
|
||||
"checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum lalrpop 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ba451f7bd819b7afc99d4cf4bdcd5a4861e64955ba9680ac70df3a50625ad6cf"
|
||||
"checksum lalrpop-snap 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "60013fd6be14317d43f47658b1440956a9ca48a9ed0257e0e0a59aac13e43a1f"
|
||||
"checksum lalrpop-util 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "60c6c48ba857cd700673ce88907cadcdd7e2cd7783ed02378537c5ffd4f6460c"
|
||||
"checksum lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739"
|
||||
"checksum libc 0.2.41 (registry+https://github.com/rust-lang/crates.io-index)" = "ac8ebf8343a981e2fa97042b14768f02ed3e1d602eac06cae6166df3c8ced206"
|
||||
"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"
|
||||
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
|
||||
"checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
|
||||
"checksum petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "8b30dc85588cd02b9b76f5e386535db546d21dc68506cff2abebee0b6445e8e4"
|
||||
"checksum phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "05a079dd052e7b674d21cb31cbb6c05efd56a2cd2827db7692e2f1a507ebd998"
|
||||
"checksum phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c2261d544c2bb6aa3b10022b0be371b9c7c64f762ef28c6f5d4f1ef6d97b5930"
|
||||
"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7"
|
||||
"checksum proc-macro2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1fa93823f53cfd0f5ac117b189aed6cfdfb2cfc0a9d82e956dd7927595ed7d46"
|
||||
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
|
||||
"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8"
|
||||
"checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035"
|
||||
"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
|
||||
"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
|
||||
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||
"checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384"
|
||||
"checksum regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75ecf88252dce580404a22444fc7d626c01815debba56a7f4f536772a5ff19d3"
|
||||
"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e"
|
||||
"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7"
|
||||
"checksum regex-syntax 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1ac0f60d675cc6cf13a20ec076568254472551051ad5dd050364d70671bf6b"
|
||||
"checksum serde 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "fba5be06346c5200249c8c8ca4ccba4a09e8747c71c16e420bd359a0db4d8f91"
|
||||
"checksum serde_derive 1.0.64 (registry+https://github.com/rust-lang/crates.io-index)" = "79e4620ba6fbe051fc7506fab6f84205823564d55da18d55b695160fb3479cd8"
|
||||
"checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0"
|
||||
"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
|
||||
"checksum string_cache 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2bc8ae5fbdcafd8573e2bfc14acb54720e27bbf102376ed05d6052f7eb238b27"
|
||||
"checksum string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35293b05cf1494e8ddd042a7df6756bf18d07f42d234f32e71dce8a7aabb0191"
|
||||
"checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
|
||||
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
|
||||
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
|
||||
"checksum syn 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6dfd71b2be5a58ee30a6f8ea355ba8290d397131c00dfa55c3d34e6e13db5101"
|
||||
"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
|
||||
"checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83"
|
||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
|
||||
"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
|
||||
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
|
||||
"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
|
||||
"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 unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
|
||||
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
|
||||
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
|
||||
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
|
||||
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
"checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767"
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
|
||||
[package]
|
||||
name = "RustPython"
|
||||
version = "0.0.1"
|
||||
authors = [ "Shing Lyu", "Windel Bouwman" ]
|
||||
build = "build.rs"
|
||||
|
||||
[build-dependencies]
|
||||
lalrpop="0.15.1"
|
||||
|
||||
[dependencies]
|
||||
clap="2.20.0"
|
||||
lalrpop-util="0.15.1"
|
||||
regex="0.2.2"
|
||||
log="0.4.1"
|
||||
env_logger="0.5.10"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
extern crate lalrpop;
|
||||
|
||||
fn main() {
|
||||
lalrpop::process_root().unwrap();
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Implement abstract syntax tree nodes for the python language.
|
||||
*/
|
||||
|
||||
/*
|
||||
#[derive(Debug)]
|
||||
pub struct Location {
|
||||
pub row: i32,
|
||||
pub column: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Node {
|
||||
pub location: Location,
|
||||
}
|
||||
*/
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Program {
|
||||
pub statements: Vec<Statement>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Statement {
|
||||
Break,
|
||||
Continue,
|
||||
Return {
|
||||
value: Option<Vec<Expression>>,
|
||||
},
|
||||
Import {
|
||||
name: String,
|
||||
},
|
||||
Pass,
|
||||
Assert {
|
||||
test: Expression,
|
||||
msg: Option<Expression>,
|
||||
},
|
||||
Delete {
|
||||
targets: Vec<Expression>,
|
||||
},
|
||||
Assign {
|
||||
targets: Vec<Expression>,
|
||||
value: Expression,
|
||||
},
|
||||
Expression {
|
||||
expression: Expression,
|
||||
},
|
||||
If {
|
||||
test: Expression,
|
||||
body: Vec<Statement>,
|
||||
},
|
||||
While {
|
||||
test: Expression,
|
||||
body: Vec<Statement>,
|
||||
},
|
||||
With {
|
||||
items: Expression,
|
||||
body: Vec<Statement>,
|
||||
},
|
||||
For {
|
||||
target: Vec<Expression>,
|
||||
iter: Vec<Expression>,
|
||||
body: Vec<Statement>,
|
||||
or_else: Option<Vec<Statement>>,
|
||||
},
|
||||
ClassDef {
|
||||
name: String,
|
||||
// TODO: docstring: String,
|
||||
},
|
||||
FunctionDef {
|
||||
name: String,
|
||||
// docstring: String,
|
||||
body: Vec<Statement>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Expression {
|
||||
Binop {
|
||||
a: Box<Expression>,
|
||||
op: Operator,
|
||||
b: Box<Expression>,
|
||||
},
|
||||
Call {
|
||||
function: Box<Expression>,
|
||||
args: Vec<Expression>,
|
||||
},
|
||||
Number {
|
||||
value: i32,
|
||||
},
|
||||
List {
|
||||
elements: Vec<Expression>,
|
||||
},
|
||||
Tuple {
|
||||
elements: Vec<Expression>,
|
||||
},
|
||||
String {
|
||||
value: String,
|
||||
},
|
||||
Identifier {
|
||||
name: String,
|
||||
},
|
||||
True,
|
||||
False,
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Operator {
|
||||
Add,
|
||||
Sub,
|
||||
Mult,
|
||||
MatMult,
|
||||
Div,
|
||||
Mod,
|
||||
Pow,
|
||||
LShift,
|
||||
RShift,
|
||||
BitOr,
|
||||
BitXor,
|
||||
BitAnd,
|
||||
FloorDiv,
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Some functions are built into the interpreter, for example the print
|
||||
* function is such a builtin function.
|
||||
*
|
||||
* Inspiration can be found here:
|
||||
* https://github.com/python/cpython/blob/master/Python/bltinmodule.c
|
||||
*/
|
||||
|
||||
use super::pyobject::PyObjectRef;
|
||||
use std::io::{self, Write};
|
||||
|
||||
pub fn fill_scope() {
|
||||
// scope[String::from("print")] = print;
|
||||
}
|
||||
|
||||
pub fn print(args: Vec<PyObjectRef>) {
|
||||
// println!("Woot: {:?}", args);
|
||||
trace!("print called with {:?}", args);
|
||||
for a in args {
|
||||
print!("{} ", a.borrow_mut().str());
|
||||
}
|
||||
println!();
|
||||
io::stdout().flush().unwrap();
|
||||
}
|
||||
|
||||
fn any() {}
|
||||
|
||||
fn all() {}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Implement python as a virtual machine with bytecodes.
|
||||
*/
|
||||
|
||||
/*
|
||||
let load_const_string = 0x16;
|
||||
let call_function = 0x64;
|
||||
*/
|
||||
|
||||
/*
|
||||
* Primitive instruction type, which can be encoded and decoded.
|
||||
*/
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CodeObject {
|
||||
pub instructions: Vec<Instruction>,
|
||||
pub label_map: HashMap<Label, usize>,
|
||||
}
|
||||
|
||||
impl CodeObject {
|
||||
pub fn new() -> CodeObject {
|
||||
CodeObject {
|
||||
instructions: Vec::new(),
|
||||
label_map: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type Label = usize;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Instruction {
|
||||
LoadName { name: String },
|
||||
StoreName { name: String },
|
||||
LoadConst { value: Constant },
|
||||
UnaryOperation { op: UnaryOperator },
|
||||
BinaryOperation { op: BinaryOperator },
|
||||
Pop,
|
||||
GetIter,
|
||||
Pass,
|
||||
Continue,
|
||||
Break,
|
||||
Jump { target: Label },
|
||||
JumpIf { target: Label },
|
||||
CallFunction { count: usize },
|
||||
ForIter,
|
||||
ReturnValue,
|
||||
PushBlock { start: Label, end: Label },
|
||||
PopBlock,
|
||||
BuildTuple { size: usize },
|
||||
BuildList { size: usize },
|
||||
BuildMap { size: usize },
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Constant {
|
||||
Integer { value: i32 },
|
||||
// TODO: Float { value: f64 },
|
||||
String { value: String },
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BinaryOperator {
|
||||
Power,
|
||||
Multiply,
|
||||
MatrixMultiply,
|
||||
Divide,
|
||||
FloorDivide,
|
||||
Modulo,
|
||||
Add,
|
||||
Subtract,
|
||||
Lshift,
|
||||
Rshift,
|
||||
And,
|
||||
Xor,
|
||||
Or,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum UnaryOperator {
|
||||
Not,
|
||||
Minus,
|
||||
}
|
||||
|
||||
/*
|
||||
Maintain a stack of blocks on the VM.
|
||||
pub enum BlockType {
|
||||
Loop,
|
||||
Except,
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Take an AST and transform it into bytecode
|
||||
*/
|
||||
|
||||
use super::ast;
|
||||
use super::bytecode::{self, CodeObject, Instruction};
|
||||
|
||||
struct Compiler {
|
||||
code_object: CodeObject,
|
||||
nxt_label: usize,
|
||||
}
|
||||
|
||||
pub fn compile(p: ast::Program) -> CodeObject {
|
||||
let mut compiler = Compiler::new();
|
||||
compiler.compile_program(p);
|
||||
compiler.code_object
|
||||
}
|
||||
|
||||
type Label = usize;
|
||||
|
||||
impl Compiler {
|
||||
fn new() -> Self {
|
||||
Compiler {
|
||||
code_object: CodeObject::new(),
|
||||
nxt_label: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_program(&mut self, program: ast::Program) {
|
||||
self.compile_statements(program.statements);
|
||||
}
|
||||
|
||||
fn compile_statements(&mut self, statements: Vec<ast::Statement>) {
|
||||
for statement in statements {
|
||||
self.compile_statement(statement)
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a new label
|
||||
fn new_label(&mut self) -> Label {
|
||||
let l = self.nxt_label;
|
||||
self.nxt_label += 1;
|
||||
l
|
||||
}
|
||||
|
||||
// Assign current position the given label
|
||||
fn set_label(&mut self, label: Label) {
|
||||
let position = self.code_object.instructions.len();
|
||||
// assert!(label not in self.label_map)
|
||||
self.code_object.label_map.insert(label, position);
|
||||
}
|
||||
|
||||
fn compile_statement(&mut self, statement: ast::Statement) {
|
||||
trace!("Compiling {:?}", statement);
|
||||
match statement {
|
||||
ast::Statement::Import { name } => {}
|
||||
ast::Statement::Expression { expression } => {
|
||||
self.compile_expression(expression);
|
||||
|
||||
// Pop result of stack, since we not use it:
|
||||
self.emit(Instruction::Pop);
|
||||
}
|
||||
ast::Statement::If { test, body } => {
|
||||
self.compile_expression(test);
|
||||
let else_label = self.new_label();
|
||||
self.emit(Instruction::JumpIf { target: else_label });
|
||||
self.compile_statements(body);
|
||||
self.set_label(else_label);
|
||||
}
|
||||
ast::Statement::While { test, body } => {
|
||||
let start_label = self.new_label();
|
||||
let end_label = self.new_label();
|
||||
self.set_label(start_label);
|
||||
|
||||
self.compile_expression(test);
|
||||
self.emit(Instruction::UnaryOperation { op: bytecode::UnaryOperator::Not });
|
||||
self.emit(Instruction::JumpIf { target: end_label });
|
||||
self.compile_statements(body);
|
||||
self.emit(Instruction::Jump { target: start_label });
|
||||
self.set_label(end_label);
|
||||
}
|
||||
ast::Statement::With { items, body } => {
|
||||
// TODO
|
||||
}
|
||||
ast::Statement::For {
|
||||
target,
|
||||
iter,
|
||||
body,
|
||||
or_else,
|
||||
} => {
|
||||
// The thing iterated:
|
||||
for i in iter {
|
||||
self.compile_expression(i);
|
||||
}
|
||||
|
||||
// Retrieve iterator
|
||||
self.emit(Instruction::GetIter);
|
||||
|
||||
// Start loop
|
||||
let start_label = self.new_label();
|
||||
let end_label = self.new_label();
|
||||
self.emit(Instruction::PushBlock {
|
||||
start: start_label,
|
||||
end: end_label,
|
||||
});
|
||||
self.set_label(start_label);
|
||||
self.emit(Instruction::ForIter);
|
||||
|
||||
// Start of loop iteration, set targets:
|
||||
for t in target {
|
||||
match t {
|
||||
ast::Expression::Identifier { name } => {
|
||||
self.emit(Instruction::StoreName { name: name });
|
||||
}
|
||||
_ => panic!("Not impl"),
|
||||
}
|
||||
}
|
||||
|
||||
// Body of loop:
|
||||
self.compile_statements(body);
|
||||
self.set_label(end_label);
|
||||
self.emit(Instruction::PopBlock);
|
||||
}
|
||||
ast::Statement::FunctionDef { name, body } => {
|
||||
self.compile_statements(body);
|
||||
}
|
||||
ast::Statement::ClassDef { name } => {
|
||||
// TODO?
|
||||
}
|
||||
ast::Statement::Assert { test, msg } => {
|
||||
// TODO: if some flag, ignore all assert statements!
|
||||
|
||||
self.compile_expression(test);
|
||||
|
||||
// if true, jump over raise:
|
||||
|
||||
self.emit(Instruction::LoadName {
|
||||
name: String::from("AssertionError"),
|
||||
});
|
||||
match msg {
|
||||
Some(e) => {
|
||||
self.compile_expression(e);
|
||||
self.emit(Instruction::CallFunction { count: 1 });
|
||||
}
|
||||
None => {
|
||||
self.emit(Instruction::CallFunction { count: 0 });
|
||||
}
|
||||
}
|
||||
// TODO?
|
||||
}
|
||||
ast::Statement::Break => {
|
||||
self.emit(Instruction::Break);
|
||||
}
|
||||
ast::Statement::Continue => {
|
||||
self.emit(Instruction::Continue);
|
||||
}
|
||||
ast::Statement::Return { value } => {
|
||||
match value {
|
||||
Some(e) => {
|
||||
let size = e.len();
|
||||
for v in e {
|
||||
self.compile_expression(v);
|
||||
}
|
||||
|
||||
// If we have more than 1 return value, make it a tuple:
|
||||
if size > 1 {
|
||||
self.emit(Instruction::BuildTuple { size });
|
||||
}
|
||||
}
|
||||
None => {
|
||||
// TODO: Put none on stack
|
||||
}
|
||||
}
|
||||
|
||||
self.emit(Instruction::ReturnValue);
|
||||
}
|
||||
ast::Statement::Assign { targets, value } => {
|
||||
self.compile_expression(value);
|
||||
|
||||
for target in targets {
|
||||
match target {
|
||||
ast::Expression::Identifier { name } => {
|
||||
self.emit(Instruction::StoreName { name: name });
|
||||
}
|
||||
_ => {
|
||||
panic!("WTF");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::Statement::Delete { targets } => {
|
||||
// Remove the given names from the scope
|
||||
// self.emit(Instruction::DeleteName);
|
||||
}
|
||||
ast::Statement::Pass => {
|
||||
self.emit(Instruction::Pass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_expression(&mut self, expression: ast::Expression) {
|
||||
trace!("Compiling {:?}", expression);
|
||||
match expression {
|
||||
ast::Expression::Call { function, args } => {
|
||||
self.compile_expression(*function);
|
||||
let count = args.len();
|
||||
for arg in args {
|
||||
self.compile_expression(arg)
|
||||
}
|
||||
self.emit(Instruction::CallFunction { count: count });
|
||||
}
|
||||
ast::Expression::Binop { a, op, b } => {
|
||||
self.compile_expression(*a);
|
||||
self.compile_expression(*b);
|
||||
|
||||
// Perform operation:
|
||||
let i = match op {
|
||||
ast::Operator::Add => bytecode::BinaryOperator::Add,
|
||||
ast::Operator::Sub => bytecode::BinaryOperator::Subtract,
|
||||
ast::Operator::Mult => bytecode::BinaryOperator::Multiply,
|
||||
ast::Operator::MatMult => bytecode::BinaryOperator::MatrixMultiply,
|
||||
ast::Operator::Div => bytecode::BinaryOperator::Divide,
|
||||
ast::Operator::FloorDiv => bytecode::BinaryOperator::FloorDivide,
|
||||
ast::Operator::Mod => bytecode::BinaryOperator::Modulo,
|
||||
ast::Operator::Pow => bytecode::BinaryOperator::Power,
|
||||
ast::Operator::LShift => bytecode::BinaryOperator::Lshift,
|
||||
ast::Operator::RShift => bytecode::BinaryOperator::Rshift,
|
||||
ast::Operator::BitOr => bytecode::BinaryOperator::Or,
|
||||
ast::Operator::BitXor => bytecode::BinaryOperator::Xor,
|
||||
ast::Operator::BitAnd => bytecode::BinaryOperator::And,
|
||||
};
|
||||
let i = Instruction::BinaryOperation { op: i };
|
||||
self.emit(i);
|
||||
}
|
||||
ast::Expression::Number { value } => {
|
||||
self.emit(Instruction::LoadConst { value: bytecode::Constant::Integer { value: value } });
|
||||
}
|
||||
ast::Expression::List { elements } => {
|
||||
let size = elements.len();
|
||||
for element in elements {
|
||||
self.compile_expression(element);
|
||||
}
|
||||
self.emit(Instruction::BuildList { size: size });
|
||||
}
|
||||
ast::Expression::Tuple { elements } => {
|
||||
let size = elements.len();
|
||||
for element in elements {
|
||||
self.compile_expression(element);
|
||||
}
|
||||
self.emit(Instruction::BuildTuple { size: size });
|
||||
}
|
||||
ast::Expression::True => {
|
||||
self.emit(Instruction::LoadConst { value: bytecode::Constant::Integer { value: 1 } });
|
||||
}
|
||||
ast::Expression::False => {
|
||||
self.emit(Instruction::LoadConst { value: bytecode::Constant::Integer { value: 0 } });
|
||||
}
|
||||
ast::Expression::None => {
|
||||
self.emit(Instruction::LoadConst { value: bytecode::Constant::Integer { value: 0 } });
|
||||
}
|
||||
ast::Expression::String { value } => {
|
||||
self.emit(Instruction::LoadConst { value: bytecode::Constant::String { value: value } });
|
||||
}
|
||||
ast::Expression::Identifier { name } => {
|
||||
self.emit(Instruction::LoadName { name });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn emit(&mut self, instruction: Instruction) {
|
||||
self.code_object.instructions.push(instruction);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,600 @@
|
||||
use std::str::FromStr;
|
||||
use std::str::CharIndices;
|
||||
pub use super::token::Tok;
|
||||
use std::iter::FromIterator;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct Lexer<'input> {
|
||||
chars: CharIndices<'input>,
|
||||
at_begin_of_line: bool,
|
||||
nesting: usize, // Amount of parenthesis
|
||||
indentation_stack: Vec<usize>,
|
||||
chr0: Option<char>,
|
||||
chr1: Option<char>,
|
||||
location: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LexicalError {
|
||||
StringError,
|
||||
}
|
||||
|
||||
pub type Spanned<Tok> = Result<(usize, Tok, usize), LexicalError>;
|
||||
|
||||
pub fn lex_source(source: &String) -> Vec<Tok> {
|
||||
let lexer = Lexer::new(source);
|
||||
Vec::from_iter(lexer.map(|x| x.unwrap().1))
|
||||
}
|
||||
|
||||
impl<'input> Lexer<'input> {
|
||||
pub fn new(input: &'input str) -> Self {
|
||||
let mut lxr = Lexer {
|
||||
chars: input.char_indices(),
|
||||
at_begin_of_line: true,
|
||||
nesting: 0,
|
||||
indentation_stack: vec![0],
|
||||
chr0: None,
|
||||
location: 0,
|
||||
chr1: None,
|
||||
};
|
||||
lxr.next_char();
|
||||
lxr.next_char();
|
||||
lxr
|
||||
}
|
||||
|
||||
// Lexer helper functions:
|
||||
fn lex_identifier(&mut self) -> Spanned<Tok> {
|
||||
let mut name = String::new();
|
||||
let start_pos = self.location;
|
||||
while self.is_char() {
|
||||
name.push(self.next_char().unwrap());
|
||||
}
|
||||
let end_pos = self.location;
|
||||
|
||||
let mut keywords: HashMap<String, Tok> = HashMap::new();
|
||||
|
||||
// Alphabetical keywords:
|
||||
keywords.insert(String::from("False"), Tok::False);
|
||||
keywords.insert(String::from("None"), Tok::None);
|
||||
keywords.insert(String::from("True"), Tok::True);
|
||||
|
||||
keywords.insert(String::from("and"), Tok::And);
|
||||
keywords.insert(String::from("as"), Tok::As);
|
||||
keywords.insert(String::from("assert"), Tok::Assert);
|
||||
keywords.insert(String::from("break"), Tok::Break);
|
||||
keywords.insert(String::from("class"), Tok::Class);
|
||||
keywords.insert(String::from("continue"), Tok::Continue);
|
||||
keywords.insert(String::from("def"), Tok::Def);
|
||||
keywords.insert(String::from("del"), Tok::Del);
|
||||
keywords.insert(String::from("elif"), Tok::Elif);
|
||||
keywords.insert(String::from("else"), Tok::Else);
|
||||
keywords.insert(String::from("except"), Tok::Except);
|
||||
keywords.insert(String::from("finally"), Tok::Finally);
|
||||
keywords.insert(String::from("for"), Tok::For);
|
||||
keywords.insert(String::from("from"), Tok::From);
|
||||
keywords.insert(String::from("global"), Tok::Global);
|
||||
keywords.insert(String::from("if"), Tok::If);
|
||||
keywords.insert(String::from("import"), Tok::Import);
|
||||
keywords.insert(String::from("in"), Tok::In);
|
||||
keywords.insert(String::from("is"), Tok::Is);
|
||||
keywords.insert(String::from("lambda"), Tok::Lambda);
|
||||
keywords.insert(String::from("nonlocal"), Tok::Nonlocal);
|
||||
keywords.insert(String::from("not"), Tok::Not);
|
||||
keywords.insert(String::from("or"), Tok::Or);
|
||||
keywords.insert(String::from("pass"), Tok::Pass);
|
||||
keywords.insert(String::from("raise"), Tok::Raise);
|
||||
keywords.insert(String::from("return"), Tok::Return);
|
||||
keywords.insert(String::from("try"), Tok::Try);
|
||||
keywords.insert(String::from("while"), Tok::While);
|
||||
keywords.insert(String::from("with"), Tok::With);
|
||||
keywords.insert(String::from("yield"), Tok::Yield);
|
||||
|
||||
if keywords.contains_key(&name) {
|
||||
Ok((start_pos, keywords.remove(&name).unwrap(), end_pos))
|
||||
} else {
|
||||
Ok((start_pos, Tok::Name { name: name }, end_pos))
|
||||
}
|
||||
}
|
||||
|
||||
fn lex_number(&mut self) -> Spanned<Tok> {
|
||||
let mut value_text = String::new();
|
||||
|
||||
let start_pos = self.location;
|
||||
while self.is_number() {
|
||||
value_text.push(self.next_char().unwrap());
|
||||
}
|
||||
let end_pos = self.location;
|
||||
|
||||
let value = i32::from_str(&value_text).unwrap();
|
||||
|
||||
return Ok((start_pos, Tok::Number { value: value }, end_pos));
|
||||
}
|
||||
|
||||
fn lex_comment(&mut self) {
|
||||
// Skip everything until end of line
|
||||
self.next_char();
|
||||
loop {
|
||||
match self.next_char() {
|
||||
Some(c) => {
|
||||
if c == '\n' {
|
||||
return;
|
||||
}
|
||||
}
|
||||
None => return,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lex_string(&mut self) -> Spanned<Tok> {
|
||||
let quote_char = self.next_char().unwrap();
|
||||
let mut string_content = String::new();
|
||||
let start_pos = self.location;
|
||||
|
||||
loop {
|
||||
match self.next_char() {
|
||||
Some(c) => {
|
||||
if c == quote_char {
|
||||
break;
|
||||
} else {
|
||||
string_content.push(c);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
return Err(LexicalError::StringError);
|
||||
}
|
||||
}
|
||||
}
|
||||
let end_pos = self.location;
|
||||
|
||||
return Ok((
|
||||
start_pos,
|
||||
Tok::String {
|
||||
value: string_content,
|
||||
},
|
||||
end_pos,
|
||||
));
|
||||
}
|
||||
|
||||
fn is_char(&self) -> bool {
|
||||
match self.chr0 {
|
||||
Some('a'...'z') => return true,
|
||||
_ => return false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_number(&self) -> bool {
|
||||
match self.chr0 {
|
||||
Some('0'...'9') => return true,
|
||||
_ => return false,
|
||||
}
|
||||
}
|
||||
|
||||
fn next_char(&mut self) -> Option<char> {
|
||||
let c = self.chr0;
|
||||
let nxt = self.chars.next();
|
||||
self.chr0 = self.chr1;
|
||||
self.chr1 = nxt.map(|x| x.1);
|
||||
self.location = match nxt {
|
||||
Some(p) => p.0,
|
||||
None => 99999,
|
||||
};
|
||||
c
|
||||
}
|
||||
}
|
||||
|
||||
/* Implement iterator pattern for the get_tok function.
|
||||
|
||||
Calling the next element in the iterator will yield the next lexical
|
||||
token.
|
||||
*/
|
||||
impl<'input> Iterator for Lexer<'input> {
|
||||
type Item = Spanned<Tok>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
// Idea: create some sort of hash map for single char tokens:
|
||||
// let mut X = HashMap::new();
|
||||
// X.insert('=', Tok::Equal);
|
||||
|
||||
// Detect indentation levels
|
||||
loop {
|
||||
if self.at_begin_of_line {
|
||||
self.at_begin_of_line = false;
|
||||
|
||||
// Determine indentation:
|
||||
let mut col: usize = 0;
|
||||
loop {
|
||||
match self.chr0 {
|
||||
Some(' ') => {
|
||||
self.next_char();
|
||||
col += 1;
|
||||
}
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.nesting == 0 {
|
||||
// Determine indent or dedent:
|
||||
let current_indentation = *self.indentation_stack.last().unwrap();
|
||||
if col == current_indentation {
|
||||
// Same same
|
||||
} else if col > current_indentation {
|
||||
// New indentation level:
|
||||
self.indentation_stack.push(col);
|
||||
return Some(Ok((0, Tok::Indent, 0)));
|
||||
} else if col < current_indentation {
|
||||
// One or more dedentations
|
||||
return Some(Ok((0, Tok::Dedent, 0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match self.chr0 {
|
||||
Some('0'...'9') => return Some(self.lex_number()),
|
||||
// TODO: 'A'...'Z'
|
||||
Some('a'...'z') => return Some(self.lex_identifier()),
|
||||
Some('#') => {
|
||||
self.lex_comment();
|
||||
continue;
|
||||
}
|
||||
Some('"') => {
|
||||
return Some(self.lex_string());
|
||||
}
|
||||
Some('\'') => {
|
||||
return Some(self.lex_string());
|
||||
}
|
||||
Some('=') => {
|
||||
self.next_char();
|
||||
match self.chr0 {
|
||||
Some('=') => {
|
||||
self.next_char();
|
||||
return Some(Ok((self.location, Tok::EqEqual, self.location + 1)));
|
||||
}
|
||||
_ => return Some(Ok((self.location, Tok::Equal, self.location + 1))),
|
||||
}
|
||||
}
|
||||
Some('+') => {
|
||||
self.next_char();
|
||||
match self.chr0 {
|
||||
Some('=') => {
|
||||
self.next_char();
|
||||
return Some(Ok((self.location, Tok::PlusEqual, self.location + 1)));
|
||||
}
|
||||
_ => return Some(Ok((self.location, Tok::Plus, self.location + 1))),
|
||||
}
|
||||
}
|
||||
Some('*') => {
|
||||
let tok_start = self.location;
|
||||
self.next_char();
|
||||
match self.chr0 {
|
||||
Some('=') => {
|
||||
self.next_char();
|
||||
return Some(Ok((tok_start, Tok::StarEqual, self.location + 1)));
|
||||
}
|
||||
Some('*') => {
|
||||
self.next_char();
|
||||
return Some(Ok((tok_start, Tok::DoubleStar, self.location + 1)));
|
||||
}
|
||||
_ => return Some(Ok((tok_start, Tok::Star, self.location + 1))),
|
||||
}
|
||||
}
|
||||
Some('/') => {
|
||||
let tok_start = self.location;
|
||||
self.next_char();
|
||||
match self.chr0 {
|
||||
Some('=') => {
|
||||
self.next_char();
|
||||
return Some(Ok((tok_start, Tok::SlashEqual, self.location + 1)));
|
||||
}
|
||||
Some('/') => {
|
||||
self.next_char();
|
||||
match self.chr0 {
|
||||
Some('=') => {
|
||||
self.next_char();
|
||||
return Some(Ok((
|
||||
tok_start,
|
||||
Tok::DoubleSlashEqual,
|
||||
self.location + 1,
|
||||
)));
|
||||
}
|
||||
_ => {
|
||||
return Some(Ok((
|
||||
tok_start,
|
||||
Tok::DoubleSlash,
|
||||
self.location + 1,
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => return Some(Ok((tok_start, Tok::Slash, self.location + 1))),
|
||||
}
|
||||
}
|
||||
Some('%') => {
|
||||
self.next_char();
|
||||
match self.chr0 {
|
||||
Some('=') => {
|
||||
self.next_char();
|
||||
return Some(Ok((self.location, Tok::PercentEqual, self.location + 1)));
|
||||
}
|
||||
_ => return Some(Ok((self.location, Tok::Percent, self.location + 1))),
|
||||
}
|
||||
}
|
||||
Some('|') => {
|
||||
self.next_char();
|
||||
match self.chr0 {
|
||||
Some('=') => {
|
||||
self.next_char();
|
||||
return Some(Ok((self.location, Tok::VbarEqual, self.location + 1)));
|
||||
}
|
||||
_ => return Some(Ok((self.location, Tok::Vbar, self.location + 1))),
|
||||
}
|
||||
}
|
||||
Some('^') => {
|
||||
self.next_char();
|
||||
match self.chr0 {
|
||||
Some('=') => {
|
||||
self.next_char();
|
||||
return Some(Ok((
|
||||
self.location,
|
||||
Tok::CircumflexEqual,
|
||||
self.location + 1,
|
||||
)));
|
||||
}
|
||||
_ => return Some(Ok((self.location, Tok::CircumFlex, self.location + 1))),
|
||||
}
|
||||
}
|
||||
Some('&') => {
|
||||
self.next_char();
|
||||
match self.chr0 {
|
||||
Some('=') => {
|
||||
self.next_char();
|
||||
return Some(Ok((self.location, Tok::AmperEqual, self.location + 1)));
|
||||
}
|
||||
_ => return Some(Ok((self.location, Tok::Amper, self.location + 1))),
|
||||
}
|
||||
}
|
||||
Some('-') => {
|
||||
let tok_start = self.location;
|
||||
self.next_char();
|
||||
match self.chr0 {
|
||||
Some('=') => {
|
||||
self.next_char();
|
||||
return Some(Ok((tok_start, Tok::MinusEqual, self.location + 1)));
|
||||
}
|
||||
_ => return Some(Ok((tok_start, Tok::Minus, self.location + 1))),
|
||||
}
|
||||
}
|
||||
Some('@') => {
|
||||
let tok_start = self.location;
|
||||
self.next_char();
|
||||
match self.chr0 {
|
||||
Some('=') => {
|
||||
self.next_char();
|
||||
return Some(Ok((tok_start, Tok::AtEqual, self.location + 1)));
|
||||
}
|
||||
_ => return Some(Ok((tok_start, Tok::At, self.location + 1))),
|
||||
}
|
||||
}
|
||||
Some('~') => {
|
||||
self.next_char();
|
||||
return Some(Ok((0, Tok::Tilde, 0)));
|
||||
}
|
||||
Some('(') => {
|
||||
self.next_char();
|
||||
self.nesting += 1;
|
||||
return Some(Ok((0, Tok::Lpar, 0)));
|
||||
}
|
||||
Some(')') => {
|
||||
self.next_char();
|
||||
self.nesting -= 1;
|
||||
return Some(Ok((0, Tok::Rpar, 0)));
|
||||
}
|
||||
Some('[') => {
|
||||
self.next_char();
|
||||
self.nesting += 1;
|
||||
return Some(Ok((0, Tok::Lsqb, 0)));
|
||||
}
|
||||
Some(']') => {
|
||||
self.next_char();
|
||||
self.nesting -= 1;
|
||||
return Some(Ok((self.location, Tok::Rsqb, self.location + 1)));
|
||||
}
|
||||
Some('{') => {
|
||||
self.next_char();
|
||||
self.nesting += 1;
|
||||
return Some(Ok((0, Tok::Lbrace, 0)));
|
||||
}
|
||||
Some('}') => {
|
||||
self.next_char();
|
||||
self.nesting -= 1;
|
||||
return Some(Ok((self.location, Tok::Rbrace, self.location + 1)));
|
||||
}
|
||||
Some(':') => {
|
||||
self.next_char();
|
||||
return Some(Ok((self.location, Tok::Colon, self.location + 1)));
|
||||
}
|
||||
Some(';') => {
|
||||
self.next_char();
|
||||
return Some(Ok((self.location, Tok::Semi, self.location + 1)));
|
||||
}
|
||||
Some('<') => {
|
||||
let tok_start = self.location;
|
||||
self.next_char();
|
||||
match self.chr0 {
|
||||
Some('<') => {
|
||||
self.next_char();
|
||||
match self.chr0 {
|
||||
Some('=') => {
|
||||
return Some(Ok((
|
||||
tok_start,
|
||||
Tok::LeftShiftEqual,
|
||||
self.location + 1,
|
||||
)))
|
||||
}
|
||||
_ => {
|
||||
return Some(Ok((tok_start, Tok::LeftShift, self.location + 1)))
|
||||
}
|
||||
}
|
||||
}
|
||||
Some('=') => {
|
||||
self.next_char();
|
||||
return Some(Ok((tok_start, Tok::LessEqual, self.location + 1)));
|
||||
}
|
||||
_ => return Some(Ok((tok_start, Tok::Less, self.location + 1))),
|
||||
}
|
||||
}
|
||||
Some('>') => {
|
||||
let tok_start = self.location;
|
||||
self.next_char();
|
||||
match self.chr0 {
|
||||
Some('>') => {
|
||||
self.next_char();
|
||||
match self.chr0 {
|
||||
Some('=') => {
|
||||
return Some(Ok((
|
||||
tok_start,
|
||||
Tok::RightShiftEqual,
|
||||
self.location + 1,
|
||||
)))
|
||||
}
|
||||
_ => {
|
||||
return Some(Ok((tok_start, Tok::RightShift, self.location + 1)))
|
||||
}
|
||||
}
|
||||
}
|
||||
Some('=') => {
|
||||
self.next_char();
|
||||
return Some(Ok((tok_start, Tok::GreaterEqual, self.location + 1)));
|
||||
}
|
||||
_ => return Some(Ok((tok_start, Tok::Greater, self.location + 1))),
|
||||
}
|
||||
}
|
||||
Some(',') => {
|
||||
self.next_char();
|
||||
return Some(Ok((self.location, Tok::Comma, self.location + 1)));
|
||||
}
|
||||
Some('.') => {
|
||||
self.next_char();
|
||||
return Some(Ok((self.location, Tok::Dot, self.location + 1)));
|
||||
}
|
||||
Some('\n') => {
|
||||
self.next_char();
|
||||
|
||||
// Depending on the nesting level, we emit newline or not:
|
||||
if self.nesting == 0 {
|
||||
self.at_begin_of_line = true;
|
||||
return Some(Ok((self.location, Tok::Newline, self.location + 1)));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Some(' ') => {
|
||||
// Skip whitespaces
|
||||
self.next_char();
|
||||
continue;
|
||||
}
|
||||
None => return None,
|
||||
_ => {
|
||||
let c = self.next_char();
|
||||
panic!("Not impl {:?}", c)
|
||||
} // Ignore all the rest..
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::Tok;
|
||||
use super::lex_source;
|
||||
|
||||
#[test]
|
||||
fn test_line_comment() {
|
||||
let source = String::from(r"99232 # Bladibla");
|
||||
let tokens = lex_source(&source);
|
||||
assert_eq!(tokens, vec![Tok::Number { value: 99232 }]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assignment() {
|
||||
let source = String::from(r"avariable = 99 + 2-0");
|
||||
let tokens = lex_source(&source);
|
||||
assert_eq!(
|
||||
tokens,
|
||||
vec![
|
||||
Tok::Name {
|
||||
name: String::from("avariable"),
|
||||
},
|
||||
Tok::Equal,
|
||||
Tok::Number { value: 99 },
|
||||
Tok::Plus,
|
||||
Tok::Number { value: 2 },
|
||||
Tok::Minus,
|
||||
Tok::Number { value: 0 },
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_indentation() {
|
||||
let source = String::from("def foo():\n return 99\n");
|
||||
let tokens = lex_source(&source);
|
||||
assert_eq!(
|
||||
tokens,
|
||||
vec![
|
||||
Tok::Def,
|
||||
Tok::Name {
|
||||
name: String::from("foo"),
|
||||
},
|
||||
Tok::Lpar,
|
||||
Tok::Rpar,
|
||||
Tok::Colon,
|
||||
Tok::Newline,
|
||||
Tok::Indent,
|
||||
Tok::Return,
|
||||
Tok::Number { value: 99 },
|
||||
Tok::Newline,
|
||||
Tok::Dedent,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_newline_in_brackets() {
|
||||
let source = String::from("x = [\n 1,2\n]\n");
|
||||
let tokens = lex_source(&source);
|
||||
assert_eq!(
|
||||
tokens,
|
||||
vec![
|
||||
Tok::Name {
|
||||
name: String::from("x"),
|
||||
},
|
||||
Tok::Equal,
|
||||
Tok::Lsqb,
|
||||
Tok::Number { value: 1 },
|
||||
Tok::Comma,
|
||||
Tok::Number { value: 2 },
|
||||
Tok::Rsqb,
|
||||
Tok::Newline,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_operators() {
|
||||
let source = String::from("//////=/ /");
|
||||
let tokens = lex_source(&source);
|
||||
assert_eq!(
|
||||
tokens,
|
||||
vec![
|
||||
Tok::DoubleSlash,
|
||||
Tok::DoubleSlash,
|
||||
Tok::DoubleSlashEqual,
|
||||
Tok::Slash,
|
||||
Tok::Slash,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// This file makes this directory a submodule.
|
||||
|
||||
mod parser;
|
||||
mod python;
|
||||
mod ast;
|
||||
mod token;
|
||||
mod lexer;
|
||||
mod compile;
|
||||
mod bytecode;
|
||||
mod builtins;
|
||||
mod pyobject;
|
||||
mod vm;
|
||||
|
||||
pub use self::parser::parse;
|
||||
pub use self::compile::compile;
|
||||
pub use self::vm::evaluate;
|
||||
|
||||
|
||||
// Mimic eval code objects:
|
||||
//pub fn eval_code() -> pyobject::PyObjectRef {
|
||||
|
||||
//}
|
||||
@@ -0,0 +1,104 @@
|
||||
use std::error::Error;
|
||||
use std::path::Path;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
|
||||
use super::python;
|
||||
use super::ast;
|
||||
use super::lexer;
|
||||
|
||||
fn read_file(filename: &Path) -> Result<String, String> {
|
||||
match File::open(&filename) {
|
||||
Ok(mut file) => {
|
||||
let mut s = String::new();
|
||||
|
||||
match file.read_to_string(&mut s) {
|
||||
Err(why) => Err(String::from("Reading file failed: ") + why.description()),
|
||||
Ok(_) => Ok(s),
|
||||
}
|
||||
}
|
||||
Err(why) => Err(String::from("Opening file failed: ") + why.description()),
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse python code.
|
||||
* Grammar may be inspired by antlr grammar for python:
|
||||
* https://github.com/antlr/grammars-v4/tree/master/python3
|
||||
*/
|
||||
|
||||
pub fn parse(filename: &Path) -> Result<ast::Program, String> {
|
||||
info!("Parsing: {}", filename.display());
|
||||
match read_file(filename) {
|
||||
Ok(txt) => {
|
||||
debug!("Read contents of file: {}", txt);
|
||||
parse_source(&txt)
|
||||
}
|
||||
Err(msg) => Err(msg),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_source(source: &String) -> Result<ast::Program, String> {
|
||||
let lxr = lexer::Lexer::new(&source);
|
||||
match python::ProgramParser::new().parse(lxr) {
|
||||
Err(why) => Err(String::from(format!("{:?}", why))),
|
||||
Ok(p) => Ok(p),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::parse_source;
|
||||
use super::ast;
|
||||
|
||||
#[test]
|
||||
fn test_parse_print_hello() {
|
||||
let source = String::from("print('Hello world')\n");
|
||||
let parse_ast = parse_source(&source).unwrap();
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
ast::Program {
|
||||
statements: vec![
|
||||
ast::Statement::Expression {
|
||||
expression: ast::Expression::Call {
|
||||
function: Box::new(ast::Expression::Identifier {
|
||||
name: String::from("print"),
|
||||
}),
|
||||
args: vec![
|
||||
ast::Expression::String {
|
||||
value: String::from("Hello world"),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_print_2() {
|
||||
let source = String::from("print('Hello world', 2)\n");
|
||||
let parse_ast = parse_source(&source).unwrap();
|
||||
assert_eq!(
|
||||
parse_ast,
|
||||
ast::Program {
|
||||
statements: vec![
|
||||
ast::Statement::Expression {
|
||||
expression: ast::Expression::Call {
|
||||
function: Box::new(ast::Expression::Identifier {
|
||||
name: String::from("print"),
|
||||
}),
|
||||
args: vec![
|
||||
ast::Expression::String {
|
||||
value: String::from("Hello world"),
|
||||
},
|
||||
ast::Expression::Number { value: 2 },
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::ops::{Add, Mul, Sub};
|
||||
|
||||
/* Python objects and references.
|
||||
|
||||
Okay, so each python object itself is an class itself (PyObject). Each
|
||||
python object can have several references to it (PyObjectRef). These
|
||||
references are Rc (reference counting) rust smart pointers. So when
|
||||
all references are destroyed, the object itself also can be cleaned up.
|
||||
Basically reference counting, but then done by rust.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
The PyRef type implements
|
||||
https://doc.rust-lang.org/std/cell/index.html#introducing-mutability-inside-of-something-immutable
|
||||
*/
|
||||
pub type PyRef<T> = Rc<RefCell<T>>;
|
||||
pub type PyObjectRef = PyRef<PyObject>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PyObject {
|
||||
String {
|
||||
value: String,
|
||||
},
|
||||
Integer {
|
||||
value: i32,
|
||||
},
|
||||
List {
|
||||
elements: Vec<PyObjectRef>,
|
||||
},
|
||||
Tuple {
|
||||
elements: Vec<PyObjectRef>,
|
||||
},
|
||||
Dict,
|
||||
Iterator {
|
||||
position: usize,
|
||||
iterated_obj: PyObjectRef,
|
||||
},
|
||||
None,
|
||||
RustFunction {
|
||||
function: fn(Vec<PyObjectRef>),
|
||||
},
|
||||
}
|
||||
|
||||
/*
|
||||
impl PyObjectRef {
|
||||
pub fn steal(&self) -> &mut PyObject {
|
||||
self.borrow_mut()
|
||||
}
|
||||
}*/
|
||||
|
||||
impl PyObject {
|
||||
pub fn call(&self, args: Vec<PyObjectRef>) {
|
||||
match *self {
|
||||
PyObject::RustFunction { ref function } => {
|
||||
function(args);
|
||||
}
|
||||
_ => {
|
||||
println!("Not impl {:?}", self);
|
||||
panic!("Not impl");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn str(&self) -> String {
|
||||
match *self {
|
||||
PyObject::String { ref value } => value.clone(),
|
||||
PyObject::Integer { ref value } => format!("{:?}", value),
|
||||
PyObject::List { ref elements } => format!("{:?}", elements),
|
||||
PyObject::Tuple { ref elements } => format!("{:?}", elements),
|
||||
PyObject::None => String::from("None"),
|
||||
_ => {
|
||||
println!("Not impl {:?}", self);
|
||||
panic!("Not impl");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implement iterator protocol:
|
||||
pub fn nxt(&mut self) -> Option<PyObjectRef> {
|
||||
match *self {
|
||||
PyObject::Iterator {
|
||||
ref mut position,
|
||||
iterated_obj: ref iterated_obj_ref,
|
||||
} => {
|
||||
let iterated_obj = &*iterated_obj_ref.borrow_mut();
|
||||
match iterated_obj {
|
||||
&PyObject::List { ref elements } => {
|
||||
if *position < elements.len() {
|
||||
let obj_ref = elements[*position].clone();
|
||||
*position += 1;
|
||||
Some(obj_ref)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("NOT IMPL");
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("NOT IMPL");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move this object into a reference object, transferring ownership.
|
||||
pub fn into_ref(self) -> PyObjectRef {
|
||||
Rc::new(RefCell::new(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Add<&'a PyObject> for &'a PyObject {
|
||||
type Output = PyObject;
|
||||
|
||||
fn add(self, rhs: &'a PyObject) -> Self::Output {
|
||||
match self {
|
||||
&PyObject::Integer { ref value } => {
|
||||
let value1 = value;
|
||||
match rhs {
|
||||
&PyObject::Integer { ref value } => {
|
||||
let value2 = value;
|
||||
PyObject::Integer {
|
||||
value: value1 + value2,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("NOT IMPL");
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// TODO: Lookup __add__ method in dictionary?
|
||||
panic!("NOT IMPL");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Sub<&'a PyObject> for &'a PyObject {
|
||||
type Output = PyObject;
|
||||
|
||||
fn sub(self, rhs: &'a PyObject) -> Self::Output {
|
||||
match self {
|
||||
&PyObject::Integer { value } => {
|
||||
let value1 = value;
|
||||
match rhs {
|
||||
&PyObject::Integer { value } => {
|
||||
let value2 = value;
|
||||
PyObject::Integer {
|
||||
value: value1 - value2,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("NOT IMPL");
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("NOT IMPL");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Mul<&'a PyObject> for &'a PyObject {
|
||||
type Output = PyObject;
|
||||
|
||||
fn mul(self, rhs: &'a PyObject) -> Self::Output {
|
||||
match self {
|
||||
&PyObject::Integer { value } => {
|
||||
let value1 = value;
|
||||
match rhs {
|
||||
&PyObject::Integer { value } => {
|
||||
let value2 = value;
|
||||
PyObject::Integer {
|
||||
value: value1 * value2,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("NOT IMPL");
|
||||
}
|
||||
}
|
||||
}
|
||||
&PyObject::String { ref value } => {
|
||||
let value1 = value;
|
||||
match rhs {
|
||||
&PyObject::Integer { value } => {
|
||||
let value2 = value;
|
||||
let mut result = String::new();
|
||||
for _x in 0..value2 {
|
||||
result.push_str(value1.as_str());
|
||||
}
|
||||
PyObject::String { value: result }
|
||||
}
|
||||
_ => {
|
||||
panic!("NOT IMPL");
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("NOT IMPL");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::PyObject;
|
||||
|
||||
#[test]
|
||||
fn test_add_py_integers() {
|
||||
let a = PyObject::Integer { value: 33 };
|
||||
let b = PyObject::Integer { value: 12 };
|
||||
let c = &a + &b;
|
||||
match c {
|
||||
PyObject::Integer { value } => assert_eq!(value, 45),
|
||||
_ => assert!(false),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiply_str() {
|
||||
let a = PyObject::String {
|
||||
value: String::from("Hello "),
|
||||
};
|
||||
let b = PyObject::Integer { value: 4 };
|
||||
let c = &a * &b;
|
||||
match c {
|
||||
PyObject::String { value } => {
|
||||
assert_eq!(value, String::from("Hello Hello Hello Hello "))
|
||||
}
|
||||
_ => assert!(false),
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
// See also: file:///usr/share/doc/python/html/reference/grammar.html?highlight=grammar
|
||||
use super::ast;
|
||||
use super::lexer;
|
||||
use std::iter::FromIterator;
|
||||
|
||||
grammar;
|
||||
|
||||
pub Program: ast::Program = {
|
||||
<lines:FileLine*> => ast::Program { statements: Vec::from_iter(lines.into_iter().filter_map(|e| e)) },
|
||||
};
|
||||
|
||||
// A file line either has a declaration, or an empty newline:
|
||||
FileLine: Option<ast::Statement> = {
|
||||
<s:Statement> => Some(s),
|
||||
"\n" => None,
|
||||
};
|
||||
|
||||
Suite: Vec<ast::Statement> = {
|
||||
<s:SimpleStatement> => vec![s],
|
||||
"\n" indent <s:Statement+> dedent => s,
|
||||
};
|
||||
|
||||
Statement: ast::Statement = {
|
||||
SimpleStatement,
|
||||
CompoundStatement,
|
||||
};
|
||||
|
||||
SimpleStatement: ast::Statement = {
|
||||
<s:SmallStatement> "\n" => s,
|
||||
};
|
||||
|
||||
SmallStatement: ast::Statement = {
|
||||
// <e:Expression> => ast::Statement::Expression { expression: e },
|
||||
ExpressionStatement,
|
||||
"pass" => ast::Statement::Pass,
|
||||
FlowStatement,
|
||||
ImportStatement,
|
||||
AssertStatement,
|
||||
};
|
||||
|
||||
ExpressionStatement: ast::Statement = {
|
||||
<e:TestList> <e2:AssignSuffix*> => {
|
||||
//match e2 {
|
||||
// None => ast::Statement::Expression { expression: e },
|
||||
// Some(e3) => ast::Statement::Expression { expression: e },
|
||||
//}
|
||||
if e2.len() > 0 {
|
||||
// Dealing with assignment here
|
||||
// TODO: for rhs in e2 {
|
||||
let rhs = e2.into_iter().next().unwrap();
|
||||
// ast::Expression::Tuple { elements: e2.into_iter().next().unwrap()
|
||||
let v = rhs.into_iter().next().unwrap();
|
||||
let lhs = ast::Statement::Assign { targets: e, value: v };
|
||||
lhs
|
||||
} else {
|
||||
if e.len() > 1 {
|
||||
panic!("Not good?");
|
||||
// ast::Statement::Expression { expression: e[0] }
|
||||
} else {
|
||||
ast::Statement::Expression { expression: e.into_iter().next().unwrap() }
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
AssignSuffix: Vec<ast::Expression> = {
|
||||
"=" <e:TestList> => e,
|
||||
};
|
||||
|
||||
FlowStatement: ast::Statement = {
|
||||
"break" => ast::Statement::Break,
|
||||
"continue" => ast::Statement::Continue,
|
||||
"return" <t:TestList?> => ast::Statement::Return { value: t},
|
||||
// raise
|
||||
// yield
|
||||
};
|
||||
|
||||
ImportStatement: ast::Statement = {
|
||||
"import" <n:DottedName> => ast::Statement::Import { name: n },
|
||||
};
|
||||
|
||||
DottedName: String = {
|
||||
<n:name> => n,
|
||||
};
|
||||
|
||||
AssertStatement: ast::Statement = {
|
||||
"assert" <t:Test> <m: ("," Test)?> => ast::Statement::Assert {
|
||||
test: t,
|
||||
msg: match m {
|
||||
Some(e) => Some(e.1),
|
||||
None => None,
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
CompoundStatement: ast::Statement = {
|
||||
"if" <e:Test> ":" <s:Suite> => ast::Statement::If { test: e, body: s },
|
||||
"while" <e:Test> ":" <s:Suite> => ast::Statement::While { test: e, body: s },
|
||||
"for" <e:ExpressionList> "in" <t:TestList> ":" <s:Suite> => ast::Statement::For { target: e, iter: t, body: s, or_else: None },
|
||||
"def" <i:Identifier> "(" ")" ":" <s:Suite> => ast::Statement::FunctionDef { name: i, body: s },
|
||||
WithStatement,
|
||||
};
|
||||
|
||||
WithStatement: ast::Statement = {
|
||||
"with" <t:Test> "as" <e:Expression> ":" <s:Suite> => ast::Statement::With { items: t, body: s },
|
||||
};
|
||||
|
||||
Test: ast::Expression = {
|
||||
<e:OrTest> => e,
|
||||
};
|
||||
|
||||
OrTest: ast::Expression = {
|
||||
<e:AndTest> => e,
|
||||
};
|
||||
|
||||
AndTest: ast::Expression = {
|
||||
<e:NotTest> => e,
|
||||
};
|
||||
|
||||
NotTest: ast::Expression = {
|
||||
<e:Expression> => e,
|
||||
};
|
||||
|
||||
Expression: ast::Expression = {
|
||||
<e1:Expression> "|" <e2:XorExpression> => ast::Expression::Binop { a: Box::new(e1), op: ast::Operator::BitOr, b: Box::new(e2) },
|
||||
<e:XorExpression> => e,
|
||||
};
|
||||
|
||||
XorExpression: ast::Expression = {
|
||||
<e1:XorExpression> "^" <e2:AndExpression> => ast::Expression::Binop { a: Box::new(e1), op: ast::Operator::BitXor, b: Box::new(e2) },
|
||||
<e:AndExpression> => e,
|
||||
};
|
||||
|
||||
AndExpression: ast::Expression = {
|
||||
<e1:AndExpression> "&" <e2:ArithmaticExpression> => ast::Expression::Binop { a: Box::new(e1), op: ast::Operator::BitAnd, b: Box::new(e2) },
|
||||
<e:ArithmaticExpression> => e,
|
||||
};
|
||||
|
||||
ArithmaticExpression: ast::Expression = {
|
||||
<a:ArithmaticExpression> <op:AddOp> <b:Term> => ast::Expression::Binop { a: Box::new(a), op: op, b: Box::new(b) },
|
||||
Term,
|
||||
};
|
||||
|
||||
AddOp: ast::Operator = {
|
||||
"+" => ast::Operator::Add,
|
||||
"-" => ast::Operator::Sub,
|
||||
};
|
||||
|
||||
Term: ast::Expression = {
|
||||
<a:Term> <op:MulOp> <b:Factor> => ast::Expression::Binop { a: Box::new(a), op: op, b: Box::new(b) },
|
||||
Factor,
|
||||
};
|
||||
|
||||
MulOp: ast::Operator = {
|
||||
"*" => ast::Operator::Mult,
|
||||
"/" => ast::Operator::Div,
|
||||
"//" => ast::Operator::FloorDiv,
|
||||
"%" => ast::Operator::Mod,
|
||||
"@" => ast::Operator::MatMult,
|
||||
};
|
||||
|
||||
Factor: ast::Expression = {
|
||||
<e:Power> => e,
|
||||
};
|
||||
|
||||
Power: ast::Expression = {
|
||||
<e:Atom> => e,
|
||||
};
|
||||
|
||||
Atom: ast::Expression = {
|
||||
<f:Atom> "(" <a:FunctionArguments> ")" => ast::Expression::Call { function: Box::new(f), args: a },
|
||||
<s:String> => ast::Expression::String { value: s },
|
||||
<n:Number> => ast::Expression::Number { value: n },
|
||||
<i:Identifier> => ast::Expression::Identifier { name: i },
|
||||
"[" <e:TestList> "]" => ast::Expression::List { elements: e },
|
||||
"(" <e:Expression> ")" => e,
|
||||
"True" => ast::Expression::True,
|
||||
"False" => ast::Expression::False,
|
||||
"None" => ast::Expression::None,
|
||||
};
|
||||
|
||||
ExpressionList: Vec<ast::Expression> = {
|
||||
<e: Comma<Expression>> => e,
|
||||
};
|
||||
|
||||
TestList: Vec<ast::Expression> = {
|
||||
<e1:Test> <e2: ("," Test)*> => {
|
||||
let mut l = vec![e1];
|
||||
l.extend(e2.into_iter().map(|x| x.1));
|
||||
l
|
||||
}
|
||||
};
|
||||
|
||||
FunctionArguments: Vec<ast::Expression> = {
|
||||
<e: Comma<Expression>> => e,
|
||||
};
|
||||
|
||||
Comma<T>: Vec<T> = {
|
||||
<items: (<T> ",")*> <last: T?> => {
|
||||
let mut items = items;
|
||||
items.extend(last);
|
||||
items
|
||||
}
|
||||
};
|
||||
|
||||
Number: i32 = <s:number> => s;
|
||||
String: String = {
|
||||
<s:string> => s,
|
||||
};
|
||||
Identifier: String = <s:name> => s;
|
||||
|
||||
// Hook external lexer:
|
||||
extern {
|
||||
type Location = usize;
|
||||
type Error = lexer::LexicalError;
|
||||
|
||||
enum lexer::Tok {
|
||||
indent => lexer::Tok::Indent,
|
||||
dedent => lexer::Tok::Dedent,
|
||||
"+" => lexer::Tok::Plus,
|
||||
"-" => lexer::Tok::Minus,
|
||||
":" => lexer::Tok::Colon,
|
||||
"," => lexer::Tok::Comma,
|
||||
"*" => lexer::Tok::Star,
|
||||
"&" => lexer::Tok::Amper,
|
||||
"@" => lexer::Tok::At,
|
||||
"%" => lexer::Tok::Percent,
|
||||
"//" => lexer::Tok::DoubleSlash,
|
||||
"^" => lexer::Tok::CircumFlex,
|
||||
"|" => lexer::Tok::Vbar,
|
||||
"/" => lexer::Tok::Slash,
|
||||
"(" => lexer::Tok::Lpar,
|
||||
")" => lexer::Tok::Rpar,
|
||||
"[" => lexer::Tok::Lsqb,
|
||||
"]" => lexer::Tok::Rsqb,
|
||||
"=" => lexer::Tok::Equal,
|
||||
"+=" => lexer::Tok::PlusEqual,
|
||||
"-=" => lexer::Tok::MinusEqual,
|
||||
"assert" => lexer::Tok::Assert,
|
||||
"import" => lexer::Tok::Import,
|
||||
"break" => lexer::Tok::Break,
|
||||
"continue" => lexer::Tok::Break,
|
||||
"return" => lexer::Tok::Return,
|
||||
"pass" => lexer::Tok::Pass,
|
||||
"if" => lexer::Tok::If,
|
||||
"while" => lexer::Tok::While,
|
||||
"for" => lexer::Tok::For,
|
||||
"in" => lexer::Tok::In,
|
||||
"with" => lexer::Tok::With,
|
||||
"as" => lexer::Tok::As,
|
||||
"def" => lexer::Tok::Def,
|
||||
"class" => lexer::Tok::Class,
|
||||
"True" => lexer::Tok::True,
|
||||
"False" => lexer::Tok::False,
|
||||
"None" => lexer::Tok::None,
|
||||
number => lexer::Tok::Number { value: <i32> },
|
||||
string => lexer::Tok::String { value: <String> },
|
||||
name => lexer::Tok::Name { name: <String> },
|
||||
"\n" => lexer::Tok::Newline,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
|
||||
// Loosely based on token.h from CPython source:
|
||||
#[derive(Debug)]
|
||||
#[derive(PartialEq)]
|
||||
pub enum Tok {
|
||||
Name { name: String },
|
||||
Number { value: i32 },
|
||||
String { value: String },
|
||||
Newline,
|
||||
Indent,
|
||||
Dedent,
|
||||
Lpar,
|
||||
Rpar,
|
||||
Lsqb,
|
||||
Rsqb,
|
||||
Colon,
|
||||
Comma,
|
||||
Semi,
|
||||
Plus,
|
||||
Minus,
|
||||
Star,
|
||||
Slash,
|
||||
Vbar, // '|'
|
||||
Amper, // '&'
|
||||
Less,
|
||||
Greater,
|
||||
Equal,
|
||||
Dot,
|
||||
Percent,
|
||||
Lbrace,
|
||||
Rbrace,
|
||||
EqEqual,
|
||||
NotEqual,
|
||||
LessEqual,
|
||||
GreaterEqual,
|
||||
Tilde,
|
||||
CircumFlex,
|
||||
LeftShift,
|
||||
RightShift,
|
||||
DoubleStar,
|
||||
PlusEqual,
|
||||
MinusEqual,
|
||||
StarEqual,
|
||||
SlashEqual,
|
||||
PercentEqual,
|
||||
AmperEqual, // '&='
|
||||
VbarEqual,
|
||||
CircumflexEqual, // '^='
|
||||
LeftShiftEqual,
|
||||
RightShiftEqual,
|
||||
DoubleSlash, // '//'
|
||||
DoubleSlashEqual,
|
||||
At,
|
||||
AtEqual,
|
||||
Rarrow,
|
||||
Ellipses,
|
||||
|
||||
// Keywords (alphabetically):
|
||||
|
||||
False,
|
||||
None,
|
||||
True,
|
||||
|
||||
And,
|
||||
As,
|
||||
Assert,
|
||||
Break,
|
||||
Class,
|
||||
Continue,
|
||||
Def,
|
||||
Del,
|
||||
Elif,
|
||||
Else,
|
||||
Except,
|
||||
Finally,
|
||||
For,
|
||||
From,
|
||||
Global,
|
||||
If,
|
||||
Import,
|
||||
In,
|
||||
Is,
|
||||
Lambda,
|
||||
Nonlocal,
|
||||
Not,
|
||||
Or,
|
||||
Pass,
|
||||
Raise,
|
||||
Return,
|
||||
Try,
|
||||
While,
|
||||
With,
|
||||
Yield,
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
|
||||
/*
|
||||
* Implement virtual machine to run instructions.
|
||||
*/
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::cell::RefMut;
|
||||
use std::ops::Deref;
|
||||
|
||||
use super::bytecode;
|
||||
use super::builtins;
|
||||
use super::pyobject::{PyObject, PyObjectRef};
|
||||
|
||||
// use objects::objects;
|
||||
|
||||
// Container of the virtual machine state:
|
||||
pub fn evaluate(code: bytecode::CodeObject) {
|
||||
let mut vm = VirtualMachine::new();
|
||||
|
||||
// Register built in function:
|
||||
vm.scope.insert(String::from("print"), PyObject::RustFunction { function: builtins::print }.into_ref());
|
||||
|
||||
// { stack: Vec::new() };
|
||||
vm.run(code);
|
||||
}
|
||||
|
||||
// Objects are live when they are on stack, or referenced by a name (for now)
|
||||
|
||||
struct VirtualMachine {
|
||||
call_stack: Vec<bytecode::CodeObject>,
|
||||
stack: Vec<PyObjectRef>,
|
||||
// A stack of block to keep track of continue break locations.
|
||||
block_stack: Vec<(bytecode::Label, bytecode::Label)>,
|
||||
scope: HashMap<String, PyObjectRef>,
|
||||
program_counter: usize,
|
||||
}
|
||||
|
||||
impl VirtualMachine {
|
||||
fn new() -> VirtualMachine {
|
||||
VirtualMachine {
|
||||
call_stack: Vec::new(),
|
||||
stack: Vec::new(),
|
||||
block_stack: Vec::new(),
|
||||
scope: HashMap::new(),
|
||||
program_counter: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn run(&mut self, code: bytecode::CodeObject) {
|
||||
// Process instruction at the program counter until exception or finished.
|
||||
let num_instructions = code.instructions.len();
|
||||
// self.call_stack.push(code);
|
||||
|
||||
// let current_frame = self.call_stack.last().unwrap();
|
||||
let current_frame = code;
|
||||
|
||||
loop {
|
||||
// for instruction in code.instructions {
|
||||
if self.program_counter > current_frame.instructions.len() {
|
||||
break;
|
||||
}
|
||||
|
||||
let ref instruction = current_frame.instructions[self.program_counter];
|
||||
trace!("Executing instruction: {:?} (stacksize={:?}, pc={:?}/{:?}", instruction, self.stack.len(), self.program_counter, num_instructions);
|
||||
self.program_counter += 1;
|
||||
self.execute_instruction(&instruction);
|
||||
}
|
||||
|
||||
// TODO: Pop call stack?
|
||||
}
|
||||
|
||||
// Execute a single instruction:
|
||||
fn execute_instruction(&mut self, instruction: &bytecode::Instruction) {
|
||||
// trace!("Executing instruction: {:?} (stacksize={:?}", instruction, self.stack.len());
|
||||
match instruction {
|
||||
&bytecode::Instruction::LoadConst { ref value } => {
|
||||
let obj = match value {
|
||||
&bytecode::Constant::Integer { ref value } => { PyObject::Integer { value: *value } },
|
||||
// &bytecode::Constant::Float
|
||||
&bytecode::Constant::String { ref value } => { PyObject::String { value: value.clone() } },
|
||||
};
|
||||
self.stack.push(obj.into_ref().clone());
|
||||
},
|
||||
&bytecode::Instruction::LoadName { ref name } => {
|
||||
// Lookup name in scope and put it onto the stack!
|
||||
let obj = &self.scope[name];
|
||||
self.stack.push(obj.clone());
|
||||
},
|
||||
&bytecode::Instruction::StoreName { ref name } => {
|
||||
// take top of stack and assign in scope:
|
||||
let obj = self.stack.pop().unwrap();
|
||||
self.scope.insert(name.clone(), obj);
|
||||
},
|
||||
&bytecode::Instruction::Pop => {
|
||||
// Pop value from stack and ignore.
|
||||
self.stack.pop();
|
||||
},
|
||||
&bytecode::Instruction::BuildList { size } => {
|
||||
let elements = self.pop_multiple(size);
|
||||
let list_obj = PyObject::List { elements: elements }.into_ref();
|
||||
self.stack.push(list_obj);
|
||||
},
|
||||
&bytecode::Instruction::BuildTuple { size } => {
|
||||
let elements = self.pop_multiple(size);
|
||||
let list_obj = PyObject::Tuple { elements: elements }.into_ref();
|
||||
self.stack.push(list_obj);
|
||||
},
|
||||
&bytecode::Instruction::BuildMap { size } => {
|
||||
let mut elements = Vec::new();
|
||||
for _x in 0..size {
|
||||
let key = self.stack.pop().unwrap();
|
||||
let obj = self.stack.pop().unwrap();
|
||||
elements.push((key,obj));
|
||||
}
|
||||
panic!("To be implemented!")
|
||||
//let list_obj = PyObject::Tuple { elements: elements }.into_ref();
|
||||
//self.stack.push(list_obj);
|
||||
},
|
||||
&bytecode::Instruction::BinaryOperation { ref op } => {
|
||||
self.execute_binop(op);
|
||||
},
|
||||
&bytecode::Instruction::UnaryOperation { ref op } => {
|
||||
panic!("TODO");
|
||||
// self.execute_binop(op);
|
||||
},
|
||||
&bytecode::Instruction::ReturnValue => {
|
||||
self.stack.pop();
|
||||
},
|
||||
&bytecode::Instruction::PushBlock { start, end } => {
|
||||
self.block_stack.push((start, end));
|
||||
},
|
||||
&bytecode::Instruction::PopBlock => {
|
||||
self.block_stack.pop();
|
||||
}
|
||||
&bytecode::Instruction::GetIter => {
|
||||
let iterated_obj = self.stack.pop().unwrap();
|
||||
let iter_obj = PyObject::Iterator {
|
||||
position: 0, iterated_obj: iterated_obj
|
||||
}.into_ref();
|
||||
self.stack.push(iter_obj);
|
||||
},
|
||||
&bytecode::Instruction::ForIter => {
|
||||
// The top of stack contains the iterator, lets push it forward:
|
||||
let next_obj: Option<PyObjectRef> = {
|
||||
let top_of_stack = self.stack.last().unwrap();
|
||||
let mut ref_mut: RefMut<PyObject> = top_of_stack.deref().borrow_mut();
|
||||
// We require a mutable pyobject here to update the iterator:
|
||||
let mut iterator = ref_mut; // &mut PyObject = ref_mut.;
|
||||
// let () = iterator;
|
||||
iterator.nxt()
|
||||
};
|
||||
|
||||
// Check the next object:
|
||||
match next_obj {
|
||||
Some(v) => {
|
||||
self.stack.push(v);
|
||||
},
|
||||
None => {
|
||||
// End of for loop
|
||||
let end_label = self.block_stack.last().unwrap().1;
|
||||
self.jump(end_label);
|
||||
}
|
||||
}
|
||||
},
|
||||
&bytecode::Instruction::CallFunction { count } => {
|
||||
let mut args: Vec<PyObjectRef> = self.pop_multiple(count);
|
||||
let func_ref = self.stack.pop().unwrap();
|
||||
let f=func_ref.borrow();// = &*func_ref.borrow();
|
||||
f.call(args);
|
||||
// call_stack.push();
|
||||
// If a builtin function, then call directly, otherwise, execute it?
|
||||
// execute(function.code);
|
||||
},
|
||||
&bytecode::Instruction::Jump { target } => {
|
||||
self.jump(target);
|
||||
}
|
||||
&bytecode::Instruction::JumpIf { target } => {
|
||||
let obj = self.stack.pop().unwrap();
|
||||
// TODO: determine if this value is True-ish:
|
||||
let result: bool = true;
|
||||
if result {
|
||||
self.jump(target);
|
||||
}
|
||||
}
|
||||
&bytecode::Instruction::Break => {
|
||||
let end_label = self.block_stack.last().unwrap().1;
|
||||
self.jump(end_label);
|
||||
},
|
||||
&bytecode::Instruction::Pass => {
|
||||
// Ah, this is nice, just relax!
|
||||
},
|
||||
&bytecode::Instruction::Continue => {
|
||||
let start_label = self.block_stack.last().unwrap().0;
|
||||
self.jump(start_label);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn pop_multiple(&mut self, count: usize) -> Vec<PyObjectRef> {
|
||||
let mut objs: Vec<PyObjectRef> = Vec::new();
|
||||
for _x in 0..count {
|
||||
objs.push(self.stack.pop().unwrap());
|
||||
}
|
||||
objs.reverse();
|
||||
objs
|
||||
}
|
||||
|
||||
fn jump(&mut self, label: bytecode::Label) {
|
||||
// let current_frame = self.call_stack.last().unwrap();
|
||||
// self.program_counter = current_frame.label_map[&label];
|
||||
}
|
||||
|
||||
fn execute_binop(&mut self, op: &bytecode::BinaryOperator) {
|
||||
let b_ref = self.stack.pop().unwrap();
|
||||
let a_ref = self.stack.pop().unwrap();
|
||||
let b = &*b_ref.borrow();
|
||||
let a = &*a_ref.borrow();
|
||||
let result = match op {
|
||||
&bytecode::BinaryOperator::Subtract => a - b,
|
||||
&bytecode::BinaryOperator::Add => a + b,
|
||||
&bytecode::BinaryOperator::Multiply => a * b,
|
||||
// &bytecode::BinaryOperator::Div => a / b,
|
||||
_ => panic!("NOT IMPL"),
|
||||
};
|
||||
self.stack.push(result.into_ref());
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
|
||||
extern crate clap;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate env_logger;
|
||||
use clap::{Arg, App};
|
||||
use std::path::Path;
|
||||
mod compiler;
|
||||
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
let matches = App::new("RsPython")
|
||||
.version("0.0.1")
|
||||
.author("Windel Bouwman")
|
||||
.about("Rust implementation of the Python language")
|
||||
.arg(Arg::with_name("script")
|
||||
.required(true)
|
||||
.index(1))
|
||||
.arg(Arg::with_name("v")
|
||||
.short("v")
|
||||
.multiple(true)
|
||||
.help("Give the verbosity"))
|
||||
.get_matches();
|
||||
|
||||
// Figure out the filename:
|
||||
let script_file = matches.value_of("script").unwrap_or("foo");
|
||||
info!("Running file {}", script_file);
|
||||
|
||||
// Parse an ast from it:
|
||||
let filepath = Path::new(script_file);
|
||||
match compiler::parse(filepath) {
|
||||
Ok(program) => {
|
||||
debug!("Got ast: {:?}", program);
|
||||
let bytecode = compiler::compile(program);
|
||||
debug!("Code object: {:?}", bytecode);
|
||||
compiler::evaluate(bytecode);
|
||||
info!("Great succes!!");
|
||||
},
|
||||
Err(msg) => error!("Parsing went horribly wrong: {}", msg),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user