forked from Rust-related/RustPython
Merge pull request #245 from coolreader18/final-demo-improvements
Final demo improvements
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,5 +1,4 @@
|
||||
/target
|
||||
wasm/target
|
||||
**/*.rs.bk
|
||||
**/*.bytecode
|
||||
__pycache__
|
||||
|
||||
157
.travis.yml
157
.travis.yml
@@ -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
207
Cargo.lock
generated
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
72
README.md
72
README.md
@@ -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:.
|
||||
|
||||
[](https://travis-ci.org/RustPython/RustPython)
|
||||
[](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
3
wasm/.gitignore
vendored
@@ -1,2 +1,5 @@
|
||||
bin/
|
||||
pkg/
|
||||
dist/
|
||||
node_modules/
|
||||
|
||||
|
||||
2
wasm/app/.gitignore
vendored
2
wasm/app/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
dist/
|
||||
node_modules/
|
||||
6
wasm/app/bootstrap.js
vendored
6
wasm/app/bootstrap.js
vendored
@@ -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)
|
||||
);
|
||||
@@ -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 ▷</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>
|
||||
@@ -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
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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'])
|
||||
],
|
||||
};
|
||||
@@ -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
34
wasm/demo/package.json
Normal 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
75
wasm/demo/src/index.html
Normal 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 ▷</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
10
wasm/demo/src/index.js
Normal 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
49
wasm/demo/src/main.js
Normal 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
27
wasm/demo/src/style.css
Normal 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;
|
||||
}
|
||||
30
wasm/demo/webpack.config.js
Normal file
30
wasm/demo/webpack.config.js
Normal 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
12
wasm/example/index.html
Normal 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
18
wasm/example/package.json
Normal 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"
|
||||
}
|
||||
6
wasm/example/src/index.js
Normal file
6
wasm/example/src/index.js
Normal 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
11
wasm/example/src/main.js
Normal 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
8
wasm/example/src/main.py
Normal 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))
|
||||
12
wasm/example/webpack.config.js
Normal file
12
wasm/example/webpack.config.js
Normal 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'
|
||||
};
|
||||
0
wasm/Cargo.lock → wasm/lib/Cargo.lock
generated
0
wasm/Cargo.lock → wasm/lib/Cargo.lock
generated
@@ -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
37
wasm/lib/README.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# RustPython
|
||||
|
||||
A Python-3 (CPython >= 3.5.0) Interpreter written in Rust.
|
||||
|
||||
[](https://travis-ci.org/RustPython/RustPython)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://github.com/RustPython/RustPython/graphs/contributors)
|
||||
[](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
236
wasm/lib/src/lib.rs
Normal 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;
|
||||
"#;
|
||||
@@ -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
1
wasm/lib/target
Symbolic link
@@ -0,0 +1 @@
|
||||
../../target
|
||||
@@ -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"
|
||||
143
wasm/src/lib.rs
143
wasm/src/lib.rs
@@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user