Merge pull request #245 from coolreader18/final-demo-improvements

Final demo improvements
This commit is contained in:
Windel Bouwman
2018-12-29 15:28:26 +01:00
committed by GitHub
34 changed files with 917 additions and 470 deletions

1
.gitignore vendored
View File

@@ -1,5 +1,4 @@
/target
wasm/target
**/*.rs.bk
**/*.bytecode
__pycache__

View File

@@ -1,4 +1,3 @@
language: rust
rust:
@@ -7,85 +6,87 @@ rust:
- nightly
script:
- cargo build --verbose --all
- cargo test --verbose --all
- cargo build --verbose --all
- cargo test --verbose --all
env:
# This is used to only capture the regular nightly test in allow_failures
- REGULAR_TEST=true
# This is used to only capture the regular nightly test in allow_failures
- REGULAR_TEST=true
cache: cargo
matrix:
include:
# To test the snippets, we use Travis' Python environment (because
# installing rust ourselves is a lot easier than installing Python)
- language: python
python: 3.6
cache:
pip: true
# Because we're using the Python Travis environment, we can't use
# the built-in cargo cacher
directories:
- /home/travis/.cargo
- target
env:
- TRAVIS_RUST_VERSION=stable
- REGULAR_TEST=false
script: tests/.travis-runner.sh
- language: python
python: 3.6
cache:
pip: true
# Because we're using the Python Travis environment, we can't use
# the built-in cargo cacher
directories:
- /home/travis/.cargo
- target
env:
- TRAVIS_RUST_VERSION=beta
- REGULAR_TEST=false
script: tests/.travis-runner.sh
- name: rustfmt
language: rust
rust: stable
cache: cargo
before_script:
- rustup component add rustfmt-preview
script:
# Code references the generated python.rs, so put something in
# place to make `cargo fmt` happy. (We use `echo` rather than
# `touch` because rustfmt complains about the empty file touch
# creates.)
- echo > parser/src/python.rs
- cargo fmt --all -- --check
env:
- REGULAR_TEST=false
- name: publish documentation
language: rust
rust: stable
cache: cargo
script:
- cargo doc --no-deps --all
if: branch = release
env:
- REGULAR_TEST=false
- name: WASM online demo
language: rust
rust: nightly
cache: cargo
install:
- nvm install node
- curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh # install wasm-pack
script:
- cd wasm
- bash release.sh
if: branch = release
env:
- REGULAR_TEST=false
allow_failures:
- rust: nightly
env: REGULAR_TEST=true
include:
# To test the snippets, we use Travis' Python environment (because
# installing rust ourselves is a lot easier than installing Python)
- language: python
python: 3.6
cache:
pip: true
# Because we're using the Python Travis environment, we can't use
# the built-in cargo cacher
directories:
- /home/travis/.cargo
- target
env:
- TRAVIS_RUST_VERSION=stable
- REGULAR_TEST=false
script: tests/.travis-runner.sh
- language: python
python: 3.6
cache:
pip: true
# Because we're using the Python Travis environment, we can't use
# the built-in cargo cacher
directories:
- /home/travis/.cargo
- target
env:
- TRAVIS_RUST_VERSION=beta
- REGULAR_TEST=false
script: tests/.travis-runner.sh
- name: rustfmt
language: rust
rust: stable
cache: cargo
before_script:
- rustup component add rustfmt-preview
script:
# Code references the generated python.rs, so put something in
# place to make `cargo fmt` happy. (We use `echo` rather than
# `touch` because rustfmt complains about the empty file touch
# creates.)
- echo > parser/src/python.rs
- cargo fmt --all -- --check
env:
- REGULAR_TEST=false
- name: publish documentation
language: rust
rust: stable
cache: cargo
script:
- cargo doc --no-deps --all
if: branch = release
env:
- REGULAR_TEST=false
- name: WASM online demo
language: rust
rust: nightly
cache: cargo
install:
- nvm install node
# install wasm-pack
- curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
script:
- cd wasm/demo
- npm install
- npm run dist
if: branch = release
env:
- REGULAR_TEST=false
allow_failures:
- rust: nightly
env: REGULAR_TEST=true
deploy:
- provider: pages
@@ -93,16 +94,18 @@ deploy:
target-branch: master
local-dir: target/doc
skip-cleanup: true
github-token: $WEBSITE_GITHUB_TOKEN # Set in the settings page of your repository, as a secure variable
# Set in the settings page of your repository, as a secure variable
github-token: $WEBSITE_GITHUB_TOKEN
keep-history: true
on:
branch: release
- provider: pages
repo: RustPython/demo
target-branch: master
local-dir: wasm/app/dist
local-dir: wasm/demo/dist
skip-cleanup: true
github-token: $WEBSITE_GITHUB_TOKEN # Set in the settings page of your repository, as a secure variable
# Set in the settings page of your repository, as a secure variable
github-token: $WEBSITE_GITHUB_TOKEN
keep-history: true
on:
branch: release

207
Cargo.lock generated
View File

@@ -136,7 +136,7 @@ name = "caseless"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -230,10 +230,22 @@ 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.2 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "env_logger"
version = "0.6.0"
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.2 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "failure"
version = "0.1.2"
@@ -286,6 +298,14 @@ dependencies = [
"typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "heck"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "humantime"
version = "1.1.1"
@@ -307,6 +327,14 @@ name = "itoa"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "js-sys"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"wasm-bindgen 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
@@ -426,6 +454,14 @@ name = "nodrop"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "nom"
version = "4.1.1"
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 = "num-bigint"
version = "0.2.1"
@@ -596,19 +632,19 @@ 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)",
"thread_local 0.3.6 (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"
version = "1.0.3"
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)",
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -674,7 +710,7 @@ dependencies = [
"num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rustpython_parser 0.0.1",
"serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -682,6 +718,18 @@ dependencies = [
"statrs 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustpython_wasm"
version = "0.1.0"
dependencies = [
"cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"js-sys 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rustpython_parser 0.0.1",
"rustpython_vm 0.1.0",
"wasm-bindgen 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"web-sys 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustyline"
version = "2.1.0"
@@ -749,6 +797,11 @@ name = "siphasher"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "sourcefile"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "statrs"
version = "0.10.0"
@@ -808,6 +861,16 @@ dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "0.15.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.20 (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 = "synstructure"
version = "0.9.0"
@@ -836,6 +899,14 @@ dependencies = [
"wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "termcolor"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "termion"
version = "1.5.1"
@@ -856,11 +927,10 @@ dependencies = [
[[package]]
name = "thread_local"
version = "0.3.5"
version = "0.3.6"
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]]
@@ -921,6 +991,89 @@ name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "wasm-bindgen"
version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"wasm-bindgen-macro 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.29"
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)",
"log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen-shared 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen-macro-support 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen-backend 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen-shared 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "wasm-bindgen-webidl"
version = "0.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen-backend 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"weedle 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "web-sys"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"js-sys 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen-webidl 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "weedle"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nom 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.8"
@@ -945,6 +1098,14 @@ name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-util"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
@@ -958,6 +1119,15 @@ dependencies = [
"winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wincolor"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-util 0.1.1 (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"
@@ -989,6 +1159,7 @@ dependencies = [
"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 env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e"
"checksum failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7efb22686e4a466b1ec1a15c2898f91fa9cb340452496dca654032de20ff95b9"
"checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426"
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
@@ -996,9 +1167,11 @@ dependencies = [
"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 heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82"
"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 itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5adb58558dcd1d786b5f0bd15f3226ee23486e24b7b58304b60f64dc68e62606"
"checksum js-sys 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58cfec35fd4a94f3cf357d5cb7da71c71cd52720c2f2a7320090a8db5f06f655"
"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"
@@ -1011,6 +1184,7 @@ dependencies = [
"checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
"checksum nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37e713a259ff641624b6cb20e3b12b2952313ba36b6823c0f16e6cfd9e5de17"
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
"checksum nom 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9c349f68f25f596b9f44cf0e7c69752a5c633b0550c3ff849518bfba0233774a"
"checksum num-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "10b8423ea72ec64751198856a853e07b37087cfc9b53a87ecb19bff67b6d1320"
"checksum num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "107b9be86cd2481930688277b675b0114578227f034674726605b8a482d8baf8"
"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
@@ -1033,7 +1207,7 @@ dependencies = [
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum redox_users 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "214a97e49be64fd2c86f568dd0cb2c757d2cc53de95b273b6ad0a1c908482f26"
"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 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d8c9f33201f46669484bacc312b00e7541bed6aaf296dffe2bb4e0ac6b8ce2a"
"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"
@@ -1046,6 +1220,7 @@ dependencies = [
"checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae"
"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 sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3"
"checksum statrs 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "10102ac8d55e35db2b3fafc26f81ba8647da2e15879ab686a67e6d19af2685e8"
"checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423"
"checksum string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35293b05cf1494e8ddd042a7df6756bf18d07f42d234f32e71dce8a7aabb0191"
@@ -1053,12 +1228,14 @@ dependencies = [
"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.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
"checksum syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9545a6a093a3f0bd59adb472700acc08cad3776f860f16a897dfce8c88721cbc"
"checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7"
"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 termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
"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 thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"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-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25"
@@ -1070,9 +1247,19 @@ dependencies = [
"checksum utf8parse 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8772a4ccbb4e89959023bc5b7cb8623a795caa7092d99f3aa9501b9484d4557d"
"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 wasm-bindgen 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "91f95b8f30407b9ca0c2de157281d3828bbed1fc1f55bea6eb54f40c52ec75ec"
"checksum wasm-bindgen-backend 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "ab7c242ebcb45bae45340986c48d1853eb2c1c52ff551f7724951b62a2c51429"
"checksum wasm-bindgen-macro 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "6e353f83716dec9a3597b5719ef88cb6c9e461ec16528f38aa023d3224b4e569"
"checksum wasm-bindgen-macro-support 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "3cc90b65fe69c3dd5a09684517dc79f42b847baa2d479c234d125e0a629d9b0a"
"checksum wasm-bindgen-shared 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "a71a37df4f5845025f96f279d20bbe5b19cbcb77f5410a3a90c6c544d889a162"
"checksum wasm-bindgen-webidl 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "b064b8b2336b5a6bf5f31bc95fc1310842395df29877d910cb6f8f791070f319"
"checksum web-sys 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d7c588c2e5a091bc4532c5a87032955f9133b644e868b54d08ead0185dcc5b9"
"checksum weedle 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "26a4c67f132386d965390b8a734d5d10adbcd30eb5cc74bd9229af8b83f10044"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd"
"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-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab"
"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"
"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba"

View File

@@ -4,6 +4,7 @@ version = "0.0.1"
authors = ["Windel Bouwman", "Shing Lyu <shing.lyu@gmail.com>"]
[workspace]
members = [".", "vm", "wasm/lib", "parser"]
[dependencies]
log="0.4.1"
@@ -12,3 +13,6 @@ clap = "2.31.2"
rustpython_parser = {path = "parser"}
rustpython_vm = {path = "vm"}
rustyline = "2.1.0"
[profile.release]
opt-level = "s"

View File

@@ -1,5 +1,6 @@
# RustPython
A Python-3 (CPython >= 3.5.0) Interpreter written in Rust :snake: :scream: :metal:.
A Python-3 (CPython >= 3.5.0) Interpreter written in Rust :snake: :scream: :metal:.
[![Build Status](https://travis-ci.org/RustPython/RustPython.svg?branch=master)](https://travis-ci.org/RustPython/RustPython)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
@@ -24,7 +25,6 @@ Or use the interactive shell:
>>>>> 2+2
4
# Goals
- Full Python-3 environment entirely in Rust (not CPython bindings)
@@ -51,13 +51,13 @@ If you wish to update the online documentation. Push directly to the `release` b
- `parser/src`: python lexing, parsing and ast
- `vm/src`: python virtual machine
- `builtins.rs`: Builtin functions
- `compile.rs`: the python compiler from ast to bytecode
- `obj`: python builtin types
- `builtins.rs`: Builtin functions
- `compile.rs`: the python compiler from ast to bytecode
- `obj`: python builtin types
- `src`: using the other subcrates to bring rustpython to life.
- `docs`: documentation (work in progress)
- `py_code_object`: CPython bytecode to rustpython bytecode convertor (work in progress)
- `wasm`: Binary crate and resources for WebAssembly build
- `wasm`: Binary crate and resources for WebAssembly build
- `tests`: integration test snippets
# Contributing
@@ -68,7 +68,7 @@ Most tasks are listed in the [issue tracker](https://github.com/RustPython/RustP
Check issues labeled with `good first issue` if you wish to start coding.
Another approach is to checkout the sourcecode: builtin functions and object methods are often the simplest
and easiest way to contribute.
and easiest way to contribute.
You can also simply run
`cargo run tests/snippets/whats_left_to_implement.py` to assist in finding any
@@ -135,44 +135,51 @@ cd emsdk-portable/
## Build
Move into the `wasm` directory. This contains a custom library crate optimized for wasm build of RustPython.
Move into the `wasm` directory. This directory contains a library crate for interop
with python to rust to js and back in `wasm/lib`, the demo website found at
https://rustpython.github.io/demo in `wasm/demo`, and an example of how to use
the crate as a library in one's own JS app in `wasm/example`.
```bash
```sh
cd wasm
```
For testing on a development server, you can run the `build.sh` script. For release build which generates files for deploying to a HTTP server, run `release.sh`.
Go to the demo directory. This is the best way of seeing the changes made to either
the library or the JS demo, as the `rustpython_wasm` module is set to the global
JS variable `rp` on the website.
If you don't want to use the above scripts, you can do it manually as follows:
Run the build. This can take several minutes depending on the machine.
```
wasm-pack build
```sh
cd demo
```
Upon successful build, cd in the the `/pkg` directory and run:
Now, start the webpack development server. It'll compile the crate and then
the demo app. This will likely take a long time, both the wasm-pack portion and
the webpack portion (from after it says "Your crate has been correctly compiled"),
so be patient.
```
npm link
```sh
npm run dev
```
Now move back out into the `/app` directory. The files here have been adapted from [wasm-pack-template](https://github.com/rustwasm/wasm-pack-template).
You can now open the webpage on https://localhost:8080 and Python code in either
the text box or browser devtools with:
Finally, run:
```
npm install
npm link rustpython_wasm
```js
rp.pyEval(
`
print(js_vars['a'] * 9)
`,
{
vars: {
a: 9
}
}
);
```
and you will be able to run the files with:
```
node_modules/.bin/webpack-dev-server
```
Now open the webpage on https://localhost:8080, you'll be able to run Python code in the text box.
Alternatively, you can run `npm run build` to build the app once, without watching
for changes, or `npm run dist` to build the app in release mode, both for the
crate and webpack.
# Code style
@@ -195,4 +202,3 @@ These are some useful links to related projects:
- https://github.com/ProgVal/pythonvm-rust
- https://github.com/shinglyu/RustPython
- https://github.com/windelbouwman/rspython

3
wasm/.gitignore vendored
View File

@@ -1,2 +1,5 @@
bin/
pkg/
dist/
node_modules/

2
wasm/app/.gitignore vendored
View File

@@ -1,2 +0,0 @@
dist/
node_modules/

View File

@@ -1,6 +0,0 @@
// A dependency graph that contains any wasm must all be imported
// asynchronously. This `bootstrap.js` file does the single async import, so
// that no one else needs to worry about it again.
import('./index.js').catch(e =>
console.error('Error importing `index.js`:', e)
);

View File

@@ -1,89 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>RustPython Demo</title>
<style type="text/css" media="screen">
textarea {
font-family: monospace;
resize: vertical;
}
#code {
height: 35vh;
width: 95vw;
}
#console {
height: 35vh;
width: 95vw;
}
#run-btn {
width: 6em;
height: 2em;
font-size: 24px;
}
#error {
color: tomato;
margin-top: 10px;
font-family: monospace;
}
</style>
</head>
<body>
<h1>RustPython Demo</h1>
<p>
RustPython is a Python interpreter writter in Rust. This demo is
compiled from Rust to WebAssembly so it runs in the browser
</p>
<p>Please input your python code below and click <kbd>Run</kbd>:</p>
<p>
Alternatively, open up your browser's devtools and play with
<code>rp.eval_py('print("a")')</code>
</p>
<textarea id="code">
n1 = 0
n2 = 1
count = 0
until = 10
print("These are the first " + str(until) + " number in a Fibonacci sequence:")
while count < until:
print(n1)
n1, n2 = n2, n1 + n2
count += 1
</textarea>
<button id="run-btn">Run &#9655;</button>
<div id="error"></div>
<script src="./bootstrap.js"></script>
<h3>Standard Output</h3>
<textarea id="console">Loading...</textarea>
<p>Here's some info regarding the <code>rp.eval_py()</code> function</p>
<ul>
<li>
You can return variables from python and get them returned to
JS, with the only requirement being that they're serializable
with <code>json.dumps</code>.
</li>
<li>
You can pass an object as the second argument to the function,
and that will be available in python as the variable
<code>js_vars</code>. Again, only values that can be serialized
with <code>JSON.stringify()</code> will go through.
</li>
</ul>
<!-- "Fork me on GitHub" banner -->
<a href="https://github.com/RustPython/RustPython"
><img
style="position: absolute; top: 0; right: 0; border: 0;"
src="https://s3.amazonaws.com/github/ribbons/forkme_right_green_007200.png"
alt="Fork me on GitHub"
/></a>
</body>
</html>

View File

@@ -1,27 +0,0 @@
import * as rp from 'rustpython_wasm';
// so people can play around with it
window.rp = rp;
function runCodeFromTextarea(_) {
const consoleElement = document.getElementById('console');
const errorElement = document.getElementById('error');
// Clean the console and errors
consoleElement.value = '';
errorElement.textContent = '';
const code = document.getElementById('code').value;
try {
rp.run_from_textbox(code);
} catch (e) {
errorElement.textContent = e;
console.error(e);
}
}
document
.getElementById('run-btn')
.addEventListener('click', runCodeFromTextarea);
runCodeFromTextarea(); // Run once for demo

View File

@@ -1,27 +0,0 @@
{
"name": "app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"hello-wasm-pack": "^0.1.0",
"webpack": "^4.16.3",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5",
"copy-webpack-plugin": "^4.5.2"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/RustPython/RustPython.git"
},
"author": "Ryan Liddle",
"license": "MIT",
"bugs": {
"url": "https://github.com/RustPython/RustPython/issues"
},
"homepage": "https://github.com/RustPython/RustPython#readme"
}

View File

@@ -1,14 +0,0 @@
const CopyWebpackPlugin = require("copy-webpack-plugin");
const path = require('path');
module.exports = {
entry: "./bootstrap.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bootstrap.js",
},
mode: "development",
plugins: [
new CopyWebpackPlugin(['index.html'])
],
};

View File

@@ -1,7 +0,0 @@
wasm-pack build --debug && \
cd pkg && \
npm link && \
cd ../app && \
npm install && \
npm link rustpython_wasm && \
node_modules/.bin/webpack-dev-server

34
wasm/demo/package.json Normal file
View File

@@ -0,0 +1,34 @@
{
"name": "app",
"version": "1.0.0",
"description": "Bindings to the RustPython library for WebAssembly",
"main": "index.js",
"dependencies": {
"codemirror": "^5.42.0"
},
"devDependencies": {
"@wasm-tool/wasm-pack-plugin": "0.2.0",
"webpack": "^4.16.3",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5",
"copy-webpack-plugin": "^4.5.2",
"mini-css-extract-plugin": "^0.5.0",
"html-webpack-plugin": "^3.2.0",
"css-loader": "^2.0.1"
},
"scripts": {
"dev": "webpack-dev-server -d",
"build": "webpack",
"dist": "webpack --mode production"
},
"repository": {
"type": "git",
"url": "git+https://github.com/RustPython/RustPython.git"
},
"author": "Ryan Liddle",
"license": "MIT",
"bugs": {
"url": "https://github.com/RustPython/RustPython/issues"
},
"homepage": "https://github.com/RustPython/RustPython#readme"
}

75
wasm/demo/src/index.html Normal file
View File

@@ -0,0 +1,75 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>RustPython Demo</title>
</head>
<body>
<h1>RustPython Demo</h1>
<p>
RustPython is a Python interpreter writter in Rust. This demo is
compiled from Rust to WebAssembly so it runs in the browser. <br />
Please input your python code below and click <kbd>Run</kbd>, or you
can open up your browser's devtools and play with
<code>rp.pyEval('print("a")')</code>
</p>
<textarea id="code">
n1 = 0
n2 = 1
count = 0
until = 10
print("These are the first {} numbers in a Fibonacci sequence:".format(until))
while count < until:
print(n1)
n1, n2 = n2, n1 + n2
count += 1
</textarea
>
<button id="run-btn">Run &#9655;</button>
<div id="error"></div>
<h3>Standard Output</h3>
<textarea id="console" readonly>Loading...</textarea>
<p>Here's some info regarding the <code>rp.pyEval()</code> function</p>
<ul>
<li>
You can return variables from python and get them returned to
JS, with the only requirement being that they're serializable
with <code>json.dumps</code>.
</li>
<li>
You can pass an options object as the second argument to the
function:
<ul>
<li>
<code>stdout</code>: either a string with a css selector
to a textarea element or a function that recieves a
string when the <code>print</code> function is called in
python. The default value is <code>console.log</code>.
</li>
<li>
<code>vars</code>: an object that will be available in
python as the variable <code>js_vars</code>. Only
functions and values that can be serialized with
<code>JSON.stringify()</code> will go through.
</li>
</ul>
</li>
<li>
JS functions that get passed to python will recieve positional
args as positional args and kwargs as the
<code>this</code> argument
</li>
</ul>
<a href="https://github.com/RustPython/RustPython">
<img
style="position: absolute; top: 0; right: 0; border: 0;"
src="https://s3.amazonaws.com/github/ribbons/forkme_right_green_007200.png"
alt="Fork me on GitHub"
/>
</a>
</body>
</html>

10
wasm/demo/src/index.js Normal file
View File

@@ -0,0 +1,10 @@
import './style.css';
import 'codemirror/lib/codemirror.css';
// A dependency graph that contains any wasm must all be imported
// asynchronously. This `index.js` file does the single async import, so
// that no one else needs to worry about it again.
import('./main.js').catch(e => {
console.error('Error importing `main.js`:', e);
document.getElementById('error').textContent = e;
});

49
wasm/demo/src/main.js Normal file
View File

@@ -0,0 +1,49 @@
import * as rp from '../../lib/pkg';
import CodeMirror from 'codemirror';
import 'codemirror/mode/python/python';
import 'codemirror/addon/comment/comment';
// so people can play around with it
window.rp = rp;
const editor = CodeMirror.fromTextArea(document.getElementById('code'), {
extraKeys: {
'Ctrl-Enter': runCodeFromTextarea,
'Cmd-Enter': runCodeFromTextarea,
'Shift-Tab': 'indentLess',
'Ctrl-/': 'toggleComment',
'Cmd-/': 'toggleComment'
},
lineNumbers: true,
mode: 'text/x-python',
indentUnit: 4,
autofocus: true
});
function runCodeFromTextarea() {
const consoleElement = document.getElementById('console');
const errorElement = document.getElementById('error');
// Clean the console and errors
consoleElement.value = '';
errorElement.textContent = '';
const code = editor.getValue();
try {
const result = rp.pyEval(code, {
stdout: '#console'
});
if (result !== null) {
consoleElement.value += `\n${result}\n`;
}
} catch (e) {
errorElement.textContent = e;
console.error(e);
}
}
document
.getElementById('run-btn')
.addEventListener('click', runCodeFromTextarea);
runCodeFromTextarea(); // Run once for demo

27
wasm/demo/src/style.css Normal file
View File

@@ -0,0 +1,27 @@
textarea {
font-family: monospace;
resize: none;
}
#code,
#console {
height: 30vh;
width: calc(100% - 3px);
}
.CodeMirror {
border: 1px solid #ddd;
height: 30vh !important;
}
#run-btn {
width: 6em;
height: 2em;
font-size: 24px;
}
#error {
color: tomato;
margin-top: 10px;
font-family: monospace;
}

View File

@@ -0,0 +1,30 @@
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const WasmPackPlugin = require('@wasm-tool/wasm-pack-plugin');
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.join(__dirname, 'dist'),
filename: 'index.js'
},
mode: 'development',
module: {
rules: [
{ test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'] }
]
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'src/index.html'
}),
new MiniCssExtractPlugin({
filename: 'styles.css'
}),
new WasmPackPlugin({
crateDirectory: path.join(__dirname, '../lib')
})
]
};

12
wasm/example/index.html Normal file
View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>RustPython Basic Example</title>
</head>
<body>
<script src="./dist/app.js"></script>
</body>
</html>

18
wasm/example/package.json Normal file
View File

@@ -0,0 +1,18 @@
{
"name": "rustpython-wasm-example",
"version": "1.0.0",
"//1": "`dependencies.rustpython_wasm` would be the version of the npm",
"//2": "library in a real app",
"dependencies": {
"rustpython_wasm": "file:../lib/pkg/"
},
"devDependencies": {
"raw-loader": "1.0.0",
"webpack": "4.28.2",
"webpack-cli": "^3.1.2"
},
"scripts": {
"build": "webpack"
},
"license": "MIT"
}

View File

@@ -0,0 +1,6 @@
// A dependency graph that contains any wasm must all be imported
// asynchronously. This `index.js` file does the single async import, so
// that no one else needs to worry about it again.
import('./main.js').catch(e => {
console.error('Error importing `main.js`:', e);
});

11
wasm/example/src/main.js Normal file
View File

@@ -0,0 +1,11 @@
import * as py from 'rustpython_wasm';
import pyCode from 'raw-loader!./main.py';
fetch('https://github-trending-api.now.sh/repositories')
.then(r => r.json())
.then(repos => {
const result = py.pyEval(pyCode, {
vars: { repos }
});
alert(result);
});

8
wasm/example/src/main.py Normal file
View File

@@ -0,0 +1,8 @@
repos = js_vars['repos']
star_sum = 0
for repo in repos:
star_sum += repo['stars']
return 'Average github trending star count: ' + str(star_sum / len(repos))

View File

@@ -0,0 +1,12 @@
const path = require('path');
module.exports = {
entry: './src/index.js',
mode: 'development',
output: {
path: path.join(__dirname, 'dist'),
filename: 'app.js',
publicPath: '/dist/'
},
devtool: 'cheap-module-eval-source-map'
};

View File

@@ -2,16 +2,16 @@
name = "rustpython_wasm"
version = "0.1.0"
authors = ["Ryan Liddle <ryan@rmliddle.com>"]
license = "MIT"
description = "A Python-3 (CPython >= 3.5.0) Interpreter written in Rust, compiled to WASM"
repository = "https://github.com/RustPython/RustPython/tree/master/wasm/lib"
[lib]
crate-type = ["cdylib", "rlib"]
[workspace]
members = []
[dependencies]
rustpython_parser = {path = "../parser"}
rustpython_vm = {path = "../vm"}
rustpython_parser = {path = "../../parser"}
rustpython_vm = {path = "../../vm"}
cfg-if = "0.1.2"
wasm-bindgen = "0.2"
js-sys = "0.3"
@@ -19,7 +19,3 @@ js-sys = "0.3"
[dependencies.web-sys]
version = "0.3"
features = [ "console", "Document", "Element", "HtmlTextAreaElement", "Window" ]
[profile.release]
opt-level = "s"

37
wasm/lib/README.md Normal file
View File

@@ -0,0 +1,37 @@
# RustPython
A Python-3 (CPython >= 3.5.0) Interpreter written in Rust.
[![Build Status](https://travis-ci.org/RustPython/RustPython.svg?branch=master)](https://travis-ci.org/RustPython/RustPython)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
[![Contributors](https://img.shields.io/github/contributors/RustPython/RustPython.svg)](https://github.com/RustPython/RustPython/graphs/contributors)
[![Gitter](https://badges.gitter.im/RustPython/Lobby.svg)](https://gitter.im/rustpython/Lobby)
## Usage
### Check out our [online demo](https://rustpython.github.io/demo/) running on WebAssembly.
## Goals
- Full Python-3 environment entirely in Rust (not CPython bindings)
- A clean implementation without compatibility hacks
## Quick Documentation
```js
pyEval(code, options?);
```
`code`: `string`: The Python code to run
`options`:
- `vars?`: `{ [key: string]: any }`: Variables passed to the VM that can be
accessed in Python with the variable `js_vars`. Functions do work, and
recieve the Python kwargs as the `this` argument.
- `stdout?`: `(out: string) => void`: A function to replace the native print
function, by default `console.log`.
## License
This project is licensed under the MIT license.

236
wasm/lib/src/lib.rs Normal file
View File

@@ -0,0 +1,236 @@
mod wasm_builtins;
extern crate js_sys;
extern crate rustpython_vm;
extern crate wasm_bindgen;
extern crate web_sys;
use js_sys::{Array, Object, Reflect, TypeError};
use rustpython_vm::compile;
use rustpython_vm::pyobject::{self, PyFuncArgs, PyObjectRef, PyResult};
use rustpython_vm::VirtualMachine;
use wasm_bindgen::{prelude::*, JsCast};
// Hack to comment out wasm-bindgen's typescript definitons
#[wasm_bindgen(typescript_custom_section)]
const TS_CMT_START: &'static str = "/*";
fn py_str_err(vm: &mut VirtualMachine, py_err: &PyObjectRef) -> String {
vm.to_pystr(&py_err)
.unwrap_or_else(|_| "Error, and error getting error message".into())
}
fn py_to_js(vm: &mut VirtualMachine, py_obj: PyObjectRef) -> JsValue {
let dumps = rustpython_vm::import::import(
vm,
std::path::PathBuf::default(),
"json",
&Some("dumps".into()),
)
.expect("Couldn't get json.dumps function");
match vm.invoke(dumps, pyobject::PyFuncArgs::new(vec![py_obj], vec![])) {
Ok(value) => {
let json = vm.to_pystr(&value).unwrap();
js_sys::JSON::parse(&json).unwrap_or(JsValue::UNDEFINED)
}
Err(_) => JsValue::UNDEFINED,
}
}
fn js_to_py(vm: &mut VirtualMachine, js_val: JsValue) -> PyObjectRef {
if js_val.is_object() {
if Array::is_array(&js_val) {
let js_arr: Array = js_val.into();
let elems = js_arr
.values()
.into_iter()
.map(|val| js_to_py(vm, val.expect("Iteration over array failed")))
.collect();
vm.ctx.new_list(elems)
} else {
let dict = vm.new_dict();
for pair in Object::entries(&Object::from(js_val)).values() {
let pair = pair.expect("Iteration over object failed");
let key = Reflect::get(&pair, &"0".into()).unwrap();
let val = Reflect::get(&pair, &"1".into()).unwrap();
let py_val = js_to_py(vm, val);
vm.ctx
.set_item(&dict, &String::from(js_sys::JsString::from(key)), py_val);
}
dict
}
} else if js_val.is_function() {
let func = js_sys::Function::from(js_val);
vm.ctx.new_rustfunc(
move |vm: &mut VirtualMachine, args: PyFuncArgs| -> PyResult {
let func = func.clone();
let this = Object::new();
for (k, v) in args.kwargs {
Reflect::set(&this, &k.into(), &py_to_js(vm, v))
.expect("Couldn't set this property");
}
let js_args = Array::new();
for v in args.args {
js_args.push(&py_to_js(vm, v));
}
func.apply(&this, &js_args)
.map(|val| js_to_py(vm, val))
.map_err(|err| js_to_py(vm, err))
},
)
} else if let Some(err) = js_val.dyn_ref::<js_sys::Error>() {
let exc_type = match String::from(err.name()).as_str() {
"TypeError" => &vm.ctx.exceptions.type_error,
"ReferenceError" => &vm.ctx.exceptions.name_error,
"SyntaxError" => &vm.ctx.exceptions.syntax_error,
_ => &vm.ctx.exceptions.exception_type,
}
.clone();
vm.new_exception(exc_type, err.message().into())
} else if js_val.is_undefined() {
// Because `JSON.stringify(undefined)` returns undefined
vm.get_none()
} else {
let loads = rustpython_vm::import::import(
vm,
std::path::PathBuf::default(),
"json",
&Some("loads".into()),
)
.expect("Couldn't get json.loads function");
let json = match js_sys::JSON::stringify(&js_val) {
Ok(json) => String::from(json),
Err(_) => return vm.get_none(),
};
let py_json = vm.new_str(json);
vm.invoke(loads, pyobject::PyFuncArgs::new(vec![py_json], vec![]))
// can safely unwrap because we know it's valid JSON
.unwrap()
}
}
fn base_scope(vm: &mut VirtualMachine) -> PyObjectRef {
let builtins = vm.get_builtin_scope();
vm.context().new_scope(Some(builtins))
}
fn eval(vm: &mut VirtualMachine, source: &str, vars: PyObjectRef) -> PyResult {
// HACK: if the code doesn't end with newline it crashes.
let mut source = source.to_string();
if !source.ends_with('\n') {
source.push('\n');
}
let code_obj = compile::compile(vm, &source, compile::Mode::Exec, None)?;
vm.run_code_obj(code_obj, vars)
}
#[wasm_bindgen(js_name = pyEval)]
/// Evaluate Python code
///
/// ```js
/// pyEval(code, options?);
/// ```
///
/// `code`: `string`: The Python code to run
///
/// `options`:
///
/// - `vars?`: `{ [key: string]: any }`: Variables passed to the VM that can be
/// accessed in Python with the variable `js_vars`. Functions do work, and
/// recieve the Python kwargs as the `this` argument.
/// - `stdout?`: `(out: string) => void`: A function to replace the native print
/// function, by default `console.log`.
pub fn eval_py(source: &str, options: Option<Object>) -> Result<JsValue, JsValue> {
let options = options.unwrap_or_else(|| Object::new());
let js_vars = {
let prop = Reflect::get(&options, &"vars".into())?;
if prop.is_undefined() {
None
} else if prop.is_object() {
Some(Object::from(prop))
} else {
return Err(TypeError::new("vars must be an object").into());
}
};
let stdout = {
let prop = Reflect::get(&options, &"stdout".into())?;
if prop.is_undefined() {
None
} else {
Some(prop)
}
};
let mut vm = VirtualMachine::new();
let print_fn: Box<Fn(&mut VirtualMachine, PyFuncArgs) -> PyResult> = match stdout {
Some(val) => {
if let Some(selector) = val.as_string() {
Box::new(
move |vm: &mut VirtualMachine, args: PyFuncArgs| -> PyResult {
wasm_builtins::builtin_print_html(vm, args, &selector)
},
)
} else if val.is_function() {
let func = js_sys::Function::from(val);
Box::new(
move |vm: &mut VirtualMachine, args: PyFuncArgs| -> PyResult {
func.call1(
&JsValue::UNDEFINED,
&wasm_builtins::format_print_args(vm, args)?.into(),
)
.map_err(|err| js_to_py(vm, err))?;
Ok(vm.get_none())
},
)
} else {
return Err(TypeError::new("stdout must be a function or a css selector").into());
}
}
None => Box::new(wasm_builtins::builtin_print_console),
};
vm.ctx.set_attr(
&vm.builtins,
"print",
vm.ctx.new_rustfunc_from_box(print_fn),
);
let mut vars = base_scope(&mut vm);
let injections = vm.new_dict();
if let Some(js_vars) = js_vars.clone() {
for pair in Object::entries(&js_vars).values() {
let pair = pair?;
let key = Reflect::get(&pair, &"0".into()).unwrap();
let val = Reflect::get(&pair, &"1".into()).unwrap();
let py_val = js_to_py(&mut vm, val);
vm.ctx.set_item(
&injections,
&String::from(js_sys::JsString::from(key)),
py_val,
);
}
}
vm.ctx.set_item(&mut vars, "js_vars", injections);
eval(&mut vm, source, vars)
.map(|value| py_to_js(&mut vm, value))
.map_err(|err| py_str_err(&mut vm, &err).into())
}
#[wasm_bindgen(typescript_custom_section)]
const TYPESCRIPT_DEFS: &'static str = r#"
*/
export interface PyEvalOptions {
stdout: (out: string) => void;
vars: { [key: string]: any };
}
export function pyEval(code: string, options?: PyEvalOptions): any;
"#;

View File

@@ -8,47 +8,53 @@ extern crate js_sys;
extern crate wasm_bindgen;
extern crate web_sys;
use crate::js_to_py;
use js_sys::Array;
use rustpython_vm::obj::objstr;
use rustpython_vm::pyobject::{PyFuncArgs, PyResult};
use rustpython_vm::pyobject::{PyFuncArgs, PyObjectRef, PyResult};
use rustpython_vm::VirtualMachine;
use wasm_bindgen::JsCast;
use wasm_bindgen::{JsCast, JsValue};
use web_sys::{console, window, HtmlTextAreaElement};
// The HTML id of the textarea element that act as our STDOUT
const CONSOLE_ELEMENT_ID: &str = "console";
pub fn print_to_html(text: &str) {
pub fn print_to_html(text: &str, selector: &str) -> Result<(), JsValue> {
let document = window().unwrap().document().unwrap();
let element = document
.get_element_by_id(CONSOLE_ELEMENT_ID)
.expect("Can't find the console textarea");
let textarea = element.dyn_ref::<HtmlTextAreaElement>().unwrap();
.query_selector(selector)?
.ok_or_else(|| js_sys::TypeError::new("Couldn't get element"))?;
let textarea = element
.dyn_ref::<HtmlTextAreaElement>()
.ok_or_else(|| js_sys::TypeError::new("Element must be a textarea"))?;
let value = textarea.value();
textarea.set_value(&format!("{}{}", value, text));
Ok(())
}
pub fn builtin_print_html(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
pub fn format_print_args(vm: &mut VirtualMachine, args: PyFuncArgs) -> Result<String, PyObjectRef> {
let mut output = String::new();
let mut first = true;
for a in args.args {
if first {
first = false;
} else {
print_to_html(&" ")
output.push_str(" ");
}
let v = vm.to_str(&a)?;
let s = objstr::get_value(&v);
print_to_html(&format!("{}\n", s))
output.push_str(&vm.to_pystr(&a)?);
output.push('\n');
}
Ok(output)
}
pub fn builtin_print_html(vm: &mut VirtualMachine, args: PyFuncArgs, selector: &str) -> PyResult {
let output = format_print_args(vm, args)?;
print_to_html(&output, selector).map_err(|err| js_to_py(vm, err))?;
Ok(vm.get_none())
}
pub fn builtin_print_console(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let arr = Array::new();
for a in args.args {
let v = vm.to_str(&a)?;
let s = objstr::get_value(&v);
arr.push(&s.into());
for arg in args.args {
arr.push(&vm.to_pystr(&arg)?.into());
}
console::log(&arr);
Ok(vm.get_none())

1
wasm/lib/target Symbolic link
View File

@@ -0,0 +1 @@
../../target

View File

@@ -1,8 +0,0 @@
wasm-pack build && \
cd pkg && \
npm link && \
cd ../app && \
npm install && \
npm link rustpython_wasm && \
node_modules/.bin/webpack --mode production && \
echo "Output saved to app/dist"

View File

@@ -1,143 +0,0 @@
mod wasm_builtins;
extern crate js_sys;
extern crate rustpython_vm;
extern crate wasm_bindgen;
extern crate web_sys;
use rustpython_vm::compile;
use rustpython_vm::pyobject::{self, PyObjectRef, PyResult};
use rustpython_vm::VirtualMachine;
use wasm_bindgen::prelude::*;
use web_sys::console;
fn py_str_err(vm: &mut VirtualMachine, py_err: &PyObjectRef) -> String {
vm.to_pystr(&py_err)
.unwrap_or_else(|_| "Error, and error getting error message".into())
}
fn py_to_js(vm: &mut VirtualMachine, py_obj: PyObjectRef) -> JsValue {
let dumps = rustpython_vm::import::import(
vm,
std::path::PathBuf::default(),
"json",
&Some("dumps".into()),
)
.expect("Couldn't get json.dumps function");
match vm.invoke(dumps, pyobject::PyFuncArgs::new(vec![py_obj], vec![])) {
Ok(value) => {
let json = vm.to_pystr(&value).unwrap();
js_sys::JSON::parse(&json).unwrap_or(JsValue::UNDEFINED)
}
Err(_) => JsValue::UNDEFINED,
}
}
fn js_to_py(vm: &mut VirtualMachine, js_val: JsValue) -> PyObjectRef {
let json = match js_sys::JSON::stringify(&js_val) {
Ok(json) => String::from(json),
Err(_) => return vm.get_none(),
};
let loads = rustpython_vm::import::import(
vm,
std::path::PathBuf::default(),
"json",
&Some("loads".into()),
)
.expect("Couldn't get json.loads function");
let py_json = vm.new_str(json);
vm.invoke(loads, pyobject::PyFuncArgs::new(vec![py_json], vec![]))
// can safely unwrap because we know it's valid JSON
.unwrap()
}
fn eval<F>(vm: &mut VirtualMachine, source: &str, setup_scope: F) -> PyResult
where
F: Fn(&mut VirtualMachine, &PyObjectRef),
{
// HACK: if the code doesn't end with newline it crashes.
let mut source = source.to_string();
if !source.ends_with('\n') {
source.push('\n');
}
let code_obj = compile::compile(vm, &source, compile::Mode::Exec, None)?;
let builtins = vm.get_builtin_scope();
let mut vars = vm.context().new_scope(Some(builtins));
setup_scope(vm, &mut vars);
vm.run_code_obj(code_obj, vars)
}
#[wasm_bindgen]
pub fn eval_py(source: &str, js_injections: Option<js_sys::Object>) -> Result<JsValue, JsValue> {
if let Some(js_injections) = js_injections.clone() {
if !js_injections.is_object() {
return Err(js_sys::TypeError::new("The second argument must be an object").into());
}
}
let mut vm = VirtualMachine::new();
vm.ctx.set_attr(
&vm.builtins,
"print",
vm.context()
.new_rustfunc(wasm_builtins::builtin_print_console),
);
let res = eval(&mut vm, source, |vm, vars| {
let injections = if let Some(js_injections) = js_injections.clone() {
js_to_py(vm, js_injections.into())
} else {
vm.new_dict()
};
vm.ctx.set_item(vars, "js_vars", injections);
});
res.map(|value| py_to_js(&mut vm, value))
.map_err(|err| py_str_err(&mut vm, &err).into())
}
#[wasm_bindgen]
pub fn run_from_textbox(source: &str) -> Result<JsValue, JsValue> {
//add hash in here
console::log_1(&"Running RustPython".into());
console::log_1(&"Running code:".into());
console::log_1(&source.to_string().into());
let mut vm = VirtualMachine::new();
// We are monkey-patching the builtin print to use console.log
// TODO: monkey-patch sys.stdout instead, after print actually uses sys.stdout
vm.ctx.set_attr(
&vm.builtins,
"print",
vm.context().new_rustfunc(wasm_builtins::builtin_print_html),
);
match eval(&mut vm, source, |_, _| {}) {
Ok(value) => {
console::log_1(&"Execution successful".into());
match value.borrow().kind {
pyobject::PyObjectKind::None => {}
_ => {
if let Ok(text) = vm.to_pystr(&value) {
wasm_builtins::print_to_html(&text);
}
}
}
Ok(JsValue::UNDEFINED)
}
Err(err) => {
console::log_1(&"Execution failed".into());
Err(py_str_err(&mut vm, &err).into())
}
}
}