diff --git a/.cargo/config b/.cargo/config index 4beb99d074..55b6b89582 100644 --- a/.cargo/config +++ b/.cargo/config @@ -8,3 +8,9 @@ xtest = "run --package x --bin x -- test" xlint = "run --package x --bin x -- lint" xbuild = "run --package x --bin x -- build" nextest = "run --package x --bin x -- nextest" + +[target.x86_64-pc-windows-msvc] +rustflags = ["-C", "link-arg=/STACK:8000000"] + +[target.x86_64-unknown-linux-gnu] +rustflags = ["-C", "link-arg=-fuse-ld=lld"] diff --git a/.gitattributes b/.gitattributes index 0a529135fd..a3cd55a9d8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -11,6 +11,5 @@ *.txt text *.yml text -# Use Rust syntax highlighter for Move and Move IR code -*.move linguist-language=Rust -*.mvir linguist-language=Rust +# Use Move syntax highlighter for Move IR code +*.mvir linguist-language=Move diff --git a/.github/workflows/ci-post-land.yml b/.github/workflows/ci-post-land.yml new file mode 100644 index 0000000000..e5ba437abc --- /dev/null +++ b/.github/workflows/ci-post-land.yml @@ -0,0 +1,30 @@ +# CI jobs to be run upon the code lands to the main branch or GitHub Action test branches. + +name: ci-post-land + +on: + push: + branches: [main, gha-test-*] + +jobs: + generate-documentation: + name: Generate the Move Book using mdBook + runs-on: ubuntu-20.04 + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + steps: + - uses: actions/checkout@v2 + + - name: Setup mdBook + uses: peaceiris/actions-mdbook@v1 + with: + mdbook-version: '0.4.10' + # mdbook-version: 'latest' + + - run: mdbook build language/documentation/book + + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./language/documentation/book/book diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-pre-land.yml similarity index 84% rename from .github/workflows/ci-test.yml rename to .github/workflows/ci-pre-land.yml index 876cea8d5f..fa6c76121a 100644 --- a/.github/workflows/ci-test.yml +++ b/.github/workflows/ci-pre-land.yml @@ -1,10 +1,10 @@ -name: ci-test +# CI jobs to be run upon the code lands to the main branch or GitHub Action test branches. + +name: ci-pre-land on: - push: - branches: [main, gha-test-*] pull_request: - branches: [main] + branches: [main, gha-test-*] jobs: prepare: @@ -21,7 +21,7 @@ jobs: name: determine changes uses: diem/actions/changes@faadd16607b77dfa2231a8f366883e01717b3225 with: - workflow-file: ci-test.yml + workflow-file: ci.yml github-token: ${{secrets.GITHUB_TOKEN}} - id: any-changes-found name: determine if there are any files listed in the CHANGES_CHANGED_FILE_OUTPUTFILE. @@ -205,17 +205,27 @@ jobs: # path: | # /tmp/benches - build-move-analyzer-vscode-extension: - name: Build VS Code extension for move-analyzer - runs-on: ubuntu-latest + test-move-analyzer-vscode-extension: + name: Test VS Code extension for move-analyzer + strategy: + fail-fast: false + matrix: + os: [ubuntu-20.04, macos-11, windows-2022] + runs-on: ${{ matrix.os }} needs: - prepare steps: - uses: actions/checkout@v2.4.0 + - name: Install rust toolchain + uses: actions-rs/toolchain@v1 + - name: Install lld + uses: knicknic/os-specific-run@v1.0.3 + with: + linux: sudo apt-get -y install lld - name: Use Node.js 14 uses: actions/setup-node@v2.4.0 with: - node-version: '14' + node-version: "14" - name: Install NPM dependencies working-directory: language/move-analyzer/editors/code run: npm install @@ -232,6 +242,28 @@ jobs: with: working-directory: language/move-analyzer/editors/code run: npm run test + + release-move-analyzer-vscode-extension: + name: Release VS Code extension for move-analyzer + runs-on: ubuntu-20.04 + needs: + - prepare + steps: + - uses: actions/checkout@v2.4.0 + - name: Install rust toolchain + uses: actions-rs/toolchain@v1 + - name: Install lld + run: sudo apt-get -y install lld + - name: Use Node.js 14 + uses: actions/setup-node@v2.4.0 + with: + node-version: "14" + - name: Install NPM dependencies + working-directory: language/move-analyzer/editors/code + run: npm install + - name: Build the extension + working-directory: language/move-analyzer/editors/code + run: npm run pretest - name: Package the extension working-directory: language/move-analyzer/editors/code run: npm run package @@ -249,15 +281,15 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up Ruby 2.6 - uses: actions/setup-ruby@v1 + uses: ruby/setup-ruby@v1 with: - ruby-version: 2.6.x + ruby-version: "2.6" - name: Run Checks run: | gem install awesome_bot # Don't look in git or target dirs. Don't check png, bib, tex, js, or shell files # We allow links to be redirects, allow duplicates, and we also allow Too Many Requests (429) errors - find . -not \( -path "./.git*" -prune \) -not \( -path "./target" -prune \) -type f -not -name "*.png" -not -name "*.sh" -not -name "*.bib" -not -name "*.tex" -not -name "*.js" | while read arg; do awesome_bot --allow-redirect --allow-dupe --allow 429 --skip-save-results $arg; done + find . -not \( -path "./.git*" -prune \) -not \( -path "./target" -prune \) -type f -not -name "*.png" -not -name "*.ai" -not -name "*.jpg" -not -name "*.svg" -not -name "*.sh" -not -name "*.bib" -not -name "*.tex" -not -name "*.js" -not -name "package-lock.json" | while read arg; do awesome_bot --allow-redirect --allow-dupe --allow 429 --skip-save-results $arg; done build-move-cli-docker-image: name: Build Docker image for the Move CLI @@ -271,4 +303,4 @@ jobs: - name: Build BasicCoin Move module run: | cd ./language/documentation/tutorial/step_1/BasicCoin - docker run -v `pwd`:/project move/cli package build + docker run -v `pwd`:/project move/cli build diff --git a/.github/workflows/daily.yml b/.github/workflows/daily.yml index 5901e076e9..75a84815e9 100644 --- a/.github/workflows/daily.yml +++ b/.github/workflows/daily.yml @@ -20,8 +20,9 @@ jobs: # List of ignored RUSTSEC # 1. RUSTSEC-2021-0073 - Not impacted. # 2. RUSTSEC-2021-0072 - Not impacted. + # 3. RUSTSEC-2020-0071 - Not impacted (chronotope/chrono#578). run: | - cargo audit --color never --ignore RUSTSEC-2021-0073 --ignore RUSTSEC-2021-0072 > $AUDIT_SUMMARY_FILE + cargo audit --color never --ignore RUSTSEC-2021-0073 --ignore RUSTSEC-2021-0072 --ignore RUSTSEC-2020-0071 > $AUDIT_SUMMARY_FILE - name: set issue body content if: ${{ failure() }} env: diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml new file mode 100644 index 0000000000..d657a63b2d --- /dev/null +++ b/.github/workflows/docker-image.yml @@ -0,0 +1,18 @@ +name: Docker Image CI + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Build the Docker image + run: docker build . --file Dockerfile --tag my-image-name:$(date +%s) diff --git a/.github/workflows/release_asset.yml b/.github/workflows/release_asset.yml index 2c77a143f8..501f716148 100644 --- a/.github/workflows/release_asset.yml +++ b/.github/workflows/release_asset.yml @@ -33,7 +33,7 @@ jobs: args: --release - name: package move asset - run: ./scripts/package_asset.sh ${{ matrix.platform }} + run: bash ./scripts/package_asset.sh ${{ matrix.platform }} - name: upload move asset if: ${{ github.event_name == 'release'}} diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000000..31000a2744 --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,22 @@ +name: Rust + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Build + run: cargo build --verbose + - name: Run tests + run: cargo test --verbose diff --git a/.gitignore b/.gitignore index 13d3db1d03..124e0b7c75 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ **/target **/*.rs.bk .idea/ +**/.vscode # Ignore wallet mnemonic files used for deterministic key derivation *.mnemonic diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a1d579e27f..44c9186fdd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -135,3 +135,26 @@ able to be built and passes all checks performed by CI. Move uses [GitHub issues](https://github.com/move-language/move/issues) to track bugs. Please include necessary information and instructions to reproduce your issue. + +## Major feature requests + +Please begin by checking the following locations for duplicate requests: +* [Approved feature proposals awaiting implementation](https://github.com/move-language/move/issues?q=is%3Aissue+is%3Aopen+label%3A%22accepted+feature+awaiting+implementation%22) +* [Feature proposals under discussion](https://github.com/move-language/move/issues?q=is%3Aissue+is%3Aopen+label%3A%22proposed+feature+in+discussion%22) +* [Language feature request graveyard](GRAVEYARD.md) + +If your feature is not in any of these locations, please add a new feature request using the following format: + +``` +Sponsor: your_github_id + +## Status: initial proposal + +## Rationale +A detailed description of the problem the proposed feature seeks to solve. This should explain why the problem is important for smart contract programmers and why it is impossible (or unacceptably unpleasant) to solve with the existing language constructs. Examples are strongly recommended. + +## Design +Explain the key decisions to be made in designing the feature. This can be organized as fully fleshed out design, a list of design options with pros and cons, or a list of questions to be answered. A proposed feature should have a very strong/clear rationale, but it is ok if many key design questions are open--the Move community and core contributors can help with this. +``` + +A Move core contributor will either add a `proposed_feature_to_be_discussed` tag and queue the feature for discussion at a future Move community meeting (and change the "Status" to reflect the meeting date), or will request changes that must be made to the issue before it is ready for discussion. diff --git a/Cargo.lock b/Cargo.lock index 77837b7dd6..275245ef03 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -116,6 +116,15 @@ version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3" +[[package]] +name = "arbitrary" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86fd10d912cab78764cc44307d9cd5f164e09abbeb87fb19fb6d95937e8da5f" +dependencies = [ + "derive_arbitrary", +] + [[package]] name = "arrayref" version = "0.3.6" @@ -134,17 +143,170 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +[[package]] +name = "ascii-canvas" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +dependencies = [ + "term 0.7.0", +] + +[[package]] +name = "assert-json-diff" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12" +dependencies = [ + "serde 1.0.145", + "serde_json", +] + +[[package]] +name = "async-channel" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "once_cell", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5262ed948da60dd8956c6c5aca4d4163593dddb7b32d73267c93dab7b2e98940" +dependencies = [ + "async-channel", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "num_cpus", + "once_cell", +] + +[[package]] +name = "async-io" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5e18f61464ae81cde0a23e713ae8fd299580c54d697a35820cfd0625b8b0e07" +dependencies = [ + "concurrent-queue", + "futures-lite", + "libc", + "log", + "once_cell", + "parking", + "polling", + "slab", + "socket2", + "waker-fn", + "winapi", +] + +[[package]] +name = "async-lock" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-object-pool" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeb901c30ebc2fc4ab46395bbfbdba9542c16559d853645d75190c3056caf3bc" +dependencies = [ + "async-std", +] + +[[package]] +name = "async-process" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf2c06e30a24e8c78a3987d07f0930edf76ef35e027e7bdb063fccafdad1f60c" +dependencies = [ + "async-io", + "blocking", + "cfg-if 1.0.0", + "event-listener", + "futures-lite", + "libc", + "once_cell", + "signal-hook", + "winapi", +] + +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-channel", + "async-global-executor", + "async-io", + "async-lock", + "async-process", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-task" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" + [[package]] name = "async-trait" version = "0.1.48" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36ea56748e10732c49404c153638a15ec3d6211ec5ff35d9bb20e13b93576adf" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] +[[package]] +name = "atomic-waker" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" + [[package]] name = "atty" version = "0.2.14" @@ -163,9 +325,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7862e21c893d65a1650125d157eaeec691439379a1cee17ee49031b79236ada4" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] [[package]] @@ -180,13 +342,24 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "basic-cookies" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb53b6b315f924c7f113b162e53b3901c05fc9966baf84d201dfcc7432a4bb38" +dependencies = [ + "lalrpop", + "lalrpop-util", + "regex", +] + [[package]] name = "bcs" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "510fd83e3eaf7263b06182f3550b4c0af2af42cb36ab8024969ff5ea7fcb2833" +checksum = "8b06b4c1f053002b70e7084ac944c77d58d5d92b2110dbc5e852735e00ad3ccc" dependencies = [ - "serde 1.0.130", + "serde 1.0.145", "thiserror", ] @@ -205,9 +378,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3deeecb812ca5300b7d3f66f730cc2ebd3511c3d36c691dd79c165d5b19a26e3" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] [[package]] @@ -333,6 +506,20 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" +[[package]] +name = "blocking" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc" +dependencies = [ + "async-channel", + "async-task", + "atomic-waker", + "fastrand", + "futures-lite", + "once_cell", +] + [[package]] name = "bstr" version = "0.2.15" @@ -342,7 +529,7 @@ dependencies = [ "lazy_static 1.4.0", "memchr", "regex-automata", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -387,10 +574,23 @@ dependencies = [ "move-unit-test", ] +[[package]] +name = "bytecode-verifier-libfuzzer" +version = "0.0.0" +dependencies = [ + "arbitrary", + "libfuzzer-sys", + "move-binary-format", + "move-bytecode-verifier", + "move-core-types", +] + [[package]] name = "bytecode-verifier-tests" version = "0.1.0" dependencies = [ + "fail", + "hex", "invalid-mutations", "move-binary-format", "move-bytecode-verifier", @@ -419,13 +619,19 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" +[[package]] +name = "cache-padded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" + [[package]] name = "camino" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52d74260d9bf6944e2208aa46841b4b8f0d7ffc0849a06837b2f510337f86b2b" dependencies = [ - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -434,7 +640,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" dependencies = [ - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -446,7 +652,7 @@ dependencies = [ "camino", "cargo-platform", "semver 1.0.4", - "serde 1.0.130", + "serde 1.0.145", "serde_json", ] @@ -465,11 +671,20 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "castaway" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" + [[package]] name = "cc" version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" +dependencies = [ + "jobserver", +] [[package]] name = "cfg-expr" @@ -508,12 +723,24 @@ dependencies = [ [[package]] name = "chrono-tz" -version = "0.5.3" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2554a3155fec064362507487171dcc4edc3df60cb10f3a1fb10ed8094822b120" +checksum = "58549f1842da3080ce63002102d5bc954c7bc843d4f47818e642abdc36253552" dependencies = [ "chrono", + "chrono-tz-build", + "phf", +] + +[[package]] +name = "chrono-tz-build" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db058d493fb2f65f41861bfed7e3fe6335264a9f0f92710cab5bdf01fef09069" +dependencies = [ "parse-zoneinfo", + "phf", + "phf_codegen", ] [[package]] @@ -565,18 +792,9 @@ checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1" dependencies = [ "heck 0.4.0", "proc-macro-error", - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", -] - -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags", + "syn 1.0.99", ] [[package]] @@ -586,7 +804,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3362992a0d9f1dd7c3d0e89e0ab2bb540b7a95fea8cd798090e758fda2899b5e" dependencies = [ "codespan-reporting", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -595,7 +813,7 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" dependencies = [ - "serde 1.0.130", + "serde 1.0.145", "termcolor", "unicode-width", ] @@ -622,6 +840,25 @@ dependencies = [ "itertools 0.10.1", ] +[[package]] +name = "combine" +version = "4.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a604e93b79d1808327a6fca85a6f2d69de66461e7620f5a4cbf5fb4d1d7c948" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "1.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af4780a44ab5696ea9e28294517f1fffb421a83a25af521333c838635509db9c" +dependencies = [ + "cache-padded", +] + [[package]] name = "config" version = "0.11.0" @@ -631,7 +868,7 @@ dependencies = [ "lazy_static 1.4.0", "nom", "rust-ini", - "serde 1.0.130", + "serde 1.0.145", "serde-hjson", "serde_json", "toml", @@ -666,6 +903,22 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + [[package]] name = "cpuid-bool" version = "0.1.2" @@ -696,7 +949,7 @@ dependencies = [ "plotters", "rayon", "regex", - "serde 1.0.130", + "serde 1.0.145", "serde_cbor", "serde_derive", "serde_json", @@ -802,7 +1055,7 @@ dependencies = [ "bitflags", "crossterm_winapi 0.8.0", "libc", - "mio", + "mio 0.7.13", "parking_lot 0.11.1", "signal-hook", "signal-hook-mio", @@ -818,7 +1071,7 @@ dependencies = [ "bitflags", "crossterm_winapi 0.9.0", "libc", - "mio", + "mio 0.7.13", "parking_lot 0.11.1", "signal-hook", "signal-hook-mio", @@ -879,7 +1132,7 @@ dependencies = [ "csv-core", "itoa 0.4.7", "ryu", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -891,6 +1144,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "ctor" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" +dependencies = [ + "quote 1.0.9", + "syn 1.0.99", +] + [[package]] name = "ctr" version = "0.6.0" @@ -910,6 +1173,37 @@ dependencies = [ "winapi", ] +[[package]] +name = "curl" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22" +dependencies = [ + "curl-sys", + "libc", + "openssl-probe", + "openssl-sys", + "schannel", + "socket2", + "winapi", +] + +[[package]] +name = "curl-sys" +version = "0.4.56+curl-7.83.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6093e169dd4de29e468fa649fbae11cdcd5551c81fe5bf1b0677adad7ef3d26f" +dependencies = [ + "cc", + "libc", + "libnghttp2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", + "winapi", +] + [[package]] name = "curve25519-dalek-fiat" version = "0.1.0" @@ -953,15 +1247,37 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "223089cd5a4e4491f0a0dddd9933f9575123160cf96ca2bb56a690046ecf1745" +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2 1.0.43", + "quote 1.0.9", + "syn 1.0.99", +] + +[[package]] +name = "derive_arbitrary" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "226ad66541d865d7a7173ad6a9e691c33fdb910ac723f4bc734b3e5294a1f931" +dependencies = [ + "proc-macro2 1.0.43", + "quote 1.0.9", + "syn 1.0.99", +] + [[package]] name = "derive_more" version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] [[package]] @@ -977,7 +1293,7 @@ dependencies = [ "once_cell", "petgraph 0.6.0", "rayon", - "serde 1.0.130", + "serde 1.0.145", "toml", ] @@ -999,6 +1315,7 @@ dependencies = [ "move-cli", "move-core-types", "move-stdlib", + "move-vm-test-utils", "move-vm-types", ] @@ -1026,7 +1343,7 @@ dependencies = [ "rand 0.8.4", "rand_core 0.6.2", "ripemd160", - "serde 1.0.130", + "serde 1.0.145", "serde-name", "serde_bytes", "serde_json", @@ -1044,9 +1361,9 @@ name = "diem-crypto-derive" version = "0.0.3" dependencies = [ "anyhow", - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] [[package]] @@ -1061,6 +1378,12 @@ dependencies = [ "smallvec", ] +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "difference" version = "2.0.0" @@ -1189,13 +1512,19 @@ dependencies = [ "shared_child", ] +[[package]] +name = "dunce" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541" + [[package]] name = "ed25519" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37c66a534cbb46ab4ea03477eae19d5c22c01da8258030280b7bd9d8433fb6ef" dependencies = [ - "serde 1.0.130", + "serde 1.0.145", "signature", ] @@ -1208,7 +1537,7 @@ dependencies = [ "curve25519-dalek-fiat", "ed25519", "rand 0.8.4", - "serde 1.0.130", + "serde 1.0.145", "serde_bytes", "sha2", "zeroize", @@ -1220,12 +1549,30 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "ena" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3" +dependencies = [ + "log", +] + [[package]] name = "encode_unicode" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +[[package]] +name = "encoding_rs" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "env_logger" version = "0.8.4" @@ -1255,7 +1602,7 @@ dependencies = [ "hex", "once_cell", "regex", - "serde 1.0.130", + "serde 1.0.145", "serde_json", "sha3 0.10.1", "thiserror", @@ -1303,7 +1650,7 @@ dependencies = [ "rlp", "rlp-derive", "scale-info", - "serde 1.0.130", + "serde 1.0.145", "sha3 0.9.1", "triehash", ] @@ -1343,6 +1690,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f58da196a1fc8f14cb51f373f504efc66c434c577b777c2cd30d6fad16e4822" +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + [[package]] name = "evm" version = "0.33.1" @@ -1360,7 +1713,7 @@ dependencies = [ "primitive-types 0.10.1", "rlp", "scale-info", - "serde 1.0.130", + "serde 1.0.145", "sha3 0.8.2", ] @@ -1374,7 +1727,7 @@ dependencies = [ "parity-scale-codec 2.3.1", "primitive-types 0.10.1", "scale-info", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -1430,7 +1783,7 @@ dependencies = [ "move-to-yul", "once_cell", "regex", - "serde 1.0.130", + "serde 1.0.145", "serde_json", ] @@ -1451,6 +1804,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +[[package]] +name = "fastrand" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +dependencies = [ + "instant", +] + [[package]] name = "fiat-crypto" version = "0.1.6" @@ -1493,6 +1855,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.0.1" @@ -1569,6 +1946,21 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b0e06c393068f3a6ef246c75cdca793d6a46347e75286933e5e75fd2fd11582" +[[package]] +name = "futures-lite" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + [[package]] name = "futures-macro" version = "0.3.16" @@ -1577,9 +1969,9 @@ checksum = "c54913bae956fb8df7f4dc6fc90362aa72e69148e3f39041fbe8742d21e0ac57" dependencies = [ "autocfg", "proc-macro-hack", - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] [[package]] @@ -1696,6 +2088,18 @@ dependencies = [ "walkdir", ] +[[package]] +name = "gloo-timers" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "guppy" version = "0.12.6" @@ -1717,7 +2121,7 @@ dependencies = [ "petgraph 0.6.0", "rayon", "semver 1.0.4", - "serde 1.0.130", + "serde 1.0.145", "serde_json", "smallvec", "target-spec", @@ -1734,7 +2138,7 @@ dependencies = [ "cfg-if 1.0.0", "diffus", "semver 1.0.4", - "serde 1.0.130", + "serde 1.0.145", "toml", ] @@ -1744,6 +2148,25 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92620684d99f750bae383ecb3be3748142d6095760afd5cbcf2261e9a279d780" +[[package]] +name = "h2" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "half" version = "1.7.1" @@ -1810,6 +2233,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + [[package]] name = "hkdf" version = "0.10.0" @@ -1830,6 +2259,68 @@ dependencies = [ "digest 0.9.0", ] +[[package]] +name = "http" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.1", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "httpmock" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c159c4fc205e6c1a9b325cb7ec135d13b5f47188ce175dabb76ec847f331d9bd" +dependencies = [ + "assert-json-diff", + "async-object-pool", + "async-trait", + "base64", + "basic-cookies", + "crossbeam-utils", + "form_urlencoded", + "futures-util", + "hyper", + "isahc", + "lazy_static 1.4.0", + "levenshtein", + "log", + "regex", + "serde 1.0.145", + "serde_json", + "serde_regex", + "similar", + "tokio", + "url", +] + [[package]] name = "humansize" version = "1.1.0" @@ -1843,13 +2334,50 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] -name = "humantime-serde" -version = "1.0.1" +name = "humantime-serde" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac34a56cfd4acddb469cc7fff187ed5ac36f498ba085caf8bbc725e3ff474058" +dependencies = [ + "humantime", + "serde 1.0.145", +] + +[[package]] +name = "hyper" +version = "0.14.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa 1.0.1", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac34a56cfd4acddb469cc7fff187ed5ac36f498ba085caf8bbc725e3ff474058" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ - "humantime", - "serde 1.0.130", + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", ] [[package]] @@ -1928,7 +2456,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" dependencies = [ - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -1937,9 +2465,9 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] [[package]] @@ -1996,12 +2524,45 @@ dependencies = [ "proptest", ] +[[package]] +name = "ipnet" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" + [[package]] name = "is_ci" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" +[[package]] +name = "isahc" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "334e04b4d781f436dc315cb1e7515bd96826426345d498149e4bde36b67f8ee9" +dependencies = [ + "async-channel", + "castaway", + "crossbeam-utils", + "curl", + "curl-sys", + "encoding_rs", + "event-listener", + "futures-lite", + "http", + "log", + "mime", + "once_cell", + "polling", + "slab", + "sluice", + "tracing", + "tracing-futures", + "url", + "waker-fn", +] + [[package]] name = "itertools" version = "0.9.0" @@ -2032,6 +2593,15 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +[[package]] +name = "jobserver" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.48" @@ -2047,6 +2617,47 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + +[[package]] +name = "lalrpop" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b30455341b0e18f276fa64540aff54deafb54c589de6aca68659c63dd2d5d823" +dependencies = [ + "ascii-canvas", + "atty", + "bit-set", + "diff", + "ena", + "itertools 0.10.1", + "lalrpop-util", + "petgraph 0.6.0", + "pico-args", + "regex", + "regex-syntax", + "string_cache", + "term 0.7.0", + "tiny-keccak", + "unicode-xid 0.2.2", +] + +[[package]] +name = "lalrpop-util" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf796c978e9b4d983414f4caedc9273aa33ee214c5b887bd55fde84c85d2dc4" +dependencies = [ + "regex", +] + [[package]] name = "language-benchmarks" version = "0.1.0" @@ -2078,6 +2689,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "levenshtein" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" + [[package]] name = "lexical-core" version = "0.7.6" @@ -2093,42 +2710,67 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.112" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" [[package]] -name = "linked-hash-map" -version = "0.5.4" +name = "libfuzzer-sys" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +checksum = "ae185684fe19814afd066da15a7cc41e126886c21282934225d9fc847582da58" +dependencies = [ + "arbitrary", + "cc", + "once_cell", +] [[package]] -name = "lock_api" -version = "0.3.4" +name = "libnghttp2-sys" +version = "0.1.7+1.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" +checksum = "57ed28aba195b38d5ff02b9170cbff627e336a20925e43b4945390401c5dc93f" dependencies = [ - "scopeguard", + "cc", + "libc", +] + +[[package]] +name = "libz-sys" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", ] +[[package]] +name = "linked-hash-map" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" + [[package]] name = "lock_api" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" dependencies = [ "scopeguard", ] [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if 1.0.0", - "serde 1.0.130", + "serde 1.0.145", + "value-bag", ] [[package]] @@ -2139,7 +2781,7 @@ checksum = "c351c75989da23b355226dc188dc2b52538a7f4f218d70fd7393c6b62b110444" dependencies = [ "crossbeam-channel", "log", - "serde 1.0.130", + "serde 1.0.145", "serde_json", ] @@ -2150,7 +2792,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f3734ab1d7d157fc0c45110e06b587c31cd82bea2ccfd6b563cbff0aaeeb1d3" dependencies = [ "bitflags", - "serde 1.0.130", + "serde 1.0.145", "serde_json", "serde_repr", "url", @@ -2192,6 +2834,22 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memory-stats" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d3f458a3076e337e027943b8cb5f4f72a6651714f9258fc7dcd3ae3b51f0276" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + [[package]] name = "mio" version = "0.7.13" @@ -2205,6 +2863,18 @@ dependencies = [ "winapi", ] +[[package]] +name = "mio" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +dependencies = [ + "libc", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys", +] + [[package]] name = "miow" version = "0.3.7" @@ -2243,24 +2913,27 @@ dependencies = [ "datatest-stable", "heck 0.3.2", "log", + "move-binary-format", "move-bytecode-verifier", "move-command-line-common", "move-core-types", "move-model", "move-prover", "move-prover-test-utils", - "serde 1.0.130", + "serde 1.0.145", "tempfile", ] [[package]] name = "move-analyzer" -version = "0.0.0" +version = "1.0.0" dependencies = [ "anyhow", "clap 3.1.8", "codespan-reporting", "crossbeam", + "derivative", + "dunce", "im", "lsp-server", "lsp-types", @@ -2270,6 +2943,7 @@ dependencies = [ "move-package", "move-symbol-pool", "petgraph 0.5.1", + "serde 1.0.145", "serde_json", "tempfile", "url", @@ -2291,6 +2965,7 @@ dependencies = [ "move-prover-test-utils", "move-stdlib", "move-vm-runtime", + "move-vm-test-utils", "move-vm-types", "sha3 0.9.1", "smallvec", @@ -2302,12 +2977,13 @@ name = "move-binary-format" version = "0.0.3" dependencies = [ "anyhow", + "arbitrary", "move-core-types", "once_cell", "proptest", "proptest-derive", "ref-cast", - "serde 1.0.130", + "serde 1.0.145", "serde_json", "variant_count", ] @@ -2327,7 +3003,7 @@ dependencies = [ "move-core-types", "move-ir-types", "move-symbol-pool", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -2346,6 +3022,8 @@ name = "move-bytecode-verifier" version = "0.1.0" dependencies = [ "anyhow", + "fail", + "hex-literal", "invalid-mutations", "move-binary-format", "move-borrow-graph", @@ -2380,6 +3058,7 @@ dependencies = [ "colored", "datatest-stable", "difference", + "httpmock", "itertools 0.10.1", "move-binary-format", "move-bytecode-source-map", @@ -2391,6 +3070,7 @@ dependencies = [ "move-core-types", "move-coverage", "move-disassembler", + "move-docgen", "move-errmapgen", "move-ir-types", "move-package", @@ -2401,13 +3081,17 @@ dependencies = [ "move-table-extension", "move-unit-test", "move-vm-runtime", + "move-vm-test-utils", "move-vm-types", "once_cell", "read-write-set", "read-write-set-dynamic", - "serde 1.0.130", + "reqwest", + "serde 1.0.145", + "serde_json", "serde_yaml", "tempfile", + "toml_edit", "walkdir", ] @@ -2417,10 +3101,12 @@ version = "0.1.0" dependencies = [ "anyhow", "difference", + "dirs-next", "hex", "move-core-types", "num-bigint 0.4.0", - "serde 1.0.130", + "once_cell", + "serde 1.0.145", "sha2", "walkdir", ] @@ -2468,17 +3154,22 @@ name = "move-core-types" version = "0.0.4" dependencies = [ "anyhow", + "arbitrary", "bcs", + "ethnum", "hex", + "num 0.4.0", "once_cell", + "primitive-types 0.10.1", "proptest", "proptest-derive", "rand 0.8.4", "ref-cast", "regex", - "serde 1.0.130", + "serde 1.0.145", "serde_bytes", "serde_json", + "uint", ] [[package]] @@ -2497,7 +3188,7 @@ dependencies = [ "move-ir-types", "once_cell", "petgraph 0.5.1", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -2534,7 +3225,7 @@ dependencies = [ "num 0.4.0", "once_cell", "regex", - "serde 1.0.130", + "serde 1.0.145", "tempfile", ] @@ -2551,7 +3242,7 @@ dependencies = [ "move-core-types", "move-model", "move-prover", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -2562,7 +3253,7 @@ dependencies = [ "ethabi", "once_cell", "regex", - "serde 1.0.130", + "serde 1.0.145", "serde_json", ] @@ -2642,7 +3333,7 @@ dependencies = [ "move-core-types", "move-symbol-pool", "once_cell", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -2669,7 +3360,7 @@ dependencies = [ "num 0.4.0", "once_cell", "regex", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -2684,6 +3375,7 @@ dependencies = [ "dirs-next", "evm-exec-utils", "hex", + "itertools 0.10.1", "move-abigen", "move-binary-format", "move-bytecode-source-map", @@ -2700,13 +3392,15 @@ dependencies = [ "petgraph 0.5.1", "ptree", "regex", - "serde 1.0.130", + "reqwest", + "serde 1.0.145", "serde_yaml", "sha2", "tempfile", "termcolor", "toml", "walkdir", + "whoami", ] [[package]] @@ -2740,7 +3434,7 @@ dependencies = [ "once_cell", "pretty", "rand 0.8.4", - "serde 1.0.130", + "serde 1.0.145", "serde_json", "shell-words", "simplelog", @@ -2763,6 +3457,7 @@ dependencies = [ "log", "move-binary-format", "move-command-line-common", + "move-compiler", "move-core-types", "move-model", "move-stackless-bytecode", @@ -2771,7 +3466,7 @@ dependencies = [ "pretty", "rand 0.8.4", "regex", - "serde 1.0.130", + "serde 1.0.145", "serde_json", "tera", "tokio", @@ -2794,7 +3489,7 @@ dependencies = [ "anyhow", "move-binary-format", "move-core-types", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -2808,7 +3503,7 @@ dependencies = [ "move-bytecode-utils", "move-core-types", "once_cell", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -2838,7 +3533,7 @@ dependencies = [ "once_cell", "paste", "petgraph 0.5.1", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -2857,7 +3552,7 @@ dependencies = [ "move-prover-test-utils", "move-stackless-bytecode", "num 0.4.0", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -2867,6 +3562,7 @@ dependencies = [ "anyhow", "dir-diff", "file_diff", + "hex", "log", "move-binary-format", "move-cli", @@ -2892,7 +3588,7 @@ name = "move-symbol-pool" version = "0.1.0" dependencies = [ "once_cell", - "serde 1.0.130", + "serde 1.0.145", "serde_json", ] @@ -2951,7 +3647,7 @@ dependencies = [ "primitive-types 0.10.1", "rand 0.8.4", "regex", - "serde 1.0.130", + "serde 1.0.145", "serde_json", "sha3 0.9.1", "simplelog", @@ -2972,6 +3668,7 @@ dependencies = [ "move-binary-format", "move-bytecode-source-map", "move-bytecode-utils", + "move-bytecode-verifier", "move-cli", "move-command-line-common", "move-compiler", @@ -2997,6 +3694,7 @@ name = "move-unit-test" version = "0.1.0" dependencies = [ "anyhow", + "better_any", "clap 3.1.8", "codespan-reporting", "colored", @@ -3032,7 +3730,9 @@ name = "move-vm-integration-tests" version = "0.1.0" dependencies = [ "anyhow", + "memory-stats", "move-binary-format", + "move-bytecode-verifier", "move-compiler", "move-core-types", "move-stdlib", @@ -3043,6 +3743,15 @@ dependencies = [ "tempfile", ] +[[package]] +name = "move-vm-paranoid-tests" +version = "0.1.0" +dependencies = [ + "datatest-stable", + "fail", + "move-transactional-test-runner", +] + [[package]] name = "move-vm-runtime" version = "0.1.0" @@ -3069,8 +3778,12 @@ name = "move-vm-test-utils" version = "0.1.0" dependencies = [ "anyhow", + "move-binary-format", "move-core-types", "move-table-extension", + "move-vm-types", + "once_cell", + "serde 1.0.145", ] [[package]] @@ -3090,30 +3803,54 @@ dependencies = [ "move-core-types", "once_cell", "proptest", - "serde 1.0.130", + "serde 1.0.145", "smallvec", ] [[package]] name = "named-lock" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3ab176d4bcfbcb53b8c7c5a25cb2c01674cda33db27064a85a16814c88c1f2d" +checksum = "40a3eb6b7c682b65d1f631ec3176829d72ab450b3aacdd3f719bf220822e59ac" dependencies = [ "libc", "once_cell", - "parking_lot 0.10.2", + "parking_lot 0.12.1", "thiserror", "widestring", "winapi", ] +[[package]] +name = "native-tls" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +dependencies = [ + "lazy_static 1.4.0", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "nested" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b420f638f07fe83056b55ea190bb815f609ec5a35e7017884a10f78839c9e" +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + [[package]] name = "nextest-config" version = "0.1.0" @@ -3122,7 +3859,7 @@ dependencies = [ "camino", "config", "humantime-serde", - "serde 1.0.130", + "serde 1.0.145", "toml", ] @@ -3148,7 +3885,7 @@ dependencies = [ "owo-colors", "quick-junit", "rayon", - "serde 1.0.130", + "serde 1.0.145", "serde_json", "strip-ansi-escapes", "twox-hash", @@ -3160,7 +3897,7 @@ version = "0.1.0" source = "git+https://github.com/diem/diem-devtools?rev=f99a204e3d3f8e503d51d7df42e55c8282b59154#f99a204e3d3f8e503d51d7df42e55c8282b59154" dependencies = [ "camino", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -3361,6 +4098,51 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "openssl" +version = "0.10.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" +dependencies = [ + "bitflags", + "cfg-if 1.0.0", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +dependencies = [ + "proc-macro2 1.0.43", + "quote 1.0.9", + "syn 1.0.99", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "ordered-float" version = "2.1.1" @@ -3407,9 +4189,9 @@ checksum = "41db02c8f8731cdd7a72b433c7900cce4bf245465b452c364bfd21f4566ab055" dependencies = [ "Inflector", "proc-macro-error", - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] [[package]] @@ -3429,7 +4211,7 @@ dependencies = [ "byte-slice-cast", "impl-trait-for-tuples", "parity-scale-codec-derive 2.3.1", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -3443,7 +4225,7 @@ dependencies = [ "byte-slice-cast", "impl-trait-for-tuples", "parity-scale-codec-derive 3.1.2", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -3453,9 +4235,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" dependencies = [ "proc-macro-crate", - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] [[package]] @@ -3465,20 +4247,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c45ed1f39709f5a89338fab50e59816b2e8815f5bb58276e7ddf9afd495f73f8" dependencies = [ "proc-macro-crate", - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] [[package]] -name = "parking_lot" -version = "0.10.2" +name = "parking" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" -dependencies = [ - "lock_api 0.3.4", - "parking_lot_core 0.7.2", -] +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" [[package]] name = "parking_lot" @@ -3487,22 +4265,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" dependencies = [ "instant", - "lock_api 0.4.4", + "lock_api", "parking_lot_core 0.8.3", ] [[package]] -name = "parking_lot_core" -version = "0.7.2" +name = "parking_lot" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ - "cfg-if 0.1.10", - "cloudabi", - "libc", - "redox_syscall 0.1.57", - "smallvec", - "winapi", + "lock_api", + "parking_lot_core 0.9.3", ] [[package]] @@ -3519,6 +4293,19 @@ dependencies = [ "winapi", ] +[[package]] +name = "parking_lot_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall 0.2.10", + "smallvec", + "windows-sys", +] + [[package]] name = "parse-zoneinfo" version = "0.3.0" @@ -3576,9 +4363,9 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] [[package]] @@ -3612,6 +4399,71 @@ dependencies = [ "indexmap", ] +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared", + "rand 0.8.4", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", + "uncased", +] + +[[package]] +name = "pico-args" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" + +[[package]] +name = "pin-project" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78203e83c48cffbe01e4a2d35d566ca4de445d79a85372fc64e378bfc812a260" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74" +dependencies = [ + "proc-macro2 1.0.43", + "quote 1.0.9", + "syn 1.0.99", +] + [[package]] name = "pin-project-lite" version = "0.2.7" @@ -3624,6 +4476,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" + [[package]] name = "plotters" version = "0.3.0" @@ -3652,6 +4510,19 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "polling" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "log", + "wepoll-ffi", + "winapi", +] + [[package]] name = "polyval" version = "0.4.5" @@ -3678,9 +4549,9 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597c3287a549da151aca6ada2795ecde089c7527bd5093114e8e0e1c3f0e52b1" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] [[package]] @@ -3689,6 +4560,12 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "pretty" version = "0.10.0" @@ -3720,7 +4597,7 @@ dependencies = [ "csv", "encode_unicode", "lazy_static 1.4.0", - "term", + "term 0.5.2", "unicode-width", ] @@ -3733,6 +4610,7 @@ dependencies = [ "fixed-hash", "impl-codec 0.5.1", "impl-rlp", + "impl-serde", "scale-info", "uint", ] @@ -3767,9 +4645,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", "version_check", ] @@ -3779,7 +4657,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", "version_check", ] @@ -3807,11 +4685,11 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.28" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" dependencies = [ - "unicode-xid 0.2.2", + "unicode-ident", ] [[package]] @@ -3862,7 +4740,7 @@ dependencies = [ "move-stackless-bytecode", "num 0.4.0", "plotters", - "serde 1.0.130", + "serde 1.0.145", "serde_json", "simplelog", "z3tracer", @@ -3885,7 +4763,7 @@ dependencies = [ "move-prover", "move-stackless-bytecode", "num 0.4.0", - "serde 1.0.130", + "serde 1.0.145", "serde_json", "simplelog", ] @@ -3901,7 +4779,7 @@ dependencies = [ "config", "directories", "petgraph 0.6.0", - "serde 1.0.130", + "serde 1.0.145", "serde-value", "tint", ] @@ -3952,7 +4830,7 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", ] [[package]] @@ -4173,9 +5051,9 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c38e3aecd2b21cb3959637b883bb3714bc7e43f0268b9a29d3743ee3e55cdd2" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] [[package]] @@ -4214,6 +5092,43 @@ dependencies = [ "winapi", ] +[[package]] +name = "reqwest" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "lazy_static 1.4.0", + "log", + "mime", + "native-tls", + "percent-encoding", + "pin-project-lite", + "serde 1.0.145", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + [[package]] name = "ripemd160" version = "0.9.1" @@ -4241,9 +5156,9 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] [[package]] @@ -4279,6 +5194,12 @@ dependencies = [ "semver 0.9.0", ] +[[package]] +name = "rustversion" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24c8ad4f0c00e1eb5bc7614d236a7f1300e3dbd76b68cac8e06fb00b015ad8d8" + [[package]] name = "rusty-fork" version = "0.3.0" @@ -4326,9 +5247,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd" dependencies = [ "proc-macro-crate", - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", +] + +[[package]] +name = "schannel" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +dependencies = [ + "lazy_static 1.4.0", + "windows-sys", ] [[package]] @@ -4337,6 +5268,29 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "security-framework" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "0.9.0" @@ -4352,7 +5306,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" dependencies = [ - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -4369,9 +5323,9 @@ checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" [[package]] name = "serde" -version = "1.0.130" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" dependencies = [ "serde_derive", ] @@ -4394,7 +5348,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12c47087018ec281d1cdab673d36aea22d816b54d498264029c05d5fa1910da6" dependencies = [ - "serde 1.0.130", + "serde 1.0.145", "thiserror", ] @@ -4405,7 +5359,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "167450ba550f903a2b35a81ba3ca387585189e2430e3df6b94b95f3bec2f26bd" dependencies = [ "once_cell", - "serde 1.0.130", + "serde 1.0.145", "thiserror", ] @@ -4416,7 +5370,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" dependencies = [ "ordered-float", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -4425,7 +5379,7 @@ version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16ae07dd2f88a366f15bd0632ba725227018c69a1c8550a927324f8eb8368bb9" dependencies = [ - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -4435,18 +5389,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" dependencies = [ "half", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] name = "serde_derive" -version = "1.0.130" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] [[package]] @@ -4457,7 +5411,17 @@ checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5" dependencies = [ "itoa 1.0.1", "ryu", - "serde 1.0.130", + "serde 1.0.145", +] + +[[package]] +name = "serde_regex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8136f1a4ea815d7eac4101cfd0b16dc0cb5e1fe1b8609dfd728058656b7badf" +dependencies = [ + "regex", + "serde 1.0.145", ] [[package]] @@ -4466,9 +5430,21 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa 1.0.1", + "ryu", + "serde 1.0.145", ] [[package]] @@ -4479,7 +5455,7 @@ checksum = "15654ed4ab61726bf918a39cb8d98a2e2995b002387807fa6ba58fdf7f59bb23" dependencies = [ "dtoa", "linked-hash-map", - "serde 1.0.130", + "serde 1.0.145", "yaml-rust", ] @@ -4594,7 +5570,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29fd5867f1c4f2c5be079aee7a2adf1152ebb04a4bc4d341f504b7dece607ed4" dependencies = [ "libc", - "mio", + "mio 0.7.13", "signal-hook", ] @@ -4613,6 +5589,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f0242b8e50dd9accdd56170e94ca1ebd223b098eb9c83539a6e367d0f36ae68" +[[package]] +name = "similar" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e24979f63a11545f5f2c60141afe249d4f19f84581ea2138065e400941d83d3" + [[package]] name = "simplelog" version = "0.9.0" @@ -4624,6 +5606,12 @@ dependencies = [ "termcolor", ] +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + [[package]] name = "sized-chunks" version = "0.6.5" @@ -4649,6 +5637,17 @@ dependencies = [ "deunicode", ] +[[package]] +name = "sluice" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d7400c0eff44aa2fcb5e31a5f24ba9716ed90138769e4977a2ba6014ae63eb5" +dependencies = [ + "async-channel", + "futures-core", + "futures-io", +] + [[package]] name = "smallvec" version = "1.7.0" @@ -4667,6 +5666,16 @@ dependencies = [ "structopt 0.3.25", ] +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "spec-flatten" version = "0.1.0" @@ -4693,6 +5702,19 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "string_cache" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot 0.12.1", + "phf_shared", + "precomputed-hash", +] + [[package]] name = "strip-ansi-escapes" version = "0.1.1" @@ -4755,9 +5777,9 @@ checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ "heck 0.3.2", "proc-macro-error", - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] [[package]] @@ -4789,13 +5811,13 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.74" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "unicode-xid 0.2.2", + "unicode-ident", ] [[package]] @@ -4804,9 +5826,9 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", "unicode-xid 0.2.2", ] @@ -4829,7 +5851,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdc03d14ed79a75163d3509ebf1970a2ec67945c5cac68d947d1dddace43cec0" dependencies = [ "cfg-expr", - "serde 1.0.130", + "serde 1.0.145", "target-lexicon", ] @@ -4849,9 +5871,9 @@ dependencies = [ [[package]] name = "tera" -version = "1.7.1" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2617ab2fb1de8587a988a761692e59895438bebf404725d4f2123251f60bf23e" +checksum = "7c9783d6ff395ae80cf17ed9a25360e7ba37742a79fa8fddabb073c5c7c8856d" dependencies = [ "chrono", "chrono-tz", @@ -4863,7 +5885,7 @@ dependencies = [ "pest_derive", "rand 0.8.4", "regex", - "serde 1.0.130", + "serde 1.0.145", "serde_json", "slug", "unic-segment", @@ -4880,6 +5902,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + [[package]] name = "termcolor" version = "1.1.2" @@ -4931,29 +5964,29 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "thiserror" -version = "1.0.26" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.26" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] [[package]] name = "thread_local" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" dependencies = [ "once_cell", ] @@ -4993,7 +6026,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" dependencies = [ - "serde 1.0.130", + "serde 1.0.145", "serde_json", ] @@ -5014,33 +6047,57 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.9.0" +version = "1.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b7b349f11a7047e6d1276853e612d152f5e8a352c61917887cc2169e2366b4c" +checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" dependencies = [ - "autocfg", "bytes", "libc", "memchr", - "mio", + "mio 0.8.4", "num_cpus", "once_cell", - "parking_lot 0.11.1", + "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", + "socket2", "tokio-macros", "winapi", ] [[package]] name = "tokio-macros" -version = "1.3.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54473be61f4ebe4efd09cec9bd5d16fa51d70ea0192213d754d2d500457db110" +checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", ] [[package]] @@ -5050,9 +6107,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" dependencies = [ "indexmap", - "serde 1.0.130", + "serde 1.0.145", +] + +[[package]] +name = "toml_edit" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5376256e44f2443f8896ac012507c19a012df0fe8758b55246ae51a2279db51f" +dependencies = [ + "combine", + "indexmap", + "itertools 0.10.1", + "serde 1.0.145", ] +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + [[package]] name = "tracing" version = "0.1.26" @@ -5060,6 +6135,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d" dependencies = [ "cfg-if 1.0.0", + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -5071,18 +6147,29 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] [[package]] name = "tracing-core" -version = "0.1.21" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" dependencies = [ - "lazy_static 1.4.0", + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", ] [[package]] @@ -5098,13 +6185,13 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.3" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245da694cc7fc4729f3f418b304cb57789f1bed2a78c575407ab8a23f53cb4d3" +checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" dependencies = [ "ansi_term 0.12.1", - "lazy_static 1.4.0", "matchers", + "once_cell", "regex", "sharded-slab", "smallvec", @@ -5124,6 +6211,12 @@ dependencies = [ "rlp", ] +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + [[package]] name = "trybuild" version = "1.0.53" @@ -5132,7 +6225,7 @@ checksum = "9d664de8ea7e531ad4c0f5a834f20b8cb2b8e6dfe88d05796ee7887518ed67b9" dependencies = [ "glob", "lazy_static 1.4.0", - "serde 1.0.130", + "serde 1.0.145", "serde_json", "termcolor", "toml", @@ -5181,9 +6274,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" [[package]] name = "uint" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f03af7ccf01dd611cc450a0d10dbc9b745770d096473e2faf0ca6e2d66d1e0" +checksum = "a45526d29728d135c2900b0d30573fe3ee79fceb12ef534c7bb30e810a91b601" dependencies = [ "byteorder", "crunchy", @@ -5191,6 +6284,15 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "uncased" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622" +dependencies = [ + "version_check", +] + [[package]] name = "unic-char-property" version = "0.9.0" @@ -5250,6 +6352,12 @@ dependencies = [ "matches", ] +[[package]] +name = "unicode-ident" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" + [[package]] name = "unicode-normalization" version = "0.1.17" @@ -5309,7 +6417,7 @@ dependencies = [ "idna", "matches", "percent-encoding", - "serde 1.0.130", + "serde 1.0.145", ] [[package]] @@ -5318,6 +6426,22 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372" +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "value-bag" +version = "1.0.0-alpha.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" +dependencies = [ + "ctor", + "version_check", +] + [[package]] name = "variant_count" version = "1.1.0" @@ -5325,9 +6449,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae2faf80ac463422992abf4de234731279c058aaf33171ca70277c98406b124" dependencies = [ "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "vec_map" version = "0.8.2" @@ -5357,7 +6487,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", ] @@ -5370,6 +6500,12 @@ dependencies = [ "libc", ] +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + [[package]] name = "walkdir" version = "2.3.2" @@ -5381,6 +6517,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -5393,6 +6539,12 @@ version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wasm-bindgen" version = "0.2.71" @@ -5412,12 +6564,24 @@ dependencies = [ "bumpalo", "lazy_static 1.4.0", "log", - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e67a5806118af01f0d9045915676b22aaebecf4178ae7021bc171dab0b897ab" +dependencies = [ + "cfg-if 1.0.0", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.71" @@ -5434,9 +6598,9 @@ version = "0.2.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5457,11 +6621,30 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "wepoll-ffi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" +dependencies = [ + "cc", +] + +[[package]] +name = "whoami" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524b58fa5a20a2fb3014dd6358b70e6579692a56ef6fce928834e488f42f65e8" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + [[package]] name = "widestring" -version = "0.4.3" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" +checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" [[package]] name = "winapi" @@ -5494,6 +6677,58 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + [[package]] name = "wyz" version = "0.2.0" @@ -5530,7 +6765,7 @@ dependencies = [ "nextest-runner", "rayon", "regex", - "serde 1.0.130", + "serde 1.0.145", "serde_json", "supports-color", "toml", @@ -5551,7 +6786,7 @@ dependencies = [ "log", "once_cell", "ouroboros", - "serde 1.0.130", + "serde 1.0.145", "toml", ] @@ -5562,7 +6797,7 @@ dependencies = [ "camino", "guppy", "once_cell", - "serde 1.0.130", + "serde 1.0.145", "toml", "x-core", ] @@ -5613,8 +6848,8 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdff2024a851a322b08f179173ae2ba620445aef1e838f0c196820eade4ae0c7" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.43", "quote 1.0.9", - "syn 1.0.74", + "syn 1.0.99", "synstructure", ] diff --git a/Cargo.toml b/Cargo.toml index 82231f04a4..ef9b55931e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ members = [ "language/move-borrow-graph", "language/move-bytecode-verifier", "language/move-bytecode-verifier/bytecode-verifier-tests", + "language/move-bytecode-verifier/fuzz", "language/move-bytecode-verifier/invalid-mutations", "language/move-bytecode-verifier/transactional-tests", "language/move-command-line-common", @@ -51,6 +52,7 @@ members = [ "language/move-stdlib", "language/move-symbol-pool", "language/move-vm/integration-tests", + "language/move-vm/paranoid-tests", "language/move-vm/runtime", "language/move-vm/test-utils", "language/move-vm/transactional-tests", @@ -72,7 +74,7 @@ members = [ "language/tools/read-write-set/types", ] -# NOTE: default-members is the complete list of binaries that form the "production Diem codebase". These members should +# NOTE: default-members is the complete list of binaries that form the "production Move codebase". These members should # never include crates that require fuzzing features or test features. These are the crates we want built with no extra # test-only code included. # @@ -95,8 +97,9 @@ default-members = [ "language/tools/move-unit-test", ] -# [profile.release] -# debug = true +# Dependencies that should be kept in sync through the whole workspace +[workspace.dependencies] +bcs = "0.1.4" [profile.bench] debug = true @@ -107,7 +110,6 @@ debug = true # use release settings to reduce memory pressure in the linking step in CI [profile.ci] inherits = "test" -opt-level = 3 debug = 0 # for saving disk space during linking incremental = false codegen-units = 16 diff --git a/GRAVEYARD.md b/GRAVEYARD.md new file mode 100644 index 0000000000..d947d6e591 --- /dev/null +++ b/GRAVEYARD.md @@ -0,0 +1,54 @@ +# Language feature idea graveyard + +Move is a smart contract language that counts minimalism as one of its guiding principles. Features are often proposed, but not always implemented. This list exists to record feature proposals that did not progress to acceptance. The goal of maintaining this list is to avoid duplicate proposals, and to explain the rationale for not moving forward with an idea that might seem promising at first blush. + +## Pure data structs + +### Decision +We should let adapters decide how to handle this + +### Rationale +Structs being passed to transactions cause safety issues because deserialization can circumvent modular encapsulation. For example, below make is the only way to create S and the program guarantees that field x is always greater zero; however, if S is obtained via deserialization, this constraint can be violated:: +``` +struct S has drop, copy { x: u64 } +public fun make(x: u64) { assert!(x > 0); S{x} } + +fun(entry) foo(s: S/*no guarantee about s.x*/) { … } +``` + +## Native structs + +### Decision +This is obsolete as regular structs can be used from native code, e.g. struct S { native_handle: u128 } + +### Rationale +As Move evolves to an extensible language, native structs are an important tool for extensibility. However, support for native structs has been removed from the VM (though still supported in compiler and file format). + +### Design +Bring back support for native structs in the VM. They can use a simple uniform representation via handles which are managed by the runtime environment (like u128 or u256 for each and every native struct value), so implementation effort should be small. + +## Signer relaxation for `move_to` + +### Decision +Tables and framework-specific workarounds like `ResourceAccount` make this unneccessary. + +### Rationale +In some usage scenarios of Move, it does not make sense to only allow move_to(s, x) with s a signer. For instance, when Move is running on the EVM, storage is not owned and paid for by the account owner, but by the contract caller, which manages the accounts on behalf of owners. In general, the signer requirement allows one to only create new resources at addresses for which the transaction has a signer, which disables the capability to manage resource collections on behalf of others. + +## Design (Option A) +Drop the requirement of passing a signer to move-to all together. For downwards compatibility reasons, the compiler allows passing either a signer or an address. Rationale for this quite radical step is that in-real world contracts (e.g. the Diem Payment Network) more complex access control patterns than enabled by signer/move_to are needed anyway. Moreover, since only modules which declare a resource R can call move_to, preventing publishing without a signer can still be modeled by modular encapsulation. + +### Design (Option B) +Use an attribute on struct declarations to indicate a signer is not required for publishing this struct. + +### Design (Option C) +Have another function which does not require a signer, e.g. move_to_address. This, however, raises questions of adequate naming and methodology (when to use which function, should there be constraints when which function is allowed, etc.) + +### Design (Option D) +Add no new features and ask clients that want this feature (e.g., the Move -> EVM compilation effort) to implement it via design patterns and/or native functions. See SignerCapability in the Starcoin Account code for one example of a design pattern for (effectively) implementing move_to_address without changing the language. + +### Design (Option E) +Support this via a new internal ability that allows framework designers to implement more powerful native functions with the same encapsulation guarantees as bytecodes. For example, the framework designer can define a function `public native fun move_to_address(a: address, t: T)` that can only be invoked on `T`’s declared in the calling module. + +### Design (Option F) +Use tables when there is a need to index storage without signer. diff --git a/README.md b/README.md index 29eacaceec..69fd0f4313 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ [![License](https://img.shields.io/badge/license-Apache-green.svg)](LICENSE) -[![Discord chat](https://img.shields.io/discord/903339070925721652.svg?logo=discord&style=flat-square)](https://discord.gg/M95qX3KnG8) +[![Discord chat](https://img.shields.io/discord/964205366541963294.svg?logo=discord&style=flat-square)](https://discord.gg/zamKKnZBZp) +![Move logo](assets/color/SVG/Move_Logo_Design_Digital_Final_-01.svg) # The Move Language @@ -21,9 +22,11 @@ docker build -t move/cli -f docker/move-cli/Dockerfile . ``` cd ./language/documentation/tutorial/step_1/BasicCoin -docker run -v `pwd`:/project move/cli package build +docker run -v `pwd`:/project move/cli build ``` +Follow the [language/documentation/tutorial](./language/documentation/tutorial/README.md) to set up move for development. + ## Community * Join us on the [Move Discord](https://discord.gg/cPUmhe24Mz). diff --git a/assets/color/AI/Move_Logo_Design_GreyScale_Digital_Final.ai b/assets/color/AI/Move_Logo_Design_GreyScale_Digital_Final.ai new file mode 100644 index 0000000000..3919fe2b2f --- /dev/null +++ b/assets/color/AI/Move_Logo_Design_GreyScale_Digital_Final.ai @@ -0,0 +1,1561 @@ +%PDF-1.6 % +1 0 obj <>/OCGs[26 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream + + + + + application/pdf + + + Move_Logo Design_GreyScale_Digital_Final + + + Adobe Illustrator 25.0 (Macintosh) + 2020-12-02T14:23:27-08:00 + 2020-12-02T14:23:27-08:00 + 2020-12-02T14:23:27-08:00 + + + + 220 + 256 + JPEG + /9j/4AAQSkZJRgABAgEBLAEsAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABABLAAAAAEA AQEsAAAAAQAB/+IMWElDQ19QUk9GSUxFAAEBAAAMSExpbm8CEAAAbW50clJHQiBYWVogB84AAgAJ AAYAMQAAYWNzcE1TRlQAAAAASUVDIHNSR0IAAAAAAAAAAAAAAAAAAPbWAAEAAAAA0y1IUCAgAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARY3BydAAAAVAAAAAz ZGVzYwAAAYQAAABsd3RwdAAAAfAAAAAUYmtwdAAAAgQAAAAUclhZWgAAAhgAAAAUZ1hZWgAAAiwA AAAUYlhZWgAAAkAAAAAUZG1uZAAAAlQAAABwZG1kZAAAAsQAAACIdnVlZAAAA0wAAACGdmlldwAA A9QAAAAkbHVtaQAAA/gAAAAUbWVhcwAABAwAAAAkdGVjaAAABDAAAAAMclRSQwAABDwAAAgMZ1RS QwAABDwAAAgMYlRSQwAABDwAAAgMdGV4dAAAAABDb3B5cmlnaHQgKGMpIDE5OTggSGV3bGV0dC1Q YWNrYXJkIENvbXBhbnkAAGRlc2MAAAAAAAAAEnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAS c1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbMWFlaIAAAAAAAAAAAAAAAAAAAAABYWVogAAAA AAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9kZXNj AAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gAAAAAAAAAAAAAABZJRUMgaHR0cDovL3d3dy5p ZWMuY2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGVzYwAA AAAAAAAuSUVDIDYxOTY2LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAA AAAAAAAuSUVDIDYxOTY2LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAA AAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlvbiBp biBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4g SUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2aWV3AAAAAAATpP4AFF8uABDP FAAD7cwABBMLAANcngAAAAFYWVogAAAAAABMCVYAUAAAAFcf521lYXMAAAAAAAAAAQAAAAAAAAAA AAAAAAAAAAAAAAKPAAAAAnNpZyAAAAAAQ1JUIGN1cnYAAAAAAAAEAAAAAAUACgAPABQAGQAeACMA KAAtADIANwA7AEAARQBKAE8AVABZAF4AYwBoAG0AcgB3AHwAgQCGAIsAkACVAJoAnwCkAKkArgCy ALcAvADBAMYAywDQANUA2wDgAOUA6wDwAPYA+wEBAQcBDQETARkBHwElASsBMgE4AT4BRQFMAVIB WQFgAWcBbgF1AXwBgwGLAZIBmgGhAakBsQG5AcEByQHRAdkB4QHpAfIB+gIDAgwCFAIdAiYCLwI4 AkECSwJUAl0CZwJxAnoChAKOApgCogKsArYCwQLLAtUC4ALrAvUDAAMLAxYDIQMtAzgDQwNPA1oD ZgNyA34DigOWA6IDrgO6A8cD0wPgA+wD+QQGBBMEIAQtBDsESARVBGMEcQR+BIwEmgSoBLYExATT BOEE8AT+BQ0FHAUrBToFSQVYBWcFdwWGBZYFpgW1BcUF1QXlBfYGBgYWBicGNwZIBlkGagZ7BowG nQavBsAG0QbjBvUHBwcZBysHPQdPB2EHdAeGB5kHrAe/B9IH5Qf4CAsIHwgyCEYIWghuCIIIlgiq CL4I0gjnCPsJEAklCToJTwlkCXkJjwmkCboJzwnlCfsKEQonCj0KVApqCoEKmAquCsUK3ArzCwsL Igs5C1ELaQuAC5gLsAvIC+EL+QwSDCoMQwxcDHUMjgynDMAM2QzzDQ0NJg1ADVoNdA2ODakNww3e DfgOEw4uDkkOZA5/DpsOtg7SDu4PCQ8lD0EPXg96D5YPsw/PD+wQCRAmEEMQYRB+EJsQuRDXEPUR ExExEU8RbRGMEaoRyRHoEgcSJhJFEmQShBKjEsMS4xMDEyMTQxNjE4MTpBPFE+UUBhQnFEkUahSL FK0UzhTwFRIVNBVWFXgVmxW9FeAWAxYmFkkWbBaPFrIW1hb6Fx0XQRdlF4kXrhfSF/cYGxhAGGUY ihivGNUY+hkgGUUZaxmRGbcZ3RoEGioaURp3Gp4axRrsGxQbOxtjG4obshvaHAIcKhxSHHscoxzM HPUdHh1HHXAdmR3DHeweFh5AHmoelB6+HukfEx8+H2kflB+/H+ogFSBBIGwgmCDEIPAhHCFIIXUh oSHOIfsiJyJVIoIiryLdIwojOCNmI5QjwiPwJB8kTSR8JKsk2iUJJTglaCWXJccl9yYnJlcmhya3 JugnGCdJJ3onqyfcKA0oPyhxKKIo1CkGKTgpaymdKdAqAio1KmgqmyrPKwIrNitpK50r0SwFLDks biyiLNctDC1BLXYtqy3hLhYuTC6CLrcu7i8kL1ovkS/HL/4wNTBsMKQw2zESMUoxgjG6MfIyKjJj Mpsy1DMNM0YzfzO4M/E0KzRlNJ402DUTNU01hzXCNf02NzZyNq426TckN2A3nDfXOBQ4UDiMOMg5 BTlCOX85vDn5OjY6dDqyOu87LTtrO6o76DwnPGU8pDzjPSI9YT2hPeA+ID5gPqA+4D8hP2E/oj/i QCNAZECmQOdBKUFqQaxB7kIwQnJCtUL3QzpDfUPARANER0SKRM5FEkVVRZpF3kYiRmdGq0bwRzVH e0fASAVIS0iRSNdJHUljSalJ8Eo3Sn1KxEsMS1NLmkviTCpMcky6TQJNSk2TTdxOJU5uTrdPAE9J T5NP3VAnUHFQu1EGUVBRm1HmUjFSfFLHUxNTX1OqU/ZUQlSPVNtVKFV1VcJWD1ZcVqlW91dEV5JX 4FgvWH1Yy1kaWWlZuFoHWlZaplr1W0VblVvlXDVchlzWXSddeF3JXhpebF69Xw9fYV+zYAVgV2Cq YPxhT2GiYfViSWKcYvBjQ2OXY+tkQGSUZOllPWWSZedmPWaSZuhnPWeTZ+loP2iWaOxpQ2maafFq SGqfavdrT2una/9sV2yvbQhtYG25bhJua27Ebx5veG/RcCtwhnDgcTpxlXHwcktypnMBc11zuHQU dHB0zHUodYV14XY+dpt2+HdWd7N4EXhueMx5KnmJeed6RnqlewR7Y3vCfCF8gXzhfUF9oX4BfmJ+ wn8jf4R/5YBHgKiBCoFrgc2CMIKSgvSDV4O6hB2EgITjhUeFq4YOhnKG14c7h5+IBIhpiM6JM4mZ if6KZIrKizCLlov8jGOMyo0xjZiN/45mjs6PNo+ekAaQbpDWkT+RqJIRknqS45NNk7aUIJSKlPSV X5XJljSWn5cKl3WX4JhMmLiZJJmQmfyaaJrVm0Kbr5wcnImc951kndKeQJ6unx2fi5/6oGmg2KFH obaiJqKWowajdqPmpFakx6U4pammGqaLpv2nbqfgqFKoxKk3qamqHKqPqwKrdavprFys0K1Erbiu La6hrxavi7AAsHWw6rFgsdayS7LCszizrrQltJy1E7WKtgG2ebbwt2i34LhZuNG5SrnCuju6tbsu u6e8IbybvRW9j74KvoS+/796v/XAcMDswWfB48JfwtvDWMPUxFHEzsVLxcjGRsbDx0HHv8g9yLzJ Osm5yjjKt8s2y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc 1+DYZNjo2WzZ8dp22vvbgNwF3IrdEN2W3hzeot8p36/gNuC94UThzOJT4tvjY+Pr5HPk/OWE5g3m lucf56noMui86Ubp0Opb6uXrcOv77IbtEe2c7ijutO9A78zwWPDl8XLx//KM8xnzp/Q09ML1UPXe 9m32+/eK+Bn4qPk4+cf6V/rn+3f8B/yY/Sn9uv5L/tz/bf///+4ADkFkb2JlAGTAAAAAAf/bAIQA BgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoKDBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8f Hx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f Hx8fHx8fHx8fHx8fHx8f/8AAEQgBAADcAwERAAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQF AwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMB AgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPBUtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdU ZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eX p7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZqbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUE BQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEyobHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PS NeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG 1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/a AAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7 FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7F XYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FX Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXY q7FXYq7FXYq7FXYq7FXYq7FXYqsmuIIFDTSJEpNAXYKCfpxVR/Sem/8ALXD/AMjE/rhpFu/Sem/8 tcP/ACMT+uNLbv0npv8Ay1w/8jE/rjS279J6b/y1w/8AIxP640tu/Sem/wDLXD/yMT+uNLbv0npv /LXD/wAjE/rjS279J6b/AMtcP/IxP640tu/Sem/8tcP/ACMT+uNLbv0npv8Ay1w/8jE/rjS279J6 b/y1w/8AIxP640tu/Sem/wDLXD/yMT+uNLbv0npv/LXD/wAjE/rjS22uo6e7BEuomZjRVDqSSegA rjSbRGBXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq8G/5y/8A+UI0b/tpj/qHkzJ03MtGfk+TszXE dirsVdirsVdirsVdirsVdirsVdirJvyy/wDJk+U/+2zp/wD1FR5DJ9J9zOH1B+gmaxz3Yq7FXYq7 FXYq7FXYq7FXYq7FXYq7FXYq8G/5y/8A+UI0b/tpj/qHkzJ03MtGfk+TszXEdirsVdirsVdirsVd irsVdirsVdirJvyy/wDJk+U/+2zp/wD1FR5DJ9J9zOH1B+gmaxz3Yq7FXYq7FXYq7FXYq7FXYq7F XYq7FXYq8G/5y/8A+UI0b/tpj/qHkzJ03MtGfk+TszXEdirsVdirsVdirsVdirsVdirsVdirJvyy /wDJk+U/+2zp/wD1FR5DJ9J9zOH1B+gmaxz3Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq8G/5y/8A +UI0b/tpj/qHkzJ03MtGfk+TszXEdirsVdirsVdirsVdirsVdirsVdirJvyy/wDJk+U/+2zp/wD1 FR5DJ9J9zOH1B+gmaxz3Yq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq8G/5y/8A+UI0b/tpj/qHkzJ0 3MtGfk+TszXEdirsVdirsVdirsVdirsVdirsVdirJvyy/wDJk+U/+2zp/wD1FR5DJ9J9zOH1B+gm axz3Yq7FXYq7FUqu/NOh2s5gluQZFNHCKzgHwJUEZkw0mSQsB12btXT45cMpb/NMLW7truFZ7aQS xN0Zf1HwOUTgYmjzczDmhljxQNhZZ6lp18rNZXUN0qEBzDIsgBPSvEmmAhtt1nqWnXwc2V1DdBKB zDIsnGvSvEmmJCLRGBLsVdirsVdirwb/AJy//wCUI0b/ALaY/wCoeTMnTcy0Z+T5OzNcR2KuxVdH HJLIscal5HIVEUEsSdgAB1xpSQBZZIPy484m39cWBIpy9P1I+dP9XlWvt1y3wJ9zgfypguuL72Pp Z3b3P1VIJGuuRX0FVjJyHUcQK1FMqOzng3uF36Pv/rf1P6tL9crT6twb1K0rThTl03wWmllxbXFt M0FzE8EyU5xSKUYVFRVTQ9DiqlhQ7FXYq7FWTfll/wCTJ8p/9tnT/wDqKjyGT6T7mcPqD9BM1jnu xV2KvLvz983eaPLmgWD6FK1qt1O0d3eooZkCrVEBYELz3367ZvuwNJizZJeILobBwtbllCI4XjWh /mj+YFzf28Nxr10YpJFVxyAqCaUqAOudPn7L00YkiEXSanWZRA1I8mbQXl1UH1CTmulAPJmRek/l /NP9ZniNRG0Qdl7BwQB+s5ou0oigfN6X2cnLxJR/h4b+Nh8t/lt5x1TyDoeqXvxm081aZc2+nMgP w6hbSelGff01lLf7IZRkiJH3PRQlwj3p9+WOr+avJd9qHkzSJIbTXdY1m00yXUbhBJHbGNHEpEZI Dvyei16098jkAlueVMoEx2Zrqf5tfmT5Z81T6RrOoW19YeXNUsYdb1CG2SIT2OooHDuvxCJoaU+A 7lqGtK5WMcSLHVmckgd+iWSfnn+ZOpaulrpbypY6zd3k2kS2mnLqF0un2rPHGIoFKeoWdG9Qsdgt R3w+DEDdHiyL2T8oPNfmjzJ5Ue58zafLYavaXUlpL60D2pmVFV1mETiq1D8SBtUHKMsQDs3Y5Ejd m+Vs3Yq8G/5y/wD+UI0b/tpj/qHkzJ03MtGfk+TszXEdiqd6NY2c1sZJFEknIgg9vozpOyNFhyYu KQ4pX8nFz5JA0GeeQdI0sat631dBNFEzRNTcEkKSPoOZOq0eKABjEB0vaWefBV7EvS1ij4E0oR0O a6cRToLNsS0i2tIf+cgfLUkNBLOjSXCj+cQzKGPuVUZpdYOb1/YM5HHR6S2ehnTdI/xgPzcov1Q6 abYxVHIaoJxYjfw4n0v86Zg2a4Xe1vxMa/OLy15H0nWNX85eZtOudbfUdRtdPt7OC4NskKJYRMzl kBYueDUU9dunXJY5EigxmANyo6l+QHlS4mj07Q1ma9sNWtP0q0sjGX9FXa+oSyfZV0qVBAGy774R lPVTjCvJ+Uf5P24tbi5aCGx1qacWs1zqotGhhhb00a1SQN9YZtnfm3wk/Rg8SSeCL598x6XBpWv6 jptvcpe29ncSww3cZDJKiMQrgio+Ib7Zkg2GgiiluFDJvyy/8mT5T/7bOn/9RUeQyfSfczh9QfoJ msc92KuxVZPBBPE0M8ayxPs0bgMp77g7YYyINhBFoP8AQGhf9W21/wCRMf8AzTlv5jJ/Ol8yxOOJ 6BILr8urFrgyWtx9XiJr6RQPx/1TVczYdpyqpCy8/m9nYSlcJcI7qv8ASn+j6LaaVAY4as70Mkrd WI+XYZh588shsu10Oghpo1HmeZYtD+Sv5dRaXpemDTS1no121/YI8srFZnKs3Ji1WVigqp22yHiy ty/DC7Ufya/L7URqhu9PZ5NXu11C6mE0qyLdJy4yRMGBjP7xtl2xGWQU4wV1n+T3kK18ual5fFi8 1lrDJJqks00klxO8bBkZ5mbn8LLUUIp9JxOWV2vhiqW6l+TnkK+0XStJaykt4dEVl0u4tppIbiEO avSVTyPM7nlXfEZZA2pximQ+WfK+h+WNIi0jRLYWtjEzOE5M7M7nkzu7lnZie5P4ZGUiTZZCIHJN cil2KvBv+cv/APlCNG/7aY/6h5MydNzLRn5Pk7M1xHYquV3X7LFa9aGmSjMx5GlIRmma1qWm3sV5 aTss0RqKklSO4YdwcmM8weZasuCGSJjIbFna/nPdC24/oxDc0/vDMfTr48ONfo5ZcdWSOTpv5Cjf 1be78fcxKz86eYbPzRH5nguANXicvFMyKyrVClAjArQKaDMSfq5u7wYo4oiMeQRX/KxfN36F/Qv1 3/cd9e/Sfo8E/wB6OfqVrSvHn8XHpXIcAu23iKcW/wCeH5hxX97eveQ3LahJHPPDPbxSQiaGNYkl SMrRHCRruvWm+Dwop8QoLTvzb8/6fq+q6vb6o36Q1lVXUJnSNuQQEJxBWicAaLxpTCcYqlEyu8u/ m7568v6PHpGn3kf1S2ZnsvXghne3ZzVjC0isVqfowHGCbUTIYhcXE9zPJcXEjSzzO0ksrkszOxqz MT1JJybFTwoZN+WX/kyfKf8A22dP/wCoqPIZPpPuZw+oP0EzWOe7FXYq7FXYq7FXYq7FXYq7FXYq 7FXYq7FXg3/OX/8AyhGjf9tMf9Q8mZOm5loz8nydma4jsVdirsVdirsVdirsVdirsVdirsVZN+WX /kyfKf8A22dP/wCoqPIZPpPuZw+oP0EzWOe7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXg3/OX/8A yhGjf9tMf9Q8mZOm5loz8nydma4jsVdirsVdirsVdirsVdirsVdirsVZN+WX/kyfKf8A22dP/wCo qPIZPpPuZw+oP0EzWOe7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXg3/OX/8AyhGjf9tMf9Q8mZOm 5loz8nydma4jsVdirsVdirsVdirsVdirsVdirsVZN+WX/kyfKf8A22dP/wCoqPIZPpPuZw+oP0Ez WOe7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXg3/OX/8AyhGjf9tMf9Q8mZOm5loz8nydma4jsVdi rsVdirsVdirsVdirsVdirsVZN+WX/kyfKf8A22dP/wCoqPIZPpPuZw+oP0EzWOe7FXYq7FXYq7FX Yq7FXYq7FXYq7FXYq7FXg3/OX/8AyhGjf9tMf9Q8mZOm5loz8nydma4jsVdirsVdirsVdirsVdir sVdirsVZN+WX/kyfKf8A22dP/wCoqPIZPpPuZw+oP0EzWOe7FXYq7FXYq7FXYq7FXYq7FXYq7FXY q7FWB/m//wAqr/Qll/ysf/jl/Wf9D/3s/wB6PTb/AJY/j+xy+1tlmLiv0teThr1PJv8ArDH/AD/T mX/vfxTV+7/Fu/6wx/z/AE5j+9/FL+7/ABbv+sMf8/05j+9/FL+7/Fu/6wx/z/TmP738Uv7v8W7/ AKwx/wA/05j+9/FL+7/Fu/6wx/z/AE5j+9/FL+7/ABbv+sMf8/05j+9/FL+7/Fu/6wx/z/TmP738 Uv7v8W7/AKwx/wA/05j+9/FL+7/Fu/6wx/z/AE5j+9/FL+7/ABbv+sMf8/05j+9/FL+7/Fu/6wx/ z/TmP738Uv7v8Wmflj/oUr/Emk/oL/jt/XLf9F/8dn/er1V9D+9/d/3lPt/D47ZGXi1v+hMfDvb9 L6CzGch2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KvBv8AnL//AJQjRv8Atpj/AKh5MydNzLRn5Pk7 M1xHYq7FXYq7FXYq7FXYq7FXYq7FXYqyb8sv/Jk+U/8Ats6f/wBRUeQyfSfczh9QfoJmsc92KuxV 2KuxV2KuxV2KuxV2KuxV2KuxV2KvBv8AnL//AJQjRv8Atpj/AKh5MydNzLRn5Pk7M1xHYq7FXYq7 FXYq7FXYq7FXYq7FXYqyb8sv/Jk+U/8Ats6f/wBRUeQyfSfczh9QfoJmsc92KuxV2KuxV2KuxV2K uxV2KuxV2KuxV2KvBv8AnL//AJQjRv8Atpj/AKh5MydNzLRn5Pk7M1xHYq7FXYq7FXYq7FXYq7FX Yq7FXYqyb8sv/Jk+U/8Ats6f/wBRUeQyfSfczh9QfoJmsc92KuxV2KuxV2KuxV2KuxV2KuxV2Kux V2KvBv8AnL//AJQjRv8Atpj/AKh5MydNzLRn5Pk7M1xHYq7FXYq7FXYq7FXYq7FXYq7FXYqyb8sv /Jk+U/8Ats6f/wBRUeQyfSfczh9QfoJmsc92KuxV2KuxV2KuxVQvr+zsYDPdSiKIbVPUnwAG5OTx 45TNRFtOfPDFHimaDGpvzCsg5ENrJIn8zME/D4s2A7MlW5Do8ntFjB9MSR8v1ozTvOml3biOYNau 2wL0Kf8ABDp9IynLoJx3G7fpu3cOQ1L0Hz5fNkAIIqOmYTu3Yq7FXYq8G/5y/wD+UI0b/tpj/qHk zJ03MtGfk+TszXEdirsVdirsVdiqc+X/AClrWuufqUQEKmj3Mh4xg+FaEk+wGWY8UpcnF1Otx4fq O/d1ZfH+TV0YqtqiCX+UQkr/AMFzB/DL/wAoe91h7cF/Tt7/ANjG/MfkLX9CjNxPGtxZjrcw1ZVr 05ggMv6vfKJ4jFz9L2jizGhtLuLG8rc52KuxVk35Zf8AkyfKf/bZ0/8A6io8hk+k+5nD6g/QTNY5 7sVdirsVYV+Yn5r+X/JKxQ3SPeancLzhsYSAeFac5HOyKSKDqT4ZtOzuycmqsjaI6lx8+pjj583n Q/5ynqaf4Y/6fv8As3zdf6Ff9s/2P/HnE/lL+j9v7FdP+cneW/8Ahun/AEe/9m+RPsvX+U/2P/Hm s9q1/D9v7FfVvO15rc6XVxbegOACWok5iOoqRy4rU16mmODRRxCgb83lO0O0JZ8ln6RyCGj1X/ir /hv7MsOJ15yJjazpMnJe3UHqMpnGlBtnvkrVZJonsJm5NCvKEnrwrQr9BpTNLr8IB4h1eu9n9aZg 4pfw7j3fsZPmvekdirsVeDf85f8A/KEaN/20x/1DyZk6bmWjPyfJ2ZriOxV2KplZ6JNPEJHcRK26 ilSR402zcaTsaeWPFI8IPxaJ5wDSKTyzyNPrNP8AYf8AN2ZR9n/6f+x/a1nVeSYaZ5EN7ew2/wBc I9RgGpHvxG7H7XgDlWTsXgF8f2ftaMvaPBEmvtez6fpVrZWkVpaqIreFQsaAdB/XxOIxACg8pkzG cjKW5KMW1NNm3+WRMGrjaeFJI3hmQPG4KyRsAVIOxBB6g5RIJEqNh4F578upoPmKa0hBFrKBPa17 RuT8P+xYEZrskeEvadn6nxsQkefIseyDmuxVk35Zf+TJ8p/9tnT/APqKjyGT6T7mcPqD9BM1jnux V2KuxV8of85BWl9D+Zl9LcKwguYbeSzJ6GNYVjan/PRHz0H2fnE6WIHME38/1U6TWg+IXnKfaGbs uGUxtSoZS26ggkewynJyLjzerxkEVG4PQ5oS80URHkCwKa6SG5Of2aAfTlGVlBmvkpXOr1HRYmLf KoH681WvPo+LvvZ8E6jb+aWd5pnt3Yq7FXg3/OX/APyhGjf9tMf9Q8mZOm5loz8nydma4jsVdirM Y2R41ZN0IBWnhnoeOQlEGPIusIoq8P2skWEmS+UmVdZg5ftBwvz4HMLWD0Ou1o/dl6EmakukKITI FgVkpBk2+nMbJzTHk8f/ADpliOuWEY/vUtqv8mkbj+o5gajm9R2ED4cj/S/Q87yh3jsVZN+WX/ky fKf/AG2dP/6io8hk+k+5nD6g/QTNY57sVdirsVSXzV5M8t+abNbTXLNbpIyTDJUpJGT1KOpDCtNx 0PfMrS63Lp5XjNNeTFGYqQYaP+cd/wAtwa+jdf8ASQ39M2f+iLVd8fk4/wCRxqi/kB+Xa9Ibr/ke 39Mj/og1PePkxPZ2I96B8wfl5b6MqPZLJLpyqFBZuTx0FKOadPA5kaXtE5dpfU8x2t2UcUuOIuB+ xJU0628D9+ZZyF0ZgEwtYN1ihQksaKiipJOUzl1KYwJNAbvRfK+iPp1oZJxS6noXX+VR0X+uaLV5 +OVDkHuOx+zzp4Ey+uX2eSd5iO4dirsVeDf85f8A/KEaN/20x/1DyZk6bmWjPyfJ2ZriOxV2Koq2 1K7t14Rv8H8pFRmbp+0M2EVE7dzCWKMuaIXX9QU7Mv8AwOZH8tZ/L5NZ08URbebtYtpo5o2QPGwZ ar3BrkZdrZpCjXyYT0WOQovZvLPmyy12xWe2cLOoAuLYkc42+X8vgctx6jjFh5TV6OWGVHl0KerP Idq0wmRcPhCC1jXNO0awe9v5RHGv2V/bduyoO5OUTkALLdg088suGIeA+YtbuNb1i41KccTM3wR9 QiKKKv0DNfOVm3tNNpxixiA6JbkW92Ksm/LL/wAmT5T/AO2zp/8A1FR5DJ9J9zOH1B+gmaxz3Yq7 FXYq7FXYq7FXEAih3B6jFUqn8raBO5d7NAx3PAsg+5CozJjq8oFCTr8nZWmmbMB9o+5FWWkaZY72 tukTdOYFW/4I1OV5M05/UW/BosWL6Igff80XlTkuxV2KuxV4N/zl/wD8oRo3/bTH/UPJmTpuZaM/ J8nZmuI7FXYq7FXYq7FVW2urm1mWe2leCZfsyRsVYfSMQSOTGcBIURYT5PzD85JF6Y1JuPiUiLf8 EU5fjlvjz73DPZmAm+H70lv9Sv8AUJvXvbiS5l6B5WLEDwFegysyJ5uXjxRgKiKCGwM3Yq7FWTfl l/5Mnyn/ANtnT/8AqKjyGT6T7mcPqD9BM1jnuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV4N/zl// AMoRo3/bTH/UPJmTpuZaM/J8nZmuI7FXYq7FXYq7FXYq7FXYq7FXYq7FWTfll/5Mnyn/ANtnT/8A qKjyGT6T7mcPqD9BM1jnuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV4N/zl//AMoRo3/bTH/UPJmT puZaM/J8nZmuI7FXYq7FXYq7FXYq7FXYq7FXYq7FWTfll/5Mnyn/ANtnT/8AqKjyGT6T7mcPqD9B M1jnuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV4N/zl//AMoRo3/bTH/UPJmTpuZaM/J8nZmuI7FX Yq7FXYq7FXYq7FXYq7FXYq7FWTfll/5Mnyn/ANtnT/8AqKjyGT6T7mcPqD9BM1jnuxV2KuxV2Kux V2KuxV2KuxV2KuxV2KuxV4N/zl//AMoRo3/bTH/UPJmTpuZaM/J8nZmuI7FXYq7FXYq7FXYq7FXY q7FXYq7FWTfll/5Mnyn/ANtnT/8AqKjyGT6T7mcPqD9BM1jnv//Z + + + + proof:pdf + uuid:65E6390686CF11DBA6E2D887CEACB407 + xmp.did:1bf257e2-7ee0-4f9f-8d89-592b6363757d + uuid:9d841657-08ba-b848-9db1-8f716b640d2e + + xmp.iid:5f10993d-fbcb-4845-8da8-c8fd23bf9b15 + xmp.did:5f10993d-fbcb-4845-8da8-c8fd23bf9b15 + uuid:65E6390686CF11DBA6E2D887CEACB407 + default + + + + + saved + xmp.iid:104773b8-b239-4d7c-827a-5a8a0e6556a6 + 2020-12-02T12:45:36-08:00 + Adobe Illustrator 25.0 (Macintosh) + / + + + saved + xmp.iid:1bf257e2-7ee0-4f9f-8d89-592b6363757d + 2020-12-02T14:23:26-08:00 + Adobe Illustrator 25.0 (Macintosh) + / + + + + Web + AIRobin + Document + Adobe PDF library 15.00 + 21.0.0 + 1 + True + False + + 500.000000 + 500.000000 + Pixels + + + + + MyriadPro-Regular + Myriad Pro + Regular + Open Type + Version 2.106;PS 2.000;hotconv 1.0.70;makeotf.lib2.5.58329 + False + MyriadPro-Regular.otf + + + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + White + RGB + PROCESS + 255 + 255 + 255 + + + Black + RGB + PROCESS + 0 + 0 + 0 + + + RGB Red + RGB + PROCESS + 255 + 0 + 0 + + + RGB Yellow + RGB + PROCESS + 255 + 255 + 0 + + + RGB Green + RGB + PROCESS + 0 + 255 + 0 + + + RGB Cyan + RGB + PROCESS + 0 + 255 + 255 + + + RGB Blue + RGB + PROCESS + 0 + 0 + 255 + + + RGB Magenta + RGB + PROCESS + 255 + 0 + 255 + + + R=193 G=39 B=45 + RGB + PROCESS + 193 + 39 + 45 + + + R=237 G=28 B=36 + RGB + PROCESS + 237 + 28 + 36 + + + R=241 G=90 B=36 + RGB + PROCESS + 241 + 90 + 36 + + + R=247 G=147 B=30 + RGB + PROCESS + 247 + 147 + 30 + + + R=251 G=176 B=59 + RGB + PROCESS + 251 + 176 + 59 + + + R=252 G=238 B=33 + RGB + PROCESS + 252 + 238 + 33 + + + R=217 G=224 B=33 + RGB + PROCESS + 217 + 224 + 33 + + + R=140 G=198 B=63 + RGB + PROCESS + 140 + 198 + 63 + + + R=57 G=181 B=74 + RGB + PROCESS + 57 + 181 + 74 + + + R=0 G=146 B=69 + RGB + PROCESS + 0 + 146 + 69 + + + R=0 G=104 B=55 + RGB + PROCESS + 0 + 104 + 55 + + + R=34 G=181 B=115 + RGB + PROCESS + 34 + 181 + 115 + + + R=0 G=169 B=157 + RGB + PROCESS + 0 + 169 + 157 + + + R=41 G=171 B=226 + RGB + PROCESS + 41 + 171 + 226 + + + R=0 G=113 B=188 + RGB + PROCESS + 0 + 113 + 188 + + + R=46 G=49 B=146 + RGB + PROCESS + 46 + 49 + 146 + + + R=27 G=20 B=100 + RGB + PROCESS + 27 + 20 + 100 + + + R=102 G=45 B=145 + RGB + PROCESS + 102 + 45 + 145 + + + R=147 G=39 B=143 + RGB + PROCESS + 147 + 39 + 143 + + + R=158 G=0 B=93 + RGB + PROCESS + 158 + 0 + 93 + + + R=212 G=20 B=90 + RGB + PROCESS + 212 + 20 + 90 + + + R=237 G=30 B=121 + RGB + PROCESS + 237 + 30 + 121 + + + R=199 G=178 B=153 + RGB + PROCESS + 199 + 178 + 153 + + + R=153 G=134 B=117 + RGB + PROCESS + 153 + 134 + 117 + + + R=115 G=99 B=87 + RGB + PROCESS + 115 + 99 + 87 + + + R=83 G=71 B=65 + RGB + PROCESS + 83 + 71 + 65 + + + R=198 G=156 B=109 + RGB + PROCESS + 198 + 156 + 109 + + + R=166 G=124 B=82 + RGB + PROCESS + 166 + 124 + 82 + + + R=140 G=98 B=57 + RGB + PROCESS + 140 + 98 + 57 + + + R=117 G=76 B=36 + RGB + PROCESS + 117 + 76 + 36 + + + R=96 G=56 B=19 + RGB + PROCESS + 96 + 56 + 19 + + + R=66 G=33 B=11 + RGB + PROCESS + 66 + 33 + 11 + + + + + + Grays + 1 + + + + R=0 G=0 B=0 + RGB + PROCESS + 0 + 0 + 0 + + + R=26 G=26 B=26 + RGB + PROCESS + 26 + 26 + 26 + + + R=51 G=51 B=51 + RGB + PROCESS + 51 + 51 + 51 + + + R=77 G=77 B=77 + RGB + PROCESS + 77 + 77 + 77 + + + R=102 G=102 B=102 + RGB + PROCESS + 102 + 102 + 102 + + + R=128 G=128 B=128 + RGB + PROCESS + 128 + 128 + 128 + + + R=153 G=153 B=153 + RGB + PROCESS + 153 + 153 + 153 + + + R=179 G=179 B=179 + RGB + PROCESS + 179 + 179 + 179 + + + R=204 G=204 B=204 + RGB + PROCESS + 204 + 204 + 204 + + + R=230 G=230 B=230 + RGB + PROCESS + 230 + 230 + 230 + + + R=242 G=242 B=242 + RGB + PROCESS + 242 + 242 + 242 + + + + + + Web Color Group + 1 + + + + R=63 G=169 B=245 + RGB + PROCESS + 63 + 169 + 245 + + + R=122 G=201 B=67 + RGB + PROCESS + 122 + 201 + 67 + + + R=255 G=147 B=30 + RGB + PROCESS + 255 + 147 + 30 + + + R=255 G=29 B=37 + RGB + PROCESS + 255 + 29 + 37 + + + R=255 G=123 B=172 + RGB + PROCESS + 255 + 123 + 172 + + + R=189 G=204 B=212 + RGB + PROCESS + 189 + 204 + 212 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 3 0 obj <> endobj 5 0 obj <>/Resources<>/ExtGState<>/Properties<>/Shading<>/XObject<>>>/TrimBox[0.0 0.0 500.0 500.0]/Type/Page>> endobj 24 0 obj <>/Resources<>/ExtGState<>/Properties<>/Shading<>/XObject<>>>/TrimBox[0.0 0.0 500.0 500.0]/Type/Page>> endobj 25 0 obj <>/Resources<>/ExtGState<>/Properties<>/Shading<>/XObject<>>>/TrimBox[0.0 0.0 500.0 500.0]/Type/Page>> endobj 28 0 obj <>/Resources<>/ExtGState<>/Properties<>/Shading<>/XObject<>>>/TrimBox[0.0 0.0 500.0 500.0]/Type/Page>> endobj 46 0 obj <>stream +H|Wn7WNղK@p>(^@LW5Y˫u~tm_C3Uq+^݂ ĂR"?[?HE=R>Eżl1.֓!]) tMq(<6|'Ac#+#V?UF WߔR 㼂W-ԟph3z~l'DOw,SH@~J/ 0gֽ,adwےI^ъ$W|l0A@9/x=,l _BZmH +9^"H5[Eb~DS{ QjpLP@ *P)6"e{,XCQ3|QxL9^}D ZC7Bڢ>6#0un& WƮ%-dzf>ׅ=+ܬR#bށyǩ,ĩ,CP:L r Ug΁Q8ʤ=yBNxqa I +)v )diw2^x؁C&άd;)rdy™'z$2gVRñ.ZN3Ky53yht@bg +RqQGN_W-2oflYXL OEGGEe40*IzOfb84ڮiT@NU /ȜM>TOhl%щHn5qZ-jB +򦀴b[DS ʝ0u%sZ[hiX"vM0lH/h٤>v`D;5 I> HS[ +gHסABn}\IoIݎ‡C'}Sj$:PXC9`$Hա%8 GVA(a5*6]8}Ilݡv0x}hΔ_gT yQo,O4T?̜pSC@kI YCCF؍ hFj(D 뮣TUu u0wd]gMݩh$Ss>O: 8 8&nmE+gԓ5I89r{zHnqb"i6V-m?8G\'M˲cҷ=2@x?9Pc<6&rfp<^Z"ˎI߶|տoo1Gz"UK!Ky{=߯ Ղm~//}gw.ڻOSiOI` endstream endobj 47 0 obj <> endobj 48 0 obj <>/ExtGState<>>>/Subtype/Form>>stream +/CS0 cs 0 0 0 scn +/GS0 gs +q 1 0 0 1 182.1221 265.5083 cm +0 0 m +-29.316 0 l +-31.742 -4.637 -33.114 -9.913 -33.114 -15.508 c +-33.114 -21.507 -31.538 -27.138 -28.776 -32.008 c +0 -32.008 l +8.839 -32.008 16.004 -24.843 16.004 -16.004 c +16.004 -7.166 8.839 0 0 0 c +f +Q + endstream endobj 49 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +q +184.508 283.5 m +166.006 283.5 151.008 268.502 151.008 250 c +151.008 231.498 166.006 216.5 184.508 216.5 c +203.01 216.5 218.008 231.498 218.008 250 c +218.008 268.502 203.01 283.5 184.508 283.5 c +W n +q +0 g +/GS0 gs +67.0007935 0 0 -67.0007935 151.0074615 250 cm +BX /Sh0 sh EX Q +Q + endstream endobj 52 0 obj <> endobj 53 0 obj <> endobj 31 0 obj [/ICCBased 55 0 R] endobj 54 0 obj <> endobj 56 0 obj <> endobj 57 0 obj <> endobj 55 0 obj <>stream +HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  + 2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 +V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= +x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- +ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 +N')].uJr + wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 +n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! +zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km endstream endobj 32 0 obj <> endobj 51 0 obj <> endobj 35 0 obj <> endobj 58 0 obj <> endobj 59 0 obj <> endobj 60 0 obj <> endobj 26 0 obj <> endobj 61 0 obj [/View/Design] endobj 62 0 obj <>>> endobj 33 0 obj <> endobj 34 0 obj <> endobj 8 0 obj <> endobj 18 0 obj <> endobj 19 0 obj <>stream +%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 24.0 %%AI8_CreatorVersion: 25.0.1 %%For: (Scott Proctor) () %%Title: (Move_Logo Design_Digital_Final.ai) %%CreationDate: 12/2/20 2:23 PM %%Canvassize: 16383 %%BoundingBox: 661 -1052 1689 157 %%HiResBoundingBox: 661 -1052 1688.40235130393 156.62060546875 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 14.0 %AI12_BuildNumber: 66 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([Registration]) %AI3_Cropmarks: 1175 -532 1675 -32 %AI3_TemplateBox: 1290.5 -510.5 1290.5 -510.5 %AI3_TileBox: 1137 -638 1713 96 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 6 %AI24_LargeCanvasScale: 1 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI9_OpenToView: -982.13440265554 693.765973876433 0.258349573623763 1458 705 18 0 0 -24 43 0 0 0 1 1 0 0 1 0 1 %AI5_OpenViewLayers: 7 %%PageOrigin:890 -810 %AI7_GridSettings: 72 8 72 8 0 0 0.800000011920929 0.800000011920929 0.800000011920929 0.899999976158142 0.899999976158142 0.899999976158142 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 20 0 obj <>stream +%AI24_ZStandard_Data(/X$$ ,%Y%jKi)-X9< e[XOtQNZsslDTG"8s-ѳb|X0G;\8&{%b:u!BAxoܘlӉ98*҇ +7-X"AȚƂHq\G]xҬ槈CN!Rz+C2ǒ0J3F_(^ ]%RC8F_a '-1<̰Uf_Fʐl鱁<Q#F"mWp(,ǁ2]0zd՛:ٷ4ޣm%!_]{噻U0\" M)Ŋmɹ4?Gd2.Z>{x Sv -{e ,,cq0 awƱ;|h +ŢV,0c^M#XY 2 VqV4 =Zb! ɺH4㉇j c8rHH>~:`yGkjEZ BL瘠@,>tKʱ8Et4"/G K\KWt5ϹcP cGTvwxqx_Qx6 + 2s‘`,G>8cJvHSXa|8 EcѠcZh,i,4)}(HA`$"M' H7,|0HXڂ-9wzбX CqװCaxf SX7h8Ɗza#Q6^H--ixrP`L+Q4+si/\CUSСXsP" R/K%yUʐ*g{+qz<_eM)<*C\zMYbf!)CziMʖ!tXbwUey\gеsi^cBV&"c ƁZDQCX( +"qőF +Q /HU⇳ +c8~X CxZ Bxa#9X8#.4G},f0慲r++:(clj2KK$^]vv>q.PxpZ1T<_(Ld  Ʊ |GMQY :ѠVG*=O,,sQ/`FQ.ju0(c[Zh j0ZZ)% Ef!Hj5jhpj-Ȩ^ESI? С]Ġ-TʅudE1Q 5V#+3;1a 6ף;_85nqM.6:}'EBChN֎gA\Ԏbe`, F j`BbИŔ10c|`n0)5D#h(Fh,4-Ps EcX`,, Bb ^[Zh(股 1Y,( +bH(H*NaRT1D#H,"H< L\hb o|q|!),z|,,\ׄ%, (E)ꕅ岪CA /-TTS @ Z%(q$Bh=La($F18767) 袊pic0"q<ΊARrPA8\#,EWUleHR2$7ChcB5洕+sJ/Cc:CYexi׻MB8FCH<װ5kXQ`,l$#HE&2LL󸴬67 +'Fgs|k%绳-X0%얆f;3+#-T(E偾Ê} +/p ax2p[yL"F./_"H4 QTARH EBP( +P,(fE8-p.xBX,(Q c9yFP, c1iцPC{zng+8/|D%*qAA 9(" *R xP:@ 7BA P  *LD4@xp(0D$DƒC"$4 <4HPLC> &ABƒ &D4v$!$g" ! H <4\#d <+)c VyTT1 R73YPC`XPI !e@!"$4@p`pT "D04` +D4H  PH4<@xWN9W*hlaٽS=Z9- ЈcU>oU+Z`{T8җ &V*ܭO,mбԓ^N֕3+˧|BS!j_J|Ӭ`[׺\SrΣ̋'^VM-%,VZ/S5(ﭩr.)_qQ 2;'=-_*KШJO꽷zuI %~X%wb'd/"y3.3%&+M^ExץmJ4g8%ebMt;e!lxs+ztNcUvf~*>m ^cI_O;S %4rз|̢{a1lowt "PKҦ,\7>oDs"B̰ +o~Е%84λf){r%&MWE>T6~r׬eڲL6z;Q+w^$˴"F,vgF_bS͟ꎄW,K7, kSn\mnÖuْ-A)w\/̃'{z7ڳcۂ%RbIz4k/T9Wf-؄V{'}&IhGV7Fv|A"{}DKDZ`Z*TDʅNZTW|eDWT&o%8mvD{ғtz=Sp$-I1s&-9%EKϝ-e_':㖐UT,_ROH:Xx?X^s\"$j[bIKHMI:4&ҧOJ"I3U/*#2JnzMV!#,f:g[T|Ҫt9#IW8fEE~eۊHY\,2F̥Dپ~1,hd9,SRumW"R/b'oJg ǾYf"˫S啒grr/կbۨ\IzVl"4IXd_CR+WIJHV鬎~ˏ]Ûq4BCWUQ2jQ|VDYȭCug[nry"yUn"O;[?,7[S7*D$<]I"9B,.r"S)#"ɪIęXniƒ^$+D>BGN푎*d\ZNU2XG~2.=]~2zũGsMi,o<&9:KΡG8`pcp "<8$@$@@(:`pT@Lhр48`pX@08$d82%$ % C` LHsѐ d08nFtKtU֩>ŌHV_~rP0a $$@*cZkƨ#q*c!aGѱ8J(~,8h Y=aLL45&siMˑUU'f8FUc8CwExx3bD04R5$ukϚk1$W%1766]VԚ4 E9pu#HW=}vdXg8FœCz5vb\V<֧Tdʲ 3i[Ƚbb̚TK^)Yҩ4kmAs ̵,陕 +̥;frZfA?61j3Vvh ˧lR"D+HfM2*WNUR a0g#VaI +a_Ҏ ^0]Vl.5ESzi+i$>i$_};dV2X%)M5$'!{3D +WbF?2ҚoF5*ęm 6#izt4$WJNҧsN^Ŧy.׉GlrfSaߞlS7^=9j6vnʙؔF^ϑy-|KmT.f#=TB7妛&,dlyfR"+: 2!38bHeWie׶lK#]􎬲G-)eBToHUgDU^ϸg8cCBE3y#_]#UK9H]ȤeGko,6Rx 'еQ SЈbzGwC你VB)2ү>HDSh2/E =hi K"y̝(Il k$.rrUr=ڙLy4$9#uC5::υV|rfs^Ef7:,>wT&c7ϐ Y eV.xbd;etY3*3&Q,xDGx鲗2VG+’cӝrtWכ,ͬvSSKӄdxl͵Ȋghl+M!BFh7?3+ud2ʎJц2-^c+=O?kV;#3VzsXRSKBc+fo.lVhдc^]h[J]9ra=cV5k3ab9S{{t/ۂFFΪ;e?XTJKdQ~UI8taj9?kZ,Q邠]+&Cb$k9$ǻ\ 3W5*91&;Lcy2h LSy3h #pX@D$tQxhx80Fb $ƒ@"Wɢ&48\p`"b ( 8\A yuIXv>FX>)M$+KW\USsxP)xb2)V-/ KVjɥt)ݥSL +Kl ʴC*>4+f+TeX>3uŨ\eiW~Lv aa<'S9:`p<(֕I,M,S%\ݹrgo[<*UU_`FiEc^y.;Vg6HK6t]o7T>uY=ȫNj4ҢʴrE܃֍=nO7|<*TAѝ`\RYVa (ˌ~V+ei#3f|u:zi^ɒD5--K8 wVGW> ^vhT5TIMB:&M1$jILuR+ˌn*2*]Y{ _Ҽn+W+57M( kSdg6a33vVI#BֹⲚѧ~JIRGsv4e{VQR)CgXtv쵩RJ毴Lņ^%,zZ=5c*BQ8x92$N*/ݹݎ\ŹXnؘZ-Gd$C|$)3H]h%jOJ+-| +a~ddJJJS^ۧfy+Fu_4CfE{`x*vmK[_Yj_Ė9߇SjKU1Q>G},3є9̿-GF4tzm ΎT\ʳ~UÚ$32K~u=q-˨y_'uim'?5]>Yi+""Q%MRoDYlmCS#]{{*Qu"n&?h]E*ZeYs}u/g+y9qG'?.nxLh%'/"U>uf卦\l龤߳jCB$gfWԃf-klsNОr΋q .8N-^Y(-NBbgV=no$\~ol;"!گijw2\a]6.>;j1dɒ0Ϧd]*-!k*K-Us>ֵd_RQgl$¡򹢩O`,MF|Rd1Ac/ƾtDj?t5i%`ϚMdEDJCRX*VmTW'lײ=v4_7U9f:aE2m3[hVКy WEQ+y'ON#WU[ʋh׺*uQrEZľH_]%w-d|P_EzTYރyOkМIV2chB˂Iv7d7IvϬBe7ITv,I"reXve,Dļ*6[\rJ,1^k5.gi;ʅ:c ]~xS%w-"FZѮ]rE!s9|v]NS#wN1 cS+vU[MX""U?gU "|^٥4iM2C~I4ry,m`%,1aj_ݰVl0m伏y*o?4ܱw}ΥI4+zT6T#)~z255+<ŷZSgue-]*NOfce)UQMi:kʺ)*~*D]-6vc'}.ORlLlrFչu^?6kbO/WɊnwY:D5U1¤2-~*%ʒիGv)ɭK&SOixey +DM̬{s*+'Iaek'VVa]m,dyeAL+e*v.whFs,QihiUgW]~Wykѯ. 1 ѪCUhr:K>Eiʙ"KzX7;Uw"1˱cYthECnH*sb9:RLYU |eZUR>iT}IGL{cQMxWYI$,|8J"5L³|)zHb{',= +kH|jƪI6u2_<ββT/XpNΒ\ܞݜ{UJP13Z8!tod"WiiͤJ)XszU")J!e["ǻ{j+dll5r2"+eWpD74b/Ǫ%jpzXWe-+U:,[^wcư1Y2kXapqES$/^Ӎ1BĺeDX*)c)"*-bw:ˎn7cH>m[H!e(_g5:`ᙕH}Xi>du;&]9D[*f^ZY*ELuW)rk+Ro۳B,E +wT ~χJJIJ AJrJX;rTa1BŊN9qbT_ef)ҳæ038-i3OM8muWngj&rf]U2Rc:- thґb|D,=’FD#]"%M♕es.FE^ɤ(ʍ܍]fk\t׼/2,f2Vb"!]օ*hiUm]am#ڬ|w5g9BF6 ˘ؓמJ{,9El.3FCu)u~vnM9>"ҹJV7S*K9)Nc,5uŲ* VR+z2tw &,Y͖> V^ Il] cOeVJt|h +>QWʴЮ/ܶL>DX +%-RaOuSA +w" +;hO>'nb`]\Y]io(kź0#h:Փ+maґV͚b'U+_/eKdGu:|WQֱeO¿Ɗ\̼-JiY 6Q!!LJ,oW + ˑLEFFղ9zNU{Yvc&MD۔[2ƲODžY)_hU9%O6?I,i/)4?zFCf63UplZW0nŽ} +uo_rv|0OK6ueDuI]츾?uhhS|&X;VS}zv:Ĵw9R/?wŢvi5x|5Rf9N YeoЬtc)߼KLewhXKoVZڔ] kS6*-o%;mYy }"jD'k?Jr-2:|{/+qҷ2Ē-؋̜KVIF6KةVz2L:kuxq!z`9f%:Dɪzr VdQa%ɎTHRc )H  @4 a٘\~D\49'jP!c$P&{KjˎuDwݭyfwzr*ȑ6U2c&BK*#AT4x-{*a7q2fS#ie?Km{ hw%j=4~iꢃx_,q5EGZh{9`!Xa/htEMڰJN 8)۸pBߛ72J9Mh6LIjn4EBT`xgM7ʜ +/\_XXSZÍGK1@'b߳Zs%MG_4mYdzl"MkP'6`xa.n;^%t֍JimtD#)$qD86g۟$&1PٸAb!S\=ln8t5jLC `(-,Ѓi;9x2^ +-J];n- EGabdi.&i&{qd>JXi/=S[`¨ bEgg%JsrpG5A(#IPNL t[{[ +x&`zBď~>2~Z_s%Md '_<߉o,Hr둄Y\43ttꡋMRcw4{M7(p]1~EЦɦF˼U!2r:!@Ӛ9Lp|y_gbU&" 5_v ZŎWI>(G턿 z vXܒDƪ10T ]s fʎn^ )0夡r𸲣9H5t F>b.2["hHYB",۩^\ZO R*cء-A;d3e,lkg*M1VL[P *>4vImx\tQ) 9Ss#cT*el'@cT= Zy-%p€%^3L'w/ 3O/''c ~.VT尗zE?3(B!7Q'bDQh+4:I@PDҹ$f}X%dYyQvpU5T΅8*)P+w>w!njW507!*T>3-8Z0/Dx:5N %|,5V>fAJr&W0X;_7 l|ĤO(Dd} +]5Ai.ؼG+0d dU%zh޺ +0Yt,m LvQJ񫲝5@cb7fvNjPjT*956# Jo62nm\br4R359D梮^k!N"LstH8Ja`8%eL %6ȘQÐ6%e"Qs<(SKe{lO*BK 7cqsFXQs; +zL`jw-^ )Wt!+PIBm^@6M_hQ3 7JL;d \gخef6L{҇'#/K̂!mWlu}-hU\=}aըe 'ǩ  *ɣٍ}_B&j!qp|e\}ZS +OHfԸR=eT_Rwr8 NڵRݐ8JAd^ut:gӊYWp,cG< e0"誚U>Q̮D[ ؝ISXDh҈PE7Gꇑa#'|Lƕ$/">[+Veئ4z˅f& +3/WB&2msțި~^eV7/I_q92@6˅!eGd +GgA]㽑/8aȊ$_N ?Yd \iЄ+cc&S. M f l=le fpw|cah?=/0ߨ4#'J*u)__󟴑bmR)L8ƴ%pIR3mFG摔%2yȎŝ)9s Z? t~O1q '}qY\=;<;q fP7ӄG.0t糖Ekz%P^rC$xX킜fU~SU}2X^!5<׶LOЧ)c">)/n@rW?Kd/*4e/4 qC=RDmMҡE 7Q6<?5D--wjqB.q'tp)R4o8nPm`;2Nz'בMlq_̛+Dwmg0@|ww6bG/**QqF|l^`!K˺ o`cEXv#@͖ 8RV,B2yM[M/`Q0<",PB#pnD<ъgX"8}q 8rD6 wc԰Ӎ:ɇ +ৣW7-j̫4lBԤ# Sk,48"]~3\ ܏\5+u^ k6>n1W!̽2|Ӈ0!@M, 7t2*͸7`,6aF  ~|w|><6"%~1cT;ꑂz;8opjU*L>l@Gc)1h~y}p盱M l-P~dP١>Ĕg*=1.hemn}_<3{F +B}SiL(yToĈOUeߑq/bdYg7i hل=*A*i$u@TW +$5-=<ZJ{Vkݖw:P6*H˙@οge +[K@ ͲOQQZ8mU,qݱLv:%sy78#;vLJ+r:=W+8lm95+R1-zQ MqnEߓ}n3;_DB)My:luD4>SB49qvjѤ+qYEwѠybJiհ ·&}0[?}ՃfzyTkRתA0:1urf_4Ν$ҎZ~?LSDLLJQ:r)x"Mk.@q/.׏9.>d5m']޳0|<Ϋ3 LQ]zO\`)2.}aUi3US2yA+m^NOKQ +f/n<:Xxй/)dY\4 *W{Lʽ<7mAuA: b&|<)$f +14Տ`#F)ShTkYň\'7+J=v  /Gb`lԛD3HXȢ[Tq:֏t⍆c9|H3 ҅ 1b$ + z!epuZLҾ!{%Q{vG)bYE'(ґ'+U:.y)GQPVnƌ\!** Yb%KEa#u~nu3A*f[7gZ 8Z52}@.}^&At{TCVفKARtwxO 䳕u/T$-ETyJȽ| lʛ|ͯ[!8Q\IhL.&0d]srJG [oMVCPl5NʙZ?կJV0,^_LG0l,'TKQny□.u:g5h=><7[ v6 2IK/SMW A JUzܬ aq@͆bs YzM+Ynx' + ;=@lx6la(KKr"z)^s/xvD(CrkʧZ0Hzo)-+~Mg-U;t ~3@g\~`om#S6i@0n͙p:gxy,ȋ7N#A,N. dim^=IL#/N7vu] ð>=AGRmHdMhW̱RNЇ=eJt)Il\E=̐='?gP=^fM߱.8;z""!ʂFp\4dMavfѶ uP۽|b#D/0Sܗh_j3.!2A.bKOZB4d$ĻSZ*!Oj(q b;gڪBq9zRb#_K Yz)b)rLҳPˤyɻKar2x T6P0%5Y44^e^k7B.l,GZwr~gqX~o .PƊj;jO֡>ZB^{ciO:>HS?, +)ER/͞A:[7/M A⛉0tj/73 <d2Z$zts_<J7E'R#)R~'6Wd $ON2cyakA>jxuy}ۓ:6Bk*S"}L6doݕ34q_=iPRp&E/  ? +<(MOelP֭\a Rc6glhQ ON$(|UVφf?ZPWޚԍk2*%-Q DiD-O`+l>+,/W< Ny{< M-@ ]NFElg=P Ov=W, 7# ^^1O? +YnOTJ1axr!,!8]RGk=09Tqld-yHY qV՝;m +Qm+qg]h )[۰f&c7r)C")^^Eo 憫Wf00DQT]SLPoW E +ʌۄ?6d54& - jyfȘY -B׽lZjhE }]ZHm;Bbr!BT/\ib*6$&96kK☕n Vӽ]Ɣkiewve" sBYĬ;BfLC Wt#Taiذ^x&f~ic VTfi]弤hx(@Q6~ülf ?d| 2YY?G2<5 ޾ 8qD0gG=,yK .%Z6Y x:O391fPFcAf2h+GDnQ!)>wu{Ól0qm!vuY(ѻlr>3Ko.$ZYi,˟J\&jrq: Ogƺ (QSHvRGz{ld5)k̰z|!YmE( r&ˠ +9&[%r M f9 Dae+,/|R2h1W`L_8P<CJD3oH=*t "' g; 2,Ѕ//De59}o=LD4E.e|ұP :T +BDh:B%CO4(Z#S +veԇVAgAJzsWs6EHb!C`zoV&T\ +oPJڟ}ODE%|57lmJ^&к@)Ų( AD(ڃݳ2e{:8ë=IRWP<@C;\vt9-* o%>ijUi>E: -'t$U1=/)>>w=8("-w !{OfMYJ<0=ij4}Сg]:=QCv]VkѦ9oa2o_(QD]95.7wFWN9L5@K eȧaHۄ72&"E|ޤ}TUx"ʸp˄nшEL3:O׳By\Ddx|Bf3rΜ +̀{)ǔO|_RzNSlE.D3<hr0v?'B64\ǭ6- *Y譧W,DЗ#`4j[.)L&TQak|cb%x' +j2U,@55AB9"NЈ)gAC?+~.Ćl(Co1Yt9lӮ_W;GL 'kT +4*!!ٮĭesLn3Y&'0 uxCI}&CF{"[nqj;# +FԹ$q"ؐqVm#ggIv +n#+?RK-$]jWGV&P{O +xnS)J&"`_N}&/>4)Q1G +{ +ƂApC=IWNP2t>65[_P8=IDt&"T 9-JN#>G\[R5brs) ]1n' l +,Q8'(橢R`*I(]CO4c!E+K'f!ϢwdHKZ8]̋; Y\4"[Gy}ȅsA5]0.uwy olmB>/(p9ѕZDK<側Tۊ0K0Ί%&!Fb-|bR˅nБicD0 u`+^j #u-`^ܙ_ +1LqO˃%ř0ʜo1wDk&]S4O!}4fw}~&WL3=c4rLt += DsJ}jhQ{5wpO b5ašj!Af$f1|͋i5da8{R^6#uA6#ڈ|jOC(2YR 48xI9]aqǁiYR8NZ?j&& rh ~R%JZQ<dmP`Y./xՒô>PԺ41iUO0DW̿xC G\EH!6<Λjpf,5 +R<^;"W|+*{LTzp;M,U&-\ʕ4lIc"oKXLG&CPC)]~Za7 6ɯ.?hZMBT?yd6[͒&/`oېy?K8SÈ!6V &K2塋 IE л* #B8i΃dM赖7S׵PKl'EG K}M=ljԂiRUTˡb#G\Yw\DeLxE .Cdr69 !=m q+aVfBBz#ْlAqqERc#yH)GBe /TZ(E\\EK :E]Ez'*.@LD8OYQV[Ad1RpCJ48zQygHPq`[3$+c/~U!}.L*( + J.lpHje \C,1& B +Jk#,[@[@@ i+ +):72_`iz .0h?CG0 E>nIT?S>e` 4HfIT-2ȁ#UKN4ŠQ,#tuT;VHKQHL jT^3/Mz$Y +Pbz#HH0ȇZEfU'<|vι amf!o}9jg\ (UѱBy&+=H:R0~QkHc.&a#óz|> +zz|艈hi9DsibӖbT¸9+{OSYCzat<-2Fo4>4z 8ȳɂ Sd]EO_S\U1l{ ZCTZ=TY>xO˳T& Z,T;0PA-/g]j^tlwǮ1w*[ɝM EI ,{sa_mj&IG܀Qfy|MdLēB]kK]GX$&S@,f*>.,6xZ^?w->zxνc򦱏 +A^´Bp·- +N+V~«@J=4| p!):.I"]BN kỬ*:[DEi⿩#Ա(?}[{P*5iK֪n5dU1Nՙ$Rߑ=tlWₔ. "!Tq>X?l\:> )Y4Y^u 8_ + ::DqI°\(FRC`FJoBck˲(KULuf> S!,|/'4@?+AE wf?(YAuh~d"i%[O",FNj(]oߋi88H?Waty?x4 0>oli{HQ3#fU@̵>jF$D7gk~F}H BsXAO#M+p7 &;X,K +ם)bQ)kY~b314 -"JM$qLwnŭgĸ$xЭ8خ/]àR36]V((d:sur?rX96k3+ledFp04p:`_mRenfDsdj騚 `9ŚFK7ݼa,c]S~Й:j=pHss_u}LJ̡[X rX/K_Mr!X[9bڈ @⪷zB֖Ȑ_)m͏,{Z3J^nd[z) ")rF]Ӂ 0a7l $]cD@HuYgFp|WslI \}AGWʉ.^M^lfUHIV?ݩ?4#h~] ?A \.|SXRS57#ރ*g+y F(J˭cTPdQn7Vpe+EW|5 R&{ ^ܔmŭO$BzwՔtX*Fm9X넣ܪ41h7weQP۪->A`}9w.u d)F%#mndZ0eB%M hfMNbdj5dɐN:I18a!0,7{sb }ZI|:RS.=^kʅN_}TPR_ +o]NltMo L)p/nqY#w~Qؔ8V%/=FdzϤHrKFT1t"a-`9')3 >&[=E)zQބF5=$Ha +큝s}h^L55k5 'Ƅ=YX5-Ӧ! +\~Vf > yC8ǵ.5=dB=mJ +(\JʾrO {t͡V3&ж ous}́l}]6USk)NSۨ[lMf1[vev"r Y6~-`h,=!U)D2(a +=5<=ᦽ:Ѯ.WmG]IKS eҏBFxZ^iQ$U$`55˲uKP *O]=}KYvRZNXN'&97mOS[h6R&%$H_,Ln22 M&e⇐b[RdgMl1 /\3[bȊ,AJ'~A`ۣv%:A)R9(4܌JR8"H@{E+:zK]g1X2Gލ8 P#;,3b +r$&d3J G#f'Q]Mė%\Q ?b W$E傔@iB*g!Oc| Sz]bv:d1"lwzH 9ءx?9 +%%/9Qa<31Kf/syWvzkPO'$-k{z@äY :9"pSSQhga`Eaa!i+Yt2Z&z#MEquԯ5K0r_)h=3Xzyp`[lxBU i1C9y Ps +/Bm2N^wC7Y20kCw]p7BS:^Z.ՐfoVZ*7Ʈ=" +1HZWzyҾUYoyk0^@Jms~ʏ1+oy:,FW`! Ihr[ֲp jQ)PL5S,(E +`f'+8NwM0H|I=f.E1R" I{y5@SxnTIAr`e&?Dz_ao>dw*l~W[?)1kdT63V9ȐL\0' Ū +%S1Dܖmrm1 @ER/{~轓ۑ(l?* )!'ݫ<2 AG/ +-F7V_SYξW?,Wl>וx}:k@PY> V-&Ǖָ]2š3b=4Tَ9@@`l)WfwSy#yN4v]Je"w5lwQ0BXP@n-Uy>Gئ{NOO˾`V(˳xMMNQc[oi JC2pXr&I|fTt}0h3!E9{/UXͯ/ 6 o`H]$iYfp`ouǡ7 +uP;Kq6 [pL[ Xb`4Ÿ5bh`@4: :zr ]34oL46ZN s gKSpk zQ<}(|ʵ\"?K ,V<.VZ- Al7 i_gګ7|t!.GoX12ѽwvhoEO.5%bXR@y)P"\E4oӲ\|QRlX괔2jdSwV9_'Lb1mRv!^ĉ4BFx6mHC2&$Z: yrycS$YL}Ybf&L|f@i0ҟ^B@[b >$[xP7noI6Mj?)tG +_%YĕjC$uSg@x1},r}Ѯ__G}\WԌ/Κr`P'CIoGx|Jb"|oS` llGk(PDySӨ/Rw/;PEwoFl lȑaw6WlaW ֱy&ܞjY=1Q!_"~g: g~C wCe[l^)eGk٢5y I!}d 36#vpQ +^ ҌS bRTLƄ40sd{y^s3jhҋ#L_]mwZz;[rT{3P½p_[_'2߱h°\aY}LF!h 9J +DnX57?[MAp؊+O~VoUh?ؘS%B} +GШ:l~ 1Cj;Akc"mǛyoxeŴ,s[{S7퇦g\씩^3tGӏnpnҸnCcy +\ZlHX孞Ȓ}C-(hp}3YɳϽVGϳ']z0MLzYLq$EB5%TȊo17Ig% Lg*GH yBcpKkfK9Iw+RTf3{ja9nK +F_ +gBU>w\8CV޹) ){b]{&]0kětw+v9#jZ̼鄄JP2r-TvaNAKhEQNP5)"M}FQB1Q_! $҉|܋2j7- qs`-j^{ࢃy{.8a1(LZ@o#U UtUz߃*/H`QPVboq@)H% +aCm#+k %!Vv&!gV=Uer)F- ͬ((+Q K@J(Up Uv2 8hYmdaYuэ G +'L6A +Kgw Ahg#P/+Zї DASǽ~ۥ[oem3xҳAze(4.lJi #=mt~dI[)~gşr>W8sB(X+ 0-gdvwZMfL/اmq 4o-V m+ݟbG_zTi8ˇa+dEgV6(y?~2_h*xo G򬔒 zt} z *܍7yiTDCnI +"Oʇtzjƨ:a)CJ`aΉh}?/c~d>{@ȥxĕ~ԇ1 {G褃3s)aӺV(9IRc+o/e~]Y!ZlҀX#?M/}vsϋ2O +L8@ZVLsEٸ\Nȉɞ1nb(©K}$*̏XvQFZ,ުxp4) u'Uڼ #%hMy7uz:DiZ!dW ++fWj] P`7k&VvՔk5Oj`-BR'5*.StE7Y2h^&BϹ=}r!8Yߘo)Jb/c[恦6IQjv·8dj:Pu*s%蔶}3gX#IX1*>/Bv "3d!8t 2>oN%5¢\Ƌ/Ɋ|I'#O##)/?"ibSz559|ekpԋ$Dd pd8;W8ٴIobsWNjs$|+$B pz!USGqp֪L ɣgQFv)R!&GA +SDHW_w#N} "_Nq,oJobf1 Q4-]Ċ;ةKB8 #?RhFzX4l!a-9jLrْ{!~1F$q}rnNyb.qԾ{ےYVAbyV3#{Aº5b>JbdG]"뭦s#mӑ.b VHuF'Q?Xc{f\ruЈhDmz"Nijh_O+Rɶ=x8a2,f>ajgtG~&JtE/ ZTPZd=EQhIv*0$?7KyixB/GKZԝ8)34ߴ&*h}_fBAƂ5Ҡr'5vKyrI> %F77 z+_!!WM QS q ,C0pl~h0/ԓr O~N!ח;R I}xO ݞ> ){(#싽>5Ȥ]ĵ\eZ_ +7FtROO\G>5T + *$Iq$Y/L 6MA.h7AvdC9$߶Èc=FpW\ 0V_AڹW"cj`adoho2xZe"o-tV:¿$OM}UE{ӷF}Rԁju9u n+Q*@=9(;0 YU Bun@*́v#ysCqsp۰6HjM]UW.$]t#ţ~o߱9Q4΁g +⼯ԭTmپ}6b`iQV>v$N)tQѡ@c>$l0?H.RC׉Q% ֎ߎ767YI9'bp+ɉ٣i8F Q8k+ɾYz{t^c#>5`܀ k^ 5'Ndv`_ӧyKtG) +3^<4&{5}Eao!pgŽ  _5 1ioՅu׳@vyAuvrZ45uW49$ecy h͸-fr 8g%c=h  JK5$^P(4l$69)D`X~p/eϋx1s섙kաfr!=p=Q GS(Ԏ(4eAB6@/~C)Vl@2 fCo֔!'[A}څuo~K7i WXCfj3UQ*DAGUTa*670kO|U'D̾yM')'g"" /krLuᛁ׿/[# (lÝmx[x)_G*kk+gwcȑMyϿqχC!,;i2ǯs9ԮP}Kei3Jp,|nA! (£emsRV!%ٌ.vP!ic9dcυe3$y^bY\^]آvP|,8(z҉fgl?DA-}k mКw풸C RaJO`i80qۚƾ*>qHsp^E8R"VA)ٷQniXqe"^3Fr܅S"iaҝ|T+i4 +gHLTn?a(Z&-H).ً_8 k8XH3 oX{k"<|XUW'xCVx3XhJ . a5x$MGrqGAV @e.`*<+1Y=h +6~Eq)۷eACFWĒ^i ^ +WYkHv)CtaP>&^-A#+iEzyCW<$J$ :ke$t{he͚4\::џ5.F}$v< +ily~QK& 3\:}D!OH`)]}#Z.ye( ACƢJ>d,'xtקQa#[לK?צ^$/\ o1x}IxxY6E=T!fIa +H6b (L(,ݨpWEZ+8M*Q盹CXCFGa٭vŊV a0%h^"V8/)[@소WP$*$8qzMe2SF7"}%G{9DRkRP[Vi!9`Z<5:=MKic@N["G=KT`}0둋*hygnSCJDg ‹׆y, ^E!DE` ߠm4A_/=Q]2Ikƍ]A*Nj j;ef|ad: \V +96rf3+D8GMvo}e_aE"O3@!+X[߬(>I@j@MM$P~j'J7zy! LoyiǺ3(O0J*W[C FeHHYvl!4Yv`4jvѮ\s^Ԥ8x>G52ҿ m.r|%:9jc:wlܻ1Jn)ΛI +_MDIڷ4ƜʥHڸ^ӖQ&ކ̝ȶ +{㉄%NnLxGqK,ga +5 p7 Qh>veORТqy]~0v?KHq]\3 -b^>؅u0aat`9!#<%(|4j(! +WAr99a'Dٝ 蟹HIitw%=#)-ߡٛMzcmn|xt#8'$-puN=n{-9o17J9G}gd,BdvSA٬V( .~Zݟ#o% +`"<%^kҌeژM-Ǿnl1~sBB8Ens߁mĔغjﻡ>xX3AZ#5#\'ۮى3'5q \|mO! 1ю'1-:RX--6jRyeHy3foRm-RÝ*;-xY~_v><IJ__ +F.ä8Au[?/Ub=u] &:q̧t[=!c cwx$IKH'rcϛ'_g>iw|/s<nU^}tb L@B4MCd\ +Yh*&)4Cș3H (@\ZGz=5 qAK+R[$'z=`UARvIwt +;D {`9J|-f(E_FQ9{?[#AbNuf"^%vC_hK]Z1)`BߵNtb.Lgb~oHխw +`+r +R䤸g4LZ@!|Y^9 ++f )^)Jz w+tv ~(-BzF.py.*}qWpcg4.Yk£b-_~d<xMF9-;A "@1gPO$ʯ4oh[~u~:1-!GH_;a}o 8pbwi9fTcc*!&T}2QIaͶ!XоАNQU #Bl PY҅+t +CU/ pMɡ*"A";M"`턉76[c=j&oTP\= YL M@ңw3f IB}A+c*IrR|ؑw?n -`-D/bɷ.]c686> z!K[*~a= dW` 3Nq,\JR2I8Ucbgm-RaTm$!PK Ւ*P) E&/T /yhOqBby0 @>~|_U}xO! ΃yNNHU&CaL!ƴ\hE($(RZ=Aq:c+WIboJ5QxKQ^}Ї5/$7*?cձtMב^4c%'|dF4bWH81tt!E!F%Sͻ5r'vDh" 7}y1$^܊W^ۈQZY!wLsZX.cS_yŶ)Ԙf% i(P0 -BUe(U1ZhքgFFlDEVQUx٩r&ByG+|Ə8qMy"5D,J]qʩ-ڲ]rWqz3$XVdR5TχaC! +B $ +K. > p |T +1B(I A38D!!H 1!dJ(Ǫ+J-! +*D0:/$!fuBp1X`C%Ж` RP$.ۢP!!"M$W:5aicZmv -%-n>f4-K-[5~#rK#o+\X`:JEL8Ą'9ԼQTE ԖFPH:g%)6E׋|Q`L> +``N󈒉zPtѾX%d5 Ef%"ڈM4:}jQ׭d-M`Th*"Gg+]!ymkf|h~XxQL`1$ hQvlbo<[\i,bЪBIfD\ŕUHϱLSwA(+{TTXZrJ +-' +F!6l CеH&kSPh(̈́2T8SJCʤό ^*)sI N,O IPH?=TI\Ȝ8C+3 +*YUw]N _l$a.Ȕ +"V yH;h8u]Y%s"nOs*YkO%ZL]LT<;%'zU4+#2%j׫xZt +%Ы}iТuOUjnՠh"u#Yc)O Q֒:MPkZ#Vj(".N9ȌJz x&EYN0qgDFEV ++ɼafWLoՋ,Dv=&&ׄ?5OiYBЊyzۮ&8|ԵޔmXQ8YOhMƐ̜,Yh) AAe^]H(v!q 4_2Z/!;%6(XԢjwo,"a`E5\S8(H zp?L7a% q23-#DGH2)ARCLeKل t FISC#Fq|V0t%~ e0i2Eʄ)paC $HJFaCf])] ƐLJhBa3t>Ctj~\V OĄpayZLY%DD "".>TBS%!f/7XP +&iF ]20hD q"?Ծ0z qζ!tܛT>#.߂D?>13nY gaL3KL#V`kNtRR*F-xwEj>)Mun9y_]AMTV]{;.τyZi+EQL4Ɖfbt>V(9FHH*#BVRCft$R$WX/-BXȘ +g0haeł)h0I6QgԾYLΚLiN5Ti|QgM)Vӵ*%gFیDpS2BsG:u'ne6BjUz*Q[QGs3tJ;=UD& &A%73lJ?k9_b?=6?Zm|~U5FBHribP w4GsX5%3ǬČcb&s쵰hoT?,ï6٣T$G|r@*kr* g<~r]e>Bg*cZgCؘE4,JGdL$ D%f"ER̐HdfdJ OX3Utff:udʆgT cՄc]Us= 3nFa UQ4R BUسQ{[ъ:Oq%hsF l5"]1M-&f(W3:l:6F]˛I"^n~3Ƿ֨%G,^7ƣH')ya57Úh&{O|QR] jGDէ`L Gl,52DΒjuݕMDߟIH,J0\eo&q'w*!:χXV8GJp.&]WԑIiVi^:M蚌e5ΛWXn[DŽwj9P]ju$UUEê)Hr +f^cGo(]Lٰi?NJ3#!q̐"W>2L4gbPlhIEJ8+T\RV] M39M+$G$8hm4fA4 \~IOњ Akj-C&]%4hT&oh4Ԙw Vr9HS ޣ{G:)3(8 2nBhTIlh8I2!Pr2%)R(ϸ"ct _QA"))SPR{y{ר:S[ 1Re#Y \HK!4tF 'F|UmFpMQ!3RU/4B$$ZU+NUA@kouVjT E3JxM id&B.Xi8 9tDAEUz!NRaɂ%/J 3_6᷿O0};2{oT(F=uwr(GQ(GP W(zwC' .Մ]jqu&c!UgBI +X&q!RL().Ac% 4 $#H +.a+ +r"n +ȂB!t'0ПM8'.S+d9%ff(E1T*xLCa#S:Ł;F ԑu?y8j$BCï@JOMQZסk w]4w/mo(6$SԴp*u:"b (D%ü.|8K梂C25H-c شeƽ]K."¯a/*l(P>R@V9Ha$WS/zqpAkHh +3PZtSPMA 2‰^'QB Q%Wqh;UqP`C d=A SAKL!#ף2\U]yr*FNTE(T5Qsg00fH EǡR ,aB$dp#do5 _"䟹*^A2do!uN4ϒ("4 43RO"숡.d@Sy9X喳dɒW?[WNq(bmsT7q  +xe&C08@@L_QFcPF+쎇@6*ӄZ#+D <\hHSR%'^*4#RRLq@$#4@h(MԄAˀB5%7(Tp҄R ]%СIL]b5X9TԚ{} +Z(CbƤB(T +Å 3`xbafjZNWZ4| Iq}"T 䚇Ԕ]CɋP +i5!* Q$0PoHL"opE9gO\#xʨZ-zBӐ7R $0.Њ%fxф+ΰ,S7 T;@ C @p;B`$'d4Np@ Cb|v4BBA(U* W0L5 jSH{i2Ç.9a +,;Ld>x=I DWX} G)nS7nP#]8P&BHfoT1:L%ryB\C1,ت%|B[kHof!2} /Cﳊ)G늖Agy8x* wY#αr9HhY iPvȩxHLb脜),K5dHl{X"DI6WGxO +K9bpe Ucu +:Ja*Fv$g&6>aikN 0'ROJdb6^HDCLTdwĜ.'z~I 1[P!lռ[dOT.C^Ch"#3|lǾX]1p6IfF[ %^ C2'lWv!mF* a[G$ƕ'xMx"GIIyT*̮ר\z/Mb.8x Skn +Rdo mz2?ɠƎ6_ai_ڈpXm%Z~czUαT]%:H5lt?uUze1CLG + ,e1Fٱ?G| 1tݓ[`⾂5Q'$M}6p +ٮ˂-:V  5aԊOa$ )Xi#MM@3SZA 0ΩB ХHӒy1;Йm$oﷺ}d$)9(qYY! tbMP*:\KZ +JLq_v66Xw3 (z,/X`EH_O#TU[ )ȉQ_'Ld]*T6GZ^5vc)jɛ5EGN3@oqXP 0CB b4K}!(3aC§WLqo+䨚=dًfI7LXbtYb<jjI< 6]njOGƑ:O*./ܕ>}/-aQ ;%E0< ~#)4!h>(@߸2^d5P-;KƠ7@lH le_Bڊ ~fg/^Ql/J]uJkL^"B@&z, Wf9t-sV߁9m(I}ng6B7RC_ +ܐQ!,pB~ʮeRĥȧҞ<0Ktbz"z:>6Ŋ(NyYR^rc߅XoT#'%Mb77JK~У%@Dzw &#urMݝlmLL:%n ;b FϴUVOny5Ф۳GWNـlFQBHѽSA9 8` 9s"Q4-?cL()90H3 eMV)(HR@FwC.0q"QJL б sg +K^#Yx:U6CRDKWdD{b3ⷘͮxD4;=}5)ԕ:p%,/f߼"f`9ƪL@6AY9uZ(ܢRc +T`12mbLr,G!M% }r3;OT +mFڨp/N +IH{hP]R}Wc&yH|%H +!0b{װac(GxA&sM\ XTh( 番co]XfF֑ e(hϗZS{)l mĿO=A.p&c%M eY}݌K4PS0&B6`e/}&Ep9=|z2)5d61=/r5~VԶ%<Jm;䨖DY {a01@8p!f@(/je3/  j4nO*p +1^f \5am?|6cZTza Q a1m 0CvcAW AQ)(uV \hP8(P7 z&ٱj14a ^<,NuAbk~/s>c_39$tX}j<xC <[nOc&?$jW ʺՇ2Fbdh +[݋Gǧc߳z!-s&pZ~vCEd? -ݲBT\Ky/Peu,W,m0$3Ay⑩Mݬ, (c@@ zʾɋ,ߢzK^\^x\˧Ab7[-H.Ўn_b:R5 ɩ@ߔ1C_Ε4FGͦF8yV XSQ|5烉B OmMuV̪^&e6lGwq铚9=ۯK''dJJ{clmwVLylJoh8ko YQK,D,z$*14>!|ym'AqrbUE8L/i%;?0PjZ6F Ddt~}{(:S!AVDBM8<'c\hz30)FXBV\vkg1z`m&tk%30 +UWnrDh C`FV#uh9LY!xUn0aWmέ4<oz罩 N/,uL$Tp8@ 7*mLzl.F,&bWjFb֜Rs.n`%xO$ ?~#uvM$98,`2+O=I.;D^&;n.Lm?xf7/a?MiĤ@7,R,Z =O)F%XIl28KiO{A)LRlF3CfЩn (]d(zE $$D ŝ$Z"C⠎4O[ETh:`%mrAʚ}x>.ņhոDEF9Ԃ)V|/Й7pr)ƊlpP ~3x32S^G4< cSTFLBal'p N\⣇VhJ*׽irx;$q>۳atFĮA$<69|uZu3ЅyӺ5 HeA U˗HkP.w$> #/7f"X:Jl4t +'c5WFչ_\VDo\76 ĿSxXrƞ)s`@Z6NZ=Pp|8ȹԦiABg +C"cZΆDasxp6ȄvrZE#4Ȩ'3 .EqH5 ܢSKx#Pft-^:XWB-UWi2IG_ 0QK6Wdi0`BMD 'X -ahAKT:䔼.`$eԎorpeᗉT%p{p61%C)(mK'2hs3n }S(#9ֵ>y"- ږH@` ѱ+˔T5wզeIa5pr kYg⫲ XaVCuq^yz+PGفKDS(pz$jĂn˅=Pob&)N;l/W|"9\YY)/0g5RHAXap71lxtL8Iz!)Z&(5% +o$0B}$=crtW,"ZuF (؜a +4wŷkZ]I/QVr +^?`PCS)-S7TxZL IBκm(Irv-` h3s$Zē>E8q5^ E0p\e#?5'(H}:r4#t)ըqUB+DQH cL*6B! Zo~AFyֽ1dQEU1~2-FbI׊P4{wh pbڬzJ@x|_ 9ᤰ|ݰy [v BM~mτ* qoOق&$3.F+/!Qƞ0jNNxDzdxN @J@ BBPRt_Q9×2ڧDiaw > +G[R(ؖms*}bx,t!Č.S /9'׃f9BX(pBV=Ah}, ݌R)G,iX%c 9L Ma@91WEpüϔQ=~X`&QXrL@"4J >L3wƈ;3 Dy~0tW8{Ɂ' +a c_Ϯc(L\mraA$/.eE̜JZZc +WT7p.yo­jѯܒ$IL Q  +l0f=w6?$-imM!pi.V/ 20i 7cƓ:RL-pJݙ%c2/8՞t])joZO+&T.qn~؆Ե<)Kd$حBis\m1B +qFQSE[ZkCW Htne܅b<ۇְ +ײbeLQ?ZI'аRK/|hnq!],5)Ip$m$yS Asp3Q9ނJ[eBJCm(Qȣ@ˡ'Zh*YPXd:ڴ =JYB* HT45g]ms^'੷aCȼgbl|%RsxAH5-}Hʿ[iJ+P{Ufdy"rC8&SO%&e<~P؆ڿg»@kX+ٜ*7^u~>I|h/ O 9!=Y;u#+aC0X~N|WM+9xCppӱԼU&Ӗ$sƈ t7lSW d +tl XI3ȰJ{[&ufB MĊ %*0t:zpapa0*֗F_C|A3u~Q{ oۚhԛuLĜ +l!FX)m<̑ GX K|2I3d`ASҎe +)_m4\co$̰,c02n)PEOIvzZnG.V[o.< ZU..0Pl9]O%S;5K 0 vPz bk)Uf5Zq}f}֜vsdylHMH@D(D6ROd[ӡheez)yOSą.ɁUeNi3^[hUloLWoq&"u#j~.3)/6(y@d)F +:&r+.=$nZ:]/+gBtR,%z4{n=*|%*8M# +!G, + c/ 鑴ϋQe.!ޙ)2$2CT:ҡrvP:RDu$ i@ៈX:TmHp6dk{$npyT78d(7>u#.:#9ɕ[BTuH;:;4}FfH{wNexE"y3FaD :>E hEvrчN.R>Cm0Xߊ8C]E.V*>"5"bR rKdIOq"u&4  C:5DQ?(z"*<=#y#?!v) z", 1b RE 1kF! kȜs8 1 v'hrz ĠwZm-QtAMW.7 +7X@ +DIR`n$M RA~\ + HHD(ȁx6S;3HpW +?臨G*"dUf@ZUC@F2Waz+. 2hŋT;WlW<K u!2l^~T~8VU!,яyZ%;[<<[|>1pi}h ꣴ\`G?χtQ8Zvt%ۅ.>X DCi|||Fh{f3+4>//uV0[5uRPpG84)_D:+pRo,TC;N~[^BF^却[ҏ8)lpTeyղ$`ypQpby +PvGx~oȵ VǏ!/@37p17PFB&vQnu| rfNVG +Ze-m0:qZH1m2 jsx+fުdpku FtBF<%xѭkL`\CZXjkDkƎ߄(Fձ՘Rg}TCA{ij8vp"5UONhik4liRl$ ?`l~ܢAeG䦅nhHBP @cXvsϠo; %$nGo;cԴZN +L8c͸܎#\3z;poʙQ;̀a\p[0 N^92\T{PzeQ5:Tex0ePFw b2t%SȨ;0Zn7f~ `Jv/#aw1XCS#H<1Lcg~G}1)HXzO COT@ydeT=nNO@sT//Y c +jT #ܕ%#\JȩtFaF$Tk5ÐUgaBPG* ף` +xD0 ya5aGFf m 8>,zT,H_|SE`!_<Wh\/ֺ?ҋ $/` ME@݅]ȍ O],uu9p.BIr'AERqP\T Ԃ`x зPAjŇ:nACB-τ0|y-BYnTPy!4ԢbĴ!R2XMg! 1v ?≇h·0,j DOєHda\,荅$BX  â'XE8KK*!"7d MaN"Fz.WF\%#G +s[q"Xh+jk6bVljC+2+*~#d8 BGW^ܮVgg=)*zLU#TEgVdG +IbT9ٞ`IO4#Dys<[Gp k׉a'G~NPR;r9![N'dpћG,m|&<#,|fI eBB&(@$' 3qg$vA&tbB)\;IJ (:%]'% 6ڧQKYJO 2}*Jx,t%S;NY◶`-q#tI9N'/1Iı/ID&`, k tQ$%+&="$hW{`H(oD3AP$Lp shTH4F UMԏkG&6AG$70'5Nʼn8rB7odt g#L'jD ]4":3#>p'fȈ8xF' 􄩋(kO[ f"gTD?.8M!(FD`&D o$y¤38|ۡ!wyf=ѩ!р3 =?r˗S; ~JlP ?T3%R)  +}V*Wvi*àz*dzT)xMHcAh "Xs#cܠښU_/* +uZŋV2Zp:Pptt_bʤXYUfUc/88*pU<ߺP^"iT($Ő{UT8ڪ8;zZGl`28T86O*yu*R nX֪u&Պ}Ƴ[aDmW>Fpx Ɔ0C  +P0_+i v ,` kwza@,8r4xd,̎ Bun>!&M@,拆/ BL L4 0ő@ ϚViA93xZp ŜZ 0a-,ɵTs̅2\0 Ȗ#C]h#"ƶcHX?:CS[d ݷhvBpQ17\Ċ Caa@0\J:4x\@Ɯ ] $]M&u +.\ ]{~B-ZQBW yͼS^z^F6/wڅ]su{AEgX(sA:_ E 2Ⱦ-_-pӲ-_jւp9`Bh`G0nbr fZbN,4{q,h0 +,w Ccq+s *..Ĵd#_[E9z22< +bϘR„Bcuةcz3rRϏzTk+2gI9 )XLGaGƿ(4ULlI֡(7dAA( +d  Ie [;N2v2](NxpP>3-ՄV sd5x [@ɚ)ڌm.̀%3}Xd*A17%`|$Ǔ`3 8h  _C+Hp]\h4yh Gip^Oa0 WM0`f!ctmNC"*O '!p@b]jBePTF^bFjn0 +uW4@05"f Z !A"a5  Zwyƣ?[ Cle mڦ |*_m\b)jҡG}zɀhiTyڶ ll +vHJ+,\cw\KLK]|\ ++k1/ 3V*1 TУu4 +›@4  VV] +ꐹJ :%0-RP hoRO'4꼛bR!Eqh1)u'& +1kM&H樀cEglpSp>]1dRp LRegyI%b6%2+W%()8}d%Q!eGံ"E['5.qKٟ(fd`Pl;Qs/n5h)VBA8QPڡ2ZC#C+8 +jfl?NuCQ2#>jQˁZk(,+ ,:@7'(/@+ߞԫ-8 'wd ;HwNq rL q"dl%?ƓqHq *']hJ{X!{LՎCvoW~8$R(ǩK^ +p& ⦱R ADy/{J(\K &\I9iq,J%8YbgrOßO h-+'b&gBܟUC`Bsl@)9$2C.$G؈0h4tUt/'iwJGPoCgd dF'v`&dwO@[E@X-q\yA/(dL^"~f$zU+$C`48H;w2d*3xA9 +k5;?!TH}GrVPf`mjW:4_&fw@YsȩP[T"x(X5".lpHU!ufj +>1`;%ը!+9 >_/@Deə. w:b@Y&=ND0NkYsJn@q&OEsOjaϚYrgkl *h¯AZ$4" `̚@H|(P|q4ƠPvqS4;kL*\6üъx.d`Axg-o/P{itP{-ܡVG# 0f(Hx*3 + #)ƞ,p7KU* `,8@oK-V @<Ƅ__o=,EU +q죎'j)*VuEQԘpX2p]K%/09fJohL( +Dlֽ.YۿjYǺ#Il_LBnEsU^حX >aASXAk o/[:fmf7sD< xڋW%dAGc +^ƒt9}?c.dƊ(!N*d6ӂsp\*M5]SeaR/iVF=gS~JXP\Lhџj鯻ztJ8J5"M*ɟnFOȚ~PLWJߟ +*ֵ$ YlLipLM +ݖ@l~4GDt&T|g*%=JH?H+v[*\%O4*C_"B|{1~*7 + YǹHLWhBϱgٛ^ zdw4>zVeQsE9}T*\bXA=W> +|}n".$>q9ǔW,}u~e R +pvc^o2!OMm$0@&OF*G 8iPt{O@"g_`Ƃg?󒌞nFn.A#]nʕ}<@kǤჱϾhbëW&د`p%ű`_DE`` 9ʸ+ ?b3R9C ΍ADA|o ɟ?H6Pq]G9߼F3bo]54! +Plak`xʈϩw3IK~"i,1kAU~åΖ>;=SYL~)V%Y!1Û*>>R\73OJK]FAR=Čt ,34GԲZ~o\qAhq}"E5$GQ|{@B"0OR٩O0lKp> +Y:GqSs{ԍ27P'/NAVh%KÁűݗ+۳ԿOs[iy|UiEĸhp N# +vttl: >%ղ=7V5OMמQ-IUFq^Szr5|4ՔZ ;x 4R;XFSWC^h,ߍZ\ CWN# + |;$S_-3?R>Ze]j07?bt|zyy5e-}m@" |yXazᴉalj6?3rwX>FO^ƹ싕>n&X.-/jkyCҫˍM1O~EJdf~.ߑRo!Qa0?5~`Ϩ@i|I(NAmقgIH ܬ5"=۱捀H?z:nj ޷?o~kA^8L)!}DekH/͂ʁ~S|1x1Jx}ZD(zNn@ˇ^ ?=W[ |VR}Pʻit͆~b?Ͼ- #Z:y]):Tg㾲r衚as Z^q/k4/|󲒌ynQGMcǜقo!`DZ4\7/Mff4m`' A8zPi" |pfGEkj[2b v+/e7O'PDv0#{R˱+@41FY>)PX7*W#^%y\)K^bm҄{wț-k"2&򘈖 +#i"nKF#/NxepJ/anŗqi[tץRUlYz*?.}_|㟈gcO8f/RzWVr +4k:kOLJ3ΏC-#Ffw@&AH`艝Zr%48<\(QhXM+ᕌ[xwwi72?4v&SzżOMͬZx8ӽN̨E^^He" zنN0r ]R:/aWa*@'J29,JCgjp򻝫&kS52H$ӦppY|E,ߵ +DAT+]ktڈs s_zO^\Y(7o%rv:-(N)@*8%(*r]C&oyБཻr(_Mr©= 2O=0 y_w[ǻO弹.;MCXAUD8=q*W/k% )ZI[Ɲ[8e{mAꖘkܫ .#R}0X bvݮc %#i!?m_zBhOvҰ%{>Z/(p)`{ +!Qq9 AvjޞYZ١Km>NXN;s9)QzEXIX +ż<{b) ?8{hc-3;(Ѽ컉KR13武Aa,{4n_;Bv_Vc=:'($UAz0iUUУw6a)yn}8wWQ!!)&p~_"URO::#~_/.RgXyHQ^'uSPq)êaV +"ǯ^U@]g$CIRKѲ]fn,Z43>/vYﷶضI{:dIJ=wR.*bI|cxh>2E,{OZMNV7%xazgNϪ.. xQ8G?ny; T_] !x(sRg[M խmXN>˛QXI9kSF7͠n +qCn"%gXEN7@pS<}l< wʵToĭbqgM콙>5IJc=t d4YY]:v>"!u}O:W +-+ᾶŜHTFYXg!C$ğ6hN=nNE,љFY]=% ll(}Ikt~.tC~%tI4{΁ zJ KX_#aO."G.#MIl}[orz:Є RX1@.N%hxΛP +ȌHark$[g "?CWG@J_jf-PfZεE 6޹^z9Hy:M? ~^:0N.Qw c:Ms^ϗ˨>ǙYAr8q?8(XHp|w3\xj9v^#2=ƿ甆"wN + Yf`D2\~K\8\wC qk~퐖 pȹnxٗ|{I_=I_!oߥ'G +%: +Ze.~0ThV>0#$yNoNy|{{ ^շEf\껶 ΋mʡ"a +}^ܯ~|̷s<\ĈmJx(㻡Tƅ6)|?lC`7W{O`J(7͉ (Ϸ6.NiooֿZe/Aܞ[gII^pa>.蘱Kߕg[.c}[7:Zu:lJ5wAkޅ-{$$3V&Y(-嵚yGE endstream endobj 21 0 obj <>stream + >\uу{ro{I{?4U8po݈'+ayoԾ/vgz Myࠃ ؒl;ԯrY{#BU>OqjM%{rzR{Ohml+½w/h("5 +; jzo /m|O1Z|.1 #8d{>& ̛+vD 'PA<"\%f^oBd/ْF%Nޥ N)6[U7 h&>@Y &Ď Ż6>}{ U1yG$xl}}7pVwntU_]A ;f@fRxn[۳&Vb7{v, ?GQ+Anmy?p莣tn3M%cbdZ'5qt %ʹ&q([.x4I7#ͭU܅{>WnP35Ivrw\+~]J"a[lː]xm *zj6lb{dnke 61 `>,n`67#MG6$oӤb]]dO_BmKm0Pd?$vw,~UGTPmEZ8mڗj=ۦ.dv[.5k 8K:L~R؞=ka{X)>\=wC}\sm$nVn~-иeU e 0aQb62e||jwkiv/>Z)EO;cp$U +nj{,Q(Ѷk2= )ђ~, PhBzжs7+lP& F9e:L|q %LEWg}$΂LP>5<2-IaO x33ݖ- mߥiU@d Ѝr60Z^ד}ZZ=sX0vUNO w!C'qwk`qdL8@G1%3h \ r=q`#E8^4UtN\DѷD61Dk(J&$K_$:E#}!;+j2E~HBD1u*_CN_`W]mکDœf6 b"Su Ihp:.n/%mQUQ6)!AgؐlSy:q%X +ӣ +F@Tk [34ˇ gUk dSm!WC}<Bę2|+svA3r{vp~|_Ϛ=\!j􌐧(y^g9+By&rϋWŽAf4c +OY{%g=Me6u'eŝC(Nah"BLxRRw3(蠝w$3%ݎ;;'dru 'L#PwҽMs=$b+b4 i4l8C/sqR_ywiuz wN +sbА-o4)Jr&kWol>X=nT +ܮi:a'\&g"v7# ᕤBzL*CE:]@J-L)/ris7p/ZΥ|j2샻]<25y@0PlRv1vVYL)\= u۔Fƨ{3@Ͱ:2j7К͐RtxKQ7b͢L)T&QK6? W/cs! JZlpsOnrRgHSnlX91 +*8XC̭'>Dnx޺4_4(@Xiɿ:C؂ZLgw88?Q]3g2#+ӈ +:<%V\S_(3z\spoOgS<"|b% 'dnGIv,%z(? V1*%]Aqf.^c4'Оt +~(Hv &Nhʋ]BIa^]k}w0>ZT=T`8F#Z4̢%{NUsQQʢz[9/4͠&@J ̆ȌyFs-5snT)n-"jD(Ÿ,{t2 C.""iu} T6.%Td9I\;XRܖ~E;SK~ۖ8R )H^kĆNASӸiSZgHRZ!.8ب:Ȗj!ϧzt>:FU\v8Ū3auϦdVBj 'UM< 0ro#58~F~ +9יMQ^`=8|`e^hs[UduyU̺7"WΙ".L;jM\^kO%acTiH\ q-U듫9PG?^rB) +.x}#9T^S6-9UX+i6J~\%A` ~>]Aa,Tݛ԰!taӽ\= F[(OYMc 'Zc:VjsCʛ -F!\Ql M\o/{c1 -,f73Hbvlfa'Ȅ6g ҈x=W7 NGM5HiJ + ]a۾bmZ+d(dvdӱ9-tٶh;ikblFln+m{bn6pW~/dm'N**Vp'pc. lO踁5vw_\8o烦rʹù]5s6K#EC6VX70?ǔaWW`Yޓ~ vf uNO'`X(F02n:* ,Z K\(ݹTą˹!J>pѭO%Kiw54C4~ +^zO.WF@pdhB02ز< +gkQO d% PxTumQ 2{Hq8V \ѲG Q;.ŏI?*Dz5PnvzUxK`.7 ܐih{+dڀF m^>?! 4`v232,?G}xc*@ +4. b``б˙|W@E s"dZar>qˬxg>„(` 9Dx:zp+Q`[jFSsd[6'"KY_Q1) ,5pY{x΀15ɀHc JPeLvb%]C23` r̀w"p~66V6gQ äS.h67Fʤv(`MrJ+ LDWod`"Oz- QFͣWǁk-+Um1*b!X9Qٝ5>\>(&B&(ɕꍣ ;~0}z >T a?uSbsPzݟZC7BSM#f{& QѓG1>?vc_S)}swiJ733 +Q! 76N|M{z6_<Q cjM/Zs%8.@N QG' KE5Xމ + [6vFVa0ar? FP ,f!xaSơDwf O47ؐ1l'~$1l2I(:U\l[1 KH`-1զlXppct,5.i֪֔3ISYFӣUup܋Hf DtR DgJPw(39;͢ / U0oؔ +"KևR +/nJXS7 lx6"uxIL2(_FˉEAl.(~X8&H=A,fO;@ˮ*}6 y`3M!dM0kƇv~$h5RzmNDsU/(c,XKZ;.؅=}._E?KWX6,M%f\QeL?,64+0/Ɵyf-5c|f&֫;S(E5Kь'?= i5 lqe@mqצY^<=ϘӔS"μ3t03|]yuLCl:k2б3#dP\@@,3X'Ni P3YCrc=ͥZ>⥸ze!|ywzxn*kM册AJ&04ߦwfUu6ל'&f{Z|3¹5YpqÜ]UEAa:Cc)=Kfga1\ȹx^Kgg#YY7+\Eo@`pAga1 tRB?(б0PuCW&i뭉'uEkHE`G0it{bq~byQш%M1hQfQ0T!Y ;~_ôȷR +f!0Ӱ06#8T7Oi!@O/Bd@=V0iNQ箐tG8uQmԭxI*wAӶHQk+U~*X}V0[cA}A՞zH ٻ:X2n[YhdI9il-钺giV,V׻"zwr}f=~&6{I ( :K0PbK FkȐ7vnIwM/Cb~7EU` k .b 3ʍ IS9ᛏsFvyZ{!煁s!5433+EyTBMA03mhE]w>v#"9X>i=ZsIAV%J[{keώG-Pb v$&䉸Tbp=xžA=Tp8>ʹ.zߊT-4.6P lo='6l-#Vhvp2vN 9SaCdG"hsa3mƲ5l݉iOÞ:6kحA{9ы^I|GV&5 a}&/jQ-Uʦ+!a/зaD:K . _0 ء?h fq;nJL&[VloIN]nm% Ŗ".Ӧ*gU^CڈT/<(cl9vX {Pf31%{)[Z_c2f35{T ӫC;C6oH{L_VM.YoAZ7 PŭbEE^*=ۅ՚gf2R x3CHR1 v/\= +g{%[ReP1 ( 8o$ =]mu/Lwο s := ˋAv}PڮmHtH +m&ܣHu[vm] ?жg!ʼ=3KN|Z6 eױʁhvlh)? a\d~!s9#}S~nMJ@I;';o_R=(հ?| !#q_F $BmV.BW^ s^@qqmaS`Zmj~= m瀲ȋA͢mL'qym[ ᐶ쥥ɞ6m{cC38-%O}Vm i.UoK5GA*aZYa +#j_ȭqpXh9e%xGB2I>e= iatF|/zͧα +7>xj&kKennwwܤiͷI?}i0gYC]{9U.exIn<-- K9c@4L|n<# OEn;b`xSϧᬆzOGkލoXξDoX$qLz :"*q) I2J}y52`2s2.sdJi̤80y4凊0nwg c$D~ais[qӡ|R%N#kٚ'L)-4O\:fK$c4"0)k妡n\MnI,k搜|cik1ӛ?y*;{N&C&yy6ŷϕpi@"z*aG!O@=z~M~$e',\+25ʄq5!O(܊:>$b``ˤ";*)oU]n;JFd#QZB^"zzsEVB.W(^ ㋝{vK(R 5gȎV~|ʼn:f+ʯvH/"nu blO@`-0[6{S)-1EVw{&zwɱڿw8H)H}y]f{c[}ߥ= +,GEs_~slIKvnHH|dxOk;|b"~&\i>jlhX&Š: 3 oUdPS?F ڇIؗqC<FSO?M}m}fߏ) +_>tq +)A[*菿 X6(j no|G=_y3RDߩ߽ǁYs.+E +Yȃ;<'-Lu@G'G^!NF_Я^>⿲-dJ"#H hz`$ :<}wHJVS4S;cnN%}L鲹~$\h(obW'_ʪ!"uIt|pu ++YoF3"=F7ҍ˨eBFjq.<0iDmDyFVr +9 8判ō.y!)3҂^&x<2ar.IF 6*k&y8;[%L[03@/Bޒ-X{'`7b_Lc "b{g 8K>gQ +cRFR2oQgO11JaZX0(p04a&D$%ʜbJ3ZҘr#]FԷ_;0@Ł-JۮDO/˃"CBmyB5o`ӐMv .3>@Й[E/i9˃P" h XRԃkv\z8w5Іw\ -ꨖ.5I0&:e__tLn25yϏjTF\i.F<"aHM +蕷'2#uUC .\ Qv'm&̲M1 ^32%Km'i싷*EBrӺJ +=XUvA] y͔a(ғn)qC1 B_%/wRKRcWj:ssЂ|5pH(A\COJ,GK[;+{a^NqР7RpAu +3=Vl,I_?s<-UN:n "?`quV~젃?3b:!wO8aGpW $!m#U# *~'UF:5qOR~3]-#x<{ Csp4d~ xցěi藻.0NA]-' Ʋo,osS(:sN_-64}r5 QԳ0mo#hW|”yGe*SSE:vN!H`o@U#\үL[M#0=y7L wV:ỻh)|vt鵁/mIxIE.e+Ɇ< EP"ueCwl][ad?gहx|P$_5,uQmHqv3m%i*lSJu@RFx'xV|z޿)5pI:`=׶#λyϡcb2l3;r6o]c`d|C1 #ibQ]@Be/&ahОr!B4~C%RDϳg0zftevB@w n_꺳 3psNbޜ\Nmbظ;y`N]-),z\{9`;s>`jh^QN JT=ƐHAGDdZaVoE$gYpIzI+ESV+@|7PqY?!JsxQ @|U@W"=iۼ  TEN"B[p}=f97t&#w!?I\LESqs]Ft0$׍JDعrr109 NPvEWM~s}l>grqb!)d9g]w Dos5 a-&D&T̈́ +outNfzNR1$k(Ǝ G'{˒&DTL+]I|y'!tpT)*e](uw7(b +xGgk~!ʽU@dT,< +I\iĤ_* H/V7sӪK꽌%;/;0`MI#xsPs`h.e2Uo`vKGD/gٺw>-o 龌 tץXP_AYd +BW&N~E%5n²6s^G @<~) U?~g΢i:⻟yOqܳy8g/w_kcָ7b10cGx#Kre>~V})ܳiZj g7ZG|g#uzm_N›1Gw}¹^:V>iS'*纠qv(z.(=UdWZJ??Ij` ZHW32aӸ8@_*LO/H&lA_(k|w @QV0`; +s>Ъ؇>Z66kU Z)l/vg\yGX +C@%T[_lx.4 +JP\8@i'EۨV?fM>G\aҸ2lc*k "< Ul?6:&/m KᾀEd݀Fes93HN@,D}Gj>, HD'WF@1 ]~RD4|,~=yD6]tih7"LQfg: ?Cu>W9l36nM$]%(>( h3Qay8x~q>~cH. Vhe8u a*:fsa7/u].]7 u>|}} +v@Sx_[-pS0*i$f_}mr݆p8} +GZύ{O' 1/rf\#('V1viܧbMX?8S/& I$oJ`RaYOD?'߀fCG0B:C0"J{ Y:4i&ľGxfɾ)UkNHb*SȬB=_WREl T@vI&xh#SAԊXOQ!L=ǮT8y'ѯr{O$`F@v@H) +PT{Go㞽d +Q?2ホ"'仇& уq5t^fOc1YzBwoy$ b\ g&qqtp "5J`ߠe-aÓfZE4ptLIرnX-}33pw(ybo5sr+DQ-8IthXӧ-D)h=~!|Ȳ .oIAmz%QD;)'~ǟ@W>~!ݟsw$lp~Ϟk2xo4K.RThC*LH󰇱/vg۝Ž JZBS)۳n_˻۱.'lWav, 3YH|bp9޼T̞5#+"*mk +䞝#3mL\wƅ3e昼e/y_ξ,\/Ce÷GlW0y˸ٖܲ;[)|g +8Z/"#Cè}ܗ,uﺍWg:7Vot6/k/y6}[aCP%RF += >}[G$Eq41*zbIk'?2\HY6 /tg\AyhS/" L_C8e|&D=&t;w' -4Y˜xX3.q x`M TTv4uw6ηH$ @g*m@h91wm[nsHW|Oa}n?;&mH]tix>!I7v>&m[}$ʎUCy̫]^ 44MuzQG`|Y;0k*u~L^ZRg}/u6K˲q6gk]l\ui*>|gi K@};x\yp]C)x~/suW5]:v]g17Ocuj$Q@d_"E5r=M{k +hK?ux(0ɾ\?`xE4 %MYJ%݀&dT}<=6ZFI<4~U/D)h<NKqw;u|#qA6&i9;[o麎";yR YzMzFwj+(VO]7g(NJfĢgY#F*bרsi?|"}5o&ls>/T *1.vLGc +X4v"Ph(uVNʺˇ'=Y9߼qwƐ]~Ewr];yO}C4m&үYj¸Fa(Aƾ8utç&GHy~;:֭k꙽^#(k]铫pg@8Oe:̞ c6yAֺt d g|" 3_lMuHӸkjAfAC:z}gQLɿxeh@z37I݀ewRePS/<8޻ūF^JdDmWD4ZdW30 o Uli08mŻ#3"O.$?_G|g4y?;خ ;w u}K?Ӹqt=l~嗻.Ɛ85p ]8w, C6ġqej6?aͶܘ޿m _\YKGkjº#IjW*=OSVg6 woqhHOi!~zk_2=|'m/t+36d|;lxe~Y֮ʽ#Yej4m>^z&l[1\Wr16XvkcҸ6pM"Mㅓ]ҶdÅ/8dV&PmSmq0nuC5,;{ g& sAӒqL̅˺dٶO=ٌqw'ϖ[yjN'4I?H.,Bءi_2 d ,~^G&Vğ4jx8Ƽsv 'Xqt?OvhS=4Ih>ZovI[36f5r=Fmkcf>QP94wY]2yl}1xk ۇKj_v\y+F(;q<;y+i ?aK{oSHkM!LߛĤ]Tyhy_9w> ^ڌ. +mJ;l@8u}3}p\]yؕ@!InPdef^vƁË͝!tnk1h&|- .3+ ;΄ٸ0{jlic6,&m&1k_bشٷ ^u`r\,^WEn>ųbִ2m\6a,sȶuyj 6ELM˦Y7,Fm;p7hPliiUa19@CUTńV3Q1Yi1qiU1TT]ZTRLTLTL?Gf +,]hfbJǶup7ŁK kKK*KkIK΋ji+Gi@u5EՅEUUյuUeueUEeUEee5EEuueuEյՕueea+k+kkkkj+kKkkjkjJj . +nՔזV)+:-+++++*YAN[,*,, [XWS[[UUW]UUZ[SUZWTY[VU\tVVWUVWTVWVUՕԖW֔WהUהUזVVVוՖՔU֖ՔUVU֖ԖVV֖U-.-++.+*-*)-,+++++-*+7V7qr2\ѹxS&d24;cx%q8 /no80E)hIXTKˊW`q +\F]x{˰CY(Fa\@Xl5slAqe-r_T1rsPI +A%.,bwx*Y1ōo@vdp=!-5`/vKe`X74yŠ,f&uyjzu A#Ef&F'CK@;mQ@d3AHiTˌUDB3#U'!u Lz{l@@Fiɡkˉ01RfB̏LH?x~~2u}B穢Jf-fKxC)RE*=[̍b>"<%e療J['*jAt? 6 +0ӫgG!DJ(\CA(HwI9}D(cM"&9)r&ȤVs1 +2q $ 'Y'Q P7@xKz̏,a +{ciƉX3u+'@R1 R1@%bY +i-@byB`(&erc(e,q6IDXJ(+r#|' +k1y&56o6V-0?:arK.rW.rk¨FJWӕI\i$xC7;X7?B=D~f1t{x-]`,QŭP%FLd~f 98d%JpZ  ()praI"$IJ-a\cXG-sh )qB,IIcF7rwv* u2)[xv;Q2 )AiIi$G$bMIX)]"Al@%>>6ݓ~Hb,ĀJܦSG 0>=dhi"pH B"!0 L" F"Wr6 LQe2 X:m\YqT9%|KbƐ+w+l d9'6'hEB"QEa-q=aasc]m XTe Z\xKtP$w(9 q$FĝE^md~ ;Fy〮gEN ` !)2 ( `ᤸ8Ӑ* B\?2ͰaBEI9cZ$,6,'p)Qj;Mq}nzp\ Psܗ7mƉĮ#gQO O@tJdܿɈ,CBhY]3%)~ْ?3ݐ=ht:NRԐBlMs32kZ$n(%;iHY! 4MO*u@9{ۂ2l/@kФv0-(XS0$X ʖ҆3NW'rK8A&Eer'*\+k:}0xN|3,4h@#_QH۱9 ()oЍ +ZȑO(DdFSTZ-+ ՠpN\uHdvJn&3zCFq',j4"%Ԉ))q Iѽ"dYuf#s4Ky +[eE={J%nG%[<QhpC>3-~l8#T`KJ"X@t:ZfքEq"K"NRn2-a̸7qq9L`Mm*/y + + פE%2n +ZP + rٶm[jwT|~RАPn&VlMU>QDqbe!s&dENT&vN(ab,ZjF,JT%l%}`{B)C& +Pn*Dސ%aA/TI3\YŚ2(ǎİ8 k#G7 4IkwÖ@ѭO\r n# 2`AYc8zh$}KI- Vȥ6h2vZUX86-tf M9`\0]Q JIR!dnލp'l1}d1S$boО BF91+1f[ +Ę wUxt6ؠXd3JY~"w0 3m +~Bw.2r@^tz8s¢;[*9q-VmCYi)'$EpIa+͵RFR@Mdwn}rQRc )Pcf#5^[46'7|‚^QQ,/hn,d(S";"ŦMH`NTTU[$ېh"]X/֤ՃUY]E>gfDEw;wd@-r ƌ4: *ΌMJ<%3IzqUl4Ԡmb̉Cܢ2irFDJ2J?DI +k=`aԀ 00"7N%d `+7d +ઍ@+K(+׭*( Ja`U3$} A(CF` q + ZH2:c:P>'2? +I^%D=D}*,̕ÓΒYkOa3E"ۀ(♁Tz1gLH^QNg&$&zU) Hs~&z(T +_bV&$>}N+}/H!@$?- 0@feACB-FGGL>"AҰ} Uf"ML;1~iwi&٥RD~'ݣgDe4nUE$KXb*i3n 6hSIKA3& + HȞjÓ8ߺTZ`Hi>$jH +LHU/.Sk}$Zh#| PHz +A>? +K6_V/񽐔Mf_ +e<( LکUI/ !|PJ`xGxY1:i@kBQ:vh+ O$k$Uo}8'ۄfW:7H1FX48 KJs]t 0_7<Z_Ff*Z=Afp +NHTŶQfЭs.X5Dۏ *T`v(/9h|Ά*̚N"L›>5^CJk IDZ5<@AȢB'aPEwhe7_Swx_O~b]E;z~G i +ޤx PDzqu@ 3#?'W;Ma cF}-c0>-49lI^I=#;(!RzJ%$eŃvێ وH8IHחT +%aO4*K2|k5bYZc蔓T5aW±2:3P9C` +#bMv!g];&Kd +}@IsଵXpP~)4lC2Q?]AEHԛRPuJSדUyVg,=(yC[׋4 :*kФ3IJ\6He"^̈}i?%2%@`]t׈|x==(2!A~ݧT[ FHSE^B@?֌K{DgacK*h7Hy?.M⮒'vQ"u O*Ff%z}`]٨~BD#O؝Bx6r.3X6kw:GUC6X1|mr.s9`Զ9ydcG ^HҞI;kH$ ( j`v݉5|@|,ouU : H0&i5AQJDG"5Mnu@TPĔk-vO65pƐnG ƥg3""Y"S"&ƛGQF5!, ! )R058Y;c6SbdUΐusz GHgŚU\+PY/Pٯfd <<@v"Aԣ`H\k +EPg-R zOC*~Xcrɕ:A *H`oyij>ݲdt~W/WﺓPvP 3V[־u?@g#0vfsomøg[S"*›f/sm옻5M!g0%G R*3&N'$ L +Y70 O'R?~uѶZ1i7o<6AyBRiU/˰gǾ2dl xܛ}.E:iհgȤ &ûnhwn6fЭ#uzm*]iTov `}.P&#λ~M`O%3)h?;("*{i9 PLk#M? +U ޵?V?P_6/pg _swwfJ߻H޳" o%NpT6`h7&QwAu}1n&wo@#u׏O+feT؁(Rk*cJAYJXo BP)-4 ص9<|]S, kRٟVS&,jISK9ء>,Z38kp'1ϟm!8vw ܧ铫cb8Yo{6rߧu>q46a+~o:wzbV.f56q 4sV z\ MTe*UŮDK +ICC' O.:5zlr7 B|ÓXWmo‚MJ R^e9 GoU$I3"P#{&/-r*r," 𰕂a9:%f[15 '|7O T<\r mL CG 3nrOe_Ǜ\3h7eyKaڇ,?` t98qvR> SX_rxhS.*/2$Oݺu-[4Z21!5ż~<P,nF'\,,\ YNeL?okeS%v*0a)ez5%1* n Oci1W@ VK񽖠T..BUkM)-A lq4Tž L,hmܭtkB~]!  8eZ<7݌1ylܬVk9l\] 0`ʌP#+=ƹea1yn\'u\rzhr+dyRPunAB%([_Y)1!JR!*n3"#cP\}׏R .%"uNbLC8'xfGy'2VJ^SVZG:QaM~]1^w < +y𝜝,]v('ioK^Wh70([H@U&RRB eu4qnHObl R@VȔ> }"j]=*H +R0,g xöĒrF!dP6꣇bmQ!"{ceG^ʅ-h@ٵ̷a8 xJߪ!T0id.k\,')\#[ul)XIn Imخ=yˮxnBE`Dq*:%*gHU2U"7{@T65Wb?NNfJ {/&ӮU3&.gZ961vjo خy̫}0/vjd Làb``x  … ܊o Iq*WM,ϧv TAR>pHDZA>^ZZL@5vܝDjtdj#lQv@AQ1g*,d +Y#}_n;uZ>ցCp`_x`+4<<bt,>}\52پyes1d~X["HDZ%@3s*% BprRZ^ZV1iDbXX?iKB_ȡPmKᎀ$*:i&BۛȈj-*A1iEualZu9\̺Xyy .+7qcմY<[ 68EXpbTv`Sk Cll, dJ]1nk%dTuh=n>lxNvt +B n-(AE`lg$?rCHy)Q. +5B #S؏B +LyWzD +xF8G[G|gevC[\*z]Z\Ev=ȃG4 C&.l'OE=%ƬG\w֏On.Lt&#ܠNѮ4Pm|d(;{3^ؙ3p37[ڪt ^^dv^Preabac8uo`&6ΒZ.Ma Ӫ:ƥ6K2- JNAt an!EQf2{lC؀0 +!vdz<.mp n\.PKKƜŅ2`u URW2?X]퉌NKSLx.$u`Wg򎻡d @&ƿvRE&Kz*ltc2|zc0ovcCcccbWpKԔ7tCAD [c0NPD 34=p0n0MF4@n_f%cTfR[XxjR8i-؀ +BXUNǒJɤhic cs)ec-\qc11y|w$m|8dt51$,YN3@$pÐu*}E='`WŸcjށLlR%{$x"".}qld[L0T:P/#al1c ,BP6(D_o˘L;.zx`v=s[./zZGG7qoxV@R BĕBF+N cZ@-GH(|T:a\Y ,vZpBD*` Ъ . +ly /C@i;\ m|C 1 Zf`L=.HY{-CTbX 8\)ΧOJ@ P|n?[ĵLJG7pHBxM&7l"- m,Rb1)P߫Ó,*vCҏH ~\%,#޷ڳq4|Y[\@OG :1\6X7xiAx +Y!^QcƯtLn|▿_pEyU@ɢג@4Ĺx,`4Bzh,I6ӐG_-4:ZdxyE#,fk~28t]BbZg+KLXr+cm-bQ,Lg2‘bi S\RlyAOiM| A2BW?G|K)$a&xj[OV/ q;B\饇ȼ9C?;)H@7RJO[Ǭa l\X[N.:8v&9)F'fLd`TTJlXVAʪxkMS pA3) %q FGB**ZDG|w KDRT705q/%&d3\LM6hq5"; +)!J \!-42EԐN4<8Zp.ńm   P4~u2륄,K,3!i{ q0#.TJRbNF<̩[Hj3ĕ^?kMLKU)@Yfha L92H/06~p~m$)1bS%%jPn12 +c% GH9&#xFpsUMmI1qF +H+M8@!M5C\( OK3@?@3ęn8 $(,0k~fII3t ߧ#J_6Rk )M,h +6’=sPo,c .(8qʪQLmR_I4тNJMo">2%s|Džg˲mw02ZxD砑,Bxi'" 7zk$ciEKX2|9; 4 >De(">8_2۰ :.zx"eSĉA|g<4AՁ,\WX8|m]qbqa*^m@*>˥[q/G5 HD +Kp3?< +&/,:Ç`z8SP1eGk§CXX!LL\Iɢ +beU)LR9p2LaƧ*:KRƢ.m5+'%dįpx S7> Y>B|+hsq@FJ? >ùKV煈`b`/Ё3 `fL4 { X`Lđayf"VMعIZ"a ;-|7q|n2|āyxJo0SNP5q5=wO1?|)Ï9\e'q"~o / +1,X*k!>R7' nf1 btC'G7oD!3QN"4f2j_q? + 8A!F|p.S_xON'T-a;D98\pzuiĈGl)bX$H:8|"0yĮQfg<MURbF9r] +P 7;!<~Z s*tu"dd&xIU c'EEr#Éx7p2gLc85,ךjl5o -4 B0ͯVN B<*76ht" !w OD.87^tk|!JIo1"` 3`?p]<_pxosacCx YK6";J67Zhzu@1SL#Ŧ*'cD8X;i<iCMU") +rHIXh8 0|e8. &!R tez`RE!Jqzd'r=>5E_0"Ҷ!9w];.5u=B8z&R0pi4e\6sF DDyG%TDuDLߛGwx_ "CF0ot0pcOpV*MX6:e-rTʙ)5u~ѨqRȤtLb/&1B5zgQozU*44cg2MD~HSUMRDy6ENE&ͥcTJY+6 @ mRjc)&oB 3*."8uŐ-Wk,U7bI,} ʮ}"^GLi=F0 i⏱YPM&F o) +#OCɾN94 2  +IUwb 7v~GgZy(!]=Va&$ӫ +bd~8w_GO1;xH'XPG^ZL\%#W[82;砙vwV]ch!Ac kO@|* Oc}鵟^^h֕X5.k:I{>X BQjFeCTN0".ksYkw{zQ!$kN)&?iT1 +ģL [@6:i ZlY3>gWFmY#EI xs)[]^lRQ Y +=b[R+-GhcJq{ KA~?&/9߼>B҃AJs&t:yC@,L;)>m+a34X2,=7P+G0B}@4k jAo NH XL9:fqꜰ^Y>8)XTE*o喷3{p)IgL?Fv˷`b܌ܛyܫ} >S*q0sgt6 f|*"?Os֫\HOveO5@+Ii]!H*]&ۦcڝ mq;Vm;^6WYF'T"bO5&QK@;.P*QF&uCtޚYK\#("tz`5lFTTD*K7w/_-#ƕ l*~{Q. s +K Y< 03|m{-άWrZw$% NPk&({Re F0L?f@EϢqft H{g +DG`TmNĠIAcWR'@MR'(5y:\gU/ZsxNjm jǽ6Jem5}$Rb]>,~Oۆpx24 tee wBdAN,(@~ ͳgA[ug"2xz(osZ7Be +r#l>aa1tmtg=n:wVȾ $uCtk: 1^=Q ۣqV?Ξ"~jML}颧Ja^t]9>iuIgbG}pruJh?BB%ADH݀kbgBM BP~r)8QJ<vsU)k\Jٶcl +iE 3joP5PA|z(¯TmⲖQ. ?O]zI߅cSЬy [-F|%TNu^PBGxB۪ťrqys#dzh3@!|X PDڠfJw6(6ULkGjQIh]@~G ;iNiu@Lξu2-ً- yż>i +j"NGP$({& *ZgT]Ҵe$K53n L"drq:zQp<dgiE_ȅÓpzّ: o6.8v +H4T)$ƟY~PEVlL߻f0ԩ4|pY~%o0 %,*IɔІ$tAcܴ3m3;.z +JV Z^2&?L`ځ+09!H].̜ZgCӋYXdv(m KL>Fg+3^\J(b*k%z<@kCU +zL$ΰ݄*2ԇ05%Eu&k]n;>$4+J?(6 .͵b8͡G#+YX:.*5Q'aC[Ӻu2l~{Cԡ7s5LjǂI[Ь^sw\ףR$1+Uj]Ix I~, jhD(MNeeּn&P9DwQeaHS[Yh+y"J`[Գg: ][A}] 3w6u]ASad!YCT_Hi0vjN#zx%CnB9 dFZm/"G>}b$U[c J/&*FP-Nv} &[3: ̛û^hW($ϯmy8c:M`c5pw͠MvlKwƐH }uV inx| +L4~!JAK;˓wz0tj8`èL}1xk\y%Mڛ3gٸ2?7R#3q߉6EBm쇙Q40XR3ƻg|j#CfO:-<}(]-}9u VI=4pxgCy@bŰJ]B6"?:f?cd5XqÐI7vv [uk"M/"wHL"A!MAB@&$#4Yz%(XVʅfsQ%YY3* ʿ,G^_#8a=LBȼguk::N/ow]3^$(tvReH`;{&!B;WRn&  4qt_fol5{m93&L[ǐ@}>fc +Y48i)$}.%Vq$b1z 흁CMIÔԣKdoX꿈~}IüVD\tXm NL#=Ckݺ'_2EK4)4g<7KWkg LJ$v RJ`}!JA;Q ɔV݂5$1~k.$(}dՌljFD؋vqƣE7W;6~ G[,(̉5|]Z bZw8RڅtV<~'qazFo Cez/ܭ#r5escظ0}j[XS.Xz^2k DNӫgPB|=^CwDvO$]xwx׊ _8? j͵#T>57:z'2N"Q#=跏 + pPS1,g [@h`_}1b)(YxJ< fLP(*s'DDZcs$U@Ĵ*ZIbBL6!^p<: e>uȦ0rh-5`dfZE2m3 CS\R'(;%a 6un"gްdUDVB{4nomjîӪ?~>|ğ#/vg?-# e~@dt:;o>:nmnB /qiWV{yBaJr#,u 6хBVրϣ_3rURm ]ZMnay,hPBzFl$Ew̉n)}u6=O$'4YW6%'8:>KY;0.Oi5##j{ 9RT5s+!I!BSzC[QŚ'OSRQYG8ʝF~·e]A@z19lw!\ HRH}Pf`gr .#yEqܫoVFk*X7yU1,k'$Q3*:὚GwD:'7/PAY/ IgukJ?OfՖY4FS*,=)q/SJ7Asv?m9Tŷv@}8ۘ٧'qzL.ҦYL][Ͼma\`PYDѴ6^δ@>h+(1,$D&|zh+m^F^ϥ $Ֆc}"d\Lb;m浖̅tfZE6b9M&\@"xc2orN70q<O;7oTAԣ:iW^{X:8%HX7*L=Jd߲I[zV).VES%(uկz6V{/D!Z=6k*{Rnr w.t#3̾t@4%)9 19Ěz +MDTGhaTꭳrpNk69Kwo2쥇$tr!ك4zߚVfM9mj+vZ?8B]J *?f.Gg:k]8@g&$=Tl]~o'(;3OIþЃYa1{m􍷮7`Q+!@88Ç&uB{fԩ4\֕h].wM(y>AfPsXɵ$u>v>u۰ݽՁ6 '?v%F할rq +T\v DL#= +d'~To;yD3ܕJ+dzhXT8w b\rwQԣL2qKZ'K0E1|kE:3Ị_䗺XP\#㈸~%$~#QĽ߀&majt"o<H/!t|K/cWBIAI1wi?JP~J0<>sahc83Oߍ̱3|mn$>=GWg>n 3}DTP%uqܫCޛL9X>`1I͜aR>Kb'38!i&n$ĝcsF +(HhYy6ELG?;q~q2 =iy _ ANu<[`/qf3H23( W\vMv4&1* j\oIgeBBˆW4 ͺ .ujfĔpD=`OgU>iqvNۙA7G\㺬cY9O6#7ٶu7;* #^6sO&a3ms)b6&[ҙ8E5'a l]hm.1NK(IUkܙwML1+"tN]A\8@i IP (i ɾ>6eĔRZ# F_Hߨl +u$T(FbܸD<Dn9L@t ƅKXqR8B(5s ]cWSHDJ~D" Um&hOy'gj]nwh鋛,%T ?}&,wX5&/Vs216F\ڸpxO#k~@d^h +F!ʭҡɝʽö.2"*)q[x}MǢ]r}^mp7NG@Vؔx\@"?:zW&԰ afĸ:x׶YglJ``e$1}j2ex _\L Na +Vx9q_θYVưN>AG`r5Xg-xvN> "PeU~TN +E8޼nsHwzR*~tay +)&z+stt @4v MTNb¶;⾺p|_д63.%971T)]2_qK2 ֈCESgwB? ]6fo_9'WC`F`rE`"iL +bH@`@bAkS0@Ģd<@GCĀ@ ӢCͻg9G`D Gt*:7JtF4blO!ߜ}A/ʹ5̟lڱI=ߑB愵Mg2}9-qE9VNHGI֫d-~P'.5t >$~-B]=~8{B_K4"xmg˒Mfٺ9 /ܬbt[gY/)^afmt&ǧDvXW$tk:[ c hb`).pT?\]^UONR9_C' #ή;di/yokt]4o/?bؗg8:Lc}atY sr}UWtiќ|ʞ WZK^~f?N|\gYF%ފjk:=vwg݇}p?(/tԜYha^G)m9o̚6vtO/7 6W(g@Y,} jI*pGp@ +y{>1-QQ2Ź=Wn>h}@Lze>? @n <ߥF{?3?m?uu~֬Ga֟/Ʌ={}~!j*t[-<h6 @xr yko[7@J꬀^ Y5l bZ8 CqP-64ś/~v}*gִk˟u{>~ ]5kkm-m_ FTYgM==𝊳EݡXjk^^?C\_t^"hOu8|2SjBN^zr?|t7|] mì3gbpGXkCJ Q=""᷈ ns:YeXڼi@;^z/uhϘJ{d|ّ6%慧c} 0玕'(tuσREyAg1j~fTR 0tQ|wjʵ3=_ +[ sɒNٞW9f_zwZ6#Ҹ]$%6cBdVӭhOl\<Ib;8잰Ry ۑ}RaDH_6 8Qf9u!o*=ن~>@ Ж fBN E:oCWWseyZ>5 @އKxs~{tSp7_j[8GH + wVl +j^(3|Fgէ<"q &})nbVX $9ћe{ug5y=wj#ډ }^_DDgc`F qh&(峏igq0FI(U jh:%?C E{~ʐq[9LB|bL̿|\<ڍv6z9LDjAm~ӣ ϼeu}0k!k:E;D53؆NbfgC埮f.83c<\@q-4| Ko@Ǖ;9Csz}ַ5OBž9ȆtՖόZ(mEQ!xٲёvhg>.IwؓLVYr|Ƞ1s5sSUW侷(|39sY_.k{; |qgry|rHhrtvK'H-l zu'q>Mzh37^],DH? +zi%bt$t`p#RDM`~ W,4EDk'Lm U r6@UX($I- ̽(}tRU]q3s +'2`W ?L12 ZeW~Hwv"G,iPnq#:zTƟD҉̋ U8C G V"DFqV*0U@ۤEfejt.K>>@G4oIJ(>A&rmRBT$ߐ:a8`+(>]UQ#c/jSy9jRS03@t9 Nua]¸9&0LjR8cuӷ.cI{ uŕm(t犖ڹ})e/Gp GFuThZ) . ?iYUa;Il+)+@lU `ܚh4uցkQcW*,DkBKɑQ $;k?}+2t+j3;qnjzbjPJOkq$Rn4I'9NaZc/ \O9=?T#saPb ][T-P\9kESlH]1xGRf+Ǜ0;=|3Zpamr}NA.';'&yn󨊘Ll% _-t6r!L§F~^y46}K0[jƏ쟐\}"R4eceV~}N Y}bS+~>sl)PoIbѭksKޒD' ˋ='e.6X6b]x ͘KTh4/Cn]Y[" šR|ரd#F=6ЧK ?F_H,3EhwrO ސ&u9lxfCٞa7q1\WW5#e:qGKfU&wa)֘[Ϣe#.B.g4$tMM0yiAދ$<[$[hngt4Wtf\rǷnj Q_3l)YVl?k FE' 9#'/r hͩ#jH BaϏMx< + 7FRR*SJ%1.4ʚx&J$1w깥μ&Y<tYCc2 ֫Sajjʼn"# '~{禇 BE.hPHd-rЅƋYBC>t3:_HàU%{Iʒl-?҆ѩgch"KfE& Avʱ1GJ'Of|@ j 6kLRÀ +^nq45j2}З*,ack d9iѯ?cX+9Q2XÎ"AF)V5'R'!=QD](璟/ kS77A-wusfȵȿsKc(;^0B߁k9nJlDtR_@xD Sqڻ* q))/XmG\sSMQi2_kFD4K }rY#"?gJA;#2~N&l͟2pm$ + T> %¸+(e{T" w A kB/zRaaPEV§GN ؜ `\F~*Śt)l`z,dXB6v{~lA&B~Τ w<7_uΦ"1tSwxPx;$'. +iLOZc>]xvn^+G RH>RH#%Z]$#>lgqVj#I>/%\5 ;3򯵿$CPJVw)ĩr Ka^A5XwWk1DXRp@34wep^KXaYD"IwZ(Oe2]ט5[[cIh?#N:eg}-;c!P7+|Y/ZäLRCS!ըX&^:,]'2Ftl ng?śi_ PBJ) Z3Z>^I-*ZE>țF*d@.gV5Fmr!+Om7֚甔B ޳1'ݲ3` HD @-M+rYE]lroRf +7ڇew YҮgQA:,T=}jEpE}50l]`cIh׿Gr &1M`+nk"-6DwQ1K|iY.E* +(45$~VzmoBQ>ZGM%,KHEEBƯxI-w6wfF}CDw 2SI^f/B!Bo0"ZOghaw+5a G#<5Oy.йq1M;XJIUyPdi!w@v O>]&ym{XŭDRGsfv% XZ/7{)sX=]c<8a1JMD]-RnA7'Dn9+*,BZg:mHBsfCIϝRH-֝gLj=;K}B N/ݕ4tc2dUfE/Oӽ&Oi>um{]w#"+|l-E)Epe6Re\;)`hqo)Xps`yܑ/ H| \bJ7_*vK0VÃeCu$,dꍵ5KGP>DBL[C+Ҽ&zqIw<(I\9fvd-\qǙ_[|dIBv@/UdEC&_ۢ0EXM+o@ |@St}A:sOI/H##9-SE +~ 3+\B>iX{F=MDW}1}DqS4DWG樒mR*GJLV+~Y=2iD`>?! lڹVܨsgbPPuL8-[1f9V306t99kjb|g gBUZ-xʲw/҇Q4vx)|> u$#ruNIl /, tPTQ XESt<:)Dx;db}lmM4P?{O O9;E)C{j󆜳: Yc i%R{o]fCM~tLDvj",Q 9r`PtׇV*MV.] !-clz;Y& k3rIj>iKŋ牡G>[hYwY6XDJ7ﴊ 墵T]DKqecDCtyĮ03C5 (/Z94 SP?AɴfHբВ:- +`0L<i `[bQ&[ v14+3Ն٫=*YzeyTm}LJ1<}MB}[(aUR1!f*|/ Q &zPD7pr`z  &V:CWf`SkW&hGqTbAwYQ*e)ٵ3֊: +D]W>Dum-!["+0?㻭l],7'63˅*a`/Gidy3 /-9\n)yh9PyW$xk/^r%y,gXq<4_+SnK5OM7}Qxdz·\bOR"asdv v.C{U8DkNp32K#ڶ=7U"ǐq +#`V/DS@0nGUz^WUzP-wXKŔ9klHMG3 LvXRhE? +J +` pt/I 9_;of ʱ AbJJq(8 haB%$K]5X0EP .p4 +B7ݴ;A-eŰcŰs/k Y(V@#A k,)4?uΑh +͐d\/ 8 pDKpu~Tс3_%Ó эx*U2Wp~b֓^j`XP($i*)AT@KP>2_%G1Wz!6 @5՚mMw|V/cwܻf{7WiL>Ԝ@|y5_7Zꜭ6뜭]s]Fʱo4zM߹gݽgXkz;I7k~۪n_k8^kq kY=b1k\WkL?m_w\;cwzbݭ>K׷Zj|::ƹ]ӭ?[/aތuw˗^L?.ciVo՘^ݴ_m{Ӝs]F78|c]lqTuNYWyN^qkksR7XGW~۽+Z[w)ONƘ޾]%M,i%M~5k{Hv|wvms"ּ~k_+T+ohkj}{y֪~_S#j벭OF/FΚ׿7_}r˕a~;xּ\-הg]/zNފZ׻Qoŵcv^?z[s. Oة^7vt;՜]h$ڍjw;>0ov{ݵ{r߷ױmcjxW yӼ;}__s{|SZc-3/۸m~ۭS{s SQ{7?a3Qu>oZb*j9U\;m1jQϱsoF9<0|o~QN9ک؆rco7Qߨ 9]I]_=űX +G5z7|ιn}gOߍokQuo4?u^u^IJ畴y^I+i% %+ikOVwY~z3kR?wMDLIovv[o(7mS:sn3VP=<÷_wa]θڋy{/u[+1z,. +MnH2;K(i[GS`j>P[_PJMӷyi￝״se~ +t^K'4 lo[j3řV~?&J_)i% +4u(ie9{c}7돱^n}ۍ=ml{|1us۳|s8߮k뾙uvwm9jj;<[u{շ<^7vNL-eu⻻;]-|{sۋn8jsߊk/o>oM>wzk?֊~b*^c(oo{߼81"襶Ԕ>HS*(iXU)R*(: 0{Xy x]vKj} 0ȱ;wnݻaZA/E6믷yキ:ckY[7ڿcܳlڜڜyowjL;|oި0ލ-[=v(619oXr{<7}fYIjUJKL[M $Ox&iZgh2s$Kd1\Q4b7I$j"[(,IRyh$?~P4Q 5)*,Ut ,?t}I?Hc~m޶m>ޜ{yv/Rnzڷb.ђPK3Fh:KQߛNL +sޣ/ +⑒34ǐhtAW }`!Dz% #d)fq!|{}\o_1|^{1-]o7/YogNM D^/Z(/6woǜ{˳W Goxhj>kW}Q/fo]-]{/^<4[Xo7=Yw^-^s{w5o-6^^[ GCyc=򫵿vzn>oks}9{ޭykpt닇b{{ͽsn{bkz͵x(V:߯;^?^8/E^89Ϙsݱη_~˳ޫ{α_qƼ}ᨶm9Ν1;V缭6{n1jup{о3fogm/gu^<ꋽVnq[~˱vݽ5g|P%_5x_W}(w{WKŝ1{ߚo/Zoorb߭c/V/z5[/9o~/=~9n}WKoWƖlp狇/;k;o{~/ߟwnv5[g5g7w@`c.zwmsߛۊE"'r싀`)a"L!r$E+B (%)PabXTᇂ\u;ܭ>w֜[mv_l϶˳|jw_/7PxasDIi +P$S($*05@o:A2 4 uu/\PVRPPKZd i.:ިDPPaZU`HP(EB1Y&,T9abb'oE ~'*$L>pA8)T +CFŇGp0y)B@`p)f@Mb8 # ܃t cb0y<.ŊPx$aMx!GAzGy=Z.J1PZK"ΆvPH\UʣR09FyQ4o!iUis/5JPH L8B1!"M?223Ql`$؁ǂ2*T1|9 Lıc5r64 Cdta +RnlTj4D E p5V@14>^CU:V]#CY2 +PHK}al2#8q,Ӱ +Q lu#P);;P: SQ_q z+A@&(AQAߓV)JOtB|'&Y(YjZc9?X47Lpit +. (sגW:#=/$L i~(O&t/HC7&/HS].E05R endstream endobj 22 0 obj <>stream +|Qsm\ j~tuz$5 )OA}#~*+ل\5? +a>r>TMJI "t"~WHrdx/p7`K%+0* +\#nu1\%d(v2 +q@/HQCErL#&2dxc4bTӈ> m=B* Ct0^}FY<@$4D4` bFEf@3D |4($%0EV d k`(B*8L2T,H Bd a6e CFJD^½߻Fh k̒CA)E(r,+Ś&kv)[IXjj5BP#e)"",yl@rA^k +Άs;Hʒ)Ad@R Hʂ),tv,3$Hsa/ VWleYJC.=<¼y@0Yؤn#0/l* c0s9WP<XH +4[0.ɫ4@BfTl&"NDC\n"8ˢI>^aVq9xy0Ki`# tQhӐ-р/߱r*%$5"pxnRf^M%DJaa(UU%sXU2e C8a,f8JVjpmě P6%*EwD ¤5PuP #M$BѰR;in"!!A(Dʭ]4Aʖ% `] 0 wlP4,,ElAAAA05ngiTEC!((88ʀ,)!EP$CD4FCDL69FCq& h-Z mA+i/KMYh,Rƒ >a؀+W9 +8L9"$F6=f*}Ѓc21GN5M©`( +y-d3Ex>ąs L.\&@\X@L1p& {pan֫TLd"+`S6R'&9X(צP +0)Ppf {? teqq #WI]OÜl8-t: 2|'d @=H@BXаLitV@TŖ`#+t%ցD78X4Lx@(8WXވ;xdg@Yg&H[@4KKfa *xF$ K+0; SD((Ip~~r*; P$$Zu̧ÑSx DŽqEyr!+4l{oJBME91i&we! a(FЂzxSx,JBs$4~8i9:6T]08ױ$$o7uojÙQQ^ܰ7>PvBZM Rd-Va#(#̂4eEPL/ +&6#`(/'>rE +^0Ga@wVņ]GX°Wm8(&ttl(`Tہp1XO<2%2p N},![s%lj2H0 |$X9rc[CN̦9H#pM(F?dpL0aHG,: AGw҄DOc Z$]]]3bAђpL* + +i9qmZ*k1 f ~T'-L٥,3s5 CÅ4t0 fƍk16."LJ w:drAC&h0Xb\e(ZL _l ; ;My +7W'׷#?H#z(GO3(:YP ЂaSI$Uԃ9+"cc.|!d(BbcZ0WƋ\qA~B`Vkdp´"-$D1?du͆BϺT$FB1BC ނ+ xh $:,K",U!dJ +qV+`H2>9%*ܨ4dDRF $@p$eȬfP2xRD.@ GbHqA +dB*.ɻqxj@RQf"r0Bb%R(x"I["hxKY;w@ 3ٴ>-=AM r8G篲g$Ayt7*t*Xs3u#l%{%wk&:Mz{ppY@}j8s/6ҿ񮮰k&pb"0o]ZsO4&> )*㋋" C [M!8PW0zҹCE$J -{j5QNًWkT-9v7?ve*HP4,.-/WL捶g!XƸ{rm @V74eFErm `cX-]n`GɄ "'TDXβ 4+.vtkF`BPlcęEr,H{nԧͤzt3,G6+b7jQ_#ɳnxf?]&%*Z:qذAPoŴYT +3>9!7MȈR7{ ~kM#`iq@$K܏PNؓ¨xb~$ЏS˓Ao NA#ͮn%cm|2.c.wn54XT1>htJ+J7\f61VCz >J^(]NCLW.oc (a>PQyrQ1w_kLtu=herL+GL + G!sTY,&U~COh40` (o눲2WCey:%]PU*54 2{>Fn`3SLVCeou1Ùf̎S+b,8gBiV^@K $f:qhf~kus?%VŃH$@9F)3h@A-vDI]![EӫeIx1lez "|ii> )@󕀤x_ [#;,;nӃV,AD +slbX?:4kB6k'Ϲ}z $ ʫ90s+\TR$jT5GMo% 2d\6UTҡKg|,&k!Ig )4-y%z&3~2r'cgiKC0Upx +UcK#]Kn^:cX &<3lL<|鐙}JlN2 +un24e izp*|J ZCifwLힷ\,7eFtf`lYpSө\zI+kF&ZåQ|m \o 6ΕeFR|bfFfr6$n03}2X:t7v;N8m6fJkLM,yK*P{3E9= HfeYZ}-hZN1ηwǗ GTkb(tAۅk{`D| 9}xWNN+Rkl"G-Iĕ,a2>S=P0y#fJ%[rİ{] dNσ6b"msq|K2 +4>aAbW\׊8%7 !"C1 ,$fw's%;f#:bO,oS$6Ɩ"tⵉ{h3 +]ICeʐq R-x-:鯋Qs;؉k`+EC yuUWmc1ٍ!h 8v UN3(;}gVop:|viP̴R8?`bJcE!4-u%3]ir +\:;9kn%X +90_ 'lUÜWfϡ~[x/cR>nm`͑xk2:מ_ =&Dpy)x*3<% k}5GG{LaXpfA.'e{Hh pjVٽ ˌGjx +/d#B;S0Պ&A0h_/ur%DoK4xBKy^ S*S9^duEE3,#QI4Đ@V_Bg1T8*y?+X N! /G[ej_84i7~ؔE bod.uKNN0|KF/`ǒyUnX Jǰt5u @Uy--B̑p11rpF23Dd Y +l3Vjx )K|V"2I58 2 n2߮]P(mZhPuD3O5h־w4ބ8D 88&n`;a֎Eko^\wiɸ7O)< :tӍv:j_//MʖM cg2WM>%A %YXʧ}m_iV|ߝoN.D^3fH b'\`fQS w^[$MR%?} +^ʛ?J+[TM->b,k`B `^8u[`*ȯq)I#U.5Z%UPe'tj~Z/"C'7)vT2-Rx(~%`6>=FDX~,1>Bd DA,lngrlwMbw0ҳKuӶ|}rls5$ŏ%Tğ6>1~J%Zu=RaFd|%w I|Oj} Lo$ aZ3eԛ9 i'I1(0+y+CKlܖ0!˂1$2&!y=x892qrG(*P͔[^h 3ð.6o0aPf,S!^Tf؈?C~[l4yql\%nSiiiGi-[7T0H!A DWc-$Tp9aP;~.SiX?HvQ c".Mڼ= #7_NK%gX͟7tVvT>Q,p?3KngK`gϷ`ȈY_&D$|x;c֡ے "ܭߥz[D5>~X.[[(/%oi*,(%TѢ()ƫ֗hQc5 +Ŋdϫrua72A9,{}P/hj 9^j: 3CDeܰ0ڝ],2;V+L%'U"Vz/(C +[+M{畓&El G.~&ODLG8 kD9Y4t \J"N>yG'|,&IٖENM4.0C;5ɰ@Bj$ 7;kH@, j`bqG [ +E\"3yzE5W dvGտl &Oh'd%$sG1d>㫠]q鏅+-D}T"&.OcP7 U^>z{˞Bໟ'Ii8>2UVV31qP#$NoaZ^H8Z*Rj'Oqq-}!T$ 2qdՙzi# ч.8uvY,,hw6x*EP6,PhxD|#g(,7 tK$1:~a hx2?֒ J>"Rn6-PB}R= P;lKq6z1-԰؃[+1*d_&:rH>$uVoU4diz! +t&m@ɨ ++V3yjxVX!i_sN8rx`c1*;qz zdaZƑ$jx`^MahsݶOV b ՘%lEBKL9-\ ٬OSNvRs h0>tmز}Dmqe˸?mˬbّL #Hlx“mB5IbX}`ۜ ݵ:7<3'/9 + IOvI*{ўZ8 &TǺo-$9K4S:C3,29۰ 46b!j}泄z(l~')<' W)(&TB/Ԟ!;~24A=I# w=XNy A]@/}pa=llHRԬGrf?nH `VM杞~@8xcǘ o;VB4,\S{SF_ 8XDS)Ef,iXullsSi?zv#!I݇5wv<߬ztA y8/H\)\-эYkl #&Hgo"p&<ېM65]3W%O}+P +KgpiAn]5[Ztp#6_} wYWK"^yP╋m~=&سj -}[MW(4/y*eT':o +VtQ7]HqCVOd<}fuaU--7?˹>!y  ^[ +v渋-a*ܶP"_5~sa"n%HidWeHک<w=B;I\D 2*s}Yaw4äٓm 9)ZܝCJO/ˁ\jK \%Okk"PYЉ*χnYk~wĦ8~"JC~'jX^2!#f!`)@ֈPmgPzu;uDX Iǚr]mS`i-+ؿO0ӴTr6r'q65VY'$Y}D AT]Y`$Q]>Oa!M*U$t&xL +ִ Ʉ έުGO wg)+|I`fNcH2tߕr5㗂ӶWeu! +R-Vא  {#ݡJg|f}N]eUY6/ɘx26@IVi&A>mRG.؞ڥr 6=ҌT:扗*sP<>St0P%wgQHHFQ7I/9OrhayL/RɈ{VJihbf߲8vyPVW^CnuId&ʩ0,TY1〚?w@[lP-]уY?E0;t}}L-$u>no.xCj 4dn"ͮ賗PxsZ*O "Wzc`GnϳݽPoᅬI@FУ%wq?5^P֪heQ{sa:6gձdeF5Q$H?늬2V i2N X1.#qLHfnN[=! +b~uHL}"dB՘ZEtJd0ELO:QpC?`RQƷ}*PyhbX =i mc% u,': +SJH4}"Th‘^ޤt[\ $Ɂ(NtET*VLl;Br oꙚBqD0OF!򏸅nM~;cu#q IOL*PJz07l>+hO +vUoݕ:3Ǚ %Eu: Sa +5 zYO3ptzJ*N)n U7vFʋ3y-۫Jl%R:jh 3Yt $D/E#K҃uCKdm.hb_ oJL\]ogZ->bvP bluAKWuW`ڄ G:-}eI^7#B[\yh`p ch@NIg}HQlƤQUZgכZI@PK+3>T5@ uCBZn|BӔgYx ~=dBҐ`Iq +sm,oLyu9O5|ScS ܊7ng#PPf)41`QgQe|Fe'BNe1c|7 _ d`ˡI lA&(l͓ѲnP]<"&6I'2K> >ʛn$qdO v9zJe +wTNʆݨ`:b6;dyXdJ|o5T!(RBhVTQ[C[ޙV> h֖ˬSf)v0||*002J0cw4ݣ|J">v ?*/` SoOlrWڬ]vbXROC;ﵗw,ؑsY O]k3zLz5!fPz"dSCSuFd#7kQ*.KneNEXe/.UOJ":|XkqEAJcnd}rTbcK mrjVӐDA$ I#˭  +$>M|e$E,^z1]X oG[;&gNKe$iSw珺:ށ +rss{wHjZI zܸ_3^~{CYHE |` n7 &HLgHo?QeuZ=nQ 0Oz]c2AY޴Pl^llAcv:ePiLy6@ӛP^'SuVcr3K=H݆4:j^8Rh[7JGz7ƪ,{04 xHKx%rrTxf}A+ύOiP_v*a׫xV*@V JՆ, q +YԴa(zc +t ̵^/F`{7Ȼ㓊ކ$-7I-jŅqtIE. M0r@=K,Ue~73|fyڇR2. G B6nBG5w@s<ѡgD+FdxgPF`)J'ʢ*[}]0cae+=4Hbݷ}{ (pqƯ4!wZńr^εd`΢ïgJ `Mtˠ yxIRQwb8q:W%ws3m8uKA`aF؞T*3GbRuGz@eD>vJ$yuT[Jtw6^$Ig!YU!ZtyMH4+4w +',H+T80B;ɣRʸrb1k.wK_=CZvT(X} FvCGŬ;'ޚb6C␇1:P#헺ibʹB2r.nBGM*"@p/{@Y 7]["V%ou8PL" 9K_ +G'ϱ} +M^Wa'x)o ZkL7$_!GĶ$M=oQAw1\klj&pe& `]ސUcDr @{ؒhz"VNgb8kNOjj[U7XwdPPj_~?o4^RaC^B{}q+I$YҮ8A**$(;곒̺^`G{(5Lց\t)~u 'DWRM*dp2usHVoℷtql& [h LecfjāXXV?n*G:"OF#6q$\ C{W ld&r֡HI&BhJ0Oy6Qs&ƻ.:Ќ'hbzc.xĢ{JQQ+a%r|Vhĸw-g&Rf1 d#rv.Ϡc?cbl BDI@4с?<`eC8V@\:4puF&1)?zMC"^vN~Y^iA4MnSh[`/[xS)"[SfЍz3fNW4JS qwAXP^;3t` z։zyHFdtx'(w4hH#{m֌ g_>STk7-fO`^bw,[sA 5[I@O_d2ȸ,_)e %>`5(ZcOIJ'{~O`R D4 JD]CrL `,ge-F(KPz OkX30z3myȾqTGvKƈ10c|.B2jc<}V!|V >>j +y.~Nmo֒=P@-_u5sNZc%oE㑴- e%e:Fw($8ڷUK֜Y}# QUgt9h@"-A<.22 ]'JkvQJ /S۪rh˨5Inv$,j}aV.#UPQ:/.dgqx~91*5ATaNwYaU4cb#SDG/_\h^Lǝ҆Gz7-l*m#}G-1{R[Qh_?^k9"i8s \mǷ\vWO,WUU\sèNR}:L<5uo]@W[lg%'m{Z;7]`6RgjI"&:8N攌/D/_3gW2o= FD}VfR !$lX} 5eci_[kmܳi$q +o%$Xf^$ Uvpt9y72`aREI5SpKtRiO}pp*(~.+Du)q>j7$saS\r% +瀝ֿ, D8qHxվtL>.$DHJOZi+w^ecrh;") ͖QRf :h.f~Xz4b~IYvo'#k"Ȱ2aoE>ИU^heYsq+4~=LhC2B"B@ ܅7H*aԹRr׎6BS+d_M8 w:ڢaF^/C$q׌e_7+^1N2'>0Iz= bq| \]đWj-S\U +XLǑn=5 [0S*.+͆8WW]qaόq 0[iÏXeYF٢f|lxvzy縆Xo$*菓[qbnpl}PR] 2hqRaqdwJt[ j[Re7bJZ[4z=%ě#rCvl?#1dd|(gx_vXFVۻH` $b;+g̡eg1x6'#F,kOJo_jeO)oOcʻg?naL͌|O`R +HJr7]Z)%:y.Mn$w@5@YT@ ce H6ʯ} nBI'qݿE6Ī>Imf-, 9e@wiwb *\šVE'8K aI ?(On0-Du 4Kcg-\C4"Iӎ昄S?.WBj#i[r \|N>ayݬvj=4Qm>% ځ8<5^/ ߧj 2T8SzsQdDwZZ&~>(>$MJG]GAylGNfJA]4dX.g-,Rُ#ԎQAQQbۢP=~Td w~6aD[ij=MJܙ8)H~-WRI +GǣYo60y)Ӆny@52㕺mtkꪛMh ݄u&2cJMw8~Nh (p5wMpB mxdo'qa(&=uG7 iDy=`&.?ݜED!sL@DawhPNsi,1)>^mZ+++ s\ݼBx B'WM@[`Wl(fo,H/6C*Τp[pb[]h輠TbB `&P6_)ᄈLPzfa+OvyGhXq׌Y-N+xvqH"!98uCƀR[bm}ph!?:5 Czhm){ Mݮ,>eX#!0F#dnRpv [q !oZ %ntPݶC ɠw势ѝdso%k8ӣ[ێoѸ!A F݃EX rdlp*PD Pq(?CZ(:n:.o,vLp @Z E-{FɡXB dΝՈygs!sIGtNLeƹlcy@kξI#Nu}Q ـN/W{p B:e)3c1 03BESLfBpu߁w|N5+>7 MiM0e3:S\whcJW ,yFB \ָIՁ3yԙw:`~0>#(Nn\(XP=>f#+phKYpԲTns7G_ +Ɍ V|JjX[Ѵu\7ZRC }WHa CJ +VSj-uJ'V/5u̲#~x֧MnFwКDd k|YM/\:I8ǵ Sqm0ʈ/g\m}A Ln@L +s={hbgH !#htvೳxbO ~QNnaXlǜ*VTo.:bب 4RT!B<ҡ2+sq UGq}6\ywzb."l#ԐP-s'] +zЭ^I#P D*e3:[~Pmt6/J[N0J&UɼhnV +4 `b‰f8mof3$ӳ&,~%ߣ;M<+sOO~|&.D╈ʄ2HPͮ)`oB, Ȝt&r2HPA8%yXZPR%BR- ol0D}͂.0P!(HQRiOHQ@/nyF["L6z0(K4e,4&:KDY!N#AD:62|b`EptЉYm,4I2*(q:QYԋ#`xx(x<2}hHeCLV zddTc  SG + h4m4[DD"LY +HuҕKW.%q0u$IjV8L|ZDa'>pPS@() I(He !@A@H))i0c4Nźm%8v + @.ɀCgb2`l0|qpApLJ6IGRJCt@T$X +8 xz)j@B„ð`{JyeP )XC?%c`7P-Rۨ +XmzhJi2FxpP0') !tbqba-D` AHM& 8p#qELHmmy|-ƒp XO<GM Iz. +@t'2/A`X7}b=NO"%TJLE 6I 6ic2 C`#m6ӱ 8`l^ #X VAhZVq + +a@\ +cɀF@Y^%Ex,,eqX8\X6X&%TFUaaѵ,NJbr,&&(es9lp8ld8M2R$Ŵl6:.FV06ZQYd.^Fq6ev;qe8ݦD)_/-#54/`zM6'A#>j'<pmxZeP`r(S2i*x P@VqB-J d'$ !iiYv'8݈\pD|q  g\VK'|͒Pұt#!ױ8tc!6KB*Rp,)%% Z;0Bx#8h`A n/8p*h=TbJ̱J:s@HЂU!Ҳ傡aFM+Jq tja#^@(Cp:& ܅֥W$bPBC=21U2( 8.ۀ8ML|zc!L8: aZLjjtݦ +.a48#04 : &:2 $KkpTy#հ0lbq R.mSebfK_mI€KIb>Tv0PwXh^ LEw6hZ4.}PІfrHZkpD."`wn$$&0m&[ݦ`qm+Zs%zÂS-mhj%ԡrI}uqPP:iX", +(CH6oDAh#ց _^'(趞xh=x=§܃wtZeG^Zmo`usZ]N CfݶAF'hw58Nc42 + Ÿ0 7eS ipe)T!Sa궓mwlAḁuĆ)9yaXU,ECqQnA&8Z$hFG椓Ptj& IAX104<@B`ripgP@8 0:Tsg{=)S4gӲ4SsZO6I:)@c4-2$$dCmQk`%sk`iHI8Jdj-DsKJ,Bs "0K3Ac2RR,Ϭsj0z8(08#EZ& Z + @ x"xE"AFZfimG^Zٓm`F`mċA-;-׽sR^'-uNrzaZrƖ0mʴZ&78e Y@Ӕh }XT@"2 c#E'Sl.::ᬖ`4Cjmڈp -chYM4N ++5K + J:FR5HN^bVa!z8K*iDimA&0-%N2c + V\z+i^(‘&.cTi95jB:(:$tϴ,(|k R7)e}?2迼}OpJOe;eϡwG,_+9s95FooWNm ++~? }+rT7Oo:|PU>UQnm߷(S6?._.YŹrNˏSGߞ3ʧѷ{(o(]ٟt߬˫}᳔8o*oC_~?{+g|-Yg92N/|;#PmyB?T"Nۻc?N}}YkcλάOOq?t] 7꺄O>ܬ%e|rKfC (ՆWT>}kvrY_K^Rˆu>p+rT_~Nej7$|T:. rd8rO=^o6oùQ!qPY;6Ԇ# ?–3jk7CsuadQ{ENEm>L^ g|=f3ǝ3ӇN~իc0 + @e22xb%єD%!Oj \#%:YDAy]HU4[RY JBU^ъoeʗK+TQBͺh> -Snwnx}(ҠwRD9yu\Ny&5)A%cEڂСfS9 U hMV*ID4wk7DC$%iBvũ #̎7Xb8 X)7j`ʂѰD *~>%h$`BYp lm-5f JJ58pjXe‰\ݔ8Ф`MFJ@>gd00mlC胀C4:NRJDyhCjcAp,n02xdNm'X۴ {4nь Yi>V'0U\/>V'*fRRX>k$dtP$::6;:ّ˵-g2S*q>JBJB| 9CNKp[u>v3J9߶TJ30F9|v2UoBB;}Y](+RVﲜ3JVUtge)}DyTt~wԏދFgtp͇Fޅ:_<5+YnT_kodgۛ9no?.;pwhFU)ҩ-W6NE'~GqJ{ϻYKd)U*{rs%~ +_(7ON^-;_scYGnerƷoƙg;=;2w֍+);sU~ dv3??#@8pN>[% +g~k3;eFQN?v*[+ѺdӣF򡫌bu7.Q}v |٩0tP ?#_%Ϗ}Ij?kydỾg(DK3F?C\FH*TVVVVVVPB +uuuu*TPBʺ:όYd9)'sq~q\>קOϟ=Jrg֊s}B' ' 'ϝ;3Sƕg(~Z6F+>UOιYgoT{ٛ~wgK5O:F;w[؛^YeatSN)yro]kg¹JGA{32>M_}hI;ml; 59l3l W__KWu>o=|'~ ɝPwη+ݡnoo?*{Yg|RYT}SrS{dJ8'|mIra|Yc}TOQl?,>ҙ}ጾd:J}u0;?YW'Os\nsd2F$R)"0 P$ dr=$vF 462 0"(aQCAABVLh9+,ޛ wE6[ck]BgKu=Bj-yR?($Pr0>[ŠCFQȃRF$i{tA#Z\!lh~^:r*ŁpeJ:$p 3+PncX~DIoܻF0x-$]mY1=iYl|g~16 yu,EhuwAR9(IC4y&R4\`mI-ym擸0t!2[nb̅qxÍv;vcPN2,"~Q:`FRW @EkuqH53aFLxq=8U\:z0uH' }n,HlԿOٶ z"fc`l6CHhD7'8`hp*'y_3- (L /(]󠊦iI_";1`lG|F^)yHF& +IAufֽd&IE֬Pͻli}\ XQ@,'m Z3{)lF,dL+:Đ$o4Rv^!id[ ]F36peG&qQdQ "Uhr#н +瑋v7r$ z$ЭG-%GQ +n3+ KLgvl_Ih{.q}+<?CԢ G-U4z#4[C4yU#SHKSi1ek90Q3fumGdܥU{Q;*h_箁d0ʠ)ݽ!zPi dD\gdYY DtvW9LXXlfugлt`dg'Akoa8_kPX9j v".1mMM@Ԛׄ"jM2kM<7rqӥ+.BstE"4kjn-Jyz?eHsγd׀P:x K0 :^9Gm-Dz ۉ50Zɧ }563_ q-& C6 0AS]S{"]tNlP\8!j~0E|Q~XFГc{&œ7jyW% +)>$U͟j! "9ܴΪ\-$%Q{I盯F150FXV$2=-: C.//ܼ흗jMh3m[;o,|[KYd# #ϑ4뱶2lHB؈̣c 3sD98mȂؑ?MsėzWÊCd5K@g˗9rh&%V$jC((VFepN4j|VڜAWic!%Ilc^FɆ^?_~D߷IYe!&Xē)a,'vF<\kޥ4#SyqFM!DP.| 0qLɩ 3 `N"y0Ն_|3"KkiAU.҇m6b']3cBmج._]YZ5v~=g'{U$ \ FP$c9X>Lsa!e%IpAgЃ!/SWp&FD6m^ ЩmYVa ۆYWj݆%H{1P/ ܆M棲n#mdDͭ2~@&Wfmԭ"f^):2zqSBp=giN@0$`{M[sPFF$brЂMMIfmq LmPo7rFϷ$2lؤk2 Hٰ@LY2 BX}ΪcG"[@ɔ•u7c%QnFfj>Dkf舖b|VAir|jNMd{LlC*o+/C8R-PMK+EfF[!z xяG0aCsm/. +٠eMh9y5Cxu&2=O:_XXr:z 3@z(9#w3 Xu5-Oi@:b%pX[WlMvسguA0 +1L~Af J؛1 aڠb$@c33_ +[ +%ihh3F=*K~ƙȌZ!iCsnñZ:`Q|MݒerU2?xxȁE,b{;K$rt_1!ڝRTmlUdIUZ;qe^FJ{}ȶC+* jv4Ei [qaȉEZaM/; +p>Jk4 pwiH5`؁d1۔jB7Ac GY+0Hw(yhHSRe&e1؂6X'ICa,Jw*ǟs5URCq)>pFDPBB4K]OVGV;S +J`Y2 F +4K=P߲9~غ ^\Z_J.k1 oD㉬vb;cA e|\ r v(/vN$M^neJHICd:p#M#dʺx%RH ǜ 5[aHX|[sb)g T9b1g!I?!pKWMA +fe>:4n}HGOhd,0'urA(7y8d&BswbuK1ZFV""%;HOM+q ,K6X$d &·ULq(AHDHlT& o5[I3R>k75 :/hnMQϯd$鲁ɝ4-\O&`ۚ3l)DƱ *M0\J\+W\X3NTbыڑ6߹F)'$oxhjn%pf'mdN:3qeƊn6#z"ψ#.mm'ry,lL{5m?C.ݱlHk̷fIKD6kcD-dN;yssT\s@8BCPʬld E9UK=7j19ٞbsF@9" f[yaz7gTYζX5.Hppwk51nim|? O>lֳny-c4C$bVkg+xG7tQ +p`ޖ^~gftчX+fhcֳ + stu@&u'\vSA֌ަ4o 3;4 ҉wAK.(vS(^LђӮ>ez:zE"Orgވjk!/=Y@l٢w2H8QTZں13뾔E<2 Cwh%MWߊu?o@;DFd7m^Q\`{B)p,,VG.5- $0,nK"2rE8)|2b|X ϗ@/K83~hƾ]<х3L2;Cte&DdbG;ځya|pNRQf$⒉Ԛ|P$,PF衜DIGd+/x 5TI5*(='ҕRC#zh$^^gb [SeD*Ye/kc Z]5vZ(6;buX0/ȶlLgeP.XHtQt e]r Bu_aSCnd`&feLЊꜺ;ma<-P`lUXعxdX'5AlyfKPY + ШoB#B8P}p-oZ<^ +oը,Nm@/ZՋ#zc=NZ2_T0b[?.;Iqcyuy#HP=M@hJiZVC–A> EQ. aJY`]U/SSBXt3M1Vw^pxmr)5DGC78zab:??0ZxMcnsN>.i^@q58Z5cjjqjw[=R?H(%f- ~r ܉D's^  CAvO9fT-8 +b[ILҭ2.m";[l#TQ^ J}ah6* +lXhph`ouiCƧķW/>Y'gΟ|FhGxx\ߟ[(}:}C`NZCc~H󤛟?KBpЉs _BgQ|I2u4H3$wJ`82&L4wKlcDTEA8aW9Q *V꠨{VBʭ7s@+c!X(5\!e.r!NTH\׬ͧKHo\G)J]*/do"g3)NC4S83M|9թ}ށEwVAݕ?x1t:fVg\ +X#/avXSC%TLB:뤤<9v˝ȭ|j-btAxz)ӫoڸ2 @bp oN>mmiwT1"*N|}K20j GX\\ZM RJPExA\u6J\L/d@5rv'UQҴ'1AP)(zFh8A:w;tg:aFLc nsf3WK?g+J$`9Y ;$6b'# "2wV겇#}N`\SK҉tm\%ܖIw48V %K2Z[ܿt̤I'#K'Jq[:pfg&@BbёLkKKY_:z .Ka_:^&I/ҳmc&F`~;㷦c~<Ek7U4iu ʽ^ؖK%7a&C.R^qs.A3qg\36'~1>j_POZTn~1α5w{LƓwaP+20oi?B$.z!Bv6I`ɨ#ɋ դ FG1^i ^7VNqfR0 ]1j0o,Eʼn'7bf,S^2+<ly˪ +0ܦʝ<4ȚVvi?{6/L|Bw\ŝjAXG"oGﻻO;-P*6=J=MsW)@_#0)S!r0_UP0i\آTi`9܁aq(Gf4Bi՘ܳT;ڏm%4ڎ +tMFzz] +k1_|`j /<8HY +,V@pkI4k@%S})Ky$4Y;Yӏ }τAJqP6n.[γAZJ΀4c<:-oAu~Af L `. Uwkc\dLnu"85D@_XÎthX?swm'n+3:V&\s[a`=ߢ-C5/de,α6.95SH;E ]yXiB2$Tw=4R'h4T̐%m;>ޕѠ Sj@@ެuTknݢuDK&uT(d¹XbѼlV)1Ya(Iy{~M۲t+هB醔=*%&x{![UrC&tl&=(lg"Cɯ3mCuA)_7`;/yٱhN=T>ah)˓p`lD^Ю;CpqW$BsGAq4g>e x>st $?W2ONɕuIzi(ׂOB5 5[C~1 ؏B'8U"@Ì MAh@S)笞HFktIiLߏkA}je8ۛ V NNL]vݾ0ףdy>7נ:yr\NUj;hQ(v8(r)sBi;ϗ7;[F5ˉk?PU~/X%`jNs\Iu[aL ^h*@|[uo/ +?" x ъ)10כKpPcdXPZ@_[ޠU˧Jv5_`E>xDhPץY k\LG[G*zyEJՕ/؊PP8E pm@#<*e@O\O Oy4l{3G`WfOXF [9Y<Á^x*{\skt F=PZ {!8[eVkkAa˪ ?Go Ck$oMd+WäP_1qiVuqw`SS3M!L[REJ_Sxcr,:LqXMDŽr/[^aգd) -h=.:̲yd S:F)7}iR9c!eS<ղdT|XEE̺IsT+[m< @\BH>Ɏ\$)VYI9?"4& ĔuŠϪ֍*{1ieӵFL*{FG9,EwK nT+@qQ$sR d1V#?w" M_m,p\Z%xMkBQW HU k!һ 3Ir +?^G9j׸$PB܏aKj/r)j tm f"߆pϓ3#R3)ɚfW`t$0zDb0VgϼM(䗣jt +2>-u@Le"8ɘL;jKY"lq?"ݮY;q$eDQFy(6I2Nb2PGƉ^H*M ܧwӿ-ELv51/I q_~+RO8l0ʨ +%OY%v -.{%7 +Gr_0N5"Wm0|F5-f&3䢏!E)v5x` +^O~AH`xvP Bs(] [Ԍ#nBbю}zUPϊaf +ۓ@2k :>]U*IDK5s`ʫbtԘ;ls| W[u&~]^$U$Z\~[o'İV2lv +ܷЈ5q~SQ0&jd/:I";-nWrCMxSY#u$g{3DUT~l#YfC\rF%+0| on[rGtI{ܼJ v@T7pRb%]:1/]NY? P/>EUrK1UgS)`JI\dF=?4P|*"lE rLL1o"Ku " doڢʧgO'@",K+o7^`Эu⮲!br_7tcK!ns_.MDa'T ΧF$|ؒKWt%ٖk—C3.a i +G-o]YJh۳ }L'm67":uhhg6hϬyIi0%WP,g:S%Xn$ [j|#aY#,-Mד9G1,Zx ?@XvL. endstream endobj 50 0 obj [/ICCBased 55 0 R] endobj 42 0 obj <>stream +H|Wn7W}Zsu9@ޫ*v!0<&ky/<˗>||pkp|1w:{.._t s..K]7zb}[Oƅ B>LJmy6^/qr9!h ]-GwGO=0`6u!yZxoV?mlO^/㎰O'9{i'a zDX",xdwݒiQ4 AHDP]= >>%[DQNE'Kb~P۴_ %|\F'k}Draa;.!ty%HH%l:lGjBTSqEp4g52 \7%ڠFit9ӧ!]H;5 u/^\@IEŢAe)A±Oä2r#%zO|R簅I0I# ud0+kP,f2< uwHYfR@26-;n.VN"tt]:Ut# ~bRԶ8ND873[c916jB6sȬ +g6Dt164ֈ*( jU⚲MD(C*~^V%ʰV :=LE62͙^eD#耒 K_t>w$l[;O 1S*uĹeq@NG lQ9XOfKBB2g6Z4<nCU(LENZ(lCH(om&Z>CStdO"6 +(!n?WA$"Wa\bfWZpJTDH['_^D+Zۡ%gղ0|ޮ@G2-^z(9oVnV6%ev^.߷o1?wH~|4d|._{yr-:: /w]wqO endstream endobj 43 0 obj <> endobj 44 0 obj <>/ExtGState<>>>/Subtype/Form>>stream +/CS0 cs 0 0 0 scn +/GS0 gs +q 1 0 0 1 182.1226 265.5083 cm +0 0 m +-29.317 0 l +-31.743 -4.637 -33.115 -9.913 -33.115 -15.508 c +-33.115 -21.507 -31.539 -27.138 -28.777 -32.008 c +0 -32.008 l +8.838 -32.008 16.004 -24.843 16.004 -16.004 c +16.004 -7.166 8.838 0 0 0 c +f +Q + endstream endobj 45 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +q +184.508 283.5 m +166.006 283.5 151.007 268.502 151.007 250 c +151.007 231.498 166.006 216.5 184.508 216.5 c +203.01 216.5 218.008 231.498 218.008 250 c +218.008 268.502 203.01 283.5 184.508 283.5 c +W n +q +0 g +/GS0 gs +67.0007935 0 0 -67.0007935 151.0074615 250 cm +BX /Sh0 sh EX Q +Q + endstream endobj 65 0 obj <> endobj 64 0 obj <> endobj 63 0 obj [/ICCBased 55 0 R] endobj 38 0 obj <>stream +H\j0Yq^I$UjEq|hԼZExd5*X@R%xTyjqd\HbcuG9aMF.;]BNpaMyFj{Xozd<@,t&D7NJj\lOۀvss__O';1~5/|2! =j5 endstream endobj 39 0 obj <> endobj 40 0 obj <>/ExtGState<>>>/Subtype/Form>>stream +/CS0 cs 0 0 0 scn +/GS0 gs +q 1 0 0 1 296.3101 282.2305 cm +0 0 m +-61.182 0 l +-66.245 -9.677 -69.108 -20.687 -69.108 -32.364 c +-69.108 -44.883 -65.818 -56.634 -60.055 -66.798 c +0 -66.798 l +18.445 -66.798 33.398 -51.845 33.398 -33.398 c +33.398 -14.953 18.445 0 0 0 c +f +Q + endstream endobj 41 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +q +301.288 319.778 m +262.677 319.778 231.375 288.478 231.375 249.866 c +231.375 211.255 262.677 179.954 301.288 179.954 c +339.9 179.954 371.201 211.255 371.201 249.866 c +371.201 288.478 339.899 319.778 301.288 319.778 c +W n +q +0 g +/GS0 gs +139.8249359 0 0 -139.8249359 231.3756104 249.8662109 cm +BX /Sh0 sh EX Q +Q + endstream endobj 68 0 obj <> endobj 67 0 obj <> endobj 66 0 obj [/ICCBased 55 0 R] endobj 29 0 obj <>stream +H\j0 z +@msm2Jݬ!08 && KYO=#Bg$E6n|8;WI@HiwM2MDKM*qxƮS[̰%cCɴĒa^Q [2ܩ%TsXk92lؐuJʍkHd>.`XLk"K$G!:g+@8xΏj}᳋̋oe"<3ir'y:g`6w endstream endobj 30 0 obj <> endobj 36 0 obj <>/ExtGState<>>>/Subtype/Form>>stream +/CS0 cs 0 0 0 scn +/GS0 gs +q 1 0 0 1 295.5586 282.4746 cm +0 0 m +-61.182 0 l +-66.244 -9.677 -69.107 -20.687 -69.107 -32.364 c +-69.107 -44.884 -65.817 -56.634 -60.054 -66.798 c +0 -66.798 l +18.446 -66.798 33.399 -51.845 33.399 -33.399 c +33.399 -14.953 18.446 0 0 0 c +f +Q + endstream endobj 37 0 obj <>/ExtGState<>/Shading<>>>/Subtype/Form>>stream +q +300.537 320.022 m +261.926 320.022 230.625 288.722 230.625 250.11 c +230.625 211.498 261.926 180.197 300.537 180.197 c +339.148 180.197 370.449 211.498 370.449 250.11 c +370.449 288.722 339.148 320.022 300.537 320.022 c +W n +q +0 g +/GS0 gs +139.8249359 0 0 -139.8249359 230.6245422 250.1100769 cm +BX /Sh0 sh EX Q +Q + endstream endobj 71 0 obj <> endobj 70 0 obj <> endobj 69 0 obj [/ICCBased 55 0 R] endobj 27 0 obj [26 0 R] endobj 72 0 obj <> endobj xref +0 73 +0000000004 65535 f +0000000016 00000 n +0000000147 00000 n +0000048491 00000 n +0000000000 00000 f +0000048563 00000 n +0000000000 00000 f +0000000000 00000 f +0000057378 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000057451 00000 n +0000057647 00000 n +0000058841 00000 n +0000124429 00000 n +0000190017 00000 n +0000000000 00000 f +0000049021 00000 n +0000049492 00000 n +0000056945 00000 n +0000234802 00000 n +0000049959 00000 n +0000233215 00000 n +0000233556 00000 n +0000053218 00000 n +0000056263 00000 n +0000057132 00000 n +0000057255 00000 n +0000056439 00000 n +0000233618 00000 n +0000234097 00000 n +0000231658 00000 n +0000231970 00000 n +0000232032 00000 n +0000232510 00000 n +0000228915 00000 n +0000230454 00000 n +0000230516 00000 n +0000230989 00000 n +0000050418 00000 n +0000051969 00000 n +0000052031 00000 n +0000052504 00000 n +0000228880 00000 n +0000056376 00000 n +0000053012 00000 n +0000053075 00000 n +0000053253 00000 n +0000053615 00000 n +0000053371 00000 n +0000053495 00000 n +0000056582 00000 n +0000056700 00000 n +0000056820 00000 n +0000057016 00000 n +0000057047 00000 n +0000231623 00000 n +0000231560 00000 n +0000231497 00000 n +0000233180 00000 n +0000233117 00000 n +0000233054 00000 n +0000234767 00000 n +0000234704 00000 n +0000234641 00000 n +0000234827 00000 n +trailer <]>> startxref 235070 %%EOF \ No newline at end of file diff --git a/assets/color/JPEG/Move_Logo_Design_Digital_Final_1.jpg b/assets/color/JPEG/Move_Logo_Design_Digital_Final_1.jpg new file mode 100644 index 0000000000..ab082343e4 Binary files /dev/null and b/assets/color/JPEG/Move_Logo_Design_Digital_Final_1.jpg differ diff --git a/assets/color/JPEG/Move_Logo_Design_Digital_Final_2.jpg b/assets/color/JPEG/Move_Logo_Design_Digital_Final_2.jpg new file mode 100644 index 0000000000..45af675e28 Binary files /dev/null and b/assets/color/JPEG/Move_Logo_Design_Digital_Final_2.jpg differ diff --git a/assets/color/JPEG/Move_Logo_Design_Digital_Final_3.jpg b/assets/color/JPEG/Move_Logo_Design_Digital_Final_3.jpg new file mode 100644 index 0000000000..e589c47137 Binary files /dev/null and b/assets/color/JPEG/Move_Logo_Design_Digital_Final_3.jpg differ diff --git a/assets/color/JPEG/Move_Logo_Design_Digital_Final_4.jpg b/assets/color/JPEG/Move_Logo_Design_Digital_Final_4.jpg new file mode 100644 index 0000000000..a2f381ebf1 Binary files /dev/null and b/assets/color/JPEG/Move_Logo_Design_Digital_Final_4.jpg differ diff --git a/assets/color/PNG/Move_Logo_Design_Digital_Final_-01.png b/assets/color/PNG/Move_Logo_Design_Digital_Final_-01.png new file mode 100644 index 0000000000..9db4c577d6 Binary files /dev/null and b/assets/color/PNG/Move_Logo_Design_Digital_Final_-01.png differ diff --git a/assets/color/PNG/Move_Logo_Design_Digital_Final_-02.png b/assets/color/PNG/Move_Logo_Design_Digital_Final_-02.png new file mode 100644 index 0000000000..556ba15470 Binary files /dev/null and b/assets/color/PNG/Move_Logo_Design_Digital_Final_-02.png differ diff --git a/assets/color/PNG/Move_Logo_Design_Digital_Final_-03.png b/assets/color/PNG/Move_Logo_Design_Digital_Final_-03.png new file mode 100644 index 0000000000..b971de8d77 Binary files /dev/null and b/assets/color/PNG/Move_Logo_Design_Digital_Final_-03.png differ diff --git a/assets/color/SVG/Move_Logo_Design_Digital_Final_-01.svg b/assets/color/SVG/Move_Logo_Design_Digital_Final_-01.svg new file mode 100644 index 0000000000..2199e2839b --- /dev/null +++ b/assets/color/SVG/Move_Logo_Design_Digital_Final_-01.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/color/SVG/Move_Logo_Design_Digital_Final_-02.svg b/assets/color/SVG/Move_Logo_Design_Digital_Final_-02.svg new file mode 100644 index 0000000000..f9673d3801 --- /dev/null +++ b/assets/color/SVG/Move_Logo_Design_Digital_Final_-02.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/color/SVG/Move_Logo_Design_Digital_Final_-03.svg b/assets/color/SVG/Move_Logo_Design_Digital_Final_-03.svg new file mode 100644 index 0000000000..5ea4d1abd6 --- /dev/null +++ b/assets/color/SVG/Move_Logo_Design_Digital_Final_-03.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/assets/greyscale/AI/Move_Logo_Design_GreyScale_Digital_Final.ai b/assets/greyscale/AI/Move_Logo_Design_GreyScale_Digital_Final.ai new file mode 100644 index 0000000000..a86385349d --- /dev/null +++ b/assets/greyscale/AI/Move_Logo_Design_GreyScale_Digital_Final.ai @@ -0,0 +1,1392 @@ +%PDF-1.6 % +1 0 obj <>/OCGs[26 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream + + + + + application/pdf + + + Move_Logo Design_GreyScale_Digital_Final + + + Adobe Illustrator 25.0 (Macintosh) + 2020-12-02T14:57:50-08:00 + 2020-12-02T14:57:50-08:00 + 2020-12-02T14:57:50-08:00 + + + + 232 + 256 + JPEG + /9j/4AAQSkZJRgABAgEBLAEsAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABABLAAAAAEA AQEsAAAAAQAB/+IMWElDQ19QUk9GSUxFAAEBAAAMSExpbm8CEAAAbW50clJHQiBYWVogB84AAgAJ AAYAMQAAYWNzcE1TRlQAAAAASUVDIHNSR0IAAAAAAAAAAAAAAAAAAPbWAAEAAAAA0y1IUCAgAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARY3BydAAAAVAAAAAz ZGVzYwAAAYQAAABsd3RwdAAAAfAAAAAUYmtwdAAAAgQAAAAUclhZWgAAAhgAAAAUZ1hZWgAAAiwA AAAUYlhZWgAAAkAAAAAUZG1uZAAAAlQAAABwZG1kZAAAAsQAAACIdnVlZAAAA0wAAACGdmlldwAA A9QAAAAkbHVtaQAAA/gAAAAUbWVhcwAABAwAAAAkdGVjaAAABDAAAAAMclRSQwAABDwAAAgMZ1RS QwAABDwAAAgMYlRSQwAABDwAAAgMdGV4dAAAAABDb3B5cmlnaHQgKGMpIDE5OTggSGV3bGV0dC1Q YWNrYXJkIENvbXBhbnkAAGRlc2MAAAAAAAAAEnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAS c1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbMWFlaIAAAAAAAAAAAAAAAAAAAAABYWVogAAAA AAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9kZXNj AAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gAAAAAAAAAAAAAABZJRUMgaHR0cDovL3d3dy5p ZWMuY2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGVzYwAA AAAAAAAuSUVDIDYxOTY2LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAA AAAAAAAuSUVDIDYxOTY2LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAA AAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlvbiBp biBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4g SUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2aWV3AAAAAAATpP4AFF8uABDP FAAD7cwABBMLAANcngAAAAFYWVogAAAAAABMCVYAUAAAAFcf521lYXMAAAAAAAAAAQAAAAAAAAAA AAAAAAAAAAAAAAKPAAAAAnNpZyAAAAAAQ1JUIGN1cnYAAAAAAAAEAAAAAAUACgAPABQAGQAeACMA KAAtADIANwA7AEAARQBKAE8AVABZAF4AYwBoAG0AcgB3AHwAgQCGAIsAkACVAJoAnwCkAKkArgCy ALcAvADBAMYAywDQANUA2wDgAOUA6wDwAPYA+wEBAQcBDQETARkBHwElASsBMgE4AT4BRQFMAVIB WQFgAWcBbgF1AXwBgwGLAZIBmgGhAakBsQG5AcEByQHRAdkB4QHpAfIB+gIDAgwCFAIdAiYCLwI4 AkECSwJUAl0CZwJxAnoChAKOApgCogKsArYCwQLLAtUC4ALrAvUDAAMLAxYDIQMtAzgDQwNPA1oD ZgNyA34DigOWA6IDrgO6A8cD0wPgA+wD+QQGBBMEIAQtBDsESARVBGMEcQR+BIwEmgSoBLYExATT BOEE8AT+BQ0FHAUrBToFSQVYBWcFdwWGBZYFpgW1BcUF1QXlBfYGBgYWBicGNwZIBlkGagZ7BowG nQavBsAG0QbjBvUHBwcZBysHPQdPB2EHdAeGB5kHrAe/B9IH5Qf4CAsIHwgyCEYIWghuCIIIlgiq CL4I0gjnCPsJEAklCToJTwlkCXkJjwmkCboJzwnlCfsKEQonCj0KVApqCoEKmAquCsUK3ArzCwsL Igs5C1ELaQuAC5gLsAvIC+EL+QwSDCoMQwxcDHUMjgynDMAM2QzzDQ0NJg1ADVoNdA2ODakNww3e DfgOEw4uDkkOZA5/DpsOtg7SDu4PCQ8lD0EPXg96D5YPsw/PD+wQCRAmEEMQYRB+EJsQuRDXEPUR ExExEU8RbRGMEaoRyRHoEgcSJhJFEmQShBKjEsMS4xMDEyMTQxNjE4MTpBPFE+UUBhQnFEkUahSL FK0UzhTwFRIVNBVWFXgVmxW9FeAWAxYmFkkWbBaPFrIW1hb6Fx0XQRdlF4kXrhfSF/cYGxhAGGUY ihivGNUY+hkgGUUZaxmRGbcZ3RoEGioaURp3Gp4axRrsGxQbOxtjG4obshvaHAIcKhxSHHscoxzM HPUdHh1HHXAdmR3DHeweFh5AHmoelB6+HukfEx8+H2kflB+/H+ogFSBBIGwgmCDEIPAhHCFIIXUh oSHOIfsiJyJVIoIiryLdIwojOCNmI5QjwiPwJB8kTSR8JKsk2iUJJTglaCWXJccl9yYnJlcmhya3 JugnGCdJJ3onqyfcKA0oPyhxKKIo1CkGKTgpaymdKdAqAio1KmgqmyrPKwIrNitpK50r0SwFLDks biyiLNctDC1BLXYtqy3hLhYuTC6CLrcu7i8kL1ovkS/HL/4wNTBsMKQw2zESMUoxgjG6MfIyKjJj Mpsy1DMNM0YzfzO4M/E0KzRlNJ402DUTNU01hzXCNf02NzZyNq426TckN2A3nDfXOBQ4UDiMOMg5 BTlCOX85vDn5OjY6dDqyOu87LTtrO6o76DwnPGU8pDzjPSI9YT2hPeA+ID5gPqA+4D8hP2E/oj/i QCNAZECmQOdBKUFqQaxB7kIwQnJCtUL3QzpDfUPARANER0SKRM5FEkVVRZpF3kYiRmdGq0bwRzVH e0fASAVIS0iRSNdJHUljSalJ8Eo3Sn1KxEsMS1NLmkviTCpMcky6TQJNSk2TTdxOJU5uTrdPAE9J T5NP3VAnUHFQu1EGUVBRm1HmUjFSfFLHUxNTX1OqU/ZUQlSPVNtVKFV1VcJWD1ZcVqlW91dEV5JX 4FgvWH1Yy1kaWWlZuFoHWlZaplr1W0VblVvlXDVchlzWXSddeF3JXhpebF69Xw9fYV+zYAVgV2Cq YPxhT2GiYfViSWKcYvBjQ2OXY+tkQGSUZOllPWWSZedmPWaSZuhnPWeTZ+loP2iWaOxpQ2maafFq SGqfavdrT2una/9sV2yvbQhtYG25bhJua27Ebx5veG/RcCtwhnDgcTpxlXHwcktypnMBc11zuHQU dHB0zHUodYV14XY+dpt2+HdWd7N4EXhueMx5KnmJeed6RnqlewR7Y3vCfCF8gXzhfUF9oX4BfmJ+ wn8jf4R/5YBHgKiBCoFrgc2CMIKSgvSDV4O6hB2EgITjhUeFq4YOhnKG14c7h5+IBIhpiM6JM4mZ if6KZIrKizCLlov8jGOMyo0xjZiN/45mjs6PNo+ekAaQbpDWkT+RqJIRknqS45NNk7aUIJSKlPSV X5XJljSWn5cKl3WX4JhMmLiZJJmQmfyaaJrVm0Kbr5wcnImc951kndKeQJ6unx2fi5/6oGmg2KFH obaiJqKWowajdqPmpFakx6U4pammGqaLpv2nbqfgqFKoxKk3qamqHKqPqwKrdavprFys0K1Erbiu La6hrxavi7AAsHWw6rFgsdayS7LCszizrrQltJy1E7WKtgG2ebbwt2i34LhZuNG5SrnCuju6tbsu u6e8IbybvRW9j74KvoS+/796v/XAcMDswWfB48JfwtvDWMPUxFHEzsVLxcjGRsbDx0HHv8g9yLzJ Osm5yjjKt8s2y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TTxtRJ1MvVTtXR1lXW2Ndc 1+DYZNjo2WzZ8dp22vvbgNwF3IrdEN2W3hzeot8p36/gNuC94UThzOJT4tvjY+Pr5HPk/OWE5g3m lucf56noMui86Ubp0Opb6uXrcOv77IbtEe2c7ijutO9A78zwWPDl8XLx//KM8xnzp/Q09ML1UPXe 9m32+/eK+Bn4qPk4+cf6V/rn+3f8B/yY/Sn9uv5L/tz/bf///+4ADkFkb2JlAGTAAAAAAf/bAIQA BgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoKDBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8f Hx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f Hx8fHx8fHx8fHx8fHx8f/8AAEQgBAADoAwERAAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQF AwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMB AgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPBUtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdU ZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eX p7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZqbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUE BQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEyobHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PS NeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG 1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/a AAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq+CfOv/ACmWvf8AbRu/+T74qkuK uxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVmf5Nf8Ak0PLn/MWv/ETir7dxV2KuxV2KuxV2KuxV2Ku xV2KuxV2KuxV8E+df+Uy17/to3f/ACffFUlxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ksz/ACa/ 8mh5c/5i1/4icVfbuKuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Kvgnzr/ymWvf9tG7/AOT74qkuKuxV 2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVmf5Nf+TQ8uf8xa/wDETir7dxV2KuxV2KuxV2KuxV2KuxV2 KuxV2KuxV8E+df8AlMte/wC2jd/8n3xVJcVdirsVdirsVdirsVdirsVdirsVdirsVdirM/ya/wDJ oeXP+Ytf+InFX27irsVdirsVdirsVdirsVdirsVdirsVdir4J86/8plr3/bRu/8Ak++KpLirsVdi rsVdirsVdirsVdirsVdirsVdirsVZn+TX/k0PLn/ADFr/wAROKvt3FXYq7FXYq7FXYq7FXYq7FXY q7FXYq7FXwT51/5TLXv+2jd/8n3xVJcVdirsVdirsVdirsVdirsVdirsVdirsVdirM/ya/8AJoeX P+Ytf+InFX27irsVQbazpavwNynL2qR942xVFo6OoZGDK24YGoI+eKt4q7FXYq7FXYq7FXYq7FXY q+CfOv8AymWvf9tG7/5PviqS4q7FXYq7FU60Xyb5o1uIzaXps1zCDT1gAsdR1Adyqk/TiqG1ny9r eiziDVbKWzkavD1ForU68WHwt9BxVLsVdirsVdirsVdirsVdirM/ya/8mh5c/wCYtf8AiJxV7rff nP5ie7kaygt4rXkfRSRGd+Pbk3ICvyGKpj5e8/eYdf8ArMF4YUhRVqIUKseROxJZttsVTPFU/wDK t3IJ5LUmsbLzUeBBAP31xV88eSNf1LQvzml1SeZzpF9rV7pFzyZiqmaQ+nWuwHMq3yU4qh7nzXda p+dtp5mkuHTQpNZ9C2kDN6ZgsPTUkKOxjKsfnir01vz48znSH82xeUmbyQk/oG+NyouSvqCP1fSp 05fDTpy25YqjrT8+bd9F8239zp6RTeXfSa0iEppdxXTcbeQckVlD1UnbYMMVSd/+ciNZuEl/Rug2 rvp1uk+rLdX8dsQ7qXaC3WUI8joNjQE8gRx+zVV6t5L82WHmzyzZa9Yq0cF4pLQvu0ciMUkQ068W U79+uKp3irsVdir4J86/8plr3/bRu/8Ak++KpLirsVZV5X8p2epWRu7uR6FikccZA+z1JJBxVkem flzoN1qNtbM04SWVEb4x0J3/AGcVe9Wdna2drFaWsSw20ChIokFFVRsABiqU+c/L9nr3lu+0+5QM WiZ4HI3jmQEo4Pah6+1RiqR/84yJpX+BtXfUI4nifU0tyZFDVM8cUSLv/MzgYqjPyV/L628qa95n m1SMGuoDR9J9VQxdAPX5Cv8APGyN9BxVh3m78rvLn6W1zzX5t139B6TfavdW2lwQQGeSQpK6sxC/ ZUMjfs9B22xVL/MH/OP50rQte1CDWRezaVbxahZxxxAJcWMtT6pbmeDL6cuwqNh47Koy1/5x0T6l ZXl9rEsEY09NR1iKO1aaWEzD91DDGjF5WJVwdtuPQ1xVif5mflaPKVjpusafeSX+h6rySKS4ge1u IpVqfTliko24BoaDodulVXn+KuxVmf5Nf+TQ8uf8xa/8ROKvqW+/J/yndXclwr3VsJWLGGF0Eak9 eIeNyPvxVUsPyw0rSBNLptzcvNIvHhO0bIaGv7KIa/Tiqg+m6gr8DbScvAKT+IxVkXl/SJbQPPcD jM44qnWi9TX54q8nu/yN1+98r+brCd7ZdQ1LWP0tokgkbitHb+8PEFSY5GG1d8Vak/IbVfq3kWyQ 25tdGEzeYG5lXd7p1eX0vgPOgqqk02AxVoflN+a8flN/y9j1HS/8JPPyGokTC8WAzeuU9MDhvJvS vtypiq/zj+QF3qPnDSbnSZYovLot7G01mGRysskdkVTZVXixMMSAdNxirvMf5J+YofNes6r5ftND 1Oy1xjMYtZiZntJ3LF2h4qVpyctv8ippUqvUfIflufy35VsdIuZYZ7qAM1xLbwx28Rkkcu3COJY1 AHKn2anqd8VT/FXYq7FXwT51/wCUy17/ALaN3/yffFUlxV2Kpto/mbUtKiaK34PEx5enKCQD4ihU 4qmtt+ZGu29xFPHDbCSJg6/DJ1U1/nxV7r5Z/M3ynrlhHMb6Gxu+I9ezuZFjdG78S5UOPAj8MVSP 8yPzU0Kw0a607SbuO91W6jaFWgYSRwhxxZ2dfh5AVoAevXFWBeUfzE0nRPys8weW2M6a1qF1Hc2E sagxqYzCwLPyBBBiPbFWc61/zkNoep+YPJ12YrmKw0t5LvW4wi1a5a3MKCIc/iVDI+5p1xVKta/N L8uPN9jdaN5qg1KGyttTuL/R7+wEXrGG4leRo5UkLBT+8PSvbpTdVWsvz70RfP8AHcvYzQ+S4tLO jrYkLJK0K/EkjxluHIkcKcvs+OKqln/zkFYSebvMsmoLfReX9bWOKyubJljvbQW6FEdAW41fkWbf Y+PTFWI/mj+YGha/pmm6Ro0+rX0Vm7TXWo6zcPJLLIQQoWFXaFAoYioUE/iVXnGKuxVmf5Nf+TQ8 uf8AMWv/ABE4q+3cVdirsVdirsVdirsVdirsVdirsVdirsVfBPnX/lMte/7aN3/yffFUlxV2KuxV 2KuxV2KuxV2KuxV2KuxV2KuxV2Ksz/Jr/wAmh5c/5i1/4icVfbuKuxV2KuxV2KuxV2KuxV2KuxV2 KuxV2Kvgnzr/AMplr3/bRu/+T74qkuKuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVmf5Nf+TQ8uf8 xa/8ROKvt3FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXwT51/5TLXv+2jd/wDJ98VSXFXYq7FXYq7F XYq7FXYq7FXYq7FXYq7FXYqzP8mv/JoeXP8AmLX/AIicVfbuKuxV2KuxV2KuxV2KuxV2KuxV2Kux V2Kvgnzr/wAplr3/AG0bv/k++KpLirsVdirsVdirsVdirsVdirsVdirsVdirsVZn+TX/AJNDy5/z Fr/xE4q+3cVdirsVdirsVdirsVdirsVdirsVdirsVfBPnX/lMte/7aN3/wAn3xVJcVdirsVdirsV dirsVdirsVdirsVdirsVdirM/wAmv/JoeXP+Ytf+InFX27irsVdirsVdirsVdirsVdirsVdirsVd ir4J86/8plr3/bRu/wDk++KpLirsVdirsVdirsVdirsVdirsVdirsVdirsVZn+TX/k0PLn/MWv8A xE4q+3cVdirsVdirsVdirsVdirsVdirsVdirsVfK3mT/AJx2/MnUPMWq39vDam3u7y4nhLXCg8JJ Wdaim2xxVLf+haPzQ/3xaf8ASSv9MVd/0LR+aH++LT/pJX+mKu/6Fo/ND/fFp/0kr/TFXf8AQtH5 of74tP8ApJX+mKu/6Fo/ND/fFp/0kr/TFXf9C0fmh/vi0/6SV/pirv8AoWj80P8AfFp/0kr/AExV 3/QtH5of74tP+klf6Yq7/oWj80P98Wn/AEkr/TFXf9C0fmh/vi0/6SV/pirv+haPzQ/3xaf9JK/0 xV3/AELR+aH++LT/AKSV/pirv+haPzQ/3xaf9JK/0xV3/QtH5of74tP+klf6YqyP8uvyF/MHQfO+ j6xqENstlZXAlnKTqzcQCNlpv1xV9MYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq+VvMn/ADkT+ZOn +YtVsLea1FvaXlxBCGt1J4Rysi1Nd9hiqW/9DL/mh/v+0/6Rl/rirv8AoZf80P8Af9p/0jL/AFxV 3/Qy/wCaH+/7T/pGX+uKu/6GX/ND/f8Aaf8ASMv9cVd/0Mv+aH+/7T/pGX+uKu/6GX/ND/f9p/0j L/XFXf8AQy/5of7/ALT/AKRl/rirv+hl/wA0P9/2n/SMv9cVd/0Mv+aH+/7T/pGX+uKu/wChl/zQ /wB/2n/SMv8AXFXf9DL/AJof7/tP+kZf64q7/oZf80P9/wBp/wBIy/1xV3/Qy/5of7/tP+kZf64q 7/oZf80P9/2n/SMv9cVZH+XX59fmDr3nfR9H1Ca2ayvbgRThIFVuJBOzV26Yq+mMVdirsVdirsVd irsVdirsVdirsVdirsVfBPnX/lMte/7aN3/yffFUlxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ks z/Jr/wAmh5c/5i1/4icVfbuKuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Kvgnzr/AMplr3/bRu/+T74q kuKuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxVmf5Nf+TQ8uf8xa/8ROKvt3FXYq7FXYq7FXYq7FXY q7FXYq7FXYq7FXwT51/5TLXv+2jd/wDJ98VSXFXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqzP8mv /JoeXP8AmLX/AIicVfbuKuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Kvgnzr/wAplr3/AG0bv/k++KpL irsVdirsVdirsVdirsVdirsVdirsVdirsVZn+TX/AJNDy5/zFr/xE4q+3cVdirsVdirsVdirQZW+ yQflireKuxV2KuxV2KuxV8E+df8AlMte/wC2jd/8n3xVJcVdirsVdirsVdirsVdiqJXTNSeL1ktJ mi6+oI2K/fSmKobFXYq7FXYq7FWZ/k1/5NDy5/zFr/xE4q+3cVdirsVdiqX6vq0dhEABznf+7T+J 9sVYndaheXTEzyswP7FaKPkBtiqirMrBlJVh0INDiqc6V5inidYrtjJCdvUO7L7+4xVlIIYAg1B3 BGKuxV2KuxV2Kvgnzr/ymWvf9tG7/wCT74qkuKuxV2KuxV2KuxVMNB0PUNd1a30vT053Nw1Frsqg CrMx7Ko3OKvo3yf+WHlry5BG3oLe6kADJfTqGbl/xWpqEHhTfxOKsvxVjnmnyB5Z8yQOt7aJHdsD wvoQEmVuxLD7Y9mqMVfOXnDynqHlfWpNNvPjAHO2uFFFliPRh4eBHY4qkeKuxV2Ksz/Jr/yaHlz/ AJi1/wCInFX2ve3cFlZz3lweMFvG0srdaKgLH8BirwnXfzN80alePJb3T2FqD+5t4DxIXtycfEx8 e3tiqWf4183f9Xe7/wCRrf1xV3+NfN3/AFd7v/ka39cVeiae949hbNeTvcXJjUySysWYkipFT4Vx VXxV2KuxVl3lq5abT+DGphbgP9XqMVTbFXYq7FXYq+CfOv8AymWvf9tG7/5PviqS4q7FXYqzfyn5 Vs5LNL++jEzy7xRN9kL0BI7k4qyP9CaN/wAsFt/yJT+mKu/Qmjf8sFt/yJT+mKs8/LbQdNtY7rUY LWGGZz6CvHGqNwADMKgDYkj7sVZtirsVdirzj89dEhvPKA1PiPrGmTIwfv6czCJl+lmQ/Rir56xV 2KuxVmf5Nf8Ak0PLn/MWv/ETir7M8yWE2oaBqNlB/fXFvJHED0LFTxH0nFXzTJHJHI0cilJEJV0Y UIINCCDiq3FXYq9esJlnsbeZfsyRow+lQcVV8VdirsVZT5URhZzOejSUH0D+3FU7xV2KuxV2Kvgn zr/ymWvf9tG7/wCT74qkuKuxV2KvT/Kl7DdaJbCM/HAoilXuCu34jfFU4xV2Ks+8gTq2lzw/txTF iPZ1FP8AiJxVk+KuxV2KsG/Oi+jtvy/vo2ID3ckMMQ8T6qyH/hYzir5sxV2KuxVmf5Nf+TQ8uf8A MWv/ABE4q+3cVSLWvI3lfWZzcX1irXJ+1NGzRs3+sUK8vpxVLf8AlU/kn/ljk/5HS/8ANWKu/wCV T+Sf+WOT/kdL/wA1Yq3e+U7fS7ONdMRvqsQIaIsXKgmtQTU03xVKcVdiqvZ2U95OIYVqT1PYDxOK s3s7WO1to4I/soKV8T3P04qrYq7FXYq7FXwT51/5TLXv+2jd/wDJ98VSXFXYq7FURZ395ZS+razN C/QlT1HuOhxVMv8AGPmT/ls/5Jxf804q7/GPmT/ls/5Jxf8ANOKp/wCSfzQ1fRdcin1CU3Gmy/u7 yJURWCH9teKj4k6079MVfRenajY6lZxXthOlxazDlHKhqCP4HxBxVEYqsnngt4XnnkWKGJS0krkK qqNySTsBir5y/Nfz+nmjVI7awJ/RFiWEDHb1ZDs0pHhtRa9vnirA8VdirsVZn+TX/k0PLn/MWv8A xE4q+3cVdirsVdirsVS+70HTbli5jMbnq0Z41+jcfhiqHTytpytVmkceBYAfgBiqZ29rb20fpwRi Ne4Hf5nviqrirsVdirsVdir4J86/8plr3/bRu/8Ak++KpLirsVdirsVdirsVdiqb6B5s8xeX5TJp F9JbcjWSIUaNj/lRsGQn3pirL1/PjzwIuBSzZv8Afhhbl09nC/hirF/MXnnzT5i+DVL55YAarbJS OIEdPgQAEjxNTiqQ4q7FXYq7FWZ/k1/5NDy5/wAxa/8AETir7dxV2KuxV2KuxV2KuxV2KuxV2Kux V2KuxV8E+df+Uy17/to3f/J98VSXFXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqzP8mv/ACaHlz/m LX/iJxV9u4q7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq+CfOv8AymWvf9tG7/5PviqS4q7FXYq7FXYq 7FXYq7FXYq7FXYq7FXYq7FWZ/k1/5NDy5/zFr/xE4q+3cVdirsVdirsVdirsVdirsVdirsVdirsV fBPnX/lMte/7aN3/AMn3xVJcVdirsVdirsVdirsVdirsVdirsVdirsVdirM/ya/8mh5c/wCYtf8A iJxV9u4q7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq+CfOv/ACmWvf8AbRu/+T74qkuKuxV2KuxV2Kux V2KuxV2KuxV2KuxV2KuxVmf5Nf8Ak0PLn/MWv/ETir7dxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV 8E+df+Uy17/to3f/ACffFUlxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Ksz/ACa/8mh5c/5i1/4i cVf/2Q== + + + + proof:pdf + uuid:65E6390686CF11DBA6E2D887CEACB407 + xmp.did:7800e661-925e-4ea8-8de2-affc20ecd1b6 + uuid:b70573ed-b1d5-414e-addb-e751d7d041d3 + + xmp.iid:1bf257e2-7ee0-4f9f-8d89-592b6363757d + xmp.did:1bf257e2-7ee0-4f9f-8d89-592b6363757d + uuid:65E6390686CF11DBA6E2D887CEACB407 + default + + + + + saved + xmp.iid:104773b8-b239-4d7c-827a-5a8a0e6556a6 + 2020-12-02T12:45:36-08:00 + Adobe Illustrator 25.0 (Macintosh) + / + + + saved + xmp.iid:7800e661-925e-4ea8-8de2-affc20ecd1b6 + 2020-12-02T14:57:33-08:00 + Adobe Illustrator 25.0 (Macintosh) + / + + + + Web + AIRobin + Document + Adobe PDF library 15.00 + 21.0.0 + 1 + True + False + + 500.000000 + 500.000000 + Pixels + + + + Cyan + Magenta + Yellow + Black + + + + + + Default Swatch Group + 0 + + + + White + RGB + PROCESS + 255 + 255 + 255 + + + Black + RGB + PROCESS + 0 + 0 + 0 + + + RGB Red + RGB + PROCESS + 255 + 0 + 0 + + + RGB Yellow + RGB + PROCESS + 255 + 255 + 0 + + + RGB Green + RGB + PROCESS + 0 + 255 + 0 + + + RGB Cyan + RGB + PROCESS + 0 + 255 + 255 + + + RGB Blue + RGB + PROCESS + 0 + 0 + 255 + + + RGB Magenta + RGB + PROCESS + 255 + 0 + 255 + + + R=193 G=39 B=45 + RGB + PROCESS + 193 + 39 + 45 + + + R=237 G=28 B=36 + RGB + PROCESS + 237 + 28 + 36 + + + R=241 G=90 B=36 + RGB + PROCESS + 241 + 90 + 36 + + + R=247 G=147 B=30 + RGB + PROCESS + 247 + 147 + 30 + + + R=251 G=176 B=59 + RGB + PROCESS + 251 + 176 + 59 + + + R=252 G=238 B=33 + RGB + PROCESS + 252 + 238 + 33 + + + R=217 G=224 B=33 + RGB + PROCESS + 217 + 224 + 33 + + + R=140 G=198 B=63 + RGB + PROCESS + 140 + 198 + 63 + + + R=57 G=181 B=74 + RGB + PROCESS + 57 + 181 + 74 + + + R=0 G=146 B=69 + RGB + PROCESS + 0 + 146 + 69 + + + R=0 G=104 B=55 + RGB + PROCESS + 0 + 104 + 55 + + + R=34 G=181 B=115 + RGB + PROCESS + 34 + 181 + 115 + + + R=0 G=169 B=157 + RGB + PROCESS + 0 + 169 + 157 + + + R=41 G=171 B=226 + RGB + PROCESS + 41 + 171 + 226 + + + R=0 G=113 B=188 + RGB + PROCESS + 0 + 113 + 188 + + + R=46 G=49 B=146 + RGB + PROCESS + 46 + 49 + 146 + + + R=27 G=20 B=100 + RGB + PROCESS + 27 + 20 + 100 + + + R=102 G=45 B=145 + RGB + PROCESS + 102 + 45 + 145 + + + R=147 G=39 B=143 + RGB + PROCESS + 147 + 39 + 143 + + + R=158 G=0 B=93 + RGB + PROCESS + 158 + 0 + 93 + + + R=212 G=20 B=90 + RGB + PROCESS + 212 + 20 + 90 + + + R=237 G=30 B=121 + RGB + PROCESS + 237 + 30 + 121 + + + R=199 G=178 B=153 + RGB + PROCESS + 199 + 178 + 153 + + + R=153 G=134 B=117 + RGB + PROCESS + 153 + 134 + 117 + + + R=115 G=99 B=87 + RGB + PROCESS + 115 + 99 + 87 + + + R=83 G=71 B=65 + RGB + PROCESS + 83 + 71 + 65 + + + R=198 G=156 B=109 + RGB + PROCESS + 198 + 156 + 109 + + + R=166 G=124 B=82 + RGB + PROCESS + 166 + 124 + 82 + + + R=140 G=98 B=57 + RGB + PROCESS + 140 + 98 + 57 + + + R=117 G=76 B=36 + RGB + PROCESS + 117 + 76 + 36 + + + R=96 G=56 B=19 + RGB + PROCESS + 96 + 56 + 19 + + + R=66 G=33 B=11 + RGB + PROCESS + 66 + 33 + 11 + + + + + + Grays + 1 + + + + R=0 G=0 B=0 + RGB + PROCESS + 0 + 0 + 0 + + + R=26 G=26 B=26 + RGB + PROCESS + 26 + 26 + 26 + + + R=51 G=51 B=51 + RGB + PROCESS + 51 + 51 + 51 + + + R=77 G=77 B=77 + RGB + PROCESS + 77 + 77 + 77 + + + R=102 G=102 B=102 + RGB + PROCESS + 102 + 102 + 102 + + + R=128 G=128 B=128 + RGB + PROCESS + 128 + 128 + 128 + + + R=153 G=153 B=153 + RGB + PROCESS + 153 + 153 + 153 + + + R=179 G=179 B=179 + RGB + PROCESS + 179 + 179 + 179 + + + R=204 G=204 B=204 + RGB + PROCESS + 204 + 204 + 204 + + + R=230 G=230 B=230 + RGB + PROCESS + 230 + 230 + 230 + + + R=242 G=242 B=242 + RGB + PROCESS + 242 + 242 + 242 + + + + + + Web Color Group + 1 + + + + R=63 G=169 B=245 + RGB + PROCESS + 63 + 169 + 245 + + + R=122 G=201 B=67 + RGB + PROCESS + 122 + 201 + 67 + + + R=255 G=147 B=30 + RGB + PROCESS + 255 + 147 + 30 + + + R=255 G=29 B=37 + RGB + PROCESS + 255 + 29 + 37 + + + R=255 G=123 B=172 + RGB + PROCESS + 255 + 123 + 172 + + + R=189 G=204 B=212 + RGB + PROCESS + 189 + 204 + 212 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + endstream endobj 3 0 obj <> endobj 5 0 obj <>/Resources<>/ExtGState<>/Properties<>/XObject<>>>/TrimBox[0.0 0.0 500.0 500.0]/Type/Page>> endobj 24 0 obj <>/Resources<>/ExtGState<>/Properties<>>>/TrimBox[0.0 0.0 500.0 500.0]/Type/Page>> endobj 25 0 obj <>/Resources<>/ExtGState<>/Properties<>>>/TrimBox[0.0 0.0 500.0 500.0]/Type/Page>> endobj 28 0 obj <>/Resources<>/ExtGState<>/Properties<>>>/TrimBox[0.0 0.0 500.0 500.0]/Type/Page>> endobj 39 0 obj <>stream +HlWˎ7 WZ+Q/M9yv 8 U=i%,Eok +?Sx| ) __oG +)<:rAQJ 2Zuhx#8f g o\?-HiRQ49ϖb͓4Hx^-j~1$-&qؘj^~BB ڹ#<VR9jC2a^FQKxp֨-@" 5:dF=|.c5GNAjNe?4&u{Զ ǜ/zls "VF + hJcE7ڎ>M+fsKf×.aQTÐ0 Ҝm/ё_<*JغCM0_vz +,',5ܹt|r,< Tiz.ѱ]da8%QPTǩx4тY=lfM`X oj+I ][lm7EFXgpK,hq]& q$o:wԶ]V& +'6K Z'K')o<zS*PGVw'9IY3/(*2gUH~i=T}y2yhrBdqKW.G=2{l,iEң:g( FJeTOv +l[">i34[s3mKQTd/ jHu!aV!cKak@q *ţf䐪ZDSKNK+O4L,XCE=%DZ&E,--T%J%u(vZN$F +{ȰS`~invT?7)LRy|ѻy-_V:Re^TmAhj T;b:+湽7rM kɃj$:sx˚Lj%(#oo͡T+0j/e-m63L|F[N610zTp;ÆNjֺ9:7}LRy*6N v,sHEV L<l\6lֱipjmܚh(01[o1`ȺAZL٩Zc'Sc<lvA]\kkh2ѝŋI̐4Vh$ܛz5r$AE41j"7X%qq &浀rlKɰ N;ۡŧ0&:ťq\ m6W8(J5hveΚ$?dLj[ aK%W}Pˈ۝_>Ὼ ἢ endstream endobj 40 0 obj <> endobj 26 0 obj <> endobj 42 0 obj [/View/Design] endobj 43 0 obj <>>> endobj 32 0 obj <> endobj 31 0 obj [/ICCBased 44 0 R] endobj 44 0 obj <>stream +HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  + 2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 +V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= +x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- +ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 +N')].uJr + wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 +n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! +zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km endstream endobj 8 0 obj <> endobj 18 0 obj <> endobj 19 0 obj <>stream +%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 24.0 %%AI8_CreatorVersion: 25.0.1 %%For: (Scott Proctor) () %%Title: (Move_Logo Design_GreyScale_Digital_Final.ai) %%CreationDate: 12/2/20 2:57 PM %%Canvassize: 16383 %%BoundingBox: 757 -1052 1675 -32 %%HiResBoundingBox: 757.064957058387 -1052 1675 -32 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 14.0 %AI12_BuildNumber: 66 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([Registration]) %AI3_Cropmarks: 1175 -1052 1675 -552 %AI3_TemplateBox: 1290.5 -510.5 1290.5 -510.5 %AI3_TileBox: 1137 -1158 1713 -424 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 6 %AI24_LargeCanvasScale: 1 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI9_OpenToView: 283.553585933554 -10.889479424075 0.699154969011053 1458 705 18 0 0 -24 43 0 0 0 1 1 0 0 1 0 1 %AI5_OpenViewLayers: 7 %%PageOrigin:890 -810 %AI7_GridSettings: 72 8 72 8 0 0 0.800000011920929 0.800000011920929 0.800000011920929 0.899999976158142 0.899999976158142 0.899999976158142 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 20 0 obj <>stream +%AI24_ZStandard_Data(/X )ЖF T 5kBkڥ])ӤfAt &òJjGVV{,gᏬ\ AC)j]ЎQ&xtTS̎[ꗭluzK~DuVeI&ֻ;[G7Oe<$S>lh0'oylN*c::v@Ap8(  pp " 8&Tp(Q (B  HH\`( <4`1czc@s F 4`NJἪS}Č3I<ΨA`!haR #a8 H, fF^- 0Q a$# +d}*"4L}ISsj&f4~?v?3#s!<*dUUɤTƠ8/ "N$ W,A.WQ,4"z*r^?⊏ f8 +*DC:l!gڒ9|Wf0( sH'FKTCUbh"#P;ګz^u.s4m0Exg%u3Z!¼C€HD!d8H'VGJ'͏Gc2g;Zg {M6-kBq0F0G$ Ƣ6L'p8 zDD]qP$jqf¸Q86aX0aY:Z!YeLahƍDl) ^0" a"!qϰх"a0@^g+E) hm@ +DQ`@9hGegy\yFdr#s2>9"?{rEsśQC~R-xIY&eT~ؑ9WˬwYMHw18`@Dbj򆃑KC+Z>b1Ɣ|yp@$5 y PF8$JZa$0 ,VFG00VtC: 4> +'Hl3/ja$P?0(6F  A!p[v0CW +@ +XQHL"M0҆2TaE&hiI ;0*@*p츣3=;dc4u1<2wBFH "q028GTJAd esAlOJziWe򮬑Bq2kt;=Kuhpd22_2P:cC<*sdzPak'e:Uhda7W>\Up1>dppA)LwAG@@à0^ؘ~;  G T'KL#iC"2\伧 ?_| 5 f hH 0$ +`̡:>yp8AqXQ! +a'D@,S K8q Lx8$DBX$FQ)Ja ++NT\aH̢ hXEbĔ|Dh 2 1t [D˜R󆃁H(A *a.0n8 c "@,°0,.nE Ba$Aq@*0)X$ Dx"NXX 0 Da28$C!a@`! h ea +}HE&|b^:-) L xLD<4$,..q; 糣 '0賹\!`KCCꕅueU @EoZH+B@ O$ +q04znYɠb3U$&qa>ذqMu`8%qttFFE*j$E8`DzumE*c,F1Q$1A a+0,48cppè +(pP` + +a "HP8W + +QA<A (0pA *pX` L +< +&D(d`2…& +$X8J #B@0.0a  `$@a*T +,p X8"\B &@pƒ ` < +*0 +" >!#@ Q$@x`G +.@H B +$XpB  +  *XP `d (H@A P# „ +&@A \ * ,hdT +.\x0aAtIɃ 8i +.`A.x0 4A ahaD#m='sȎL0N- +aB`"XPg.dpA X01 *D0 "H(A##QV'HLM2F`0`a D`#`P A(a(Р12 "T 0`dq 2bqwB`@X0A  0 &HX80 @x0p„ 6p<@! pPxa ,TPA T0 "`@YAn$ *A@aT8\@AHPРQYR ! D&p @P.!L'xCU1!SDG5)%4iUfd'#l*))>eMz}s:XJ,ZC0]b#Mb^)=3н#i5_}iJ56u!GjSzeohF)2o:4K!ܭ\!\K#"ɕ+2]5I:{dR]*jyO*^bU>̟;id/umɚU$LE*iz#ebM\S|Wߺ^%ɫ8M`h89Y[xף.Dc$[I6sbN\wi"˹_0m&U]ȿVNuӐ~2uX665K;Gl{M6hYJus.Mb%{v}6ic.1GҭY^taaZO/)MW9?e}X]eݭ6E&^xGe'f8ߧkeQ+3-=덡X˙Om +N/Qu|VN=T5|XrV3{½(HJ#2"J"lI2,4+d_Y$fsɦ{L҈xG$WxǺݰV޸Y:h`$3`o\DL~]n9=kJL}lT[_2XSZ{eQOd)M9oؤslOY$#,ʒk6~OJˊkJ]_bk4{F~+H߻{{+*-[8?6p.:r;CLJoxJ S /_xy^=)7:fFjJ3㔦.exWWzJMMf##3T؏^SǷi2oDDΤ&7TK>.G?K9at3)f2!_R˙9;t~Zk-GWߍvϻSj-ՖmAkW>X*h/SLHGcoiCKAke|&<:%;I;wt +d8ӆeַJK"|MQ^w'LBl?r×srg/yr^"Τu!Tscc~kJ|=!S"x=,WT?5+ӒQ\~Z^*{QIU?zuRG %nL|P CGi_dǑV"lJbil8CebM82C7/G.zsy%J=l&k|K%|xשrأMT%4+z9OEU_f֓e R#(z8ϝ|?DBn3UVǽױ;{\VRg*:uqt'yG:>TvMW=Kl{;I:txbezj->&4tamFa#OX#Ų@ǧ ⧮bmTm,2:V +S-:)w71zV1R/U9;lg792[թ8h`@8<>0OJuE'HeQYĞ$:oyϜJ.RVumnY^#4Q>*̔qΤګ&aoru>d2q%ǽ<ٌs!`ΕήjX6,#Mfz7[FC39kw*g_Ns:?wfpEbƙj77D)|&s{ݴu)(A}$ӏU1»7Ғ,;iq Ѥ54֦%MܐvVx~i#S.$*1!QdͲD[d^ϵ$U_V2]c/ҳ3㓬%!ጽ OlN,T~Mʾ<^btXK9:fhuf-<ꨗzoR1kgˬɩz얶**RrH9+v1VuYJѝNgi;4)%]AӃbxw#N gMmݙN;bSn&&,%uJ]đS!ݬJU7Gt余+M36T4ӏC9HRYO莖e9EPΎ^^"OAI4^ώ +Y*7JwRo𨧯tPh(Y£yjGiL<vD1;xy8DR2$O{~W82mfcXSxM͞_Dg85QiA3, # ߫^wnd,jm{̐Ui,떦?ܳIZ,3(sIblH'_>I6M6J +ȄJ9뼪#~2]sG>_̪߮iO'#$c{ظE&7caKx1޹hQ 6JM: cVYn,Y=r5w/սԵFRM*ò(X&n,I5ȇUyq1`U=kZr,q\he$$莓$ye/j$95#31{yJhL#y{s|i +"@B,P@< vB"L3"T P @BEWupA #p +(Hp0 +p H(,=40 ` +Wic,ɧ3D2(hKG*WuOxH'Y2Ia} l)Ó)ak[Bf$IL3]R)2ri[BXR$I Ff#A޳XfB U&; ko e(ѝjeC/!gմ*с8Ⱦ։ԽI&gM(VU2H9{ygV$<ʼzCuٱ^^ե~H%S}{󐐛guFLVҵՐS++ +EټChyEt{^hAͤl=xKǹCfژ ȧR҅RYsDS#{e2jRFgdm\'枫R&,NTsҢ*j^(粰LTgSZ\gKtc~'7^Eң*aM!fRI#D<]ZYftVQi/Wאgeq|c+5SyB0J3׹.N9#$ʫ}jwG~'Lc$͑g=HTHֆ@6%%ͬ伱ߚ^:zIK4X3jZbE'o"<4-TԎ)HvLwRb +g4%e$eT)2υD1B] Kr2:^|%G)GXlv\yeަSO^m0s,nƜ&ﲎ}Ӝi͡evҞ6#M:,LRi+_H9n6^&?3)-4Vw#Ivty+K6eQSu_L<̬lϬyOҲЈmf͢xH{CB*mTr5K!vṭ:ydmXsm(Spx5/еYb剔G3Q}:QF*2|ԯGm]uOU1KF<>+=dsGaJ:Wv\$ctEu,fc|Ff^9%MoSD{=3ٝDVhw{}$OwMX7NwrpR&Lۈ0'k*V7tj*EJJVK/%u*vGD8(M ~dyTxO;YieQ&a'R;zج\*a Wì9eRPgq&[Fh8;*iծEdw+s,sذz!eWYU\sU?F9Xnlz|*ZM߭.:Yo_ƪ2;tU=麓]g.ww'ikT;Eb=0[]i7 ]yw;+ +Ν' T'8YDž7=z M-rSΝԆU%N&ުi왒aNY5feLDI}IT*HB +`@ C (Hp8*V)SSNM#X$w-hpw=&D$*W)#EW+#fBN;]lFMS +>e|L$Lg3͹nzlz鹪f>դ#іru"Ĵ3^%&*/#/4XaQOY5VE'ٔ2/Dy!:FU,[bsq:Uߍo.)F!1;2 -p*}CxJÛLZIj=R>W%Qq(Kgg-GZ&}DGDfcSl,ZI^9d+%Z؉nhicfǪ|f585Ŋ'kv]LŬ*}z_d֙ֆMI~MO1B^ˤD(EcEQu]S=֑ϻm%(3ʗ FǢ<6+A4&Z4h,3F4_,Ƙ:_[I|IG+yRGIٺ_K$;p|I̓9l;G:5N8;n\ֽq$:u=gQˡ3cf+yf7;ikA]qdypj<̳1^UOȎ#[hYh>ю%ʳ;"Jm&/$AZJbg6+9vZ27%{ș"gvE)feurP +87f%hiUWmwW$6Y3/Lhs}6AFggq#nr {Oɩdr|6Ż^]]krw`9g"䫒gU)uIuC)˲c. +VuOZWBfUӁWOs}Rm/\mV4յ$βe6tw=o*H/R՘CSX3UW2-4ūk+Sʘ]6y8"%:]=6'A90omvj{Wh,ׯ➚ 4XUMP֊3¬&98]OBW[$ѵTgլQ:zNғR?ȒGsAt*:I) k芙!QEy|&d7#ٜfd[dyuڲBX?d|[KizsT5 +tuM<ŞH + +bZ̠d=xdQ0ʸ\ IhѷξvVvFVݻrucEB u+YL A:R#yĺ)Ì˺:s k0l; U]EƃD4|T8+蝻ĵU&jA^'5kTf27ŴpX ܗ f!Dlٍj'ko69M.n|h5d !߈v^&[kt>8CC7P;c]:Bچf67˜)o("6G 7t!FwAm d>֓/}s Z@Y7V28we1}ځo4:*t_`5G+N0{_ &d[Ҕ46C;yvXeC`C\$ge{3}߃Evv2h!d䲨??% p7Zn"%kXdC$GwisCnQ9*He2重 t)ӠBA m' +zQ5kؿ`p2^i@O܏әZϿ8ϟ^/]̈' GMܻ[S }ȃ0~g,+$_ nDWOuD pNiL㿍 +'t#`rB|jSIC`7ͯR6A{*k[t Pg7T@AL>2UR8_XRDt[~պ;o.B:Q%e@Z{pV̋R7L0@HM;!V̷K| ,REZwxSm9FeDګW5NVct>$qD(Y~WS#G8!0 *nu+f)ۉ]"%I6.2+>,UyeytNU8'vpP^WةgdnA0ch&?0@<MP](HMƚRPE[QZcP$m -#FȅX0IvF>mLHh/^T /Rx=)C2ye%@dh`BG(VgN eGDhl64c`|ظ h;A{_ >$5nRx.~.U K`6pmb$@Y@hd #tUb[l3vwk2QK负*%j P,{C :*@Rb;xg;4n*o }ҵ6N_ZxByOJ@=k||˔)ԙmNdxCB 9WFn]oEu&ɦG^O8LVt&حz=kQF^.l$%Ɂv)Ξu q1 ޺ #2V[n_u)0LYRIJ%`z&ɣW4Xd'v\dH֮XZIg5HmjE0y*nR8gzCr|M[ѿɌ"jj/VW-9dbҳ37u\}qyEDJmLyRȫr vY +LYSizk ˙(~D[?߷DhZ;ȟtI>qv& 2h=:YVF.gz[XƿZ+5`lv*.eޒ!+ { _O +4'nV?DfON'<|A?buV3 +5fKU*l4o.lsi +HN։Rשs/iK"'uyʂׯ0`غ 0ϒ~(gK93\kS1ݲ͸o'{]U(x xrrK3E}?T` +fXzFo LPe:Įw4 =׮C!w7`n&6 LW\k!J M,,\ffCO O̱ | +QӨȆپ܀տL-l$C=N ;~;~$ᣉJ@D0N-[-F٫$ "&ŀU+@!E 68:⼖YL'̲Y̕=7A àZtil!K|Rw>v|<ٷ1@t?)`cM59 GAJ ^³̩ێm,.-NioUA{ljmՈjn-.z1f\+NmNU@NI+CHM+N`H3~Hl e:DrMm-Mҍy@$!8.6%tXVijnUG!J%avgJủՔu.N \ OV@ז̺h+]!q)5eEbioռ5r6ňfVچ;_ppy2Sb &q YVK.҇OigݲUg2:,ztݢsvK!P>,1}<ֈ7%;Q;5>fdFma}Zw N`ȑǸ` Ķ/@9ۖ8PjQn`8_Z@LtyYWyV^bGI=ʌ01(U*k +q}G5kw& (ڌOa-_hFnTe +7#\:P;GH)R&ryWbzh'Ǽ78ʊV'qzLi~[ƚ(IBrMv'oVs9sV}X-m]CxV&s_@uNE~IsM"0* K"9ayo0 a<ŧZM>I8tw@pto4(:([ߠӈY*[A@) w}?J6Q08qKä5SÉe&fCŗP%<֎E) t_ œϚIfFh')Z\՝B<;AfP7&xB#I:KԢܸYw']J,a!~xKMl[:O6`Nqld + Ր }%@d> +|^\ +y l 5 @"&E@o-6^ vZ#4wz8aA+ 1 ))/ř^.=>$5&ڋzCW1 +]KNh$))KJ³=1&b6^`Q/.Zy06@f@H:;эJLipB1ۜ +}4t/ώqf7cjQ(o=uL'"k(Qۀݿk:IURFbSj qu4RLP&F4%Lx ZӤH+r#Xm@-kXmqd]viL$0BJ]0C5:S-s5gy9d,aZw}(?{\bN](`l|?hi]E)a;YHZZi;=dy4o;~rhj>Z8W`]ja} +!JhxR|_*ݙ^ޒ.)NW}ym$ok"6?KGDg7(LgHηtV"na4p Eg:%S:[ޭ W>`\/-:ٮS_29a2MC3:~?hƴQdK{pRPHN\7kBj.TB:H9<"@ҩLH8Yh:Ow{᱅ ~ԣEJ*;&=tV[TzE>E ېT^i|8@y9f 54Z&'39\ `R}F:}/G@5-71Ww2I# ƒEK\\[q(5ZЄ5߃%%cT5pEގa40TaN!zG ~ijVF$)e#óe8b[~]TֽxQSiS : 6_w5t՚E3S 5YM8v[ RpH.܌##0;5>:6 ƻ +Eʱ"RFM?F` 1%9f͙̀A+N$X{4VW"Hš7q7ڔ=>H$rZ +`JJ i]H,&/x{3CjE0x-G2dVc=kį R霙ZT@ +3@ +WU dK%;^oqH2Lu]lu*X#Wy'L+jc6jds^ teWpahm k˜ +htwXG 0We!J)!fͶfZn%G` '(NBrA2 PV͝^ͨjlDa¼Bɤp gx.dm' w1S u51?K@ fli%_V=jB1fZdqR&ӲMҷ `yX +G +-2_"vǼHS-0y@.!Fg\d9l)AfxIPm)23ل\X"qyb ӚDC'3JylF8Hx0->2HؕwQ EjTn!PIDCv_ %q{{B.S<MW*pAxs-1D& +deSfgPOH'XWޟ2^V29ЧIZlenˢT U2b ;~(770Fo&?fo", +p+?kǟu\[E?CzZ&D3~&g /Ogs|QFQq%̟K&zMXS/{BCȑ]\LrZja%yRlԊPg*F +; N32C"خ)/\64\?aaR18!j J2\ ꓯ.bϷ6ibj%|r bQelg ೊG`P$a{8ݨ&D=NW{1#;E!fyhxHㆄL4ɤoFTq4^C.^(6ǻde 3I ZR3ui_X$H +V1XOgvєvLq~xU+0]|- =:1z[ovQ0\rk t(-݋JK[ 0o0K0?EC3;M;xA%\ /пG@ llӟ ڶ +^]D^Tme)„WXѥBc J4s>LLx +؝.;Ea=U(CAqqb ~ X5qQDSpONs#Tm;-# -`rȗ1,K,@NMFNS-a^`=C']x%[W{61떿&! +ZC`".:u ңY@e)Gt|x 6)*XaRPh~W4Wr'@$Yn+Nk0>A}ռ"ĭTK)1?f +/^zzRA&WdL"n%ݙˠs|ʢ=Ϥ[0DiZ5qځ)i K"=2ȅ(-9PdA 2b;n%uz +{1 2] +&_u59 iB^f@@Hy I\$ + a-dU"Rqx|OTK9>" C! $-LfE6MYuASDM{_s8kр3t)++FY+U~''Cb~qǠ*sn&Tqi5am7zݾpǔ18.Ǣ[ + +mVxY}'egĀBem dB]q g~^C$@:]jm_EOf)gs1`ZF.qg2i+ܢꆹ{=xfV"Es6)f +Sa{2=\H120K(%Lҵ;[N*V-Avm /VG Ep8M« ׀i&uKX?BY(4$iÍD6,32AsR/DꡥysK$Tb-P*k]q3ijG+31MK78DaDG] +dqDVKW*r dPc웃 @,1]SZ&3KN]75g=k{kQHnL3XAhKG81D$%TL]EW'WoTj&k r ++XW]1w ی]D ~,, iC#[, +ˀ')+_fفf #W}nj@]m6R1D!\eձMSѴ)Zz:Wuq?@)(~b7yA.^㹐ЬQҩ2;4}rLPHmzoSRRޒVn=e$GY) ]pGOd}PzMfPi<et +DB5և(;ߵ4pҝ姍d/ua*&_S4Xih> Cq7qGQ&(٣Q5 ?OV&z>*2ON"Nj)Ȱmjs3`+jBQ*|LRZ'Sv^Q=Tql~Yߛ?E@GD4ɘ @IY䗗͆|ረ2 +Sali ̤o`CAۑ&o{뇶 +.lTB&`4P9ELStiC8 ǩ,PӉ3z2+Xʐ̠]*u@ 0Ot"JZ/їd6`% <ƌdb#F^4"r* +7WyN(ۢh-=>P<ףHs 7@"a?Axt(,7#~h[S8CI`5lMМ^!.g,\x!? Y4PlRQ)\قCK\a ڃ10H!) G8BDdrlN-q|r)\Xv !Ra\~ :LELg)DP}fAC@Ⴤ]$GNjOߍy[-ѢVSWi>jV>A'wb9(:*CBE8\m/)GMsX*#;GFuaڬEyO <@?X)/B{0e>qZp[9Jp;(BhQҽW/3G@*ZV1+`LE1_5% ܺgPNp +n08nO H3ǰɔ&z0ePHiX +wZ.f{2A(w_ ⥗Im<ǓjL +=8t1Bp`c.(ŘN/#SP٫}J,-vf5L*a *:W|UPžpF[)EaJC;{0N珮}dXɗ3_UˋP8 +2&L6pnވ69Y,::iSĸחBh?mIxK {r>:X ƃJ ;?S<'WZlO^=Rz]8j)4(^#/GK҅އdq$ak|s_٩\zIEA== :ِ`V)#&¥IRe**H NBSָRZVtꎭ1֚1qʦ^Z/^A$(,|FRKh@yuI]f}z9]:w=Uj$ _H8`h NjZ "GaDe4wY\ /X*O'|Ȧ +DY+6*\+50)q +)@gUkK5H*"YO6E%ub80fMa a(72 93 0xQeT3PvyPHmXGmUj3jż fs$6$]e~~}/a A'q= ,xq/P0Pr`5 }ibE1t$"G$b+(~|9C86ĎN [TK7"_)?QQʮWwI +)ǎqvk*AlVMkf\Yf2r*'nK3\,^Adƺ"Ug2ɅQ9}F{5aL3F:p>(s7IF5r܇Cw;֡̕ݛ,Z#Pˣ*18慱ġt.Œ Q_ZL~z+vYOf* D!vx'\N&k*1}i)_^I)`KDY7|0B<)Mz*Zx0bn+yq`UiV +aDo~>ez+ٖUeĪF4+""+ީ)x G ʝAQf;|銻ʲ,#Ճ1L'y[#_S5T[u3l-n4`ƝC _6bT҉eXAܜ&zrR[YMzٽD^IH☀:?ghLJSTi ozvi= хhZ5J)HW G*jyuAՇdSHdW񵍁z:§ZZ$I)O +i’j=خm 57 "=)]C[3 w3+'4b,"u%1*cR|B$(=Hle%4[!.XjIl+vrO}F&d;#Ytƀ{s* ֽ> xh*pMjYMn;[,g2WyHD]+͆|VwD dpP5S%{Phĥk+F?if;&>HesȘJT!V8RB&I*JMS- +E|ZkQWiDOd()5 Uf@l +=*(ߧ=,ͺ\H2xSvN#9fn6 ֚v4 F+gj)Ni^ y2=<|q?S,H)2!oО\dIVb̢x$ye()=m0 J½Itv%$J!PuÑ&҉3*xiBF ++V;YT;jՈ@d""FYF/|@E9Yg]5TX%J/Pz-yקH6DYPP% tY _B[o;π0 +cM, +:Ki'gAQ >C#mT`k& Ozw{7/{0cT<-۰JuB(jY[i9]B(\B,8}[]B,#Uit%DnOǂM /;z hA4Ǝ:*Cp? =;-̉4ϒymL- 1xRo P*^oCV>rVJZC*n5o3Dv;' AL?pvU.nѼsU]JP=N^6c +SMbӫЮQ2$j ++-:uJE|%ۛWժLY/ }@kQho ۉm+.3h&rx-IBy\WX%/ A`?]~Go&4#~<4-:s&B[E1FL +2$+Ouۚ`l.UgojmCQ6@DP + +X1֧# F"am)Ҍ&.(\b#M湏D3sa,,TI$' )g6 L#f,G 1,Ǧ{˛JyH3ZE*lR1s)XgAdV\eXo(nSz-h%SyYbkY`w뫘N# SX ^0T!]=W~yI4sIΎـD?~?+-7U̽ |:eW'֜]2#` `ay`PEUg]YZ[?w)c`~B`] -36H*mftkUZlIu%l?ȸw2C! J(d5[%fʞϡ()}ni!4cL^K`unhc<[Hnl&8,ɮ&0h*:>wh!˾({*WcVhO/7 9b {BIa Z^ ;ޱQ̓5[O2kp&n{үZ^48`#Tj\X3YɹI1rc#rd6 ~41:CܮܡG2N׺Px|ȧ^}^J4cS%l +?Ky3HdAʉ7wVX>_[p@2;>As91NL1bo D%}s`A\^_S)~D_,52t,)PŊ kE + 82T[^TcJlu~G THI?W?0-2,~!EEu{r)cJ1!:I?@D.̍6HQ+ l8}1z@T*8*=#e]0`$ j%\c >(2[p(3>O}c1.(G\mf95%:+`>Ϋ\ +E/ M@w8TFMMI<{SFeHd>-#Sw Z@۬"x;UDL__N2(Y~΀p~=w=i VʛumT%i$gXr*;U˅udS]?@y{G=)y0秞q-.=# +a3oۼ88 lZM#>bN(}Ob5aĘʣRjJw[W͍%l`d1^rR{G_W[][+tKl*p߼߬h߅lt.L`Om}KBѶEJm[`MoYX[bQ1$VDb +̰+vhL#7>DO]գĜ$B}V}(K@^1=^RXiƱ"ʦ`TfoVw1i\)4;qp3}hw+6m]; +f2V|?;Ӡ?J +<߲JL<a((u'y!ى*o"28n?2z `(_"0ihw\_2Y:Jy&c EO}Z[=7gbUVr ?|k6)Xǖ:2\f +#z~eRȍ( :|]aVX&K.azܷ DIώ'48, +q=z3U!#XR7c +|)h6hpDowI~,)bP0t0HbSSߺ& [kNyZPjU!iMRJ7ܸI yڂLB?1%3pb02eGSĶe1tp& 0.DͨڥuYJE]鴦΅k%WBᚥ4@ꇗ:+R~h Jz Yȁhk L^[_C|adT{i][8Jfd +xUۨ{vI][VޠRKKa dQƐbM.yz[*2[)lؠc3\l&*NrJx:]8D;R7Ym +4؝=1$K;_2O>@U0=頮M~כo=gӓ.bL nb*\W:^ +G"0Bt Iwr4 +);L=!޻x7| s{A%EkYGqWPS; a!3_^Hdu KVP>`oJ7}F=ͧ@q6 +!N<,8B[ŒNBlBJ^6@%1H!2t$c~_3SŘ2ʘ\ +4ѓa[X-:JV,H D-W]H &ڂ,}:$4wĜhSdKw"f{x[lU#%v1K,4|cEa#M,y ڳ03_afd#¥CJ^ v G(N[F +nG+82 #:4kR_MITzv#o`JNTl hFPГfQeEn2/"u~G+Ic;`J_۳;[j+|ᣧ]lb. +jwdJ_:2J;D +5}qEiv::nMKe^ql9[jK[7󪬒Њ+ہ2ŵ%*zQn~T\~GQJad'*WD%#S}^Qު4.w< SoT&v=MbWf] FIAP>e1.إLGRq3ҿJʼn\BѤZhgNCG0(K `̏v\ZF^,"j1A:)J ^pŸl(͓Ai9ݓ^MbNCmMsOi~3b 3i*yŇjybN ${Pi{xp\%{Z-^E VbFU!4Χd,Hj4nǔ*y,F={!*2BAU7()hWR |E/VSzY`Y1'# +? nu6G[d/Ŵ&qr-]K ꢪ +d$E:,X!dugA1.j" <G,)WĘ_YDG֔J5D Ͽb R t4Y}Kck)OE*4VNsrYL,V Qr$-#uh& >9vKv8s bE&ց&zR'0X 8;O>l%1y.m ζUǩ/wnxq#.g&,W h:PBD̍pNbK+.*MuNJ?m;bhAΩy=NX9ِ'FfD)doO@ W+"a!̇joEn6_*HZnu?H=]㢳YG`s34ڌc%IcHLefCJ! > h1a7+7eG ~xRiW%q]P6HWUUygZu.0Q\Ԧ Xn{>vagfy' D_V1 Nm<Jb jP[=-bvЈx/#m$8oQ m@\*pmqLrZO,C\asL#5q)[+?"&(}9V!cd-I0/DZįKnMY'oksT@G_ͬ0:WJfWvWL0Oq\a7p:A$.R2 TXGaQ#hX=mׇc2<?H}_}~/t?R |'j{j>о6*,d_S_(ا|:ur\oL&-$DJ xُcJeADZ3Xr,,s[ +6*CD 0}X l ؎|%;q#zq^euv cnr~L{\K~ Q秴7 !CE-=>2%j竩Kћwv:A>7ԃ:`l&SۣvҒ*֘hčtlܐT̅m]+ץ \}gk }i}xo+i ֯ˁO\}GU.8SHP~<hC"PA]_Z~[2@N.IL_-Vo&sInΈk.yPx\~?LmdM"6|iF@A8k+ƾYZ{t sۙ~ﮀ~j^5*7ܺ_~$qd@ g`,(t_eU2vù\ 7İPFz;pӼ%{3:Ka:cx㵱{C:x};~`V4pz}GeAd'ft뚦y ;s\щ]J\/6BM#򇈒=Ilƫʫ Azm4OEy!|`hꮌAS IT_+ zM#Smx恡)*Ce#>GJRRϚقq˵V;0f)ST0(=J='mFrIGHM;GH +èbt Y5>&,sMѭe`e+ 6&l\ܢ2`"xploqF9HZ@~!4rWYUu7U4UR*E#OEJvITLR5T{IC'!*6*]?qܔph{O`uXKxI5ȶܦ6kb3S􁨅ͨ?Q_Y7F+"[?Qop=5 _0@Oϳ1^K7sO[gb: *"JUcY4ρ^9V!;y/Xۧ03hc˖'[ͦvxhW ">QO۟Sh;X@:rVup؝-v3~s^t-ѸY-AbdU +99^ {  Lc ޔ1d?L>Knr~(WNGP*'|{StȠ |ទ9w$t} _|h\J*J**kWCbaR%\'}BfE{cI :ad"Py6Ǎ8BCB8xa[Fb7c4?+ƪŞ0#Z#+\jJ@) Gkk +0&bI*^ޙ0$JBYPgvN)M35, i\]h_;gmDzƺr8A.4uT DvF)@h+,:7^/0BG {5o*۽?AVUme5@49m.y37J)m&ӿt^ L*ny.52Ҩ<0y@bnQCs7g5It; )3-iZaN-8 )/[~VB5>:$#_Z7~6ʖ2VV-\=z"|\‹EBW]7g9R:>rMKߞ^n{>^)]Ejoި4xF{g_l*3"M6{Bl IUr~TwnX*[>ݺ,!w@soK"`Xa@DΗ^a;nZsj}1TBq!68?#HrW8e1,M$0>f+IZ-XK2V@-N,U$;(R|76C_o|3 g!n?!?pAɑtߗ݃utlR$RF b`Ub5PA-̉7~9aĆ%(&}.Ge%ʊjLs":)/B qyCSzo*CL T.??.8]: *R->Ks<<%]N |iMs֐)c-3M辤E:v^F2J*%k8_PuYpx"E@c6#\#[/22"nPn{.a4)OpAa ߤ(ιER|*`ÅpZovqXDXXȍW J㮰6N8Uz3t6"O__%Lc) aIA;|Pi0U *ĭ4T.s]Hd aZЁJS ;gi_ҰJ7w"HӇ!pm2V|qVd (0!sGrӒ?.KXOx:XP#*0hkf= AI"2JO2idAau,=.-j_\bD1"ǡvR1Aƒy9m|8y +^]բ8tujʼnIu?\8ف `r]&_c߾`Z6bd-j5'G=zV-մZ-30-x`]Ξakws,AN +E5H]-C8W)$1{+_B39-73@;WvҪr+8Cݑi@Q*LC{ j;YaI?,1)I8# q_׻dҪ+{5Lu(y(icq|}=ۜKTOBjZJ5\gN -B/论 L5yKċat88%j {]bxJCzA70QFbP`יlۜ.^YylPͭ$雡װ|i+D< +y +ߏ% DQ{얤eSwClf+, Lv;)eUEE-֤_ )Y Ce-ZbtJjTP Bsn0#K,)SJRD?SBc2+4RR*F-xwEj>)Mun9y_]0B5E՛ک"-B=wH]#$]3>nn"HTV'B 9$W!+Gq®4{B3q)5C!(3By^1d="/K6Qrz31!5U4NU5TUmds"Qa meQa*1+E9 1<拽\ic@}/k:um7&MZ% +gdH»B +#徎0z?{a _NkV33P}sZ5֪KIJsM'TFG 1x7)}^P +91Jя#31O1R˶CIJ0IKhBxOvc%LUIjIBi"J /#5MОKoahYi}^# DC A$%=ȝ ;ȝ)psH;8)$˜ A]J=(Ng c*QM&c~I#ˣPE7♙d)oT~(Ǫcc&b:Rً}y~䤒ÖF8!N]H#h<ŠQ!{T.!wGʼn]f"Mkv߸gyA:"GU'6bTgVV+ŜfXTlƗxp^-FAAjA %5 !Y DB 4 BB PUy=61@U Zdh56>xdbb+,QQUET+^crv*\P^bj>.ND\SwH Rerj˦lE\ތ>U tv հaؐEDH@9!,)BR eoBeb*$$bB?@N*T $A"$a2E%cUuB `p"RBfC!bB$".Y6K0l,D*ąb[!$DB&L7mLt:R]=e'Ќ&e)e/tdXNxiRm6+KLG)YH {5t0pQ.RYAJ pxQ"_EeFj+U0 +R'yDD=(:_h_2Ú"3XT!7t%1d].#*93=WaUDaUոB>ShB}5]D˧"An 2Cp^35zQbBXYRBq'QZ *ZPAsչ8$PAf.UsVH%(Hpvєhԃh$ 2-3 5cCkuwAH[xqMhHKhlMMiE#1UHrG +u4%Sf|;PpeC: r'4sϡў25q +$eC$$dJRPrq9D$,""D†"aCr?bVdmJPF +gPI}ZQK!5~.T)%I ! 1 +ɐc*)ːguterZ~F!8Yw8QWzX8yi2?qr}$e"ҖQ]BA +A"oig4Nk: dcNMiy.Q%kUW)g'DPOFrEpD&#cD-zoZ]zբV3 ZJM.4|$r,Ia>Z2uT)jM+sJ=bkdvdF%t=b<,D'{]Gٸ +""pd0+e뷋EA"a21&L 'OiYBl N*.h*um7w#V"89NZ1"3!9=1 w֨b:Z| +~BePٱDW>' +]Ḧ́&L$jNɤh3 +1h飚~|ůi8XQ W/AV3߄e \C 4Z4Όo#xxZ?I 1ZmBAnBTL$F(O B}4)=T)1uqd#czTBS%!f/7XP +&iF ]20hD q"?Ծ0z qζ!tܛT>#.߂D?>13nY gaL3KL#V`kNt3fDjZNWZ4| Iq}"T rtjʮFBCݡE( dzgB((x.S[<)sQAW2*VA 1Zi+EQL4Ɖfbt>V(9FHH*#BVRCLd7CB 2JKbX^X S -X9E &I^&3YS8 #4Z|єb5]KRgf}&W;שs8v0(PSںj>ʞ>w=C;=UD& &A%73lJ?k9_b?=6?Zm|Uy| #ʅ*C.EaՔL{3"Y^86¢Q`nd~RT~!ɉC3(I|܂uaU`i ccRz Ұ,o(Q{Wk6Y2 C6v^0uHN +K9T""2Cv#B)!'^2TEHi$8 WMbF) +VmE+Z<ĕx-J-J5ZԈtň6\wI_ʹF넂 2%3we6¿v/o&!xE{}:"ZFB_ZB I[Q!֔HJsB.E{LZi:C:>R DbN3uj 5y9Lk$˳dF^򄺝N:Q≂2Ⓦ*HL8^g2Mǖӑ]xqchMj,s` +i*hlU?cH<R(n +O%`֘\|O ߠ ?CD5&'fᕹ,GH0DX~FSRP/*Q;tAb.FQd `)$Ĉom)" +>d&__jp*cC2d]Czxԩ*(UW Vg5FP43D} ֈ01L&juKVbUA4:zH& 8T("#&8ل?~S 4]ɡE-C\Ac4T:*v-fZmՙTŽYC邩tX:tu2tbMrC8UjK1(9R[*5JLR1 T^4[i)(b%≴I,夷,EGB^hLCcB T@ ȩT@U(T5Qsg00fH EǡR ,aB$dp#do5 _"䟹*^A2do!uN4ϒ("4 43RO"숡.d@Sy9X喳dɒW?[WR`9̸bOZH<2!B (@(#1?(vChqxCikpd~9QuĂ !iT*DKfD] +")Sb#@2 P"@:EPM u % +%8iBxڮ$*`X (n&U8^8ʐ1>Ъ) +d*-%GXM*5&G57ˊ: +('-q/YS㵚 +s$X;Q܁}:x!c9[LմWO {銋1LAc,Ͳ؞Ƶ ,OpYWFAdX%(L5u/%F!呣WgVy{lZƟI_4HWr̆5.B~7(f݋=M^Q׳s:28ˊ}夀É' -3 .zX!mhw+3ǀ!k='j$sI1ޛk35D3 h('B€IVlHMYҜ.+ohŜDkb+jc\xe1Ȳe5s{? +ot>œ1dx9!m,Z̶K;fc6vXvSʹH4cl+x1MӮ~EXST +r +m-UVZi|EnEt*8"K02xzJ8cfkvcJtXOÎɉPc c\lნTS?E5I)r/6=J)e!$1 So_' +v{~9TSpN&xDf*T0-*6%f]Yލb,zL,1wxcҒB>dV$} X_-Cf<WʳFw,nFB֠Y> y$֬#لJB!h{ YPFg&) +665~wkj6 M]\[8OHpۇۂxe + le-&"uP (g!W Y +$s~c_; >br̴,p_Vj9do7x`]\DB2|iXBA :n!eQ7#ʊ`ľ8D E~!#ǖ]V 8I@XxZaIN΋B?(8xe`ʃu4)?5A˂=$a(y;yv|Mg!;-HehPFj®|a<B<[ ƥQ`uHZŏ1֫r)I_0XAa x̐{"ίM0>tHfm0`q]ڃ.븘 p'oՖE;_ +h +?:18\Cѳ+pl8۸\ڲiHmm10U\E٠QWbIa"7~qq>1=xR"( fi";*>ǟnӮ q +v;մM)2C$TWMJO!mHbzI{ C#iGuT #fQ;֊eKLzS:r6v)-ن1oRO/ݣ!ː>pF}F%jvE7,K7ě=ӫxM6M.,3kIٱG̎Ck7HFP{On5@OAbV3T}n$7tPK9@?@;[AfZ) H~[oES1ջ̢z'Jsϸ"QB%\|W&mXߕs{\^(H@mn'V52eˀBH1t9{k\ jvNKÝ"ItGx!3ay:׹d7(pcB.L SBHg;]bU8: +-hZȗ$ (Ti+̇LEWU,^:_A6Wn-TѴ81z G<8B *u^՞&o< +>ߖ?.N xΌ/☿f%?[WP9 KmZ},c+ eqz%YHDLmo4ʀAuHaIW`^&aE BD-/a㋃UPgDM +0q Uts2hpc|)ibd%UG Zf=h]֫QD=4^r34kqŜ/G?&£(8Z}(-/Mx'Mz`] =I4MՃ j=֥]w[sߥ !эlu/Cຽj25[j!u/xF"j鞧 J!a`r7KS1Xu.=[q#YfpPCY$H 40ye,)1Cg +BWG׋y0WKqs7= ~>VJK`0,z^oπgl@':7E}m&ٵN xa/g~AgS DP/sc_w],@Zנ)ӟ !?M g~qslՅ fȨpނN. UOL9P= |;ǾCl>E J)j@dsrf[BwmJΛxS|D2ng`6YT8Ad%_ɉ tQ9F:Ri61Rm㾱`=![x.:렸ɴ/G11#qi e$|oBW7@J /ݦ$tF|`<2 +å Pry.Z.Mc/Wv{IJ~-p h*Sbs0YƘGgc-#ftT$>wCƏkx:("\dX! E'vd-XS5/l{ Lxa ǜ}^@yVw +Op Aﮪx[̯ȫL=pmvc|tw#1LȩA+ќ}%dѨלz3߀ +f,<b&a & F-:d&Iqij2N!9ۯƗ '8?Du6 X61+>F + +?ׂfQg5㑋yxF` y6Éwd~h9Ѯ͗;G!uJ!sSō2hpJϤƽ_8,43v]JAeMa*AƮdѴ`{F[{fd NcNTscn6Ne\hAܨ-E1@H_{<& iɋRg=ݦ*4մɡbak㼽nCDx⳰Ԏ ^XF6)3'qibp;Z!$1 +0͜OH(z.׿751YP@<pH,X\n2?.NcrF> `l x7Ii[]:At6:QNp9-;H1toax=7D_ Ll.o:M'WrC Wľ=FjE23JY`m.k%qn0uŻf9Gw~QUŚVG=)J^mV%:_ScYYluiε@41e8\fXJI&55)! +x6ChǠ}]" npP^ŋx$sh=G-S]a!yL: +-uKuYT,*~ԍO3D4S/9(+=1j*>fl qD..8= +/@aKG@?!=辵A\YݲQ큾^uOvSe/ENh +Elv +OP> C>RƂ)*9k"Kr1{:"v7A ]r!TYdaB޼4#Ҽ2Rm%|Se "22u]`y8&X?}WB9L$G@Z[PjQaN.炠>+y,|& bw@^/¯W':FzCbK3liFCuq &OL ,WڄpU x)guߕ$ɞ2tׂ0Ҋݝmi7(ardQN$QϞdAD#_<[#:cUٌpfPSФ &]wRD' 2Vs"G!}zK 'háX!KPET'_s,GDZd7*9F"R⁢HdO"WQ z#.I+c{X,E}DZpf @Эý3^kĈePLlֻ( ak{tA~b! 3^$BkX%TlV@\ +!ۈMn^WMNx-7 5  +k,I0H}Ib܈}7)Jދp%!Q,3aSp;K]'%kNL\xWF9P嶅sC2$;nqA;XDC% h=,2iBEZkMan`dTiEJaV"?È`w +&] P,?rS4,@8E$ E޳<ʞU2C[:%1@vk1e۾3ζ%f$Ikb ʒ$vk4&Qv 1"'Knb pU{g9v$6,I [9xݥB>> ibp>حמ& o%G9Cn$'4eCBH dKZ9=fїe$^f3k4O)+UHUIp(\JJ,ËmdXxX1{eaM|F|!/a%<oqz⯫Tʞh + 4rwm\ ?2q2!vSFH2ڬB^F7VZU~gg;KRAѝCG!oYXk` :K1}y)ET4}dnugS#˔H0s4"삤{[\C>ĠM3'Ђ]4:e Gl][>|l O|"/<r‚ +d_x=h{kQ ڣC.{aPz@a4HGN=t"FC(Tz,p==х1j4aRdT<$!MHxy02|v< SQcRp4xfx;Ck|FaC1Q,ޡWhtewhtBwhs4:4v84Jb0 Fq(ev@?0;|5Q p5:}R1l:ď* : W$FCvmc(tê!txN |[Co4%%BzϑN9Fk9m.qT9W5D`FgYxrrC`Dڭ;%^bf3XC q|]8Za?H]t8t4:a~dP{}#oš)x[4 e¡Իqr-sDֿڡ2F;^.Np/Ҏ> 3O'sdy¡PU$u.] ;ÓJ[GKi+p:2Lɺ!utY.|@: DvCݺ!0ꨉnd:^0X&-ÍEIogюۨ-m626&ԫiݢb[lVCaרB`l|&t 6d¿Ʀ*ӡ;ӯFjt= +i%"jԣ? [;M&ӨtpҠAҘ.8- ө %s߸$7-^DGv$4XJ4M Q}Fj{r3vX r I68u͐(_}ΌdسY̸E$y;U2ҳ ,+gaT_)wx e:#pq G`ZdvȨ;*.Щ17XY5yaOLbǼDؤxwI&^dK@7``÷ yVTcqztZ0_` 2$m@P1O t[,10F q)sbzr?`RahW,6Aaba>EF{x+t`30)Bh| ô?+j /ȹF8O"_~Gs?*Gu^d.p`  +HO@w%+J M 8uQYrr+ƹMtL. eH-\Ђt.1HoA`u/-!͵$la$R ($Z +,j1BP bHBo4SkHahϢ YP0bac(O>rY^# IA!xDڍHbM,88ÂUX4" gHG`aT+lfn|T"$E]+ȉsE؍+ nF +4ҠP[#5mZqAV+̬F.& +_. +rD +%0#U&bS#RqU릂ڥb@I]wTtQT( eHi +zt>EOeI%n.(j +{ăl~=S#%\ +"X +S(;@X,)K)TA(<ӣG$ QxVM7R&ȅ84A "1ҙ@U$ vFB`A21H C$A6L|W` KKH=-q K,1o)!J2R%Y$+ҕl KL&V)-ѼK8 XyɁ&q} &"p$7LD\1ى$\Z|UG@1f̤"!3i<$CViqN8 jRHT~^|D68#$oa.I PpB#U'F<@ɣĘtш$ό; u1+O0ӓ.ԞT"f',ĮOQ +@ +|6"5naOꑈ+f(lCf祇ynJ@{Q8ĕgqy1u(ٻ#ňWRSzO((!jA"ĬVgVG dJ T dAao t d5BV T&•LqH)n +/\A&QF))fRF};4Mݦ @ ).\N,T?. v)S~si +>oS@ $[{oS:#F5!r%N9~uٔM)>)oД.Ca]'|P{HԐ{)EidJKq[=k)fӃ/4!y|){`2\CAx(K;0-݁-pеFM7l1^JYT!CtXHPR:QJfH'!4s JJ9Wb'(hCbqmMJUq@H2`S1mFH)vKYB]dJ2/!Myբ)ܔ,XBvL=)Рro{D3*H$p`20$R䢩\ꩴp"*ǧJpR`\1AXJVW ~'f:`Y]8*촊S2b]ނ'R'PK-88{\bLrdU^p*X/{ AX<ŮphU1pp*ӱ d0- 8(6<ױUr*M +  a~Ua6HT+%g+0aBڀ-t|6rt-+ecixŇ!zpA1_)ktD,t5hwaihNd,;@Ȣ0CCNL4ZY/,sh  ,}g38=K!a҃3-5LtfP3x8T2ȀY'̵'؂ ehb0ڑ-u bЖ2"R2gH1\;lc)o1d ol2R1xiKAB ŕPDbaS( * 7䎹A ty IX'ߒ +[2^Lv'@"x.:e$; zYQZA* +jGLU%=ɐpK* USTȽǤS=cj +SP ǔTWpf +yLݥ0ΏiVk dFK +m!RQdZKL (%rBKƤPn2P:TOp2E|R*S'ne r:AJ)ږћ028Me:qb{qTڈT#3S3%l^akK(f7S g +4뫄6nhJa<3%3O^a$3@@.pkv^mEs#hyѐ%1?i<6BKc=#ab1XM.:_ 7sUiԠ|0)GMR"̃jH. A5ާj4RVcC(Wcw5I!nx|,A0i3v}Mؘ2l[$s5xГ?6 $/~lΦ}ghc}P7m<aTA>4JMm ҃pcy:nV*~Nꦠ;pU;t7MxaT2oM%Co= +oT!voܕ0#,"KkGF؊v+08 )͓i Ji`H/jik@tݝd8lR=MRAASNpx{30pJ3X8TéQp-oHGq &-N[8nKitXis98DarHB9@) r^Ɯ@4!lKS@9VX?1`@A Cѱ(B:J/蛦cmڨs{w@ :=\0{AزR~vO휿3 p:PW,NwL/w/w½C*/v SF&xJ rxbK(n6L +$\>!IAEfҴI45h`R(sfRM +099T7)xsj-$gIY-ӶWR ፄ?>%N-` +:ʣ)FXSyHmh{l <(S zw5V' +F(,2:ivx+Z' +~O*DAd[֔ +9dch8 +D^mrlʤ~r6M] ZRLDdVwjPT,PnUɹnj`ȣ0>x'@㤾nq&& Ԓwn 9A[y 5)Oat""vI=dv-Np5큀5NN06ĘZvw (k I2_ˡQkm%,^,V^ffM1Pe[D$r&49p@ d\"U0P@ofH%$2rb.39){k'01c%ø{"@k`xᙔO E@o󧩎$B2@%W%R SP>8|oV dVr!83l4.!ȝJՄJ +cpI@c ;EN@lG<^ 駡,\[[n@H4^}uYb9ɳ,yL<ғň@O0";B@=\ ֹRIPgXbد)O8Ym`g&Z6v-Өvػ:"?}: L>Iy3u+ZE=A *<@n~Sxdyqf*O *9jpY'AWGl.l(~#oHrS0@; .jy2w뛪 @ y'F5 1E,;,:|ݛ=- ?gw `~;vfNvYI6OSԗuǀL Bh~6N)꺫c%f*Bn hbEp克ٍ^E?S4zCUPC4Z! +`b-1(+3rF@ ([k2T~@¬BapӀ7Zlb7J 0!WK_h9@R[5BaayuD c֐gp[p!yR غfrK<+󑢏Q)ܞ +Xyi %*B~%ocܑ,U 8TRx5PX@ !9dU ݄ddov?Tm@FT(?7v>KRT @WA`%`_m HXANhTֈ򴬉BqI?&GVaX,Jhܲ殨;@Yx~Bo ;ļ[El"tyg((x\k>t+;ƬAT8) 6v:bA0K= kϖxF)pkN*2Cj%]xTH7R }>`B |iF;4+Zaհ E\v?'ũÕb]EԵ&C-@+ 6\# 0Qқ68: ^/9ct<9",*v gLB7D!v^ >j?'ÂPXRk+o/J=8f7M6V? h&ӧ/ت$^GAeqN8•:"^8/& LAu) +?Qd%!llx*Qp-75eCЮ-%R ͠Q +#P]ֿ-%o{nX ].K>NSWIJ\%>Sd_?VЗ;S>]EP6ҲcYdH2BH{:Og½YȍU90dXz g7ܯρ*c| + 'R):@k}'wN#]w.Tfmq}ҭE;W,_W) 7a8˂P{,+P.2j` SԾrBdfQH!W p`wmO-0K~cSle?)}%ÿٷg3x\^@Ol_5we_HϪ_\C4g/<UJkRD +X%ڤ>Qw!؟}>3ϒUX$XW6mط tp~/+y[?) XK +1fF(1e Y_P+tI֬rMD!PMEESx\L՜z/GpcPU=uQ&|ؤv鯾2`Bg%#Qdy:?-g-U}>JJWx +υfNr&ݝ8g\>6۰lWCJ:WF&32Uu( P|b +/GSzΧLZF()/Τ,Qm'YۨMU.5t1?|H`wJŗMDBo+p}}S :aV^Roľ5#,tsqn7CT?g sD(tZća;#ag_k6݆M'6|/[X"ǣ/[:y< +~xkZ'R$#*_>ӊ]iD \O7(͋pZP-cJ-W^D5Ѱ^<~ޫӵI1b"VB4Qrӈ" >YK K=nev2HF}e)t{l`t>}|ZJ»AhKUӋ,!eȅNROxGםiNzO`%z=y]NU EDo?_|bG47zh˕yV䜓ruxZ`?"}WPdwwNWмP [y~ܷ3o *zϼ^"p,!ݦ +^,awҧy$)rcbh6= +jQȅ@zhhq,#K z;l5ZW_yBh@T4@J'<I~"$PvKY67Рu@?c<$ӝ~kIC̙[߼h^NT̷kp,@懏~l|t+{C/8H7Ɩ*ЖwXnT%|+6.G`Z;J7"'{DZ€^|3PnDU#9ʽ%ܾ<͸qڌK ?Ƒ*k6M9-cI[ܶ"]qD,+cf']N9>2!6e*D%LQDl(?.iPƇ`}ڈ&k4I2Qs{+~QT%k!v:[MLJou/#F.`$Apa;Z%8|Ob+E6`VuKG4nǞݝǸ Fe'}:Ʒj(kQAG ui#Bw*9:J$ubTE@x|$k;؄\5{@;s= +|adۇ$hwFd#0> I@Ape;ἷ N4=Մ +_BΜrtg}dV kBf(gvwWJ_ܝzj[($~KCJՂg%^(tDBACҧ^,JR+:᭻tw빽;vK hnƽ-6a{a>Ф8U'1K{HZ])D q̪\R(w6DgSwƤ3'P]E!2B՗|onӤÚ`uތzԣXE=?E  jˡ!@!z=ULӧiC(#|N_|=R)Yu˘krk(8pfADL n=?ָ']KzX)Ct_1Ў߷IWlˮ%]!f%80'% B(_/C nE٣˂^Bڣ!nA&rt'E`W0Cuڹxb56/%~A/4 CA%6I7\^D=} +H^(a)^~$G.li J\"j +п'>:As¦}C Zύ' zHJhg_yMB)*';ä_NoE ÚI&Fpƿe?96r^5x{I41NlrEP4|`auTf u )Z_}Va 6׿*fWsH}sV/ꑓ1'($"jg1>+9ZR^}@(y/i]9#s'"'(i!o,qrHOr Op2#ǐ`*tyzΏ[TSqG< TwtÔH;=šr!h K6X[p΍㧶E1jVZ Ӹޮ+3~7wh<-)*P#C 8 ~b6p?Ka^,IN"lʝA*8#0T`EoE% yi瀖DZ$Ѳ %,΅1 7쐇A!K{pq`6'dFcɒы3~A@\\rW9POu2xhkjX#N\AZyexF*ي8sljx +p)q(!s };?.ޕi~  K8 +-.ŶK0e~š* }okM+nS|w&~e >0v(.A SV'ݞT*?&nIed7̤4rm|čM"sFшO1A 'rԇ endstream endobj 21 0 obj <>stream + xxtħ;ps0!}%"~anߑV&yp6هc3%}ir1:1E|/~wCЬL`M x߲uL"ٷ¡oڹob >/+*zST'=⽘{+01ZpIl3ːroN2aj(. Y8M a}Cδ{Wxڜx{'ʥIk/7-~76Ls$DB$"*Nio-io.L?O{84M|s)eby FbڼA[n}ʽe),rn~-{@IrontBɽ$~rx'`pokD"YEiqr+i|ޛU.zo)wB޻g# PoY7i,ygz yC^{ӰϸޱxM7.ռ7yo2BE# ܛq"/;I"% +j3]0 +I!t`[%ےŹ,=?L +{&n{7ɞLQx{#zpoxEo2ýkTh~NBZ?Z$ IY|Gx +k(~1Y7"yzo[QF[{hsʕ{3|CqӀ,@< \1K&BolqB Z>Dy߾ڷY4dII* TNLHs 7 jw!P1 4bU]ywnJz3ZU@=69XMw~7l0R}Ȕ{C`99U4Bݺ4dQ=4|ee CuCh%GZ񋆺{^V[~Ąэao nM;KJȹ'L&gl1 @sKj4[6iWkd"ɝ>utuDn<rɗxOz*`w}3L۞vU+!aVÝأ]pvEN +ߎ aiou XztJ*䡫م-n5$I9]P ۼB綃H(k}ᨖ١:϶K58cͲme|=BC<yϡ),ę~Zd\;:G^\rjmh@Rʺ3laǨCDXs2|TPUk<|K7'(!a1j^Dj&+d_]xp[&uixVb5N ]5gWY{V4cz. UGRv¤8ٝNdQ_hl>n6?#sN+>9UB) dԇERfiE0uMQ]-#uCX,dG`lfԖ0V]_ ;Dž*s Qn0ԜK\}tPw WjfT8h> z"L>z˱[('ȭ +uzw!wN#)86r$̬\)BIe4'c7͂W31Z$~M dGO`O0M +Kh%QYfH]8BCbiE'le", $4R?GѾA"Z +|RZD5i.ۤIjȮLWAKo ̳< IZʩ#ǧⵑ.&PYhr_i!f'b lhA(;Z-d8z$ROl4",>CM C`h6{ l)Ѣ_Л\*,ԲThDÛif +9~$(@$Y#ՆodWfjpH&Gck*uVÜ\ַ[ )q;ehS]d.y!U4QB+Я;g[ +P u{dGuY.[K< Z^- w}'7ǕP 4RH~F7`atR6^B2~|?jƛGb8FZȡ@gNv +]ь =y#%v>gV@bWH;Rx Wu#,q<r+AG Gl 3PgYYr]og:e{>lX +JxfT {R KY蝏z }3QCVҸ띣{'q{Bw$ KG&,+2)9l(OZ 鸭Rqg|K F{\P^jYJ*>C;ЩRvS-;($-*qZ%;7'wss[#9/o+thƄ- &G1Y]l2y;%\`ܙ''V vơZog/2v^̒RG9}Rv=Bۙ, +?&f^($^Y2H糺GC'6`]3R`UNry@)Pd8SO)pf%WP-ޔ0ƸŽ@& +͖LsIdm7GhֻRyHxy.-2VuI!IOPm~&lf jB_&v/3k&HMLᦴ%qtn\#xuرo8Giq^x>9r,Y0' +aE:gNr-0QUc$Du?/C;B>OHQ6T8 +sn4^=Xy;Ogv\px% +KK޿}]%3e=X +bUϒ6r:i=VFj@nt|PWBӠTU/BU]'a(i쬉y}=TpF!AF4kؐ%Z*'sOxE׶b(k5M@z],є5̓[XjȥDTrш~2|Fӭe!5 iD5P}W1.,K?fUFv1XIUHiGgc;ٳ)Jiܖ8쌭ԥ@h}o<'P7L?TwfݥM;XGwZ󊋌 uc/sevژir+\m6P1ĦԔDǴT@5ZT2Wm]X~Jn|eGTFxt;SK~_;R STHVC'.qSm΀"%j1\Q2Q,'jt>IBU7rY*Ūf۰ +1oȹjuKyNBF5`_j8g:_ga=%#/8`E^vFXoɪ6K1k p\')E 7ַ;X՚3QV8>56n=r3ܳ;5X + FMsGB@QwkkEv](f++Rymױ*WZ+^٬4+վftJĴ龎 u T +(By$;KwC!zQ#vX7):@^{uqkν>Y$6$ \*f.>s17s_It+*N+ǿ-~jo݀8}]Bq(e56{-x t 4^Ϗ81?ּb9z3H" Ѓz\q^/#0(ۊW9Ðխurm{ + ygh3_x8>]aJǔW `_pރ_3rO\oDG{{jǷ@ a/NS$u^Z͐|z,ѢačK)ۆGX?2ӥo0^b'}x[V҇@pdhʾ<Ae`Ҳx$@Xr KǢ5.fɨ{ | qh\Lu\0I?:yvP\`2+iz YO5pgARt،(5 xhҀ Lр0'3H8#09s9&,4T2k' -Ȝ bxlLE&Q'`LlLP)P>eq={8"*؀ph,-s'@ "bt{9VL8= #F2`p Y3QLKGYpml{R(Yl7\J,hUF BA>2%7B2Y#Z5NAӗ=-X=ډ CG):T,9>aecDڂ,ҹ9E3X1[Q.C^jQ&؛,́&ݮ-/ȭtm(N_? +r>1>/`M?i6io7}|":=WCQ +kB$b㠾Gy9US_}M jR!:4ȶ/?nd3'<; XŴcW-?317I-@%df${:+D:A?#m@Dro, Ǘlf*H'߲<p"9JrDL[)+)jn[ۡ_;O̕a̐ɲ⭩~㖅p/Wd^/n.Qw}/cf#Zm̧A2Jٖ>LC h&Jr-+t{ l3r%XÏ|˸虦E:Ws^Uj `H<gicXAOplCH +3#;kޤXckFNSxH 0鬄 _rO=U?_5kP!HkHk^k DL!> 1Gs'ќV)QW>dW=4OGiW1{9 LzL?{pͥDAY*m4/gffm#s՚;ѢSQHb2$E3' hGJ"<ɨgE["wWyf}3oMtHY5gH0fmYgN>gיL =t qgFDȊE(1ɘ'32O #O !AOsr$Tc4shKsfCn4 2f~%4o{ÍE 4CSM{f[iF0%p,eXQf#fHy +|8-6sWzecsNA|3;+xgEz3^]b>|=_#CXT"ni}C]0-6 +]CtCf\]&].Ez'KY{'NKa|-iA +Ҵ4}N .1[+H-E-7PB=43m&3pi1Q4zJ;eN;>V@vP*dW8.ɾRjJ6/0K.zQ<_xf9m#ne_0[>xxVy%F٠)EهކQD˙Ir5Cd$@'3@i\I67 Y HHI6 պX$;M{_ +I!`*Ar@Ɠ.}.~UHr٘*. {do>ѝ:|Zmͺ*Jc `6&],Z ZR?ɧ. +Rƣ0$ѫfU[Z0+#'l},T*9*xGl|-1{X!qQ +5-v٠p)jBgB1K-w\Qjxl wTh>chcTɈh]S[Lؐ)nK-Xn90چݽeFc.}˿;gh؍lH 4l >i5bYMFFwbvҰsSTon [kHaE?9eǓB ԋ}Gb-†JG/E{/%FDB6r$0 H vqx(l7ڃ6anۇ$P֙= dN>^m؈{7b~iZzU>]h$UBTiA."Ⱦ\#ىMUH>-lJƒ/-;^bj-OÖ` 곍)C,ݸ/J]=;8Peڋw5X(SGL;an_qW@Vm۔Z{XJ\6&,@"mkn`g&zTl/T:_<0BK1FmQsY?9CUhɼ XVж#`G۱N" *UYm{4˖&5 dkOfP:m{sf*m+'θ-n_o'j\T9q!#¸GT!7^#*wvAe;%޷3A`,mF%өRNP/<Os+o;L8zo?7b&軷`)l- +eͿ}i8eqD{\\fo*5uđG_S|s@(rR(d㋗ƻ?ΗdiӎC¸bdkffi|`y_צ|ST~2lwDI|Ќ#+?^2G7.6=(3VBDѭv̊dy2[ +ute' sb逇rD6lѥtn p ?#A)_M+p`^y殺Zd*[='Ri +eHlp[=,׮ ?_% 9aH]OW#;xYvNN{P ~lrgbvKc{蛗,,ݞ_ޙ=FZឭ#v¨)zu'ݕsһ;^ňˁpcGP '{ҩ>ǝ ^Y4rO2;.;. |Q8jy + O[)$քălS10PXFK[XS{YFw\A;H`2'ObyewQ>.f~F/oc:&ϯ~m<ÏGE6>%@ґN Vi ZO+-fC>e,բRc'4py5@ziK zvtQ/Nj}+/R[9 aCo͇g4zw=뎽Y2ׇ)7[kGa g#@<1װ?GYIgw݅]8Y!##8ܷs/@ =4CN`#HA2.0$} 5v)6 n4ShW!濒A6y}m:3:ƭlCm<JԳ&6l^!8FPK8L[FlŒ4XMs0`|C1q|C\rB!J`dm԰3}zS'Mgw)UDF ?T)"MZ}e@ĸGgǼ0fuVflrP,D~}-#gky-‹{Mim_, W06mt Vk#&0fu`a`WY;9^8/3(%|}O^M6ԙ6zoM1(m?7Wxӹ0UP:PFjڀj_%ќF~ Ƽӥ{ W7.,Aù/t>"w +T, EPT&ΰ 5N d.7~mF 9<;}B`_4|i4h;uC6ga`]a/ +J|XGZE8RN铻=`lS&'4ygH['N­b=wF_۶LFԕell `ۼSh7_߼\]0jY4mϢ]M$I=Hr8󝳏.; +DJު":xR%؜sL_ \,z)ʴ6B|԰xlYI2e0;S(HɚNZLZ?E"@FF.$VD~OmihȻf׆-I +<\i:soD|!KȐoFx>u_[Csqly=Q7o5N \8o%veYp\K!GԈEEgO.Chg}Ƽ}}nZԳG<H1*#$K1syƯL6n4 ןFö69{eb:sSSpJ$v(; E4hsjs`Bgz#ĨL$Md`qY?p$< R%=;ˈ U-.r$Ԉ/$[8 C6g IBk K>g+}(1}=!L O7r=ZlL]/mzH'1ԕ\bLݾlNY)( [m.)h }YhSŀ1\}cD?)#:6)o0#qI;!Y(%5R+]~%?U G4ƽuqp$y0>v?)>w/3|hڜp[2HkԂrZˬ(|u$G"z Ž~Ju6}mPjm| [Y0RXfhλsoߦ&q'Ӱ_+}kaʴb=s*dēnPcg2 =_Tp!蠤p#ਤqO"O k;}~E/gwr[ ƻShWJ)VZ TFT^ EaYcȤ#ؠ88_73G#{x>ÿ׀dn=9@$-& uzh#av=w*N#i後0MqPV9e,O±>c6?(_Vؙ>`<)h䈬hh \4'¯#Ayhq+m~)v=*/mzP#Q;E ~ +@~'irSV1GS(Jx#U +@zj("?; 3z@wqܝiihZiohNou>iCP)A?!*hqp|!3&T.jhU:\9;'fnoLZ}U2pd ||V+3gDz6c^/ I[M78ݷ^çV]y.}4>HWh[ >zg[kD=&&r~662xc̜3m:PKmA GMoL_@oBnBErN!]u$KA;[X9WXIoW?ĴhaẠmn3У^Djرlj18 Ĩ8$_g*%% 3T`@y]LH nOHl ++;pO^-w$ƾ.WO`| ZDzDo"0=aÝ@xvS5N z)TD!Fvf_lLܝq8nLݘ,gA8z\W4yʼNd,}];ed3/|蜯A9߹ڦ}A7Õ8pfϭԡ2pd3MZmVZ !kD}yگ., u}@)#mrXh(mM/׶Qٷt K>}&]kV#SNL_@d}JE$v2%6m]lحxH 5msyaGdDs޺bPt t!*'MÛ϶s!#Q#IAH6l#dٵ: %N_)? ٵ _V 9<` o]sizW%MݭJhKN;IA3whsYf$TVm,nFݪ"'l)$6.靮RPFeQٙ> 86i7n m?FC#ԍ4~j/_n쵭4i 6l-Üy1> V,Ζm4ύ&M>i{l_öi:"]Z^5]6il=˽:cJ!>ԨqrtO!^}4}|Ob7@J}:d^icyj$̮ G{,|'7pf q!mjcH2}~CYLʈJimcRgBEdBMB|'Lgx!J/l=(jnSiغ͟[un\?|?Bܻql@{rod*ar$1>s_g9?c6ء@yŽnCL,0vKU!a'ZgK#]\P +I@e#A[KWቧlI'5)|+]zݷc5}j&tC9_cƴ2xerVF}+#srMwɻ嘺}5K=w ׭CЩ2oeL|uw |Ϣ]HǮ`gD 0;fW7[ ֱW;+s7F3|d3L C6iÀ~O]>w}H/M|utF] $|#_1Y'Wm4}l[M6eeд;vX+qr?ᜟCex'Ӱ:]kjg|zE} ;['H,@ (Π$ %c꽁w4N 9F$~(SOg-%̯=UbShjut|= yb QC|8%/ӕ9qǰ EB;:?$W&O4 + +T,z(Sg>w6pC\#(qh(=5FVl&Ϯ eJE~c twtM #kj#MTMawBSxD~?k ׭Hv M6k1_AB}_%Fd5$n I;^Shut=g0M~(CJ==v}m G=7:ƭlywsRG_I}ꙻtwD=eB?J/e0FodĂ)s3q~'40^Z=u^p}"I@Ih?@} #KA{ k#Y +A{hNPҰ}Dx)>;(&쳋m#J[Koza-0!H>[Kur6x&H6R'D|v堭ٵ"oFcxGDgpl>8{ȑE2<5/3WFǤLYu9^8MW5+0WNޱQG7n}S+ ?u4y&Lk?{Xe~C:|o<~oz6[ݳM_S4~f]o+qݼ_[ SFcau5yj~=ō1l,CW&|:PcI7p5\}(G"qO]9A|>葯y5.Ogjx;١JQz*_KuuSxT R'v&Mm49DJ:ʮ Eg F?<%cH{x#e~'O;JK"GytO"'䳇$Zwvplûogj8w3yvv +F;^Kn<6mi6)s E6|np)LI]g G/jh'@h=M[}ݷk8~ot9h/a~m@Mژ8[#qk6ܿ2`@x'8^7Ԩusa:s MD<3|ds-m9qG4iZ082L\VCm| Z;kvkgf>:fk6>qu2se4dž`j8LZ]uqP$2pduv} Žå:]~{yHRM%NW9߹g;t}HUQ:=F :J]í8r?iS>p*mJ\I4TwS$?Ti$Q;4C"zί=~CXurk F{)?yh2'm +J #(Bۨ9q~{}a:9cX{loMsij.7 J v7 Û)F~cb컙2 H*J_F@x#Sh} ~30R EOq:Lw։C|Mߛg1C|v̍5;Cgksnߦפֿ0fZ0lX- 8ܷo#soOuٛZ7nֳ0i^ fAdZcG5hvgj˷rٜKoL+k/D\[*Ў*EL]k y:g0Y V8&"IP)<{.[}"s4wl4 r䳙>we17jQJۢH@[gЮ8?#wFǴ1l[yM+edR컉oE; M9m~MSgx{ ~$6zpOԭ=~8x[͐Z8Ķ}\iϦkoz-w'eD~Pޝt9h;zNA[(_ݶڭu"Iߴ"I}nܝuih^ۼ4j3 6^]jN8=r1Ê`4p/+L񮾺Y꺾m1n[-/Qӂ]Ǽ:^9[K{ +l((&P]4s7pG0|lO`ţ}ɵm< ?=w_lFv&vn,m&MdlCxgx|^[]VYr;fw[jur6M B5kuql.b]cb^2|dpV,{u` Lziqqr ]]vuŶ8Mu~_w?Tuv،&PMK#TiiY6-.Ё{0j`"`ľ`dq]îkt ZVE"6pqNVӄ22NV$N `9IrkuH|hYceŔܓC5G&f s6"I \aBBCF K+,8EjK>$ Ieںix򒰈(:]BjX +1C"㲰ǩe샄8ccUd ~(˖i˘8XqaƬpn!frPE|o;|HƈC9F'(ކ $kF\x. ^D+"|JJ ~hO@C܋$uI$.4_b[0Pf1!@i3 g#DMULLB#AhLrGTq+dthsh8 +c$jtaWCJoĥlGp~ăOJ?R0!ph_#(D܉q$ĕ8oD26!"I:e}RRLA!ǥ%zYhKd%RMN4ULa2:u +'bFVLX0{d94eY5M'}1.=Ltj"L,}bdERiҽPF$YnQM(EN=XZ*\M1V!6Z~-ZQDpH@.L@/L@@n Ks]챖c+"vIdS ERS-'*V/A0O_W +~ysh2Z*ڗV11q .g(=&QfR @HYC -f*uΉY3ZbE)#*w$-F3HZV7P'vN0-ZZpf&"iԬL29 Yظpkk f "ɾ'@*!Tb ɾ'=$8d+by1]\Q+=!nģI"ES@s\[U+bL/3 ++nG$??Y<-^bT,yb + +6;!rd4Ҙ)ī)ihdqH㪕m#vߓ! ;n +D֐obA2)QqRC+8UHTP +&1A)ĄdSIӑ̩J۷9 $SˤEH'+p!ܱRBABaˌC,'ٮߤb RDJG ,QUaAqMakYS \J ^RuP~J!T6^Xj60?^q6%o/Q.IjH1!dd}PrH=1X0Ɋ˰(~'m–Y@4E [&:i\B(х,2Iqn /W!gP@VJZd $.E*xB-^hI#ؒL*Wa+u˭ge ++6B0ToQgHQgbƎgd DrƸˏe,s wrpe "~HL%YS$o I#=&܃*dG bJC$N-jyf9 +f)m: KZUFav[k +Z:PKFK!Z 0 2 +a|CDmX@zQDkܧj+i8+~/E(|n]۞԰Ը˼Pu!Bh0af:L +6) YlL˕XK4Q-EܸݜܰͮլvPvtL~|:&8!G$Dn?$@;)B~\غj? +BemcQ_ZkZrx(2"=ܸ3x5,M}QaRYaB3RhCi|y +[aMG#sT)n^0/5"'xE,UD؎Cl"6kɦv42"At!\\FiYHg[L(^J(n%6l@";>}uKLOP3%S%,e\#C +' b@p{7dqV\  R2zL U9+#=dGa5&iӶ8x2`ƭ'_l!] Y(Nj4Voe\b*,l[QX^Զ$5^#!".KˍyCRq1SNt`b.R×AiaSRxVHbXPu흐dkGbl VNe/)u¢m*0:mEݧ(-LA|IZTeU + C܉Sn:,Ez>1ti1!2B^N;`G6G?R\b-5j7,;|~ۅM *qOnnLn|2V66J +ڃҺKJi2JwbJoKCLtƚ,NZK,o9ٖfxj@JXuBbaWEْ;oω-omI6q+dNldMؙ&YhA*KuK`xwd3ۘ+}a(@*ւX.ڭR .*JdOWpW;({#41`Eb'X]YNW:i',%TN-.XH><ƸP42ygb1qf S>;fp]DŅ 1?vXnLV;({VZDjE BL/H@$vU`C&C;: ."" - +ڎ°N^yfW^|6-9mgyAmѷ]d`Epb%, U×Y ZNe UFe"2C!)UtGLl%ۯ'JqR;\13P\tD[XH +LBdH`;!7ЖVGѳXV4]̋YT`^Vu=eER)3\)Rp9w:TH|)7ZߌJ}.D FD!J)=a|a,G&}uòANc@wdGNB2߀0MLZM R>k4"g4&i +G6k&7Wt{dX[8'6lK {Am Wlp\z:-GԈUgc#Y Ѫ).VǬ-@ -טEXU0/ +&UBz K}R,!4,?VH&M5CK rIcK/F3Ig +(ݠ??Iw@)DcZAi DퟴҢ^kaYcYjH'H^2zҢJkR:g":gќ% ɤ' +('(+(-85!z0::kR*c ИJ*H@WahYȒJsQ91d@v-#sj|UTe:ZH'malaa +heҒZڹf|ll@ L8 +J<*uV2N~ @4?vUL62jMT5=A +F &OF}Q=d)m+1j9(:&95Vv tpu*ݻ 1)c* -Hd?@B*F|iOg2O&RNࢱ6`ܝJ>xO b8z">Hޯ8`;)C}-QH9`-Hv#OZȒcZX?d!lpFm#uri"=HD EɾNZl8VC*+{D+HLnCS+ʩJ)?19WhZ?[UDg+R+ R,(UĿ NPG&v+$؜\TY=2istV9ɺ‘ +I9g h4a +AdYu#3x؏4;d'1qd٫0"4R|j<5oMi昹 _VfmLKV4uo[C zM3m԰+mz$ߤ`TO6~gJ|vn;O-,UKzu6^OL z0f`yī*: ȮsT`㒞2XE#OPN*^HedsH4\g7DA9D)t`Ma'@xW=.g+dBؓ2V:5$2'U IuzhUG@!Iţ[8I%9s5УRq1]URk KFM䷚!t o/TDH@"#!_ON =a**l`T("Tp ߠEg K EcgG(Ju!T>ȦVBفGq9cJgМJ0>_D:*?ʎ (ͥ2JGqI+`X( H]ε]"fdmdiD`l9P~DK&~"F@[GV7$Q>uvRBZpҹґI/D= \4Y +>y߈RЖREfD~(Pe޿d7n\g=m#$)=yHׇ*S^b/hH Ay%Joo~M[MV9r\ cւ8XWES^8!@ؕ6~|W} n@ j<[ZF`ђĸr(z)E6}n=wzH F4Hÿɓ&4\WFk+ RiV + +f(ZK6g/(g$k L:-P%} h㲮!J &Pw +@yУ U%𸬱b\)RlK"SA~]CZHG@KMz$=HvkS*CAIWH*cPJg(JoX x +@:C[;i3ŢmUc308 $ '(V+@+4\ 7`7M[36|<aT%u L>g6*kiV^GQI'h 9;u~FPw5I3(n\vG@=HauS&^D`Fd7ih+i~=mj)ԻAn`~)UV|:Ti"FP-gV[ưm.6wR2scgj]gC18o5p+av/&;g|>7:+GM}>'lw?7B ODVPNA០S":we1PES&T6(NaU25B{W?Ǵ4yj&oӍ1iz#G.j .[(Q@hYxO& R(zDK:ؗޝE L8k-" kǦ,UB A&T0- J) F>9?P6c6>x{C.=tـ@ij)Z<4ArLfgcy\WK@pZh"X8]i2#AK-N"#*zip $4ۣĠo)2jm)݃U9sNBCAIoBJ[ P k)Bk !˩ˉFdjHIܞC('m|,&5}= Wm4lYnA5jsM7c1<7C~GܺLACG:(.&g IIގiUU`FdF弔9t'-T*(k=o6ѧQ_ӶYv6 SFc-CXd񯭭L>#ObQkrT{ T'Pe!,Ć0 +E/' +VHF*bIj KƗ\d0ڒŲKJ-(!J)%ΰ$dT68eOa %Mau60Woll"ʽ-}F`cgЮo[n49ű!@8p-W 2}dbH9I(6ªZ15-ԉZCY ^PUBZ ]T@*j}(E-QAMP&MdjŴٚsGnl'.<X[0*^*֓Nzn qq3bhG3~k TF+Z,& : t0i5Exe2zNy5Q|eȰW6,nQ@7$P*eQAiQ!_bB8?0Рذ`Q)+pH#i5:๺h.jH !{}11S`.y"  +RT颗:MS&e`b|ԡI]j}H"h1W̳^"x + +\ϪҢ tD2|fa0hڮkD k*aET,khUGGȢMŶtf2G_BqR9s%*{H U2Urw_ˤTFuUXIPtNv"љhҁyMe2|=뙹~yv?;W,@}ژ0u.ź.\+΁*De_4(6!(A6,Q2TEZC0Q4R]GH +XbR٨V` Ղm)Qgj`UL^VJZCi +E>.~4eBqN:a; '#PX{yQ xx3i7x+[`:p v. Y9M +J:公‚rZŔJT-5&2&rs`ݳhGf QL*VH6J^#MHP: ˞DI} +ro_m[s̑# , T0Я`E]˶Zue+0A;P\1i0hXÄ-`%k6heh C:b,fH@ţ #$zX'hHg-P&UBCSo%$m_@Ԃ̸74!"O#c)= iȱoV4Ů')'dً2sgƯ@z6ޜCje؜.È's/>usi 2ugb4nY6,CtJE xUĀe=@pvH{ zpuȘ[7R%T/SGSEPИ;6兼FeG'ۂc@oúfBBLl/٪Z!7EJ^:D|#sЊ*oA1)' Ѭ;t)YUtTBkMnGZ9 N6gQ/dX/?l&`m \70R/gοy&/-nsXv30d"51{!bX!b\x&,:(o^%젔j0(*l)/~|îp_9CTlL mcRFIayqPڙ8`=aPnka<}\v0dZr0/„  C<°#y `1ʷt $XS +ŰOAfWpEdQ!{@Ѭ"b*'H3(r w1BG[Qo+CgV_, Y-3ֿ.TϢ̵&`h [W9LL;x_R4.|>utoP+/q/o+ƕ$V :ˉ'V+11 c_ZPR +`uS Hm(0&aT(jB3R'lDD:-*jwjuA{r6Z&L9݀j֮!QQbj_JwXp(!]Y,˿@p 99Xd 2x/!^\>za8 3g!@0FBIWʗ٘ʗ>gGO,C9/A J]S3 A` +̠Y pa=p3 >#@H!/7o\2E!crUlR(v &nhi*# jА+,5Xh&d`$g] +Ezţ|)+qiYWxQH%|=ų:p "bN-c7] + +hLjw +3zlbBܰq z@ЀzØ˧Gw=O9D&; qó G7; r*(4<%;"c:})q{:/~'DOOiQor*_F9[B࡙ꑙM$e[y"B.bÇF9Z Db6Az(cvU0+&`P(*ÖDŞT#ňL_8xN;Hi0nx c*:-܂4e[8H| ][ o._X_Fd4b ^l{MvA%uƮM;w<R8\H!vFg[b %,u*)1 +jZ4j`"YlbdۦX!fUòF:DSé3>hyRgPgsOBTŸ-$$@Kfq "wN*zB.zBS CЌ/W 5#޶fR*ȤI!]"ak| +'tڗsVdrLp*۱yXԝՄ( dKT z3f-=xslBvk[Дy)AU'AMHOY +Fc@K~t̮drdX113bP / c,!Klc ,8Ԝ +x">ovd:x^L0fhX)#MŅcbc[d̏-uªf]@ &W{$S岂%U#S4ZypyH0UN,dl͵&^[^DEﶮ`(Ll/@j{94~{\(]z,j7-:@O1XX]N60Brq+kFJ<)Ƈ'n']>9-/ٽ%={Ptl QSxI/zOX/n+sWX6(sO1Z1.,JCbIѠ `Ek,8%^ 8#`_/̗/jF?li!6Gū ~T@q/ +̄ +$0cc.!mxe#scp fkqH_@z!؆Y;f*3<+2$Z)7zk_Y%4gʹ/ T F `]c ! Sɻa+\E ⥆eYֺ8G8ql~0lܤ&c1K\{)xWDH/pqf +Ux̱HkYvñ:BYsˮ<)rA^|%+h2rl|ŤB1 #B`dZi8" +"F5Eal㫏hNDE1_tō3CԸ)cV_A!ux Ia8yfNic^^x/^tϤT +rPd5|ksu"l]ƾ2a@@Th/ں1l٘ø1 Yc8KdB_~feq%?1DppEٚ0f`J X!1$h(Nࡲ(a&G\G:Y*)U}8 @xu:`4BlL3oh5噂(<V6KLyvBadHt$`ڸHk#ͣ8/%XDP/#l@1X SB xD8 ;.@c~PjxQY<.!c%%q d#đjW,'O_>7`> GLK +D{`0/q`9ìJdyy-c"`aUV^ v1>X} +(= 4AE@rxq $ `T?x`e,SS>[-m x!upY8ق'ub Gi3| nS"c{oq0oTe3|,D|VS@"æX-C,iY@z_ +%ø + J +xgkaD֊3~1mX?M)5Fjdkj|XϒǬowePn4 aSEg0*+̞ǀ" MYKF5hI$]KTqKJ_~⏧Ўxy3`@lk̄C#ldij`E<e`p055iLI 26"= N3@hq%!4#yrrM]yeX.EV2Z +R֩*S1f*W0QMh]+䢥|iWـae iCI15ج&݀;~5v[R?x4'K@Rx$N-q M86A?ˊ}p(A)3!L1?)&) +˜H1B)T=b]X^ꘁp HJJ0"caCRF+0eLi)B6_),q0J‘=lƫYJ㬊 8gO'N /#tı8"@g FntMW #ėbx5#+Ă( c&& jrW:M2et P-)J,>d~y( (ME&kkcB4L]d͊+v%q p'R$+ +@G\kS;CPWsģr @|\yL >Ձ{\.0N.%Lh.)xK&H 9rt d3\KFW@9Ks0µÄ[cb|@B\ECɈRF|6Ŀ$feYr*_0J~7~ \!ߴ +sarpqׇ KB)ĄBF1 |B2/ p=dX&Tihk`#NA +\ҋ8!ΕTàx;Ĺ#nEĭx$n`pSk͖[)ąC.5D\ra BÇfGM.#_F4=h~w< É`zR79BmQv`+\!O, OA)8%aTKS.$5rLyoKĐGj!y4YNb;r;[+,UTaI:ҪRBJ L,+*5 UTδ \eiiUE*-BVYZ+XTjTea9YAhP'✪$`e9U=кrڡ!--K-* +BUhZTZVhVTZjXeTXgiUV԰22{e26:8NV@l͝X=:KVff& *eVTehfWTWUVU L9YAhnkA)' +N ƬM9MpB!vcwWPq@㊊;x `W7,(4{h3ڿ^j3tkF HFiMP%_F`|Thb7L=F&Mg'mr6 dI:`'Ro*$5HuZ?y F,R#?w)0 ՊhR#ظ>?|Lc[`3X +ؤ%ЬȨ +#ب[4v(}{_gG1/ ˺*$&f*F1%mJ""?OTם@Ee lN.b޷у:9$ +&B}D>iQFJF_ ;tC7~r}{'L(zϰ2mf4b6CF'm + N4e/WQBԸy?N'wt~_pK6&PR/sqgHZݨQ/&f-V;0e ى'azg] +>QIgؔJÞMq`4gt]!|U/I؝B /Hn ;Oӧ&ڙ3 +?QIK)?pQY3m,tI6x0Sk!8?@ B ~h_MP6IEtRF T0 +EBq]H',aG@N0h5c{xpS&kP.?p"_}Y4zdXW84g)UD'Od)G6UGcN)o`5#а $L'S&{J6TDnagE׍̉NP_SJ M;xzkɨPf$G$ 5 [ +#(qh;z%N"8H s[ݐV5; 86Q +ogh[l,=e/`X;g<5/!ww_ h4pZF0kB LFew?5oYcZx"^ ĸH6bޗ#n,ߟC;xN~ZhG"^@, 砽ɽd@-'#ؑӭgt3^QUrt`%ٜt`V?e*'9ɉ!uX]ЖJ5J=Ȟ@1 E-s͚jdG8ge~&`FfM"?~po$66j?4-۵xj+`Hz%o8)s[jeƺ$v ef0zQߝb )\cgOC}waTBǤR JCe1YC*˯70ZX@ A0k* Pd޷ L4|hW_K|N >xT m5B9ؗ>>Ж"q4o@ӕ3zLߴb],cwDaFD6B{7Nߛsxg|H@mg^J'lz-spX<8 % ʈ>+)a9x3qjQƢ$>=}GZj̅$o~)UEMogG&~ 90ՌJ; +n +O IoEIKqY'8ɽyHthW1, ETE PvT(##_4O#$R haO`@$TAJ~2*ڱdUPEGp|spuo _j鋳5vkɨ ieS9g(?ɚ +E7>`=4T)VK)4uk5 D}(C"z)C{ +G?UbAuo2&Ռ.#S(f# qh7 ǘ2 Mĸ, rLHa?zt&`m@5ܝ> ytLΗ2yc򕭇ebny3o#V]`2j/Hُ(o)UDo xԡoP ~,=&hrОJ]&횽lZ^\+J_ ~)e䫛S2Oc=c6j!?5fkh?1geM^M 1p[9fLIj#𰜏2M[]זӍ:= \/p8gV_پmc5Oٵ*[ýR>PJ,)Rg/򕭖c1f$BB '{*5Ai_/@D)KhBYH6\VJ(/!AP>ۭ$jX vו:]ġOpB_帤<x\W4."=, U$WɀN-Q%w%-pv#{GEF0z3sh5 {;6>1B=;1S F-#wFNkaj:k.ofpPvZJ[rɾEc2qS' ?dIxǬmi +"xY᜷1YW퐬0 ^FqM`"LFl!eLU M q9_>iAR(.#1+ q8A筥C ԘgvCD{c<3/wIG#Rf$86$ xgumM<[lzB>(2D%^CНoCe{})k#UrkYS5yi\m7U2r}0v~ +^`?zBlVyCRQZO'w/ev} +~ON&Y?Y}@"ZO#}<4iUͦch62jbk2zgJ QV&/ [W_帤pԛN5ԉ'k&vGVw+Ird'U eR깒|~+}G]JUT0aQv)Òۀ L7ܵB (=y$1>pZukq5Pm +98g!ʽDe8}s~ B9mc2 hI3pӱ0(#ҾA(Ұٵ2y92--E!l-)ԩMB}7WlQo |MnHZ`Psf>{ݧQ +z(D-Wi~oo6kgҴ2zgY0PmWzc~ID*gx왻~ؖDI:OcݜCHGx~q\x E>Ah-9srtOP(zMoؐ7|)e[qٰq:TNbRX3HK0~LxQ' +}ҧ9RYCКK iݕ qƳgk,&jVgwu E JX%)Ted H >t1Knh2o?VcyjJ}80lZ83ܬH'HFtv[0)#)iۣR SDeJ* +Oa%½ Nb_l\H>?u,, uDriJ]Giss5 <`p ^@aLJtMH ?4.$&Ja 51oZ(rχ-Ae()UlPžIXFНM޻NARE;?S6pjT@yk^0csvlJKݭgwd986#֯l>{u}:"k<^>XV(ހ 켥 %S'}o^_w&ί7n%C!/fƼg؞Ky I3<3@L =NY8 8 +8 [0e5H'Q9rZ\BN9b5;w&E{uA-<&<\!zاN0UOAHh GL +Og핤c)zU>=ZžD꥟R]LZÒFeow!Ǿ +!!XCoSB}(AISVW>.iUNk Q@k5M|B{=kuWx9SpCb>\qo5a[ E°kٜXI][Pk +L> T!N;hiyhWPgT[`gV0?Ìd0$t#q/X1`F ӕbDz 9< +=8;7|t]'pc2rgg-ŰmkV+3WB{=u}

a +AmQ'-"ZA/&$>UUrgBM#C񼑤 i_mlصmqԣL$@{s \YXTZJ*o;=4m!Lӧ&_؍M)|y;p I\8k~fA|I; *k=*`؅(>Ҧ`eTvdV=*5 HOC!;(aKNGF(xġB|>I}:M[q60j4Έr+i;P%BvOcHG1tdX;)4L&Ø09,b]})(<1(B;:&nL;ri%ٜ&([$ŷN8SĠ7 'D ?QhgpܿY7?\[m6UT(m.NЙ@xR̈6Ѯ yy3ς]ƴA|9].6y<$X'izNخ0p KS搅tQī96, l XmF@;SИǤ^VHMaۧ03`Vgbb9+qv Ǝ#-gڜ;l'Nm#aʴam_oźx؇ Cwggа\..Q!̙6M&yG;Z [Q1ncژ22Zѯ3([fsQx<MGQI{`=GLհ3vA N +e`$bVEg(S^D9us]fL{}51D `7V6Wm9^:h"=b]=Sg6sk^5j(ՍL Cƍ(Ge`Sah앭}0!̽Z‘NSiy829L󵛣`ZNpT;t}KI_p2-I 9Fӭ%A E?W F{z$WNhZA: [Ne-&TD4w-׊15Jhq9s W.' ;YL+#gNP0op2L-$W?AIOhLBzBaVX/*94{ȘoCZmTK">^X'/zߍeru-([@%I +T I)i2Qz +uKzPm(=6 \Oٔ^vr-9mJXDk[)sH߷ua<iQti}:|g:,װa^'kyW[;Css1|=v{Ef)(&<{0ϒopQGnoYGv[gLk5f\ca.6j[-Ł9f L7x*cm0 x\e=?4qg,h=<)\R*FՕ +k ?y h>'w8}bcq4&gcaԛŵd7't\g?@ԺYBj _rs~tɏϪ:?+i(\?wjY`uXy|}~{xvPt?k#OFX~zwGu?0?k֜mGo1bͪ8bﴔcaC(wUg)+R킫`YQ/صMkDì2 p[b__+G^v`?k?7g-C@;r@{^s!gp?\ްDɿNGb5^/WW֓vBg=0BK27*NyUK\6/@q¾}xp7g9?+:]6fKR3p*QZ 8I-L=u|Y/-?_h۔{ UaV9S Q64].,݋un7ʞ,>n%Oӷ|E/EA?vpy>R{?;3/~o ޻Z8-H_^=\H3w~KCPg3UdIktd7jzВt:] Kb!D/D5k<8y bשhx5zc9>'|qX>Qӽ%"Y8Wu"ʸ0HVW^1ݿY6,O BE׮'4y$?fELҷ _Q~mf֟Z@La;Ov\#:Z}"OUz\UZ&sR1'mx苢l"8sPLO]>}?J4@$d*5']Yl}{p,iagXSH}Mz0K"pc]˦L~ygSJoOnaǥdSXŔO~樃Ϸf^WN@~} >{ye1~/~8#Eζ\GHUZB|pgg8"gXٵl(=pvKk}-_ŧn_([jocIJ0|vnB(:FWsS\-l1~:~| Ӥ;#}.[ހռNJNE6P8X[Et`l?/7f/aM@53$F(l:J@)1Eyk6I蟘3wnօsyud]Sɫ?H}NA7G <u!P"B}Q)afwNI59:f٘_v7|pJa<خ8{ IނVqth͆s`ط*S:wגJ#k~Sí-όţ\?mWU%׏v^٣t#qg%Z%'l%yHn4C%SW+3>En;EN6bg%ϟOI!G_KE^qd㻳w/\zCeQ7@EY_& i-KS #!! ^Q7@ QͦɴED"f@;57P=`@Xu誄Ȍ!@@_ZX~AĨ"(dD(k׊+ӀYLHeebn>_J|VvF+rTτ͆κOx;uFFoퟓܩeޣ(-FpW(p]Q[ x zuDnYQs$.6KzfP8JF57O@H㛔*A x!3$)PzpőUGoج/v )Q5sd1gUIuN A0hϕЅES˗c6|86>`z\k1K߿/ʹpcY:ê3v'1Wk^"MmU[V)eI"%=ʍ)Ecꨃ:ITgUi6 X18Ýtͮ+҈I["q|[auh-#R+] a]&^7₊",Lz/oEY>u£37Ʊ6 ɥGwuXAzJ!5 qe~ hxV#b2\$N@tH(~ИXG;09sn#OaA5>%[gQ{-WvLEeE Zބw8`x(wt + 976416f62-1aef-47d1-a288-c7f430b64-6700-4412-8486-7f9327eff5b580 688.25238b9870c91-374b-4d2f-9bc0-9dce5bcc061205cf2a05-4c5b-459a-af75-c8cf6b25.46612553.37133 K)"<& \y#N,Togl \ c+{jJ+j4k7#so'_PY# +~L I *o0:6܆5*^o*e⁅Ĉtp' /Ed DCޭ+ ~x471 0 0%Ko[m+w׈hh[u#W())Izw&v$Q#hEթN}9Ѩx0|t:epO7xL6)BE:wB݇N*{@QLDv&\IE乍 IQ&@׹T9N%Hx N)G؛B 뀦CUqART&8aNH&P)Dn4*\I6*DŌ(偸Ϥ:vl4 +T + +5|DeR!^ԈP͏ +5JPeALZ DNq&Ed>}HD!HP݉,^5|r֔WUFϱǣ(UǎUHSNNGtջ%rV+L՜vnR$ݟ/&;(!lZR# ]MTXX2!^Ω +B" }( 1#P gB >8 I6ʄڱƄ@%tJ./<{ȽNmJu^95vnMoEujDi ESETk)W6]TXTHe$%T).(0 9H<:Yҷ_.t%ecRO,2our8ܓC"d|glt0{},,,,,,,,,,,̒",/5܉A[r[ Yթ\s?٫{\hL%Gje0t^G" ž:I0`$V]bg|KCloY0dg6 ??c,W3Gj;ǎK32+SU JS P8 &dsY0cP @ 0AGa,}p=e2m߈LJSb|W3;H5m0D86XƁ`z:Ue8D>X ͎T3 5bA}P~eij/Z]ч[^>cӬ@pO&ngІ&R@9Db%JC( HswقƦ7OVR͋=)Q|0ݕ,\g j;3;!b#3zJ oO-2)+bd97k)A{92)O@)}w| Z[3';I dp avؾ}PHMZ`? Aixm+)ROr(5>N5սY|Q/QAh\=THd!3ne:Uڤ $SCᇟ6ᕧEL+=O m*kJr(7 x +ˈe<(-/˧EXW8SfwHӿUvzQ>j9f^-+%_Ʀ)WlIĤ& NA}-221V VfviQ$ZE_T"eE6MZs˂h';;MSȜ +9#Ώ{֕6cYY#XQ\̥cF2T7#%ZB+Ҁ8dyGu),.SNAP37 |+gW>ٶ" ^6Š&?.R9l(&шd}rcN+>puKB}m`BqvS٘Xz [G,Cl߮Q0d"4vMR^>al v N,EPk7q۔KN3C)ֈ)YW"‘ׇ^V#?1?Bsѓm++J#S% Rf6`b:;$(,qƑ +l[Cg&8rU{$IP)@id ،GQ_فPeKUY$uNDv˸مI HٳI}q3F [hhVZ!ycn恜 D).4* ڙ[&)K8e@ne u<1T7!3̈́!f68#CSj5uiX96X{Uk>$k :# +rx(Ye82&D(ږr}1!IZiO-_"|x0 1^ 89Ul}pt30y M@^T 0&+ q9d\0FD\{Y㆙2d4xɃlcsc9Pxħ& Icc9#Yl7(B2@5|N6Q2ʪod +_%"n]R ÈJDdopITp{l5 2=兯Xp4P?m\W7w[ERCt'C|F?BS飴prƴ_ĎQЮVeeL!%@KHyْ*]"]xT3TrB-2sZ wEsҠ39L_,g1V/XZ U}3ڽ5 O 6.I + ϲKkF%7г Շ(D9pMEWVv~XXE+7p"-G"\I̭Gy'`.. r"knâKB`HůSXi7#D,}ЗΠiOOhBH<1! 1f(^}pG6MJ Ǧik`׮Yv5XZ]b"*`@zJ);MZ.I{N*҉H=@)sHnAEjEQ})B^Om\ͧL5{JZlc%S+ǐ +@5F]n1- Xlc%B +/څ;x)ZKe +`6mP/xWqf\$C w5>Z;0Q(&(L)Bzk"Zln.M/]vF$q4bjݿU9itk]ifm +E9`qADX_²ԙ,ZQߢ<9~ü +6UeF`Cd~Dm)dMГ%C ^*XzRbPz8:,WZrhsPH*\_85->jSO^(ңYR +ǏK'ayƆ3E݇(4簷N3rEj8dWC@R +L .3:'H靗8emi̡@ǵ딚mqh,ܔDt/zTi''#ql`|?39ywXJ!:@'l-X\ }s]2ɋ*Bq5 ZќƎ3c"xo *2TQ6SwliJ<)3H1)l4bxM8^hK7%MG^[ֿ2 E5"r:&x{xj-YIk[U^d] nFlh*:rͰ|:7!=2ї# .fJ5%_JPק˕HĬX @K^U!aɦ-Ǻ<AY= ?0,th^piq8x|RpVz(N\){BaUw^K(/`/k8^{6PƵ1H/\WM6+;ISZPf ў[XŠ. >E p}đ0-PoŒLu*\S{ƫ2)B`l#(QCT\~lmD2er%2,n9D 3iX H2qD|UT֗Փߣ8ߑ̶HL/|E@Xq +}AXg~K,̀y Y~ +βخq5&+:0@lVxpӤa ,?I2: !]7Z544i4RfÐ/?Ŋ@R6DlEɳL#~Tzg ާQ)glt`ԱbM먪T2&.ӹ.b򐫆^S[ ʐѣ⬛LGΩd]+9` +n77i0D71cc`HXI;+I}،ϲ2!V* : +e-Q)TEhXy +tZf hjL-o<7fwݙ,Zz0L[TMElQ?.no%& 6 BGZ`ACHc;%s G_'r^rrf,^Tœ z)rE~qf+Og56EL6ְR𑈴h-#c@XY2]@W6 G"0*/EErC2NA" Ǝ_'q(t"u5 + S'5]:%7 :t! ,H=fe+ѹؘ Lf0*Xՠ*k8N$n(Sym!q |a`p a,֓vÅ1jYQ7tc0C-ݲ!xWpea'n"&V"󌰍pLÿ7id:K_ gŸF#=ʆx# 8eנF נgA.Vݨqp}H4seZ2§6OM+Z>6erPP&Ko`CKnH:c+z8Dzs#*ΒEfyP끼dwz[h @0GUz^WUzP-ww.1=|3v 1 9!hş + + ;WibQίD}[W-vۮ:` ;[ЈiC)AKI&K`]2B[BEU5\a|ql޾js^/k͹fnlDKu~\Q3g%+XqU~/|fZOn{iu4Raf֓VhY%}#2gj$Y蚉%: @5՚^mMw|V/cww7ۻqZdVc+$˻zqVluYlu[뾽޸Uk^]98f\;ۨ>lw{cm۽jގҽƪG5W;Wbܫbjw*sy{Ϲssy]_v8׎)wlV[~K5[~:ƹ]ӭ?D\-pVqj̻ћ5~14gsշjL/v׶iιw\ƹ|c]lqTuNYW9[7򟫽/\zo5_Ϳvl\oݽ/<;cz{wק81ť81[\՜k"2Ӟ;ڵͽX[swS;ijzvZKV׫ifm~;z5׿;wּWj;ŕk^ׯ4O;m]rMyҬ;muuv[\;\mS5(pukWWSUNݚHxK{N:o9׋]/}{{f֡vaUi_o4z߾gUqܯ9FyG_y-Ey/vqbk}G1S{[ϝ梶v8۫ϚG+׽u8c͋m XzW}s]LGռ}G=W+Ν{ۿX<;w~oޟ9绎rʩN:r4OPN?rC?uk1;9 4GAWuyeauOqlLz,2 UvH29vҐ⸷,V}Aݱq4htJŰEeuIeKjdy&`Q_ + C/u~_E2<,sf% #1|1ĭ +'5QH"gJ+hhx4TP~,t?d"h} a(~8jAeUU5Rj) jAq;9\e% jW)*I,A2m5['hV@ M oom~߫3׸[Wo;4_6k߮{~gm׬^3*BƗ Z /jmWn9g{;_{Qm_v_m{w޷_ݟۼx_uX{ ۫ڞf߻߽_6 }3_wZ;o/zl(x}kbr|P*K#$ԮJZ,6;A(^Z칷96w}Qq޾mnmxxolxg{31~=g_=l3ϻ_1 r~5{{[s[m~o|߷{g{Z7ǘ_6 f5zc\wny fo]-]{/hm=~띱voܵ{c5?WyXc18/g<ᄑ|r_6^@7꛻z^/Z{o7_|c/{ϻ9o jclsu^6o_{kz͵(V:߯;^?^64_eCo{yƜ뎭η_~˳ޫ{α_qƼ}PmVWK;r;\cwy[mg?כ}b~Dθ㚽ߟ9ם{Q/Zwřo/wvko[o7[s_Us|ߗ noq4j鯸9|o[meC_1jwki狭 ^w~ο-j)ϗ =~9n}WKoWƖll^Lm=wn_xw{|޹W˯ƗLܬyyw>۾8ﭿ[%s7ֻkVh [}} [4@'(~%̓" qvNn*(h 3RƝo~ǻk7ksWk[ZuZp@h` 7%HoˏY2QxhV*P/R+co6j)c՜fk8ZP5o1Tl̄4m2Sd,& 0ȐCY;eJqC2N1LaA #)LXtP0ER&' +Ѫ)8!BB8aY*V)d &̕rH.Qٕ Z֬ZUr4K @TUUEOt0yZqD+JRJ(JU*T %; +| 5 12L#W*/D,,Ԃ-I?-E1;%,D,[TA@9ĶD 0* փ+:F1iBh!_YXbIp% +'D/O'Q/Sa# g :Q.KVa 7H:}X߹tï"DTɤO͇&癍D»R[9SlMm6@}6$ z1q0ЎNpYќfI ]E.hl饼09y"y:`x@UIv`3bqXVpU +ȹpGWt½AD܅u#9Ae:.eNv h (UTѪH,BHff|Ee2ul2 P:WAU^GI\en1eƖx1T h:MguLA`œ'V\p0~La(l)ӺiqNQL8sMʆDP&-;љIjxD&b : Fk`a~1Ϙdfx|!~ 0xe(O _x N EB"cEj; QBu.,d iG,҂(B,*ʂ, d7 6Ù,^q,F}m”s`XUlJ +Kl Yl;yVkk dB6V /4@llذ-(fm.lz$:mFE&-}ަu$6 m(-xleM`s]Pdlq8\6moyT2u&̀70[d J1]BWetQx %lEdm H.D8 +mLx|<۶Lˊr<۶mm2۶m(q%m[5mmȜ5+JB)3f@<۶E*"P{۶_lۖm&"Fa۶llvE e޶m+@xsmd:m+Ṕ @>? HSH;6Pn@is)3CJ'c0[jcP3϶mF k\E"IS)AJ-期N BpH~ [)Y_ R L+A<)>stream +i\&j`NTy73qhphphPF VNT2Te54`puy`9L8L5tPQQQP-۰. + +fBA@x.'GѲ0L $NQ#jDܙ`Q Dv h5 X +N e"d9'BiIWlpn!`Lȃ-d|@Z2 dL29f@,-ka&7<3  Ȝ4 F6IfodL8PhLD/3P,p@HFD0#("ˌ˖HD3 6Ӵi Rhl42gȵeN$aj``ِ(7aI2M$h&qy0C\LW(UV@ǴH-1} XaeUPHⶬG_h]sLR: (f=YJaQK4TR< rZP:2#fa&sDFr8CP0Q>s@9G˄4Ʉ<++ɬ.uM,9$.0@7@DAs ^"809-"Ň $ڹtÁw7N: WU „pz9m${-e9kTCGi!oV#30%J^ 7= FTx0&B<0(MX6$ +B<| ֣DaL˦b3'aVf6Nϳ [15e HHYN48&XB=#$ + aarZDa5éI$ fAiLA&Q@U@ Pf Uqgar)%`p'a(D.BāCD 2 }6$F3^x(W Bdu H Չ(<**2?%̄,Ǩ7JȲAciUcKYI⛏9m#@1a 4Ĭ$t,ʒ`e&>Wq@䴅"(a9awB:XVb -`&q+vԉD @Y^"hc& M@{|qeq34lI PaGM*(lEV +& +^ MɂǑ7<'˄OlL_b&H3 "$&/L@ &lA㏠zq30&B6f1n5t(~$,; 폀NG%nNT +0 P< HS )H +HP@ +^IOc49-!ٶk$L_Ie4؊ +􉍙h'P~8Waz_ߜ>\g&ϓBp0nyNoX)6$윬~)a]Pwu{K|F?cM5ٹsŬ1p/=7Dtwo4ޥ<0?Qb@+-i`-^m.KV/mc]|\]8- @y"<2e3y.ml>F S 8-A4|!uqTT-&:x*WXqI 7e^3L녍Cx2cVw}~vO]ԚPN˂3L=&jÄGAkWc6l~Ͳ5~7cƄ9m fڇgBCӤd@{ nl27nSNcū.cdZ<ˍS\*' )ۍbhhр@ l,d\sH70)o@ P3~K/m"i r(G3g@ +`xbqhVo#2J-;d.3^7SƕxW, ~v;]y۞VX\;jw[U-wfu`jY?pm-jM{g[~GV$`7v?jGQڄ0RcWhB5_~ RՂ8& 18 b=i^w W"@$JY{l=ip@g`bͫ|5j%[-COI=C%P5Ph3{Vo-ebC2>ĥR*)5|%z +hq[ W-yTEC{tD{lA'DRptEO93qBaHQ#d96Qt9 ytW<3:a`i.[ =&2I=_gǾxCm,x)=F?]'ƝLJ(z0D#5,6#9YDi#"ŰUoHqIfL$Nh8իwP,[Ga*>_y',aHvoI{rI^%c<&iǜ g0k|y]GVG>i7*<f#H̫hlҁز'H,2]6_b#Sg'CsGtg);aA[+/5*] =< E<> U9|)ݧb~nTD|}t!8UP r&9x>&$= +8Se`׏GLC2X>'* utve0XrTjTG{q>{gIVOe\U.$LV]cqPY(^9֒52U1 'i[]\~40zϓzOfNqPx8P 1ŚP51ђfnu^$б&f-(9o8_GAK6∐0+jK3'hxᗜ54cqsDSzFO|'c>󟉳}`2+$4V?*\;I`x./ny hZS oqH&,euEi:} SPn P|ҥo {+J]৷WNNic~`|q09+l X W_w'2^JZ[`-cJSX@\xFj2HgNwSunpY{b|CLiΟ/3q*cRr14CoiU ^TL* (TWphi6[hZ5rǭx[f0EuuIU]wek֒wc]%~$"Z΄zY|S+#fj&6|5fVCz;̆R/A}+8^:ű$p+}TS߷-jE:,!>*gqrD-\F[ll["w~З}I:Σ8v)zm‚oW+m*()#0i8;/XYy`!q^(xYͶOh+)>˵3Ce1aAGrU0yʝZPzWK +6+-ѼezՅ7`>ŔON7ZX㚨G,!(Y!U-Q +ޟ"Zpۀgx>wڔ82]co@ 0LsT8ܛM5)m^#1{PNEdZ"H w(|'wԆi WJ5<ԩ{eWۆrn潑7xS<~`==f Nn+#K*6i˝"b&<܍_Ѿ?Lw{}=H∕{m.B;bC3=qLQ%aK΃3bUI8<=qE_ߋX9a1GL*2bIJrusfATbqq6+6[V? M w[ED1kaXr,%k,88ào\ZY +0w|;B_^T{Vy ??O8%^֕Sc3qu=oj\3s c:ӡgŰ9œaQ@pUXa&_&P84 ۵Lh'hZ_d~XjF93{VoC/;FKå/v5Y%3 cE9#'XuS[{\%/_e0a[n ٌx"/Wd,E8ubʊe8_?R(*M/GGend4 R?9!Zd}`#^{O4 +;E_M{6/ /ϭ^jj߰e[kpIf[~#P=sUG=\;7Yq qkG~xZ\-<@_]"W{v-P8̔izR,71n/aۃe9v^> 9v8<, cMJY\>A-=3L\k[ +%2Ys-~*x0J-ҐFTB>2r)bA%ayouDŽ&0(ef74tLm^牷S $ +LJJ!3v1_^>C7о+v ? XZ{is^X{qrfaM S5t_Zgp> S h"Ez gB8j`DTPͤjxtҺqS5<.1Y Cd>̬Wa[>~xBNWƊK'@ (Мv0:x8@]SZ>z$ԤI5T)M'Wfq2 +xPdᝋzPlb;_~IɄKcH\& }%ZqkJZߝ|HKU UԂW:9&fzq̃DA؛;CN;Rcl=#^+<{)[oLnxiZV~Rz_+JQ[hCRۈjRCH7[ߑ\R\1Ԯ4j1Ur1,Xm| +(zemSU>o6E¬MpX XK SdAN;ہH9m#[Ҭ}j]xB/_[9fںFJ`޸-LE`wcc4?TpS]1jͨm*H #yy%ץ)^|sYRCX؋?5D)c=JL!vCe]K{=cq(G2~mկS^(VFr,OX7ʍtS6R%:\^8ig:$vqxE`cJkys{_[TuΔPyL[OV5G>J(PsPE*T|LGx[5hQeb}:Rq냵q@t('CuTP̎,l$(/UU@ s|b1YuA]+#N #Oi:6Hqi4 y.29p/_qAG 'D@D ?C@2,b.-gz.4.`ynÏdߢcD `2ME>O9iMNpd)G}O+a[EZUvU߯ ]ygw,&C c|^RI~h.C"I2R&-^޾xm'dlLu?cj` @\qWQśLsh)G[2sMD3yƨbBޒJk&k/L f8Dƫ@gAlWB630E[ IZ;fPMv9B}$u>}I59րg-NAfc +Cr!"mh=ϸph)dވR +0D;qտbbHQ˜"FDija-?,Ućۉ?A8]9QOAonPRRu +qVN5t|$&@$yML~"йAxX|X=IgH0D;$;l0V}_{3#4F{ژ8,&t >j%=%s/i bN^>0Lk71iσk sV֊ [+V2tyĕfXXD,\tZV`v9.:+T劌Q/V8ԠCѾ) 8yVNM7N(Yw;h(D!7A.tyU]p<ղb2~M@ WKQEZVt͗ahU\t Qa:r 1M.:`oN M%0j3 jLb>MLUCHr5 %)nR-*GCtm0$; :S"\vZ `Is$CYJЙĎO*_48NC`CJ/?e%FE(R?'& - Y%1uX<ЅH5gt``mV&=0)/2uYxZm,_ļHr΅ C/1{mjq`QĜ5Wn,QjζޜJ"QH :iK)P M 'h[RKpD\j P +5᳽@Xd{vʺ\U"Šo.K:]%asLm`_7:Ke!4u KQAH]تM~@cHDY?!UJE~N@Q;(Wa:]WIظ; :?_{qǾ^0&¸V(Lv?.y ZN'Ixodz=-D)\㰅+D悷h4A #':5Y<{ +jҰz^;sY[j9&s'p{!#EƉՑ!6wl;HoaB=h{|k=K%,7A +# +tuF~<|)CFvᱵ(B +/ٯECu~i rI\P•{X`&fdֹn #΂M(X.qjSeVlj4haRL(G(!4B.T~E}QxVBlڔfQ,*#^\,)jB=]"l81WcQSeD(-V ?HGjV$(P[YIɾC%b,ըY5o!dĝN]=̮֠YS@҅= +O% =IFdLg$*V}O5X!Ϥ ?ke3P!PyܙM3^6V=Mu1FoŃBb^qaj=RsIgmE44EolXnO P'%p+/U{hѩSUD_=G8 0.6\4 ˫2bngߞ--KiA[8'bfDg`\DgAqS@'|-V Xz28ʒ;\6LAϐO80ƺo5t]Fn cqr\7}` {y/O,Xh8۲cQٔ'NH%豢 ؆60\CiHWa7^j$Xnކ_,N}zcvUzX0~2c~`\xofnHCTs盻AYO} 7.)(EfxB'MqslEI/u ՎHx*%7'ҙsǍ- >ZNJ8[-,i 70P\$ +⛥=-"@f@?};|礽pٓT[OCHI~wՉVpD`!i$1YR{Qk4Sw3D:C 9(Y6-BieG + !ClQ#>P҃>,$xWzg: #ڰ#wb)vEhnmMz?ft45Unar +eزf)!j߉%,ʝtBM1y',w g芒,]<a)49eRmP @V u + 6Ⴠ%٭e-$$ u$z8O(괔|3Qf=# M>t?+$8G5/~8j@~J+bEX5\Dks`ӄWfoґ>_l6W +Z6LރXX4Jh&DfZOLߐ`*NߠU5ESa"1pS+k.~ v/"YU7I[ٳ~Bug֋L?3w48LX7 {+WkdLSPRr9j5W$\%2hRLKFjRX,P3)8mԞxJd 9.WU'mzQ_73-3M|&!qCGsPj% zwN#ޓC(e|p)9-Foq '"6x(Lh  )lB.x~ڥ! V4{ӌ*9:_󍖠Ā0PLK>8) udF,&u^f9Obrh/lL.-d(J`bfGJzYLoJ??+vyĐpniXR(3TX2"VMz ٟ۪-6ۮYѿ0;3Q7B-Z$r>ȻkĊqx=3 9t2 QJr + u&0a-@R: %g@6g+݇-GMCzh]5s͚Jenw{9'ۓYk% -䡻'wx'qaA"5?F6]Z!ġZ86Yr(32 +!&k>wez 'zV{6CVty SlSNz^myL-5zMDN cB7&n#b(=ApڶOE1Tb eNixK{8-e Jxyߑ4J0] Du![΅&;?mHꕏIcOW4iQZ6Hʅ)t%SE厈0ڨ>&QnAu#j31}Xt(qK%LM^ +Sb8t'y[w-ɘ)$&d#O5Da+v[{ćp/|y.<`rED <<3/Cagyqv?O~^).FIev\O,W }pD 07#[ 踁0q=}?FOX aZ2I=](+2ZY O uioǥ%D$]vD*oq5-h"pWJzDuZՂ -K#4mF % 4#! P{ACiǸQW Q- +ag$BGS+C&P5,Hꆉ] nc|`{zvgiZDAe(^`f$˭x^H,S0|E,%Y|FL!gqs A`PntxÅVƫ%)@E*[x J[Fef[H\H 0yZDDfrA}'bz҂Čng8?^I&[>┵NYF 5 4cGvܥ)" oY Ίubzf1);e- q!|^+kf lcF$(2M~|{`)eQ14ϛ'-vP,b.ń)MExOs?}y +ٸ̿m_,Y+7z%_3~N|Y}(BUTy%+\ADȞEB-4>lX$Z[{㿸d l\?͐8 GIs7qh/M2C1qRe4CRԝ) +[fgfu|H6 ("_Zn`MZ|`Q8\mXQ+M`֣ԁ?ڒ6a:Ei)5\7pb\f$fkq|OXRʎxnQJ*I.㷿n+8rTeLA#~VD*Ovc3黕9D(~ b N57f2f65jRv[98jQɉ:`&G#O-3PRKљ~;[e_Rqn.hɭC/ΐ4X]F4TMhJ=[5etBa]ӻtЇSk1@j}0yC֫5oR~/ELe|k8B9j +/b 僳bNpKI(r+b:#zR.xKh5..a;A/`/+BZc@H\lKlҥ] h7Y&^Q |lhMM`.@-IN?@@jةPYQ4'L?Z\mY?]`59vlc(Wt Mʗr@IF!OJjdUR'Tb^@cw +Ґ:9G&Xxq֧98uGkw nP(IUPDg䎶.TYyDFsiU-' sfӗv@(v͚cZ3:{&UȢ#8 (1L/}#,F?QoRkՈ']eZɆU~l$hXK1fWsJ[')'sa+냠g;}a2Ќ, +F5^3N܉/SQ2IJּ=nU*77_țJe_W ?Oz6ŕqxhFx߈pIT-_+ -)OE߀Ssm.bAU>Wa)'Q vի;Nav4kC6;:$ l'Y&^IU9kM</vtdq>CctTwF*>ªXɠlF81S6B7WRh@A*rm;%ՋmZЭbWѥq))V-x娭}f9XGH |AulyF-Sj'LSA7W~.^ C\lSTNЇ1ѿLH]e[?m\aE|MKUyp-)27G@xN2'RYU]@:usb1?AaqCWX`qLs&Qʆ!"M-D٧a!xnEvYP\a 8L bӊQ9)0l؇%ncAҵLEaZ##!TsZ8&Ey$&b76wH@`0PeqNVfxP )X }~"n1낺Ȍ u6HA> DG4fB_zZ'_wKIi>qi:^@uNW:v1#&ӚO<={flS-A5=*& 7sN)ė}U- XL]g%o4V[c-໼ ) VJy,V|Ho F.LBҽ0sMvQ<0JO``2? ֡lP ̏]9DZMSxΌ־@iaq0MJoOj]g(^Tbz%>&IsȊ~z$N|Ggj/bhDmm"C7Mr㊯zQ:xE*%G{JOrqT]gv 4-.]zY-I`nz̒!+QBG t z 4jzaUW'RݗX5 U˃[rGn7!Y:U5P"\atO@oLb-8A&% /mdIh9U?cZ0%Ddre0|-g<T3]OЊC"$x, qޑ+<&{k' +c z-=TUl ~΁no\xY٦-'=akbe]g/;54J;$)%=^{~v"7`ƧjI1Ia^)dL}[WTI'3πX@$Pp$@{6#?r"iP ɡ*q `k ZҠmg%mGa]._!s\ǖ +(5pߛr}"(!fB–x ς +ʵб3;156ociHe(YǬ:ɹQfɰcؘE*îz-ՅWQD;ɴ %N4:$@ҥW _`u䯱%^VPH́8u}Vh__ATz2NO5g"؀s#$H%)!{t{~_(n7mHPJ|$19ۥ`րuƏ5"KU_H;1c{aืp!ao +fS> ϟb +aÈT uƳ&hJU7CP=xn֒{vH#)EL-'ؘ',IC뜱9(ntT)0%krxza]Oa] ".IX1xF-VMXn\qjkeRZ<ȮIJ}|ںE@қ%߃8""vv%Sf Ӕ$ *[ +w? N~~׳ѥy;kD [ J-K n Nhq<4IA#ϋpcPVjdlhЯ waZ4`Kr&GVXMq~^=+N+x8S"ϭdCcPgRp p(ǫ{@!g@L2:t{ ,.tc0Hǰ"ljDeh0Fdr5i:M"3w[)S2pn +3ʀ .%Fm7tJF,u%W#E^7GW?ةҩ*@b,(A! y>&+˱u!\2 /ƅ.0feU6 +MXhn!:VS!V>YZN +F<^@ +4QSY. MQmeL~3Z\IQG/j+J[ɵI+SfK\wP !kGOՎ~ޗHٮ~ϵ$m'`H>UW+ `эy{޴SJ:49$x<H+ *|N'"y!_;L@> 1@ + ^GҲx(B mz0̣I!NU., %>q(bE3 .o=Ŷ2%YDD$xH)PץYORbDI )@Ey *oi,‚ P .Ht㩓 ڪE[5m[ZҰt6Dsp6 wSHۨ׽û0[nӈ6bKi/ۂ s`TŁ2|p@BAIm&.ԁك۪mPX6鿮U0.: ,[Zvkp- 뾌 SSD3IiSQ!hA4i F"MEgpEB}ODȣb#×р::5\, Ra*.<mc/&ڪŢ!+Dނb v*UXAA FòXԖl0v2MZIe2Ԅ1 @T (B P Ca0rB:m[X"xȥFq<a *CѲJ T 6¨~4hpBN袭ZHվ2_GhRͦEvu`!p &0SLL`dC,H"Kq`#!lTDG +]hJ mBA"df 4RmhY0|CBa4M aB_%x? Itf! H@59"n3d:7]:4"8r}F_ :59Y*o;U[ݞ.$BOX`SSPb .@dO@si&j.MU6  uby u\yǔL+_ HCPH bH)ads$.aWTz|+V c+mղJW6G"ĕV*9> +jV\*ZÑ,#FTE1/Z-14Ai`r @!V'tĥK OD*p6r j6rτ˃b,^ $_m@Iy19 .m"@Z$ͺCb.IҊ4$C!q܀X3FYP#Fdd&+J֢Q R3b&0CMh|@@^H)wLA@6Lf۠07 +0+R壀H LТDҳY@abNE  f]j 8i1ń3 y-Mj!41.J*DJj!Ab Lm2oBoó +xxqùZdfAX)&,5I} hh=JgZCY!gT)0 u!4ԧ/#oA&-Fޖ$nBcpREA〢aQlJ}WaMWZ$y (:, +``3I^\,Wx0l,HK$f.V!LZ|y_) @ѩ]Fpkk{?vqwҡW]]_ku >c[G^_uI!%W=R^kCIƍpkqֺ{(.Z.2߿ܒ#=t4rgZC:#K괙 em%4Nn)D*I솱viS4NZ{S6`l,YY%qVRƧ=GdidZSrZ%[S^Xk|)s:aX!YB5~)|ښlϵtN҅ۋKͼOw/ICYU5I#otJqa~}B-GJ%*etSst +Z+^y2FqNKo;#Gf)?:&R=C.HeJO*zOƆtVVy+JTƍ+!wC@Rg^*Re/H&y%켕۝k?GXD"G> yF\Dv"lRd#¤ŴԴH]FbG؊KHڪ/Oc2 F h*x1|+ K2e$%YFH"f"_ h!q2Z РE` 6ˈ2Z Z"0h ֱњ=h4ػ6OMDί JYh:. KNs+5ӝS-zoy8-=t+J>N7nܸq}}{{{{yyyy{{{{}}ƍ7nܸ2G׬nYgu*ׯWiJ'O*~_kѱRZi^\ɴ~-chi]٩ܮ/.y{Q#^}__W6elgɕYBΛG?Ӯ\@;tJ Z\6ћ'æ'J~?HROصyD_YkR.߿CϑJ7qzii0v0JuƏu>ֹ[kCik"seNԿ{KiHip;/_X'}~TVHSYiX'#+Ӹ[!/)ΧӹJ8gӥ:/5e]ﮑ?;J(8֮NimJ{RK)mM:Yg߮-#n{J=wXttϭg3C[!Q:5pgZ#Uߒ62e,뜒2U>f_֟ίp]BɻL{CN^Svw7NH9v,!DgU2 +[m!J}< +?W>ʍ3>HI㤐~ܹz3+).g^u~ȑiS6.2C_?R){io3S3>G&ǹsc\Z{?i}6iܝΔ7v9)C__^]7ҥtؒPV796e鲹C)ǦTWQ>[i[N*}N9?\\OJ)9ّsit:ON5^=v%HkaOSIc 4rRH! @H0P IDf|nH$880,&, ( 00HjM'@ǣGIV!#wf`j/s@QDʠw@I^GIeFII"p%+ %yZQVv )[!.JaIcPx@$;IRGS?(w]z%4'$$5 +%j^~?J)6Jo!Bl4UnA\$QP3؁JmW+!NӮ*v~G"Fįb>ov8tPZԛzK3A@-b0] 5;E~ru:/zڈ˃iĶgU،6_#v|x5!ΨE4ħL>hGc3 v]HA%8xbAΦ8-$v-.,gVܼiQ xt})#EJm];%{[!܊p=mQ jhhL}gVY XFnxo(B(NO^A$lG]<ڡt iQ*^< Z}>E؄7u9%(A BxPˁ0U +joh*6qn1DY7P]k4\:WˆJFGIfk$j51?ҴME\~ٍ38cc8=!^$( _?u+\|\4$[7R&ohSlFN!i7mttR9~B<A33/z%YB>73>pp&RP&I ˠxgK/Mƀ:3bjEhCTUpʭT +f75ӆDUlۚ~1rDaՒٖwdz6R<䋬OԑY"pp5$q @MgVL2MRZĜ}¥ &$H ߲yʗ-=3v GizUo%? 9cefß#DdѾ3qr9?F:+HK xܤvъKDk>W7AV* <O(7&.XouHAGyT3AQfA`/ n.&~pS'{]TPgz!;#Z:5h6Tx3<#ӖQRAz&l(%ktbLɮ>UcN0$9; $#czd@(Ķ_ߋgDa¡džaMlUNcXi +-B3VǶUz=;A)Ei2k`v(S72(cmFi9;5SNC$~8 ND{&M" JeN$G+8. [ocw>C,+,'P9'[-V)e|`@?(aȂU- cЛTNRrAԃ%:q}” \5M@jo%bQ3"&^śfXM`z\'NpgWguwCnqV+A-/8QeWLv̍&;PEKM+=#C-FvbC#gN[SlFդFY,†2pU)Ʉ%xH +rpHLPW;c1$SdAXWL2گYH@M~2Rʋu^ЇsΙ$3BESlm_6Ô݆565d3BDebtYHHbQ`%t%#P/4B1 ɮ 'BcSlcHO} `bd`kpƘ3l[c|NaM1pL%D0Nݑ3$J;7AU)l9 +n+ԙMZ5@~qM9f,b [١l>yw$R9 R_8, r2{#T j +%],e 1qtoBnDAbu` +8A/GYD%l!蕲*YDžFxl"6琐؅WEz7ġEqFy )7d'wJfǹ.# ]pq&J7 ά$'Vٱq/-,aZc#z~yryKy^@N<30M6 1YL)y83S -wx]=cX#2D_ Ҩ2 @"N@sB|" /~wQ=JZݟo4Es/YzY+ڀzJAhj%9dj3ȣx^zeki?4H̀hn8Z1q1U k ]TH;G)Yem<\ 'ۭj.8 Vۋ ݿaT[^H]%gWڇ $8[3jwdwO?1REά gJ_a1I31…k h8)/ ;;s9?ؓ'KfE;{d(4kvcD92:QuBgԏ|ko"iqKS- ez#$x~B0ǜhh~54cxL+& k:YʇYb (% +{mMZ3Jw45 J.lf}UDT3ΗeOT\c7 d"FFxcc7W_Bb;T/5jKpB+X3գ;RSE5sNJ78SR:ٿ x2Nz!<(d wl-:@W}<|`Zr14a Յ>e\# a[w\i[ +O:lnNro(߱,_3EWs<ˌ3{+_E$}ʱ0I9#'C<.bPp:l!k$沤@]gM,)_GZpfdWz^ oC@R7^]>:2n ͯЬs`YCC~D^)@-* 9lTV Nϲ]%F(.Ix"y$@EڦߎD/c1G?XJmpɺ({Eur,pṀBnuy8^b XƤCŸM-Rl }qs"yG2nһ]r$؃W "ս< +5JaNT?0b^ OhG9'@Hj^2Nk:*3W Xf|܄0}yԓ`Eu1f( ,BgR2\';aR,OvO7Cd!1SmjIbdmB U2jE8dBBͷr e!p7@a &:Dˠ_; z$^Aԛh9x ,#WqxপO~uڲxvM*ٯ[V0ez+k]4rŐe"8.㣏6 @PPضQ^n@D =5*e\)O/'¾OX8ai+8(3rBDAScM'c, ],Ufk7*>f"O_Csf]~) .q 1e(-)Y/Y)pg@AF!RleX}4Im]@ 7lGy/Zr)e"CϤC$,C8lCE&45~eF=Cd7b}y#ĔJJnܐ+íx1-qv֌rųj` + ;@b2S,?*)O$$O0 s΂5j@) ĺ229+lԂYKLcu@vbn`̀4;E(39|+Gk~58֎aݗZ0LcPzzK4slTE IRʆA8A>y-Ym\)8U~m +jڂڊ]In+ORyWbX;ó-DVG|ߢ_x`C5LBON/k8%䞟?F}~v'5:|iY#FdG>Bs3Pt + nĿ_Wޚ ]N( 쁉 Z_ ręE['a #*+ZKJycĿ~yka ++?b#{sSq'UՀOؕ>_X,p~3M@G];$Iw$p.*`du$`q.nEBW?<4.AG7/ _PJ%K(z V|: 6{4z E/c H]3D(z/>N,ay,VJ^q̴`[ +3QM3{ײzrTU2'uTͿ`6J`0ώ >@`*-,caO%㬜^1S8of +T +ЂMRgEoE0T 8Vi6s);<2w}uJk| _@I :Jk\ 45 @) WʫzNaF7#TΦ$<҈)w#,ޛ|/ur^17X|e K#iW섀S& J.Y +ort&m^'ƫ>kLwDHq',2:#sR '9,A엄xBƸT)Vi=]'Թ m-Jv}l.T9R4L("GYȡ݇zqCmvRl9"4GAΟ p垭\P2MDi7Q"רJ1{=OB#}F<`@:Ew6bam-l$y䊎 =vP7^_#byY"ײ:j}ư8z9bb 3tJ;VDia yr p:dM-Gܿ*Kt ܨN%|)J"يOu'/1RLg-@EܒC1Q3C+}+1ي=EO][N1-nʮ +F}W}aS-bӱ +AI +"1 a5g&iITym6%!];jI4܊ <5;!{ܶQ^ԕyN)zd3(Uoz\+DX +U? x*^n +'}r} 0Ⱥ$4rP^$VUoPJұZzCW/gfT[֍ +SkJNt)>U/r TqVF2ܵ퇺щV*H;Gxh|I_|۾ThZA {e˿P1^O/|6#asPoY3辒avj(3dٚvEWR5i|1$@L؍Fnwom(4ճ+ۿfAzE4jIX%>i% ,@ eF}zȄ>stream +HlWI$7 +Tkuui` | +^=#H*z;sZ䁈j%;뭗G¥lj1{]tL6[Wgr+|Qs}X5n.fN!骺4**Gyc$R(Y.fFkn7?t['VAdu| 7[Cģ N bE"ԟN6 ȣ;qqj~:S) +C rX IjݨjkWd!][Dr(v^憠W#`Tx!ԅ,k@ȌR7C}ej'rAJgU,5|.AIa$L}Vec +Nֵ&h0JVyj> +z( Mvzҙ0Ep~F7ܴ: zHH~x_2ID&aa_Ȫ<ݨ p+BKĢyå-"ŀELME֠}iMUq=R{sfE]Lm۱6`Mpy; -t7 5 "A5G,DBBWDbnnd_MrNdy^br ռҝZf8rPW7:BO&+#[JeR@H J LPYINI y!@VfʢC/ W; :TbYm:~BfcCXP~sƳv`H9 )ꬶ%3.v֟l_pgs~> 0 endstream endobj 38 0 obj <> endobj 45 0 obj [/ICCBased 44 0 R] endobj 35 0 obj <>stream +HdRIn0 iRk z'@v]8CsH ܿ_FƗ[O;;cɳs5} d]&x4Q;KXO'ޒ0hQp~GXC`Ĵ)BbkDAZ> endobj 46 0 obj [/ICCBased 44 0 R] endobj 29 0 obj <>stream +HT]N0 ~)|vҤ: M q_ɒvqؖ?_?}ݍpFݤ ^1^ɱv%jA Qu S?4  8h:Nj8Kj4HGs7kpB2@u9@gƧz@wZTP|M,$+c"G9/q1ug, qߧnDa jeVG87 t<^:*J*?Lϔ4ry¤"""!bg_ + endstream endobj 30 0 obj <> endobj 34 0 obj <>/ExtGState<>>>/Subtype/Form>>stream +/CS0 cs 0 0 0 scn +/GS0 gs +q 1 0 0 1 296.0986 282.5586 cm +0 0 m +-61.191 0 l +-66.255 -9.679 -69.119 -20.689 -69.119 -32.369 c +-69.119 -44.89 -65.828 -56.642 -60.063 -66.808 c +0 -66.808 l +18.448 -66.808 33.403 -51.853 33.403 -33.404 c +33.403 -14.955 18.448 0 0 0 c +f +Q + endstream endobj 48 0 obj <> endobj 33 0 obj <> endobj 47 0 obj [/ICCBased 44 0 R] endobj 27 0 obj [26 0 R] endobj 49 0 obj <> endobj xref +0 50 +0000000004 65535 f +0000000016 00000 n +0000000147 00000 n +0000046321 00000 n +0000000000 00000 f +0000046393 00000 n +0000000000 00000 f +0000000000 00000 f +0000052524 00000 n +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000000000 00000 f +0000052597 00000 n +0000052793 00000 n +0000053991 00000 n +0000119579 00000 n +0000185167 00000 n +0000000000 00000 f +0000046806 00000 n +0000047194 00000 n +0000049541 00000 n +0000222892 00000 n +0000047582 00000 n +0000221751 00000 n +0000222132 00000 n +0000049841 00000 n +0000049728 00000 n +0000222734 00000 n +0000222194 00000 n +0000221322 00000 n +0000221654 00000 n +0000219714 00000 n +0000221225 00000 n +0000047962 00000 n +0000049479 00000 n +0000219679 00000 n +0000049612 00000 n +0000049643 00000 n +0000049876 00000 n +0000221287 00000 n +0000221716 00000 n +0000222857 00000 n +0000222671 00000 n +0000222917 00000 n +trailer <]>> startxref 223160 %%EOF \ No newline at end of file diff --git a/assets/greyscale/JPEG/Move_Logo_Design_GreyScale_Digital_Final_1.jpg b/assets/greyscale/JPEG/Move_Logo_Design_GreyScale_Digital_Final_1.jpg new file mode 100644 index 0000000000..db9b1bbf76 Binary files /dev/null and b/assets/greyscale/JPEG/Move_Logo_Design_GreyScale_Digital_Final_1.jpg differ diff --git a/assets/greyscale/JPEG/Move_Logo_Design_GreyScale_Digital_Final_2.jpg b/assets/greyscale/JPEG/Move_Logo_Design_GreyScale_Digital_Final_2.jpg new file mode 100644 index 0000000000..86ee9fc512 Binary files /dev/null and b/assets/greyscale/JPEG/Move_Logo_Design_GreyScale_Digital_Final_2.jpg differ diff --git a/assets/greyscale/JPEG/Move_Logo_Design_GreyScale_Digital_Final_3.jpg b/assets/greyscale/JPEG/Move_Logo_Design_GreyScale_Digital_Final_3.jpg new file mode 100644 index 0000000000..fdf0e8e404 Binary files /dev/null and b/assets/greyscale/JPEG/Move_Logo_Design_GreyScale_Digital_Final_3.jpg differ diff --git a/assets/greyscale/JPEG/Move_Logo_Design_GreyScale_Digital_Final_4.jpg b/assets/greyscale/JPEG/Move_Logo_Design_GreyScale_Digital_Final_4.jpg new file mode 100644 index 0000000000..64c6541164 Binary files /dev/null and b/assets/greyscale/JPEG/Move_Logo_Design_GreyScale_Digital_Final_4.jpg differ diff --git a/assets/greyscale/PNG/Move_Logo_Design_GreyScale_Digital_Final_1.png b/assets/greyscale/PNG/Move_Logo_Design_GreyScale_Digital_Final_1.png new file mode 100644 index 0000000000..2bcba7a740 Binary files /dev/null and b/assets/greyscale/PNG/Move_Logo_Design_GreyScale_Digital_Final_1.png differ diff --git a/assets/greyscale/PNG/Move_Logo_Design_GreyScale_Digital_Final_2.png b/assets/greyscale/PNG/Move_Logo_Design_GreyScale_Digital_Final_2.png new file mode 100644 index 0000000000..0d8f2b88e9 Binary files /dev/null and b/assets/greyscale/PNG/Move_Logo_Design_GreyScale_Digital_Final_2.png differ diff --git a/assets/greyscale/PNG/Move_Logo_Design_GreyScale_Digital_Final_3.png b/assets/greyscale/PNG/Move_Logo_Design_GreyScale_Digital_Final_3.png new file mode 100644 index 0000000000..7e5079895e Binary files /dev/null and b/assets/greyscale/PNG/Move_Logo_Design_GreyScale_Digital_Final_3.png differ diff --git a/assets/greyscale/SVG/Move_Logo_Design_GreyScale_Digital_Final_1.svg b/assets/greyscale/SVG/Move_Logo_Design_GreyScale_Digital_Final_1.svg new file mode 100644 index 0000000000..4a4d4202bb --- /dev/null +++ b/assets/greyscale/SVG/Move_Logo_Design_GreyScale_Digital_Final_1.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/greyscale/SVG/Move_Logo_Design_GreyScale_Digital_Final_2.svg b/assets/greyscale/SVG/Move_Logo_Design_GreyScale_Digital_Final_2.svg new file mode 100644 index 0000000000..fcebdb262d --- /dev/null +++ b/assets/greyscale/SVG/Move_Logo_Design_GreyScale_Digital_Final_2.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/greyscale/SVG/Move_Logo_Design_GreyScale_Digital_Final_3.svg b/assets/greyscale/SVG/Move_Logo_Design_GreyScale_Digital_Final_3.svg new file mode 100644 index 0000000000..deedae788b --- /dev/null +++ b/assets/greyscale/SVG/Move_Logo_Design_GreyScale_Digital_Final_3.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + diff --git a/devtools/x-core/Cargo.toml b/devtools/x-core/Cargo.toml index cad7367c3a..b02bb7fe89 100644 --- a/devtools/x-core/Cargo.toml +++ b/devtools/x-core/Cargo.toml @@ -3,7 +3,7 @@ name = "x-core" version = "0.1.0" authors = ["Diem Association "] description = "Core data structures used by x" -edition = "2018" +edition = "2021" publish = false license = "Apache-2.0" @@ -14,7 +14,7 @@ determinator = "0.7.0" guppy = "0.12.3" indoc = "1.0.3" hex = "0.4.3" -log = "0.4.14" +log = "0.4.17" toml = "0.5.8" once_cell = "1.7.2" ouroboros = "0.9.2" diff --git a/devtools/x-core/src/errors.rs b/devtools/x-core/src/errors.rs index a354faf80a..ed333ff5bd 100644 --- a/devtools/x-core/src/errors.rs +++ b/devtools/x-core/src/errors.rs @@ -8,7 +8,7 @@ use serde::{de, ser}; use std::{borrow::Cow, error, fmt, io, process::ExitStatus, result, str::Utf8Error}; /// Type alias for the return type for `run` methods. -pub type Result = result::Result; +pub type Result> = result::Result; /// A system error that happened while running a lint. #[derive(Debug)] @@ -46,49 +46,49 @@ pub enum SystemError { } impl SystemError { - pub fn io(context: impl Into>, err: io::Error) -> Self { - SystemError::Io { + pub fn io(context: impl Into>, err: io::Error) -> Box { + Box::new(SystemError::Io { context: context.into(), err, - } + }) } - pub fn guppy(context: impl Into>, err: guppy::Error) -> Self { - SystemError::Guppy { + pub fn guppy(context: impl Into>, err: guppy::Error) -> Box { + Box::new(SystemError::Guppy { context: context.into(), err, - } + }) } - pub fn git_root(msg: impl Into>) -> Self { - SystemError::GitRoot(msg.into()) + pub fn git_root(msg: impl Into>) -> Box { + Box::new(SystemError::GitRoot(msg.into())) } - pub fn from_hex(context: impl Into>, err: FromHexError) -> Self { - SystemError::FromHex { + pub fn from_hex(context: impl Into>, err: FromHexError) -> Box { + Box::new(SystemError::FromHex { context: context.into(), err, - } + }) } pub fn de( context: impl Into>, err: impl de::Error + Send + Sync + 'static, - ) -> Self { - SystemError::Serde { + ) -> Box { + Box::new(SystemError::Serde { context: context.into(), err: Box::new(err), - } + }) } pub fn ser( context: impl Into>, err: impl ser::Error + Send + Sync + 'static, - ) -> Self { - SystemError::Serde { + ) -> Box { + Box::new(SystemError::Serde { context: context.into(), err: Box::new(err), - } + }) } } diff --git a/devtools/x-core/src/git.rs b/devtools/x-core/src/git.rs index 3fc03e4f33..72e791c82a 100644 --- a/devtools/x-core/src/git.rs +++ b/devtools/x-core/src/git.rs @@ -48,18 +48,18 @@ impl GitCli { let output = self .git_command() // The -z causes files to not be quoted, and to be separated by \0. - .args(&["ls-files", "-z"]) + .args(["ls-files", "-z"]) .output() .map_err(|err| SystemError::io("running git ls-files", err))?; if !output.status.success() { - return Err(SystemError::Exec { + return Err(Box::new(SystemError::Exec { cmd: "git ls-files", status: output.status, - }); + })); } Utf8Paths0::from_bytes(output.stdout) - .map_err(|(path, err)| SystemError::NonUtf8Path { path, err }) + .map_err(|(path, err)| Box::new(SystemError::NonUtf8Path { path, err })) }) } @@ -67,16 +67,16 @@ impl GitCli { pub fn merge_base(&self, commit_ref: &str) -> Result { let output = self .git_command() - .args(&["merge-base", "HEAD", commit_ref]) + .args(["merge-base", "HEAD", commit_ref]) .output() .map_err(|err| { SystemError::io(format!("running git merge-base HEAD {}", commit_ref), err) })?; if !output.status.success() { - return Err(SystemError::Exec { + return Err(Box::new(SystemError::Exec { cmd: "git merge-base", status: output.status, - }); + })); } // The output is a hex-encoded hash followed by a newline. @@ -96,7 +96,7 @@ impl GitCli { diff_filter: Option<&str>, ) -> Result { let mut command = self.git_command(); - command.args(&["diff", "-z", "--name-only"]); + command.args(["diff", "-z", "--name-only"]); if let Some(diff_filter) = diff_filter { command.arg(format!("--diff-filter={}", diff_filter)); } @@ -109,14 +109,14 @@ impl GitCli { .output() .map_err(|err| SystemError::io("running git diff", err))?; if !output.status.success() { - return Err(SystemError::Exec { + return Err(Box::new(SystemError::Exec { cmd: "git diff", status: output.status, - }); + })); } Utf8Paths0::from_bytes(output.stdout) - .map_err(|(path, err)| SystemError::NonUtf8Path { path, err }) + .map_err(|(path, err)| Box::new(SystemError::NonUtf8Path { path, err })) } /// Returns a package graph for the given commit, using a scratch repo if necessary. @@ -139,7 +139,7 @@ impl GitCli { // Check that the project root and the Git root match. let output = self .git_command() - .args(&["rev-parse", "--show-toplevel"]) + .args(["rev-parse", "--show-toplevel"]) .stderr(Stdio::inherit()) .output() .map_err(|err| SystemError::io("running git rev-parse --show-toplevel", err))?; @@ -189,7 +189,7 @@ impl GitCli { /// performance reasons. fn get_or_init_scratch(&self, hash: &GitHash) -> Result { let mut scratch_dir = self.root.join("target"); - scratch_dir.extend(&["x-scratch", "tree"]); + scratch_dir.extend(["x-scratch", "tree"]); if scratch_dir.is_dir() && self.is_git_repo(&scratch_dir)? { debug!("Using existing scratch worktree at {}", scratch_dir,); @@ -199,14 +199,14 @@ impl GitCli { .git_command() .current_dir(&scratch_dir) // TODO: also git clean? - .args(&["reset", &format!("{:x}", hash), "--hard"]) + .args(["reset", &format!("{:x}", hash), "--hard"]) .output() .map_err(|err| SystemError::io("running git checkout in scratch tree", err))?; if !output.status.success() { - return Err(SystemError::Exec { + return Err(Box::new(SystemError::Exec { cmd: "git checkout", status: output.status, - }); + })); } } else { if scratch_dir.is_dir() { @@ -218,16 +218,16 @@ impl GitCli { info!("Setting up scratch worktree in {}", scratch_dir); let output = self .git_command() - .args(&["worktree", "add"]) + .args(["worktree", "add"]) .arg(&scratch_dir) - .args(&[&format!("{:x}", hash), "--detach"]) + .args([&format!("{:x}", hash), "--detach"]) .output() .map_err(|err| SystemError::io("running git worktree add", err))?; if !output.status.success() { - return Err(SystemError::Exec { + return Err(Box::new(SystemError::Exec { cmd: "git worktree add", status: output.status, - }); + })); } } @@ -240,7 +240,7 @@ impl GitCli { let output = self .git_command() .current_dir(dir) - .args(&["rev-parse", "--git-dir"]) + .args(["rev-parse", "--git-dir"]) .output() .map_err(|err| SystemError::io("checking if a directory is a git repo", err))?; @@ -270,6 +270,6 @@ impl<'a, 'b> From<&'a GitHash> for Cow<'b, OsStr> { impl fmt::LowerHex for GitHash { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", hex::encode(&self.0)) + write!(f, "{}", hex::encode(self.0)) } } diff --git a/devtools/x-core/src/lib.rs b/devtools/x-core/src/lib.rs index 90b2b4b391..008cd63f34 100644 --- a/devtools/x-core/src/lib.rs +++ b/devtools/x-core/src/lib.rs @@ -39,10 +39,10 @@ impl XCoreContext { let current_rel_dir = match current_dir.strip_prefix(project_root) { Ok(rel_dir) => rel_dir.to_path_buf(), Err(_) => { - return Err(SystemError::CwdNotInProjectRoot { + return Err(Box::new(SystemError::CwdNotInProjectRoot { current_dir, project_root, - }) + })) } }; // TODO: The project root should be managed by this struct, not by the global project_root diff --git a/devtools/x-core/src/workspace_subset.rs b/devtools/x-core/src/workspace_subset.rs index e8b969f7fa..34dd2199df 100644 --- a/devtools/x-core/src/workspace_subset.rs +++ b/devtools/x-core/src/workspace_subset.rs @@ -63,7 +63,7 @@ impl<'g> WorkspaceSubsets<'g> { WorkspaceSubset::new(&initial_packages, StandardFeatures::Default, &cargo_opts); Ok((name.clone(), subset)) }) - .collect::>()?; + .collect::>()?; Ok(Self { default_members, diff --git a/devtools/x-lint/Cargo.toml b/devtools/x-lint/Cargo.toml index 4174311b85..69ddfb7c08 100644 --- a/devtools/x-lint/Cargo.toml +++ b/devtools/x-lint/Cargo.toml @@ -3,7 +3,7 @@ name = "x-lint" version = "0.1.0" authors = ["Diem Association "] description = "Lint engine for x" -edition = "2018" +edition = "2021" publish = false license = "Apache-2.0" diff --git a/devtools/x-lint/src/lib.rs b/devtools/x-lint/src/lib.rs index 3aeea9dfeb..6c337c0c7c 100644 --- a/devtools/x-lint/src/lib.rs +++ b/devtools/x-lint/src/lib.rs @@ -5,7 +5,7 @@ //! Lint engine. //! //! The overall design is generally inspired by -//! [Arcanist](https://secure.phabricator.com/book/phabricator/article/arcanist_lint)'s lint engine. +//! Arcanist](https://www.phacility.com/phabricator/arcanist)'s lint engine. pub mod content; pub mod file_path; diff --git a/devtools/x-lint/src/runner.rs b/devtools/x-lint/src/runner.rs index 1382f59cf0..034f9541d9 100644 --- a/devtools/x-lint/src/runner.rs +++ b/devtools/x-lint/src/runner.rs @@ -245,7 +245,7 @@ impl<'cfg> LintEngine<'cfg> { // TODO: make global exclusions configurable Ok(tracked_files .iter() - .filter(|f| !f.starts_with("testsuite/diem-fuzzer/artifacts/"))) + .filter(|f| !f.starts_with("testsuite/diem-bytecode-verifier-fuzzer/artifacts/"))) } } diff --git a/devtools/x/Cargo.toml b/devtools/x/Cargo.toml index 2d9c9498ea..f4a0ab058f 100644 --- a/devtools/x/Cargo.toml +++ b/devtools/x/Cargo.toml @@ -3,7 +3,7 @@ name = "x" version = "0.1.0" authors = ["Diem Association "] description = "Diem extended cargo tasks" -edition = "2018" +edition = "2021" publish = false license = "Apache-2.0" @@ -23,7 +23,7 @@ env_logger = "0.8.3" log = "0.4.14" chrono = "0.4.19" globset = "0.4.6" -regex = "1.4.3" +regex = "1.5.5" rayon = "1.5.0" nextest-config = { git = "https://github.com/diem/diem-devtools", rev = "f99a204e3d3f8e503d51d7df42e55c8282b59154" } nextest-runner = { git = "https://github.com/diem/diem-devtools", rev = "f99a204e3d3f8e503d51d7df42e55c8282b59154" } diff --git a/devtools/x/src/cargo.rs b/devtools/x/src/cargo.rs index c88a026dc3..e84800b9a1 100644 --- a/devtools/x/src/cargo.rs +++ b/devtools/x/src/cargo.rs @@ -104,13 +104,13 @@ impl Cargo { SelectedInclude::Workspace => { self.inner.arg("--workspace"); for &e in &packages.excludes { - self.inner.args(&["--exclude", e]); + self.inner.args(["--exclude", e]); } } SelectedInclude::Includes(includes) => { for &p in includes { if !packages.excludes.contains(p) { - self.inner.args(&["--package", p]); + self.inner.args(["--package", p]); } } } @@ -326,7 +326,7 @@ impl<'a> CargoCommand<'a> { Ok(vec![]) } else { let mut cargo = self.prepare_cargo(packages); - cargo.args(&["--message-format", "json-render-diagnostics"]); + cargo.args(["--message-format", "json-render-diagnostics"]); Ok(cargo.run_with_output()?) } } diff --git a/devtools/x/src/config.rs b/devtools/x/src/config.rs index b3b5ac8023..6f28f18bf9 100644 --- a/devtools/x/src/config.rs +++ b/devtools/x/src/config.rs @@ -8,7 +8,7 @@ use determinator::rules::DeterminatorRules; use guppy::graph::summaries::CargoOptionsSummary; use serde::{Deserialize, Serialize}; use std::{ - collections::{HashMap, HashSet}, + collections::HashMap, fs, path::{Path, PathBuf}, }; @@ -130,8 +130,6 @@ pub struct WorkspaceConfig { pub test_only: TestOnlyConfig, /// Exceptions to whitespace linters pub whitespace_exceptions: Vec, - /// Move to Diem dependencies - pub move_to_diem_deps: MoveToDiemDepsConfig, } #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] @@ -158,12 +156,6 @@ pub struct DirectDepDupsConfig { pub allow: Vec, } -#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] -pub struct MoveToDiemDepsConfig { - pub diem_crates_in_language: HashSet, - pub exclude: HashSet, -} - #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] #[serde(rename_all = "kebab-case")] pub struct OverlayConfig { diff --git a/devtools/x/src/installer.rs b/devtools/x/src/installer.rs index ec8d5884b9..1ff62c0690 100644 --- a/devtools/x/src/installer.rs +++ b/devtools/x/src/installer.rs @@ -90,7 +90,7 @@ impl Installer { pub fn install_rustup_component_if_needed(name: &str) -> bool { let mut cmd = Command::new("rustup"); - cmd.args(&["component", "list", "--installed"]); + cmd.args(["component", "list", "--installed"]); let result = cmd.output(); let installed = if let Ok(output) = result { @@ -103,7 +103,7 @@ pub fn install_rustup_component_if_needed(name: &str) -> bool { if !installed { info!("installing rustup component: {}", name); let mut cmd = Command::new("rustup"); - cmd.args(&["component", "add", name]); + cmd.args(["component", "add", name]); if cmd.output().is_ok() { info!("rustup component {} has been installed", name); } else { diff --git a/devtools/x/src/lint/guppy.rs b/devtools/x/src/lint/guppy.rs index cc7e1534c3..6c8bd7f090 100644 --- a/devtools/x/src/lint/guppy.rs +++ b/devtools/x/src/lint/guppy.rs @@ -5,8 +5,7 @@ //! Project and package linters that run queries on guppy. use crate::config::{ - BannedDepsConfig, DirectDepDupsConfig, EnforcedAttributesConfig, MoveToDiemDepsConfig, - OverlayConfig, + BannedDepsConfig, DirectDepDupsConfig, EnforcedAttributesConfig, OverlayConfig, }; use guppy::{ graph::{feature::FeatureFilterFn, PackagePublish}, @@ -14,6 +13,7 @@ use guppy::{ }; use std::{ collections::{BTreeMap, HashMap}, + fmt::Write as FmtWrite, iter, }; use x_core::{WorkspaceStatus, XCoreContext}; @@ -270,9 +270,7 @@ impl<'cfg> ProjectLinter for DirectDepDups<'cfg> { if versions.len() > 1 { let mut msg = format!("duplicate direct dependency '{}':\n", direct_dep); for (version, packages) in versions { - msg.push_str(&format!(" * {} (", version)); - msg.push_str(&packages.join(", ")); - msg.push_str(")\n"); + writeln!(&mut msg, " * {} ({})", version, &packages.join(", ")).unwrap(); } out.write(LintLevel::Error, msg); } @@ -361,12 +359,14 @@ impl<'cfg> PackageLinter for OverlayFeatures<'cfg> { if !overlays.is_empty() { let mut msg = "overlay features enabled by default:\n".to_string(); for (from_feature, to_package, to_feature) in overlays { - msg.push_str(&format!( - " * {} -> {}/{}\n", + writeln!( + &mut msg, + " * {} -> {}/{}", feature_str(from_feature), to_package, feature_str(to_feature) - )); + ) + .unwrap(); } msg.push_str("Use a line in the [features] section instead.\n"); out.write(LintLevel::Error, msg); @@ -510,75 +510,3 @@ impl PackageLinter for CratesInCratesDirectory { Ok(RunStatus::Executed) } } - -// Ensure that Move crates do not depend on Diem crates. -#[derive(Debug)] -pub struct MoveCratesDontDependOnDiemCrates<'cfg> { - config: &'cfg MoveToDiemDepsConfig, -} - -impl<'cfg> MoveCratesDontDependOnDiemCrates<'cfg> { - pub fn new(config: &'cfg MoveToDiemDepsConfig) -> Self { - Self { config } - } -} - -impl<'cfg> Linter for MoveCratesDontDependOnDiemCrates<'cfg> { - fn name(&self) -> &'static str { - "move-crates-dont-depend-on-diem-crates" - } -} - -impl<'cfg> PackageLinter for MoveCratesDontDependOnDiemCrates<'cfg> { - fn run<'l>( - &self, - ctx: &PackageContext<'l>, - out: &mut LintFormatter<'l, '_>, - ) -> Result> { - let metadata = ctx.metadata(); - - let crate_name = metadata.name(); - let crate_path = metadata.source().to_string(); - - // Determine if a crate is considered a Move crate or Diem crate. - // - // Current criteria: - // 1. All crates outside language are considered Diem crates. - // 2. All crates inside language are considered Move crates, unless marked otherwise. - let is_move_crate = |crate_path: &str, crate_name: &str| { - if crate_path.starts_with("language/") { - if self.config.diem_crates_in_language.contains(crate_name) { - return false; - } - return true; - } - false - }; - - if is_move_crate(&crate_path, crate_name) { - for direct_dep in metadata.direct_links() { - let dep = direct_dep.to(); - let dep_name = dep.name(); - - if dep.in_workspace() - && !self.config.exclude.contains(dep_name) - && !is_move_crate(&dep.source().to_string(), dep_name) - { - println!("(\"{}\", \"{}\"),", crate_name, dep_name); - out.write( - LintLevel::Error, - format!( - "depending on non-move crate `{}`\n\ - Note: all crates in language/ are considered Move crates by default. \ - If you are creating a new Diem crate in language, you need to add its name to the \ - diem_crates_in_language list in x.toml to make the linter recognize it.", - dep_name - ), - ); - } - } - } - - Ok(RunStatus::Executed) - } -} diff --git a/devtools/x/src/lint/mod.rs b/devtools/x/src/lint/mod.rs index f26f445b5c..d0fac9e655 100644 --- a/devtools/x/src/lint/mod.rs +++ b/devtools/x/src/lint/mod.rs @@ -37,7 +37,6 @@ pub fn run(args: Args, xctx: XContext) -> crate::Result<()> { &guppy::PublishedPackagesDontDependOnUnpublishedPackages::new(xctx.core()), &guppy::OnlyPublishToCratesIo, &guppy::CratesInCratesDirectory, - &guppy::MoveCratesDontDependOnDiemCrates::new(&workspace_config.move_to_diem_deps), &workspace_classify::DefaultOrTestOnly::new( xctx.core().package_graph()?, &workspace_config.test_only, diff --git a/devtools/x/src/test.rs b/devtools/x/src/test.rs index 1ee8d11194..ccc39df9c9 100644 --- a/devtools/x/src/test.rs +++ b/devtools/x/src/test.rs @@ -146,13 +146,13 @@ pub fn run(mut args: Args, xctx: XContext) -> Result<()> { } if let Some(html_cov_dir) = &args.html_cov_dir { - create_dir_all(&html_cov_dir)?; + create_dir_all(html_cov_dir)?; let html_cov_path = &html_cov_dir.canonicalize()?; info!("created {}", &html_cov_path.to_string_lossy()); exec_grcov(html_cov_path, llvm_profile_path)?; } if let Some(html_lcov_dir) = &args.html_lcov_dir { - create_dir_all(&html_lcov_dir)?; + create_dir_all(html_lcov_dir)?; let html_lcov_path = &html_lcov_dir.canonicalize()?; info!("created {}", &html_lcov_path.to_string_lossy()); exec_lcov(html_lcov_path, llvm_profile_path)?; diff --git a/docker/move-cli/Dockerfile b/docker/move-cli/Dockerfile index dcdb026b87..a3543ff5e6 100644 --- a/docker/move-cli/Dockerfile +++ b/docker/move-cli/Dockerfile @@ -20,6 +20,7 @@ ENV PATH "/opt/cargo/bin:/usr/lib/golang/bin:/opt/bin:${DOTNET_ROOT}:${DOTNET_RO RUN mkdir -p /github/home && \ mkdir -p /opt/cargo/ && \ mkdir -p /opt/git/ && \ + sed -i -e 's/\r$//' /move/scripts/*.sh && \ /move/scripts/dev_setup.sh -t -b -p -y -d -g -n && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* diff --git a/language/benchmarks/Cargo.toml b/language/benchmarks/Cargo.toml index 8398914568..c2becf96cb 100644 --- a/language/benchmarks/Cargo.toml +++ b/language/benchmarks/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/diem/diem" homepage = "https://diem.com" license = "Apache-2.0" publish = false -edition = "2018" +edition = "2021" [dependencies] anyhow = "1.0.52" diff --git a/language/benchmarks/src/move_vm.rs b/language/benchmarks/src/move_vm.rs index 72b4c337e0..46ac387218 100644 --- a/language/benchmarks/src/move_vm.rs +++ b/language/benchmarks/src/move_vm.rs @@ -12,7 +12,7 @@ use move_core_types::{ }; use move_vm_runtime::move_vm::MoveVM; use move_vm_test_utils::BlankStorage; -use move_vm_types::gas_schedule::GasStatus; +use move_vm_types::gas::UnmeteredGasMeter; use once_cell::sync::Lazy; use std::path::PathBuf; @@ -27,6 +27,7 @@ pub fn bench(c: &mut Criterion, fun: &str) { let modules = compile_modules(); let move_vm = MoveVM::new(move_stdlib::natives::all_natives( AccountAddress::from_hex_literal("0x1").unwrap(), + move_stdlib::natives::GasParameters::zeros(), )) .unwrap(); execute(c, &move_vm, modules, fun); @@ -65,7 +66,8 @@ fn execute( let storage = BlankStorage::new(); let sender = CORE_CODE_ADDRESS; let mut session = move_vm.new_session(&storage); - let mut gas_status = GasStatus::new_unmetered(); + + // TODO: we may want to use a real gas meter to make benchmarks more realistic. for module in modules { let mut mod_blob = vec![]; @@ -73,7 +75,7 @@ fn execute( .serialize(&mut mod_blob) .expect("Module serialization error"); session - .publish_module(mod_blob, sender, &mut gas_status) + .publish_module(mod_blob, sender, &mut UnmeteredGasMeter) .expect("Module must load"); } @@ -90,7 +92,7 @@ fn execute( fun_name, vec![], Vec::>::new(), - &mut gas_status, + &mut UnmeteredGasMeter, ) .unwrap_or_else(|err| { panic!( diff --git a/language/changes/4-unit-testing.md b/language/changes/4-unit-testing.md index ef622fd8c5..464d1ce30c 100644 --- a/language/changes/4-unit-testing.md +++ b/language/changes/4-unit-testing.md @@ -112,7 +112,7 @@ $ cargo run --bin move-unit-test .. When running tests, every test will either `PASS`, `FAIL`, or `TIMEOUT`. If a test case fails, the location of the failure along with the function name that caused the failure will be reported if possible. You can see an example of this below. -A test will be marked as timing out if it exceeds the maximum number of instructions that can be executed for any single test. This bound can be changed using the options below, and its default value is set to 5000 instructions. Additionally, while the result of a test is always deterministic, tests are run in parallel by default, so the ordering of test results in a test run is non-deterministic unless running with only one thread (see `OPTIONS` below). +A test will be marked as timing out if it exceeds the maximum gas that can be executed for any single test. When a gas table is not provided, each bytecode instruction is assigned a gas cost of 1 unit. This bound can be changed using the options below, and its default value is set to 5000 gas units. Additionally, while the result of a test is always deterministic, tests are run in parallel by default, so the ordering of test results in a test run is non-deterministic unless running with only one thread (see `OPTIONS` below). There are also a number of options that can be passed to the unit testing binary to fine-tune testing, and to help debug failing tests. These are: @@ -129,7 +129,7 @@ FLAGS: OPTIONS: -f, --filter A filter string to determine which unit tests to run - -i, --instructions Bound the number of Move bytecode instructions that can be executed by any one test [default: 5000] + -i, --gas_limit Bound the amount of gas used by any one test. [default: 1_000_000] -t, --threads Number of threads to use for running tests [default: 8] ARGS: @@ -215,8 +215,8 @@ Running Move unit tests Test result: OK. Total tests: 2; passed: 2; failed: 0 ``` -#### `-i ` or `--instructions ` -This bounds the number of instructions that can be executed for any one test to ``: +#### `-i ` or `--gas_limit ` +This bounds the amount of gas that can be consumed for any one test to ``: ``` cargo run --bin move-unit-test

-i 0 MyModule.move @@ -247,7 +247,7 @@ Test result: FAILED. Total tests: 3; passed: 0; failed: 3 ``` #### `-s` or `--statistics` -With these flags you can gather statistics about the tests run and report the runtime and instructions executed for each test. For example, if we wanted to see the statistics for the tests in the `MyModule` example above: +With these flags you can gather statistics about the tests run and report the runtime and gas used for each test. For example, if we wanted to see the statistics for the tests in the `MyModule` example above: ``` $ cargo run --bin move-unit-test MyModule.move -s @@ -259,7 +259,7 @@ Running tests Test Statistics: ┌───────────────────────────────────────────────┬────────────┬───────────────────────────┐ -│ Test Name │ Time │ Instructions Executed │ +│ Test Name │ Time │ Gas Used │ ├───────────────────────────────────────────────┼────────────┼───────────────────────────┤ │ 0x1::MyModule::make_sure_non_zero_coin_passes │ 0.005 │ 1 │ ├───────────────────────────────────────────────┼────────────┼───────────────────────────┤ diff --git a/language/changes/7-packages.md b/language/changes/7-packages.md index 9ddf636428..dae0e71799 100644 --- a/language/changes/7-packages.md +++ b/language/changes/7-packages.md @@ -267,10 +267,10 @@ NamedAddr = "0xC0FFEE" ## Usage, Artifacts, and Data Structures The Move package system comes with a command line option as part of the Move -CLI `move package `. Unless a +CLI `move `. Unless a particular path is provided, all package commands will run in the current working -directory. The full list of commands and flags for the Move Package CLI can be found by -running `move package --help`. +directory. The full list of commands and flags for the Move CLI can be found by +running `move --help`. ### Usage diff --git a/language/documentation/book/book.toml b/language/documentation/book/book.toml new file mode 100644 index 0000000000..8ead41f879 --- /dev/null +++ b/language/documentation/book/book.toml @@ -0,0 +1,12 @@ +[book] +title = "The Move Book" +description = "Move book maintained by the Move core team." +authors = ["The Move Contributors"] +language = "en" +multilingual = false +src = "src" + +[output.html] +git-repository-url = "https://github.com/move-language/move" +git-repository-icon = "fa-github" +edit-url-template = "https://github.com/move-language/move/edit/main/language/documentation/book/{path}" diff --git a/language/documentation/book/src/abilities.md b/language/documentation/book/src/abilities.md index 8d3c2f9b5a..827147b4e8 100644 --- a/language/documentation/book/src/abilities.md +++ b/language/documentation/book/src/abilities.md @@ -49,9 +49,9 @@ If a value has `key`, all values contained inside of that value have `store`. Th ## Builtin Types -Most primitive, builtin types have `copy`, `drop`, and `store` with the exception of `signer`, which just has `store` +Most primitive, builtin types have `copy`, `drop`, and `store` with the exception of `signer`, which just has `drop` -* `bool`, `u8`, `u64`, `u128`, and `address` all have `copy`, `drop`, and `store`. +* `bool`, `u8`, `u16`, `u32`, `u64`, `u128`, `u256`, and `address` all have `copy`, `drop`, and `store`. * `signer` has `drop` * Cannot be copied and cannot be put into global storage * `vector` may have `copy`, `drop`, and `store` depending on the abilities of `T`. @@ -135,7 +135,7 @@ Here are examples for this conditional system for each ability: ### Example: conditional `copy` -``` +```move struct NoAbilities {} struct S has copy, drop { f: bool } struct Cup has copy, drop, store { item: T } @@ -160,7 +160,7 @@ fun invalid(c_account: Cup, c_n: Cup) { ### Example: conditional `drop` -``` +```move struct NoAbilities {} struct S has copy, drop { f: bool } struct Cup has copy, drop, store { item: T } @@ -187,7 +187,7 @@ fun invalid_unused() { fun invalid_left_in_local(): u64 { let n = Cup { item: NoAbilities {}}; - // Invalid return: 'c_n' has a value + // Invalid return: 'n' has a value // and 'Cup' does not have 'drop' 0 } @@ -195,7 +195,7 @@ fun invalid_left_in_local(): u64 { ### Example: conditional `store` -``` +```move struct Cup has copy, drop, store { item: T } // 'MyInnerResource' is declared with 'store' so all fields need 'store' @@ -214,7 +214,7 @@ struct MyResource has key { ### Example: conditional `key` -``` +```move struct NoAbilities {} struct MyResource has key { f: T } diff --git a/language/documentation/book/src/abort-and-assert.md b/language/documentation/book/src/abort-and-assert.md index 87ed86bafb..ce3e87478e 100644 --- a/language/documentation/book/src/abort-and-assert.md +++ b/language/documentation/book/src/abort-and-assert.md @@ -205,4 +205,3 @@ let b = else abort 42; // ^^^^^^^^ `abort 42` has type `bool` ``` -```` diff --git a/language/documentation/book/src/address.md b/language/documentation/book/src/address.md index 73753bcd1a..88d8b3f5e8 100644 --- a/language/documentation/book/src/address.md +++ b/language/documentation/book/src/address.md @@ -16,7 +16,7 @@ literals. To distinguish when an address is being used in an expression context or not, the syntax when using an address differs depending on the context where it's used: -* When an address is used as an expression the address must be prefixed by the `@` character, i.e., `@`[``](./integers.md)` or `@`. +* When an address is used as an expression the address must be prefixed by the `@` character, i.e., [`@`](./integers.md) or `@`. * Outside of expression contexts, the address may be written without the leading `@` character, i.e., [``](./integers.md) or ``. In general, you can think of `@` as an operator that takes an address from being a namespace item to being an expression item. diff --git a/language/documentation/book/src/coding-conventions.md b/language/documentation/book/src/coding-conventions.md index dc305bd5ac..caea845e41 100644 --- a/language/documentation/book/src/coding-conventions.md +++ b/language/documentation/book/src/coding-conventions.md @@ -4,14 +4,15 @@ This section lays out some basic coding conventions for Move that the Move team ## Naming -- **Module names**: should be lower snake case, e.g., `fixed_point32`, `vector` -- **Type names**: should be camel case if they are not a native type, e.g., `Coin`, `RoleId` -- **Function names**: should be lower snake case, e.g., `destroy_empty` -- **Constant names**: should be upper snake case, e.g., `REQUIRES_CAPABILITY` -- Generic types should be descriptive, or anti-descriptive where appropriate, e.g., `T` or `Element` for the Vector generic type parameter. Most of the time the "main" type in a module should be the same name as the module e.g., `option::Option`, `fixed_point32::FixedPoint32`. -- **Module file names**: should be the same as the module name e.g., `Option.move` +- **Module names**: should be lower snake case, e.g., `fixed_point32`, `vector`. +- **Type names**: should be camel case if they are not a native type, e.g., `Coin`, `RoleId`. +- **Function names**: should be lower snake case, e.g., `destroy_empty`. +- **Constant names**: should be upper camel case and begin with an `E` if they represent error codes (e.g., `EIndexOutOfBounds`) and upper snake case if they represent a non-error value (e.g., `MIN_STAKE`). +- +- **Generic type names**: should be descriptive, or anti-descriptive where appropriate, e.g., `T` or `Element` for the Vector generic type parameter. Most of the time the "main" type in a module should be the same name as the module e.g., `option::Option`, `fixed_point32::FixedPoint32`. +- **Module file names**: should be the same as the module name e.g., `Option.move`. - **Script file names**: should be lower snake case and should match the name of the “main” function in the script. -- **Mixed file names**: If the file contains multiple modules and/or scripts, the file name should be lower_snake_case, where the name does not match any particular module/script inside. +- **Mixed file names**: If the file contains multiple modules and/or scripts, the file name should be lower snake case, where the name does not match any particular module/script inside. ## Imports @@ -19,9 +20,9 @@ This section lays out some basic coding conventions for Move that the Move team - Functions should be imported and used fully qualified from the module in which they are declared, and not imported at the top level. - Types should be imported at the top-level. Where there are name clashes, `as` should be used to rename the type locally as appropriate. -For example, if there is a module +For example, if there is a module: -```move= +```move module 0x1::foo { struct Foo { } const CONST_FOO: u64 = 0; @@ -32,7 +33,7 @@ module 0x1::foo { this would be imported and used as: -```move= +```move module 0x1::bar { use 0x1::foo::{Self, Foo}; @@ -49,7 +50,7 @@ module 0x1::bar { And, if there is a local name-clash when importing two modules: -```move= +```move module other_foo { struct Foo {} ... @@ -58,19 +59,19 @@ module other_foo { module 0x1::importer { use 0x1::other_foo::Foo as OtherFoo; use 0x1::foo::Foo; -.... + ... } ``` ## Comments -- Each module, struct, and public function declaration should be commented -- Move has doc comments `///`, regular single-line comments `//`, block comments `/* */`, and block doc comments `/** */` +- Each module, struct, and public function declaration should be commented. +- Move has doc comments `///`, regular single-line comments `//`, block comments `/* */`, and block doc comments `/** */`. ## Formatting The Move team plans to write an autoformatter to enforce formatting conventions. However, in the meantime: -- Four space indentation should be used except for `script` and `address` blocks whose contents should not be indented -- Lines should be broken if they are longer than 100 characters -- Structs and constants should be declared before all functions in a module +- Four space indentation should be used except for `script` and `address` blocks whose contents should not be indented. +- Lines should be broken if they are longer than 100 characters. +- Structs and constants should be declared before all functions in a module. diff --git a/language/documentation/book/src/constants.md b/language/documentation/book/src/constants.md index 050fc5a147..c59f0107c5 100644 --- a/language/documentation/book/src/constants.md +++ b/language/documentation/book/src/constants.md @@ -65,7 +65,7 @@ module. ## Valid Expressions -Currently, constants are limited to the primitive types `bool`, `u8`, `u64`, `u128`, `address`, and +Currently, constants are limited to the primitive types `bool`, `u8`, `u16`, `u32`, `u64`, `u128`, `u256`, `address`, and `vector`. Future support for other `vector` values (besides the "string"-style literals) will come later. @@ -95,6 +95,7 @@ const SHIFTY: u8 = { (1 << 1) * (1 << 2) * (1 << 3) * (1 << 4) }; const HALF_MAX: u128 = 340282366920938463463374607431768211455 / 2; +const REM: u256 = 57896044618658097711785492504343953926634992332820282019728792003956564819968 % 654321; const EQUAL: bool = 1 == 1; ``` diff --git a/language/documentation/book/src/functions.md b/language/documentation/book/src/functions.md index 5ced412477..9515b2d87f 100644 --- a/language/documentation/book/src/functions.md +++ b/language/documentation/book/src/functions.md @@ -187,6 +187,7 @@ Function names can start with letters `a` to `z` or letters `A` to `Z`. After th fun FOO() {} fun bar_42() {} fun _bAZ19() {} + ^^^^^^ Invalid function name '_bAZ19'. Function names cannot start with '_' ``` ### Type Parameters @@ -322,13 +323,13 @@ fun zero(): u64 { 0 } Here `: u64` indicates that the function's return type is `u64`. -Using tuples, a function can return multiple values +Using tuples, a function can return multiple values: ```move fun one_two_three(): (u64, u64, u64) { (0, 1, 2) } ``` -If no return type is specified, the function has an implicit return type of unit `()`. These functions are equivalent +If no return type is specified, the function has an implicit return type of unit `()`. These functions are equivalent: ```move fun just_unit(): () { () } @@ -336,9 +337,9 @@ fun just_unit() { () } fun just_unit() { } ``` -`script` functions must have a return type of unit `()` +`script` functions must have a return type of unit `()`: -```move= +```move script { fun do_nothing() { } diff --git a/language/documentation/book/src/generics.md b/language/documentation/book/src/generics.md index d74ffd9401..9377c498f0 100644 --- a/language/documentation/book/src/generics.md +++ b/language/documentation/book/src/generics.md @@ -34,7 +34,7 @@ struct Bar has copy, drop { } ``` -[Note that type parameters do not have to be used](#unused-type-parameters) +Note that [type parameters do not have to be used](#unused-type-parameters) ## Type Arguments @@ -42,7 +42,7 @@ struct Bar has copy, drop { When calling a generic function, one can specify the type arguments for the function's type parameters in a list enclosed by a pair of angle brackets. -```move= +```move fun foo() { let x = id(true); } @@ -54,7 +54,7 @@ If you do not specify the type arguments, Move's [type inference](#type-inferenc Similarly, one can attach a list of type arguments for the struct's type parameters when constructing or destructing values of generic types. -```move= +```move fun foo() { let foo = Foo { x: true }; let Foo { x } = foo; @@ -65,17 +65,17 @@ If you do not specify the type arguments, Move's [type inference](#type-inferenc ### Type Argument Mismatch -If you specify the type arguments and they conflict with the actual values supplied, an error will be given +If you specify the type arguments and they conflict with the actual values supplied, an error will be given: -```move= +```move fun foo() { let x = id(true); // error! true is not a u64 } ``` -and similarly +and similarly: -```move= +```move fun foo() { let foo = Foo { x: 0 }; // error! 0 is not a bool let Foo
{ x } = foo; // error! bool is incompatible with address @@ -84,9 +84,9 @@ fun foo() { ## Type Inference -In most cases, the Move compiler will be able to infer the type arguments so you don't have to write them down explicitly. Here's what the examples above would look like if we omit the type arguments. +In most cases, the Move compiler will be able to infer the type arguments so you don't have to write them down explicitly. Here's what the examples above would look like if we omit the type arguments: -```move= +```move fun foo() { let x = id(true); // ^ is inferred @@ -101,7 +101,7 @@ fun foo() { Note: when the compiler is unable to infer the types, you'll need annotate them manually. A common scenario is to call a function with type parameters appearing only at return positions. -```move= +```move address 0x2 { module m { using std::vector; @@ -117,9 +117,9 @@ module m { } ``` -However, the compiler will be able to infer the type if that return value is used later in that function +However, the compiler will be able to infer the type if that return value is used later in that function: -```move= +```move address 0x2 { module m { using std::vector; @@ -141,7 +141,7 @@ does not appear in any field defined in the struct, but is checked statically at compile time. Move allows unused type parameters so the following struct definition is valid: -```move= +```move struct Foo { foo: u64 } @@ -149,7 +149,7 @@ struct Foo { This can be convenient when modeling certain concepts. Here is an example: -```move= +```move address 0x2 { module m { // Currency Specifiers @@ -214,9 +214,9 @@ In this way, arguments to phantom type parameters are not considered when deriving the abilities for generic types, thus avoiding the need for spurious ability annotations. For this relaxed rule to be sound, -Move's type system guarantees that a parameter declared as phantom is either +Move's type system guarantees that a parameter declared as `phantom` is either not used at all in the struct definition, or -it is only used as an argument to type parameters also declared as phantom. +it is only used as an argument to type parameters also declared as `phantom`. #### Declaration @@ -239,7 +239,7 @@ In the first one, the parameter `T1` is not used at all inside the struct definition. In the second one, the parameter `T1` is only used as an argument to a phantom type parameter. -```move= +```move struct S1 { f: u64 } ^^ Ok: T1 does not appear inside the struct definition @@ -252,7 +252,7 @@ struct S2 { f: S1 } The following code shows examples of violations of the rule: -```move= +```move struct S1 { f: T } ^ Error: Not a phantom position @@ -264,22 +264,21 @@ struct S3 { f: S2 } Error: Not a phantom position ``` - #### Instantiation When instantiating a struct, the arguments to phantom parameters are excluded when deriving the struct abilities. For example, consider the following code: -```move= +```move struct S has copy { f: T1 } struct NoCopy {} struct HasCopy has copy {} ``` Consider now the type `S`. -Since `S` is defined with `copy` and all non-phantom arguments have copy -then `S` also has copy. +Since `S` is defined with `copy` and all non-phantom arguments have `copy` +then `S` also has `copy`. #### Phantom Type Parameters with Ability Constraints @@ -290,7 +289,7 @@ the type argument has to satisfy that constraint, even though the parameter is phantom. For example, the following definition is perfectly valid: -```move= +```move struct S {} ``` @@ -306,12 +305,12 @@ This is where constraints come into play: they offer a way to specify what prope Constraints can be imposed on type parameters using the following syntax. -```move= +```move // T is the name of the type parameter T: (+ )* ``` -The `` can be any of the four [abilities](./abilities.md), and a type parameter can be constrained with multiple [abilities](./abilities.md) at once. So all of the following would be valid type parameter declarations +The `` can be any of the four [abilities](./abilities.md), and a type parameter can be constrained with multiple abilities at once. So all of the following would be valid type parameter declarations: ```move T: copy @@ -323,7 +322,7 @@ T: copy + drop + store + key Constraints are checked at call sites so the following code won't compile. -```move= +```move struct Foo { x: T } struct Bar { x: Foo } @@ -333,7 +332,7 @@ struct Baz { x: Foo } // ^ error! T does not have 'key' ``` -```move= +```move struct R {} fun unsafe_consume(x: T) { @@ -352,7 +351,7 @@ fun foo() { } ``` -```move= +```move struct R {} fun unsafe_double(x: T) { @@ -367,11 +366,11 @@ fun double(x: T) { fun foo(): (R, R) { let r = R {}; double(r) - // ^ error! R does not have copy + // ^ error! R does not have 'copy' } ``` -For more information, see the abilities section on [conditional abilities and generic types](./abilities.html#conditional-abilities-and-generic-types) +For more information, see the abilities section on [conditional abilities and generic types](./abilities.html#conditional-abilities-and-generic-types). ## Limitations on Recursions @@ -379,7 +378,7 @@ For more information, see the abilities section on [conditional abilities and ge Generic structs can not contain fields of the same type, either directly or indirectly, even with different type arguments. All of the following struct definitions are invalid: -```move= +```move struct Foo { x: Foo // error! 'Foo' containing 'Foo' } @@ -405,7 +404,7 @@ Move allows generic functions to be called recursively. However, when used in co Allowed: -```move= +```move address 0x2 { module m { struct A {} @@ -427,7 +426,7 @@ module m { Not allowed: -```move= +```move address 0x2 { module m { struct A {} @@ -442,7 +441,7 @@ module m { } ``` -```move= +```move address 0x2 { module n { struct A {} @@ -466,7 +465,7 @@ module n { Note, the check for type level recursions is based on a conservative analysis on the call sites and does NOT take control flow or runtime values into account. -```move= +```move address 0x2 { module m { struct A {} diff --git a/language/documentation/book/src/global-storage-structure.md b/language/documentation/book/src/global-storage-structure.md index 83cf8a2ea0..dc624e60c9 100644 --- a/language/documentation/book/src/global-storage-structure.md +++ b/language/documentation/book/src/global-storage-structure.md @@ -2,7 +2,7 @@ The purpose of Move programs is to [read from and write to](./global-storage-operators.md) tree-shaped persistent global storage. Programs cannot access the filesystem, network, or any other data outside of this tree. -In pseudocode, the global storage looks something like +In pseudocode, the global storage looks something like: ```move struct GlobalStorage { diff --git a/language/documentation/book/src/integers.md b/language/documentation/book/src/integers.md index a78f1a8668..4864d2effc 100644 --- a/language/documentation/book/src/integers.md +++ b/language/documentation/book/src/integers.md @@ -1,17 +1,22 @@ # Integers -Move supports three unsigned integer types: `u8`, `u64`, and `u128`. Values of these types range from 0 to a maximum that depends on the size of the type. +Move supports six unsigned integer types: `u8`, `u16`, `u32`, `u64`, `u128`, and `u256`. Values of these types range from 0 to a maximum that depends on the size of the type. | Type | Value Range | | -------------------------------- | ------------------------ | | Unsigned 8-bit integer, `u8` | 0 to 28 - 1 | +| Unsigned 16-bit integer, `u16` | 0 to 216 - 1 | +| Unsigned 32-bit integer, `u32` | 0 to 232 - 1 | | Unsigned 64-bit integer, `u64` | 0 to 264 - 1 | | Unsigned 128-bit integer, `u128` | 0 to 2128 - 1 | +| Unsigned 256-bit integer, `u256` | 0 to 2256 - 1 | ## Literals Literal values for these types are specified either as a sequence of digits (e.g.,`112`) or as hex literals, e.g., `0xFF`. The type of the literal can optionally be added as a suffix, e.g., `112u8`. If the type is not specified, the compiler will try to infer the type from the context where the literal is used. If the type cannot be inferred, it is assumed to be `u64`. +Number literals can be separated by underscores for grouping and readability. (e.g.,`1_234_5678`, `1_000u128`, `0xAB_CD_12_35`). + If a literal is too large for its specified (or inferred) size range, an error is reported. ### Examples @@ -19,32 +24,42 @@ If a literal is too large for its specified (or inferred) size range, an error i ```move // literals with explicit annotations; let explicit_u8 = 1u8; +let explicit_u16 = 1u16; +let explicit_u32 = 1u32; let explicit_u64 = 2u64; let explicit_u128 = 3u128; +let explicit_u256 = 1u256; +let explicit_u64_underscored = 154_322_973u64; // literals with simple inference let simple_u8: u8 = 1; +let simple_u16: u16 = 1; +let simple_u32: u32 = 1; let simple_u64: u64 = 2; let simple_u128: u128 = 3; +let simple_u256: u256 = 1; // literals with more complex inference let complex_u8 = 1; // inferred: u8 // right hand argument to shift must be u8 let _unused = 10 << complex_u8; -let x: u8 = 0; +let x: u8 = 38; let complex_u8 = 2; // inferred: u8 // arguments to `+` must have the same type let _unused = x + complex_u8; -let complex_u128 = 3; // inferred: u128 +let complex_u128 = 133_876; // inferred: u128 // inferred from function argument type function_that_takes_u128(complex_u128); // literals can be written in hex let hex_u8: u8 = 0x1; +let hex_u16: u16 = 0x1BAE; +let hex_u32: u32 = 0xDEAD80; let hex_u64: u64 = 0xCAFE; let hex_u128: u128 = 0xDEADBEEF; +let hex_u256: u256 = 0x1123_456A_BCDE_F; ``` ## Operations @@ -63,24 +78,23 @@ All arithmetic operations abort instead of behaving in a way that mathematical i | `%` | modular division | The divisor is `0` | `/` | truncating division | The divisor is `0` - ### Bitwise The integer types support the following bitwise operations that treat each number as a series of individual bits, either 0 or 1, instead of as numerical integer values. Bitwise operations do not abort. -| Syntax | Operation | Description -|--------|------------|------------ -| `&` | bitwise and| Performs a boolean and for each bit pairwise -| `|` | bitwise or | Performs a boolean or for each bit pairwise -| `^` | bitwise xor| Performs a boolean exclusive or for each bit pairwise +| Syntax | Operation | Description | +|---------------------|-------------|-------------------------------------------------------| +| `&` | bitwise and | Performs a boolean and for each bit pairwise | +| | | bitwise or | Performs a boolean or for each bit pairwise | +| `^` | bitwise xor | Performs a boolean exclusive or for each bit pairwise | ### Bit Shifts Similar to the bitwise operations, each integer type supports bit shifts. But unlike the other operations, the righthand side operand (how many bits to shift by) must *always* be a `u8` and need not match the left side operand (the number you are shifting). -Bit shifts can abort if the number of bits to shift by is greater than or equal to `8`, `64`, or `128` for `u8`, `u64`, and `u128` respectively. +Bit shifts can abort if the number of bits to shift by is greater than or equal to `8`, `16`, `32`, `64`, `128` or `256` for `u8`, `u16`, `u32`, `u64`, `u128` and `u256` respectively. | Syntax | Operation | Aborts if |--------|------------|---------- @@ -123,13 +137,16 @@ Casts *do not* truncate. Casting will abort if the result is too large for the s |------------|---------------------------------------------------------------------------------|--------------------------------------- | `(e as T)`| Cast integer expression `e` into an integer type `T` | `e` is too large to represent as a `T` -Here, the type of `e` must be `u8`, `u64`, or `u128` and `T` must be `u8`, `u64`, or `u128`. +Here, the type of `e` must be `8`, `16`, `32`, `64`, `128` or `256` and `T` must be `u8`, `u16`, `u32`, `u64`, `u128` oe `u256`. For example: - `(x as u8)` +- `(y as u16)` +- `(873u16 as u32)` - `(2u8 as u64)` - `(1 + 3 as u128)` +- `(4/2 + 12345 as u256)` ## Ownership diff --git a/language/documentation/book/src/introduction.md b/language/documentation/book/src/introduction.md index 997ea0ab05..c2417c517b 100644 --- a/language/documentation/book/src/introduction.md +++ b/language/documentation/book/src/introduction.md @@ -8,8 +8,6 @@ Move takes its cue from [Rust](https://www.rust-lang.org/) by using resource typ Move was designed and created as a secure, verified, yet flexible programming language. The first use of Move is for the implementation of the Diem blockchain. That said, the language is still evolving. Move has the potential to be a language for other blockchains, and even non-blockchain use cases as well. -Given custom Move modules will not be supported at the [launch](https://diem.com/white-paper/#whats-next) of the Diem Payment Network (DPN), we are targeting an early Move Developer persona. - The early Move Developer is one with some programming experience, who wants to begin understanding the core programming language and see examples of its usage. ### Hobbyists diff --git a/language/documentation/book/src/modules-and-scripts.md b/language/documentation/book/src/modules-and-scripts.md index 8705991591..f3580e4ded 100644 --- a/language/documentation/book/src/modules-and-scripts.md +++ b/language/documentation/book/src/modules-and-scripts.md @@ -18,14 +18,14 @@ script { } ``` -A `script` block must start with all of its [use](./uses.md) declarations, followed by any [constants](./constants.md) and (finally) the main +A `script` block must start with all of its [`use`](./uses.md) declarations, followed by any [constants](./constants.md) and (finally) the main [function](./functions.md) declaration. The main function can have any name (i.e., it need not be called `main`), is the only function in a script block, can have any number of arguments, and must not return a value. Here is an example with each of these components: ```move script { - // Import the Debug module published at the named account address std. + // Import the debug module published at the named account address std. use std::debug; const ONE: u64 = 1; @@ -41,7 +41,7 @@ Scripts have very limited power—they cannot declare friends, struct types or a ### Modules -A Module has the following syntax: +A module has the following syntax: ```text module
:: { @@ -54,11 +54,11 @@ where `
` is a valid [named or literal address](./address.md). For example: ```move -module 0x42::Test { +module 0x42::test { struct Example has copy, drop { i: u64 } use std::debug; - friend 0x42::AnotherTest; + friend 0x42::another_test; const ONE: u64 = 1; @@ -70,19 +70,19 @@ module 0x42::Test { } ``` -The `module 0x42::Test` part specifies that the module `Test` will be published under the [account address](./address.md) `0x42` in [global storage](./global-storage-structure.md). +The `module 0x42::test` part specifies that the module `test` will be published under the [account address](./address.md) `0x42` in [global storage](./global-storage-structure.md). Modules can also be declared using [named addresses](./address.md). For example: ```move module test_addr::test { - struct Example has copy, drop { a: address} + struct Example has copy, drop { a: address } use std::debug; friend test_addr::another_test; public fun print() { - let example = Example { a: @test_addr}; + let example = Example { a: @test_addr }; debug::print(&example) } } @@ -92,7 +92,7 @@ Because named addresses only exist at the source language level and during compi named addresses will be fully substituted for their value at the bytecode level. For example if we had the following code: -```move= +```move script { fun example() { my_addr::m::foo(@my_addr); @@ -103,7 +103,7 @@ script { and we compiled it with `my_addr` set to `0xC0FFEE`, then it would be equivalent to the following operationally: -```move= +```move script { fun example() { 0xC0FFEE::m::foo(@0xC0FFEE); @@ -112,7 +112,7 @@ script { ``` However at the source level, these _are not equivalent_—the function -`M::foo` _must_ be accessed through the `MyAddr` named address, and not through +`m::foo` _must_ be accessed through the `my_addr` named address, and not through the numerical value assigned to that address. Module names can start with letters `a` to `z` or letters `A` to `Z`. After the first character, module names can contain underscores `_`, letters `a` to `z`, letters `A` to `Z`, or digits `0` to `9`. @@ -122,10 +122,10 @@ module my_module {} module foo_bar_42 {} ``` -Typically, module names start with an uppercase letter. A module named `my_module` should be stored in a source file named `my_module.move`. +Typically, module names start with an lowercase letter. A module named `my_module` should be stored in a source file named `my_module.move`. All elements inside a `module` block can appear in any order. Fundamentally, a module is a collection of [`types`](./structs-and-resources.md) and [`functions`](./functions.md). -[Uses](./uses.md) import types from other modules. -[Friends](./friends.md) specify a list of trusted modules. -[Constants](./constants.md) define private constants that can be used in the functions of a module. +The [`use`](./uses.md) keyword is used to import types from other modules. +The [`friend`](./friends.md) keyword specifies a list of trusted modules. +The [`const`](./constants.md) keyword defines private constants that can be used in the functions of a module. diff --git a/language/documentation/book/src/packages.md b/language/documentation/book/src/packages.md index 82f95666b4..c4abace5ca 100644 --- a/language/documentation/book/src/packages.md +++ b/language/documentation/book/src/packages.md @@ -122,6 +122,7 @@ individually: ### Declaration Let's say we have a Move module in `example_pkg/sources/A.move` as follows: + ```move module named_addr::A { public fun x(): address { @named_addr } @@ -248,10 +249,10 @@ named_addr = "0xC0FFEE" ## Usage, Artifacts, and Data Structures The Move package system comes with a command line option as part of the Move -CLI `move package `. Unless a +CLI `move `. Unless a particular path is provided, all package commands will run in the current working -directory. The full list of commands and flags for the Move Package CLI can be found by -running `move package --help`. +directory. The full list of commands and flags for the Move CLI can be found by +running `move --help`. ### Usage diff --git a/language/documentation/book/src/references.md b/language/documentation/book/src/references.md index eb57079a50..57a5b99e1f 100644 --- a/language/documentation/book/src/references.md +++ b/language/documentation/book/src/references.md @@ -94,7 +94,7 @@ A mutable reference can be used in a context where an immutable reference is exp ```move let x = 7; -let y: &mut u64 = &mut x; +let y: &u64 = &mut x; ``` This works because the under the hood, the compiler inserts `freeze` instructions where they are diff --git a/language/documentation/book/src/signer.md b/language/documentation/book/src/signer.md index 0707ff957a..820963c8b2 100644 --- a/language/documentation/book/src/signer.md +++ b/language/documentation/book/src/signer.md @@ -26,7 +26,7 @@ However, `signer` values are special because they cannot be created via literals instructions--only by the Move VM. Before the VM runs a script with parameters of type `signer`, it will automatically create `signer` values and pass them into the script: -```move= +```move script { use std::signer; fun main(s: signer) { @@ -37,10 +37,10 @@ script { This script will abort with code `0` if the script is sent from any address other than `0x42`. -A transaction script can have an arbitrary number of `signer`s as long as the signers are a prefix -to any other arguments. In other words, all of the signer arguments must come first: +A transaction script can have an arbitrary number of `signer`s as long as the `signer`s are a prefix +to any other arguments. In other words, all of the `signer` arguments must come first: -```move= +```move script { use std::signer; fun main(s1: signer, s2: signer, x: u64, y: u8) { @@ -57,10 +57,10 @@ swap between `s1` and `s2`. The `std::signer` standard library module provides two utility functions over `signer` values: -| Function | Description | -| ------------------------------------------- | ------------------------------------------------------------- | -| `signer::address_of(&signer): address` | Return the `address` wrapped by this `&signer`. | -| `signer::borrow_address(&signer): &address` | Return a reference to the `address` wrapped by this `&signer` | +| Function | Description | +| ------------------------------------------- | ------------------------------------------------------------- | +| `signer::address_of(&signer): address` | Return the `address` wrapped by this `&signer`. | +| `signer::borrow_address(&signer): &address` | Return a reference to the `address` wrapped by this `&signer`. | In addition, the `move_to(&signer, T)` [global storage operator](./global-storage-operators.md) requires a `&signer` argument to publish a resource `T` under `signer.address`'s account. This @@ -70,4 +70,4 @@ ensures that only an authenticated user can elect to publish a resource under th Unlike simple scalar values, `signer` values are not copyable, meaning they cannot be copied (from any operation whether it be through an explicit [`copy`](./variables.md#move-and-copy) instruction -or through a [dereference `*`](./references.md#reference-operators)). +or through a [dereference `*`](./references.md#reading-and-writing-through-references). diff --git a/language/documentation/book/src/standard-library.md b/language/documentation/book/src/standard-library.md index 8f17814977..7dcd8f2251 100644 --- a/language/documentation/book/src/standard-library.md +++ b/language/documentation/book/src/standard-library.md @@ -486,12 +486,10 @@ Used for extension points, should be not used under most circumstances. Construc ## fixed_point32 - The `fixed_point32` module defines a fixed-point numeric type with 32 integer bits and 32 fractional bits. Internally, this is represented as a `u64` integer wrapped in a struct to make a unique `fixed_point32` type. Since the numeric representation is a binary one, some decimal values may not be exactly representable, but it provides more than 9 decimal digits of precision both before and after the decimal point (18 digits total). For comparison, double precision floating-point has less than 16 decimal digits of precision, so you should be careful about using floating-point to convert these values to decimal. ### Types - Represents a fixed-point numeric number with 32 fractional bits. ```move diff --git a/language/documentation/book/src/structs-and-resources.md b/language/documentation/book/src/structs-and-resources.md index ba73d2f1d6..a073a44cd4 100644 --- a/language/documentation/book/src/structs-and-resources.md +++ b/language/documentation/book/src/structs-and-resources.md @@ -32,7 +32,7 @@ module m { Structs cannot be recursive, so the following definition is invalid: -```move= +```move struct Foo { x: Foo } // ^ error! Foo cannot contain Foo ``` @@ -42,7 +42,7 @@ to be used with certain operations (that copy it, drop it, store it in global st a storage schema), structs can be granted [abilities](./abilities.md) by annotating them with `has `: -```move= +```move address 0x2 { module m { struct Foo has copy, drop { x: u64, y: bool } @@ -54,7 +54,7 @@ For more details, see the [annotating structs](./abilities.md#annotating-structs ### Naming -Structs must start with a capital letter `A` to `Z`. After the first letter, constant names can +Structs must start with a capital letter `A` to `Z`. After the first letter, struct names can contain underscores `_`, letters `a` to `z`, letters `A` to `Z`, or digits `0` to `9`. ```move @@ -73,7 +73,7 @@ features. It may or may not be removed later. Values of a struct type can be created (or "packed") by indicating the struct name, followed by value for each field: -```move= +```move address 0x2 { module m { struct Foo has drop { x: u64, y: bool } @@ -102,7 +102,7 @@ This is called sometimes called "field name punning". Struct values can be destroyed by binding or assigning them patterns. -```move= +```move address 0x2 { module m { struct Foo { x: u64, y: bool } @@ -122,6 +122,7 @@ module m { fun example_destroy_foo_wildcard() { let foo = Foo { x: 3, y: false }; let Foo { x, y: _ } = foo; + // only one new binding since y was bound to a wildcard // x: u64 = 3 } @@ -130,6 +131,7 @@ module m { let x: u64; let y: bool; Foo { x, y } = Foo { x: 3, y: false }; + // mutating existing variables x & y // x = 3, y = false } @@ -137,6 +139,7 @@ module m { fun example_foo_ref() { let foo = Foo { x: 3, y: false }; let Foo { x, y } = &foo; + // two new bindings // x: &u64 // y: &bool @@ -145,6 +148,7 @@ module m { fun example_foo_ref_mut() { let foo = Foo { x: 3, y: false }; let Foo { x, y } = &mut foo; + // two new bindings // x: &mut u64 // y: &mut bool @@ -154,9 +158,10 @@ module m { let bar = Bar { foo: Foo { x: 3, y: false } }; let Bar { foo: Foo { x, y } } = bar; // ^ nested pattern + // two new bindings // x: u64 = 3 - // foo_y: bool = false + // y: bool = false } fun example_destroy_baz() { @@ -172,7 +177,7 @@ module m { The `&` and `&mut` operator can be used to create references to structs or fields. These examples include some optional type annotations (e.g., `: &Foo`) to demonstrate the type of operations. -```move= +```move let foo = Foo { x: 3, y: true }; let foo_ref: &Foo = &foo; let y: bool = foo_ref.y; // reading a field via a reference to the struct @@ -182,18 +187,18 @@ let x_ref_mut: &mut u64 = &mut foo.x; *x_ref_mut = 42; // modifying a field via a mutable reference ``` -It is possible to borrow inner fields of nested structs. +It is possible to borrow inner fields of nested structs: -```move= +```move let foo = Foo { x: 3, y: true }; let bar = Bar { foo }; let x_ref = &bar.foo.x; ``` -You can also borrow a field via a reference to a struct. +You can also borrow a field via a reference to a struct: -```move= +```move let foo = Foo { x: 3, y: true }; let foo_ref = &foo; let x_ref = &foo_ref.x; @@ -202,9 +207,9 @@ let x_ref = &foo_ref.x; ### Reading and Writing Fields -If you need to read and copy a field's value, you can then dereference the borrowed field +If you need to read and copy a field's value, you can then dereference the borrowed field: -```move= +```move let foo = Foo { x: 3, y: true }; let bar = Bar { foo: copy foo }; let x: u64 = *&foo.x; @@ -215,37 +220,37 @@ let foo2: Foo = *&bar.foo; If the field is implicitly copyable, the dot operator can be used to read fields of a struct without any borrowing. (Only scalar values with the `copy` ability are implicitly copyable.) -```move= +```move let foo = Foo { x: 3, y: true }; let x = foo.x; // x == 3 let y = foo.y; // y == true ``` -Dot operators can be chained to access nested fields. +Dot operators can be chained to access nested fields: -```move= +```move let baz = Baz { foo: Foo { x: 3, y: true } }; let x = baz.foo.x; // x = 3; ``` However, this is not permitted for fields that contain non-primitive types, such a vector or another -struct +struct: -```move= +```move let foo = Foo { x: 3, y: true }; let bar = Bar { foo }; let foo2: Foo = *&bar.foo; -let foo3: Foo = bar.foo; // error! add an explicit copy with *& +let foo3: Foo = bar.foo; // error! must add an explicit copy with *& ``` The reason behind this design decision is that copying a vector or another struct might be an expensive operation. It is important for a programmer to be aware of this copy and make others aware -with the explicit syntax `*&` +with the explicit syntax `*&`. In addition reading from fields, the dot syntax can be used to modify fields, regardless of the -field being a primitive type or some other struct +field being a primitive type or some other struct. -```move= +```move let foo = Foo { x: 3, y: true }; foo.x = 42; // foo = Foo { x: 42, y: true } foo.y = !foo.y; // foo = Foo { x: 42, y: false } @@ -254,9 +259,9 @@ bar.foo.x = 52; // bar = Bar { foo: Foo { x: 52, y: false } } bar.foo = Foo { x: 62, y: true }; // bar = Bar { foo: Foo { x: 62, y: true } } ``` -The dot syntax also works via a reference to a struct +The dot syntax also works via a reference to a struct: -```move= +```move let foo = Foo { x: 3, y: true }; let foo_ref = &mut foo; foo_ref.x = foo_ref.x + 1; @@ -272,11 +277,11 @@ Most struct operations on a struct type `T` can only be performed inside the mod - The fields of a struct are only accessible inside the module that defines the struct. Following these rules, if you want to modify your struct outside the module, you will need to -provide publis APIs for them. The end of the chapter contains some examples of this. +provide public APIs for them. The end of the chapter contains some examples of this. However, struct _types_ are always visible to another module or script: -```move= +```move // m.move address 0x2 { module m { @@ -289,7 +294,7 @@ module m { } ``` -```move= +```move // n.move address 0x2 { module n { @@ -320,7 +325,7 @@ ephemeral. This means they cannot be copied or dropped. This property can be ver modeling real world resources like money, as you do not want money to be duplicated or get lost in circulation. -```move= +```move address 0x2 { module m { struct Foo { x: u64 } @@ -347,10 +352,10 @@ module m { } ``` -To fix the second example (`fun dropping_resource`), you would need to manually "unpack" the +To fix the second example (`fun destroying_resource1`), you would need to manually "unpack" the resource: -```move= +```move address 0x2 { module m { struct Foo { x: u64 } @@ -370,7 +375,7 @@ If on the other hand, your struct does not represent something valuable, you can `copy` and `drop` to get a struct value that might feel more familiar from other programming languages: -```move= +```move address 0x2 { module m { struct Foo has copy, drop { x: u64 } @@ -394,19 +399,19 @@ module m { Only structs with the `key` ability can be saved directly in [persistent global storage](./global-storage-operators.md). All values stored within those `key` -structs must have the `store` abilities. See the [ability](./abilities] and +structs must have the `store` ability. See the [ability](./abilities) and [global storage](./global-storage-operators.md) chapters for more detail. ## Examples Here are two short examples of how you might use structs to represent valuable data (in the case of -`Coin`) or more classical data (in the case of `Point` and `Circle`) +`Coin`) or more classical data (in the case of `Point` and `Circle`). ### Example 1: Coin -```move= +```move address 0x2 { module m { // We do not want the Coin to be copied because that would be duplicating this "money", @@ -422,7 +427,7 @@ module m { public fun mint(value: u64): Coin { // You would want to gate this function with some form of access control to prevent - // anyone using this module from minting an infinite amount of coins + // anyone using this module from minting an infinite amount of coins. Coin { value } } @@ -457,7 +462,7 @@ module m { ### Example 2: Geometry -```move= +```move address 0x2 { module point { struct Point has copy, drop, store { @@ -497,10 +502,10 @@ module point { } ``` -```move= +```move address 0x2 { module circle { - use 0x2::Point::{Self, Point}; + use 0x2::point::{Self, Point}; struct Circle has copy, drop, store { center: Point, @@ -512,7 +517,7 @@ module circle { } public fun overlaps(c1: &Circle, c2: &Circle): bool { - let d = Point::dist_squared(&c1.center, &c2.center); + let d = point::dist_squared(&c1.center, &c2.center); let r1 = c1.radius; let r2 = c2.radius; d*d <= r1*r1 + 2*r1*r2 + r2*r2 diff --git a/language/documentation/book/src/tuples.md b/language/documentation/book/src/tuples.md index 1bf9d8e147..1f4575b817 100644 --- a/language/documentation/book/src/tuples.md +++ b/language/documentation/book/src/tuples.md @@ -1,13 +1,13 @@ # Tuples and Unit Move does not fully support tuples as one might expect coming from another language with them as a -first-class value. However, in order to support multiple return values, Move has tuple-like +[first-class value](https://en.wikipedia.org/wiki/First-class_citizen). However, in order to support multiple return values, Move has tuple-like expressions. These expressions do not result in a concrete value at runtime (there are no tuples in the bytecode), and as a result they are very limited: they can only appear in expressions (usually in the return position for a function); they cannot be bound to local variables; they cannot be stored in structs; and tuple types cannot be used to instantiate generics. -Similarly, unit `()` is a type created by the Move source language in order to be expression based. +Similarly, [unit `()`](https://en.wikipedia.org/wiki/Unit_type) is a type created by the Move source language in order to be expression based. The unit value `()` does not result in any runtime value. We can consider unit`()` to be an empty tuple, and any restrictions that apply to tuples also apply to unit. @@ -21,7 +21,7 @@ multiple return values are represented using tuples. ## Literals -Tuples are created by a comma separated list of expressions inside of parentheses +Tuples are created by a comma separated list of expressions inside of parentheses. | Syntax | Type | Description | | --------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------ | @@ -37,19 +37,19 @@ Sometimes, tuples with two elements are called "pairs" and tuples with three ele ### Examples -```move= +```move address 0x42 { module example { // all 3 of these functions are equivalent // when no return type is provided, it is assumed to be `()` - fun returs_unit_1() { } + fun returns_unit_1() { } // there is an implicit () value in empty expression blocks - fun returs_unit_2(): () { } + fun returns_unit_2(): () { } - // explicit version of `returs_unit_1` and `returs_unit_2` - fun returs_unit_3(): () { () } + // explicit version of `returns_unit_1` and `returns_unit_2` + fun returns_unit_3(): () { () } fun returns_3_values(): (u64, bool, address) { @@ -72,7 +72,7 @@ For tuples of any size, they can be destructured in either a `let` binding or in For example: -```move= +```move address 0x42 { module example { // all 3 of these functions are equivalent @@ -107,23 +107,25 @@ For more details, see [Move Variables](./variables.md). ## Subtyping -Along with references, tuples are the only types that have subtyping in Move. Tuples do have +Along with references, tuples are the only types that have [subtyping](https://en.wikipedia.org/wiki/Subtyping) in Move. Tuples do have subtyping only in the sense that subtype with references (in a covariant way). -For example +For example: -```move= +```move let x: &u64 = &0; let y: &mut u64 = &mut 1; // (&u64, &mut u64) is a subtype of (&u64, &u64) -// since &mut u64 is a subtype of &u64 +// since &mut u64 is a subtype of &u64 let (a, b): (&u64, &u64) = (x, y); + // (&mut u64, &mut u64) is a subtype of (&u64, &u64) -// since &mut u64 is a subtype of &u64 +// since &mut u64 is a subtype of &u64 let (c, d): (&u64, &u64) = (y, y); + // error! (&u64, &mut u64) is NOT a subtype of (&mut u64, &mut u64) -// since &u64 is NOT a subtype of &mut u64 +// since &u64 is NOT a subtype of &mut u64 let (e, f): (&mut u64, &mut u64) = (x, y); ``` diff --git a/language/documentation/book/src/unit-testing.md b/language/documentation/book/src/unit-testing.md index db64a94869..75649da190 100644 --- a/language/documentation/book/src/unit-testing.md +++ b/language/documentation/book/src/unit-testing.md @@ -95,7 +95,7 @@ fun test_only_function(...) { ... } ## Running Unit Tests -Unit tests for a Move package can be run with the [`move package test` +Unit tests for a Move package can be run with the [`move test` command](./packages.md). When running tests, every test will either `PASS`, `FAIL`, or `TIMEOUT`. If a test case fails, the location of the failure along with the function name that caused the failure will be reported if possible. You can see an example of this below. @@ -105,7 +105,7 @@ A test will be marked as timing out if it exceeds the maximum number of instruct There are also a number of options that can be passed to the unit testing binary to fine-tune testing and to help debug failing tests. These can be found using the the help flag: ``` -$ move package -h +$ move -h ``` ## Example @@ -113,8 +113,9 @@ $ move package -h A simple module using some of the unit testing features is shown in the following example: First create an empty package and change directory into it: + ``` -$ move package new TestExample; cd TestExample +$ move new TestExample; cd TestExample ``` Next add the following to the `Move.toml`: @@ -173,10 +174,10 @@ module 0x1::my_module { ### Running Tests -You can then run these tests with the `move package test` command: +You can then run these tests with the `move test` command: ``` -$ move package test +$ move test BUILDING MoveStdlib BUILDING TestExample Running Move unit tests @@ -192,7 +193,7 @@ Test result: OK. Total tests: 3; passed: 3; failed: 0 This will only run tests whose fully qualified name contains ``. For example if we wanted to only run tests with `"zero_coin"` in their name: ``` -$ move package test -f zero_coin +$ move test -f zero_coin CACHED MoveStdlib BUILDING TestExample Running Move unit tests @@ -201,11 +202,11 @@ Running Move unit tests Test result: OK. Total tests: 2; passed: 2; failed: 0 ``` -#### `-i ` or `--instructions ` -This bounds the number of instructions that can be executed for any one test to ``: +#### `-i ` or `--gas_used ` +This bounds the amount of gas that can be consumed for any one test to ``: ``` -$ move package test -i 0 +$ move test -i 0 CACHED MoveStdlib BUILDING TestExample Running Move unit tests @@ -235,10 +236,10 @@ Test result: FAILED. Total tests: 3; passed: 0; failed: 3 ``` #### `-s` or `--statistics` -With these flags you can gather statistics about the tests run and report the runtime and instructions executed for each test. For example, if we wanted to see the statistics for the tests in the example above: +With these flags you can gather statistics about the tests run and report the runtime and gas used for each test. For example, if we wanted to see the statistics for the tests in the example above: ``` -$ move package test -s +$ move test -s CACHED MoveStdlib BUILDING TestExample Running Move unit tests @@ -249,7 +250,7 @@ Running Move unit tests Test Statistics: ┌────────────────────────────────────────────────┬────────────┬───────────────────────────┐ -│ Test Name │ Time │ Instructions Executed │ +│ Test Name │ Time │ Gas Used │ ├────────────────────────────────────────────────┼────────────┼───────────────────────────┤ │ 0x1::my_module::make_sure_non_zero_coin_passes │ 0.009 │ 1 │ ├────────────────────────────────────────────────┼────────────┼───────────────────────────┤ @@ -276,10 +277,10 @@ module 0x1::my_module { } ``` -we would get get the following output when running the tests: +we would get the following output when running the tests: ``` -$ move package test -g +$ move test -g CACHED MoveStdlib BUILDING TestExample Running Move unit tests diff --git a/language/documentation/book/src/uses.md b/language/documentation/book/src/uses.md index 87d1914760..5e7edf8d9f 100644 --- a/language/documentation/book/src/uses.md +++ b/language/documentation/book/src/uses.md @@ -252,7 +252,7 @@ module example { Inside a given scope, all aliases introduced by `use` declarations must be unique. -For a module, this means aliases introduced by `use` cannot overla +For a module, this means aliases introduced by `use` cannot overlap ```move= address 0x42 { diff --git a/language/documentation/book/src/variables.md b/language/documentation/book/src/variables.md index b6cbaaf70e..e16738adbc 100644 --- a/language/documentation/book/src/variables.md +++ b/language/documentation/book/src/variables.md @@ -99,7 +99,7 @@ let x: T = e; // "Variable x of type T is initialized to expression e" Some examples of explicit type annotations: -```move= +```move address 0x42 { module example { @@ -315,7 +315,7 @@ fun three(): (u64, u64, u64) { ```move let (x1, _, z1) = three(); let (x2, _y, z2) = three(); -assert!(x1 + z1 == x2 + z2) +assert!(x1 + z1 == x2 + z2, 42); ``` This can be necessary at times as the compiler will error on unused local variables @@ -401,7 +401,7 @@ if (cond) x = 1 else x = 2; The assignment uses the same pattern syntax scheme as `let` bindings: -```move= +```move address 0x42 { module example { struct X { f: u64 } @@ -442,8 +442,7 @@ reference `&mut`. let x = 0; let r = &mut x; *r = 1; -assert!(x == 1, 42) -} +assert!(x == 1, 42); ``` This is particularly useful if either: @@ -469,7 +468,7 @@ This sort of modification is how you modify structs and vectors! ```move let v = vector::empty(); vector::push_back(&mut v, 100); -assert!(*vector::borrow(&v, 0) == 100, 42) +assert!(*vector::borrow(&v, 0) == 100, 42); ``` For more details, see [Move references](./references.md). @@ -566,7 +565,7 @@ explicitly destroyed within its declaring module.) ``` If a final expression is not present in a block---that is, if there is a trailing semicolon `;`, -there is an implicit unit `()` value. Similarly, if the expression block is empty, there is an +there is an implicit [unit `()` value](https://en.wikipedia.org/wiki/Unit_type). Similarly, if the expression block is empty, there is an implicit unit `()` value. ```move diff --git a/language/documentation/book/src/vector.md b/language/documentation/book/src/vector.md index 54a2808658..ad18a7e919 100644 --- a/language/documentation/book/src/vector.md +++ b/language/documentation/book/src/vector.md @@ -23,7 +23,7 @@ specified explicitly: ```move vector[]: vector -vecctor[e1, ..., en]: vector +vector[e1, ..., en]: vector ``` #### Example Vector Literals @@ -43,14 +43,14 @@ result. These values are so common that specific syntax is provided to make the readable, as opposed to having to use `vector[]` where each individual `u8` value is specified in numeric form. -There are currently two supported types of `vector` literals, byte strings and hex strings. +There are currently two supported types of `vector` literals, *byte strings* and *hex strings*. #### Byte Strings Byte strings are quoted string literals prefixed by a `b`, e.g. `b"Hello!\n"`. These are ASCII encoded strings that allow for escape sequences. Currently, the supported escape -sequences are +sequences are: | Escape Sequence | Description | | --------------- | ---------------------------------------------- | @@ -64,10 +64,10 @@ sequences are #### Hex Strings -Hex strings are quoted string literals prefixed by a `x`, e.g. `x"48656C6C6F210A"` +Hex strings are quoted string literals prefixed by a `x`, e.g. `x"48656C6C6F210A"`. Each byte pair, ranging from `00` to `FF`, is interpreted as hex encoded `u8` value. So each byte -pair corresponds to a single entry in the resulting `vector` +pair corresponds to a single entry in the resulting `vector`. #### Example String Literals @@ -91,24 +91,24 @@ fun byte_and_hex_strings() { `vector` supports the following operations via the `std::vector` module in the Move standard library: -| Function | Description | Aborts? | -| ---------------------------------------------------------- | ------------------------------------------------------------- | ----------------------- | -| `vector::empty(): vector` | Create an empty vector that can store values of type `T` | Never | -| `vector::singleton(t: T): vector` | Create a vector of size 1 containing `t` | Never | -| `vector::push_back(v: &mut vector, t: T)` | Add `t` to the end of `v` | Never | -| `vector::pop_back(v: &mut vector): T` | Remove and return the last element in `v` | If `v` is empty | -| `vector::borrow(v: &vector, i: u64): &T` | Return an immutable reference to the `T` at index `i` | If `i` is not in bounds | -| `vector::borrow_mut(v: &mut vector, i: u64): &mut T` | Return an mutable reference to the `T` at index `i` | If `i` is not in bounds | -| `vector::destroy_empty(v: vector)` | Delete `v` | If `v` is not empty | -| `vector::append(v1: &mut vector, v2: vector)` | Add the elements in `v2` to the end of `v1` | If `i` is not in bounds | -| `vector::contains(v: &vector, e: &T): bool` | Return true if `e` is in the vector `v` | Never | -| `vector::swap(v: &mut vector, i: u64, j: u64)` | Swaps the elements at the `i`th and `j`th indices in the vector `v`.| If `i` or `j` is out of bounds | -| `vector::reverse(v: &mut vector)` | Reverses the order of the elements in the vector `v` in place | Never | -| `vector::index_of(v: &vector, e: &T): bool` | Return `(true, i)` if `e` is in the vector `v` at index `i`. Otherwise, returns `(false, 0)`.| Never | -| `vector::remove(v: &mut vector, i: u64): T` | Remove the `i`th element of the vector `v`, shifting all subsequent elements. This is O(n) and preserves ordering of elements in the vector. | If `i` is out of bounds. | -| `vector::swap_remove(v: &mut vector, i: u64): T` | Swap the `i`th element of the vector `v` with the last element and then pop the vector, This is O(1), but does not preserve ordering of elements in the vector. | If `i` is out of bounds. | - -More operations may be added overtime +| Function | Description | Aborts? | +| ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | +| `vector::empty(): vector` | Create an empty vector that can store values of type `T` | Never | +| `vector::singleton(t: T): vector` | Create a vector of size 1 containing `t` | Never | +| `vector::push_back(v: &mut vector, t: T)` | Add `t` to the end of `v` | Never | +| `vector::pop_back(v: &mut vector): T` | Remove and return the last element in `v` | If `v` is empty | +| `vector::borrow(v: &vector, i: u64): &T` | Return an immutable reference to the `T` at index `i` | If `i` is not in bounds | +| `vector::borrow_mut(v: &mut vector, i: u64): &mut T` | Return a mutable reference to the `T` at index `i` | If `i` is not in bounds | +| `vector::destroy_empty(v: vector)` | Delete `v` | If `v` is not empty | +| `vector::append(v1: &mut vector, v2: vector)` | Add the elements in `v2` to the end of `v1` | Never | +| `vector::contains(v: &vector, e: &T): bool` | Return true if `e` is in the vector `v`. Otherwise, returns false | Never | +| `vector::swap(v: &mut vector, i: u64, j: u64)` | Swaps the elements at the `i`th and `j`th indices in the vector `v` | If `i` or `j` is out of bounds | +| `vector::reverse(v: &mut vector)` | Reverses the order of the elements in the vector `v` in place | Never | +| `vector::index_of(v: &vector, e: &T): (bool, u64)` | Return `(true, i)` if `e` is in the vector `v` at index `i`. Otherwise, returns `(false, 0)` | Never | +| `vector::remove(v: &mut vector, i: u64): T` | Remove the `i`th element of the vector `v`, shifting all subsequent elements. This is O(n) and preserves ordering of elements in the vector | If `i` is out of bounds | +| `vector::swap_remove(v: &mut vector, i: u64): T` | Swap the `i`th element of the vector `v` with the last element and then pop the element, This is O(1), but does not preserve ordering of elements in the vector | If `i` is out of bounds | + +More operations may be added over time. ## Example @@ -166,4 +166,4 @@ For more details see the sections on [type abilities](./abilities.md) and [gener As mentioned [above](#destroying-and-copying-vectors), `vector` values can be copied only if the elements can be copied. In that case, the copy must be explicit via a -[`copy`](./variables.md#move-and-copy) or a [dereference `*`](./references.md#reference-operators). +[`copy`](./variables.md#move-and-copy) or a [dereference `*`](./references.md#reading-and-writing-through-references). diff --git a/language/documentation/book/translations/move-book-zh/.gitignore b/language/documentation/book/translations/move-book-zh/.gitignore new file mode 100644 index 0000000000..7585238efe --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/.gitignore @@ -0,0 +1 @@ +book diff --git a/language/documentation/book/translations/move-book-zh/CONTRIBUTING.md b/language/documentation/book/translations/move-book-zh/CONTRIBUTING.md new file mode 100644 index 0000000000..8d7724ea56 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/CONTRIBUTING.md @@ -0,0 +1,74 @@ +# Contributing to Move Book Chinese Version + +感谢您有兴趣为**《Move Book 中文版》**做出贡献!有很多方法可以做出贡献,我们感谢所有这些方式。 + +本翻译项目由 [*Move 中文社区(MoveCC)*](https://github.com/move-cc)[发起](https://github.com/move-language/move/issues/353),并与 [MoveDAO 社区](https://github.com/move-dao)共同初步完善。 + +目前工作仍在进行中! + +欢迎所有对 Move 感兴趣的朋友一起加入到《Move Book 中文版》的翻译工作中。 + +## 提交 PR 的 Commits 格式 + +```text +[move-book-zh] 关于这个 PR 的描述信息 +``` + +## 文档规范 + +请参考:[中文技术文档的写作规范](https://github.com/ruanyf/document-style-guide) + +### 断句 + +本书使用 Markdown 作为源文件,使用 [mdBook](https://github.com/rust-lang/mdBook) 作为渲染引擎。 + +由于中英文有所区别,换行后渲染引擎会自动追加一个空格。为了优化视觉体验,中文一个段落内不必换行,保持中文的段内容为一个物理行。 + +英文是由空格分隔的文本,所以不存在上述问题。 + +### 中英文混排规范 + +文中出现中英文混排时,中文与英文之间需要添加一个空格。如果英文单词结尾,此时单词与标点符号之间不添加空格。 + +### 数字规范 + +数字之间需要添加一个空格,如果数字带有英文单位,那么数字与英文单位之间不能添加空格。如果数字后带有中文单位,需要添加一个空格。 + +```text +正确:如果一个 1s 的帧被划分为 10 个时隙,每个时隙为 100ms。 + +错误:如果一个1s的帧被划分为10个时隙,每个时隙为100ms。 + +错误:如果一个 1 s 的帧被划分为10个时隙,每个时隙为 100 ms。 +``` + +### 逗号问题 + +英文中,没有顿号这种标点符号,逗号常用分隔并列的句子成分或结构。 + +英文中,像 `and` 并列词的前面通常会有一个 `,`,但在中文里表示对象之间的并列关系时,`和`的前面不能带逗号。 + +```text +War, famine, and flood are terrible. +战争, 饥荒和洪水都是很可怕的。 +``` + +### 冒号和逗号的使用场景规范 + +冒号通常用在“问、答、说、指出、宣布、证明、表明、例如”一类动词后面,表示提起下文。 +如果在较短的提示句子中,需要将 `:` 改为 `,`;如果提示内容比较多,则使用 `:` 来提起下文: + +示例1,提起的内容短少: + +```text +十六进制字符串是以 x 为前缀的带引号的字符串文字,例如x'48656C6C6F210A' +``` + +示例2,提起的内容多: + +```text +在这些情况下,vector 的类型是从元素类型或从动态数组的使用上推断出来的。如果无法推断类型或者只是为了更清楚地表示,则可以显式指定类型: + +vector[]: vector +vector[e1, ..., en]: vector +``` diff --git a/language/documentation/book/translations/move-book-zh/README.md b/language/documentation/book/translations/move-book-zh/README.md new file mode 100644 index 0000000000..9de276331c --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/README.md @@ -0,0 +1,73 @@ +## 参与贡献的重要提示 + +《Move Book 中文版》翻译工作还在持续进行中,如果你愿意贡献你的一份力量,欢迎提交 pr 或 issue。 + +为了方便翻译工作的进行,在提交 pr 时请不要删除英文原文的内容! + +在贡献之前请阅读[官方的贡献指南](https://github.com/move-language/move/blob/main/CONTRIBUTING.md)和[《Move Book 中文版》的贡献指南](./CONTRIBUTING.md)。 + +# Move Book 中文版 + +区块链技术的发展经历了两个阶段,比特币(BTC)开启了*区块链1.0时代*,以太坊(ETH)开启了*区块链2.0时代*。 +以太坊的出现为区块链带来了*智能合约*这一关键技术,让区块链不只停留在记账这一单的目的,而是带来更多的应用拓展性。 +遗憾的是,智能合约如同一把双刃剑,在带来众多丰富功能拓展的同时,也容易让智能合约开发者无意间引入不安全的代码,让链的资产受到威胁。 + +编写简单、安全、易部署的智能合约应该是*区块链3.0时代*应该关注的重点,**面向资源编程**的 [Move 语言](https://github.com/move-language/move),无疑给这个问题提供了一个很好的解决方案。 + +本书是 [Move Book](https://move-language.github.io/move/) 的中文版。 + +## 快速开始 + +本书使用 [mdBook](https://rust-lang.github.io/mdBook/) 构建。 + +1. 使用 Cargo 安装 mdBook: + +```shell +cargo install mdbook +``` + +2. 下载 + +```shell +git clone https://github.com/move-language/move.git +``` + +3. 构建并预览 + +```shell +cd language/documentation/book/translations/move-book-zh +mdbook serve --open +``` + +## Contributors ✨ + +[各章节译者](Translators.md) + +Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): + + + + + + + + + + + + + + + + + + + + + +

zhang

💻 📖 🌍 🚇

ruyisu

💻 🌍 📖 🚇

lshoo

💻 🌍 📖 🤔 👀

Container

💻 🌍 📖 👀

nosalt

💻 🌍 📖 🚇

geometryolife

💻 🌍 📢

666thi

💻 🌍 📢

MagicGordon

💻 🌍 📢

xixifusi1984

💻 🌍 📢

yvvw

💻 🌍 📢

xiaochuan891102

💻 🌍 📢

stephenLee

💻 🌍 📢
+ + + + + diff --git a/language/documentation/book/translations/move-book-zh/Translators.md b/language/documentation/book/translations/move-book-zh/Translators.md new file mode 100644 index 0000000000..35bce4ce50 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/Translators.md @@ -0,0 +1,30 @@ +| | 章节 | 译者 | 校对 | +|----|----------------------------|------------------------------------------------|-------------------------------------------------------------------------------------| +| 0 | Intoduction | Tom | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 1 | Modules and Scripts | [@Kusou1](https://github.com/kusou1) | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 2 | Move Tutorial | loadi、[@leego](https://github.com/leego) | [@Joe Chen](https://github.com/geometryolife) | +| 3 | Integers | Tom | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 4 | Bool | Tom | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 5 | Address | ([@stephenLee](https://github.com/stephenLee)) | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 6 | Vector | ([@stephenLee](https://github.com/stephenLee)) | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 7 | Signer | ([@stephenLee](https://github.com/stephenLee)) | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 8 | References | container | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 9 | Tuples and Unit | container | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 10 | Local Variables and Scopes | @ruyisu | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 11 | Equality | @ruyisu | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 12 | Abort and Assert | @ruyisu | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 13 | Conditionals | [@Kusou1](https://github.com/kusou1) | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 14 | While and Loop | [@Kusou1](https://github.com/kusou1) | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 15 | Functions | @nosalt99 | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 16 | Structs and Resource | @nosalt99 | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 17 | Constants | @nosalt99 | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 18 | Generics | 小川 | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 19 | Type Abilities | 小川 | [@lshoo](https://github.com/lshoo)、[@Joe Chen](https://github.com/geometryolife) | +| 20 | Uses and Aliases | 小川 | [@ruyisu](https://github.com/ruy1su)、[@Joe Chen](https://github.com/geometryolife) | +| 21 | Friends | @xiaochuan891102 | [@ruyisu](https://github.com/ruy1su)、[@Joe Chen](https://github.com/geometryolife) | +| 22 | Packages | @xiaochuan891102 | [@ruyisu](https://github.com/ruy1su)、[@Joe Chen](https://github.com/geometryolife) | +| 23 | Unit Test | [@yvvw](https://github.com/yvvw) | [@ruyisu](https://github.com/ruy1su)、[@Joe Chen](https://github.com/geometryolife) | +| 24 | Global Storage Structure | [@yvvw](https://github.com/yvvw) | [@ruyisu](https://github.com/ruy1su)、[@Joe Chen](https://github.com/geometryolife) | +| 25 | Global Storage Operators | [@yvvw](https://github.com/yvvw) | [@ruyisu](https://github.com/ruy1su)、[@Joe Chen](https://github.com/geometryolife) | +| 26 | Standard Library | @MagicGordon | [@ruyisu](https://github.com/ruy1su)、[@Joe Chen](https://github.com/geometryolife) | +| 27 | Coding Conventions | @MagicGordon | [@ruyisu](https://github.com/ruy1su)、[@Joe Chen](https://github.com/geometryolife) | diff --git a/language/documentation/book/translations/move-book-zh/book.toml b/language/documentation/book/translations/move-book-zh/book.toml new file mode 100644 index 0000000000..1f51aef586 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/book.toml @@ -0,0 +1,7 @@ +[book] +authors = ["The Move Contributors"] +description = "Move book maintained by the Move Chinese contributors." +language = "zh" +multilingual = false +src = "src" +title = "Move Book 中文版" diff --git a/language/documentation/book/translations/move-book-zh/src/SUMMARY.md b/language/documentation/book/translations/move-book-zh/src/SUMMARY.md new file mode 100644 index 0000000000..4b75899b44 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/SUMMARY.md @@ -0,0 +1,45 @@ +# The Move Programming Language + +[引言(Introduction)](introduction.md) + +## Getting Started + +- [模块和脚本(Modules and Scripts)](modules-and-scripts.md) +- [Move 教程(Move Tutorial)](move-tutorial.md) + +## Primitive Types + +- [整数(Integers)](integers.md) +- [布尔类型(Bool)](bool.md) +- [地址(Address)](address.md) +- [向量(Vector)](vector.md) +- [签名(Signer)](signer.md) +- [引用(References)](references.md) +- [元组和单值(Tuples and Unit)](tuples.md) + +## Basic Concepts + +- [局部变量和作用域(Local Variables and Scopes)](variables.md) +- [等式(Equality)](equality.md) +- [中止和断言(Abort and Assert)](abort-and-assert.md) +- [条件语句(Conditionals)](conditionals.md) +- [循环(While and Loop)](loops.md) +- [函数(Functions)](functions.md) +- [结构体和资源(Structs and Resources)](structs-and-resources.md) +- [常量(Constants)](constants.md) +- [泛型(Generics)](generics.md) +- [类型能力(Type Abilities)](abilities.md) +- [导入和别名(Uses and Aliases)](uses.md) +- [友元函数(Friends)](friends.md) +- [程序包(Packages)](packages.md) +- [单元测试(Unit Tests)](unit-testing.md) + +## Global Storage + +- [全局存储结构(Global Storage Structure)](global-storage-structure.md) +- [全局存储操作(Global Storage Operators)](global-storage-operators.md) + +## Reference + +- [标准库(Standard Library)](standard-library.md) +- [Move 编码约定(Coding Conventions)](coding-conventions.md) diff --git a/language/documentation/book/translations/move-book-zh/src/abilities.md b/language/documentation/book/translations/move-book-zh/src/abilities.md new file mode 100644 index 0000000000..440362288e --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/abilities.md @@ -0,0 +1,321 @@ +# 能力 (abilities) + +Abilities are a typing feature in Move that control what actions are permissible for values of a given type. This system grants fine grained control over the "linear" typing behavior of values, as well as if and how values are used in global storage. This is implemented by gating access to certain bytecode instructions so that for a value to be used with the bytecode instruction, it must have the ability required (if one is required at all—not every instruction is gated by an ability). + +能力是 Move 语言中的一种类型特性,用于控制对给定类型的值允许哪些操作。 该系统对值的“线性”类型行为以及值如何在全局存储中使用提供细粒度控制。这是通过对某些字节码指令的进行访问控制来实现的,因此对于要与字节码指令一起使用的值,它必须具有所需的能力(如果需要的话,并非每条指令都由能力控制) + +## 四种能力 (The Four Abilities) + +The four abilities are: + +* [`copy`](#copy) + * Allows values of types with this ability to be copied. +* [`drop`](#drop) + * Allows values of types with this ability to be popped/dropped. +* [`store`](#store) + * Allows values of types with this ability to exist inside a struct in global storage. +* [`key`](#key) + * Allows the type to serve as a key for global storage operations. + +这四种能力分别是: + +* [`copy`](#copy) 复制 + * 允许此类型的值被复制 + +* [`drop`](#drop) 丢弃 + * 允许此类型的值被弹出/丢弃 + +* [`store`](#store) 存储 + * 允许此类型的值存在于全局存储的某个结构体中 + +* [`key`](#key) 键值 + * 允许此类型作为全局存储中的键(具有 `key` 能力的类型才能保存到全局存储中) + + +### `copy` + +The `copy` ability allows values of types with that ability to be copied. It gates the ability to copy values out of local variables with the [`copy`](./variables.md#move-and-copy) operator and to copy values via references with [dereference `*e`](./references.md#reading-and-writing-through-references). + +If a value has `copy`, all values contained inside of that value have `copy`. + +`copy` 能力允许具有此能力的类型的值被复制。 它限制了从本地变量通过 [`copy`](./variables.md#.move-and-copy)能力复制值以及通过 [`dereference *e`](./references.html#reading-and-writing-through-references)复制值这两种情况之外的复制操作。 + +如果一个值具有 `copy` 能力,那么这个值内部的所有值都有 `copy` 能力。 + +### `drop` + +The `drop` ability allows values of types with that ability to be dropped. By dropped, we mean that value is not transferred and is effectively destroyed as the Move program executes. As such, this ability gates the ability to ignore values in a multitude of locations, including: +* not using the value in a local variable or parameter +* not using the value in a [sequence via `;`](./variables.md#expression-blocks) +* overwriting values in variables in [assignments](./variables.md#assignments) +* overwriting values via references when [writing `*e1 = e2`](./references.md#reading-and-writing-through-references). + +If a value has `drop`, all values contained inside of that value have `drop`. + +`drop` 能力允许类型的值被丢弃。丢弃的意思程序执行后值会被有效的销毁而不必被转移。因此,这个能力限制在多个位置忽略使用值的可能性,包括: +* 未被使用的局部变量或者参数 +* 未被使用的 [`sequence` via `;`](./variables.md#expression-blocks)中的值 +* 覆盖[赋值(assignments)](./variables.html#assignments)变量中的值 +* [写入(writing) `*e1 = e2`](https://move-language.github.io/move/references.html#reading-and-writing-through-references) 时通过引用覆盖的值。 + +如果一个值具有 `drop` 能力,那么这个值内部的所有值都有 `drop` 能力。 + +### `store` + +The `store` ability allows values of types with this ability to exist inside of a struct (resource) in global storage, *but* not necessarily as a top-level resource in global storage. This is the only ability that does not directly gate an operation. Instead it gates the existence in global storage when used in tandem with `key`. + +If a value has `store`, all values contained inside of that value have `store` + +`store` 能力允许具有这种能力的类型的值位于[全局存储](./global-storage-operators.html)中的结构体(资源)内, *但不一定是* 全局存储中的顶级资源。这是唯一不直接限制操作的能力。相反,当(`store`)与 `key` 一起使用时,它对全局存储中的可行性进行把关。。 + +如果一个值具有 `store` 能力,那么这个值内部的所有值都有 `store` 能力。 + +### `key` + +The `key` ability allows the type to serve as a key for [global storage operations](./global-storage-operators.md). It gates all global storage operations, so in order for a type to be used with `move_to`, `borrow_global`, `move_from`, etc., the type must have the `key` ability. Note that the operations still must be used in the module where the `key` type is defined (in a sense, the operations are private to the defining module). + +If a value has `key`, all values contained inside of that value have `store`. This is the only ability with this sort of asymmetry. + +`key` 能力允许此类型作为[全局存储](./global-storage-operators.html)中的键。它会限制所有[全局存储](./global-storage-operators.html)中的操作,因此一个类型如果与 `move_to`, `borrow_global`, `move_from` 等一起使用,那么这个类型必须具备 `key` 能力。请注意,这些操作仍然必须在定义 `key` 类型的模块中使用(从某种意义上说,这些操作是此模块的私有操作)。 + +如果有一个值有 `key` 能力,那么这个值包含的所有字段值也都具有 `store` 能力,`key` 能力是唯一一个具有非对称的能力。 + +## Builtin Types (内置类型) + + +Most primitive, builtin types have `copy`, `drop`, and `store` with the exception of `signer`, which just has `store` + +* `bool`, `u8`, `u64`, `u128`, and `address` all have `copy`, `drop`, and `store`. +* `signer` has `drop` + * Cannot be copied and cannot be put into global storage +* `vector` may have `copy`, `drop`, and `store` depending on the abilities of `T`. + * See [Conditional Abilities and Generic Types](#conditional-abilities-and-generic-types) for more details. +* Immutable references `&` and mutable references `&mut` both have `copy` and `drop`. + * This refers to copying and dropping the reference itself, not what they refer to. + * References cannot appear in global storage, hence they do not have `store`. + +None of the primitive types have `key`, meaning none of them can be used directly with the [global storage operations](./global-storage-operators.md). + +几乎所有内置的基本类型具都有 `copy`,`drop`,以及 `store` 能力,`singer` 除外,它只有 `drop` 能力(原文是 `store` 有误,译者注) + +* `bool`, `u8`, `u64`, `u128`, `address` 都具有 `copy`, `drop`, 以及 `store` 能力。 +* `signer` 具有 `drop` 能力。 不能被复制以及不能被存放在全局存储中 +* `vector` 可能具有 `copy`,`drop`,以及`store` 能力,这依赖于 `T` 具有的能力。 查看 [条件能力与泛型类型](#conditional-abilities-and-generic-types)获取详情 +* 不可变引用 `&` 和可变引用 `&mut` 都具有 `copy` 和 `drop` 能力。 + * 这是指复制和删除引用本身,而不是它们所引用的内容。 + * 引用不能出现在全局存储中,因此它们没有 `store` 能力。 + +所有基本类型都没有 `key`,这意味着它们都不能直接用于[全局存储操作](./global-storage-operators.html)。 + +## Annotating Structs (标注结构体) + +To declare that a `struct` has an ability, it is declared with `has ` after the struct name but before the fields. For example: + +要声明一个 `struct` 具有某个能力,它在结构体名称之后, 在字段之前用 `has ` 声明。例如: + +```move +struct Ignorable has drop { f: u64 } +struct Pair has copy, drop, store { x: u64, y: u64 } +``` + +In this case: `Ignorable` has the `drop` ability. `Pair` has `copy`, `drop`, and `store`. + +在这个例子中:`Ignorable` 具有 `drop` 能力。 `Pair` 具有 `copy`、`drop` 和 `store` 能力。 + +All of these abilities have strong guarantees over these gated operations. The operation can be performed on the value only if it has that ability; even if the value is deeply nested inside of some other collection! + +所有这些能力对这些访问操作都有强有力的保证。只有具有该能力,才能对值执行对应的操作;即使该值深层嵌套在其他集合中! + +As such: when declaring a struct’s abilities, certain requirements are placed on the fields. All fields must satisfy these constraints. These rules are necessary so that structs satisfy the reachability rules for the abilities given above. If a struct is declared with the ability... + +* `copy`, all fields must have `copy`. +* `drop`, all fields must have `drop`. +* `store`, all fields must have `store`. +* `key`, all fields must have `store`. + * `key` is the only ability currently that doesn’t require itself. + +因此:在声明结构体的能力时,对字段提出了某些要求。所有字段都必须满足这些约束。这些规则是必要的,以便结构体满足上述功能的可达性规则。如果一个结构被声明为具有某能力: + +* `copy`, 所有的字段必须具有 `copy` 能力。 +* `drop`,所有的字段必须具有 `drop` 能力。 +* `store`,所有的字段必须具有 `store` 能力。 +* `key`,所有的字段必须具有 `store` 能力。`key` 是目前唯一不需要包含自身的能力。 + +例如: + +```move +// A struct without any abilities +struct NoAbilities {} + +struct WantsCopy has copy { + f: NoAbilities, // ERROR 'NoAbilities' does not have 'copy' +} +``` + +and similarly: + +类似的: + +```move +// A struct without any abilities +struct NoAbilities {} + +struct MyResource has key { + f: NoAbilities, // Error 'NoAbilities' does not have 'store' +} +``` + +## Conditional Abilities and Generic Types (条件能力与泛型类型) + +When abilities are annotated on a generic type, not all instances of that type are guaranteed to have that ability. Consider this struct declaration: + +在泛型类型上标注能力时,并非该类型的所有实例都保证具有该能力。考虑这个结构体声明: + +```move +struct Cup has copy, drop, store, key { item: T } +``` + + +It might be very helpful if `Cup` could hold any type, regardless of its abilities. The type system can *see* the type parameter, so it should be able to remove abilities from `Cup` if it *sees* a type parameter that would violate the guarantees for that ability. + +This behavior might sound a bit confusing at first, but it might be more understandable if we think about collection types. We could consider the builtin type `vector` to have the following type declaration: + +如果 `Cup` 可以容纳任何类型,可能会很有帮助,不管它的能力如何。类型系统可以 *看到* 类型参数,因此,如果它 *发现* 一个类型参数违反了对该能力的保证,它应该能够从 `Cup` 中删除能力。 + +这种行为一开始可能听起来有点令人困惑,但如果我们考虑一下集合类型,它可能会更容易理解。我们可以认为内置类型 `Vector` 具有以下类型声明: + +```move +vector has copy, drop, store; +``` + +We want `vector`s to work with any type. We don't want separate `vector` types for different abilities. So what are the rules we would want? Precisely the same that we would want with the field rules above. So, it would be safe to copy a `vector` value only if the inner elements can be copied. It would be safe to ignore a `vector` value only if the inner elements can be ignored/dropped. And, it would be safe to put a `vector` in global storage only if the inner elements can be in global storage. + +To have this extra expressiveness, a type might not have all the abilities it was declared with depending on the instantiation of that type; instead, the abilities a type will have depends on both its declaration **and** its type arguments. For any type, type parameters are pessimistically assumed to be used inside of the struct, so the abilities are only granted if the type parameters meet the requirements described above for fields. Taking `Cup` from above as an example: + +* `Cup` has the ability `copy` only if `T` has `copy`. +* It has `drop` only if `T` has `drop`. +* It has `store` only if `T` has `store`. +* It has `key` only if `T` has `store`. + +我们希望 `vector` 适用于任何类型。我们不希望针对不同的能力使用不同的 `vector` 类型。那么我们想要的规则是什么?与上面的字段规则完全相同。因此,仅当可以复制内部元素时,复制`vector` 值才是安全的。仅当可以忽略/丢弃内部元素时,忽略 `vector` 值才是安全的。而且,仅当内部元素可以在全局存储中时,将向量放入全局存储中才是安全的。 + +为了具有这种额外的表现力,一个类型可能不具备它声明的所有能力,具体取决于该类型的实例化;相反,一个类型的能力取决于它的声明 **和** 它的类型参数。对于任何类型,类型参数都被悲观地假定为在结构体内部使用,因此只有在类型参数满足上述字段要求时才授予这些能力。以上面的 `Cup` 为例: + +* `Cup` 拥有 `copy` 能力 仅当 `T` 拥有 `copy` 能力时。 +* `Cup` 拥有 `drop` 能力 仅当 `T` 拥有 `drop` 能力时。 +* `Cup` 拥有 `store` 能力 仅当 `T` 拥有 `store` 能力时。 +* `Cup` 拥有 `key` 能力 仅当 `T` 拥有 `store` 能力时。 + +Here are examples for this conditional system for each ability: + +以下是每个能力的条件系统的示例: + +### Example: conditional `copy` + +```move +struct NoAbilities {} +struct S has copy, drop { f: bool } +struct Cup has copy, drop, store { item: T } + +fun example(c_x: Cup, c_s: Cup) { + // Valid, 'Cup' has 'copy' because 'u64' has 'copy' + let c_x2 = copy c_x; + // Valid, 'Cup' has 'copy' because 'S' has 'copy' + let c_s2 = copy c_s; +} + +fun invalid(c_account: Cup, c_n: Cup) { + // Invalid, 'Cup' does not have 'copy'. + // Even though 'Cup' was declared with copy, the instance does not have 'copy' + // because 'signer' does not have 'copy' + let c_account2 = copy c_account; + // Invalid, 'Cup' does not have 'copy' + // because 'NoAbilities' does not have 'copy' + let c_n2 = copy c_n; +} +``` + +### Example: conditional `drop` + +```move +struct NoAbilities {} +struct S has copy, drop { f: bool } +struct Cup has copy, drop, store { item: T } + +fun unused() { + Cup { item: true }; // Valid, 'Cup' has 'drop' + Cup { item: S { f: false }}; // Valid, 'Cup' has 'drop' +} + +fun left_in_local(c_account: Cup): u64 { + let c_b = Cup { item: true }; + let c_s = Cup { item: S { f: false }}; + // Valid return: 'c_account', 'c_b', and 'c_s' have values + // but 'Cup', 'Cup', and 'Cup' have 'drop' + 0 +} + +fun invalid_unused() { + // Invalid, Cannot ignore 'Cup' because it does not have 'drop'. + // Even though 'Cup' was declared with 'drop', the instance does not have 'drop' + // because 'NoAbilities' does not have 'drop' + Cup { item: NoAbilities {}}; +} + +fun invalid_left_in_local(): u64 { + let n = Cup { item: NoAbilities {}}; + // Invalid return: 'c_n' has a value + // and 'Cup' does not have 'drop' + 0 +} +``` + +### Example: conditional `store` + +```move +struct Cup has copy, drop, store { item: T } + +// 'MyInnerResource' is declared with 'store' so all fields need 'store' +struct MyInnerResource has store { + yes: Cup, // Valid, 'Cup' has 'store' + // no: Cup, Invalid, 'Cup' does not have 'store' +} + +// 'MyResource' is declared with 'key' so all fields need 'store' +struct MyResource has key { + yes: Cup, // Valid, 'Cup' has 'store' + inner: Cup, // Valid, 'Cup' has 'store' + // no: Cup, Invalid, 'Cup' does not have 'store' +} +``` + +### Example: conditional `key` + +```move +struct NoAbilities {} +struct MyResource has key { f: T } + +fun valid(account: &signer) acquires MyResource { + let addr = signer::address_of(account); + // Valid, 'MyResource' has 'key' + let has_resource = exists>(addr); + if (!has_resource) { + // Valid, 'MyResource' has 'key' + move_to(account, MyResource { f: 0 }) + }; + // Valid, 'MyResource' has 'key' + let r = borrow_global_mut>(addr) + r.f = r.f + 1; +} + +fun invalid(account: &signer) { + // Invalid, 'MyResource' does not have 'key' + let has_it = exists>(addr); + // Invalid, 'MyResource' does not have 'key' + let NoAbilities {} = move_from(addr); + // Invalid, 'MyResource' does not have 'key' + move_to(account, NoAbilities {}); + // Invalid, 'MyResource' does not have 'key' + borrow_global(addr); +} +``` diff --git a/language/documentation/book/translations/move-book-zh/src/abort-and-assert.md b/language/documentation/book/translations/move-book-zh/src/abort-and-assert.md new file mode 100644 index 0000000000..314940ee18 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/abort-and-assert.md @@ -0,0 +1,255 @@ +# 中止和断言 (Abort and Assert) + +[`return`](./functions.md) and `abort` are two control flow constructs that end execution, one for +the current function and one for the entire transaction. + +More information on [`return` can be found in the linked section](./functions.md) + +[`return`](./functions.md) 和 `abort` 是两种结束程序执行的控制流结构。前者针对当前函数,后者针对整个事务。 + + [`return`](./functions.md)的更多信息可以参考链接中的文章。 + +## `abort` 中止 + +`abort` is an expression that takes one argument: an **abort code** of type `u64`. For example: + +`abort` 表达式只接受一个参数: 类型为 `u64` 的**中止代码**。例如: + +```move +abort 42 +``` + +The `abort` expression halts execution the current function and reverts all changes made to global +state by the current transaction. There is no mechanism for "catching" or otherwise handling an `abort`. + +`abort` 表达式会中止执行当前函数并恢复当前事务对全局状态所做的所有更改。Move语言没有“捉捕”或者额外处理`abort`的机制。 + +Luckily, in Move transactions are all or nothing, meaning any changes to global storage are made all +at once only if the transaction succeeds. Because of this transactional commitment of changes, after +an abort there is no need to worry about backing out changes. While this approach is lacking in +flexibility, it is incredibly simple and predictable. + +幸运的是,在Move里事务的计算要么完全执行要么完全不执行。这意味着只有在事务成功时,任何对全局存储状态的改变才会被一并执行。 +由于这种对于所有更改的事务承诺,在 `abort` 之后我们不需要担心去回滚任何更改。尽管这种方法缺少灵活性,它还是非常简单和可预测的。 + + +Similar to [`return`](./functions.md), `abort` is useful for exiting control flow when some condition cannot be met. + +In this example, the function will pop two items off of the vector, but will abort early if the vector does not have two items + +与 [`return`](./functions.md)相似, 在一些条件无法被满足的时候,`abort` 可以被用于退出控制流(control flow)。 + +在以下示例中,目标函数会从vector里弹出两个元素,但是如果vector中并没有两个元素,函数会提前中止。 + +```move= +use std::vector; +fun pop_twice(v: &mut vector): (T, T) { + if (vector::length(v) < 2) abort 42; + + (vector::pop_back(v), vector::pop_back(v)) +} +``` + +This is even more useful deep inside a control-flow construct. For example, this function checks +that all numbers in the vector are less than the specified `bound`. And aborts otherwise + +这在控制流结构的深处甚至会更有用。例如,此函数检查vector中是否所有数字都小于指定的边界(`bound`)。否则函数中止: + +```move= +use std::vector; +fun check_vec(v: &vector, bound: u64) { + let i = 0; + let n = vector::length(v); + while (i < n) { + let cur = *vector::borrow(v, i); + if (cur > bound) abort 42; + i = i + 1; + } +} +``` + +### `assert` 断言 + +`assert` is a builtin, macro-like operation provided by the Move compiler. It takes two arguments, a condition of type `bool` and a code of type `u64` + +`assert` 是 Move 编译器提供的内置的类宏(macro-like)操作。它需要两个参数:一个 `bool` 类型的条件和一个 `u64` 类型的错误状态码(类似HTTP中的StatusCode: 404, 500等,译者注) + +```move +assert!(condition: bool, code: u64) +``` + +Since the operation is a macro, it must be invoked with the `!`. This is to convey that the +arguments to `assert` are call-by-expression. In other words, `assert` is not a normal function and +does not exist at the bytecode level. It is replaced inside the compiler with + +由于该操作是一个宏,因此必须使用 `!` 调用它。这是为了表达 `assert` 的参数属于表达式调用(call-by-expression)。换句话说,`assert` 不是一个正常的函数,并且在字节码(bytecode)级别不存在。它在编译器内部被替换为以下代码: + +```move +if (condition) () else abort code +``` + +`assert` is more commonly used than just `abort` by itself. The `abort` examples above can be rewritten using `assert` + +`assert` 比 `abort` 本身更常用。上面的 `abort` 示例可以使用 `assert` 重写 + +```move= +use std::vector; +fun pop_twice(v: &mut vector): (T, T) { + assert!(vector::length(v) >= 2, 42); // 现在使用'assert' + + (vector::pop_back(v), vector::pop_back(v)) +} +``` + +和 + +```move= +use std::vector; +fun check_vec(v: &vector, bound: u64) { + let i = 0; + let n = vector::length(v); + while (i < n) { + let cur = *vector::borrow(v, i); + assert!(cur <= bound, 42); // 现在使用 'assert' + i = i + 1; + } +} +``` + +Note that because the operation is replaced with this `if-else`, the argument for the `code` is not +always evaluated. For example: + +请注意,因为此操作被替换为 `if-else`,这段 `代码` 的参数不是总是被执行(evaluated)。例如: + +```move +assert!(true, 1 / 0) +``` + +Will not result in an arithmetic error, it is equivalent to + +不会导致算术错误,因为它相当于: + +```move +if (true) () else (1 / 0) +``` + +So the arithmetic expression is never evaluated! + +所以这个算术表达式永远不会被执行(evaluated)! + +### Abort codes in the Move VM (Move虚拟机中的中止代码) + +When using `abort`, it is important to understand how the `u64` code will be used by the VM. + +Normally, after successful execution, the Move VM produces a change-set for the changes made to +global storage (added/removed resources, updates to existing resources, etc). + +当使用 `abort` 时,理解虚拟机将如何使用 `u64` 代码是非常重要的。 + +通常,在成功执行后,Move 虚拟机会为对全局存储(添加/删除资源、更新现有资源等)所做的更改生成一个更改集。 + +If an `abort` is reached, the VM will instead indicate an error. Included in that error will be two +pieces of information: + +- The module that produced the abort (address and name) +- The abort code. + +For example + +如果执行到 `abort` 代码,虚拟机将指示错误。该错误中包含两块信息: + +- 发生中止的模块(地址和名称) +- 错误状态码。 + +例如 + +```move= +address 0x2 { + module example { + public fun aborts() { + abort 42 + } + } +} + +script { + fun always_aborts() { + 0x2::example::aborts() + } +} +``` + +If a transaction, such as the script `always_aborts` above, calls `0x2::example::aborts`, the VM +would produce an error that indicated the module `0x2::example` and the code `42`. + +This can be useful for having multiple aborts being grouped together inside a module. + +In this example, the module has two separate error codes used in multiple functions + +如果一个事务,例如上面的脚本 `always_aborts` 调用了 `0x2::example::aborts`,虚拟机将产生一个指示模块 `0x2::example` 和错误状态码 `42` 的错误。 + +这在一个模块内将多个中止功能组合起来会很有用。 + +在以下示例中,模块有两个单独的错误状态码,用于多个函数 + +```move= +address 0x42 { + module example { + + use std::vector; + + const EMPTY_VECTOR: u64 = 0; + const INDEX_OUT_OF_BOUNDS: u64 = 1; + + // 移动 i 到 j, 移动 j 到 k, 移动 k 到 i + public fun rotate_three(v: &mut vector, i: u64, j: u64, k: u64) { + let n = vector::length(v); + assert!(n > 0, EMPTY_VECTOR); + assert!(i < n, INDEX_OUT_OF_BOUNDS); + assert!(j < n, INDEX_OUT_OF_BOUNDS); + assert!(k < n, INDEX_OUT_OF_BOUNDS); + + vector::swap(v, i, k); + vector::swap(v, j, k); + } + + public fun remove_twice(v: &mut vector, i: u64, j: u64): (T, T) { + let n = vector::length(v); + assert!(n > 0, EMPTY_VECTOR); + assert!(i < n, INDEX_OUT_OF_BOUNDS); + assert!(j < n, INDEX_OUT_OF_BOUNDS); + assert!(i > j, INDEX_OUT_OF_BOUNDS); + + (vector::remove(v, i), vector::remove(v, j)) + } + } +} +``` + +## The type of `abort` (`abort` 的类型) + +The `abort i` expression can have any type! This is because both constructs break from the normal +control flow, so they never need to evaluate to the value of that type. + +The following are not useful, but they will type check + +`abort i` 表达式可以有任何类型!这是因为这两种构造都打破了正常控制流,因此他们永远不需要计算该类型的值。 + +以下的示例不是特别有用,但它们会做类型检查 + +```move +let y: address = abort 0; +``` + +This behavior can be helpful in situations where you have a branching instruction that produces a +value on some branches, but not all. For example: + +在您有一个分支指令,并且这个指令会产生某些分支(不是全部)的值的时候,这种行为会非常有用。例如: + +```move +let b = + if (x == 0) false + else if (x == 1) true + else abort 42; +// ^^^^^^^^ `abort 42` 的类型是 `bool` +``` diff --git a/language/documentation/book/translations/move-book-zh/src/address.md b/language/documentation/book/translations/move-book-zh/src/address.md new file mode 100644 index 0000000000..1a5edc9d99 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/address.md @@ -0,0 +1,58 @@ +# 地址 + +`地址(address)`是 Move 中的内置类型,用于表示全局存储中的的位置(有时称为账户)。`地址(address)` 值是一个 128 位(16 字节)标识符。在一个给定的地址,可以存储两样东西:[模块(Module)](./modules-and-scripts.md)和[资源(Resources)](./structs-and-resources.md)。 + +虽然`地址(address)`在底层是一个 128 位整数,但 Move 语言有意让其不透明 —— 它们不能从整数创建,不支持算术运算,也不能修改。即使可能有一些有趣的程序会使用这种特性(例如,C 中的指针算法实现了类似壁龛(niche)的功能),但 Move 语言不允许这种动态行为,因为它从头开始就被设计为支持静态验证。*(壁龛指安装在墙壁上的小格子或在墙身上留出的作为贮藏设施的空间,最早在宗教上是指排放佛像的小空间,现在多用在家庭装修上,因其不占建筑面积,使用比较方便,深受大家喜爱,Joe 注)* + +你可以通过运行时地址值(`address` 类型的值)来访问该地址处的资源。但*无法*在运行时通过地址值访问模块。 + +## 地址及其语法 + +地址有两种形式:*命名的*或*数值的*。命名地址的语法遵循 Move 命名标识符的规则。数值地址的语法不受十六进制编码值的限制,任何有效的 [`u128` 数值](./integers.md)都可以用作地址值。例如,`42`,`0xCFAE` 和 `2021` 都是合法有效的数值地址字面量(literal)。 + +为了区分何时在表达式上下文中使用地址,使用地址时的语法根据使用地址的上下文而有所不同: + +* 当地址被用作表达式时,地址必须以 `@` 字符为前缀,例如:[`@`](./integers.md) 或 `@`。 +* 在表达式上下文之外,地址可以不带前缀字符 `@`。例如:[``](./integers.md) 或 ``。 + +通常,可以将 `@` 视为将地址从命名空间项变为表达式项的运算符。 + +## 命名地址 + +命名地址是一项特性,它允许在使用地址的任何地方使用标识符代替数值,而不仅仅是在值级别。命名地址被声明并绑定为 Move 包中的顶级元素(模块和脚本之外)或作为参数传递给 Move 编译器。 + +命名地址仅存在于源语言级别,并将在字节码级别完全替代它们的值。因此,模块和模块成员*必须*通过模块的命名地址而不是编译期间分配给命名地址的数值来访问,例如:`use my_addr::foo` *不等于* `use 0x2::foo`,即使 Move 程序编译时将 `my_addr` 设置成 `0x2`。这个区别在[模块和脚本](./modules-and-scripts.md)一节中有更详细的讨论。 + +### 例子 + +```move +let a1: address = @0x1; // 0x00000000000000000000000000000001 的缩写 +let a2: address = @0x42; // 0x00000000000000000000000000000042 的缩写 +let a3: address = @0xDEADBEEF; // 0x000000000000000000000000DEADBEEF 的缩写 +let a4: address = @0x0000000000000000000000000000000A; +let a5: address = @std; // 将命名地址 `std` 的值赋给 `a5` +let a6: address = @66; +let a7: address = @0x42; + +module 66::some_module { // 不在表达式上下文中,所以不需要 @ + use 0x1::other_module; // 不在表达式上下文中,所以不需要 @ + use std::vector; // 使用其他模块时,可以使用命名地址作为命名空间项 + ... +} + +module std::other_module { // 可以使用命名地址作为命名空间项来声明模块 + ... +} +``` + +## 全局存储操作 + +`address` 值主要用来与全局存储操作进行交互。 + +`address` 值与 `exists`、`borrow_global`、`borrow_global_mut` 和 `move_from` [操作(operation)](./global-storage-operators.md)一起使用。 + +唯一*不使用* `address` 的全局存储操作是 `move_to`,它使用了 [`signer`](./signer.md)。 + +## 所有权 + +与 Move 语言内置的其他标量值一样,`address` 值是隐式可复制的,这意味着它们可以在没有显式指令(例如 [`copy`](./variables.md#移动和复制))的情况下复制。 diff --git a/language/documentation/book/translations/move-book-zh/src/bool.md b/language/documentation/book/translations/move-book-zh/src/bool.md new file mode 100644 index 0000000000..d49844ddbe --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/bool.md @@ -0,0 +1,49 @@ +# 布尔类型 (Bool) + +`bool`is Move's primitive type for boolean `true` and `false`values. + +`bool` 是 Move 布尔基本类型,有 `true` 和 `false` 两个值。 + +## 字面量 (Literals) + +Literals for `bool` are either `true` or `false` . + +布尔类型字面值只能是 `true` 或者 `false`中的一个 。 + +## 操作 (Operations) + +### 逻辑运算 (Logical) + +`bool`supports three logical operations: + +| Syntax | Description | Equivalent Expression | +| ------------------------- | ---------------------------- | ------------------------------------------------------------------- | +| `&&` | short-circuiting logical and | `p && q` is equivalent to `if (p) q else false` | +| || | short-circuiting logical or | p || q is equivalent to `if (p) true else q` | +| `!` | logical negation | `!p` is equivalent to `if (p) false else true` | + + +`bool` 支持三种逻辑运算: + +| 句法 | 描述 | Equivalent Expression | +| ------ | ---------------------------- | ----------------------------------------------- | +| `&&` | 短路逻辑与(short-circuiting logical and) | `p && q` 等价于 `if (p) q else false` | +| || | 短路逻辑或(short-circuiting logical or) | `p || q` 等价于 `if (p) true else q` | +| `!` | 逻辑非(logical negation) | `!p` 等价于 `if (p) false else true` | + + +### 控制流 (Control Flow) + +`bool`values are used in several of Move's control-flow constructs: + +布尔值用于 Move 的多个控制流结构中: + +- [`if (bool) { ... }`](./conditionals.html) +- [`while (bool) { .. }`](/loops.html) +- [`assert!(bool, u64)`](./abort-and-assert.html) + +## 所有权 (Ownership) + +As with the other scalar values built-in to the language, boolean values are implicitly copyable, meaning they can be copied without an explicit instruction such as `[copy]().` + +与语言内置的其他标量值一样,布尔值是隐式可复制的,这意味着它们可以在没有明确指令如[`copy`](./variables.md#move-and-copy)的情况下复制。 diff --git a/language/documentation/book/translations/move-book-zh/src/coding-conventions.md b/language/documentation/book/translations/move-book-zh/src/coding-conventions.md new file mode 100644 index 0000000000..0ea7920b8d --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/coding-conventions.md @@ -0,0 +1,76 @@ +# Move 编码约定 + +本节列出了 Move 团队认为有用的一些基本的 Move 编码约定。这些只是建议,如果你喜欢其他格式指南和约定,你可以随时使用它们。 + +## 命名 + +- **模块名称**:应该使用小写的蛇形命名法,例如:`fixed_point32`、`vector`。 +- **类型名称**:如果不是原生数据类型,则应使用驼峰命名法,例如:`Coin`、`RoleId`。 +- **函数名称**:应该使用小写的蛇形命名法,例如:`destroy_empty`。 +- **常量名称**:应该使用大写的蛇形命名法,例如:`REQUIRES_CAPABILITY`。 +- 泛型类型应该具备描述性,当然在适当的情况下也可以是反描述性的,例如:Vector 泛型类型的参数可以是 `T` 或 `Element`。大多数情况下,模块中的“主”类型命名应该与模块名相同,例如:`option::Option`,`fixed_point32::FixedPoint32`。 +- **模块文件名称**:应该与模块名相同,例如:`Option.move`。 +- **脚本文件名称**:应该使用小写的蛇形命名法,并且应该与脚本中的“主”函数名匹配。 +- **混合文件名称**:如果文件包含多个模块和/或脚本,文件命名应该使用小写的蛇形命名法,并且不需要与内部的任何特定模块/脚本名匹配。 + +## 导入 + +- 所有模块的 `use` 语句都应该位于模块的顶部。 +- 函数应该从声明它们的模块中完全限定地导入和使用, 而不是在顶部导入。 +- 类型应该在顶部导入。如果存在名称冲突,应使用 `as` 在本地适当地重命名类型。 + +例如,如果有一个模块: + +```move +module 0x1::foo { + struct Foo { } + const CONST_FOO: u64 = 0; + public fun do_foo(): Foo { Foo{} } + ... +} +``` + +此时将被导入并使用: + +```move +module 0x1::bar { + use 0x1::foo::{Self, Foo}; + + public fun do_bar(x: u64): Foo { + if (x == 10) { + foo::do_foo() + } else { + abort 0 + } + } + ... +} +``` + +并且,如果在导入两个模块时存在本地名称冲突: + +```move +module other_foo { + struct Foo {} + ... +} + +module 0x1::importer { + use 0x1::other_foo::Foo as OtherFoo; + use 0x1::foo::Foo; + ... +} +``` + +## 注释 + +- 每个模块、结构体和公共函数声明都应该有对应的注释。 +- Move 有文档注释 `///`,常规单行注释 `//`,块注释 `/* */`,和块文档注释 `/** */`。 + +## 格式化 + +Move 团队计划编写一个自动格式化程序来执行格式化约定。然而,在此期间: + +- 除 `script` 和 `address` 块外,其他的内容应使用四个空格的缩进。 +- 每行代码,如果超过 100 个字符,应该换行。 +- 结构体和常量应该在模块中的所有函数之前声明。 diff --git a/language/documentation/book/translations/move-book-zh/src/conditionals.md b/language/documentation/book/translations/move-book-zh/src/conditionals.md new file mode 100644 index 0000000000..0edbb8c42d --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/conditionals.md @@ -0,0 +1,78 @@ +# 条件语句 (Conditionals) + +An `if` expression specifies that some code should only be evaluated if a certain condition is true. For example: + +`if` 语句可以用来指定一块代码块,但只在判断条件(condition)为true时才会被执行。例如: + +```move +if (x > 5) x = x - 5 +``` + +The condition must be an expression of type `bool`. + +An `if` expression can optionally include an `else` clause to specify another expression to evaluate when the condition is false. + +条件语句(condition)必须是 `bool` 类型的表达式。 + +`if` 语句可选包含 `else` 子句,以指定当条件(condition)为 false 时要执行的另一个代码块。 + +```move +if (y <= 10) y = y + 1 else y = 10 +``` + +Either the "true" branch or the "false" branch will be evaluated, but not both. Either branch can be a single expression or an expression block. + +The conditional expressions may produce values so that the `if` expression has a result. + +无论是"true"分支还是"false"分支都会被执行,但不会同时执行.其中任何一个分支都可以是单行代码或代码块。条件表达式会产生值,所以 `if` 表达式会有一个结果。 + +```move +let z = if (x < 100) x else 100; +``` + +The expressions in the true and false branches must have compatible types. For example: + +true 和 false 分支的表达式类型必须是一致的,例如: + +```move= +// x和y必须是u64整型 +// x and y must be u64 integers +let maximum: u64 = if (x > y) x else y; + +// 错误!分支的类型不一致 +// (ERROR! branches different types) +let z = if (maximum < 10) 10u8 else 100u64; + +// 错误!分支的类型不一致,false-branch默认是()不是u64 +// ERROR! branches different types, as default false-branch is () not u64 +if (maximum >= 10) maximum; +``` + +If the `else` clause is not specified, the false branch defaults to the unit value. The following are equivalent: + +如果`else`子句未定义,false分支默认为 unit 。下面的例子是相等价的: + +```move +if (condition) true_branch // implied default: else () +if (condition) true_branch else () +``` + +Commonly, [`if` expressions](./conditionals.md) are used in conjunction with expression blocks. + +一般来说, [`if` 表达式](./conditionals.md)与多个表达式块结合使用. + +```move +let maximum = if (x > y) x else y; +if (maximum < 10) { + x = x + 10; + y = y + 10; +} else if (x >= 10 && y >= 10) { + x = x - 10; + y = y - 10; +} +``` + +## 条件语句的语法 (Grammar for Conditionals) + +> *if-expression* → **if (** *expression* **)** *expression* *else-clause**opt* +> *else-clause* → **else** *expression* diff --git a/language/documentation/book/translations/move-book-zh/src/constants.md b/language/documentation/book/translations/move-book-zh/src/constants.md new file mode 100644 index 0000000000..380322e8fc --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/constants.md @@ -0,0 +1,136 @@ +# 常量 (Constants) + +Constants are a way of giving a name to shared, static values inside of a `module` or `script`. + +The constant's must be known at compilation. The constant's value is stored in the compiled module +or script. And each time the constant is used, a new copy of that value is made. + +常量是一种对 `module` 或 `script` 内的共享静态值进行命名的方法(类似变量,但值不变,译者注)。 + +常量必须在编译时知道。常量的值存储在编译模块或脚本中。每次使用该常量时,都会生成该值的新副本。 + +## 声明 (Declaration) + +Constant declarations begin with the `const` keyword, followed by a name, a type, and a value. They +can exist in either a script or module + +常量声明以 `const` 关键字开头,后跟名称、类型和值。他们可以存在于脚本或模块中 + +```text +const : = ; +``` + +例如 + +```move= +script { + + const MY_ERROR_CODE: u64 = 0; + + fun main(input: u64) { + assert!(input > 0, MY_ERROR_CODE); + } + +} + +address 0x42 { + module example { + + const MY_ADDRESS: address = @0x42; + + public fun permissioned(s: &signer) { + assert!(std::signer::address_of(s) == MY_ADDRESS, 0); + } + + } +} +``` + +## 命名 (Naming) + +Constants must start with a capital letter `A` to `Z`. After the first letter, constant names can +contain underscores `_`, letters `a` to `z`, letters `A` to `Z`, or digits `0` to `9`. + +常量必须以大写字母 `A` 到 `Z` 开头。在第一个字母之后,常量名可以包含下划线 `_`、字母 `a` 到 `z`、字母 `A` 到 `Z` 或数字 `0` 到 `9`。 + +```move +const FLAG: bool = false; +const MY_ERROR_CODE: u64 = 0; +const ADDRESS_42: address = @0x42; +``` + +Even though you can use letters `a` to `z` in a constant. The +[general style guidelines](./coding-conventions.md) are to use just uppercase letters `A` to `Z`, +with underscores `_` between each word. + +虽然你可以在常量中使用字母 `a` 到 `z`。但[通用风格指南](./coding-conventions.md) 只使用大写字母 `A` 到 `Z`,每个单词之间有下划线`_`。 + +This naming restriction of starting with `A` to `Z` is in place to give room for future language features. It may or may not be removed later. + +这种以 `A` 到 `Z` 开头的命名限制是为了给未来的语言特性留出空间。此限制未来可能会保留或删除。 + +## 可见性 (Visibility) + +`public` constants are not currently supported. `const` values can be used only in the declaring +module. + +当前不支持 `public` 常量。 `const` 值只能在声明的模块中使用。 + +## 有效表达式 (Valid Expressions) + +Currently, constants are limited to the primitive types `bool`, `u8`, `u64`, `u128`, `address`, and +`vector`. Future support for other `vector` values (besides the "string"-style literals) will come later. + +目前,常量仅限于原始类型 `bool`、`u8`、`u64`、`u128`、`address` 和`vector`。其他 `vector` 值(除了“string”风格的字面量)将在不远的将来获得支持。 + +### 值 (Values) + +Commonly, `const`s are assigned a simple value, or literal, of their type. For example + +通常,`const` (常量)会被分配一个对应类型的简单值或字面量。例如 + +```move +const MY_BOOL: bool = false; +const MY_ADDRESS: address = @0x70DD; +const BYTES: vector = b"hello world"; +const HEX_BYTES: vector = x"DEADBEEF"; +``` + +### 复杂表达式 (Complex Expressions) + + +In addition to literals, constants can include more complex expressions, as long as the compiler is +able to reduce the expression to a value at compile time. + +Currently, equality operations, all boolean operations, all bitwise operations, and all arithmetic +operations can be used. + +除了字面量,常量还可以包含更复杂的表达式,只要编译器能够在编译时将表达式归纳(reduce)为一个值。 + +目前,相等运算、所有布尔运算、所有按位运算和所有算术运算可以使用。 + +```move +const RULE: bool = true && false; +const CAP: u64 = 10 * 100 + 1; +const SHIFTY: u8 = { + (1 << 1) * (1 << 2) * (1 << 3) * (1 << 4) +}; +const HALF_MAX: u128 = 340282366920938463463374607431768211455 / 2; +const EQUAL: bool = 1 == 1; +``` + +If the operation would result in a runtime exception, the compiler will give an error that it is +unable to generate the constant's value + +如果操作会导致运行时异常,编译器会给出无法生成常量值的错误。 + +```move +const DIV_BY_ZERO: u64 = 1 / 0; // error! +const SHIFT_BY_A_LOT: u64 = 1 << 100; // error! +const NEGATIVE_U64: u64 = 0 - 1; // error! +``` + +Note that constants cannot currently refer to other constants. This feature, along with support for +other expressions, will be added in the future. + +请注意,常量当前不能引用其他常量。此功能会在将来和支持其他表达方式一起被补充。 diff --git a/language/documentation/book/translations/move-book-zh/src/creating-coins.md b/language/documentation/book/translations/move-book-zh/src/creating-coins.md new file mode 100644 index 0000000000..1f06df9a00 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/creating-coins.md @@ -0,0 +1,7 @@ +# Move Tutorial + +Please refer to the [Move Tutorial](https://github.com/move-language/move/tree/main/language/documentation/tutorial). + +# Move 教程 + +请参阅 [Move 教程](https://github.com/move-language/move/tree/main/language/documentation/tutorial)。 diff --git a/language/documentation/book/translations/move-book-zh/src/equality.md b/language/documentation/book/translations/move-book-zh/src/equality.md new file mode 100644 index 0000000000..2abe89623f --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/equality.md @@ -0,0 +1,192 @@ + +# 等式 (Equality) + +Move supports two equality operations `==` and `!=` + +Move 支持两种等式操作: `==` 和 `!=` + +## 操作 (Operations) + +| Syntax | Operation | Description | +| ------ | --------- | --------------------------------------------------------------------------- | +| `==` | equal | Returns `true` if the two operands have the same value, `false` otherwise | +| `!=` | not equal | Returns `true` if the two operands have different values, `false` otherwise | + +| 语法 | 操作 | 描述 | +| ------ | --------- | --------------------------------------------------------------------------- | +| `==` | 相等 | 如果两个操作数(operands)值相同,返回 `true` , 否则返回 `false` | +| `!=` | 不相等 | 如果两个操作数(operands)值不相同,返回 `true` , 否则返回 `false` | + +### 类型校验 (Typing) + +Both the equal (`==`) and not-equal (`!=`) operations only work if both operands are the same type. + +只有当左右两个操作数类型相同,相等操作 (`==`) 与不等操作 (`!=`) 才能正常使用。 + +```move +0 == 0; // `true` +1u128 == 2u128; // `false` +b"hello" != x"00"; // `true` +``` + +Equality and non-equality also work over user defined types! + +等式与不等式也可以在用户自定义的类型下使用! + +```move= +address 0x42 { + module example { + struct S has copy, drop { f: u64, s: vector } + + fun always_true(): bool { + let s = S { f: 0, s: b"" }; + // 括号不是必需的,但为了清楚起见在此示例中添加了括号 + (copy s) == s + } + + fun always_false(): bool { + let s = S { f: 0, s: b"" }; + // 括号不是必需的,但为了清楚起见在此示例中添加了括号 + (copy s) != s + } + } +} +``` + +If the operands have different types, there is a type checking error. + +如果两边操作数的类型不同,则会出现类型检测错误。 + +```move +1u8 == 1u128; // 错误! +// ^^^^^ 期望此变量的类型是 'u8' +b"" != 0; // 错误! +// ^ 期望此变量的类型是 'vector' +``` + +### 引用变量的类型校验 (Typing with references) + +When comparing [references](./references.md), the type of the reference (immutable or mutable) does +not matter. This means that you can compare an immutable `&` reference with a mutable one `&mut` of +the same underlying type. + +当比较[引用变量](./references.md)时,引用的类别(不可变更的或可变更的(immutable or mutable))无关紧要。这意味着我们可以拿一个不可变更的 `&` 引用变量和另一个有相同相关类型的可变更的 `&mut ` 引用变量进行比较。 + +```move +let i = &0; +let m = &mut 1; + +i == m; // `false` +m == i; // `false` +m == m; // `true` +i == i; // `true` +``` + +The above is equivalent to applying an explicit freeze to each mutable reference where needed + +在需要时,对每个可变引用使用显式冻结(explicit freeze)的结果与上述情况一致。 + +```move +let i = &0; +let m = &mut 1; + +i == freeze(m); // `false` +freeze(m) == i; // `false` +m == m; // `true` +i == i; // `true` +``` +But again, the underlying type must be the same type + +但同样的,我们需要两边操作数的类型一致 + +```move +let i = &0; +let s = &b""; + +i == s; // 错误! +// ^ 期望此变量的类型是 '&u64' +``` + +## 限制 (Restrictions) + +Both `==` and `!=` consume the value when comparing them. As a result, the type system enforces that +the type must have [`drop`](./abilities.md). Recall that without the [`drop` ability](./abilities.md), +ownership must be transferred by the end of the function, and such values can only be explicitly destroyed +within their declaring module. If these were used directly with either equality `==` or non-equality `!=`, +the value would be destroyed which would break [`drop` ability](./abilities.md) safety guarantees! + +`==` 和 `!=` 会在比较不同变量的时候消耗 (consume)它们所包含的值,所以 Move 的类型系统会强制要求这些类型含有[`drop` 能力](./abilities.md)。回想一下,变量在没有[`drop` 能力](./abilities.md)时,所有权必须在函数结束前进行转移,而且这些值只能在其声明模块中被明确销毁(explicitly destroyed)。如果它们被直接使用于等式 `==` 或不等式 `!=` ,其值会被销毁并且这会打破[`drop` 能力](./abilities.md)的安全保证! + +```move= +address 0x42 { + module example { + struct Coin has store { value: u64 } + fun invalid(c1: Coin, c2: Coin) { + c1 == c2 // 错误! + // ^^ ^^ 这些资源将会被销毁! + } + } +} +``` + + +But, a programmer can _always_ borrow the value first instead of directly comparing the value, and +reference types have the [`drop` ability](./abilities.md). For example + +然而, 程序员 _总是_ 可以优先借用变量的值,而不直接比较它们的值。这样一来,引用变量的类型将会拥有[`drop` 能力](./abilities.md)。例如: + +```move= +address 0x42 { + module example { + struct Coin as store { value: u64 } + fun swap_if_equal(c1: Coin, c2: Coin): (Coin, Coin) { + let are_equal = &c1 == &c2; // 合规范的 + if (are_equal) (c2, c1) else (c1, c2) + } + } +} +``` + +## 避免额外的复制 (Avoid Extra Copies) + +While a programmer _can_ compare any value whose type has [`drop`](./abilities.md), a programmer +should often compare by reference to avoid expensive copies. + +当程序员 _可以_ 比较其类型含有[`drop` 能力](./abilities.md)的任意值时,他们应该尽可能多地使用引用变量来比较,以此来避免昂贵的复制。 + +```move= +let v1: vector = function_that_returns_vector(); +let v2: vector = function_that_returns_vector(); +assert!(copy v1 == copy v2, 42); +// ^^^^ ^^^^ +use_two_vectors(v1, v2); + +let s1: Foo = function_that_returns_large_struct(); +let s2: Foo = function_that_returns_large_struct(); +assert!(copy s1 == copy s2, 42); +// ^^^^ ^^^^ +use_two_foos(s1, s2); +``` + +This code is perfectly acceptable (assuming `Foo` has [`drop`](./abilities.md)), just not efficient. +The highlighted copies can be removed and replaced with borrows + +以上代码是完全可以接受的(假设`Foo`具备[`drop`](./abilities.md)能力),但它不是最有效的写法。突出显示的副本可以删除并替换为借用。 + +```move= +let v1: vector = function_that_returns_vector(); +let v2: vector = function_that_returns_vector(); +assert!(&v1 == &v2, 42); +// ^ ^ +use_two_vectors(v1, v2); + +let s1: Foo = function_that_returns_large_struct(); +let s2: Foo = function_that_returns_large_struct(); +assert!(&s1 == &s2, 42); +// ^ ^ +use_two_foos(s1, s2); +``` + +The efficiency of the `==` itself remains the same, but the `copy`s are removed and thus the program is more efficient. + +`==` 本身的效率还是和之前一样,但是 `copy` 操作被移除后整个程序会比之前更有效率。 diff --git a/language/documentation/book/translations/move-book-zh/src/friends.md b/language/documentation/book/translations/move-book-zh/src/friends.md new file mode 100644 index 0000000000..238dce84f4 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/friends.md @@ -0,0 +1,154 @@ +# 友元函数(Friends) + +The `friend` syntax is used to declare modules that are trusted by the current module. +A trusted module is allowed to call any function defined in the current module that have the `public(friend)` visibility. +For details on function visibilities, please refer to the *Visibility* section in [Functions](./functions.md). + +友元语法用于声明当前模块信任的其它模块。受信任的模块可以调用当前模块中定义的任何具有`公开(友元)`可见性的函数。有关函数可见性的详细信息,请参阅[函数](./functions.md)中的可见性部分。 + +## 友元声明(Friend declaration) + +A module can declare other modules as friends via friend declaration statements, in the format of + +一个模块可以通过友元声明语句将其他模块声明为友元,格式为: + +- `friend ` — friend declaration using fully qualified module name like the example below, or +- `friend —` 使用完全合格的模块名称的友元声明,如下例所示,或 + + ``` + address 0x42 { + module a { + friend 0x42::b; + } + } + ``` + +- `friend ` — friend declaration using a module name alias, where the module alias is introduced via the `use` statement. +- `friend —` 使用模块名称别名的友元声明,其中模块别名是通过use语句引入的。 + + ```move + address 0x42 { + module a { + use 0x42::b; + friend b; + } + } + ``` + +A module may have multiple friend declarations, and the union of all the friend modules forms the friend list. +In the example below, both `0x42::B` and `0x42::C` are considered as friends of `0x42::A`. + +一个模块可能有多个友元声明,所有好友模块的并集形成友元列表。在下面的示例中`,0x42::B`和`0x42::C`都被视为 的友元函数`0x42::A`。 + + ```move + address 0x42 { + module a { + friend 0x42::b; + friend 0x42::c; + } + } + ``` + +Unlike `use` statements, `friend` can only be declared in the module scope and not in the expression block scope. +`friend` declarations may be located anywhere a top-level construct (e.g., `use`, `function`, `struct`, etc.) is allowed. +However, for readability, it is advised to place friend declarations near the beginning of the module definition. + +与`use`语句不同,`friend`只能在模块作用域内声明,而不能在表达式块的作用域内声明。`friend`声明可以位于允许顶层构造的任何位置(例如, `use`, `function,struct`等)是被允许的。但是,为了可读性,建议将友元声明放在模块定义的开头附近。 + +Note that the concept of friendship does not apply to Move scripts: +- A Move script cannot declare `friend` modules as doing so is considered meaningless: there is no mechanism to call the function defined in a script. +- A Move module cannot declare `friend` scripts as well because scripts are ephemeral code snippets that are never published to global storage. + +请注意,友元关系(friendship)的概念不适用于 Move 脚本: +- `Move` 脚本不能声明`friend`模块,因为这样做被认为是无意义的:没有机制可以调用脚本中定义的函数。 +- `Move` 模块也不能声明`friend`脚本,因为脚本是永远不会发布到全局存储的临时代码片段。 + +### 友元声明规则(Friend declaration rules) +Friend declarations are subject to the following rules: +友元声明须遵守以下规则: + +- A module cannot declare itself as a friend +- 一个模块不能将自己声明为友元。 + + ```move= + address 0x42 { + module m { friend Self; // 错误! } + // ^^^^ 不能将自己声明为友元 + } + + address 0x43 { + module m { friend 0x43::M; // 错误! } + // ^^^^^^^ 不能将自己声明为友元 + } + ``` + +- Friend modules must be known by the compiler +- 编译器必须知道友元模块 + + ```move= + address 0x42 { + module m { friend 0x42::nonexistent; // 错误! } + // ^^^^^^^^^^^^^^^^^ 未绑定的模块 '0x42::nonexistent' + } + ``` + + - Friend modules must be within the same account address. (Note: this is not a technical requirement but rather a policy decision which *may* be relaxed later.) + + - 友元模块必须在同一个账号地址内。(注:这不是技术要求,而是以后可能放宽的决策。) + + ```move + address 0x42 { + module m {} + } + + address 0x43 { + module n { friend 0x42::m; // 错误! } + // ^^^^^^^ 不能声明当前地址外的模块作为友元 + } + ``` + +- 友元关系不能创建循环模块依赖关系(Friends relationships cannot create cyclic module dependencies) + +Cycles are not allowed in the friend relationships, e.g., the relation `0x2::a` friends `0x2::b` friends `0x2::c` friends `0x2::a` is not allowed. +More generally, declaring a friend module adds a dependency upon the current module to the friend module (because the purpose is for the friend to call functions in the current module). +If that friend module is already used, either directly or transitively, a cycle of dependencies would be created. + +友元关系中不允许循环,例如 `0x2::a` 友元 `0x2::b` 友元 `0x2::c` 友元`0x2::a`是不允许的。更普遍地,声明一个友元模块会将对当前模块的依赖添加到友元模块(因为目的是让友元调用当前模块中的函数)。如果该友元模块已被直接或传递地使用,则将形成一个依赖循环。 + + ```move + address 0x2 { + module a { + use 0x2::c; + friend 0x2::b; + + public fun a() { + c::c() + } + } + + module b { + friend 0x2::c; // 错误! + // ^^^^^^ 这个友元关系形成了一个依赖循环: '0x2::a' 使用了 '0x2::c' 但'0x2::b' 同时是 '0x2::a'和'0x2::b' 的友元 + } + + module c { + public fun c() {} + } + } +``` + +- The friend list for a module cannot contain duplicates. +- 模块的友元列表不能包含重复项。 + + ```move= + address 0x42 { + module a {} + + module m { + use 0x42::a as aliased_a; + friend 0x42::A; + friend aliased_a; // 错误! + // ^^^^^^^^^ 重复的友元声明 '0x42::a'. 模块内的友元声明必须是唯一的 + } + } + ``` diff --git a/language/documentation/book/translations/move-book-zh/src/functions.md b/language/documentation/book/translations/move-book-zh/src/functions.md new file mode 100644 index 0000000000..e0fb8d2a04 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/functions.md @@ -0,0 +1,607 @@ +# 函数 (Functions) + +Function syntax in Move is shared between module functions and script functions. Functions inside of modules are reusable, whereas script functions are only used once to invoke a transaction. + +Move中的函数语法在模块函数和脚本函数之间是一致的。模块内部的函数可重复使用,而脚本的函数只能被使用一次用来调用事务。 + +# 声明 (Declaration) + +Functions are declared with the `fun` keyword followed by the function name, type parameters, parameters, a return type, acquires annotations, and finally the function body. + +函数使用 `fun` 关键字声明,后跟函数名称、类型参数、参数、返回类型、获取标注(annotation),最后是函数体。 + +```text +fun <[type_parameters: constraint],*>([identifier: type],*): +``` + +例如 + +```move +fun foo(x: u64, y: T1, z: T2): (T2, T1, u64) { (z, y, x) } +``` + +### 可见性 (Visibility) + +Module functions, by default, can only be called within the same module. These internal (sometimes called private) functions cannot be called from other modules or from scripts. + +默认情况下,模块函数只能在同一个模块内调用。这些内部(有时称为私有)函数不能从其他模块或脚本中调用。 + +```move= +address 0x42 { + module m { + fun foo(): u64 { 0 } + fun calls_foo(): u64 { foo() } // valid + } + + module other { + fun calls_m_foo(): u64 { + 0x42::m::foo() // ERROR! + // ^^^^^^^^^^^^ 'foo' is internal to '0x42::m' + } + } +} + +script { + fun calls_m_foo(): u64 { + 0x42::m::foo() // ERROR! +// ^^^^^^^^^^^^ 'foo' is internal to '0x42::m' + } +} +``` + +To allow access from other modules or from scripts, the function must be declared `public` or `public(friend)`. + +要允许从其他模块或脚本访问,该函数必须声明为 `public` 或 `public(friend)`。 + +#### `public` 可见性 (`public` visibility) + +A `public` function can be called by *any* function defined in *any* module or script. As shown in the following example, a `public` function can be called by: +- other functions defined in the same module, +- functions defined in another module, or +- the function defined in a script. + +`public` 函数可以被任何模块或脚本中定义的任何函数调用。如以下示例所示,可以通过以下方式调用 `public` 函数: + +- 在同一模块中定义的其他函数 +- 在另一个模块中定义的函数 +- 在脚本中定义的函数 + +```move= +address 0x42 { + module m { + public fun foo(): u64 { 0 } + fun calls_foo(): u64 { foo() } // valid + } + + module other { + fun calls_m_foo(): u64 { + 0x42::m::foo() // valid + } + } +} + +script { + fun calls_m_foo(): u64 { + 0x42::m::foo() // valid + } +} +``` + +#### `public(friend)` 可见性 (`public(friend)` visibility) + +The `public(friend)` visibility modifier is a more restricted form of the `public` modifier to give more control about where a function can be used. A `public(friend)` function can be called by: +- other functions defined in the same module, or +- functions defined in modules which are explicitly specified in the **friend list** (see [Friends](./friends.md) on how to specify the friend list). + +Note that since we cannot declare a script to be a friend of a module, the functions defined in scripts can never call a `public(friend)` function. + +`public(friend)` 可见性修饰符是一种比 `public` 修饰符限制更严格的形式,可以更好地控制函数的使用位置。 `public(friend)` 函数可以通过以下方式调用: + +- 在同一模块中定义的其他函数,或者在 **friend list** 中明确指定的模块中定义的函数(请参阅 [Friends](./friends.md) 了解如何指定友元(friends)列表)。 + +请注意,由于我们不能将脚本声明为模块的友元关系,因此脚本中定义的函数永远不能调用 `public(friend)` 函数。 + +```move= +address 0x42 { + module m { + friend 0x42::n; // friend declaration + public(friend) fun foo(): u64 { 0 } + fun calls_foo(): u64 { foo() } // valid + } + + module n { + fun calls_m_foo(): u64 { + 0x42::m::foo() // valid + } + } + + module other { + fun calls_m_foo(): u64 { + 0x42::m::foo() // ERROR! + // ^^^^^^^^^^^^ 'foo' can only be called from a 'friend' of module '0x42::m' + } + } +} + +script { + fun calls_m_foo(): u64 { + 0x42::m::foo() // ERROR! +// ^^^^^^^^^^^^ 'foo' can only be called from a 'friend' of module '0x42::m' + } +} +``` + +### `entry` 修饰符 (`entry` modifier) + +The `entry` modifier is designed to allow module functions to be safely and directly invoked much like scripts. This allows module writers to specify which functions can be to begin execution. The module writer then knows that any non-`entry` function will be called from a Move program already in execution. + +Essentially, `entry` functions are the "main" functions of a module, and they specify where Move programs start executing. + +Note though, an `entry` function _can_ still be called by other Move functions. So while they _can_ serve as the start of a Move program, they aren't restricted to that case. + +`entry` 修饰符旨在允许像脚本一样安全直接地调用模块函数。这允许模块编写者指定哪些函数可以成为开始执行的入口。这样模块编写者就知道任何非`entry`函数都是从已经在执行的 Move 程序中被调用的。 + +本质上,`entry` 函数是模块的“main”函数,它们指定 Move 程序开始执行的位置。 + +但请注意,`entry` 函数仍可被其他 Move 函数调用。因此,虽然它们 _可以_ 作为 Move 程序的入口,但它们并不局限于这种用法。 + +例如: + +```move= +address 0x42 { + module m { + public entry fun foo(): u64 { 0 } + fun calls_foo(): u64 { foo() } // valid! + } + + module n { + fun calls_m_foo(): u64 { + 0x42::m::foo() // valid! + } + } + + module other { + public entry fun calls_m_foo(): u64 { + 0x42::m::foo() // valid! + } + } +} + +script { + fun calls_m_foo(): u64 { + 0x42::m::foo() // valid! + } +} +``` + +Even internal functions can be marked as `entry`! This lets you guarantee that the function is called only at the beginning of execution (assuming you do not call it elsewhere in your module) + +甚至内部函数也可以标记为 `entry`!这使你可以保证仅在开始执行时调用该函数(假如你没有在模块中的其他地方调用它) + +```move= +address 0x42 { + module m { + entry fun foo(): u64 { 0 } // valid! entry functions do not have to be public + } + + module n { + fun calls_m_foo(): u64 { + 0x42::m::foo() // ERROR! + // ^^^^^^^^^^^^ 'foo' is internal to '0x42::m' + } + } + + module other { + public entry fun calls_m_foo(): u64 { + 0x42::m::foo() // ERROR! + // ^^^^^^^^^^^^ 'foo' is internal to '0x42::m' + } + } +} + +script { + fun calls_m_foo(): u64 { + 0x42::m::foo() // ERROR! +// ^^^^^^^^^^^^ 'foo' is internal to '0x42::m' + } +} +``` + +### 函数名 (Name) + +Function names can start with letters `a` to `z` or letters `A` to `Z`. After the first character, function names can contain underscores `_`, letters `a` to `z`, letters `A` to `Z`, or digits `0` to `9`. + +函数名称可以以字母 `a` 到 `z` 或字母 `A` 到 `Z` 开头。在第一个字符之后,函数名称可以包含下划线 `_`、字母 `a` 到 `z` 、字母 `A` 到 `Z` 或数字 `0` 到 `9`。 + +```move +fun FOO() {} +fun bar_42() {} +fun _bAZ19() {} +``` + +### 类型参数 (Type Parameters) + +After the name, functions can have type parameters + +函数名后可以有类型参数 + +```move +fun id(x: T): T { x } +fun example(x: T1, y: T2): (T1, T1, T2) { (copy x, x, y) } +``` + +For more details, see [Move generics](./generics.md). + +有关更多详细信息,请参阅 [移动泛型](./generics.md)。 + +### 参数 (Parameters) + +Functions parameters are declared with a local variable name followed by a type annotation + +函数参数使用局部变量名,后跟类型标注的方式进行声明。 + +```move +fun add(x: u64, y: u64): u64 { x + y } +``` + +We read this as `x` has type `u64` + +A function does not have to have any parameters at all. + +(上面代码中的函数参数) 我们读为:`x` 参数的类型是 `u64` 。 + +函数可以没有任何参数。 + +```move +fun useless() { } +``` + +This is very common for functions that create new or empty data structures + +在函数中创建新或空的数据结构是常见的用法。 + +```move= +address 0x42 { + module example { + struct Counter { count: u64 } + + fun new_counter(): Counter { + Counter { count: 0 } + } + + } +} +``` + +### Acquires + +When a function accesses a resource using `move_from`, `borrow_global`, or `borrow_global_mut`, the function must indicate that it `acquires` that resource. This is then used by Move's type system to ensure the references into global storage are safe, specifically that there are no dangling references into global storage. + +当一个函数使用 `move_from`、`borrow_global` 或 `borrow_global_mut` 访问资源时,则该函数必须表明它 `获取(acquires)` 该资源。然后 Move 的类型系统使用它来确保对全局存储的引用是安全的,特别是没有对全局存储的悬垂引用(dangling references)。 + +```move= +address 0x42 { + module example { + + struct Balance has key { value: u64 } + + public fun add_balance(s: &signer, value: u64) { + move_to(s, Balance { value }) + } + + public fun extract_balance(addr: address): u64 acquires Balance { + let Balance { value } = move_from(addr); // acquires needed + value + } + } +} +``` +`acquires` annotations must also be added for transitive calls within the module. Calls to these functions from another module do not need to annotated with these acquires because one module cannot access resources declared in another module--so the annotation is not needed to ensure reference safety. + +`acquires` 标注也必须为模块内有传递性的调用添加。从另一个模块对这些函数的调用不需要使用 `acquires` 进行注释,因为一个模块无法访问在另一个模块中声明的资源——因此不需要用标注来确保引用安全。 + +```move= +address 0x42 { + module example { + + struct Balance has key { value: u64 } + + public fun add_balance(s: &signer, value: u64) { + move_to(s, Balance { value }) + } + + public fun extract_balance(addr: address): u64 acquires Balance { + let Balance { value } = move_from(addr); // acquires needed + value + } + + public fun extract_and_add(sender: address, receiver: &signer) acquires Balance { + let value = extract_balance(sender); // acquires needed here + add_balance(receiver, value) + } + } +} + +address 0x42 { + module other { + fun extract_balance(addr: address): u64 { + 0x42::example::extract_balance(addr) // no acquires needed + } + } +} +``` + +A function can `acquire` as many resources as it needs to + +函数可以根据需要 `acquire` 尽可能多的资源。 + +```move= +address 0x42 { + module example { + use std::vector; + + struct Balance has key { value: u64 } + struct Box has key { items: vector } + + public fun store_two( + addr: address, + item1: Item1, + item2: Item2, + ) acquires Balance, Box { + let balance = borrow_global_mut(addr); // acquires needed + balance.value = balance.value - 2; + let box1 = borrow_global_mut>(addr); // acquires needed + vector::push_back(&mut box1.items, item1); + let box2 = borrow_global_mut>(addr); // acquires needed + vector::push_back(&mut box2.items, item2); + } + } +} +``` + +### 返回类型 (Return type) + +After the parameters, a function specifies its return type. + +在参数之后,函数指定其返回类型。 + +```move +fun zero(): u64 { 0 } +``` + +Here `: u64` indicates that the function's return type is `u64`. + +Using tuples, a function can return multiple values + +这里 `: u64` 表示函数的返回类型是 `u64`。 + +使用元组,一个函数可以返回多个值: + +```move +fun one_two_three(): (u64, u64, u64) { (0, 1, 2) } +``` + +If no return type is specified, the function has an implicit return type of unit `()`. These functions are equivalent + +如果未指定返回类型,则该函数具有隐式返回类型单值 `()`。这些函数是等价的: + +```move +fun just_unit(): () { () } +fun just_unit() { () } +fun just_unit() { } +``` + +`script` functions must have a return type of unit `()` + +`script` 函数的返回类型必须为单值 `()`(不能是任何其他类型,例如 `bool`、`u64` 等,注者注): + +```move +script { + fun do_nothing() { + } +} +``` + +As mentioned in the [tuples section](./tuples.md), these tuple "values" are virtual and do not exist at runtime. So for a function that returns unit `()`, it will not be returning any value at all during execution. + +如[元组部分](./tuples.md)所述,这些元组“值”是虚拟的(virtual),且在运行时不存在。因此,对于返回单值 `()` 的函数,它在执行期间根本不会返回任何值。 + +### Function body (函数体) + +A function's body is an expression block. The return value of the function is the last value in the sequence + +函数体是一个表达式块。函数的返回值是序列中最后一个表达式的值。 + +```move= +fun example(): u64 { + let x = 0; + x = x + 1; + x // returns 'x' +} +``` + +See [the section below for more information on returns](#returning-values) + +请参阅[有关返回值的更多信息](#returning-values) + +For more information on expression blocks, see [Move variables](./variables.md). + +有关表达式块的更多信息,请参阅 [Move variables](./variables.md)。 + +### Native Functions + +Some functions do not have a body specified, and instead have the body provided by the VM. These functions are marked `native`. + +Without modifying the VM source code, a programmer cannot add new native functions. Furthermore, it is the intent that `native` functions are used for either standard library code or for functionality needed for the given Move environment. + +Most `native` functions you will likely see are in standard library code such as `vecto + +有些函数没有函数体,而是由 Move VM 提供的函数体。这些函数被标记为 `native`。 + +如果不修改 Move VM 源代码,程序员就无法添加新的 `native` 函数。此外,`native` 函数的意图是用于标准库代码或 Move 环境所需的基础功能。 + +你看到的大多数 `native` 函数可能都在标准库代码中,例如 `vector` + +```move= +module std::vector { + native public fun empty(): vector; + ... +} +``` + +## 调用 (Calling) + +When calling a function, the name can be specified either through an alias or fully qualified + +调用函数时,名称可以通过别名或完全限定名指定 + +```move= +address 0x42 { + module example { + public fun zero(): u64 { 0 } + } +} + +script { + use 0x42::example::{Self, zero}; + fun call_zero() { + // With the `use` above all of these calls are equivalent + 0x42::example::zero(); + example::zero(); + zero(); + } +} +``` + +When calling a function, an argument must be given for every parameter. + +调用函数时,每个参数必须指定一个值。 + +```move= +address 0x42 { + module example { + public fun takes_none(): u64 { 0 } + public fun takes_one(x: u64): u64 { x } + public fun takes_two(x: u64, y: u64): u64 { x + y } + public fun takes_three(x: u64, y: u64, z: u64): u64 { x + y + z } + } +} + +script { + use 0x42::example; + fun call_all() { + example::takes_none(); + example::takes_one(0); + example::takes_two(0, 1); + example::takes_three(0, 1, 2); + } +} +``` + +Type arguments can be either specified or inferred. Both calls are equivalent. + +函数的类型参数可以被指定或推断出来。以下两个调用是等价的。 + +```move= +address 0x42 { + module example { + public fun id(x: T): T { x } + } +} + +script { + use 0x42::example; + fun call_all() { + example::id(0); + example::id(0); + } +} +``` + +For more details, see [Move generics](./generics.md). + +有关更多详细信息,请参阅 [Move generics](./generics.md)。 + + +## Returning values (返回值) + +The result of a function, its "return value", is the final value of its function body. For example + +一个函数的结果,也就是它的“返回值”,是函数体的最后一个值。例如: + +```move= +fun add(x: u64, y: u64): u64 { + x + y +} +``` + +[As mentioned above](#function-body), the function's body is an [expression block](./variables.md). The expression block can sequence various statements, and the final expression in the block will be be the value of that block + +[如上所述](#function-body),函数体是一个[表达式块](./variables.md)。表达式块中可以有各种各种语句,块中最后一个表达式将是该表达式块的值。 + +```move= +fun double_and_add(x: u64, y: u64): u64 { + let double_x = x * 2; + let double_y = y * 2; + double_x + double_y +} +``` + +The return value here is `double_x + double_y` + +这里的返回值是 `double_x + double_y` + +### `return` 表达式 (`return` expression) + +A function implicitly returns the value that its body evaluates to. However, functions can also use the explicit `return` expression: + +函数隐式返回其函数体计算的值。但是,函数也可以使用显式的 `return` 表达式: + +```move +fun f1(): u64 { return 0 } +fun f2(): u64 { 0 } +``` + + +These two functions are equivalent. In this slightly more involved example, the function subtracts two `u64` values, but returns early with `0` if the second value is too large: + +这两个功能是等价的。在下面这个稍微复杂的示例中,该函数返回两个 `u64` 值相减的结果,但如果第二个值大于第一个值,则提前返回 `0` : + +```move= +fun safe_sub(x: u64, y: u64): u64 { + if (y > x) return 0; + x - y +} +``` + +Note that the body of this function could also have been written as `if (y > x) 0 else x - y`. + +However `return` really shines is in exiting deep within other control flow constructs. In this example, the function iterates through a vector to find the index of a given value: + +请注意,这个函数的函数体也可以写成 `if (y > x) 0 else x - y`。 + +然而,`return` 真正的亮点在于在其他控制流结构的深处退出。在此示例中,函数遍历数组以查找给定值的索引: + +```move= +use std::vector; +use std::option::{Self, Option}; +fun index_of(v: &vector, target: &T): Option { + let i = 0; + let n = vector::length(v); + while (i < n) { + if (vector::borrow(v, i) == target) return option::some(i); + i = i + 1 + }; + + option::none() +} +``` + +Using `return` without an argument is shorthand for `return ()`. That is, the following two functions are equivalent: + +使用不带参数的 `return` 是 `return ()` 的简写。即以下两个函数是等价的: + +```move +fun foo() { return } +fun foo() { return () } +``` diff --git a/language/documentation/book/translations/move-book-zh/src/generics.md b/language/documentation/book/translations/move-book-zh/src/generics.md new file mode 100644 index 0000000000..888ca5df47 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/generics.md @@ -0,0 +1,422 @@ +# 泛型 + +泛型可用于定义具有不同输入数据类型的函数和结构体。这种语言特性有时被称为*参数多态*(parametric polymorphism)。在 Move 中,我们经常将术语泛型与类型形参(type parameter)和类型实参(type argument)互换使用。*(有些书籍的中文翻译通常将 type parameter 和 type argument 不加以区别地翻译为“类型参数”,译者注)* + +泛型通常用于库(library)代码中,例如向量中,声明适用于任何可能的实例化(满足指定约束)的代码。在其他框架中,泛型代码有时可用多种不同的方式与全局存储进行交互,这些方式有着相同的实现。 + +## 声明类型参数 + +函数和结构体都可以在其签名中带上类型参数列表,由一对尖括号括起来 `<...>`。 + +### 泛型函数 + +函数的类型参数放在函数名称之后和(值)参数列表之前。以下代码定义了一个泛型标识函数,该函数接受任何类型的值并返回原值。 + +```move +fun id(x: T): T { + // 此类型标注是不必要但有效的 + (x: T) +} +``` + +一旦定义,类型参数 `T` 就可以在参数类型、返回类型和函数体内使用。 + +### 泛型结构体 + +结构体的类型参数放在结构名称之后,可用于命名字段的类型。 + +```move +struct Foo has copy, drop { x: T } + +struct Bar has copy, drop { + x: T1, + y: vector, +} +``` + +请注意,[未使用的类型参数](#未使用的类型参数)。 + +## 类型实参 + +### 调用泛型函数 + +调用泛型函数时,可以在由一对尖括号括起来的列表中为函数的类型形参指定类型实参。 + +```move +fun foo() { + let x = id(true); +} +``` + +如果你不指定类型实参,Move 的[类型推断](#类型推断)(功能)将为你提供它们。 + +### 使用泛型结构体 + +类似地,在构造或销毁泛型类型的值时,可以为结构体的类型参数附加一个类型实参列表。 + +```move +fun foo() { + let foo = Foo { x: true }; + let Foo { x } = foo; +} +``` + +如果你不指定类型实参,Move 的[类型推断](#类型推断)(功能)将为你提供它们。 + +### 类型实参不匹配 + +如果你指定类型实参并且它们与提供的实际值冲突,则会报错: + +```move +fun foo() { + let x = id(true); // 错误!true 不是 u64 +} +``` + +同样地: + +```move +fun foo() { + let foo = Foo { x: 0 }; // 错误!0 不是布尔值 + let Foo
{ x } = foo; // 错误!bool 与 address 不兼容 +} +``` + +## 类型推断 + +在大多数情况下,Move 编译器能够推断类型实参,因此你不必显式地写下它们。如果我们省略类型实参,上面的例子会是这样的: + +```move +fun foo() { + let x = id(true); + // ^ 被推断为 + + let foo = Foo { x: true }; + // ^ 被推断为 + + let Foo { x } = foo; + // ^ 被推断为 +} +``` + +注意:当编译器无法推断类型时,你需要手动标注它们。一个常见的场景是调用一个函数,其类型参数只出现在返回位置。 + +```move +address 0x2 { +module m { + using std::vector; + + fun foo() { + // let v = vector::new(); + // ^ 编译器无法确定元素类型。 + + let v = vector::new(); + // ^~~~~ 必须手动标注。 + } +} +} +``` + +但是,如果稍后在该函数中使用该返回值,编译器将能够推断其类型: + +```move +address 0x2 { +module m { + using std::vector; + + fun foo() { + let v = vector::new(); + // ^ 被推断为 + vector::push_back(&mut v, 42); + } +} +} +``` + +## 未使用的类型参数 + +对于结构体定义,未使用的类型参数是没有出现在结构体定义的任何字段中,但在编译时静态检查的类型参数。Move 允许未使用的类型参数,因此以下结构体定义有效: + +```move +struct Foo { + foo: u64 +} +``` + +这在对某些概念建模时会很方便。这是一个例子: + +```move +address 0x2 { +module m { + // 货币说明符 + struct Currency1 {} + struct Currency2 {} + + // 可以使用货币说明符类型实例化的泛型钱币类型。 + // 例如 Coin, Coin 等。 + struct Coin has store { + value: u64 + } + + // 泛型地编写有关所有货币的代码 + public fun mint_generic(value: u64): Coin { + Coin { value } + } + + // 具体编写关于一种货币的代码 + public fun mint_concrete(value: u64): Coin { + Coin { value } + } +} +} +``` + +在此示例中,`struct Coin` 是类型参数为 `Currency` 的泛型结构体,该参数指定钱币的货币(类型),并允许将代码泛型地写入任何货币或具体地写入特定货币。即使 `Currency` 类型参数未出现在 `Coin` 中定义的任何字段中,这种通用性也适用。 + +### 虚类型参数 + +在上面的例子中,虽然 `struct Coin` 要求有 `store` 能力,但 `Coin` 和 `Coin` 都没有 `store` 能力。这实际是因为[条件能力与泛型类型](./abilities.md#条件能力与泛型类型)的规则以及 `Currency1` 和 `Currency2` 没有 `store` 能力,尽管它们甚至没有在 `struct Coin` 的结构体中使用。这可能会导致一些不合意的后果。例如,我们无法将 `Coin` 放入全局存储中的钱包。 + +一种可能的解决方案是向 `Currency1` 和 `Currency2` 添加伪能力(spurious ability)标注(例如:`struct Currency1 has store {}`)。但是,这可能会导致错误(bug)或安全漏洞,因为它削弱了类型,引入了不必要的能力声明。例如,我们永远不会期望全局存储中的资源有一个类型为 `Currency1` 的字段,但是通过伪 `store` 能力这是有可能的。此外,伪标注具有传染性,需要在许多未使用类型参数的泛型函数上也包含必要的约束。 + +虚类型(phantom type)参数解决了这个问题。未使用的类型参数可以标记为 *phantom* 类型参数,不参与结构体的能力推导。这样,在派生泛型类型的能力时,不考虑虚类型参数的实参,从而避免了对伪能力标注的需要。为了使这个宽松的规则合理,Move 的类型系统保证声明为 `phantom` 的参数要么在结构体定义根本不使用,要么仅用作声明为 `phantom` 的类型参数的实参。 + +#### 声明 + +在结构定义中,可以通过在声明前添加 `phantom` 关键字来将类型参数声明为 phantom。如果一个类型参数被声明为 phantom,我们就说它是一个虚类型参数。在定义结构时,Move 的类型检查器确保每个虚类型参数要么未在结构定义中使用,要么仅用作虚类型参数的实参。 + +更正式地说,如果一个类型被用作虚类型参数的实参,我们说该类型出现在_虚位置_。有了这个定义,正确使用虚参数的规则可以指定如下:**虚类型参数只能出现在虚位置**。 + +以下两个示例显示了虚参数的合法使用。在第一个中,结构定义中根本没有使用参数 `T1`。在第二个中,参数 `T1` 仅用作虚类型参数的实参。 + +```move +struct S1 { f: u64 } + ^^ + Ok: T1 没有出现在结构定义中 + +struct S2 { f: S1 } + ^^ + Ok: T1 出现在虚位置 +``` + +以下代码展示违反规则的示例: + +```move +struct S1 { f: T } + ^ + 错误:不是虚位置 + +struct S2 { f: T } + +struct S3 { f: S2 } + ^ + 错误:不是虚位置 +``` + +#### 实例化 + +实例化结构时,在派生结构能力时排除虚参数的实参。例如,考虑以下代码: + +```move +struct S has copy { f: T1 } +struct NoCopy {} +struct HasCopy has copy {} +``` + +现在考虑类型 `S`。因为 `S` 是用 `copy` 定义的,并且所有非虚参数都有 copy 能力,所以 `S` 也有 copy 能力。 + +#### 具有能力约束的虚类型参数 + +能力约束和虚类型参数是正交特征,虚参数可以用能力约束来声明。当实例化具有能力约束的虚类型参数时,类型实参必须满足该约束,即使该参数是虚的(phantom)。例如,以下定义是完全有效的: + +```move +struct S {} +``` + +通常用来限制应用并且 `T` 只能用具有 `copy` 的实参实例化。 + +## 约束 + +在上面的示例中,我们演示了如何使用类型参数来定义稍后可以由调用者插入的“未知”类型。然而,这意味着类型系统几乎没有关于类型的信息,并且必须以非常保守的方式执行检查。在某种意义上,类型系统必须为不受约束的泛型假设最坏的情况。简单地说,默认泛型类型参数没有[能力](./abilities.md)。 + +这就是约束发挥作用的地方:它们提供了一种方法来指定这些未知类型具有哪些属性,以便类型系统可以允许在其他情况下不安全的操作。 + +### 声明约束 + +可以使用以下语法对类型参数施加约束。 + +```move +// T 是类型参数的名称 +T: (+ )* +``` + +`` 可以是四种[能力](./abilities.md)中的任何一种,一个类型参数可以同时被多种能力约束。因此,以下所有内容都是有效的类型参数声明: + +```move +T: copy +T: copy + drop +T: copy + drop + store + key +``` + +### 验证约束 + +在调用点检查约束,所以下面的代码不会编译。 + +```move +struct Foo { x: T } + +struct Bar { x: Foo } +// ^ 错误!u8 没有 'key' + +struct Baz { x: Foo } +// ^ 错误! T 没有 'key' +``` + +```move +struct R {} + +fun unsafe_consume(x: T) { + // 错误!x 没有 'drop' +} + +fun consume(x: T) { + // 合法! + // x 会被自动删除 +} + +fun foo() { + let r = R {}; + consume(r); + // ^ 错误!R 没有 'drop' +} +``` + +```move +struct R {} + +fun unsafe_double(x: T) { + (copy x, x) + // 错误!x 没有 'copy' +} + +fun double(x: T) { + (copy x, x) // 合法! +} + +fun foo(): (R, R) { + let r = R {}; + double(r) + // ^ 错误!R 没有 'copy' +} +``` + +有关详细信息,请参阅有关[条件能力与泛型类型](./abilities.md#conditional-abilities-and-generic-types)。 + +## 递归的限制 + +### 递归结构体 + +泛型结构不能直接或间接包含相同类型的字段,即使具有不同类型的参数也是如此。以下所有结构定义均无效: + +```move +struct Foo { + x: Foo // 错误!'Foo' 包含 'Foo' +} + +struct Bar { + x: Bar // 错误!'Bar' 包含 'Bar' +} + +// 错误!'A' 和 'B' 形成一个循环,这也是不允许的。 +struct A { + x: B +} + +struct B { + x: A + y: A +} +``` + +### 高级主题:类型级递归 + +Move 允许递归调用泛型函数。然而,当与泛型结构体结合使用时,在某些情况下这可能会创建无限数量的类型,这意味着会给编译器、虚拟机(mv)和其他语言组件增加不必要的复杂性。因此,这样的递归是被禁止的。 + +被允许的用法: + +```move +address 0x2 { +module m { + struct A {} + + // 有限多种类型 —— 允许。 + // foo -> foo -> foo -> ... is valid + fun foo() { + foo(); + } + + // 有限多种类型 —— 允许。 + // foo -> foo> -> foo> -> ... is valid + fun foo() { + foo>(); + } +} +} +``` + +不被允许的用法: + +```move +address 0x2 { +module m { + struct A {} + + // 无限多种类型 —— 不允许。 + // 错误! + // foo -> foo> -> foo>> -> ... + fun foo() { + foo>(); + } +} +} +``` + +```move +address 0x2 { +module n { + struct A {} + + // 无限多种类型 —— 不允许。 + // 错误! + // foo -> bar -> foo> + // -> bar, T2> -> foo, A> + // -> bar, A> -> foo, A>> + // -> ... + fun foo() { + bar(); + } + + fun bar { + foo>(); + } +} +} +``` + +请注意,类型级递归的检查基于对调用点的保守分析,所以不考虑控制流或运行时值。 + +```move +address 0x2 { +module m { + struct A {} + + fun foo(n: u64) { + if (n > 0) { + foo>(n - 1); + }; + } +} +} +``` + +上面示例中的函数在技术上将终止任何给定的输入,因此只会创建有限多种类型,但它仍然被 Move 的类型系统视为无效的。 diff --git a/language/documentation/book/translations/move-book-zh/src/global-storage-operators.md b/language/documentation/book/translations/move-book-zh/src/global-storage-operators.md new file mode 100644 index 0000000000..d31b2959f4 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/global-storage-operators.md @@ -0,0 +1,312 @@ +# 全局存储 - 操作(Global Storage - Operators) + +Move programs can create, delete, and update [resources](./structs-and-resources.md) in global storage using the following five instructions: + +Move程序可以使用下面五种指令创建、删除、更新全局存储中的[资源](./structs-and-resources.md): + +| Operation | Description | Aborts? | +---------------------------------------- |---------------------------------------------------------------- |---------------------------------------- | +|`move_to(&signer,T)` | Publish `T` under `signer.address` | If `signer.address` already holds a `T` | +|`move_from(address): T` | Remove `T` from `address` and return it | If `address` does not hold a `T` | +|`borrow_global_mut(address): &mut T` | Return a mutable reference to the `T` stored under `address` | If `address` does not hold a `T` | +|`borrow_global(address): &T` | Return an immutable reference to the `T` stored under `address` | If `address` does not hold a `T` | +|`exists(address): bool` | Return `true` if a `T` is stored under `address` | Never + +| 操作符 | 描述 | 出错 | +---------------------------------------- |------------------------------------------------------ |---------------------------------- | +|`move_to(&signer,T)` | 在 `signer.address` 下发布 `T` | 如果 `signer.address` 已经存在 `T` | +|`move_from(address): T` | 从 `address` 下删除 `T` 并返回 | 如果 `address` 下没有 `T` | +|`borrow_global_mut(address): &mut T` | 返回 `address` 下 `T` 的可变引用 mutable reference | 如果 `address` 下没有 `T` | +|`borrow_global(address): &T` | 返回 `address` 下 `T` 的不可变引用 immutable reference | 如果 `address` 下没有 `T` | +|`exists(address): bool` | 返回 `address` 下的 `T` | 永远不会 | + | + +Each of these instructions is parameterized by a type `T` with the [`key` ability](./abilities.md). However, each type `T` *must be declared in the current module*. This ensures that a resource can only be manipulated via the API exposed by its defining module. The instructions also take either an [`address`](./address.md) or [`&signer`](./signer.md) representing the account address where the resource of type `T` is stored. + +每个指令的参数 `T` 都具有 [`key` 能力](./abilities.md)。然而,类型 `T` *必须在当前模块*中声明。这确保资源只能通过当前模块暴露的 API 来操作。指令在存储 `T` 类型资源的同时,使用 [`address`](./address.md) 或 [`&signer`](./signer.md) 表示账户地址。 + + +## 资源参考(References to resources) + +References to global resources returned by `borrow_global` or `borrow_global_mut` mostly behave like references to local storage: they can be extended, read, and written using ordinary [reference operators](./references.md) and passed as arguments to other function. However, there is one important difference between local and global references: **a function cannot return a reference that points into global storage**. For example, these two functions will each fail to compile: + +`borrow_global` 或 `borrow_global_mut` 指令返回的全局资源引用在大多数情况下类似本地存储的引用:它们可以通过[引用操作](./references.md)进行拓展、读和写,也可以作为其它函数的参数。然而本地引用和全局引用有个重要差异:**函数不能返回指向全局存储的引用**。例如,下面两个函数编译会失败: + + +```move +struct R has key { f: u64 } +// 不能编译 // will not compile +fun ret_direct_resource_ref_bad(a: address): &R { + borrow_global(a) // error! +} +// 也不能编译 // also will not compile +fun ret_resource_field_ref_bad(a: address): &u64 { + &borrow_global(a).f // error! +} +``` + +Move must enforce this restriction to guarantee absence of dangling references to global storage. [This](#reference-safety-for-global-resources) section contains much more detail for the interested reader. + +Move必须强制这种限制来保证全局存储引用不会出现空引用。对于感兴趣的读者,[此节](#全局资源引用安全)包含了更多的细节。 + + +## 使用泛型的全局存储操作(Global storage operators with generics) + +Global storage operations can be applied to generic resources with both instantiated and uninstantiated generic type parameters: + +全局存储操作可以与实例化和未实例化的泛型资源参数使用: + + +```move +struct Container has key { t: T } + +/// 发布用于存储调用者提供 T 类型对象的 Container /// Publish a Container storing a type T of the caller's choosing +fun publish_generic_container(account: &signer, t: T) { + move_to>(account, Container { t }) +} + +/// 发布存储 u64 类型的 Container /// Publish a container storing a u64 +fun publish_instantiated_generic_container(account: &signer, t: u64) { + move_to>(account, Container { t }) +} +``` + +The ability to index into global storage via a type parameter chosen at runtime is a powerful Move feature known as *storage polymorphism*. For more on the design patterns enabled by this feature, see [Move generics](./generics.md). + +能够通过参数类型在运行时中索引全局存储的能力是 Move 的强大特性,该特性称之为*存储多态性*。关于此特性更多的设计模式,请参考[Move泛型](./generics.md)这节。 + +## 示例: `Counter` (Example: `Counter`) + +The simple `Counter` module below exercises each of the five global storage operators. The API exposed by this module allows: + +- Anyone to publish a `Counter` resource under their account +- Anyone to check if a `Counter` exists under any address +- Anyone to read or increment the value of a `Counter` resource under any address +- An account that stores a `Counter` resource to reset it to zero +- An account that stores a `Counter` resource to remove and delete it + +下面简单的 `Counter` 模块使用五种全局存储操作。该模块暴露的API允许: + +- 任何人可以在他们的账户下发布 `Counter` 资源。 +- 任何人可以检查任何地址下是否包含 `Counter`。 +- 任何人可以读或增加任何地址下的 `Counter` 值。 +- 存储 `Counter` 资源的账号可以将其重置为 0。 +- 存储 `Counter` 资源的账号可以删除该对象。 + +```move +address 0x42 { +module counter { + use std::signer; + + /// 包含整数的资源 /// Resource that wraps an integer counter + struct Counter has key { i: u64 } + + /// 给定账户下发布带有 `i` 值的 `Counter` 资源 /// Publish a `Counter` resource with value `i` under the given `account` + public fun publish(account: &signer, i: u64) { + // “打包"(创建)Counter 资源。这是需要授权的操作,只能在声明 `Counter` 资源的此模块内执行。 // "Pack" (create) a Counter resource. This is a privileged operation that can only be done inside the module that declares the `Counter` resource + move_to(account, Counter { i }) + } + + /// 读取 `addr` 地址下 `Counter` 内的值 /// Read the value in the `Counter` resource stored at `addr` + public fun get_count(addr: address): u64 acquires Counter { + borrow_global(addr).i + } + + /// 增加 `addr` 地址下 `Counter` 内的值 /// Increment the value of `addr`'s `Counter` resource + public fun increment(addr: address) acquires Counter { + let c_ref = &mut borrow_global_mut(addr).i; + *c_ref = *c_ref + 1 + } + + /// 将 `account` 的 `Counter` 重置为 0 /// Reset the value of `account`'s `Counter` to 0 + public fun reset(account: &signer) acquires Counter { + let c_ref = &mut borrow_global_mut(signer::address_of(account)).i; + *c_ref = 0 + } + + /// 删除 `account` 的 `Counter` 资源并返回其内值 /// Delete the `Counter` resource under `account` and return its value + public fun delete(account: &signer): u64 acquires Counter { + // 删除 Counter 资源 // remove the Counter resource + let c = move_from(signer::address_of(account)); + // 将 `Counter` 资源“拆”为字段。这是需要授权的操作,只能在声明 `Counter` 资源的此模块内执行。 // "Unpack" the `Counter` resource into its fields. This is a privileged operation that can only be done inside the module that declares the `Counter` resource + let Counter { i } = c; + i + } + + /// 如果 `addr` 下包含 `Counter` 资源,则返回 `true`。 /// Return `true` if `addr` contains a `Counter` resource + public fun exists(addr: address): bool { + exists(addr) + } +} +} +``` + +## `acquires` 函数标注(Annotating functions with `acquires`) + +In the `counter` example, you might have noticed that the `get_count`, `increment`, `reset`, and `delete` functions are annotated with `acquires Counter`. A Move function `m::f` must be annotated with `acquires T` if and only if: + +- The body of `m::f` contains a `move_from`, `borrow_global_mut`, or `borrow_global` instruction, or +- The body of `m::f` invokes a function `m::g` declared in the same module that is annotated with `acquires` + +在 `counter` 例子中,可以注意到 `get_count`、`increment`、`reset` 和 `delete` 方法都使用 `acquires Counter` 进行标注。函数 `m::f` 在且仅在下述情况必须使用 `acquires T` 进行标注: + +- `m::f` 的主体包含 `move_from`、`borrow_global_mut` 或 `borrow_global` 指令调用 +- `m::f` 的主体调用了同模块内被 `acquires` 注解的 `m::g` 的函数 + +For example, the following function inside `Counter` would need an `acquires` annotation: + +例如,下面 `Counter` 内的函数需要使用 `acquires` 标注: + +```move +// 由于 `increment` 使用了 `acquires` 标注,所以函数需要 `acquires` // Needs `acquires` because `increment` is annotated with `acquires` +fun call_increment(addr: address): u64 acquires Counter { + counter::increment(addr) +} +``` + +However, the same function *outside* `Counter` would not need an annotation: + +然而,在 `Counter` *外面*的函数则不需要进行标注: + + +```move +address 0x43 { +module m { + use 0x42::counter; + + // 可以,仅在函数声明在同一模块内时需要标注 // Ok. Only need annotation when resource acquired by callee is declared in the same module + fun call_increment(addr: address): u64 { + counter::increment(addr) + } +} +} +``` + +If a function touches multiple resources, it needs multiple `acquires`: + +如果函数需要多个资源,`acquires` 则需要多个参数: + +```move= +address 0x42 { +module two_resources { + struct R1 has key { f: u64 } + struct R2 has key { g: u64 } + + fun double_acquires(a: address): u64 acquires R1, R2 { + borrow_global(a).f + borrow_global.g + } +} +} +``` + +The `acquires` annotation does not take generic type parameters into account: + +`acquires` 标注不会将泛型类型参数纳入声明中: + + +```move= +address 0x42 { +module m { + struct R has key { t: T } + + // 效果为 `acquires R` 而不是 `acquires R` // `acquires R`, not `acquires R` + fun acquire_generic_resource(a: addr) acquires R { + let _ = borrow_global>(a); + } + + // 效果为 `acquires R` 而不是 `acquiresR` // `acquires R`, not `acquires R + fun acquire_instantiated_generic_resource(a: addr) acquires R { + let _ = borrow_global>(a); + } +} +} +``` + +Finally: redundant `acquires` are not allowed. Adding this function inside `Counter` will result in a compilation error: + +最后:不允许使用不必要的 `acquires`。在 `Counter` 内添加下述方法将会导致编译错误: + + +```move +// 下面代码不会编译,因为函数体没有使用全局存储指令也没调用使用 `acquires` 注解的函数 // This code will not compile because the body of the function does not use a global storage instruction or invoke a function with `acquires` +fun redundant_acquires_bad() acquires Counter {} +``` + +For more information on `acquires`, see [Move functions](./functions.md). + +关于 `acquires` 更多信息,参见 [Move 函数](./functions.md)。 + +## 全局资源引用安全(Reference Safety For Global Resources) + +Move prohibits returning global references and requires the `acquires` annotation to prevent dangling references. This allows Move to live up to its promise of static reference safety (i.e., no dangling references, no `null` or `nil` dereferences) for all [reference](./references.md) types. + +Move 禁止返回全局引用并且需要使用 `acquires` 标注来防止空引用。这使 Move 保证了所有[引用](./references.md)类型的静态引用安全性(例如,没有空引用、不会解引用 `null` 或 `nil` 对象)。 + +This example illustrates how the Move type system uses `acquires` to prevent a dangling reference: + +这个例子展示了 Move 类型系统如何通过使用 `acquires` 来防止空引用: + +```move= +address 0x42 { +module dangling { + struct T has key { f: u64 } + + fun borrow_then_remove_bad(a: address) acquires T { + let t_ref: &mut T = borrow_global_mut(a); + let t = remove_t(a); // 类型系统不允许 t_ref 这种空引用 // type system complains here + // t_ref now dangling! + let uh_oh = *&t_ref.f + } + + fun remove_t(a: address): T acquires T { + move_from(a) + } + +} +} +``` + +In this code, line 6 acquires a reference to the `T` stored at address `a` in global storage. The callee `remove_t` then removes the value, which makes `t_ref` a dangling reference. + +代码中第六行获取了 `a` 地址在全局存储中 `T` 类型资源的引用。`remove_t` 调用删除了该值,使 `t_ref` 变成空引用。 + + +Fortunately, this cannot happen because the type system will reject this program. The `acquires` annotation on `remove_t` lets the type system know that line 7 is dangerous, without having to recheck or introspect the body of `remove_t` separately! + +幸运的是,由于类型系统拒绝编译程序导致这种情况不会发生。`remove_t` 方法的 `acquires` 标注让类型系统知道第七行是危险的,不需要再分析 `remove_t` 的函数体。 + +The restriction on returning global references prevents a similar, but even more insidious problem: + +禁止返回全局引用的限制同时也防止了类似却更隐晦的问题: + +```move= +address 0x42 { +module m1 { + struct T has key {} + + public fun ret_t_ref(a: address): &T acquires T { + borrow_global(a) // 报错 类型系统在这不能继续编译 // error! type system complains here + } + + public fun remove_t(a: address) acquires T { + let T {} = move_from(a); + } +} + +module m2 { + fun borrow_then_remove_bad(a: address) { + let t_ref = m1::ret_t_ref(a); + let t = m1::remove_t(a); // t_ref 为空引用 // t_ref now dangling! + } +} +} +``` + +Line 16 acquires a reference to a global resource `m1::T`, then line 17 removes that same resource, which makes `t_ref` dangle. In this case, `acquires` annotations do not help us because the `borrow_then_remove_bad` function is outside of the `m1` module that declares `T` (recall that `acquires` annotations can only be used for resources declared in the current module). Instead, the type system avoids this problem by preventing the return of a global reference at line 6. + +第十六行获取了全局资源 `m1::T` 类型的引用,然后第十七行删除了同一资源,这使 `t_ref` 变成空引用。在这个例子中,`acquires` 标注没有帮助到我们,因为 `borrow_then_remove_bad` 函数在声明了 `T` 类型(回顾 `acquires` 标注只用在声明此类型的模块内)的 `m1` 模块外。然而禁止返回全局引用的规则使第六行避免了这个问题。 + + +Fancier type systems that would allow returning global references without sacrificing reference safety are possible, and we may consider them in future iterations of Move. We chose the current design because it strikes a good balance between expressivity, annotation burden, and type system complexity. + +允许返回全局引用而尽可能不牺牲引用安全的高级类型系统是可行的,我们将会在 Move 未来的迭代过程中考虑此事。我们选择目前的设计方式是因为它很好的平衡了语言表现力、复杂的标注和复杂的类型系统三者的关系。 diff --git a/language/documentation/book/translations/move-book-zh/src/global-storage-structure.md b/language/documentation/book/translations/move-book-zh/src/global-storage-structure.md new file mode 100644 index 0000000000..763d253d52 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/global-storage-structure.md @@ -0,0 +1,14 @@ +# 全局存储 —— 结构 + +Move 程序的目的是[读取和写入](./global-storage-operators.md)树形的持久全局存储。程序不能访问文件系统、网络或任何此树以外的数据。 + +在伪代码中,全局存储看起来像: + +```move +struct GlobalStorage { + resources: Map<(address, ResourceType), ResourceValue> + modules: Map<(address, ModuleName), ModuleBytecode> +} +``` + +从结构上讲,全局存储是一个[森林(forest)](https://en.wikipedia.org/wiki/Tree_(graph_theory)),这个森林由以账户[地址(`address`)](./address.md)为根的树组成。每个地址可以存储[资源(resource)](./structs-and-resources.md)数据和[模块(module)](./modules-and-scripts.md)代码。如上面的伪代码所示,每个地址(`address`)最多可以存储一个给定类型的资源值,最多可以存储一个给定名称的模块。 diff --git a/language/documentation/book/translations/move-book-zh/src/integers.md b/language/documentation/book/translations/move-book-zh/src/integers.md new file mode 100644 index 0000000000..a1a70430b0 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/integers.md @@ -0,0 +1,214 @@ +# 整数 (Integers) + +Move supports three unsigned integer types: `u8`, `u64`, and `u128`. Values of these types range from 0 to a maximum that depends on the size of the type. + +| Type | Value Range | +| -------------------------------- | ------------------------ | +| Unsigned 8-bit integer, `u8` | 0 to 28 - 1 | +| Unsigned 64-bit integer, `u64` | 0 to 264 - 1 | +| Unsigned 128-bit integer, `u128` | 0 to 2128 - 1 | + + +Move 支持三种无符号整数类型:`u8`、`u64` 和 `u128`。这些类型的值范围从 0 到最大值,最大值的具体取值取决于整数类型。 + +| 类型 | 取值范围 | +|---------------------------|--------------------------| +| 无符号 8位 整数, `u8` | 0 to 28 - 1 | +| 无符号 64位 整数, `u64` | 0 to 264 - 1 | +| 无符号 128位 整数, `u128` | 0 to 2128 - 1 | + + +## 字面值(Literal) + +Literal values for these types are specified either as a sequence of digits (e.g.,`112`) or as hex literals, e.g., `0xFF`. The type of the literal can optionally be added as a suffix, e.g., `112u8`. If the type is not specified, the compiler will try to infer the type from the context where the literal is used. If the type cannot be inferred, it is assumed to be `u64`. + +If a literal is too large for its specified (or inferred) size range, an error is reported. + +(在Move中)这些类型的字面值指定为数字序列(例如:112)或十六进制文字(例如:0xFF), 可以选择将字面值的类型定义为后缀, 例如 `112u8`。如果未指定类型,编译器将尝试从使用字面值的上下文推断类型。如果无法推断类型,则默认为 `u64。 + +如果字面值太大,超出其指定的(或推断的)大小范围,则会报错。 + +### 例如: + +```jsx +// literals with explicit annotations; +let explicit_u8 = 1u8; +let explicit_u64 = 2u64; +let explicit_u128 = 3u128; + +// literals with simple inference +let simple_u8: u8 = 1; +let simple_u64: u64 = 2; +let simple_u128: u128 = 3; + +// literals with more complex inference +let complex_u8 = 1; // inferred: u8 +// right hand argument to shift must be u8 +let _unused = 10 << complex_u8; + +let x: u8 = 0; +let complex_u8 = 2; // inferred: u8 +// arguments to `+` must have the same type +let _unused = x + complex_u8; + +let complex_u128 = 3; // inferred: u128 +// inferred from function argument type +function_that_takes_u128(complex_u128); + +// literals can be written in hex +let hex_u8: u8 = 0x1; +let hex_u64: u64 = 0xCAFE; +let hex_u128: u128 = 0xDEADBEEF; +``` + +## 运算集 (Operations) + +### 算术运算 (Arithmetic) + +Each of these types supports the same set of checked arithmetic operations. For all of these operations, both arguments (the left and right side operands) must be of the same type. If you need to operate over values of different types, you will need to first perform a cast. Similarly, if you expect the result of the operation to be too large for the integer type, perform a cast to a larger size before performing the operation. + +每一种(无符号整数)类型都支持相同算术运算集。对于所有这些运算,两个参数(左侧和右侧操作数)必须是同一类型。如果您需要对不同类型的值进行运算,则需要首先执行强制转换。同样,如果您预计运算结果对于当下整数类型来说太大,请在执行运算之前将之转换为更大的整数类型。 + +All arithmetic operations abort instead of behaving in a way that mathematical integers would not (e.g., overflow, underflow, divide-by-zero). + +| Syntax | Operation | Aborts If | +| ------ | ------------------- | ---------------------------------------- | +| `+` | addition | Result is too large for the integer type | +| `-` | subtraction | Result is less than zero | +| `*` | multiplication | Result is too large for the integer type | +| `%` | modular division | The divisor is `0` | +| `/` | truncating division | The divisor is `0` | + +### [Bitwise](https://move-language.github.io/move/integers.html#bitwise) + +算术运算在遇到异常时将会中止,而不是以上溢、下溢、被零除等数学整数未定义的的方式输出结果。 + +| 句法 | 操作 | 中止条件 | +| ------ | ------------| ---------------------------------------- | +| `+` | 加法 | 结果对于整数类型来说太大了 | +| `-` | 减法 | 结果小于零 | +| `*` | 乘法 | 结果对于整数类型来说太大了 | +| `%` | 取余运算 | 除数为 `0` | +| `/` | 截断除法 | 除数为 `0` | + +### 位运算 (Bitwise) + +The integer types support the following bitwise operations that treat each number as a series of individual bits, either 0 or 1, instead of as numerical integer values. + +Bitwise operations do not abort. + +| Syntax | Operation | Description | +|---------------------|-------------|-------------------------------------------------------| +| `&` | bitwise and | Performs a boolean and for each bit pairwise | +| | | bitwise or | Performs a boolean or for each bit pairwise | +| `^` | bitwise xor | Performs a boolean exclusive or for each bit pairwise | + +整数类型支持下列位运算,即将每个数字视为一系列单独的位:0 或 1,而不是整型数值。 + +位运算不会中止。 + +| 语法 | 操作符 | 描述 | +|---------------------|----------|----------------------------| +| `&` | 按位和 | 对每个位成对执行布尔值和 | +| | | 按位或 | 对每个位成对执行布尔值或 | +| `^` | 按位异或 | 对每个位成对执行布尔值异或 | + +### 位移 (Bit shift) + +Similar to the bitwise operations, each integer type supports bit shifts. But unlike the other operations, the righthand side operand (how many bits to shift by) must *always* be a `u8` and need not match the left side operand (the number you are shifting). + +Bit shifts can abort if the number of bits to shift by is greater than or equal to `8`, `64`, or `128` for `u8`, `u64`, and `u128` respectively. + +| Syntax | Operation | Aborts if | +| ------ | ----------- | ------------------------------------------------------------ | +| `<<` | shift left | Number of bits to shift by is greater than the size of the integer type | +| `>>` | shift right | Number of bits to shift by is greater than the size of the integer type | + +与按位运算类似,每种整数类型都支持位移(bit shifts)。但与其他运算不同的是,右侧操作数(要移位多少位)必须始终是 `u8`  并且不需要与左侧操作数类型(您要移位的数字)匹配。 + +如果要移位的位数分别大于或等于 `8`、`64`, `u128` 或 `128` 的 `u8`, `u64`, 则移位可以中止。 + +| 句法 | 操作 | 中止条件 | +| ------ | ----------- | ------------------------------------------------------------ | +| `<<` | 左移 | 要移位的位数大于整数类型的大小 | +| `>>` | 右移 | 要移位的位数大于整数类型的大小 | + +### 比较运算 (Comparisons) + +Integer types are the *only* types in Move that can use the comparison operators. Both arguments need to be of the same type. If you need to compare integers of different types, you will need to [cast](https://move-language.github.io/move/integers.html#casting) one of them first. + +Comparison operations do not abort. + +| Syntax | Operation | +| ------ | ------------------------ | +| `<` | less than | +| `>` | greater than | +| `<=` | less than or equal to | +| `>=` | greater than or equal to | + +整数类型是 Move 中唯一可以使用比较(Comparisons)运算符的类型。两个参数必须是同一类型。如果您需要比较不同类型的整数,则需要先转换其中一个。 + +比较操作不会中止。 + +| 句法 | 操作 | +| ------ | ------------------------ | +| `<` | 小于 | +| `>` | 大于 | +| `<=` | 小于等于 | +| `>=` | 大于等于 | + +### 相等 (Equality) + +Like all types with [`drop`](https://move-language.github.io/move/abilities.html) in Move, all integer types support the ["equal"](https://move-language.github.io/move/equality.html) and ["not equal"](https://move-language.github.io/move/equality.html) operations. Both arguments need to be of the same type. If you need to compare integers of different types, you will need to [cast](https://move-language.github.io/move/integers.html#casting) one of them first. + +Equality operations do not abort. + +| Syntax | Operation | +| ------ | --------- | +| `==` | equal | +| `!=` | not equal | + +For more details see the section on [equality](https://move-language.github.io/move/equality.html) + +与 Move 中的所有具有[`drop`](./chapter_19_abilities.html)能力的类型一样,所有整数类型都支持 ["equal(等于)"](./chapter_11_equality.html) 和 ["not equal(不等于)](./chapter_11_equality.html)运算。两个参数必须是同一类型。如果您需要比较不同类型的整数,则需要先转换其中一个。 + +相等(Equality)运算不会中止。 + +| 句法 | 操作 | +| ------ | --------- | +| `==` | 等于 | +| `!=` | 不等于 | + +更多细节可以参考[相等]([equality](https://move-language.github.io/move/equality.html))章节。 + +## 转换 (Casting) + +Integer types of one size can be cast to integer types of another size. Integers are the only types in Move that support casting. + +Casts *do not* truncate. Casting will abort if the result is too large for the specified type + +| Syntax | Operation | Aborts if | +| ---------- | ---------------------------------------------------- | -------------------------------------- | +| `(e as T)` | Cast integer expression `e` into an integer type `T` | `e` is too large to represent as a `T` | + +Here, the type of `e` must be `u8`, `u64`, or `u128` and `T` must be `u8`, `u64`, or `u128`. + +For example: + +- `(x as u8)` +- `(2u8 as u64)` +- `(1 + 3 as u128)` + +一种大小的整数类型可以转换为另一种大小的整数类型。整数是 Move 中唯一支持强制转换的类型。 + +强制转换不会截断。如果结果对于指定类型来说太大,则转换将中止。 + +| Syntax | 操作 | 中止条件 | +| ---------- | ---------------------------------------------------- | -------------------------------------- | +| `(e as T)` | 将整数表达式 `e` 转换为整数类型 `T` | `e` 太大而不能表示为 `T` | + +## 所有权 (Ownership) + +As with the other scalar values built-in to the language, integer values are implicitly copyable, meaning they can be copied without an explicit instruction such as [`copy`](https://move-language.github.io/move/variables.html#move-and-copy). + +与语言内置的其他标量值一样,整数值是隐式可复制的,这意味着它们可以在没有明确指令如[`copy`](./variables.md#move-and-copy)的情况下复制。 diff --git a/language/documentation/book/translations/move-book-zh/src/introduction.md b/language/documentation/book/translations/move-book-zh/src/introduction.md new file mode 100644 index 0000000000..5e3ea6f79f --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/introduction.md @@ -0,0 +1,47 @@ +# 引言 (Introduction) + +Welcome to Move, a next generation language for secure, sandboxed, and formally verified programming. Its first use case is for the Diem blockchain, where Move provides the foundation for its implementation. Move allows developers to write programs that flexibly manage and transfer assets, while providing the security and protections against attacks on those assets. However, Move has been developed with use cases in mind outside a blockchain context as well. + +欢迎来到Move的世界,Move是一种安全、沙盒式和形式化验证的下一代编程语言,它的第一个用例是 Diem 区块链(当时名字叫Libra, 脸书团队开发的项目, 译者注), Move 为其实现提供了基础。 Move 允许开发人员编写灵活管理和转移数字资产的程序,同时提供安全保护,防止对那些链上资产的攻击。不仅如此,Move 也可用于区块链世界之外的开发场景。 + +Move takes its cue from [Rust](https://www.rust-lang.org/) by using resource types with move (hence the name) semantics as an explicit representation of digital assets, such as currency. + +Move 的诞生从[Rust](https://www.rust-lang.org/)中吸取了灵感,Move也是因为使用具有移动(move)语义的资源类型作为数字资产(例如货币)的显式表示而得名。 + +## Move是为谁准备的?(Who is Move for?) + +Move was designed and created as a secure, verified, yet flexible programming language. The first use of Move is for the implementation of the Diem blockchain. That said, the language is still evolving. Move has the potential to be a language for other blockchains, and even non-blockchain use cases as well. + +Move语言被设计和创建为安全、可验证, 同时兼顾灵活性的编程语言。Move的第一个应用场景是用于Diem区块链的开发。现在,Move语言仍在不断发展中。Move 还有成为其他区块链,甚至非区块链用例开发语言的潜质。 + +Given custom Move modules will not be supported at the [launch](https://diem.com/white-paper/#whats-next) of the Diem Payment Network (DPN), we are targeting an early Move Developer persona. + +鉴于在 Diem 支付网络 (DPN) [启动](https://diem.com/white-paper/#whats-next)时将不支持自定义 Move 模块(custom Move modules),我们的目标是早期的 Move 开发人员。 + +The early Move Developer is one with some programming experience, who wants to begin understanding the core programming language and see examples of its usage. + +早期的 Move 开发人员应该是具有一定编程经验的程序员,他们愿意了解编程语言核心,并探索它的用法。 + +### 爱好者 (Hobbyists) + +Understanding that the capability to create custom modules on the Diem Payment Network will not be available at launch, the hobbyist Move Developer is interested in learning the intricacies of the language. She will understand the basic syntax, the standard libraries available, and write example code that can be executed using the Move CLI. The Move Developer may even want to dig into understanding how the Move Virtual Machine executes the code she writes. + +作为(Move语言)爱好者角色,首先需要明白在Diem支付网络上创建自定义模块(custom modules)是不可能的,其次,你还要对探索这门语言的复杂性保持兴趣。你将了解基本语法、可用的标准库,并编写可以用的Move CLI执行的示例代码。如果可能,你甚至可以去尝试体验Move虚拟机如何执行你自己编写的代码。 + +### 核心贡献者 (Core Contributor) + +Beyond a hobbyist wanting to stay ahead of the curve for the core programming language is someone who may want to [contribute](https://diem.com/en-US/cla-sign/) directly to Move. Whether this includes submitting language improvements or even, in the future, adding core modules available on the Diem Payment Network, the core contributor will understand Move at a deep level. + +核心贡献者指那些超越爱好者并想在核心编程语言方面保持领先,还直接为 Move 做出[贡献](https://diem.com/en-US/cla-sign/)的人。无论是提交语言改进,甚至未来添加 Diem 支付网络上可用的核心模块等,核心贡献者都将深入了解Move。 + +### Move不适用于哪些人?(Who Move is currently not targeting) + +Currently, Move is not targeting developers who wish to create custom modules and contracts for use on the Diem Payment Network. We are also not targeting novice developers who expect a completely polished developer experience even in testing the language. + +目前,Move 并不适用那些希望在在 Diem 支付网络上创建自定义模块和合约的开发人员。我们也不针对期望在测试语言时就能获得完美开发体验的初学开发者。 + +## 从哪里开始?(Where Do I Start?) + +Begin with understanding [modules and scripts](https://move-language.github.io/move/modules-and-scripts.html) and then work through the [Move Tutorial](https://move-language.github.io/move/creating-coins.html). + +你可以从了解模块和脚本([modules and scripts](./modules-and-scripts.html))开始,然后跟随Move教程([Move Tutorial](./move-tutorial.html))进行练习。 diff --git a/language/documentation/book/translations/move-book-zh/src/loops.md b/language/documentation/book/translations/move-book-zh/src/loops.md new file mode 100644 index 0000000000..34626ed284 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/loops.md @@ -0,0 +1,215 @@ +# While and Loop + +Move offers two constructs for looping: `while` and `loop`. + +Move 提供了两种循环结构: `while` and `loop`. + +## `while` 循环 + +The `while` construct repeats the body (an expression of type unit) until the condition (an expression of type `bool`) evaluates to `false`. + +Here is an example of simple `while` loop that computes the sum of the numbers from `1` to `n`: + +`while` 会重复执行结构(一个 `unit` 类型的表达式), 直到条件语句(`bool` 类型的表达式)运算结果为 `false`。 + +下面是一个简单的 `while` 循环的例子,计算从 `1` 到 `n` 数字之和: + +```move +fun sum(n: u64): u64 { + let sum = 0; + let i = 1; + while (i <= n) { + sum = sum + i; + i = i + 1 + }; + + sum +} +``` + +Infinite loops are allowed: + +无限循环是被允许的: + +```move= +fun foo() { + while (true) { } +} +``` + +### `break` + +The `break` expression can be used to exit a loop before the condition evaluates to `false`. For example, this loop uses `break` to find the smallest factor of `n` that's greater than 1: + +`break` 表达式可用于在条件计算结果为 `false` 之前退出循环。例如,这个循环使用 `break` 查找 `n` 大于1的最小因子: + +```move +fun smallest_factor(n: u64): u64 { + // assuming the input is not 0 or 1 + let i = 2; + while (i <= n) { + if (n % i == 0) break; + i = i + 1 + }; + + i +} +``` + +The `break` expression cannot be used outside of a loop. + +`break` 表达式不能在循环之外使用。 + +### `continue` + +The `continue` expression skips the rest of the loop and continues to the next iteration. This loop uses `continue` to compute the sum of `1, 2, ..., n`, except when the number is divisible by 10: + +`continue` 表达式跳过当前循环的剩余部分, 并继续下一轮迭代。下面的例子, 使用 `continue` 去计算 `1, 2, ..., n` 的总和,过滤掉不能被10整除的数: + +```move +fun sum_intermediate(n: u64): u64 { + let sum = 0; + let i = 0; + while (i < n) { + i = i + 1; + if (i % 10 == 0) continue; + sum = sum + i; + }; + + sum +} +``` + +The `continue` expression cannot be used outside of a loop. + +`continue` 表达式不能在循环之外使用。 + +### The type of `break` and `continue` + +`break` and `continue`, much like `return` and `abort`, can have any type. The following examples illustrate where this flexible typing can be helpful: + +`break` and `continue`, 和 `return` and `abort` 很相像, 可以是任何类型。下面的例子说明了这种灵活的类型在那些方面有帮助: + +```move +fun pop_smallest_while_not_equal( + v1: vector, + v2: vector, +): vector { + let result = vector::empty(); + while (!vector::is_empty(&v1) && !vector::is_empty(&v2)) { + let u1 = *vector::borrow(&v1, vector::length(&v1) - 1); + let u2 = *vector::borrow(&v2, vector::length(&v2) - 1); + let popped = + if (u1 < u2) vector::pop_back(&mut v1) + else if (u2 < u1) vector::pop_back(&mut v2) + else break; // Here, `break` has type `u64` + vector::push_back(&mut result, popped); + }; + + result +} + +fun pick( + indexes: vector, + v1: &vector
, + v2: &vector
+): vector
{ + let len1 = vector::length(v1); + let len2 = vector::length(v2); + let result = vector::empty(); + while (!vector::is_empty(&indexes)) { + let index = vector::pop_back(&mut indexes); + let chosen_vector = + if (index < len1) v1 + else if (index < len2) v2 + else continue; // Here, `continue` has type `&vector
` + vector::push_back(&mut result, *vector::borrow(chosen_vector, index)) + }; + + result +} +``` + +## `loop`表达式 + +The `loop` expression repeats the loop body (an expression with type `()`) until it hits a `break` + +Without a `break`, the loop will continue forever + +`loop` 表达式重复循环体(类型为unit()的表达式) ,直到遇到 `break` 为止。 + +(下面的代码中)没有 `break`, 循环将一直执行。 + +```move +fun foo() { + let i = 0; + loop { i = i + 1 } +} +``` + +Here is an example that uses `loop` to write the `sum` function: + +这是一个使用 `loop` 编写 `sum` 函数的示例(可与 `while` 循环比较): + +```move +fun sum(n: u64): u64 { + let sum = 0; + let i = 0; + loop { + i = i + 1; + if (i > n) break; + sum = sum + i + }; + + sum +} +``` + +As you might expect, `continue` can also be used inside a `loop`. Here is `sum_intermediate` from above rewritten using `loop` instead of `while` + +正如你所料, `continue` 也可以在 `loop` 中使用。这是上面的 `sum_intermediate` 使用 `loop` 代替 `while` 重写的: + +```move +fun sum_intermediate(n: u64): u64 { + let sum = 0; + let i = 0; + loop { + i = i + 1; + if (i % 10 == 0) continue; + if (i > n) break; + sum = sum + i + }; + + sum +} +``` + +## `while` and `loop` 的类型 + +Move loops are typed expressions. A `while` expression always has type `()`. + +Move 循环是有类型化的表达式。 `while` 表达式始终具有 `()` 类型。 + +```move +let () = while (i < 10) { i = i + 1 }; +``` + +If a `loop` contains a `break`, the expression has type unit `()` + +如果 `loop` 中包含 `break` , 这个表达式的类型则为 unit `()` + + +```move +(loop { if (i < 10) i = i + 1 else break }: ()); +let () = loop { if (i < 10) i = i + 1 else break }; +``` + +If `loop` does not have a `break`, `loop` can have any type much like `return`, `abort`, `break`, and `continue`. + +如果 `loop` 不包含 `break`, `loop` 可以是任何类型, 就像`return`, `abort`, `break`, 和 `continue`。 + +```move +(loop (): u64); +(loop (): address); +(loop (): &vector>); +``` diff --git a/language/documentation/book/translations/move-book-zh/src/modules-and-scripts.md b/language/documentation/book/translations/move-book-zh/src/modules-and-scripts.md new file mode 100644 index 0000000000..9dbca68ebf --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/modules-and-scripts.md @@ -0,0 +1,119 @@ +# 模块和脚本 + +Move 有两种不同类型的程序:***模块(Module)***和***脚本(Script)***。模块是定义结构类型以及对这些类型进行操作的函数的库。*结构类型*定义了 Move 的[全局存储](./global-storage-structure.md)的模式,*模块函数*定义了更新存储的规则。模块本身也存储在全局存储中。脚本是[可执行文件](https://en.wikipedia.org/wiki/Executable)的入口点,类似于传统语言中的主函数 `main`。脚本通常调用已发布模块的函数来更新全局存储。脚本是临时代码片段,不会发布在全局存储中。 + +一个 Move 源文件(或**编译单元**)可能包含多个模块和脚本。然而,发布模块或执行脚本都是独立的虚拟机(VM)操作。 + +## 语法 + +### 脚本 + +脚本具有以下结构: + +```text +script { + * + * + fun <[type parameters: constraint]*>([identifier: type]*) +} +``` + +一个 `script` 块必须以它的所有 [`use`](./uses.md) 声明开头,然后是[常量(constant)](./constants.md)声明,最后是主[函数](./functions.md)声明。主函数的名称可以是任意的(也就是说,它不一定命名为 `main`),它是脚本块中唯一的函数,可以有任意数量的参数,并且不能有返回值。下面是每个组件的示例: + +```move +script { + // 导入在命名账户地址 std 上发布的 debug 模块。 + use std::debug; + + const ONE: u64 = 1; + + fun main(x: u64) { + let sum = x + ONE; + debug::print(&sum) + } +} +``` + +脚本(Script)的功能非常有限 —— 它们不能声明友元(friend)、结构类型或访问全局存储。他们的主要作用主要是调用*模块函数*。 + +### 模块 + +模块具有以下结构: + +```text +module
:: { + ( | | | | )* +} +``` + +其中 `
` 是一个有效的[命名或字面量地址](./address.md)。 + +例子: + +```move +module 0x42::test { + struct Example has copy, drop { i: u64 } + + use std::debug; + friend 0x42::another_test; + + const ONE: u64 = 1; + + public fun print(x: u64) { + let sum = x + ONE; + let example = Example { i: sum }; + debug::print(&sum) + } +} +``` + +`module 0x42::test` 这部分指定模块 `test` 将在[全局存储](./global-storage-structure.md)的[账户地址](./address.md) `0x42` 下发布。 + +模块也可以使用[命名地址](./address.md)来声明,例如: + +```move +module test_addr::test { + struct Example has copy, drop { a: address } + + use std::debug; + friend test_addr::another_test; + + public fun print() { + let example = Example { a: @test_addr }; + debug::print(&example) + } +} +``` + +因为命名地址只存在于源语言级别和编译期间,所以命名地址将在字节码级别彻底替换它们的值。例如,如果我们有以下代码: + +```move +script { + fun example() { + my_addr::m::foo(@my_addr); + } +} +``` + +我们在把 `my_addr` 设置为 `0xC0FFEE` 的情况下编译它,那么它在操作上等同于以下内容: + +```move +script { + fun example() { + 0xC0FFEE::m::foo(@0xC0FFEE); + } +} +``` + +然而,在源代码级别,这些是*不等价的* —— 函数 `m::foo` *必须*通过 `my_addr` 命名地址来访问,而不是通过分配给该地址的数值来访问。 + +模块名称可以以字母 `a` 到 `z` 或字母 `A` 到 `Z` 开头。在第一个字符之后,模块名可以包含下划线 `_`、字母 `a` 到 `z`、字母 `A` 到 `Z` 或数字 `0` 到 `9`。 + +```move +module my_module {} +module foo_bar_42 {} +``` + +通常,模块名称以小写字母开头。名为 `my_module` 的模块应该存储在名为 `my_module.move` 的源文件中。 + +`module` 块内的所有元素都可以按任意顺序出现。从根本上说,模块是[`类型(type)`](./structs-and-resources.md)和[`函数(function)`](./functions.md)的集合。[`use`](./uses.md) 关键字用来从其他模块导入类型。[`friend`](./friends.md) 关键字指定一个可信的模块列表。[`const`](./constants.md) 关键字定义了可以在模块函数中使用的私有常量。 diff --git a/language/documentation/book/translations/move-book-zh/src/move-tutorial.md b/language/documentation/book/translations/move-book-zh/src/move-tutorial.md new file mode 100644 index 0000000000..209d54950a --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/move-tutorial.md @@ -0,0 +1,970 @@ +# Move 教程(Move Tutorial) + +Welcome to the Move Tutorial! In this tutorial, we are going to go through some steps of developing Move code including design, implementation, unit testing and formal verification of Move modules. + +欢迎来到 Move 语言教程,在本教程中,我们通过一些具体的步骤进行 Move 语言代码的开发,包括 Move 模块的设计、实现、单元测试和形式化验证。 + +There are nine steps in total: + +- [Step 0: Installation](#Step0) +- [Step 1: Writing my first Move module](#Step1) +- [Step 2: Adding unit tests to my first Move module](#Step2) +- [Step 3: Designing my `BasicCoin` module](#Step3) +- [Step 4: Implementing my `BasicCoin` module](#Step4) +- [Step 5: Adding and using unit tests with the `BasicCoin` module](#Step5) +- [Step 6: Making my `BasicCoin` module generic](#Step6) +- [Step 7: Use the Move prover](#Step7) +- [Step 8: Writing formal specifications for the `BasicCoin` module](#Step8) + +整个过程共包含9个步骤: + +- [Step 0: 安装 Move 开发环境](#Step0) +- [Step 1: 编写第一个 Move 模块(Move Module)](#Step1) +- [Step 2: 给模块(Module)添加单元测试](#Step2) +- [Step 3: 设计自己的 `BasicCoin` 模块(Module)](#Step3) +- [Step 4: `BasicCoin` 模块(Module)的实现](#Step4) +- [Step 5: 给 `BasicCoin` 模块添加单元测试](#Step5) +- [Step 6: 使用泛型(generic)编写 `BasicCoin` 模块](#Step6) +- [Step 7: 使用 `Move prover`](#Step7) +- [Step 8: 为 `BasicCoin` 模块编写形式化规范(formal specifications)](#Step8) + +Each step is designed to be self-contained in the corresponding `step_x` folder. For example, if you would +like to skip the contents in step 1 through 4, feel free to jump to step 5 since all the code we have written +before step 5 will be in `step_5` folder. At the end of some steps, we also include +additional material on more advanced topics. + +其中每一步都被设计为自包含的文件夹, 相应名字为 `step_x`。 例如,如果您愿意跳过 `step 1` 到 `step 4` 的内容,可直接跳到 `step 5`,因为所有在 `step 5` 之前的代码均在在`step_5` 文件夹之下。在部分步骤结束时,我们还引入有关更高级主题的附加资料。 + +Now let's get started! + +好了,我们现在开始! + +## Step 0: 安装 Move 开发环境 (Step 0: Installation) + +If you haven't already, open your terminal and clone [the Move repository](https://github.com/move-language/move): + +如果您还没有安装过 Move,首先打开命令终端(terminal) 并clone [Move代码库](https://github.com/move-language/move): + +```bash +git clone https://github.com/move-language/move.git +``` + +Go to the `move` directory and run the `dev_setup.sh` script: + +进入到 `move` 文件夹下,执行 `dev_setup.sh` 脚本: + +```bash +cd move +./scripts/dev_setup.sh -ypt +``` + +Follow the script's prompts in order to install all of Move's dependencies. + +The script adds environment variable definitions to your `~/.profile` file. +Include them by running this command: + +根据脚本命令的提示,按顺序安装 Move 的所有依赖项。 +脚本将会将(move命令所在路径)环境变量写入到 `~/.profile` 文件中。 + +执行如下命令使环境变量生效: + +```bash +source ~/.profile +```` + +Next, install Move's command-line tool by running this commands: + +然后执行如下命令来安装 Move 命令行工具: + +```bash +cargo install --path language/tools/move-cli +``` + +You can check that it is working by running the following command: + +通过如下运行命令可以检查 move 命令是否可正常: + +```bash +move --help +``` +You should see something like this along with a list and description of a number of commands: + +您应该会看到类似这样的内容以及许多命令的列表和描述: + +``` +move-package +Execute a package command. Executed in the current directory or the closest containing Move package + +USAGE: + move [OPTIONS] + +OPTIONS: + --abi Generate ABIs for packages +... +``` + +If you want to find what commands are available and what they do, running +a command or subcommand with the `--help` flag will print documentation. + +如果想了解有支持哪引命令及其作用, 执行命令或子命令时添加 `--help` 标记,此时会打印帮助文档。 + +Before running the next steps, `cd` to the tutorial directory: + +在执行下一步骤之前,请先执行 `cd` 命令进入到教程对应目录下: + +```bash +cd /language/documentation/tutorial +``` + +
+ +Visual Studio Code Move 支持 (Visual Studio Code Move Support) + +There is official Move support for Visual Studio Code. You need to install +the move analyzer first: + +Visual Studio Code 有正式的 Move 语言支持, 您需要先安装 `move analyzer` : + +```bash +cargo install --path language/move-analyzer +``` + +Now you can install the VS extension by opening VS Code, searching for the "move-analyzer" in the Extension Pane, and installing it. More detailed instructions can be found +in the extension's [README](https://github.com/move-language/move/tree/main/language/move-analyzer/editors/code). + +现在您可以打开 VS Code 并安装 Move 扩展插件了,在扩展页面下找到 `move-analyzer` 并安装即可。关于扩展的详细信息可以查看扩展的[README](https://github.com/move-language/move/tree/main/language/move-analyzer/editors/code)。 +
+ +## Step 1: 编写第一个Move模块 (Writing my first Move module) + +Change directory into the [`step_1/BasicCoin`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_1/BasicCoin) directory. +You should see a directory called `sources` -- this is the place where all +the Move code for this package lives. You should also see a +`Move.toml` file as well. This file specifies dependencies and other information about +the package; if you're familiar with Rust and Cargo, the `Move.toml` file +is similar to the `Cargo.toml` file, and the `sources` directory similar to +the `src` directory. + +切换当前目录到[`step_1/BasicCoin`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_1/BasicCoin)下,您将看到 `sources` 子目录 -- 这个包(package)下所有的 Move 代码都在此目录中,同时您还会看到一个 `Move.toml` 文件。该文件指定当前包的依赖列表和其他信息。 +如果您熟悉 `Rust` 和 `Cargo`,那 `Move.toml` 文件类似 `Cargo.toml` 文件, `sources` 目录类似 `src` 目录(它们的作用是一样的) + +Let's take a look at some Move code! Open up +[`sources/FirstModule.move`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_1/BasicCoin/sources/FirstModule.move) in +your editor of choice. The first thing you'll see is this: + +来一起看看 Move 语言代码内容! 用你的编辑器打开[`sources/FirstModule.move`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_1/BasicCoin/sources/FirstModule.move)文件,会看到如下内容: + +``` +// sources/FirstModule.move +module 0xCAFE::BasicCoin { + ... +} +``` + +This is defining a Move +[module](https://move-language.github.io/move/modules-and-scripts.html). Modules are the +building block of Move code, and are defined with a specific address -- the address that the module can be published under. +In this case, the `BasicCoin` module can only be published under `0xCAFE`. + +这是一个 `Move` [module(模块)](./chpater_1_modules-and-scripts.html)的定义。 +模块是 Move 语言的代码块, 并且它使用指定的地址(address)进行定义 -- 模块只能在该地址下发布。 +当前 `BasicCoin` 模块只能被发布在 `0xCAFE` 地址下。 + +Let's now take a look at the next part of this file where we define a [struct](https://move-language.github.io/move/structs-and-resources.html) to represent a `Coin` with a given `value`: + +再看这个文件的下一部分,这里定义了一个具有字段 `value` 的[结构体](./structs-and-resources.html) `Coin`: + +``` +module 0xCAFE::BasicCoin { + struct Coin has key { + value: u64, + } + ... +} +``` + +Looking at the rest of the file, we see a function definition that creates a `Coin` struct and stores it under an account: + +再看文件剩余部分,我们会看到一个函数,它会创建一个 `Coin` 结构体,并将其保存在某个账号(account)下: + +``` +module 0xCAFE::BasicCoin { + struct Coin has key { + value: u64, + } + + public fun mint(account: signer, value: u64) { + move_to(&account, Coin { value }) + } +} +``` + +Let's take a look at this function and what it's saying: +* It takes a [`signer`](https://move-language.github.io/move/signer.html) -- an + unforgeable token that represents control over a particular address, and + a `value` to mint. +* It creates a `Coin` with the given value and stores it under the + `account` using the `move_to` operator. + +Let's make sure it builds! This can be done with the `build` command from within the package folder ([`step_1/BasicCoin`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_1/BasicCoin/)): + +让我们来看看这个函数和它的含义: +* 此函数需要一个[`signer`](./signer.html)参数 -- 表示不可伪造的 token 受此特定地址的控制; 和一个需要铸造的数量参数 `value`。 +* 此函数使用给定的参数值铸造一个 `Coin`,然后通过 `move_to` 操作将其保存在(全局存储中)给定的 `account` 账户下。 + +我们需要确保它真的执行,这可以通过在包文件夹([`step_1/BasicCoin`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_1/BasicCoin/))下的运行 `build` 命令来完成: + +```bash +move build +``` + +
+ +进阶概念及参考引用 (Advanced concepts and references) + +* You can create an empty Move package by calling: + ```bash + move new + ``` +* Move code can also live a number of other places. More information on the + Move package system can be found in the [Move book](https://move-language.github.io/move/packages.html) +* More information on the `Move.toml` file can be found in the [package section of the Move book](https://move-language.github.io/move/packages.html#movetoml). +* Move also supports the idea of [named addresses](https://move-language.github.io/move/address.html#named-addresses), Named addresses are a way to parametrize Move source code so that you can compile the module using different values for `NamedAddr` to get different bytecode that you can deploy, depending on what address(es) you control. They are used quite frequently, and can be defined in the `Move.toml` file in the `[addresses]` section, e.g., + ``` + [addresses] + SomeNamedAddress = "0xC0FFEE" + ``` + +* 你可以通过以下命令创建一个空的 Move 包(move package): + ```bash + move new + ``` +* Move 代码也可以放在其他很多地方, 更多关于 Move 包系统的信息请参阅[Move book](./packages.html) +* 更多关于 `Move.toml` 文件的信息可以参阅[package section of the Move book](./packages.html#movetoml). +* Move语言也支持命名地址的概念([named addresses](./address.html#named-addresses)), 命名地址是一种参数化 Move 源代码的方法, + 就是如果对 `NamedAddr` 使用的不同赋值编译,编译后会获得部署到你控制地址的不同字节码. 这种用法很常见,一般都将地址变量其定义在 `Move.toml` 文件 + 的 `[addresses]` 部分. 例如: + ``` + [addresses] + SomeNamedAddress = "0xC0FFEE" + ``` + +* [Structures](https://move-language.github.io/move/structs-and-resources.html) in Move can be given different + [abilities](https://move-language.github.io/move/abilities.html) that describe what can be done with that type. There are four different abilities: + - `copy`: Allows values of types with this ability to be copied. + - `drop`: Allows values of types with this ability to be popped/dropped. + - `store`: Allows values of types with this ability to exist inside a struct in global storage. + - `key`: Allows the type to serve as a key for global storage operations. + + So in the `BasicCoin` module we are saying that the `Coin` struct can be used as a key + in global storage and, because it has no other abilities, it cannot be + copied, dropped, or stored as a non-key value in storage. So you can't copy + coins, and you also can't lose coins by accident! +* [Functions](https://move-language.github.io/move/functions.html) are default + private, and can also be `public`, + [`public(friend)`](https://move-language.github.io/move/friends.html), or + `public(script)`. The last of these states that this function can be + called from a transaction script. `public(script)` functions can also be + called by other `public(script)` functions. +* `move_to` is one of the [five different global storage operators](https://move-language.github.io/move/global-storage-operators.html). + +* Move [结构体](./chpater_16_structs-and-resources.html)可以通过给类型设定不同的能力[abilities](./chapter_19_abilities.html)让类型下支持对应的行为. 有四种能力: + - `copy`: 允许此类型的值被复制 + - `drop`: 允许此类型的值被弹出/丢弃 + - `store`: 允许此类型的值存在于全局存储的某个结构体中 + - `key`: 允许此类型作为全局存储中的键(具有 `key` 能力的类型才能保存到全局存储中) + + 所以 `BasicCoin` 模块下的 `Coin` 结构体可以用作全局存储(global storage)的键(key), 因为它又不具备其他能力,它不能 + 被拷贝,不能被丢弃, 也不能作为非key来保存在(全局)存储里. 你无法复制 `Coin`,也不会意外弄丢它. +* 函数[Functions](./functions.html)默认是私有的(private), 也可以声明为 `public` [`public(friend)`](https://move-language.github.io/move/friends.html), `public(script)`. 最后一个声明(指 `public(script)`)的函数可以被事务脚本调用。`public(script)` 函数也可以被其他 `public(script)` 函数调用。(注意:在最新版本的 Move中,`public(script)` 已经被废弃,被`public entry` 取代,下同,译者注) +* `move_to` 是[五种不同的全局存储操作](./global-storage-operators.html)之一 + +
+ +## Step 2: 给模块(Module)添加单元测试 (Adding unit tests to my first Move module) + +Now that we've taken a look at our first Move module, we'll take a look at a test to make sure minting works the way we expect it to by changing directory to [`step_2/BasicCoin`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_2/BasicCoin). Unit tests in Move are similar to unit tests in Rust if you're familiar with them -- tests are annotated with `#[test]` and written like normal Move functions. + +You can run the tests with the `move test` command: (原文是 `package test`,应该有误) + +现在我们已经完成了我们的第一个 Move 模块,我们将切换到目录[`step_2/BasicCoin`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_2/BasicCoin)下并完成一个测试,确保铸币按我们预期的方式工作。 +如果你熟悉它们(Move 和 Rust)的话,Move 中的单元测试类似于 Rust 中的单元测试 —— 测试代码使用 `#[test]` 注解,并像编写普通的 Move 函数一样。 + +可以通过 `move test` 命令来执行测试: + +```bash +move test +``` + +Let's now take a look at the contents of the [`FirstModule.move`file](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_2/BasicCoin/sources/FirstModule.move). The first new thing you'll +see is this test: + +现在我们来完成文件[`FirstModule.move`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_2/BasicCoin/sources/FirstModule.move)的具体内容,你将看到的第一个新事项是这个测试: + +``` +module 0xCAFE::BasicCoin { + ... + // Declare a unit test. It takes a signer called `account` with an + // address value of `0xC0FFEE`. + #[test(account = @0xC0FFEE)] + fun test_mint_10(account: signer) acquires Coin { + let addr = signer::address_of(&account); + mint(account, 10); + // Make sure there is a `Coin` resource under `addr` with a value of `10`. + // We can access this resource and its value since we are in the + // same module that defined the `Coin` resource. + assert!(borrow_global(addr).value == 10, 0); + } +} +``` + +This is declaring a unit test called `test_mint_10` that mints a `Coin` struct under the `account` with a `value` of `10`. It is then checking that the minted +coin in storage has the value that is expected with the `assert!` call. If the assertion fails the unit test will fail. + +这里声明了一个命名为 `test_mint_10` 的单元测试,它在 `account` 账户地址下铸造了一个包含 `value` 为 `10`的 `Coin`,然后通过 `assert!` 断言检查已经铸造成功并保存在(全局)存储中的 `Coin` 的值是否与期望值一致。如果断言 `assert` 执行失败,则单元测试失败。 + +
+ +进阶概念及参考练习 (Advanced concepts and exercises) + +* There are a number of test-related annotations that are worth exploring, they can be found + [here](https://github.com/move-language/move/blob/main/language/changes/4-unit-testing.md#testing-annotations-their-meaning-and-usage). + You'll see some of these used in Step 5. +* Before running unit tests, you'll always need to add a dependency on the Move + standard library. This can be done by adding an entry to the `[dependencies]` + section of the `Move.toml`, e.g., + + ```toml + [dependencies] + MoveStdlib = { local = "../../../../move-stdlib/", addr_subst = { "Std" = "0x1" } } + ``` + + Note that you may need to alter the path to point to the `move-stdlib` directory under + `/language`. You can also specify git dependencies. You can read more on Move + package dependencies [here](https://move-language.github.io/move/packages.html#movetoml). + +* 很多测试相关的注解(annotations)都值得仔细探索, 参阅[用法](https://github.com/move-language/move/blob/main/language/changes/4-unit-testing.md#testing-annotations-their-meaning-and-usage)。 在 `Step 5` 中会看到更多用法. + +* 执行测试之前,需要设定Move标准库依赖关系,找到 `Move.toml` 并在 `[dependencies]` 段内进行设定, 例如 + + ```toml + [dependencies] + MoveStdlib = { local = "../../../../move-stdlib/", addr_subst = { "Std" = "0x1" } } + ``` +注意, 需要修改 `/language` 中的内容来匹配实际 `move-stdlib` 所在的目录路径. 也可以用 `git` 方式指定依赖, 关于 Move 包依赖(package denpendices)信息可参阅[package文档](./packages.html#movetoml) + +#### 练习 (Exercises) + +* Change the assertion to `11` so that the test fails. Find a flag that you can pass to the `move test` command that will show you the global state when the test fails. It should look something like this: + +* 将断言值改为 `11` 将导致断言执行失败, 找一个可以传递给 `move test` 命令的标志,当测试失败时它会显示全局状态。看起来像这样: + ``` + ┌── test_mint_10 ────── + │ error[E11001]: test failure + │ ┌─ ./sources/FirstModule.move:24:9 + │ │ + │ 18 │ fun test_mint_10(account: signer) acquires Coin { + │ │ ------------ In this function in 0xcafe::BasicCoin + │ · + │ 24 │ assert!(borrow_global(addr).value == 11, 0); + │ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Test was not expected to abort but it aborted with 0 here + │ + │ + │ ────── Storage state at point of failure ────── + │ 0xc0ffee: + │ => key 0xcafe::BasicCoin::Coin { + │ value: 10 + │ } + │ + └────────────────── + ``` + +* Find a flag that allows you to gather test coverage information, and then play around with using the `move coverage` command to look at coverage statistics and source coverage. + +* 找一个允许您收集测试覆盖率信息的标志,然后使用 `move coverage` 命令查看覆盖率统计信息和源码覆盖率。 + +
+ +## Step 3: 设计 `BasicCoin` 模块(Module) (Designing my `BasicCoin` module) + +In this section, we are going to design a module implementing a basic coin and balance interface, where coins can be minted and transferred between balances held under different addresses. + +在本节中,我们将设计一个具有基本代币和余额(balance)接口功能的模块,通过他们来实现币的挖矿铸造,不同地址之下钱包的转账。 + +The signatures of the public Move function are the following: + +Move 语言的 `public function` 签名如下: + +``` +/// Publish an empty balance resource under `account`'s address. This function must be called before +/// minting or transferring to the account. +public fun publish_balance(account: &signer) { ... } + +/// Mint `amount` tokens to `mint_addr`. Mint must be approved by the module owner. +public fun mint(module_owner: &signer, mint_addr: address, amount: u64) acquires Balance { ... } + +/// Returns the balance of `owner`. +public fun balance_of(owner: address): u64 acquires Balance { ... } + +/// Transfers `amount` of tokens from `from` to `to`. +public fun transfer(from: &signer, to: address, amount: u64) acquires Balance { ... } +``` + +Next we look at the data structs we need for this module. + +接下来再看本模块所需要各数据结构. + +A Move module doesn't have its own storage. Instead, Move "global storage" (what we call our +blockchain state) is indexed by addresses. Under each address there are Move modules (code) and Move resources (values). + +Move 语言的模块没有自己的数据存储,相反的是 Move 语言提供按地址(addresses) 索引的 **全局存储** (也是就是我们所说的区块链状态(blockchain state)). +每个地址之下包含有 Move 模块(代码)和 Move 资源 (数据)。 + +The global storage looks roughly like this in Rust syntax: + +在 Rust 语法中,全局存储看起来有点像这样: + +```rust +struct GlobalStorage { + resources: Map> + modules: Map> +} +``` + +The Move resource storage under each address is a map from types to values. (An observant reader might observe that this means each address can only have one value of each type.) This conveniently provides us a native mapping indexed by addresses. +In our `BasicCoin` module, we define the following `Balance` resource representing the number of coins each address holds: + +每个地址下的 Move 资源存储是一个类型到数值的映射。(细心的读者也许已经注意到每个地址, 每个类型下只能对应一个具体值)。这方便地为我们提供了一个按地址索引的本地映射。 +在 `BasicCoin` 模块中,定义了每个 `Balance` (钱包,余额)资源表示每个地址下持有的币的数量: + +``` +/// Struct representing the balance of each address. +struct Balance has key { + coin: Coin // same Coin from Step 1 +} +``` + +Roughly the Move blockchain state should look like this: + +区块链状态(`Move blockchain state`)看起来大致如下: + +![](https://raw.githubusercontent.com/move-language/move/main/language/documentation/tutorial/diagrams/move_state.png) + +#### 进阶主题 (Advanced topics) : + +public(script) functions + +Only functions with `public(script)` visibility can be invoked directly in transactions. So if you would like to call the `transfer` method directly from a transaction, you'll want to change its signature to: + +只有`public(script)`可见行的函数才能直接被交易调用,所以如果你要直接在交易内调用`transfer`方法,那么需要将函数签改成如下格式: + +``` +public(script) fun transfer(from: signer, to: address, amount: u64) acquires Balance { ... } +``` +Read more on Move function visibilities [here](https://move-language.github.io/move/functions.html#visibility). + +关于函数可见性的更多信息,请参阅[Move function visibilities](./functions.html#visibility)。 + + +
+与 Ethereum/Solidity 的比较 (Comparison with Ethereum/Solidity) + +In most Ethereum [ERC-20]((https://ethereum.org/en/developers/docs/standards/tokens/erc-20/)) contracts, the balance of each address is stored in a _state variable_ of type mapping(address => uint256). This state variable is stored in the storage of a particular smart contract. + +在大多数以太坊[ERC-20]((https://ethereum.org/en/developers/docs/standards/tokens/erc-20/))智能合约中,各个账户地址下的余额保存在类型为 mapping(address => uint256)的 __状态变量__ 中,此状态变量存储在具体的智能合约内部存储中。 + +The Ethereum blockchain state might look like this: + +以太坊区块链的状态看起来大致如下: + +![](https://raw.githubusercontent.com/move-language/move/main/language/documentation/tutorial/diagrams/solidity_state.png) +
+ +## Step 4: 实现 `BasicCoin` 模块span id="Step4"> (Implementing my `BasicCoin` module) + +We have created a Move package for you in folder `step_4` called `BasicCoin`. The `sources` folder contains source code for all your Move modules in the package, including `BasicCoin.move`. In this section, we will take a closer look at the implementation of the methods inside [`BasicCoin.move`](https://github.com/move-language/move/blob/main/language/documentation/tutorial/step_4/BasicCoin/sources/BasicCoin.move). + +我们已经在 `step_4` 文件夹上创建了名叫 `BasicCoin` 的 Move 包。`sources` 文件夹包含所有的 Move 包(package)的模块源码,包括 `BasicCoin.move`。 在本节中,我们将仔细研究[`BasicCoin.move`](https://github.com/move-language/move/blob/main/language/documentation/tutorial/step_4/BasicCoin/sources/BasicCoin.move)内部方法的实现。 + +### 编译代码 (Compiling our code) + +Let's first try building the code using Move package by running the following command in [`step_4/BasicCoin`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_4/BasicCoin) folder: + +首先尝试在文件夹[`step_4/BasicCoin`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_4/BasicCoin)中运行以下命令,使用 Move 包构建代码: + +```bash +move build +``` + +### 方法的实现 (Implementation of methods) + +Now let's take a closer look at the implementation of the methods inside [`BasicCoin.move`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_4/BasicCoin/sources/BasicCoin.move). + +现在仔细看看[`BasicCoin.move`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_4/BasicCoin/sources/BasicCoin.move)中内部方法的实现。 + +
+ +publish_balance方法 (Method publish_balance) + +This method publishes a `Balance` resource to a given address. Since this resource is needed to receive coins through minting or transferring, `publish_balance` method must be called by a user before they can receive money, including the module owner. + +此方法将 `Balance` 资源发布到指定地址名下。由于此资源需要通过铸造或转账来接收代币,必须由用户先调用方法 `publish_balance` 才能接收钱,包括模块所有者。 + +This method uses a `move_to` operation to publish the resource: + +此方法使用 `move_to` 操作来发布资源: + +``` +let empty_coin = Coin { value: 0 }; +move_to(account, Balance { coin: empty_coin }); +``` + +
+
+ +mint方法 (Method mint)) + +Here we require that `mint` must be approved by the module owner. We enforce this using the assert statement: +`mint` method mints coins to a given account. + +`mint` 方法将代币铸造到指定的帐户。在此我们要求 `mint` 必须得到模块所有者的批准。我们使用 `assert` 语句强制执行此操作: + +``` +assert!(signer::address_of(&module_owner) == MODULE_OWNER, errors::requires_address(ENOT_MODULE_OWNER)); +``` + +Assert statements in Move can be used in this way: `assert!(, );`. This means that if the `` is false, then abort the transaction with ``. Here `MODULE_OWNER` and `ENOT_MODULE_OWNER` are both constants defined at the beginning of the module. And `errors` module defines common error categories we can use. +It is important to note that Move is transactional in its execution -- so if an [abort](https://move-language.github.io/move/abort-and-assert.html) is raised no unwinding of state needs to be performed, as no changes from that transaction will be persisted to the blockchain. + +Move 中的 `assert` 语句可以这样使用:`assert!(, );`。这意味着如果 `` 为假,则使用中止错误码 `` 来终止交易。此处的 `MODULE_OWNER` 和 `ENOT_MODULE_OWNER` 都是在模块开头定义的常量。`errors` 模块定义了我们可以使用的常见错误种类。重点是我们需要注意 Move 在其执行过程中是事务性的-- 因此,如果触发[中止(abort)](./chapter_12_abort-and-assert.html),并不用回退已执行状态的,因为该事务的任何更改都不会持久保存到区块链。 + +We then deposit a coin with value `amount` to the balance of `mint_addr`. + +然后将数量为 `amount` 的代币存入 `mint_addr` 的余额中。 + +``` +deposit(mint_addr, Coin { value: amount }); +``` +
+ +
+ +balance_of方法 (Method balance_of) + +We use `borrow_global`, one of the global storage operators, to read from the global storage. + +我们使用全局存储操作之一的 `borrow_global` 从全局存储中读取资源(数据)。 + +``` +borrow_global(owner).coin.value + | | \ / + resource type address field names +``` +
+ +
+ +transfer方法 (Method transfer) + +This function withdraws tokens from `from`'s balance and deposits the tokens into `to`s balance. We take a closer look at `withdraw` helper function: + +该函数从 `from` 的余额中提取代币并将代币存入 `to` 的余额中。我们仔细研究帮助函数 `withdraw`: + +``` +fun withdraw(addr: address, amount: u64) : Coin acquires Balance { + let balance = balance_of(addr); + assert!(balance >= amount, EINSUFFICIENT_BALANCE); + let balance_ref = &mut borrow_global_mut(addr).coin.value; + *balance_ref = balance - amount; + Coin { value: amount } +} +``` + +At the beginning of the method, we assert that the withdrawing account has enough balance. We then use `borrow_global_mut` to get a mutable reference to the global storage, and `&mut` is used to create a [mutable reference](https://move-language.github.io/move/references.html) to a field of a struct. We then modify the balance through this mutable reference and return a new coin with the withdrawn amount. + +在方法开始,我们断言提款账户有足够的余额。然后我们使用 `borrow_global_mut` 来获得全局存储的可变引用,并用 `&mut` 创建结构体字段的[可变引用](./references.html)。然后我们通过这个可变引用修改余额并返回一个带有提取金额的新代币。 + +
+ +### 练习 (Exercises) + +There are two `TODO`s in our module, left as exercises for the reader: +- Finish implementing the `publish_balance` method. +- Implement the `deposit` method. + +在模块中有两个 TODOs,留给读者练习: +- 完成 `publish_balance` 方法的实现。 +- 实现 `deposit` 方法。 + +The solution to this exercise can be found in [`step_4_sol`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_4_sol) folder. + +此练习的解决方案可以在[`step_4_sol`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_4_sol)文件夹中找到。 + +**额外练习** (**Bonus exercise**) + +- What would happen if we deposit too many tokens to a balance? +- 如果我们在余额中存入太多会发生什么? + + +## Step 5: 在模块 `BasicCoin` 中添加和使用单元测试 (Adding and using unit tests with the `BasicCoin` module) + +In this step we're going to take a look at all the different unit tests we've written to cover the code we wrote in step 4. We're also going to take a look at some tools we can use to help us write tests. + +在这一步中,来看看我们为覆盖在 `step 4` 中编写的代码而编写的所有不同的单元测试。还将看看我们可以用来帮助我们编写测试用例的一些工具。 + +To get started, run the `move test` command in the [`step_5/BasicCoin`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_5/BasicCoin) folder + +首先,请在文件夹 [`step_5/BasicCoin`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_5/BasicCoin)中 运行 `move test` 命令。 + +```bash +move test +``` +You should see something like this: + +您应该看到如下内容: + +``` +INCLUDING DEPENDENCY MoveStdlib +BUILDING BasicCoin +Running Move unit tests +[ PASS ] 0xcafe::BasicCoin::can_withdraw_amount +[ PASS ] 0xcafe::BasicCoin::init_check_balance +[ PASS ] 0xcafe::BasicCoin::init_non_owner +[ PASS ] 0xcafe::BasicCoin::publish_balance_already_exists +[ PASS ] 0xcafe::BasicCoin::publish_balance_has_zero +[ PASS ] 0xcafe::BasicCoin::withdraw_dne +[ PASS ] 0xcafe::BasicCoin::withdraw_too_much +Test result: OK. Total tests: 7; passed: 7; failed: 0 +``` + +Taking a look at the tests in the [`BasicCoin` module](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_5/BasicCoin/sources/BasicCoin.move) we've tried to keep each unit test to testing one particular behavior. + +看看 [`BasicCoin` ](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_5/BasicCoin/sources/BasicCoin.move)模块中的测试,我们试图让每个单元测试都测试一个具体的行为。 + +
+Exercise (练习) + +After taking a look at the tests, try and write a unit test called `balance_of_dne` in the `BasicCoin` module that tests the case where a `Balance` resource doesn't exist under the address that `balance_of` is being called on. It should only be a couple lines! + +在查看测试之后,尝试在 `BasicCoin` 模块中编写一个单元测试 `balance_of_dne`,测试地址没有 `Balance` 资源的情况,调用 `balance_of` 方法的执行结果。它应该只有几行代码。 + +The solution to this exercise can be found in [`step_5_sol`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_5_sol). + +练习的答案可以在[`step_5_sol`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_5_sol)中找到。 + +
+ +## Step 6: `BasicCoin` 模块泛型化(Making my `BasicCoin` module generic) + +In Move, we can use generics to define functions and structs over different input data types. Generics are a great building block for library code. In this section, we are going to make our simple `BasicCoin` module generic so that it can serve as a library module that can be used by other user modules. + +在 Move 语言中,我们可以使用泛型来定义不同输入数据类型的函数和结构体。泛型是库代码的重要组成部分。在本节中,我们将使我们的简单 `BasicCoin` 模块泛型化,以便它可以用作其他用户模块可以使用的模块库。 + +First, we add type parameters to our data structs: + +首先,我们将类型参数添加到我们的数据结构中: + +``` +struct Coin has store { + value: u64 +} + +struct Balance has key { + coin: Coin +} +``` + +We also add type parameters to our methods in the same manner. For example, `withdraw` becomes the following: + +我们还以相同的方式将类型参数添加到我们的方法中。例如,`withdraw` 变成如下: + +``` +fun withdraw(addr: address, amount: u64) : Coin acquires Balance { + let balance = balance_of(addr); + assert!(balance >= amount, EINSUFFICIENT_BALANCE); + let balance_ref = &mut borrow_global_mut>(addr).coin.value; + *balance_ref = balance - amount; + Coin { value: amount } +} +``` + +Take a look at [`step_6/BasicCoin/sources/BasicCoin.move`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_6/BasicCoin/sources/BasicCoin.move) to see the full implementation. + +查看[`step_6/BasicCoin/sources/BasicCoin.move`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_6/BasicCoin/sources/BasicCoin.move)完整的实现。 + +At this point, readers who are familiar with Ethereum might notice that this module serves a similar purpose as the [ERC20 token standard](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/), which provides an interface for implementing fungible tokens in smart contracts. One key advantage of using generics is the ability to reuse code since the generic library module already provides a standard implementation and the instantiating module can provide customizations by wrapping the standard implementation. + +此时,熟悉以太坊的读者可能会注意到,该模块的用途与[ERC20 token standard](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/)类似,后者提供了在智能合约中实现可替代代币的接口。使用泛型的一个关键优势是能够重用代码,因为泛型模块库已经提供了标准实现,并且实例化模块可以通过包装标准实现提供定制化功能。 + +We provide a little module called [`MyOddCoin`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_6/BasicCoin/sources/MyOddCoin.move) that instantiates the `Coin` type and customizes its transfer policy: only odd number of coins can be transferred. We also include two [tests](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_6/BasicCoin/sources/MyOddCoin.move) to test this behavior. You can use the commands you learned in step 2 and step 5 to run the tests. + +我们提供了一个称为[`MyOddCoin`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_6/BasicCoin/sources/MyOddCoin.move)并实例化 `Coin` 类型并自定义其转移策略的小模块:只能转移奇数个代币。其还包括两个 [tests](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_6/BasicCoin/sources/MyOddCoin.move)来测试这种行为。您可以使用在第 2 步和第 5 步中学到的命令来运行测试。 + + +#### 进阶主题 (Advanced topics): + +
+ +phantom 类型参数 (phantom type parameters) + +In definitions of both `Coin` and `Balance`, we declare the type parameter `CoinType` to be phantom because `CoinType` is not used in the struct definition or is only used as a phantom type parameter. + +在 `Coin` 和 `Balance `的定义中,我们将类型参数 `CoinType` 声明为phantom,因为 `CoinType` 没有在结构体定义中使用或仅用作 phantom 类型参数。 + +Read more about phantom type parameters here. + +阅读更多有关 [phantom 类型参数](./generics.md#phantom-type-parameters) 信息. + +
+ +## 进阶步骤 (Advanced steps) + +Before moving on to the next steps, let's make sure you have all the prover dependencies installed. + +在继续下一步之前,确保您已安装所有的验证器依赖项。 + +Try running `boogie /version `. If an error message shows up saying "command not found: boogie", you will have to run the setup script and source your profile: + +尝试运行 `boogie /version` 。如果出现错误消息“找不到命令:boogie”,您将必须运行安装脚本并更新环境配置(`source ~/.profile`): + +```bash +# run the following in move repo root directory +./scripts/dev_setup.sh -yp +source ~/.profile +``` + +## Step 7: 使用Move验证器(Use the Move prover) + +Smart contracts deployed on the blockchain may manipulate high-value assets. As a technique that uses strict mathematical methods to describe behavior and reason correctness of computer systems, formal verification has been used in blockchains to prevent bugs in smart contracts. [The Move prover](https://github.com/move-language/move/blob/main/language/move-prover/doc/user/prover-guide.md) is an evolving formal verification tool for smart contracts written in the Move language. The user can specify functional properties of smart contracts using the [Move Specification Language (MSL)](https://github.com/move-language/move/blob/main/language/move-prover/doc/user/spec-lang.md) and then use the prover to automatically check them statically. To illustrate how the prover is used, we have added the following code snippet to the [BasicCoin.move](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_7/BasicCoin/sources/BasicCoin.move): + +部署在区块链上的智能合约可能会操纵高价值资产。作为一种使用严格的数学方式来描述计算机系统的行为和推理正确性的技术,形式化验证已被用于区块链,以防止智能合约中错误的产生。 [Move验证器](https://github.com/move-language/move/blob/main/language/move-prover/doc/user/prover-guide.md)是一种在进化中、用Move 语言编写的智能合约形式化验证工具。用户可以使用[Move语言规范(Move Specification Language (MSL))](https://github.com/move-language/move/blob/main/language/move-prover/doc/user/spec-lang.md)指定智能合约的功能属性,然后使用验证器自动静态检查它们。 +为了说明如何使用验证器,我们在[BasicCoin.move](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_7/BasicCoin/sources/BasicCoin.move)中添加了以下代码片段: + +``` + spec balance_of { + pragma aborts_if_is_strict; + } +``` + +Informally speaking, the block `spec balance_of {...}` contains the property specification of the method `balance_of`. + +通俗地说,代码块 `spec balance_of {...}` 包含 `balance_of` 方法的属性规范说明。 + +Let's first run the prover using the following command inside [`BasicCoin` directory](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_7/BasicCoin/): + +首先在[`BasicCoin` directory](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_7/BasicCoin/)目录中使用以下命令运行验证器。 + +```bash +move prove +``` + +which outputs the following error information: + +它输出以下错误信息: + +``` +error: abort not covered by any of the `aborts_if` clauses + ┌─ ./sources/BasicCoin.move:38:5 + │ +35 │ borrow_global>(owner).coin.value + │ ------------- 由于执行失败这里发生中止 + · +38 │ ╭ spec balance_of { +39 │ │ pragma aborts_if_is_strict; +40 │ │ } + │ ╰─────^ + │ + = at ./sources/BasicCoin.move:34: balance_of + = owner = 0x29 + = at ./sources/BasicCoin.move:35: balance_of + = 中止 + +Error: exiting with verification errors +``` + +The prover basically tells us that we need to explicitly specify the condition under which the function `balance_of` will abort, which is caused by calling the function `borrow_global` when `owner` does not own the resource `Balance`. To remove this error information, we add an `aborts_if` condition as follows: + +验证器大体上告诉我们,我们需要明确指定函数 `balance_of` 中止的条件,中止原因是 `owner`(函数调用者)在没有资源 `Balance` 的情况下调用 `borrow_global` 函数导致的。要去掉此错误信息,我们添加如下 `aborts_if` 条件: + + +``` + spec balance_of { + pragma aborts_if_is_strict; + aborts_if !exists>(owner); + } +``` + +After adding this condition, try running the `prove` command again to confirm that there are no verification errors: + +添加此条件后,再次尝试运行prove命令,确认没有验证错误: + +```bash +move prove +``` + +Apart from the abort condition, we also want to define the functional properties. In Step 8, we will give more detailed introduction to the prover by specifying properties for the methods defined the `BasicCoin` module. + +除了中止条件,我们还想定义功能属性。在第 8 步中,我们将通过为定义 `BasicCoin` 模块的方法指定属性来更详细地介绍验证器。 + + +## 第 8 步:为 `BasicCoin` 模块编写正式规范(Write formal specifications for the `BasicCoin` module) + +
+ + 取款方法 (Method withdraw) + +The signature of the method `withdraw` is given below: + + 取款(`withdraw`) 方法的签名如下: + +``` +fun withdraw(addr: address, amount: u64) : Coin acquires Balance +``` + +The method withdraws tokens with value `amount` from the address `addr` and returns a created Coin of value `amount`. The method `withdraw` aborts when 1) `addr` does not have the resource `Balance` or 2) the number of tokens in `addr` is smaller than `amount`. We can define conditions like this: + +该方法从地址 `addr` 中提取数量为 `amount` 的代币,然后创建数量为 `amount` 的代币并将其返回。当出现如下情况会中止: + 1) 地址 `addr` 没有资源 `Balance`,或 + 2) 地址 `addr` 中的代币数量小于 `amount` 时,`withdraw` 。 + +我们可以这样定义条件: + +``` + spec withdraw { + let balance = global>(addr).coin.value; + aborts_if !exists>(addr); + aborts_if balance < amount; + } +``` + +As we can see here, a spec block can contain let bindings which introduce names for expressions. `global(address): T` is a built-in function that returns the resource value at `addr`. `balance` is the number of tokens owned by `addr`. `exists(address): bool` is a built-in function that returns true if the resource T exists at address. Two `aborts_if` clauses correspond to the two conditions mentioned above. In general, if a function has more than one `aborts_if` condition, those conditions are or-ed with each other. By default, if a user wants to specify aborts conditions, all possible conditions need to be listed. Otherwise, the prover will generate a verification error. However, if `pragma aborts_if_is_partial` is defined in the spec block, the combined aborts condition (the or-ed individual conditions) only *imply* that the function aborts. The reader can refer to the [MSL](https://github.com/move-language/move/blob/main/language/move-prover/doc/user/spec-lang.md) document for more information. + +正如我们在这里看到的,一个 spec 块可以包含 `let` 绑定,它为表达式引入名称。 +`global(address): T` 是一个返回 `addr` 资源值的内置函数。`balance` 是 `addr` 拥有的代币数量。 +`exists(address): bool` 是一个内置函数,如果指定的地址(address)在(全局存储中)有资源 `T` 则返回 `true` 。 +两个 `aborts_if` 子句对应上述两个条件。通常,如果一个函数有多个 `aborts_if` 条件,这些条件之间是相互对等的。默认情况下,如果用户想要指定中止条件,则需要列出所有可能的条件。否则验证器将产生验证错误。 +但是,如果在 `spec` 代码块中定义了 `pragma aborts_if_is_partial`,则组合中止条件(或对等的单个条件)仅 *暗示* 函数中止。 +读者可以参考 [MSL](https://github.com/move-language/move/blob/main/language/move-prover/doc/user/spec-lang.md) 文档了解更多信息。 + +The next step is to define functional properties, which are described in the two `ensures` clauses below. First, by using the `let post` binding, `balance_post` represents the balance of `addr` after the execution, which should be equal to `balance - amount`. Then, the return value (denoted as `result`) should be a coin with value `amount`. + +下一步是定义功能属性,这些属性在下面的两个 `ensures` 子句中进行了描述。首先,通过使用 `let post` 绑定,`balance_post` 表示地址 `addr` 执行后的余额,应该等于 `balance - amount`。那么,返回值(表示为 `result` )应该是一个价值为 `amount` 的代币。 + +``` + spec withdraw { + let balance = global>(addr).coin.value; + aborts_if !exists>(addr); + aborts_if balance < amount; + + let post balance_post = global>(addr).coin.value; + ensures balance_post == balance - amount; + ensures result == Coin { value: amount }; + } +``` +
+ +
+ + 存款方法 (Method deposit) + +The signature of the method `deposit` is given below: + +存款(`deposit`)方法的签名如下: + +``` +fun deposit(addr: address, check: Coin) acquires Balance +``` + +The method deposits the `check` into `addr`. The specification is defined below: + +该方法将代币 `check` 存入地址 `addr`. 规范定义如下: + +``` + spec deposit { + let balance = global>(addr).coin.value; + let check_value = check.value; + + aborts_if !exists>(addr); + aborts_if balance + check_value > MAX_U64; + + let post balance_post = global>(addr).coin.value; + ensures balance_post == balance + check_value; + } +``` + +`balance` represents the number of tokens in `addr` before execution and `check_value` represents the number of tokens to be deposited. The method would abort if 1) `addr` does not have the resource `Balance` or 2) the sum of `balance` and `check_value` is greater than the maxium value of the type `u64`. The functional property checks that the balance is correctly updated after the execution. + +`balance` 表示 `addr` 执行前的代币数量,`check_value` 表示要存入的代币数量。方法出现如下情况将会中止: + 1) 地址 `addr` 没有 `Balance` 资源, 或 + 2) `balance` 与 `check_value` 之和大于 `u64` 的最大值。 + +该功能属性检查执行后余额是否正确更新。 + + +
+ +
+ + 转账方法 (Method transfer) + +The signature of the method `transfer` is given below: + +转账(`transfer`)方法的签名如下: + +``` +public fun transfer(from: &signer, to: address, amount: u64, _witness: CoinType) acquires Balance +``` + +The method transfers the `amount` of coin from the account of `from` to the address `to`. The specification is given below: + +该方法将数量为 `amount` 的代币从帐户 `from` 转账给地址 `to`。规范如下: + +``` + spec transfer { + let addr_from = signer::address_of(from); + + let balance_from = global>(addr_from).coin.value; + let balance_to = global>(to).coin.value; + let post balance_from_post = global>(addr_from).coin.value; + let post balance_to_post = global>(to).coin.value; + + ensures balance_from_post == balance_from - amount; + ensures balance_to_post == balance_to + amount; + } +``` + +`addr_from` is the address of `from`. Then the balances of `addr_from` and `to` before and after the execution are obtained. +The `ensures` clauses specify that the `amount` number of tokens is deducted from `addr_from` and added to `to`. However, the prover will generate the error information as below: + +`addr_from` 是账户 `from` 的地址,然后获取执行前两个地址 `addr_from` 和 `to` 的余额。 + `ensures` 子句指定从 `addr_from` 减去 `amount` 数量的代币,添加到 `to`。然而,验证器会生成以下错误: + +``` +error: post-condition does not hold + ┌─ ./sources/BasicCoin.move:57:9 + │ +62 │ ensures balance_from_post == balance_from - amount; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + │ + ... +``` + +The property is not held when `addr_from` is equal to `to`. As a result, we could add an assertion `assert!(from_addr != to)` in the method to make sure that `addr_from` is not equal to `to`. + +当 `addr_from` 等于 `to` 时,这个属性无效。因此,我们可以在方法中添加一个断言,`assert!(from_addr != to)` 来确保 `addr_from` 不等于 `to`。 + +
+ + +
+ + 练习 (Exercises) + +- Implement the `aborts_if` conditions for the `transfer` method. +- 为` transfer` 方法实现 `aborts_if` 条件。 +- Implement the specification for the `mint` and `publish_balance` method. +- 为 `mint` 和 `publish_balance` 方法实现规范。 + +The solution to this exercise can be found in [`step_8_sol`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_8_sol). + +练习的解答可以在 [`step_8_sol`](https://github.com/move-language/move/tree/main/language/documentation/tutorial/step_8_sol)中找到。 diff --git a/language/documentation/book/translations/move-book-zh/src/overview.md b/language/documentation/book/translations/move-book-zh/src/overview.md new file mode 100644 index 0000000000..d08bf43529 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/overview.md @@ -0,0 +1,200 @@ +--- +id: overview +title: Overview +sidebar_label: Move +--- + +Move is a next generation language for secure, sandboxed, and formally verified programming. Its first use case is for the Diem blockchain, where Move provides the foundation for its implementation. However, Move has been developed with use cases in mind outside a blockchain context as well. + +### Start Here + + + + + + + +### Primitive Types + + + + + + + + + + + +### Basic Concepts + + + + + + + + + + + + + + +### Global Storage + + + + + + +### Reference + + + + + diff --git a/language/documentation/book/translations/move-book-zh/src/packages.md b/language/documentation/book/translations/move-book-zh/src/packages.md new file mode 100644 index 0000000000..4ab185d120 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/packages.md @@ -0,0 +1,348 @@ +# 程序包(packages) + +Packages allow Move programmers to more easily re-use code and share it +across projects. The Move package system allows programmers to easily: +* Define a package containing Move code; +* Parameterize a package by [named addresses](./address.md); +* Import and use packages in other Move code and instantiate named addresses; +* Build packages and generate associated compilation artifacts from packages; and +* Work with a common interface around compiled Move artifacts. + +包允许 `Move` 程序员更轻松地重用代码并在项目之间共享。`Move` 包系统允许程序员轻松地: +* 定义一个包含 `Move`代码的包; +* 通过命名地址参数化包; +* 在其他 `Move` 代码中导入和使用包并实例化命名地址; +* 构建包并从包中生成相关的编译源代码; +* 使用围绕已编译 `Move` 工件的通用接口。 + +## 包布局和清单语法(Package Layout and Manifest Syntax) + +A Move package source directory contains a `Move.toml` package manifest +file along with a set of subdirectories: + +`Move` 包源目录包含一个`Move.toml`包清单文件以及一组子目录: + +``` + a_move_package + ├── Move.toml (required)(需要的) + ├── sources (required)(需要的) + ├── examples (optional, test & dev mode)(可选的,测试 & 开发者模式) + ├── scripts (optional)(可选的) + ├── doc_templates (optional)(可选的) + └── tests (optional, test mode)(可选的,测试模式) +``` + +The directories marked `required` _must_ be present in order for the directory +to be considered a Move package and to be compiled. Optional directories can +be present, and if so will be included in the compilation process. Depending on +the mode that the package is built with (`test` or `dev`), the `tests` and +`examples` directories will be included as well. + +标记为`required` 的目录必须存在才可以将该目录作为 `Move` 包并进行编译。可选目录被视为可存在的,如果存在,将包含在编译过程里。根据使用 (`test`或`dev`)构建包的模式,`tests`和`examples` 目录也将包含在内。 + +The `sources` directory can contain both Move modules and Move scripts (both +transaction scripts and modules containing script functions). The `examples` +directory can hold additional code to be used only for development and/or +tutorial purposes that will not be included when compiled outside `test` or +`dev` mode. + +`sources`目录可以包含 `Move` 模块和 `Move` 脚本(事务脚本和包含脚本函数的模块)。`Example`目录可以保留仅用于开发和/或用作教程目的附加代码,当在 `test` 或者`dev`模式之外时,这些附加代码编译时不会被包括进来。 + +A `scripts` directory is supported so transaction scripts can be separated +from modules if that is desired by the package author. The `scripts` +directory will always be included for compilation if it is present. +Documentation will be built using any documentation templates present in +the `doc_templates` directory. + +`scripts`目录是被支持的,如果包作者需要,事物脚本可以从模块中分离。如果该`scripts`目录存在,则编译时将始终包含该目录。 +Move将使用存在于`doc_templates` 目录的任何模板构建文档。 + + +### 包清单 Move.toml + +The Move package manifest is defined within the `Move.toml` file and has the +following syntax. Optional fields are marked with `*`, `+` denotes +one or more elements: + +Move 包清单在`Move.toml`文件中定义,并具有以下语法。可选字段标有`*`,`+`表示一个或多个元素: +``` + [package] + name = # e.g., "MoveStdlib" + version = ".." # e.g., "0.1.1" + license* = # e.g., "MIT", "GPL", "Apache 2.0" + authors* = [] # e.g., ["Joe Smith (joesmith@noemail.com)", "Jane Smith (janesmith@noemail.com)"] + + [addresses] # (Optional section) Declares named addresses in this package and instantiates named addresses in the package graph + # One or more lines declaring named addresses in the following format + = "_" | "" # e.g., std = "_" or my_addr = "0xC0FFEECAFE" + + [dependencies] # (Optional section) Paths to dependencies and instantiations or renamings of named addresses from each dependency + # One or more lines declaring dependencies in the following format + = { local = , addr_subst* = { ( = ( | ""))+ } } # local dependencies + = { git = , subdir=, rev=, addr_subst* = { ( = ( | ""))+ } } # git dependencies + + [dev-addresses] # (Optional section) Same as [addresses] section, but only included in "dev" and "test" modes + # One or more lines declaring dev named addresses in the following format + = "_" | "" # e.g., std = "_" or my_addr = "0xC0FFEECAFE" + + [dev-dependencies] # (Optional section) Same as [dependencies] section, but only included in "dev" and "test" modes + # One or more lines declaring dev dependencies in the following format + = { local = , addr_subst* = { ( = ( |
))+ } } +``` +An example of a minimal package manifest with one local dependency and one git dependency: + +一个具有局部依赖项和一个 git 依赖项的最小包清单示例: +``` + [package] + name = "AName" + version = "0.0.0" +``` + +An example of a more standard package manifest that also includes the Move +standard library and instantiates the named address `Std` from it with the +address value `0x1`: + +一个包括 Move 标准库并从中使用地址值`0x1`实例化命名地址`Std`的更标准的包清单示例: + +``` + [package] + name = "AName" + version = "0.0.0" + license = "Apache 2.0" + + [addresses] + address_to_be_filled_in = "_" + specified_address = "0xB0B" + + [dependencies] + # Local dependency + LocalDep = { local = "projects/move-awesomeness", addr_subst = { "std" = "0x1" } } + # Git dependency + MoveStdlib = { git = "https://github.com/diem/diem.git", subdir="language/move-stdlib", rev = "56ab033cc403b489e891424a629e76f643d4fb6b" } + + [dev-addresses] # For use when developing this module + address_to_be_filled_in = "0x101010101" + ``` + +Most of the sections in the package manifest are self explanatory, but named +addresses can be a bit difficult to understand so it's worth examining them in +a bit more detail. + +包清单中的大部分段落都是不言自明的,但命名地址可能有点难以理解,因此值得更详细地检查它们。 + +## 编译期间的命名地址(Named Addresses During Compilation) + +Recall that Move has [named addresses](./address.md) and that +named addresses cannot be declared in Move. Because of this, until now +named addresses and their values needed to be passed to the compiler on the +command line. With the Move package system this is no longer needed, and +you can declare named addresses in the package, instantiate other named +addresses in scope, and rename named addresses from other packages within +the Move package system manifest file. Let's go through each of these +individually: + +回想一下,Move 具有命名地址,并且不能在 Move 中声明命名地址。正因为如此,到目前为止,命名地址及其值都需要在命令行上传递给编译器。但使用 Move 包系统时这将不再需要,您可以在包中声明命名地址,实例化范围内的其他命名地址,并从 Move 包系统清单文件中的其他包重命名命名地址,让我们分别来看看这些: + +### 声明(Declaration) +Let's say we have a Move module in `example_pkg/sources/A.move` as follows: + +假设我们有一个Move模块,`example_pkg/sources/A.move`如下所示: + +```move + module named_addr::A { + public fun x(): address { @named_addr } + } +``` + +We could in `example_pkg/Move.toml` declare the named address `named_addr` in +two different ways. The first: + +我们可以用两种不同`example_pkg/Move.toml`的方式声明命名地址`named_addr`。首先: + +``` + [package] + name = "ExamplePkg" + ... + [addresses] + named_addr = "_" +``` + +Declares `named_addr` as a named address in the package `ExamplePkg` and +that _this address can be any valid address value_. Therefore an importing +package can pick the value of the named address `named_addr` to be any address +it wishes. Intuitively you can think of this as parameterizing the package +`ExamplePkg` by the named address `named_addr`, and the package can then be +instantiated later on by an importing package. + +声明`named_addr`为包`ExamplePkg`中的命名地址,并且 _该地址可以是任何有效的地址值_。因此,导入包可以选择命名地址的值作为`named_addr`它希望的任何地址。直观地,您可以将其视为通过命名地址`named_addr`参数化包 `ExamplePkg`,然后稍后通过导入包使包被实例化。 + +`named_addr` can also be declared as: + +`named_addr`也可以声明为: + +``` + [package] + name = "ExamplePkg" + ... + [addresses] + named_addr = "0xCAFE" +``` + +which states that the named address `named_addr` is exactly `0xCAFE` and cannot be +changed. This is useful so other importing packages can use this named +address without needing to worry about the exact value assigned to it. + +这表明命名的地址`named_addr`是准确的`0xCAFE`并且不能更改。这很有用,因此其他导入包可以使用这个命名地址,而无需担心分配给它的确切值。 + +With these two different declaration methods, there are two ways that +information about named addresses can flow in the package graph: +* The former ("unassigned named addresses") allows named address values to flow + from the importation site to the declaration site. +* The latter ("assigned named addresses") allows named address values to flow + from the declaration site upwards in the package graph to usage sites. + +使用这两种不同的声明方法,有关命名地址的信息可以通过两种方式在包图中流动: +* 前者(“未分配的命名地址”)允许命名地址值从进口站点流向申报站点。 +* 后者(“分配的命名地址”)允许命名地址值从包图中的声明站点向上流动到使用站点。 + +With these two methods for flowing named address information throughout the +package graph the rules around scoping and renaming become important to +understand. + +通过这两种在整个包图中流动命名地址信息的方法,了解范围和重命名的规则变得很重要。 + +## 命名地址的作用域和重命名(Scoping and Renaming of Named Addresses) + +A named address `N` in a package `P` is in scope if: +1. It declares a named address `N`; or +2. A package in one of `P`'s transitive dependencies declares the named address + `N` and there is a dependency path in the package graph between between `P` and the + declaring package of `N` with no renaming of `N`. + +在包`P`中的命名地址`N`如果满足以下条件,则在作用域内: + + 1. 它声明了一个命名地址`N`;或者 + 2. `P`的传递依赖项之一中的包声明了命名地址`N`,并且封装图在`P`和没有重命名的声明包`N`之间有一个依赖路径。 + + Additionally, every named address in a package is exported. Because of this and +the above scoping rules each package can be viewed as coming with a set of +named addresses that will be brought into scope when the package is imported, +e.g., if the `ExamplePkg` package was imported, that importation would bring +into scope the `named_addr` named address. Because of this, if `P` imports two +packages `P1` and `P2` both of which declare a named address `N` an issue +arises in `P`: which "`N`" is meant when `N` is referred to in `P`? The one +from `P1` or `P2`? To prevent this ambiguity around which package a named +address is coming from, we enforce that the sets of scopes introduced by all +dependencies in a package are disjoint, and provide a way to _rename named +addresses_ when the package that brings them into scope is imported. + + 此外,包中的每个命名地址都会被导出。由于这个和上面的范围规则,每个包都可以被视为带有一组命名地址,当包被导入时,这些地址将被带入作用域,例如,如果包`ExamplePkg`被导入,则该导入会将命名地址`named_addr`带入作用域。 因此,如果`P`导入两个包`P1`并且`P2`都声明了一个命名地址`N`,在`P`中则会出现以下问题:当`N`被引用于`P`时我们指的是哪个`N`?来自`P1`或来自`P2`的`N`? 为了防止命名地址来自哪个包的这种歧义,我们强制一个包中所有依赖项引入的范围集是不相交的,并提供一种在将命名地址带入范围的包被导入时重命名命名地址的方法。 + +Renaming a named address when importing can be done as follows in our `P`, +`P1`, and `P2` example above: + +导入时重命名一个命名地址可以在我们的`P`,`P1`和`P2`上面的示例中完成: +``` + [package] + name = "P" + ... + [dependencies] + P1 = { local = "some_path_to_P1", addr_subst = { "P1N" = "N" } } + P2 = { local = "some_path_to_P2" } +``` +With this renaming `N` refers to the `N` from `P2` and `P1N` will refer to `N` +coming from `P1`: + +这种重命名`N`指的是`P2`中的`N`并且`P1N`将指 `P1`中的`N`: +``` + module N::A { + public fun x(): address { @P1N } + } +``` +It is important to note that _renaming is not local_: once a named address `N` +has been renamed to `N2` in a package `P` all packages that import `P` will not +see `N` but only `N2` unless `N` is reintroduced from outside of `P`. This is +why rule (2) in the scoping rules at the start of this section specifies a +"dependency path in the package graph between between `P` and the declaring +package of `N` with no renaming of `N`." + +重要的是要注意 _重命名不是局部的_:一旦一个命名地址`N`在一个包`P`中被重命名为`N2`,所有导入`P`的包都不会看到`N`但只会看到`N2`,除非`N`是从`P`外引入的。这就是为什么本节开头的范围规则中的规则 (2) 特别说明了“在`P`和没有重命名的声明包`N` 的封装图中的依赖路径” 。 + +### 实例化(Instantiation) + +Named addresses can be instantiated multiple times across the package graph as +long as it is always with the same value. It is an error if the same named +address (regardless of renaming) is instantiated with differing values across +the package graph. + +只要命名地址始终具有相同的值,就可以在封装图中多次实例化命名地址。如果在整个封装图中使用不同的值实例化相同的命名地址(无论是否重命名),则会出现错误。 + +A Move package can only be compiled if all named addresses resolve to a value. +This presents issues if the package wishes to expose an uninstantiated named +address. This is what the `[dev-addresses]` section solves. This section can +set values for named addresses, but cannot introduce any named addresses. +Additionally, only the `[dev-addresses]` in the root package are included in +`dev` mode. For example a root package with the following manifest would not compile +outside of `dev` mode since `named_addr` would be uninstantiated: + +只有当所有命名地址都解析为一个值时,才能编译 Move 包。如果包希望公开未实例化的命名地址,则会出现问题。这就是`[dev-addresses]`段要解决的问题。此段可以设置命名地址的值,但不能引入任何命名地址。此外, `dev`模式下仅根包中的`[dev-addresses]`会被包括进来。例如,具有以下清单的根包将不会在`dev`模式之外编译,因为`named_addr`不会被实例化: +``` +[package] +name = "ExamplePkg" +... +[addresses] +named_addr = "_" + +[dev-addresses] +named_addr = "0xC0FFEE" +``` +## 用法、源代码和数据结构( Usage, Artifacts, and Data Structures) + +The Move package system comes with a command line option as part of the Move +CLI `move `. Unless a +particular path is provided, all package commands will run in the current working +directory. The full list of commands and flags for the Move CLI can be found by +running `move --help`. + +Move 软件包系统带有一个命令行选项,作为 Move CLI 的一部分move ` ` ``。除非提供特定路径,否则所有包命令都将在当前工作目录中运行。可以通过运行`move --help`找到 Move CLI 的命令和标志的完整列表。 + +### 用法(Usage) + +A package can be compiled either through the Move CLI commands, or as a library +command in Rust with the function `compile_package`. This will create a +`CompiledPackage` that holds the compiled bytecode along with other compilation +artifacts (source maps, documentation, ABIs) in memory. This `CompiledPackage` +can be converted to an `OnDiskPackage` and vice versa -- the latter being the data of +the `CompiledPackage` laid out in the file system in the following format: + +一个包可以通过 Move CLI 命令,或是当作Rust函数`compile_package`的库命令来编译。 这种编译方法将创建一个编译包`CompiledPackage` 保存已编译的字节码以及其他编译内存中的源代码(源映射、文档、ABIs)。这个`CompiledPackage`可以转换为`OnDiskPackage`,反之亦然——后者是文件系统中的编译包 `CompiledPackage`数据,它的格式如下: + +``` +a_move_package +├── Move.toml +... +└── build + ├── + │ ├── BuildInfo.yaml + │ ├── bytecode_modules + │ │ └── *.mv + │ ├── source_maps + │ │ └── *.mvsm + │ ├── bytecode_scripts + │ │ └── *.mv + │ ├── abis + │ │ ├── *.abi + │ │ └── /*.abi + │ └── sources + │ └── *.move + ... + └── + ├── BuildInfo.yaml + ... + └── sources +``` + +See the `move-package` crate for more information on these data structures and +how to use the Move package system as a Rust library. + +有关这些数据结构和如何将 Move 包系统用作 Rust 库的更多信息,请参阅 `move-package` 箱(crate) 。 diff --git a/language/documentation/book/translations/move-book-zh/src/references.md b/language/documentation/book/translations/move-book-zh/src/references.md new file mode 100644 index 0000000000..2a23f0cb2e --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/references.md @@ -0,0 +1,289 @@ +# 引用(references) + +Move has two types of references: immutable `&` and mutable `&mut`. Immutable references are read +only, and cannot modify the underlying value (or any of its fields). Mutable references allow for +modifications via a write through that reference. Move's type system enforces an ownership +discipline that prevents reference errors. + +Move 支持两种类型的引用:不可变引用 `&` 和可变引用 `&mut`。不可变引用是只读的,不能修改相关值(或其任何字段)。可变引用通过写入该引用进行修改。Move的类型系统强制执行所有权规则,以避免引用错误。 + +For more details on the rules of references, see [Structs and Resources](./structs-and-resources.md) + +更多有关引用规则的详细信息,请参阅:[结构和资源](./structs-and-resources.html). + +## 引用运算符 (Reference Operators) + +Move provides operators for creating and extending references as well as converting a mutable +reference to an immutable one. Here and elsewhere, we use the notation `e: T` for "expression `e` +has type `T`". + +Move 提供了用于创建和扩展引用以及将可变引用转换为不可变引用的运算符。在这里和其他地方,我们使用符号 `e: T` 来表示“表达式 `e` 的类型是 `T` ” + +| Syntax | Type | Description | +| ----------- | ----------------------------------------------------- | -------------------------------------------------------------- | +| `&e` | `&T` where `e: T` and `T` is a non-reference type | Create an immutable reference to `e` | +| `&mut e` | `&mut T` where `e: T` and `T` is a non-reference type | Create a mutable reference to `e`. | +| `&e.f` | `&T` where `e.f: T` | Create an immutable reference to field `f` of struct `e`. | +| `&mut e.f` | `&mut T` where `e.f: T` | Create a mutable reference to field `f` of struct`e`. | +| `freeze(e)` | `&T` where `e: &mut T` | Convert the mutable reference `e` into an immutable reference. | + +| 语法 | 类型 | 描述 | +| ------ | ------ |------ | +| `&e` | `&T` 其中 `e: T` 和 `T` 是非引用类型 | 创建一个不可变的引用 `e` +| `&mut e` | `&mut T` 其中 `e: T` 和 `T` 是非引用类型 | 创建一个可变的引用 `e` +| `&e.f` | `&T` 其中 `e.f: T` | 创建结构 `e` 的字段 `f` 的不可变引用 +| `&mut e.f` | `&mut T` 其中`e.f: T` | 创建结构 `e` 的字段 `f` 的可变引用 +| `freeze(e)` | `&T` 其中`e: &mut T` | 将可变引用 `e` 转换为不可变引用 + +The `&e.f` and `&mut e.f` operators can be used both to create a new reference into a struct or to extend an existing reference: + +`&e.f`和`&mut e.f`运算符既可以用于在结构中创建新引用,也可以用于扩展现有引用: + +```move +let s = S { f: 10 }; +let f_ref1: &u64 = &s.f; // works +let s_ref: &S = &s; +let f_ref2: &u64 = &s_ref.f // also works +``` + +A reference expression with multiple fields works as long as both structs are in the same module: + +只要两个结构都在同一个模块中,具有多个字段的引用表达式就可以工作: + +```move +struct A { b: B } +struct B { c : u64 } +fun f(a: &A): &u64 { + &a.b.c +} +``` + +Finally, note that references to references are not allowed: + +最后,请注意,不允许引用"引用"(Move不支持多重引用, 但Rust可以,译者注): + +```move +let x = 7; +let y: &u64 = &x; +let z: &&u64 = &y; // will not compile +``` + +## 通过引用读取和写入 + +Both mutable and immutable references can be read to produce a copy of the referenced value. + +Only mutable references can be written. A write `*x = v` discards the value previously stored in `x` +and updates it with `v`. + +可以读取可变和不可变引用以生成引用值的副本。 + +只能写入可变引用。写入表达式 `*x = v` 会丢弃先前存储在x中的值,并用 `v` 更新。 + +Both operations use the C-like `*` syntax. However, note that a read is an expression, whereas a +write is a mutation that must occur on the left hand side of an equals. + +两种操作都使用类 C `*` 语法。但是请注意,读取是一个表达式,而写入是一个必须发生在等号左侧的改动。 + +| Syntax | Type | Description | +| ---------- | ----------------------------------- | ----------------------------------- | +| `*e` | `T` where `e` is `&T` or `&mut T` | Read the value pointed to by `e` | +| `*e1 = e2` | `()` where `e1: &mut T` and `e2: T` | Update the value in `e1` with `e2`. | + +| 语法 | 类型 | 描述 | +| ------ | ------ |------ | +| `*e` | `T` 其中 `e` 为 `&T` 或 `&mut T` | 读取 `e` 所指向的值 +| `*e1 = e2` | () 其中 `e1: &mut T` 和 `e2: T` | 用 `e2` 更新 `e1` 中的值 + +In order for a reference to be read, the underlying type must have the +[`copy` ability](./abilities.md) as reading the reference creates a new copy of the value. This rule +prevents the copying of resource values: + +为了读取引用,相关类型必须具备[`copy` 能力](./abilities.html),因为读取引用会创建值的新副本。此规则防止复制资源值: + +```move= +fun copy_resource_via_ref_bad(c: Coin) { + let c_ref = &c; + let counterfeit: Coin = *c_ref; // not allowed! + pay(c); + pay(counterfeit); +} +``` + +Dually: in order for a reference to be written to, the underlying type must have the +[`drop` ability](./abilities.md) as writing to the reference will discard (or "drop") the old value. +This rule prevents the destruction of resource values: + +双重性:为了写入引用,相关类型必须具备[`drop` 能力](./abilities.html),因为写入引用将丢弃(或“删除”)旧值。此规则可防止破坏资源值: + +```move= +fun destroy_resource_via_ref_bad(ten_coins: Coin, c: Coin) { + let ref = &mut ten_coins; + *ref = c; // not allowed--would destroy 10 coins! +} +``` + +## `freeze` 推断 (`freeze` inference) + +A mutable reference can be used in a context where an immutable reference is expected: + +可变引用可以在预期不可变引用的上下文中使用: + +```move +let x = 7; +let y: &mut u64 = &mut x; +``` + +This works because the under the hood, the compiler inserts `freeze` instructions where they are +needed. Here are a few more examples of `freeze` inference in action: + +这是因为编译器会在底层需要的地方插入 `freeze` 指令。以下是更多 `freeze` 实际推断行为的示例: + +```move= +fun takes_immut_returns_immut(x: &u64): &u64 { x } + +// freeze inference on return value +fun takes_mut_returns_immut(x: &mut u64): &u64 { x } + +fun expression_examples() { + let x = 0; + let y = 0; + takes_immut_returns_immut(&x); // no inference + takes_immut_returns_immut(&mut x); // inferred freeze(&mut x) + takes_mut_returns_immut(&mut x); // no inference + + assert!(&x == &mut y, 42); // inferred freeze(&mut y) +} + +fun assignment_examples() { + let x = 0; + let y = 0; + let imm_ref: &u64 = &x; + + imm_ref = &x; // no inference + imm_ref = &mut y; // inferred freeze(&mut y) +} +``` + +### 子类型化 (Subtyping) + +With this `freeze` inference, the Move type checker can view `&mut T` as a subtype of `&T`. As shown +above, this means that anywhere for any expression where a `&T` value is used, a `&mut T` value can +also be used. This terminology is used in error messages to concisely indicate that a `&mut T` was +needed where a `&T` was supplied. For example + +通过freeze推断,Move 类型检查器可以将 `&mut T` 视为 `&T` 的子类型。 如上所示,这意味着对于使用 `&T` 值的任何表达式,也可以使用 `&mut T` 值。此术语用于错误消息中,以简明扼要地表明在提供 `&T` 的地方需要 `&mut T` 。例如: + +```move= +address 0x42 { + module example { + fun read_and_assign(store: &mut u64, new_value: &u64) { + *store = *new_value + } + + fun subtype_examples() { + let x: &u64 = &0; + let y: &mut u64 = &mut 1; + + x = &mut 1; // valid + y = &2; // invalid! + + read_and_assign(y, x); // valid + read_and_assign(x, y); // invalid! + } + } +} +``` + +will yield the following error messages + +将产生以下错误消息 + +```text +error: + ┌── example.move:12:9 ─── + │ + 12 │ y = &2; // invalid! + │ ^ Invalid assignment to local 'y' + · + 12 │ y = &2; // invalid! + │ -- The type: '&{integer}' + · + 9 │ let y: &mut u64 = &mut 1; + │ -------- Is not a subtype of: '&mut u64' + │ + +error: + ┌── example.move:15:9 ─── + │ + 15 │ read_and_assign(x, y); // invalid! + │ ^^^^^^^^^^^^^^^^^^^^^ Invalid call of '0x42::example::read_and_assign'. Invalid argument for parameter 'store' + · + 8 │ let x: &u64 = &0; + │ ---- The type: '&u64' + · + 3 │ fun read_and_assign(store: &mut u64, new_value: &u64) { + │ -------- Is not a subtype of: '&mut u64' + │ +``` + +The only other types currently that has subtyping are [tuples](./tuples.md) + +当前唯一具有子类型的其他类型是[tuple(元组)](./tuples.html) + +## 所有权 (Ownership) + +Both mutable and immutable references can always be copied and extended _even if there are existing +copies or extensions of the same reference_: + +_即使同一引用存在现有副本或扩展_,可变引用和不可变引用始终可以被复制和扩展: + +```move +fun reference_copies(s: &mut S) { + let s_copy1 = s; // ok + let s_extension = &mut s.f; // also ok + let s_copy2 = s; // still ok + ... +} +``` + +This might be surprising for programmers familiar with Rust's ownership system, which would reject +the code above. Move's type system is more permissive in its treatment of +[copies](./variables.md#move-and-copy), but equally strict in ensuring unique ownership of mutable +references before writes. + +对于熟悉 Rust 所有权系统的程序员来说,这可能会令人惊讶,因为他们会拒绝上面的代码。Move 的类型系统在处理[副本](./variables.html#move-and-copy)方面更加宽松 ,但在写入前确保可变引用的唯一所有权方面同样严格。 + +### 无法存储引用 (References Cannot Be Stored) + +References and tuples are the _only_ types that cannot be stored as a field value of structs, which +also means that they cannot exist in global storage. All references created during program execution +will be destroyed when a Move program terminates; they are entirely ephemeral. This invariant is +also true for values of types without the `store` [ability](./abilities.md), but note that +references and tuples go a step further by never being allowed in structs in the first place. + +This is another difference between Move and Rust, which allows references to be stored inside of +structs. + +引用和元组是唯一不能存储为结构的字段值的类型,这也意味着它们不能存在于全局存储中。当 Move 程序终止时,程序执行期间创建的所有引用都将被销毁;它们完全是短暂的。这种不变式也适用于没有[`store` 能力](./chatper_19_abilities.html)的类型的值,但请注意,引用和元组更进一步,从一开始就不允许出现在结构中。 + +这是 Move 和 Rust 之间的另一个区别,后者允许将引用存储在结构内。 + +Currently, Move cannot support this because references cannot be +[serialized](https://en.wikipedia.org/wiki/Serialization), but _every Move value must be +serializable_. This requirement comes from Move's +[persistent global storage](./global-storage-structure.md), which needs to serialize values to +persist them across program executions. Structs can be written to global storage, and thus they must +be serializable. + +One could imagine a fancier, more expressive, type system that would allow references to be stored +in structs _and_ ban those structs from existing in global storage. We could perhaps allow +references inside of structs that do not have the `store` [ability](./abilities.md), but that would +not completely solve the problem: Move has a fairly complex system for tracking static reference +safety, and this aspect of the type system would also have to be extended to support storing +references inside of structs. In short, Move's type system (particularly the aspects around +reference safety) would have to expand to support stored references. But it is something we are +keeping an eye on as the language evolves. + +目前,Move 无法支持这一点,因为引用无法被[序列化](https://en.wikipedia.org/wiki/Serialization),但 _每个 Move 值都必须是可序列化的_。这个要求来自于 Move 的 [持久化全局存储](./global-storage-structure.html),它需要在程序执行期间序列化值以持久化它们。结构体可以写入全局存储,因此它们必须是可序列化的。 + +可以想象一种更奇特、更有表现力的类型系统,它允许将引用存储在结构中,并禁止这些结构存在于全局存储中。我们也许可以允许在没有[`store` 能力](./abilities.html)的结构内部使用引用,但这并不能完全解决问题:Move 有一个相当复杂的系统来跟踪静态引用安全性,并且类型系统的这一方面也必须扩展以支持在结构内部存储引用。简而言之,Move 的类型系统(尤其是与引用安全相关的方面)需要扩展以支持存储的引用。随着语言的发展,我们正在关注这一点。 diff --git a/language/documentation/book/translations/move-book-zh/src/signer.md b/language/documentation/book/translations/move-book-zh/src/signer.md new file mode 100644 index 0000000000..2bba515c0a --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/signer.md @@ -0,0 +1,60 @@ +# 签名者 + +`签名者(signer)`是 Move 内置的资源类型。`签名者(signer)`是一种允许持有者代表特定`地址(address)`行使权力的[能力(capability)](https://en.wikipedia.org/wiki/Object-capability_model)。你可以将原生实现(native implementation)视为: + +```move +struct signer has drop { a: address } +``` + +`signer` 有点像 Unix [UID](https://en.wikipedia.org/wiki/User_identifier),因为它表示一个通过 Move *之外*的代码(例如,通过检查加密签名或密码)进行身份验证的用户。 + +## 与 `address` 的比较 + +Move 程序可以使用地址字面量(literal)创建任何`地址(address)`值,而无需特殊许可: + +```move +let a1 = @0x1; +let a2 = @0x2; +// ... 等等,所有其他可能的地址 +``` + +但是,`signer` 值是特殊的,因为它们不能通过字面量或者指令创建 —— 只能通过 Move 虚拟机(VM)创建。在虚拟机运行带有 `signer` 类型参数的脚本之前,它会自动创建 `signer` 值并将它们传递给脚本: + +```move +script { + use std::signer; + fun main(s: signer) { + assert!(signer::address_of(&s) == @0x42, 0); + } +} +``` + +如果脚本是从 `0x42` 以外的任何地址发送的,则此脚本将中止并返回代码 `0`。 + +交易脚本可以有任意数量的 `signer`,只要 `signer` 参数排在其他参数前面。换句话说,所有 `signer` 参数都必须放在第一位。 + +```move +script { + use std::signer; + fun main(s1: signer, s2: signer, x: u64, y: u8) { + // ... + } +} +``` + +这对于实现具有多方权限原子行为的*多重签名脚本(multi-signer scripts)*很有用。例如,上述脚本的扩展可以在 `s1` 和 `s2` 之间执行原子货币交换。 + +## `signer` 操作符 + +`std::signer` 标准库模块为 `signer` 提供了两个实用函数: + +| 函数 | 描述 | +| ------------------------------------------- | ------------------------------------------------------------- | +| `signer::address_of(&signer): address` | 返回由 `&signer` 包装的地址值。 | +| `signer::borrow_address(&signer): &address` | 返回由 `&signer` 包装的地址的引用。 | + +此外,`move_to(&signer, T)` [全局存储](./global-storage-operators.md)操作符需要一个 `&signer` 参数在 `signer.address` 的帐户下发布资源 `T`。这确保了只有经过身份验证的用户才能在其地址下发布资源。 + +## 所有权 + +与简单的标量值不同,`signer` 值是不可复制的,这意味着他们不能被复制(通过任何操作,无论是通过显式 [`copy`](./variables.md#移动和复制)指令还是通过[解引用(dereference)`*`](./references.md#通过引用读取和写入))。 diff --git a/language/documentation/book/translations/move-book-zh/src/standard-library.md b/language/documentation/book/translations/move-book-zh/src/standard-library.md new file mode 100644 index 0000000000..85c8d9f433 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/standard-library.md @@ -0,0 +1,695 @@ +# 标准库(Standard Library) + +The Move standard library exposes interfaces that implement the following functionality: +* [Basic operations on vectors](#vector). +* [Option types and operations on`Option` types](#option). +* [A common error encoding code interface for abort codes](#errors). +* [32-bit precision fixed-point numbers](#fixed_point32). + +Move标准库公开了实现以下功能的接口: +* [向量的基本操作](#向量). +* [Option类型与基本操作](#option). +* [终止码的常见错误编码接口](#errors). +* [32位精确定点数字](#fixed_point32). + +## 向量(vector) + + +The `vector` module defines a number of operations over the primitive +[`vector`](./vector.md) type. The module is published under the +named address `Std` and consists of a number of native functions, as +well as functions defined in Move. The API for this module is as follows. + +`向量`模块在原生类型[`向量`](./vector.md)上定义了许多操作。该模块以命名地址`Std`发布,并由许多原生函数以及在Move中定义的函数组成。此模块的API如下所示: + +### 函数(Functions) + +--------------------------------------------------------------------------- + +Create an empty [`vector`](./vector.md). +The `Element` type can be both a `resource` or `copyable` type. + +创建一个空的[`向量`](./vector.md)。 +`Element`类型可以是`资源`或`可复制`类型。 + +```move + native public fun empty(): vector; +``` + +--------------------------------------------------------------------------- + +Create a vector of length `1` containing the passed in `element`. + +创建一个长度为`1`的vector,并且包含传入的`element`。 + +```move + public fun singleton(e: Element): vector; +``` + +--------------------------------------------------------------------------- + +Destroy (deallocate) the vector `v`. Will abort if `v` is non-empty. +*Note*: The emptiness restriction is due to the fact that `Element` can be a +resource type, and destruction of a non-empty vector would violate +[resource conservation](./structs-and-resources.md). + +销毁(释放)向量`v`。如果`v`非空操作将终止。 +*注意*:空的限制是由于`Element`可以是资源类型,而销毁非空的向量会违反[资源保护机制](./structs-and-resources.md)。 + +```move + native public fun destroy_empty(v: vector); +``` + +--------------------------------------------------------------------------- + +Acquire an [immutable reference](./references.md) to the `i`th element of the vector `v`. Will abort if +the index `i` is out of bounds for the vector `v`. + +获取向量`v`的第`i`个元素的[不可变引用](./references.md)。如果索引`i`超出了向量`v`的范围,操作将会终止。 + +```move + native public fun borrow(v: &vector, i: u64): ∈ +``` + +--------------------------------------------------------------------------- + +Acquire a [mutable reference](./references.md) +to the `i`th element of the vector `v`. Will abort if +the index `i` is out of bounds for the vector `v`. + +获取向量`v`的第`i`个元素的[可变引用](./references.md)。如果索引`i`超出了向量`v`的范围,操作将会终止。 + +```move + native public fun borrow_mut(v: &mut vector, i: u64): &mut Element; +``` + +--------------------------------------------------------------------------- + +Empty and destroy the `other` vector, and push each of the elements in +the `other` vector onto the `lhs` vector in the same order as they occurred in `other`. + +清空并销毁`other`动态数组,并将`other`向量中的每个元素按顺序添加到`lhs`动态数组。 + +```move + public fun append(lhs: &mut vector, other: vector); +``` + +--------------------------------------------------------------------------- + +Push an element `e` of type `Element` onto the end of the vector `v`. May +trigger a resizing of the underlying vector's memory. + +将类型为`Element`的元素`e`添加到向量`v`的末尾。可能触发底层向量内存的大小调整。 + +```move + native public fun push_back(v: &mut vector, e: Element); +``` + +--------------------------------------------------------------------------- + +Pop an element from the end of the vector `v` in-place and return the owned +value. Will abort if `v` is empty. + +从向量`v`的末尾取出一个元素并返回。如果`v`为空将终止操作。 + +```move + native public fun pop_back(v: &mut vector): Element; +``` + +--------------------------------------------------------------------------- + +Remove the element at index `i` in the vector `v` and return the owned value +that was previously stored at `i` in `v`. All elements occurring at indices +greater than `i` will be shifted down by 1. Will abort if `i` is out of bounds +for `v`. + +移除向量`v`中索引`i`处的元素,并返回之前存储在`v`中的`i`处的值。所有下标大于`i`的元素将向前移动1个位置。如果`i`超出了`v`的范围,操作将会终止。 + +```move + public fun remove(v: &mut vector, i: u64): Element; +``` + +--------------------------------------------------------------------------- + +Swap the `i`th element of the vector `v` with the last element and then pop +this element off of the back of the vector and return the owned value that +was previously stored at index `i`. +This operation is O(1), but does not preserve ordering of elements in the vector. +Aborts if the index `i` is out of bounds for the vector `v`. + +将向量`v`的第`i`个元素与最后一个元素交换,然后将这个元素从向量的后面取出,并返回之前存储在索引`i`处的所有元素的值。 +这个操作时间复杂度是O(1),但是不保持向量容器中元素的顺序。 +如果索引`i`超出了向量`v`的边界,则操作终止。 + +```move + public fun swap_remove(v: &mut vector, i: u64): Element; +``` + +--------------------------------------------------------------------------- + +Swap the elements at the `i`'th and `j`'th indices in the vector `v`. Will +abort if either of `i` or `j` are out of bounds for `v`. + +交换向量`v`中下标为第`i`和第`j`的元素。如果`i`或`j`中的任何一个超出了`v`的范围,则操作将终止。 + +```move + native public fun swap(v: &mut vector, i: u64, j: u64); +``` + +--------------------------------------------------------------------------- + +Reverse the order of the elements in the vector `v` in-place. + +将向量v中的元素顺序颠倒。 + +```move + public fun reverse(v: &mut vector); +``` + +--------------------------------------------------------------------------- + +Return the index of the first occurrence of an element in `v` that is +equal to `e`. Returns `(true, index)` if such an element was found, and +`(false, 0)` otherwise. + +返回`v`中第一个与`e`相等的元素的索引。如果找到这样的元素,则返回`(true, index)`,否则返回`(false, 0)`。 + +```move + public fun index_of(v: &vector, e: &Element): (bool, u64); +``` + +--------------------------------------------------------------------------- +Return if an element equal to `e` exists in the vector `v`. + +如果向量`v`中存在等于`e`的元素,则返回true, 否则返回false。 + +```move + public fun contains(v: &vector, e: &Element): bool; +``` + +--------------------------------------------------------------------------- +Return the length of a `vector`. + +返回`向量`的长度。 + +```move + native public fun length(v: &vector): u64; +``` + +--------------------------------------------------------------------------- +Return whether the vector `v` is empty. + +如果向量`v`中没有元素,则返回true, 否则返回false。 + +```move + public fun is_empty(v: &vector): bool; +``` + +--------------------------------------------------------------------------- + +## 选项(option) + +The `option` module defines a generic option type `Option` that represents a +value of type `T` that may, or may not, be present. It is published under the named address `Std`. + +`option`模块定义了一个泛型option类型`Option`,它表示类型为`T`的值可能存在,也可能不存在。它发布在命名地址`Std`下。 + +The Move option type is internally represented as a singleton vector, and may +contain a value of `resource` or `copyable` kind. If you are familiar with option +types in other languages, the Move `Option` behaves similarly to those with a +couple notable exceptions since the option can contain a value of kind `resource`. +Particularly, certain operations such as `get_with_default` and +`destroy_with_default` require that the element type `T` be of `copyable` kind. + +Move option类型在内部表示为一个单例向量,可能包含`资源`或`可复制`类型的值。如果你熟悉其他语言中的option类型,Move `Option`的行为与那些类似,但有几个显著的例外,因为option可以包含一个类型为`资源`的值。 +特别地,某些操作如`get_with_default`和`destroy_with_default`要求元素类型`T`为`可复制`类型。 + +The API for the `option` module is as as follows + +`option`模块的API如下所示: + +### 类型(Types) + +Generic type abstraction of a value that may, or may not, be present. Can contain +a value of either `resource` or `copyable` kind. + +一个值的泛型类型的抽象,可能存在,也可能不存在。它可以包含`资源`或`可复制`类型的值。 + +```move + struct Option; +``` + +### 函数(Functions) + +Create an empty `Option` of that can contain a value of `Element` type. + +创建一个可以包含`Element`类型值的空`Option`。 + +```move + public fun none(): Option; +``` + +--------------------------------------------------------------------------- + +Create a non-empty `Option` type containing a value `e` of type `Element`. + +创建一个非空的`Option`类型,包含类型为`Element`的值`e`。 + +```move + public fun some(e: T): Option; +``` + +--------------------------------------------------------------------------- + +Return an immutable reference to the value inside the option `opt_elem` +Will abort if `opt_elem` does not contain a value. + +返回`opt_elem`内部值的不可变引用,如果`opt_elem`不包含值,则将终止操作。 + +```move + public fun borrow(opt_elem: &Option): ∈ +``` + +--------------------------------------------------------------------------- + +Return a reference to the value inside `opt_elem` if it contains one. If +`opt_elem` does not contain a value the passed in `default_ref` reference will be returned. +Does not abort. + +如果`opt_elem`中包含值,则返回该值的引用。如果`opt_elem`不包含值,将返回传入的`default_ref`引用。不会终止操作。 + +```move + public fun borrow_with_default(opt_elem: &Option, default_ref: &Element): ∈ +``` + +--------------------------------------------------------------------------- + +Return a mutable reference to the value inside `opt_elem`. Will abort if +`opt_elem` does not contain a value. + +返回`opt_elem`内部值的可变引用。如果`opt_elem`不包含值,则操作将终止。 + +```move + public fun borrow_mut(opt_elem: &mut Option): &mut Element; +``` + +--------------------------------------------------------------------------- + +Convert an option value that contains a value to one that is empty in-place by +removing and returning the value stored inside `opt_elem`. +Will abort if `opt_elem` does not contain a value. + +通过删除并返回存储在`opt_elem`中的值,将包含值的`opt_elem`转换为空option类型。 +如果`opt_elem`不包含值,则将终止。 + +```move + public fun extract(opt_elem: &mut Option): Element; +``` + +--------------------------------------------------------------------------- + +Return the value contained inside the option `opt_elem` if it contains one. +Will return the passed in `default` value if `opt_elem` does not contain a +value. The `Element` type that the `Option` type is instantiated with must be +of `copyable` kind in order for this function to be callable. + +如果`opt_elem`中包含值,则返回该值。 +如果`opt_elem`不包含值,将返回传入的`default`值。`default`类型必须是`可复制`类型,这样该函数才能被调用。 + +```move + public fun get_with_default(opt_elem: &Option, default: Element): Element; +``` + +--------------------------------------------------------------------------- + +Convert an empty option `opt_elem` to an option value that contains the value `e`. +Will abort if `opt_elem` already contains a value. + +将空option类型`opt_elem`转换为包含值`e`的option类。 +如果`opt_elem`已经包含值,则操作将终止。 + +```move + public fun fill(opt_elem: &mut Option, e: Element); +``` + +--------------------------------------------------------------------------- + +Swap the value currently contained in `opt_elem` with `new_elem` and return the +previously contained value. Will abort if `opt_elem` does not contain a value. + +将`opt_elem`当前包含的值与`new_elem`交换,并返回先前包含的值。如果`opt_elem`不包含值,则操作将终止。 + +```move + public fun swap(opt_elem: &mut Option, e: Element): Element; +``` + +--------------------------------------------------------------------------- + +Return true if `opt_elem` contains a value equal to the value of `e_ref`. +Otherwise, `false` will be returned. + +如果`opt_elem`包含一个等于`e_ref`的值,则返回`true`。否则,将返回`false`。 + +```move + public fun contains(opt_elem: &Option, e_ref: &Element): bool; +``` + +--------------------------------------------------------------------------- + +Return `true` if `opt_elem` does not contain a value. + +如果`opt_elem`不包含值,则返回`true`。 + +```move + public fun is_none(opt_elem: &Option): bool; +``` + +--------------------------------------------------------------------------- + +Return `true` if `opt_elem` contains a value. + +如果`opt_elem`包含值,则返回`true`。 + +```move + public fun is_some(opt_elem: &Option): bool; +``` + +--------------------------------------------------------------------------- + +Unpack `opt_elem` and return the value that it contained. +Will abort if `opt_elem` does not contain a value. + +解包`opt_elem`并返回它所包含的值。 +如果`opt_elem`不包含值,则操作将终止。 + +```move + public fun destroy_some(opt_elem: Option): Element; +``` + +--------------------------------------------------------------------------- + +Destroys the `opt_elem` value passed in. If `opt_elem` contained a value it +will be returned otherwise, the passed in `default` value will be returned. + +销毁传入的`opt_elem`。如果`opt_elem`包含值,它将被返回,否则将返回传入的`default`值。 + +```move + public fun destroy_with_default(opt_elem: Option, default: Element): Element; +``` + +--------------------------------------------------------------------------- + +Destroys the `opt_elem` value passed in, `opt_elem` must be empty and not +contain a value. Will abort if `opt_elem` contains a value. + +销毁传入的`opt_elem`,`opt_elem`必须为空且不包含值。如果`opt_elem`包含一个值,则会终止操作。 + +```move + public fun destroy_none(opt_elem: Option); +``` + +## 错误(errors) + +Recall that each abort code in Move is represented as an unsigned 64-bit integer. The `errors` module defines a common interface that can be used to "tag" each of these abort codes so that they can represent both the error **category** along with an error **reason**. + +回想一下,Move中的每个终止代码都表示为无符号64位整数。`errors`模块定义了一个通用接口,可用于"标记"每个终止代码,以便它们既可以表示错误**类别**,也可以表示错误**原因**。 + +Error categories are declared as constants in the `errors` module and are globally unique with respect to this module. Error reasons on the other hand are module-specific error codes, and can provide greater detail (perhaps, even a particular _reason_) about the specific error condition. This representation of a category and reason for each error code is done by dividing the abort code into two sections. + +错误类别在`errors`模块中声明为常量,并且对该模块来说是全局唯一的。另一方面,错误原因是特定于模块的错误代码,可以提供关于特定错误条件的更详细的信息(甚至可能是一个特定的_reason_)。每个错误代码的类别和原因的这种表示是通过将终止代码分成两部分来完成的。 + +The lower 8 bits of the abort code hold the *error category*. The remaining 56 bits of the abort code hold the *error reason*. +The reason should be a unique number relative to the module which raised the error and can be used to obtain more information about the error at hand. It should mostly be used for diagnostic purposes as error reasons may change over time if the module is updated. + +| Category | Reason | +|----------|--------| +| 8 bits | 56 bits| + +Since error categories are globally stable, these present the most stable API and should in general be what is used by clients to determine the messages they may present to users (whereas the reason is useful for diagnostic purposes). There are public functions in the `errors` module for creating an abort code of each error category with a specific `reason` number (represented as a `u64`). + +终止代码的较低8位保存*错误类别*。终止代码的其余56位包含*错误原因*。 +原因应该是相对于引发错误的模块的唯一数字,并且可以用来获取关于当前错误的更多信息。它应该主要用于诊断目的,因为如果模块更新,错误原因可能会随着时间的推移而变化。 + +| 类型 | 原因 | +|----------|--------| +| 8 bits | 56 bits| + +由于错误类别是全局稳定的,所以它们提供了稳定的API,通常应该由客户端用来确定它们可能向用户提供的消息(而原因则用于诊断目的)。在`errors`模块中有一些公共函数,用于创建每个错误类别的带有特定`原因`号的终止代码(表示为`u64`)。 + +### 常量(Constants) + +The system is in a state where the performed operation is not allowed. + +系统处于不允许操作的状态。 + +```move + const INVALID_STATE: u8 = 1; +``` + +--------------------------------------------------------------------------- +A specific account address was required to perform an operation, but a different address from what was expected was encounterd. + +执行操作需要一个特定的帐户地址,但遇到的地址与预期的不同。 + +```move + const REQUIRES_ADDRESS: u8 = 2; +``` + +--------------------------------------------------------------------------- +An account did not have the expected role for this operation. Useful for Role Based Access Control (RBAC) error conditions. + +帐户没有此操作的预期角色。用于基于角色访问控制(RBAC)错误。 + +```move + const REQUIRES_ROLE: u8 = 3; +``` + +--------------------------------------------------------------------------- +An account did not not have a required capability. Useful for RBAC error conditions. + +帐户没有所需的能力。用于RBAC错误。 + +```move + const REQUIRES_CAPABILITY: u8 = 4; +``` + +--------------------------------------------------------------------------- +A resource was expected, but did not exist under an address. + +地址下不存在期望的资源。 + +```move + const NOT_PUBLISHED: u8 = 5; +``` + +--------------------------------------------------------------------------- +Attempted to publish a resource under an address where one was already published. + +试图在已发布资源的地址发布资源。 + +```move + const ALREADY_PUBLISHED: u8 = 6; +``` + +--------------------------------------------------------------------------- +An argument provided for an operation was invalid. + +为操作提供的参数无效。 + +```move + const INVALID_ARGUMENT: u8 = 7; +``` + +--------------------------------------------------------------------------- +A limit on a value was exceeded. + +超过了一个值的限制。 + +```move + const LIMIT_EXCEEDED: u8 = 8; +``` + +--------------------------------------------------------------------------- +An internal error (bug) has occurred. + +发生了内部错误(bug)。 + +```move + const INTERNAL: u8 = 10; +``` + +--------------------------------------------------------------------------- +A custom error category for extension points. + +扩展自定义错误类别。 + +```move + const CUSTOM: u8 = 255; +``` + +--------------------------------------------------------------------------- + +### 函数(Functions) + + Should be used in the case where invalid (global) state is encountered. Constructs an abort code with specified `reason` and category `INVALID_STATE`. Will abort if `reason` does not fit in 56 bits. + +在遇到无效(全局)状态的情况下应使用。构造一个具有指定的`reason`和类别`INVALID_STATE`的终止代码。如果`reason`不适合56位,将会终止操作。 + +```move + public fun invalid_state(reason: u64): u64; +``` + +--------------------------------------------------------------------------- +Should be used if an account's address does not match a specific address. Constructs an abort code with specified `reason` and category `REQUIRES_ADDRESS`. Will abort if `reason` does not fit in 56 bits. + +当账户地址与特定地址不匹配时应使用。构造一个具有指定的`reason`和类别`REQUIRES_ADDRESS`的终止代码。如果`reason`不适合56位,将会终止操作。 + +```move + public fun requires_address(reason: u64): u64; +``` + +--------------------------------------------------------------------------- +Should be used if a role did not match a required role when using RBAC. Constructs an abort code with specified `reason` and category `REQUIRES_ROLE`. Will abort if `reason` does not fit in 56 bits. + +在使用RBAC时,角色与所需角色不匹配时应使用。构造一个具有指定的`reason`和类别`REQUIRES_ROLE`的终止代码。如果`reason`不适合56位,将会终止操作。 + +```move + public fun requires_role(reason: u64): u64; +``` + +--------------------------------------------------------------------------- +Should be used if an account did not have a required capability when using RBAC. Constructs an abort code with specified `reason` and category `REQUIRES_CAPABILITY`. Should be Will abort if `reason` does not fit in 56 bits. + +在使用RBAC时,帐户没有必要的能力时应使用。构造一个具有指定的`reason`和类别`REQUIRES_CAPABILITY`的终止代码。如果`reason`不适合56位,将会终止操作。 + +```move + public fun requires_capability(reason: u64): u64; +``` + +--------------------------------------------------------------------------- +Should be used if a resource did not exist where one was expected. Constructs an abort code with specified `reason` and category `NOT_PUBLISHED`. Will abort if `reason` does not fit in 56 bits. + +在需要资源的地方不存在资源时应使用。构造一个具有指定的`reason`和类别`NOT_PUBLISHED`的终止代码。如果`reason`不适合56位,将会终止操作。 + +```move + public fun not_published(reason: u64): u64; +``` + +--------------------------------------------------------------------------- +Should be used if a resource already existed where one was about to be published. Constructs an abort code with specified `reason` and category `ALREADY_PUBLISHED`. Will abort if `reason` does not fit in 56 bits. + +要发布资源的地方已经存在资源时使用。构造一个具有指定的`reason`和类别`ALREADY_PUBLISHED`的终止代码。如果`reason`不适合56位,将会终止操作。 + +```move + public fun already_published(reason: u64): u64; +``` + +--------------------------------------------------------------------------- +Should be used if an invalid argument was passed to a function/operation. Constructs an abort code with specified `reason` and category `INVALID_ARGUMENT`. Will abort if `reason` does not fit in 56 bits. + +当向函数/操作传递无效参数时使用。构造一个具有指定的`reason`和类别`INVALID_ARGUMENT`的终止代码。如果`reason`不适合56位,将会终止操作。 + +```move + public fun invalid_argument(reason: u64): u64; +``` + +--------------------------------------------------------------------------- +Should be used if a limit on a specific value is reached, e.g., subtracting 1 from a value of 0. Constructs an abort code with specified `reason` and category `LIMIT_EXCEEDED`. Will abort if `reason` does not fit in 56 bits. + +当达到特定值的限制时应使用,例如,0减去1。构造一个具有指定的`reason`和类别`LIMIT_EXCEEDED`的终止代码。如果`reason`不适合56位,将会终止操作。 + +```move + public fun limit_exceeded(reason: u64): u64; +``` + +--------------------------------------------------------------------------- +Should be used if an internal error or bug was encountered. Constructs an abort code with specified `reason` and category `INTERNAL`. Will abort if `reason` does not fit in 56 bits. + +在遇到内部错误或错误时使用。构造一个具有指定的`reason`和类别`INTERNAL`的终止代码。如果`reason`不适合56位,将会终止操作。 + +```move + public fun internal(reason: u64): u64; +``` + +--------------------------------------------------------------------------- +Used for extension points, should be not used under most circumstances. Constructs an abort code with specified `reason` and category `CUSTOM`. Will abort if `reason` does not fit in 56 bits. + +用于扩展,大多数情况下不应使用。构造一个具有指定的`reason`和类别`CUSTOM`的终止代码。如果`reason`不适合56位,将会终止操作。 + +```move + public fun custom(reason: u64): u64; +``` + +--------------------------------------------------------------------------- + +## 32位精确定点数字(fixed_point32) + +The `fixed_point32` module defines a fixed-point numeric type with 32 integer bits and 32 fractional bits. Internally, this is represented as a `u64` integer wrapped in a struct to make a unique `fixed_point32` type. Since the numeric representation is a binary one, some decimal values may not be exactly representable, but it provides more than 9 decimal digits of precision both before and after the decimal point (18 digits total). For comparison, double precision floating-point has less than 16 decimal digits of precision, so you should be careful about using floating-point to convert these values to decimal. + +`fixed_point32`模块定义了一个具有32个整数位和32个小数位的定点数值类型。在内部,它被表示为一个`u64`整数,包装在一个结构中,形成一个唯一的`fixed_point32`类型。由于数字表示是二进制的,一些十进制值可能不能完全表示,但它在小数点之前和之后都提供了9位以上的十进制精度(总共18位)。为了进行比较,双精度浮点数的精度小于16位十进制数字,因此在使用浮点数将这些值转换为十进制时应该小心。 + +### 类型(Types) +Represents a fixed-point numeric number with 32 fractional bits. + +表示具有32个小数位的定点数字。 + +```move + struct FixedPoint32; +``` + +### 函数(Functions) + +Multiply a u64 integer by a fixed-point number, truncating any fractional part of the product. This will abort if the product overflows. + +当u64整数乘以定点数,截断乘积的任何小数部分。如果乘积溢出,该操作将终止。 + +```move + public fun multiply_u64(val: u64, multiplier: FixedPoint32): u64; +``` + +--------------------------------------------------------------------------- +Divide a u64 integer by a fixed-point number, truncating any fractional part of the quotient. This will abort if the divisor is zero or if the quotient overflows. + +当u64整数除以定点数,截断商的任何小数部分。如果除数为零或商溢出,该操作将终止。 + +```move + public fun divide_u64(val: u64, divisor: FixedPoint32): u64; +``` + +--------------------------------------------------------------------------- +Create a fixed-point value from a rational number specified by its numerator and denominator. Calling this function should be preferred for using `fixed_point32::create_from_raw_value` which is also available. This will abort if the denominator is zero. It will also abort if the numerator is nonzero and the ratio is not in the range $2^{-32}\ldots2^{32}-1$. When specifying decimal fractions, be careful about rounding errors: if you round to display $N$ digits after the decimal point, you can use a denominator of $10^N$ to avoid numbers where the very small imprecision in the binary representation could change the rounding, e.g., 0.0125 will round down to 0.012 instead of up to 0.013. + +根据分子和分母指定的有理数创建定点值。如果`fixed_point32::create_from_raw_value`函数可用,应优先使用。如果分母为零,该操作将终止。如果分子非零且比值不在$2^{-32}\ldots2^{32}-1$范围内,该操作将终止。指定小数时,请注意四舍五入错误:如果要对小数点后$N$位进行四舍五入,则可以用$10^N$做分母,这样就能避免精确度丢失问题,例如,0.0125将四舍五入到0.012而不是0.013。 + +```move + public fun create_from_rational(numerator: u64, denominator: u64): FixedPoint32; +``` + +--------------------------------------------------------------------------- +Create a fixedpoint value from a raw `u64` value. + +通过`u64`原始值创建一个定点值。 + +```move + public fun create_from_raw_value(value: u64): FixedPoint32; +``` + +--------------------------------------------------------------------------- +Returns `true` if the decimal value of `num` is equal to zero. + +如果`num`的十进制值等于0,则返回`true`。 + +```move + public fun is_zero(num: FixedPoint32): bool; +``` + +--------------------------------------------------------------------------- +Accessor for the raw `u64` value. Other less common operations, such as adding or subtracting `FixedPoint32` values, can be done using the raw values directly. + +获取`u64`原始值的方法。其他不太常见的操作,例如添加或减去`FixedPoint32`值,可以直接使用原始值来完成。 + +```move + public fun get_raw_value(num: FixedPoint32): u64; +``` + +--------------------------------------------------------------------------- diff --git a/language/documentation/book/translations/move-book-zh/src/structs-and-resources.md b/language/documentation/book/translations/move-book-zh/src/structs-and-resources.md new file mode 100644 index 0000000000..9dcf97c958 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/structs-and-resources.md @@ -0,0 +1,591 @@ +# 结构体和资源 + +A _struct_ is a user-defined data structure containing typed fields. Structs can store any +non-reference type, including other structs. + +***结构体***(struct)是包含类型字段的自定义数据结构。结构体可以存储任何非引用类型,包括其他结构。 + +We often refer to struct values as _resources_ if they cannot be copied and cannot be dropped. In +this case, resource values must have ownership transferred by the end of the function. This property +makes resources particularly well served for defining global storage schemas or for representing +important values (such as a token). + +如果结构值无法复制且无法删除,我们通常将其称为***资源***(resource)。在这种情况下,资源值必须在函数结束时转移所有权。这个属性使资源特别适合定义全局存储模式或表示重要的值(如 token)。 + +By default, structs are linear and ephemeral. By this we mean that they: cannot be copied, cannot be +dropped, and cannot be stored in global storage. This means that all values have to have ownership +transferred (linear) and the values must be dealt with by the end of the program's execution +(ephemeral). We can relax this behavior by giving the struct [abilities](./abilities.md) which allow +values to be copied or dropped and also to be stored in global storage or to define global storage +schemas. + +默认情况下,结构体是线性的和临时的。我们的意思是它们:不能被复制,不能被删除,不能被存储在全局存储中。这意味着所有值都必须转移所有权(线性),并且必须在程序执行结束时处理这些值(临时)。我们可以通过赋予结构体允许复制或删除值以及将值存储在全局存储中或定义全局存储模式的[能力](./abilities.md)来放松这种行为(减轻限制)。 + +## 定义结构体 + +Structs must be defined inside a module: + +结构体必须在模块内定义: + +```move +address 0x2 { +module m { + struct Foo { x: u64, y: bool } + struct Bar {} + struct Baz { foo: Foo, } + // ^ 注意:尾随逗号是可以的 +} +} +``` + +Structs cannot be recursive, so the following definition is invalid: + +结构体不能递归(定义),所以下面的定义是无效的: + +```move +struct Foo { x: Foo } +// ^ 错误! Foo 不能包含 Foo +``` + +As mentioned above: by default, a struct declaration is linear and ephemeral. So to allow the value +to be used with certain operations (that copy it, drop it, store it in global storage, or use it as +a storage schema), structs can be granted [abilities](./abilities.md) by annotating them with +`has `: + +如上所述:默认情况下,结构体声明是线性且临时的。因此,为了允许将值用于某些操作(复制、删除、将其存储在全局存储中或将其用作存储模式),可以通过使用 `has ` 标注它们来授予结构体[能力](./abilities.md): + +```move +address 0x2 { +module m { + struct Foo has copy, drop { x: u64, y: bool } +} +} +``` + +For more details, see the [annotating structs](./abilities.md#annotating-structs) section. + +有关更多详细信息,请参阅[标注结构体](./abilities.md#标注结构体)部分。 + +### 命名 + +Structs must start with a capital letter `A` to `Z`. After the first letter, constant names can +contain underscores `_`, letters `a` to `z`, letters `A` to `Z`, or digits `0` to `9`. + +结构体必须以大写字母 `A` 到 `Z` 开头。在第一个字母之后,结构体名称可以包含下划线 `_`、字母 `a` 到 `z`、字母 `A` 到 `Z` 或数字 `0` 到 `9`。 + +```move +struct Foo {} +struct BAR {} +struct B_a_z_4_2 {} +``` + +This naming restriction of starting with `A` to `Z` is in place to give room for future language +features. It may or may not be removed later. + +这种以 `A` 到 `Z` 开头的命名限制是为了给未来的语言特性留出空间。以后可能会也可能不会删除这个限制。 + +## 使用结构体 + +### 创建结构体 + +Values of a struct type can be created (or "packed") by indicating the struct name, followed by +value for each field: + +可以通过写明结构体名称来创建(或“打包”)结构体类型的值,然后是每个字段的值: + +```move +address 0x2 { +module m { + struct Foo has drop { x: u64, y: bool } + struct Baz has drop { foo: Foo } + + fun example() { + let foo = Foo { x: 0, y: false }; + let baz = Baz { foo: foo }; + } +} +} +``` + +If you initialize a struct field with a local variable whose name is the same as the field, you can +use the following shorthand: + +如果使用与字段名相同的局部变量初始化结构体字段,则可以使用以下简写: + +```move +let baz = Baz { foo: foo }; +// 相当于 +let baz = Baz { foo }; +``` + +This is called sometimes called "field name punning". + +这有时称为“字段名双关语”。 + +### 通过模式匹配销毁结构体 + +Struct values can be destroyed by binding or assigning them patterns. + +结构值可以通过绑定或赋值模式来销毁。 + +```move +address 0x2 { +module m { + struct Foo { x: u64, y: bool } + struct Bar { foo: Foo } + struct Baz {} + + fun example_destroy_foo() { + let foo = Foo { x: 3, y: false }; + let Foo { x, y: foo_y } = foo; + // ^ `x: x` 的简写 + + // 两个新绑定 + // x: u64 = 3 + // foo_y: bool = false + } + + fun example_destroy_foo_wildcard() { + let foo = Foo { x: 3, y: false }; + let Foo { x, y: _ } = foo; + + // 由于 y 绑定到通配符,因此只有一个新绑定 + // x: u64 = 3 + } + + fun example_destroy_foo_assignment() { + let x: u64; + let y: bool; + Foo { x, y } = Foo { x: 3, y: false }; + + // 改变现有变量 x 和 y + // x = 3, y = false + } + + fun example_foo_ref() { + let foo = Foo { x: 3, y: false }; + let Foo { x, y } = &foo; + + // 两个新绑定 + // x: &u64 + // y: &bool + } + + fun example_foo_ref_mut() { + let foo = Foo { x: 3, y: false }; + let Foo { x, y } = &mut foo; + + // 两个新绑定 + // x: &mut u64 + // y: &mut bool + } + + fun example_destroy_bar() { + let bar = Bar { foo: Foo { x: 3, y: false } }; + let Bar { foo: Foo { x, y } } = bar; + // ^ 嵌套模式 + + // 两个新绑定 + // x: u64 = 3 + // y: bool = false + } + + fun example_destroy_baz() { + let baz = Baz {}; + let Baz {} = baz; + } +} +} +``` + +### 借用结构体和字段 + +The `&` and `&mut` operator can be used to create references to structs or fields. These examples +include some optional type annotations (e.g., `: &Foo`) to demonstrate the type of operations. + +`&` 和 `&mut` 运算符可用于创建对结构体或字段的引用。这些例子包括一些可选的类型标注(例如,`: &Foo`)来演示操作的类型。 + +```move +let foo = Foo { x: 3, y: true }; +let foo_ref: &Foo = &foo; +let y: bool = foo_ref.y; // 通过对结构体的引用读取字段 +let x_ref: &u64 = &foo.x; + +let x_ref_mut: &mut u64 = &mut foo.x; +*x_ref_mut = 42; // 通过可变引用修改字段 +``` + +It is possible to borrow inner fields of nested structs. + +可以借用嵌套结构体的内部字段: + +```move +let foo = Foo { x: 3, y: true }; +let bar = Bar { foo }; + +let x_ref = &bar.foo.x; +``` + +You can also borrow a field via a reference to a struct. + +你还可以通过对结构体的引用来借用字段: + +```move +let foo = Foo { x: 3, y: true }; +let foo_ref = &foo; +let x_ref = &foo_ref.x; +// 这与 let x_ref = &foo.x 的效果相同 +``` + +### 读写字段 + +If you need to read and copy a field's value, you can then dereference the borrowed field + +如果你需要读取和复制字段的值,则可以解引用借用的字段: + +```move +let foo = Foo { x: 3, y: true }; +let bar = Bar { foo: copy foo }; +let x: u64 = *&foo.x; +let y: bool = *&foo.y; +let foo2: Foo = *&bar.foo; +``` + +If the field is implicitly copyable, the dot operator can be used to read fields of a struct without +any borrowing. (Only scalar values with the `copy` ability are implicitly copyable.) + +如果该字段是隐式可复制的,则点运算符可用于读取结构体的字段而无需任何借用。(只有具有 `copy` 能力的标量值是隐式可复制的。) + +```move +let foo = Foo { x: 3, y: true }; +let x = foo.x; // x == 3 +let y = foo.y; // y == true +``` + +Dot operators can be chained to access nested fields. + +点运算符可以链式访问嵌套字段: + +```move +let baz = Baz { foo: Foo { x: 3, y: true } }; +let x = baz.foo.x; // x = 3; +``` + +However, this is not permitted for fields that contain non-primitive types, such a vector or another +struct + +但是,对于包含非原始类型(例如向量或其他结构体)的字段,这是不允许的: + +```move +let foo = Foo { x: 3, y: true }; +let bar = Bar { foo }; +let foo2: Foo = *&bar.foo; +let foo3: Foo = bar.foo; // 错误!必须使用 *& 添加显式复制 +``` + +The reason behind this design decision is that copying a vector or another struct might be an +expensive operation. It is important for a programmer to be aware of this copy and make others aware +with the explicit syntax `*&` + +In addition reading from fields, the dot syntax can be used to modify fields, regardless of the +field being a primitive type or some other struct + +这个设计决策背后的原因是复制一个向量或另一个结构体可能是一项昂贵的操作。对于程序员来说,了解这个复制(操作)并使用显式语法 `*&` 让其他人意识到是很重要的。 + +除了从字段中读取之外,点语法还可用于修改字段,无论该字段是原始类型还是其他结构体。 + +```move +let foo = Foo { x: 3, y: true }; +foo.x = 42; // foo = Foo { x: 42, y: true } +foo.y = !foo.y; // foo = Foo { x: 42, y: false } +let bar = Bar { foo }; // bar = Bar { foo: Foo { x: 42, y: false } } +bar.foo.x = 52; // bar = Bar { foo: Foo { x: 52, y: false } } +bar.foo = Foo { x: 62, y: true }; // bar = Bar { foo: Foo { x: 62, y: true } } +``` + +The dot syntax also works via a reference to a struct + +点语法也适用于对结构体的引用: + +```move +let foo = Foo { x: 3, y: true }; +let foo_ref = &mut foo; +foo_ref.x = foo_ref.x + 1; +``` + +## 私有结构体操作 + +Most struct operations on a struct type `T` can only be performed inside the module that declares +`T`: + +- Struct types can only be created ("packed"), destroyed ("unpacked") inside the module that defines + the struct. +- The fields of a struct are only accessible inside the module that defines the struct. + +Following these rules, if you want to modify your struct outside the module, you will need to +provide public APIs for them. The end of the chapter contains some examples of this. + +However, struct _types_ are always visible to another module or script: + +大多数对结构体类型 `T` 的结构体操作只能在声明 `T` 的模块内执行: + +- 结构体类型只能在定义结构体的模块内创建(“打包”)、销毁(“解包”)。 +- 结构体的字段只能在定义结构体的模块内部访问。 + +按照这些规则,如果你想在模块之外修改你的结构体,你需要为他们提供公共 API。本章的最后包含了这方面的一些例子。 + +但是,结构体类型始终对其他模块或脚本可见: + +```move +// m.move +address 0x2 { +module m { + struct Foo has drop { x: u64 } + + public fun new_foo(): Foo { + Foo { x: 42 } + } +} +} +``` + +```move +// n.move +address 0x2 { +module n { + use 0x2::m; + + struct Wrapper has drop { + foo: m::Foo + } + + fun f1(foo: m::Foo) { + let x = foo.x; + // ^ 错误!此处无法访问 `foo` 的字段 + } + + fun f2() { + let foo_wrapper = Wrapper { foo: m::new_foo() }; + } +} +} +``` + +Note that structs do not have visibility modifiers (e.g., `public` or `private`). + +请注意,结构体没有可见性修饰符(例如,`public` 或 `private`)。 + +## 所有权 + +As mentioned above in [Defining Structs](#defining-structs), structs are by default linear and +ephemeral. This means they cannot be copied or dropped. This property can be very useful when +modeling real world resources like money, as you do not want money to be duplicated or get lost in +circulation. +正如上面[定义结构体](#定义结构体)中提到的,结构体默认是线性的和临时的。这意味着它们不能被复制或删除。在模拟货币等现实世界资源时,此属性非常有用,因为你不希望货币被复制或在流通中丢失。 + +```move +address 0x2 { +module m { + struct Foo { x: u64 } + + public fun copying_resource() { + let foo = Foo { x: 100 }; + let foo_copy = copy foo; // 错误!“复制”需要“复制”能力 + let foo_ref = &foo; + let another_copy = *foo_ref // 错误!解引用需要“复制”能力 + } + + public fun destroying_resource1() { + let foo = Foo { x: 100 }; + + // 错误!当函数返回时,foo 仍然包含一个值。 + // 这种销毁需要“drop”能力 + } + + public fun destroying_resource2(f: &mut Foo) { + *f = Foo { x: 100 } // 错误!通过写入销毁旧值需要“drop”能力 + } +} +} +``` + +To fix the second example (`fun dropping_resource`), you would need to manually "unpack" the resource: + +要修复第二个示例(`fun destroying_resource1`),你需要手动“解包”资源: + +```move +address 0x2 { +module m { + struct Foo { x: u64 } + + public fun destroying_resource1_fixed() { + let foo = Foo { x: 100 }; + let Foo { x: _ } = foo; + } +} +} +``` + +Recall that you are only able to deconstruct a resource within the module in which it is defined. +This can be leveraged to enforce certain invariants in a system, for example, conservation of money. + +If on the other hand, your struct does not represent something valuable, you can add the abilities +`copy` and `drop` to get a struct value that might feel more familiar from other programming +languages: + +回想一下,你只能在定义资源的模块中解构资源。这可以用来在系统中强制执行某些不变量,例如货币守恒。 + +另一方面,如果你的结构体不代表有价值的东西,你可以添加 `copy` 和 `drop` 能力来获取一个结构值,这感觉可能会与其他编程语言更相似。 + +```move +address 0x2 { +module m { + struct Foo has copy, drop { x: u64 } + + public fun run() { + let foo = Foo { x: 100 }; + let foo_copy = copy foo; + // ^ 此代码复制 foo,而 `let x = foo` 或 + // `let x = move foo` 都移动 foo + + let x = foo.x; // x = 100 + let x_copy = foo_copy.x; // x = 100 + + // 函数返回时 foo 和 foo_copy 都被隐式丢弃 + } +} +} +``` + +## 在全局存储中存储资源 + +Only structs with the `key` ability can be saved directly in +[persistent global storage](./global-storage-operators.md). All values stored within those `key` +structs must have the `store` abilities. See the [ability](./abilities] and +[global storage](./global-storage-operators.md) chapters for more detail. + +只有具有 `key` 能力的结构体才能直接保存在[持久性全局存储](./global-storage-operators.md)中。存储在这些 `key` 结构体中的所有值都必须具有 `store` 能力。有关更多详细信息,请参阅[能力](./abilities.md)和[全局存储](./global-storage-operators.md)章节。 + +## 示例 + +Here are two short examples of how you might use structs to represent valuable data (in the case of +`Coin`) or more classical data (in the case of `Point` and `Circle`) + +这里有两个简短的示例,说明如何使用结构体来表示有价值的数据(在 `Coin` 的情况下)或更经典的数据(在 `Point` 和 `Circle` 的情况下)。 + +### 示例 1:Coin + + + +```move +address 0x2 { +module m { + // 我们不希望钱币(Coin)被复制,因为那会复制这个“钱”, + // 所以我们不会给结构体“copy”能力。 + // 同样,我们不希望程序员销毁钱币,所以我们不会给结构体“drop”能力。 + // 但是,我们*希望*模块的用户能够将这个钱币存储在持久的全局存储中, + // 所以我们授予结构体“store”能力。 + // 这个结构体只会在全局存储内的其他资源中,因此我们不会赋予该结构体“key”能力。 + struct Coin has store { + value: u64, + } + + public fun mint(value: u64): Coin { + // 你可能希望通过某种形式的访问控制来关闭此(铸币)功能,以防止使用此模块的任何人铸造无限数量的钱币。 + Coin { value } + } + + public fun withdraw(coin: &mut Coin, amount: u64): Coin { + assert!(coin.balance >= amount, 1000); + coin.value = coin.value - amount; + Coin { value: amount } + } + + public fun deposit(coin: &mut Coin, other: Coin) { + let Coin { value } = other; + coin.value = coin.value + value; + } + + public fun split(coin: Coin, amount: u64): (Coin, Coin) { + let other = withdraw(&mut coin, amount); + (coin, other) + } + + public fun merge(coin1: Coin, coin2: Coin): Coin { + deposit(&mut coin1, coin2); + coin1 + } + + public fun destroy_zero(coin: Coin) { + let Coin { value } = coin; + assert!(value == 0, 1001); + } +} +} +``` + +### 示例 2:Geometry + +```move +address 0x2 { +module point { + struct Point has copy, drop, store { + x: u64, + y: u64, + } + + public fun new(x: u64, y: u64): Point { + Point { + x, y + } + } + + public fun x(p: &Point): u64 { + p.x + } + + public fun y(p: &Point): u64 { + p.y + } + + fun abs_sub(a: u64, b: u64): u64 { + if (a < b) { + b - a + } + else { + a - b + } + } + + public fun dist_squared(p1: &Point, p2: &Point): u64 { + let dx = abs_sub(p1.x, p2.x); + let dy = abs_sub(p1.y, p2.y); + dx*dx + dy*dy + } +} +} +``` + +```move +address 0x2 { +module circle { + use 0x2::point::{Self, Point}; + + struct Circle has copy, drop, store { + center: Point, + radius: u64, + } + + public fun new(center: Point, radius: u64): Circle { + Circle { center, radius } + } + + public fun overlaps(c1: &Circle, c2: &Circle): bool { + let d = point::dist_squared(&c1.center, &c2.center); + let r1 = c1.radius; + let r2 = c2.radius; + d*d <= r1*r1 + 2*r1*r2 + r2*r2 + } +} +} +``` diff --git a/language/documentation/book/translations/move-book-zh/src/tuples.md b/language/documentation/book/translations/move-book-zh/src/tuples.md new file mode 100644 index 0000000000..b3182e8c2a --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/tuples.md @@ -0,0 +1,117 @@ +# 元组和单值 + +Move 不完全支持元组,因为人们可能期望像来自另一种语言的元组一样将它们作为[头等值(即头等公民)](https://zh.wikipedia.org/wiki/%E9%A0%AD%E7%AD%89%E7%89%A9%E4%BB%B6)。但是,为了支持多个返回值,Move 具有类似元组的表达式。这些表达式在运行时不会产生具体的值(字节码中没有元组),因此它们非常有限:它们只能出现在表达式中(通常在函数的返回位置);它们不能绑定到局部变量;它们不能存储在结构中;元组类型不能用于实例化泛型。 + +类似地,[单值(unit)`()`](https://zh.wikipedia.org/wiki/%E5%8D%95%E5%80%BC%E7%B1%BB%E5%9E%8B) 是 Move 源语言创建的一种以表达式为基础的类型。单值 `()` 不会产生任何运行时值。我们可以认为单值 `()` 是一个空元组,适用于元组的任何限制也适用于单值。 + +考虑到这些限制,在语言中使用元组可能会感觉很奇怪。但其他语言中,元组最常见的用例之一是函数 —— 允许函数返回多个值。一些语言通过强制用户编写包含多个返回值的结构来解决这个问题。但是在 Move 中,您不能将引用放在[结构体](./structs-and-resources.md)中。这需要 Move 支持多个返回值。这些多个返回值都在字节码级别被压入到堆栈中。在源码级别,这些多个返回值使用元组表示。 + +## 字面量 + +元组(tuple)是由括号内以逗号分隔的表达式列表创建的。 + +| 语法 | 类型 | 描述 | +|-----------------|-----------------------------------------------------------------------------|-----------------------------------------| +| `()` | `(): ()` | 单值、空元组或 0 元素元组 | +| `(e1, ..., en)` | `(e1, ..., en): (T1, ..., Tn)` 其中 `e_i: Ti` 满足 `0 < i <= n` and `n > 0` | n 元组、n 元素元组、带有 n 个元素的元组 | + +注意 `(e)` 没有类型 `(e): (t)`,换句话说,没有一个元素的元组。如果括号内只有一个元素,则括号仅用于消除歧义,不带有任何其他特殊含义。 + +有时,具有两个元素的元组称为“二元组(pairs)”,而具有三个元素的元组称为“三元组(triples)”。 + +### 例子 + +```move +address 0x42 { +module example { + // 这三个函数都是等价的 + + // 当没有提供返回类型时,假定为 `()` + fun returns_unit_1() { } + + // 空表达式块中存在隐式 () 值 + fun returns_unit_2(): () { } + + // `returns_unit_1` 和 `returns_unit_2` 的显式版本 + fun returns_unit_3(): () { () } + + + fun returns_3_values(): (u64, bool, address) { + (0, false, @0x42) + } + fun returns_4_values(x: &u64): (&u64, u8, u128, vector) { + (x, 0, 1, b"foobar") + } +} +} +``` + +## 操作 + +目前唯一可以对元组执行的操作是解构(destructuring)。 + +### 解构 + +对于任何大小的元组,它们可以在 `let` 绑定或赋值中被解构。 + +例如: + +```move +address 0x42 { +module example { + // 这三个函数都是等价的 + fun returns_unit() {} + fun returns_2_values(): (bool, bool) { (true, false) } + fun returns_4_values(x: &u64): (&u64, u8, u128, vector) { (x, 0, 1, b"foobar") } + + fun examples(cond: bool) { + let () = (); + let (x, y): (u8, u64) = (0, 1); + let (a, b, c, d) = (@0x0, 0, false, b""); + + () = (); + (x, y) = if (cond) (1, 2) else (3, 4); + (a, b, c, d) = (@0x1, 1, true, b"1"); + } + + fun examples_with_function_calls() { + let () = returns_unit(); + let (x, y): (bool, bool) = returns_2_values(); + let (a, b, c, d) = returns_4_values(&0); + + () = returns_unit(); + (x, y) = returns_2_values(); + (a, b, c, d) = returns_4_values(&1); + } +} +} +``` + +有关更多详细信息,请参阅 [Move 变量](./variables.md)。 + +## 子类型 + +除了引用,元组是唯一在 Move 中具有[子类型(subtyping)](https://zh.wikipedia.org/wiki/%E5%AD%90%E7%B1%BB%E5%9E%8B)的类型。元组只有在具有引用的子类型(以协变方式)的意义上才具有子类型。 + +例如: + +```move +let x: &u64 = &0; +let y: &mut u64 = &mut 1; + +// (&u64, &mut u64) 是 (&u64, &u64) 的子类型 +// 因为 &mut u64 是 &u64 的子类型 +let (a, b): (&u64, &u64) = (x, y); + +// (&mut u64, &mut u64) 是 (&u64, &u64) 的子类型 +// 因为 &mut u64 是 &u64 的子类型 +let (c, d): (&u64, &u64) = (y, y); + +// 错误!(&u64, &mut u64) 不是 (&mut u64, &mut u64) 的子类型 +// 因为 &u64 不是 &mut u64 的子类型 +let (e, f): (&mut u64, &mut u64) = (x, y); +``` + +## 所有权 + +如上所述,元组值在运行时并不真正存在。由于这个原因,目前它们不能存储到局部变量中(但这个功能很可能很快就会出现)。因此,元组目前只能移动,因为复制它们需要先将它们放入局部变量中。 diff --git a/language/documentation/book/translations/move-book-zh/src/unit-testing.md b/language/documentation/book/translations/move-book-zh/src/unit-testing.md new file mode 100644 index 0000000000..24f1fa5fc9 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/unit-testing.md @@ -0,0 +1,367 @@ +# 单元测试 (Unit Tests) + +Unit testing for Move adds three new annotations to the Move source language: + +Move 语言中存在三种单元测试标注: + +* `#[test]` +* `#[test_only]`, and +* `#[expected_failure]`. + +They respectively mark a function as a test, mark a module or module member (`use`, function, or struct) as code to be included for testing only, and mark that a test is expected to fail. These annotations can be placed on a function with any visibility. Whenever a module or module member is annotated as `#[test_only]` or `#[test]`, it will not be included in the compiled bytecode unless it is compiled for testing. + +它们分别把函数、模块或模块成员(`use` 声明,函数 function,或结构体 struct)标记为只用于测试的代码,同时也标记期望失败的测试。这些标注可以用在任何可见性(visibility)函数上。无论何种情况,被标注为 `#[test_only]` 或 `#[test]` 的模块或模块成员除非用于测试,其它情况都不会被编译成字节码。 + +## 测试注解:含义和使用方法(Testing Annotations: Their Meaning and Usage) + +Both the `#[test]` and `#[expected_failure]` annotations can be used either with or without arguments. + +`#[test]` 和 `#[expected_failure]` 两个注解均可以在有、无参数情况下使用。 + +Without arguments, the `#[test]` annotation can only be placed on a function with no parameters. This annotation simply marks this function as a test to be run by the unit testing harness. + +没有参数的 `#[test]` 标记只能用于没有参数的函数。表示该函数作为单元测试函数被运行。 + +``` +#[test] // 正确 // OK +fun this_is_a_test() { ... } + +#[test] // 编译失败,因为函数需要参数 // Will fail to compile since the test takes an argument +fun this_is_not_correct(arg: signer) { ... } +``` + +A test can also be annotated as an `#[expected_failure]`. This annotation marks that the test should is expected to raise an error. You can ensure that a test is aborting with a specific abort code by annotating it with `#[expected_failure(abort_code = )]`, if it then fails with a different abort code or with a non-abort error the test will fail. Only functions that have the `#[test]` annotation can also be annotated as an #`[expected_failure]`. + +测试也可以使用 `#[expected_failure]` 标注,表示该函数会抛出错误。你可以使用 `#[expected_failure(abort_code = )]` 这种方式方式确保此测试会被指定错误码打断,如果抛出不同错误码或没有抛出错误测试将失败。只有被 `#[test]` 标注的函数才能使用 `#[expected_failure]` 标注。 + +``` +#[test] +#[expected_failure] +public fun this_test_will_abort_and_pass() { abort 1 } + +#[test] +#[expected_failure] +public fun test_will_error_and_pass() { 1/0; } + +#[test] +#[expected_failure(abort_code = 0)] +public fun test_will_error_and_fail() { 1/0; } + +#[test, expected_failure] // 可以合并多个属性。测试将会通过。 // Can have multiple in one attribute. This test will pass. +public fun this_other_test_will_abort_and_pass() { abort 1 } +``` + +With arguments, a test annotation takes the form `#[test( =
, ..., =
)]`. If a function is annotated in such a manner, the function's parameters must be a permutation of the parameters <`param_name_1>, ..., `, i.e., the order of these parameters as they occur in the function and their order in the test annotation do not have to be the same, but they must be able to be matched up with each other by name. + +测试标注可以采用 `#[test( =
, ..., =
)]` 这种形式指定参数。如果函数使用这样的标注,函数的参数则必须为 `, ..., ` 的形式。参数在函数中的顺序不必与注解中顺序一致,但必须要能根据参数名匹配。 + +Only parameters with a type of `signer` are supported as test parameters. If a non-`signer` parameter is supplied, the test will result in an error when run. + +只有 `signer` 类型可以用作测试参数。使用非 `signer` 类型参数,测试将会失败。 + +``` +#[test(arg = @0xC0FFEE)] // 正确 // OK +fun this_is_correct_now(arg: signer) { ... } + +#[test(wrong_arg_name = @0xC0FFEE)] // 不正确: 参数名不匹配 // Not correct: arg name doesn't match +fun this_is_incorrect(arg: signer) { ... } + +#[test(a = @0xC0FFEE, b = @0xCAFE)] // 正确,多参数情况下必须为每个参数提供值。 // OK. We support multiple signer arguments, but you must always provide a value for that argument +fun this_works(a: signer, b: signer) { ... } + +// 在某处声明一个命名地址(named address) // somewhere a named address is declared +#[test_only] // 命名地址支持 test-only 注解 // test-only named addresses are supported +address TEST_NAMED_ADDR = @0x1; +... +#[test(arg = @TEST_NAMED_ADDR)] // 支持命名地址! // Named addresses are supported! +fun this_is_correct_now(arg: signer) { ... } +``` + +An expected failure annotation can also take the form `#[expected_failure(abort_code = )]`. If a test function is annotated in such a way, the test must abort with an abort code equal to ``. Any other failure or abort code will result in a test failure. + +预期失败的标注使用 `#[expected_failure(abort_code = )]` 这种形式。如果函数被这样标注,测试错误码必须为 ``。任何其它的错误或错误码都会失败。 + +``` +#[test, expected_failure(abort_code = 1)] // 这个测试会失败 // This test will fail +fun this_test_should_abort_and_fail() { abort 0 } + +#[test] +#[expected_failure(abort_code = 0)] // 这个测试会通过 // This test will pass +fun this_test_should_abort_and_pass_too() { abort 0 } +``` + +A module and any of its members can be declared as test only. In such a case the item will only be included in the compiled Move bytecode when compiled in test mode. Additionally, when compiled outside of test mode, any non-test `use`s of a `#[test_only]` module will raise an error during compilation. + +模块和它的成员可以被声明为仅测试用。这种情况它们只会在测试模式下编译。此外,在非测试模式下,任何被 `#[test_only]` 标记的模块都会在编译时报错。 + +``` +#[test_only] // test only 属性可以用于模块 // test only attributes can be attached to modules +module abc { ... } + +#[test_only] // test only 属性可以用于命名地址 // test only attributes can be attached to named addresses +address ADDR = @0x1; + +#[test_only] // .. 用于 use 声明 // .. to uses +use 0x1::some_other_module; + +#[test_only] // .. 用于结构体 // .. to structs +struct SomeStruct { ... } + +#[test_only] // .. 用于函数。只能在测试函数中调用,但自身不是测试 // .. and functions. Can only be called from test code, but not a test +fun test_only_function(...) { ... } +``` + +## 运行单元测试(Running Unit Tests) + +Unit tests for a Move package can be run with the [`move test` +command](./packages.md). + +使用 [`move test` 命令](./packages.md)运行包中的单元测试。 + +When running tests, every test will either `PASS`, `FAIL`, or `TIMEOUT`. If a test case fails, the location of the failure along with the function name that caused the failure will be reported if possible. You can see an example of this below. + +运行测试的结果包括 `PASS`、`FAIL` 或 `TIMEOUT`。如果测试失败,将会尽可能的提供执行失败的位置及函数名信息。请看下面的例子。 + +A test will be marked as timing out if it exceeds the maximum number of instructions that can be executed for any single test. This bound can be changed using the options below, and its default value is set to 5000 instructions. Additionally, while the result of a test is always deterministic, tests are run in parallel by default, so the ordering of test results in a test run is non-deterministic unless running with only one thread (see `OPTIONS` below). + +任何测试执行超过最大数量指令限制将会标记成超时。可以通过参数调整此限制,默认值为 5000 条指令。此外,虽然测试结果是确定的,但由于测试默认并行执行,所以测试结果的顺序是不确定的,除非使用单线程模式(见下述参数)。 + +There are also a number of options that can be passed to the unit testing binary to fine-tune testing and to help debug failing tests. These can be found using the the help flag: + +存在大量参数细粒度调整测试工具的行为,帮助调试失败的测试。可以通过 help 参数查看。 + +``` +$ move -h +``` + +## 示例(Example) + +A simple module using some of the unit testing features is shown in the following example: + +下面例子展示了一个简单的使用了单元测试特性的模块: + +First create an empty package and change directory into it: + +首先创建一个空 package 进入目录: + +``` +$ move new TestExample; cd TestExample +``` + +Next add the following to the `Move.toml`: + +接下来添加下面内容到 `Move.toml` 文件: + +``` +[dependencies] +MoveStdlib = { git = "https://github.com/diem/diem.git", subdir="language/move-stdlib", rev = "56ab033cc403b489e891424a629e76f643d4fb6b", addr_subst = { "std" = "0x1" } } +``` + +Next add the following module under the `sources` directory: + +接下来在 `sources` 目录下添加下述模块: + +``` +// 文件路径: sources/my_module.move // filename: sources/my_module.move +module 0x1::my_module { + + struct MyCoin has key { value: u64 } + + public fun make_sure_non_zero_coin(coin: MyCoin): MyCoin { + assert!(coin.value > 0, 0); + coin + } + + public fun has_coin(addr: address): bool { + exists(addr) + } + + #[test] + fun make_sure_non_zero_coin_passes() { + let coin = MyCoin { value: 1 }; + let MyCoin { value: _ } = make_sure_non_zero_coin(coin); + } + + #[test] + // 如果不关心错误码也可以使用 #[expected_failure] // Or #[expected_failure] if we don't care about the abort code + #[expected_failure(abort_code = 0)] + fun make_sure_zero_coin_fails() { + let coin = MyCoin { value: 0 }; + let MyCoin { value: _ } = make_sure_non_zero_coin(coin); + } + + #[test_only] // 仅用作测试的帮助方法 // test only helper function + fun publish_coin(account: &signer) { + move_to(account, MyCoin { value: 1 }) + } + + #[test(a = @0x1, b = @0x2)] + fun test_has_coin(a: signer, b: signer) { + publish_coin(&a); + publish_coin(&b); + assert!(has_coin(@0x1), 0); + assert!(has_coin(@0x2), 1); + assert!(!has_coin(@0x3), 1); + } +} +``` + +### 运行测试(Running Tests) + +You can then run these tests with the `move test` command: + +你可以使用 `move test` 命令运行测试。 + +``` +$ move test +BUILDING MoveStdlib +BUILDING TestExample +Running Move unit tests +[ PASS ] 0x1::my_module::make_sure_non_zero_coin_passes +[ PASS ] 0x1::my_module::make_sure_zero_coin_fails +[ PASS ] 0x1::my_module::test_has_coin +Test result: OK. Total tests: 3; passed: 3; failed: 0 +``` + +### 使用测试参数(Using Test Flags) + +#### `-f ` 或 `--filter `(`-f ` or `--filter `) + +This will only run tests whose fully qualified name contains ``. For example if we wanted to only run tests with `"zero_coin"` in their name: + +仅运行名字包含 `` 字符的测试。例如只想运行名字包含 `"zero_coin"` 的测试: + + +``` +$ move test -f zero_coin +CACHED MoveStdlib +BUILDING TestExample +Running Move unit tests +[ PASS ] 0x1::my_module::make_sure_non_zero_coin_passes +[ PASS ] 0x1::my_module::make_sure_zero_coin_fails +Test result: OK. Total tests: 2; passed: 2; failed: 0 +``` + +#### `-i ` 或 `--gas_used `(`-i ` or `--gas_used `) + +This bounds the amount of gas that can be consumed for any one test to ``: + +调整测试指令限制为 ``: + +``` +$ move test -i 0 +CACHED MoveStdlib +BUILDING TestExample +Running Move unit tests +[ TIMEOUT ] 0x1::my_module::make_sure_non_zero_coin_passes +[ TIMEOUT ] 0x1::my_module::make_sure_zero_coin_fails +[ TIMEOUT ] 0x1::my_module::test_has_coin + +Test failures: + +Failures in 0x1::my_module: + +┌── make_sure_non_zero_coin_passes ────── +│ Test timed out +└────────────────── + + +┌── make_sure_zero_coin_fails ────── +│ Test timed out +└────────────────── + + +┌── test_has_coin ────── +│ Test timed out +└────────────────── + +Test result: FAILED. Total tests: 3; passed: 0; failed: 3 +``` + +#### `-s` 或 `--statistics`(`-s` or `--statistics`) + +With these flags you can gather statistics about the tests run and report the runtime and gas used for each test. For example, if we wanted to see the statistics for the tests in the example above: + +使用此参数你可以得到每个测试的运行报告及执行指令的统计信息。例如查看上述示例的统计数据: + +``` +$ move test -s +CACHED MoveStdlib +BUILDING TestExample +Running Move unit tests +[ PASS ] 0x1::my_module::make_sure_non_zero_coin_passes +[ PASS ] 0x1::my_module::make_sure_zero_coin_fails +[ PASS ] 0x1::my_module::test_has_coin + +Test Statistics: + +┌────────────────────────────────────────────────┬────────────┬───────────────────────────┐ +│ Test Name │ Time │ Gas Used │ +├────────────────────────────────────────────────┼────────────┼───────────────────────────┤ +│ 0x1::my_module::make_sure_non_zero_coin_passes │ 0.009 │ 1 │ +├────────────────────────────────────────────────┼────────────┼───────────────────────────┤ +│ 0x1::my_module::make_sure_zero_coin_fails │ 0.008 │ 1 │ +├────────────────────────────────────────────────┼────────────┼───────────────────────────┤ +│ 0x1::my_module::test_has_coin │ 0.008 │ 1 │ +└────────────────────────────────────────────────┴────────────┴───────────────────────────┘ + +Test result: OK. Total tests: 3; passed: 3; failed: 0 +``` + +#### `-g` 或 `--state-on-error`(`-g` or `--state-on-error`) + +These flags will print the global state for any test failures. e.g., if we added the following (failing) test to the `my_module` example: + +这个参数会在测试失败情况下打印全局状态。如在 `my_module` 模块中添加下述失败测试: + +``` +module 0x1::my_module { + ... + #[test(a = @0x1)] + fun test_has_coin_bad(a: signer) { + publish_coin(&a); + assert!(has_coin(@0x1), 0); + assert!(has_coin(@0x2), 1); + } +} +``` + +we would get get the following output when running the tests: + +当运行测试时我们将得到下面的输出: + +``` +$ move test -g +CACHED MoveStdlib +BUILDING TestExample +Running Move unit tests +[ PASS ] 0x1::my_module::make_sure_non_zero_coin_passes +[ PASS ] 0x1::my_module::make_sure_zero_coin_fails +[ PASS ] 0x1::my_module::test_has_coin +[ FAIL ] 0x1::my_module::test_has_coin_bad + +Test failures: + +Failures in 0x1::my_module: + +┌── test_has_coin_bad ────── +│ error[E11001]: test failure +│ ┌─ /home/tzakian/TestExample/sources/my_module.move:47:10 +│ │ +│ 44 │ fun test_has_coin_bad(a: signer) { +│ │ ----------------- In this function in 0x1::my_module +│ · +│ 47 │ assert!(has_coin(@0x2), 1); +│ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^ Test was not expected to abort but it aborted with 1 here +│ +│ +│ ────── Storage state at point of failure ────── +│ 0x1: +│ => key 0x1::my_module::MyCoin { +│ value: 1 +│ } +│ +└────────────────── + +Test result: FAILED. Total tests: 4; passed: 3; failed: 1 +``` diff --git a/language/documentation/book/translations/move-book-zh/src/uses.md b/language/documentation/book/translations/move-book-zh/src/uses.md new file mode 100644 index 0000000000..79918badf6 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/uses.md @@ -0,0 +1,376 @@ +# 使用与别名(Uses and Aliases) + +The `use` syntax can be used to create aliases to members in other modules. `use` can be used to +create aliases that last either for the entire module, or for a given expression block scope. + +`use` 语法可用于为其他模块中的成员创建别名。 `use` 可用于创建持续整个模块或给定表达式块范围的别名。 + +## 语法(Syntax) +There are several different syntax cases for `use`. Starting with the most simple, we have the +following for creating aliases to other modules + +这里有几种不同的语法案例可供使用。从最简单的开始,我们有以下例子用于为其他模块创建别名 + +```move +use
::; +use
:: as ; +``` +For example +举例 +```move +use std::vector; +use std::vector as V; +``` + +`use std::vector;` introduces an alias `vector` for `std::vector`. This means that anywhere you +would want to use the module name `std::vector` (assuming this `use` is in scope), you could use +`vector` instead. `use std::vector;` is equivalent to `use std::vector as vector;` + +`use std::vector;`为 `std::vector` 引入别名向量。这意味着在任何您想使用模块名称 `std::vector` 的地方(假设此`use`在作用域内),您都可以使用 `vector` 代替使用`std::vector`; + +Similarly `use std::vector as V;` would let you use `V` instead of `std::vector` + +同样使用 `std::vector as V`;会让你使用 `V` 代替 `std::vector` + +```move +use std::vector; +use std::vector as V; + +fun new_vecs(): (vector, vector, vector) { + let v1 = std::vector::empty(); + let v2 = vector::empty(); + let v3 = V::empty(); + (v1, v2, v3) +} +``` +If you want to import a specific module member (such as a function, struct, or constant). You can +use the following syntax. + +如果要导入特定的模块成员(例如函数、结构或常量)。您可以使用以下语法。 +```move +use
::::; +use
:::: as ; +``` +For example +举例 + +```move +use std::vector::empty; +use std::vector::empty as empty_vec; +``` + +This would let you use the function `std::vector::empty` without full qualification. Instead you +could use `empty` and `empty_vec` respectively. Again, `use std::vector::empty;` is equivalent to +`use std::vector::empty as empty;` + +这将允许您在没有前缀限定的情况下使用函数 `std::vector::empty`。相反,您可以分别使用 `empty` 和 `empty_vec`,使用 `std::vector::empty;`使用`empty` 相当于使用`std::vector::empty`; + +```move +use std::vector::empty; +use std::vector::empty as empty_vec; + +fun new_vecs(): (vector, vector, vector) { + let v1 = std::vector::empty(); + let v2 = empty(); + let v3 = empty_vec(); + (v1, v2, v3) +} +``` +If you want to add aliases for multiple module members at once, you can do so with the following +syntax + +如果要一次为多个模块成员添加别名,可以使用以下语法 +```move +use
::::{, as ... }; +``` +For example +举例 + +```move +use std::vector::{push_back, length as len, pop_back}; + +fun swap_last_two(v: &mut vector) { + assert!(len(v) >= 2, 42); + let last = pop_back(v); + let second_to_last = pop_back(v); + push_back(v, last); + push_back(v, second_to_last) +} +``` + +If you need to add an alias to the Module itself in addition to module members, you can do that in a +single `use` using `Self`. `Self` is a member of sorts that refers to the module. + +如果除了模块成员之外,您还需要为模块本身添加别名,您可以使用 `Self` 在一次`use`中完成。 `Self` 是指模块的各种成员。 +```move +use std::vector::{Self, empty}; +For clarity, all of the following are equivalent: +``` +For clarity, all of the following are equivalent: + +为清晰起见,以下所有内容都是等效的: +```move +use std::vector; +use std::vector as vector; +use std::vector::Self; +use std::vector::Self as vector; +use std::vector::{Self}; +use std::vector::{Self as vector}; +``` +If needed, you can have as many aliases for any item as you like + +如果需要,您可以为任何项目设置任意数量的别名 + +```move +use std::vector::{ + Self, + Self as V, + length, + length as len, +}; + +fun pop_twice(v: &mut vector): (T, T) { + // all options available given the `use` above + assert!(vector::length(v) > 1, 42); + assert!(V::length(v) > 1, 42); + assert!(length(v) > 1, 42); + assert!(len(v) > 1, 42); + + (vector::pop_back(v), vector::pop_back(v)) +} +``` + +## 模块内部(Inside a `module`) +Inside of a `module` all `use` declarations are usable regardless of the order of declaration. + +在模块内部,无论声明顺序如何,所有 `use` 声明都是可用的。 +```move +address 0x42 { +module example { + use std::vector; + + fun example(): vector { + let v = empty(); + vector::push_back(&mut v, 0); + vector::push_back(&mut v, 10); + v + } + + use std::vector::empty; +} +} +``` +The aliases declared by `use` in the module usable within that module. + +在该模块中可用的模块中使用声明的别名。 + +Additionally, the aliases introduced cannot conflict with other module members. See +[Uniqueness](#uniqueness) for more details + +此外,引入的别名不能与其他模块成员冲突。有关详细信息,请参阅[唯一性](#uniqueness)。 + +## 表达式内部(Inside an expression) +You can add `use` declarations to the beginning of any expression block + +您可以将 `use` 声明添加到任何表达式块的开头 +```move +address 0x42 { +module example { + + fun example(): vector { + use std::vector::{empty, push_back}; + + let v = empty(); + push_back(&mut v, 0); + push_back(&mut v, 10); + v + } +} +} +``` +As with `let`, the aliases introduced by `use` in an expression block are removed at the end of that +block. + +与 `let` 一样,在表达式块中使用 `use` 引入的别名在该块的末尾被删除。 + +```move +address 0x42 { +module example { + + fun example(): vector { + let result = { + use std::vector::{empty, push_back}; + let v = empty(); + push_back(&mut v, 0); + push_back(&mut v, 10); + v + }; + result + } + +} +} +``` +Attempting to use the alias after the block ends will result in an error + +在块结束后尝试使用别名将导致错误 +```move +fun example(): vector { + let result = { + use std::vector::{empty, push_back}; + let v = empty(); + push_back(&mut v, 0); + push_back(&mut v, 10); + v + }; + let v2 = empty(); // 错误! +// ^^^^^ 未绑定的函数 'empty' + 结果 +} +``` +Any `use` must be the first item in the block. If the `use` comes after any expression or `let`, it +will result in a parsing error + +任何使用都必须是块中的第一项。如果 use 出现在任何表达式或 let 之后,则会导致解析错误 +```move +{ + let x = 0; + use std::vector; // 错误! + let v = vector::empty(); +} +``` + +## 命名规则(Naming rules) +Aliases must follow the same rules as other module members. This means that aliases to structs or +constants must start with `A` to `Z` + +别名必须遵循与其他模块成员相同的规则。这意味着结构或常量的别名必须以 `A` 到 `Z` 开头 +```move +address 0x42 { +module data { + struct S {} + const FLAG: bool = false; + fun foo() {} +} +module example { + use 0x42::data::{ + S as s, // 错误! + FLAG as fLAG, // 错误! + foo as FOO, // 有效 + foo as bar, // 有效 + }; +} +} +``` +## 唯一性(Uniqueness) +Inside a given scope, all aliases introduced by `use` declarations must be unique. + +在给定范围内,所有由 use 声明引入的别名必须是唯一的。 + +For a module, this means aliases introduced by `use` cannot overlap + +对于一个模块,这意味着使用引入的别名不能重复 +```move +address 0x42 { +module example { + + use std::vector::{empty as foo, length as foo}; // ERROR! + // ^^^ duplicate 'foo' + + use std::vector::empty as bar; + + use std::vector::length as bar; // 错误! + // ^^^ 重复的 'bar' + +} +} +``` +And, they cannot overlap with any of the module's other members + +而且,它们不能与模块的任何其他成员重复 +```move +address 0x42 { +module data { + struct S {} +} +module example { + use 0x42::data::S; + + struct S { value: u64 } // ERROR! + // ^ conflicts with alias 'S' above +} +} +``` +Inside of an expression block, they cannot overlap with each other, but they can +[shadow](#shadowing) other aliases or names from an outer scope + +在表达式块内部,它们不能相互重复,但它们可以遮蔽外部作用域中的其他别名或名称 + +## 遮蔽(Shadowing) +`use` aliases inside of an expression block can shadow names (module members or aliases) from the +outer scope. As with shadowing of locals, the shadowing ends at the end of the expression block; + +在表达式块内使用别名可以覆盖外部作用域的名称(模块成员或别名)。当遮蔽局部变量时,遮蔽会在表达式块的末尾结束; +```move +address 0x42 { +module example { + + struct WrappedVector { vec: vector } + + fun empty(): WrappedVector { + WrappedVector { vec: std::vector::empty() } + } + + fun example1(): (WrappedVector, WrappedVector) { + let vec = { + use std::vector::{empty, push_back}; + // 'empty' 现在指向 std::vector::empty + + let v = empty(); + push_back(&mut v, 0); + push_back(&mut v, 1); + push_back(&mut v, 10); + v + }; + // 'empty' 现在指向 Self::empty + + (empty(), WrappedVector { vec }) + } + + fun example2(): (WrappedVector, WrappedVector) { + use std::vector::{empty, push_back}; + let w: WrappedVector = { + use 0x42::example::empty; + empty() + }; + push_back(&mut w.vec, 0); + push_back(&mut w.vec, 1); + push_back(&mut w.vec, 10); + + let vec = empty(); + push_back(&mut vec, 0); + push_back(&mut vec, 1); + push_back(&mut vec, 10); + + (w, WrappedVector { vec }) + } +} +} +``` + +## 未使用的Use或别名(Unused Use or Alias) +An unused `use` will result in an error + +未使用的 `use` 会导致错误 +```move +address 0x42 { +module example { + use std::vector::{empty, push_back}; // ERROR! + // ^^^^^^^^^ 未使用的别名 'push_back' + + fun example(): vector { + empty() + } +} +} +``` diff --git a/language/documentation/book/translations/move-book-zh/src/variables.md b/language/documentation/book/translations/move-book-zh/src/variables.md new file mode 100644 index 0000000000..3625728ef5 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/variables.md @@ -0,0 +1,879 @@ +# 局部变量和作用域(Local Variables and Scopes) + +Local variables in Move are lexically (statically) scoped. New variables are introduced with the +keyword `let`, which will shadow any previous local with the same name. Locals are mutable and can +be updated both directly and via a mutable reference. + +在 Move 语言中,局部变量的解析依赖于词法作用域(lexically scoped)或静态作用域(statically scoped)。使用关键字 `let` 引入新的变量,它将隐藏任何以前的同名局部变量。局部变量是可变的(Rust 中的变量默认不可变,译者注),可以直接更新,也可以通过可变引用更新。 + +## 声明局部变量(Declaring Local Variables) + +### `let` 绑定(`let` bindings) + +Move programs use `let` to bind variable names to values: + +Move 程序使用 `let` 给变量名绑定一个值: + +```move +let x = 1; +let y = x + x: +``` + +`let` can also be used without binding a value to the local. + +`let` 使用时也可以不绑定任何数值给局部变量。 + +```move +let x; +``` + +The local can then be assigned a value later. + +然后可以稍后为局部变量赋一个值。 + +```move +let x; +if (cond) { + x = 1 +} else { + x = 0 +} +``` + +This can be very helpful when trying to extract a value from a loop when a default value cannot be provided. + +当无法提供默认值时,这在尝试从循环中提取值时非常有用。 + +```move +let x; +let cond = true; +let i = 0; +loop { + (x, cond) = foo(i); + if (!cond) break; + i = i + 1; +} +``` + +### 变量必须在使用前赋值(Variables must be assigned before use) + +Move's type system prevents a local variable from being used before it has been assigned. + +Move 的类型系统防止在赋值之前使用局部变量。 + +```move +let x; +x + x // ERROR! +``` + +```move +let x; +if (cond) x = 0; +x + x // ERROR! +``` + +```move +let x; +while (cond) x = 0; +x + x // ERROR! +``` + +### 有效的变量名(Valid variable names) + +Variable names can contain underscores `_`, letters `a` to `z`, letters `A` to `Z`, and digits `0` +to `9`. Variable names must start with either an underscore `_` or a letter `a` through `z`. They +_cannot_ start with uppercase letters. + +变量名可以包含下划线 `_`、小写字母 `a` 到 `z`、大写字母 `A` 到 `Z`、和数字 `0` 到 `9`。变量名必须以下划线 `_` 或者以小写字母`a`到`z`开头。它们*不能*以大写字母开头。 + +```move +// 全部有效 +let x = e; +let _x = e; +let _A = e; +let x0 = e; +let xA = e; +let foobar_123 = e; + +// 全部无效 +let X = e; // ERROR! +let Foo = e; // ERROR! +``` + +### 类型标注(Type annotations) + +The type of a local variable can almost always be inferred by Move's type system. However, Move +allows explicit type annotations that can be useful for readability, clarity, or debuggability. The +syntax for adding a type annotation is: + +局部变量的类型几乎总是可以通过 Move 的类型系统推断出来。但是,Move 允许显式类型标注,这对可读性、清晰性或可调试性很有用。添加类型标注的语法如下: + +```move +let x: T = e; // “T 类型的变量 x 被初始化为表达式 e” +``` + +Some examples of explicit type annotations: + +一些显式类型标注的示例: + +```move +address 0x42 { +module example { + + struct S { f: u64, g: u64 } + + fun annotated() { + let u: u8 = 0; + let b: vector = b"hello"; + let a: address = @0x0; + let (x, y): (&u64, &mut u64) = (&0, &mut 1); + let S { f, g: f2 }: S = S { f: 0, g: 1 }; + } +} +} +``` + +Note that the type annotations must always be to the right of the pattern: + +请注意,类型标注必须始终位于变量模式的右侧: + +```move +let (x: &u64, y: &mut u64) = (&0, &mut 1); // 错误!正确写法是 let (x, y): ... = +``` + +### 何时需要类型标注(When annotations are necessary) + +In some cases, a local type annotation is required if the type system cannot infer the type. This +commonly occurs when the type argument for a generic type cannot be inferred. For example: + +在某些情况下,如果类型系统无法推断类型,则需要局部类型标注。这通常发生在无法推断某个泛型(generic type)的类型参数时,比如: + +```move +let _v1 = vector::empty(); // 错误! +// ^^^^^^^^^^^^^^^ Could not infer this type. Try adding an annotation (无法推断此类型。尝试添加标注) +let v2: vector = vector::empty(); // 没有错误 +``` + +In a rarer case, the type system might not be able to infer a type for divergent code (where all the +following code is unreachable). Both `return` and [`abort`](./abort-and-assert.md) are expressions +and can have any type. A [`loop`](./loops.md) has type `()` if it has a `break`, but if there is no +break out of the `loop`, it could have any type. If these types cannot be inferred, a type +annotation is required. For example, this code: + +在极少数情况下,Move 的类型系统可能无法推断出一段发散式代码(divergent code)的类型(后面所有代码无法访问)。在 Move 语言中,`return` 和 [`abort`](./abort-and-assert.md) 都属于表达式,它们可以返回任何类型。如果一段 [`loop`](./loops.md) 有 `break`,那么它的返回类型是 `()`,但是如果它不包含 `break`,它的返回类型可以是任何类型。如果无法推断出这些类型,那么类型标注是必须的。例如,这段代码: + +```move +let a: u8 = return (); +let b: bool = abort 0; +let c: signer = loop (); + +let x = return (); // ERROR! +// ^ Could not infer this type. Try adding an annotation +let y = abort 0; // ERROR! +// ^ Could not infer this type. Try adding an annotation +let z = loop (); // ERROR! +// ^ Could not infer this type. Try adding an annotation +``` + +Adding type annotations to this code will expose other errors about dead code or unused local +variables, but the example is still helpful for understanding this problem. + +在这段代码中添加类型标注会暴露其他关于死代码或未使用的局部变量的错误,但该示例仍然有助于理解这个问题。 + +### 元组式的多个变量声明(Multiple declarations with tuples) + +`let` can introduce more than one local at a time using tuples. The locals declared inside the +parenthesis are initialized to the corresponding values from the tuple. + +`let` 可以使用元组一次引入多个局部变量。在括号内声明的局部变量会被初始化为元组中的对应值。 + +```move +let () = (); +let (x0, x1) = (0, 1); +let (y0, y1, y2) = (0, 1, 2); +let (z0, z1, z2, z3) = (0, 1, 2, 3); +``` + +The type of the expression must match the arity of the tuple pattern exactly. + +表达式的类型必须与元组模式的数量完全匹配。 + +```move +let (x, y) = (0, 1, 2); // 错误! +let (x, y, z, q) = (0, 1, 2); // 错误! +``` + +You cannot declare more than one local with the same name in a single `let`. + +你不能在单个 `let` 中声明多个具有相同名称的局部变量。 + +```move +let (x, x) = 0; // 错误! +``` + +### 结构体式的多个变量声明(Multiple declarations with structs) + +`let` can also introduce more than one local at a time when destructuring (or matching against) a +struct. In this form, the `let` creates a set of local variables that are initialized to the values +of the fields from a struct. The syntax looks like this: + +`let` 还可以在解构(或匹配)结构体时一次引入多个局部变量。在这种形式中,`let` 创建了一组局部变量,这些变量被初始化为结构体中字段的值。语法如下所示: + +```move +struct T { f1: u64, f2: u64 } +``` + +```move +let T { f1: local1, f2: local2 } = T { f1: 1, f2: 2 }; +// local1: u64 +// local2: u64 +``` + +Here is a more complicated example: + +这是一个更复杂的示例: + +```move +address 0x42 { + module example { + struct X { f: u64 } + struct Y { x1: X, x2: X } + + fun new_x(): X { + X { f: 1 } + } + + fun example() { + let Y { x1: X { f }, x2 } = Y { x1: new_x(), x2: new_x() }; + assert!(f + x2.f == 2, 42); + + let Y { x1: X { f: f1 }, x2: X { f: f2 } } = Y { x1: new_x(), x2: new_x() }; + assert!(f1 + f2 == 2, 42); + } + } +} +``` + +Fields of structs can serve double duty, identifying the field to bind _and_ the name of the +variable. This is sometimes referred to as punning. + +结构体的字段可以起到双重作用:识别要绑定的字段*和*命名变量。这有时被称为双关语。 + +```move +let X { f } = e; +``` + +is equivalent to: + +等价于: + +```move +let X { f: f } = e; +``` + +As shown with tuples, you cannot declare more than one local with the same name in a single `let`. + +如元组所示,您不能在单个 `let` 中声明多个具有相同名称的局部变量。 + +```move +let Y { x1: x, x2: x } = e; // 错误!(两个 x 同名了) +``` + +### 针对引用进行解构(Destructuring against references) + +In the examples above for structs, the bound value in the let was moved, destroying the struct value +and binding its fields. + +在上面的结构体示例中,`let` 中绑定的值被移动了,这销毁了结构体的值并同时绑定了它的字段(到变量)。 + +```move +struct T { f1: u64, f2: u64 } +``` + +```move +let T { f1: local1, f2: local2 } = T { f1: 1, f2: 2 }; +// local1: u64 +// local2: u64 +``` + +In this scenario the struct value `T { f1: 1, f2: 2 }` no longer exists after the `let`. + +If you wish instead to not move and destroy the struct value, you can borrow each of its fields. For +example: + +在这种场景下结构体的值 `T { f1: 1, f2: 2 }` 会在 `let` 后消失。 + +如果您希望不移动和销毁结构体的值,则可以借用其中的每个字段。例如: + +```move +let t = T { f1: 1, f2: 2 }; +let T { f1: local1, f2: local2 } = &t; +// local1: &u64 +// local2: &u64 +``` + +And similarly with mutable references: + +可变引用也类似: + +```move +let t = T { f1: 1, f2: 2 }; +let T { f1: local1, f2: local2 } = &mut t; +// local1: &mut u64 +// local2: &mut u64 +``` + +This behavior can also work with nested structs. + +此行为也适用于嵌套结构体。 + +```move +address 0x42 { + module example { + struct X { f: u64 } + struct Y { x1: X, x2: X } + + fun new_x(): X { + X { f: 1 } + } + + fun example() { + let y = Y { x1: new_x(), x2: new_x() }; + + let Y { x1: X { f }, x2 } = &y; + assert!(*f + x2.f == 2, 42); + + let Y { x1: X { f: f1 }, x2: X { f: f2 } } = &mut y; + *f1 = *f1 + 1; + *f2 = *f2 + 1; + assert!(*f1 + *f2 == 4, 42); + } + } +} +``` + +### 忽略值(Ignoring Values) + +In `let` bindings, it is often helpful to ignore some values. Local variables that start with `_` +will be ignored and not introduce a new variable + +在 `let` 绑定中,忽略某些值通常很有帮助。以 `_` 开头的局部变量将被忽略并且不会引入新变量。 + +```move +fun three(): (u64, u64, u64) { + (0, 1, 2) +} +``` + +```move +let (x1, _, z1) = three(); +let (x2, _y, z2) = three(); +assert!(x1 + z1 == x2 + z2, 42); +``` + +This can be necessary at times as the compiler will error on unused local variables。 + +这有时是必要的,因为编译器会在未使用的局部变量上报错。 + +```move +let (x1, y, z1) = three(); // 错误! +// ^ 未被使用的局部变量 'y' +``` + +### 通用的 `let` 语法(General `let` grammar) + +All of the different structures in `let` can be combined! With that we arrive at this general +grammar for `let` statements: + +`let` 中所有不同的结构体都可以组合!这样,我们就得出了 `let` 语句的通用语法: + +> _let-binding_ → **let** _pattern-or-list_ _type-annotation__opt_ +> _initializer__opt_ > _pattern-or-list_ → _pattern_ | **(** _pattern-list_ **)** > +> _pattern-list_ → _pattern_ **,**_opt_ | _pattern_ **,** _pattern-list_ > +> _type-annotation_ → **:** _type_ _initializer_ → **=** _expression_ + +The general term for the item that introduces the bindings is a _pattern_. The pattern serves to +both destructure data (possibly recursively) and introduce the bindings. The pattern grammar is as +follows: + +引入绑定的项的通用术语是 *模式(pattern)*。该模式用于解构数据(可能是递归的)并引入绑定。模式语法如下: + +> _pattern_ → _local-variable_ | _struct-type_ **{** _field-binding-list_ **}** > +> _field-binding-list_ → _field-binding_ **,**_opt_ | _field-binding_ **,** +> _field-binding-list_ > _field-binding_ → _field_ | _field_ **:** _pattern_ + +A few concrete examples with this grammar applied: + +应用此语法的一些具体示例: + +```move + let (x, y): (u64, u64) = (0, 1); +// ^ local-variable(局部变量) +// ^ pattern(模式) +// ^ local-variable(局部变量) +// ^ pattern(模式) +// ^ pattern-list(模式列表) +// ^^^^ pattern-list(模式列表) +// ^^^^^^ pattern-or-list(模式或列表) +// ^^^^^^^^^^^^ type-annotation(类型标注) +// ^^^^^^^^ initializer(初始化器) +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ let-binding(let 绑定) + + let Foo { f, g: x } = Foo { f: 0, g: 1 }; +// ^^^ struct-type(结构类型) +// ^ field(字段) +// ^ field-binding(字段绑定) +// ^ field(字段) +// ^ local-variable(局部变量) +// ^ pattern(模式) +// ^^^^ field-binding(字段绑定) +// ^^^^^^^ field-binding-list(字段绑定列表) +// ^^^^^^^^^^^^^^^ pattern(模式) +// ^^^^^^^^^^^^^^^ pattern-or-list(模式或列表) +// ^^^^^^^^^^^^^^^^^^^^ initializer(初始化器) +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ let-binding(let 绑定) +``` + +## 变更(Mutations) + +### 赋值(Assignments) + +After the local is introduced (either by `let` or as a function parameter), the local can be +modified via an assignment: + +在引入局部变量后(通过 `let` 或作为函数参数),可以通过赋值来修改局部变量: + +```move +x = e +``` + +Unlike `let` bindings, assignments are expressions. In some languages, assignments return the value +that was assigned, but in Move, the type of any assignment is always `()`. + +与 `let` 绑定不同,赋值是表达式。在某些语言中,赋值会返回被赋予的值,但在 Move 语言中,任何赋值的返回类型始终是 `()`。 + +```move +(x = e: ()) +``` + +Practically, assignments being expressions means that they can be used without adding a new +expression block with braces (`{`...`}`). + +实际上,赋值作为表达式意味着它们可以在不添加带有大括号(`{`...`}`)的新表达式块(expression block)的情况下使用。 + +```move +let x = 0; +if (cond) x = 1 else x = 2; +``` + +The assignment uses the same pattern syntax scheme as `let` bindings: + +赋值使用与 `let` 绑定相同的模式语法方案: + +```move +address 0x42 { +module example { + struct X { f: u64 } + + fun new_x(): X { + X { f: 1 } + } + + // 这个例子会因为存在未使用的变量和赋值而报错。 + fun example() { + let (x, _, z) = (0, 1, 3); + let (x, y, f, g); + + (X { f }, X { f: x }) = (new_x(), new_x()); + assert!(f + x == 2, 42); + + (x, y, z, f, _, g) = (0, 0, 0, 0, 0, 0); + } +} +} +``` + +Note that a local variable can only have one type, so the type of the local cannot change between +assignments. + +注意,一个局部变量只能有一种类型,所以局部变量的类型不能在赋值之间(多次赋值)改变。 + +```move +let x; +x = 0; +x = false; // 错误! +``` + +### 通过引用进行变更(Mutating through a reference) + +In addition to directly modifying a local with assignment, a local can be modified via a mutable +reference `&mut`. + +除了通过赋值直接修改局部变量外,还可以通过可变引用 `&mut` 的方式修改局部变量。 + +```move +let x = 0; +let r = &mut x; +*r = 1; +assert!(x == 1, 42); +``` + +This is particularly useful if either: + +(1) You want to modify different variables depending on some condition. + +这在以下情况下特别有用: + +(1) 你想根据某些条件修改不同的变量。 + +```move +let x = 0; +let y = 1; +let r = if (cond) &mut x else &mut y; +*r = *r + 1; +``` + +(2) You want another function to modify your local value. + +(2) 你想要另一个函数来修改你的局部变量值。 + +```move +let x = 0; +modify_ref(&mut x); +``` + +This sort of modification is how you modify structs and vectors! + +这种修改方法就是你修改结构体和向量的方式! + +```move +let v = vector::empty(); +vector::push_back(&mut v, 100); +assert!(*vector::borrow(&v, 0) == 100, 42); +``` + +For more details, see [Move references](./references.md). + +有关更多详细信息,请参阅 [Move 引用](./references.md)。 + +## 作用域(Scopes) + +Any local declared with `let` is available for any subsequent expression, _within that scope_. +Scopes are declared with expression blocks, `{`...`}`. + +Locals cannot be used outside of the declared scope. + +使用 `let` 声明的任何局部变量都可用于*该作用域内*的任何后续表达式。作用域用表达式块(expression blocks)声明,`{`...`}`。 + +局部变量不能在声明的作用域之外使用。 + +```move +let x = 0; +{ + let y = 1; +}; +x + y // 错误! +// ^ unbound local 'y'(未绑定的局部变量“y”) +``` + +But, locals from an outer scope _can_ be used in a nested scope. + +但是,来自外部作用域的本地变量*可以*在嵌套作用域中使用。 + +```move +{ + let x = 0; + { + let y = x + 1; // 有效的 + } +} +``` + +Locals can be mutated in any scope where they are accessible. That mutation survives with the local, +regardless of the scope that performed the mutation. + +局部变量可以在允许访问的任何作用域内进行变更。无论执行变更的作用域如何,这种变更会跟随局部变量的生命周期。 + +```move +let x = 0; +x = x + 1; +assert!(x == 1, 42); +{ + x = x + 1; + assert!(x == 2, 42); +}; +assert!(x == 2, 42); +``` + +### 表达式块(Expression Blocks) + +An expression block is a series of statements separated by semicolons (`;`). The resulting value of +an expression block is the value of the last expression in the block. + +表达式块是由分号(`;`)分隔的一系列语句。表达式块的结果值是块中最后一个表达式的值。 + +```move +{ let x = 1; let y = 1; x + y } +``` + +In this example, the result of the block is `x + y`. + +A statement can be either a `let` declaration or an expression. Remember that assignments (`x = e`) +are expressions of type `()`. + +在此示例中, 此区块的结果是 `x + y`. + +语句可以是 `let` 声明或表达式。请记住,赋值(`x = e`)是 `()` 类型的表达式。 + +```move +{ let x; let y = 1; x = 1; x + y } +``` + +Function calls are another common expression of type `()`. Function calls that modify data are +commonly used as statements. + +函数调用是 `()` 类型的另一种常见表达方式。修改数据的函数调用通常被用作语句。 + +```move +{ let v = vector::empty(); vector::push_back(&mut v, 1); v } +``` + +This is not just limited to `()` types---any expression can be used as a statement in a sequence! + +这不仅限于 `()` 类型 —— 任何表达式都可以用作序列中的语句! + +```move +{ + let x = 0; + x + 1; // 值会被丢弃 + x + 2; // 值会被丢弃 + b"hello"; // 值会被丢弃 +} +``` + +But! If the expression contains a resource (a value without the `drop` [ability](./abilities.md)), +you will get an error. This is because Move's type system guarantees that any value that is dropped +has the `drop` [ability](./abilities.md). (Ownership must be transferred or the value must be +explicitly destroyed within its declaring module.) + +但是!如果表达式包含资源(没有 `drop` [能力](./abilities.md)的值),你将收到错误消息。这是因为 Move 的类型系统保证任何被删除的值都具有 `drop` [能力](./abilities.md)。(必须转移所有权,或者必须在其声明模块中显式销毁该值。) + +```move +{ + let x = 0; + Coin { value: x }; // 错误! +// ^^^^^^^^^^^^^^^^^ unused value without the `drop` ability(未使用没有 `drop` 能力的值) + x +} +``` + +If a final expression is not present in a block---that is, if there is a trailing semicolon `;`, +there is an implicit unit `()` value. Similarly, if the expression block is empty, there is an +implicit unit `()` value. + +如果块中不存在最终表达式 —— 也就是说,如果有一个尾随分号 `;`,则含有一个隐式的[单值(unit)`()`](https://zh.wikipedia.org/wiki/%E5%8D%95%E5%80%BC%E7%B1%BB%E5%9E%8B)。同样,如果表达式块为空,那么也存在隐式的单值 `()`。 + +```move +// 两者是等价的 +{ x = x + 1; 1 / x; } +{ x = x + 1; 1 / x; () } +``` + +```move +// 两者是等价的 +{ } +{ () } +``` + +An expression block is itself an expression and can be used anyplace an expression is used. (Note: +The body of a function is also an expression block, but the function body cannot be replaced by +another expression.) + +表达式块本身就是一个表达式,可以在任何使用表达式的地方使用。(注意:函数体也是一个表达式块,但函数体不能被另一个表达式替换。) + +```move +let my_vector: vector> = { + let v = vector::empty(); + vector::push_back(&mut v, b"hello"); + vector::push_back(&mut v, b"goodbye"); + v +}; +``` + +(The type annotation is not needed in this example and only added for clarity.) + +(此示例中不需要类型标注,只是为了清楚起见而添加。) + +### 遮蔽(Shadowing) + +If a `let` introduces a local variable with a name already in scope, that previous variable can no +longer be accessed for the rest of this scope. This is called _shadowing_. + +如果一个 `let` 引入了一个名称已经在作用域中的局部变量,则该作用域的剩余部分将无法再访问先前的变量。这称为*遮蔽(shadowing)*。 + +```move +let x = 0; +assert!(x == 0, 42); + +let x = 1; // x 被遮蔽了 +assert!(x == 1, 42); +``` + +When a local is shadowed, it does not need to retain the same type as before. + +当局部变量被遮蔽时,它不需要保留与以前相同的类型。 + +```move +let x = 0; +assert!(x == 0, 42); + +let x = b"hello"; // x 被遮蔽了 +assert!(x == b"hello", 42); +``` + +After a local is shadowed, the value stored in the local still exists, but will no longer be +accessible. This is important to keep in mind with values of types without the +[`drop` ability](./abilities.md), as ownership of the value must be transferred by the end of the +function. + +在局部变量被遮蔽后,存储在局部变量的值仍然存在,但是将不再可访问。对于没有 [`drop` 能力](./abilities.md)的类型的值,请记住这一点很重要,因为值的所有权必须在函数结束时转移。 + +```move +address 0x42 { + module example { + struct Coin has store { value: u64 } + + fun unused_resource(): Coin { + let x = Coin { value: 0 }; // ERROR! +// ^ This local still contains a value without the `drop` ability(这个局部变量仍然包含一个没有 `drop` 能力的值) + x.value = 1; + let x = Coin { value: 10 }; + x +// ^ Invalid return(无效的返回) + } + } +} +``` + +When a local is shadowed inside a scope, the shadowing only remains for that scope. The shadowing is +gone once that scope ends. + +当局部变量在作用域内被遮蔽时,该遮蔽作用仅保留在该作用域内。一旦该作用域结束,遮蔽作用就消失了。 + +```move +let x = 0; +{ + let x = 1; + assert!(x == 1, 42); +}; +assert!(x == 0, 42); +``` + +Remember, locals can change type when they are shadowed. + +请记住,局部变量在被遮蔽时可以更改类型。 + +```move +let x = 0; +{ + let x = b"hello"; + assert!(x = b"hello", 42); +}; +assert!(x == 0, 42); +``` + +## 移动和复制(Move and Copy) + +All local variables in Move can be used in two ways, either by `move` or `copy`. If one or the other +is not specified, the Move compiler is able to infer whether a `copy` or a `move` should be used. +This means that in all of the examples above, a `move` or a `copy` would be inserted by the +compiler. A local variable cannot be used without the use of `move` or `copy`. + +`copy` will likely feel the most familiar coming from other programming languages, as it creates a +new copy of the value inside of the variable to use in that expression. With `copy`, the local +variable can be used more than once. + +Move 中的所有局部变量都可以通过两种方式使用,通过 `move` 或 `copy`。如果未指定其中之一,则 Move 编译器能够推断应该使用 `copy` 还是 `move`。这意味着在上述所有示例中,编译器将插入 `move` 或 `copy`。如果不使用 `move` 或 `copy`,就不能使用局部变量。 + +`copy` 对来自其他编程语言的开发者来说可能会觉得最熟悉,因为它会在变量内部创建一个新的副本值以在该表达式中使用。使用 `copy`,局部变量可以被多次使用。 + +```move +let x = 0; +let y = copy x + 1; +let z = copy x + 2; +``` + +Any value with the `copy` [ability](./abilities.md) can be copied in this way. + +`move` takes the value out of the local variable _without_ copying the data. After a `move` occurs, +the local variable is unavailable. + +任何具有 `copy` [能力](./abilities.md)的值都可以通过这种方式复制。 + +`move` 从局部变量中取出值*而不是*复制数据。`移动(move)`发生后,局部变量将不可用。 + +```move +let x = 1; +let y = move x + 1; +// ------ Local was moved here(局部变量被移动到这里了) +let z = move x + 2; // 错误! +// ^^^^^^ Invalid usage of local 'x'(局部变量“x”的无效使用方式) +y + z +``` + +### 安全性(Safety) + +Move's type system will prevent a value from being used after it is moved. This is the same safety +check described in [`let` declaration](#let-bindings) that prevents local variables from being used +before it is assigned a value. + +Move 的类型系统会阻止一个值在移动后被使用。这与 [`let` 声明](#let-绑定let-bindings)中描述的防止在局部变量被赋值之前使用的安全检查相同。 + + + + + +### 推断(Inference) + +As mentioned above, the Move compiler will infer a `copy` or `move` if one is not indicated. The +algorithm for doing so is quite simple: + +- Any scalar value with the `copy` [ability](./abilities.md) is given a `copy`. +- Any reference (both mutable `&mut` and immutable `&`) is given a `copy`. + - Except under special circumstances where it is made a `move` for predictable borrow checker errors. +- Any other value is given a `move`. + - This means that even though other values might be have the `copy` [ability](./abilities.md), it must be done _explicitly_ by the programmer. + - This is to prevent accidental copies of large data structures. + +如上所述,如果未指明,Move 编译器将推断出 `copy` 还是 `move`。这样做的算法非常简单: + +- 任何带有 `copy` [能力](./abilities.md)的标量值都被赋予了 `copy`。 +- 任何引用(可变的 `&mut` 和不可变的 `&`)都被赋予 `copy`。 + - 除非在可预测的借用检查器错误的特殊情况下,会进行 `move` 操作。 +- 任何其他值都被赋予 `move`。 + - 这意味着即使其他值可能具有 `copy` [能力](./abilities.md),它也必须由程序员*显式*声明。 + - 这是为了防止意外地复制很大的数据结构。 + +例如: + +```move +let s = b"hello"; +let foo = Foo { f: 0 }; +let coin = Coin { value: 0 }; + +let s2 = s; // 移动 +let foo2 = foo; // 移动 +let coin2 = coin; // 移动 + +let x = 0; +let b = false; +let addr = @0x42; +let x_ref = &x; +let coin_ref = &mut coin2; + +let x2 = x; // 复制 +let b2 = b; // 复制 +let addr2 = @0x42; // 复制 +let x_ref2 = x_ref; // 复制 +let coin_ref2 = coin_ref; // 复制 +``` diff --git a/language/documentation/book/translations/move-book-zh/src/vector.md b/language/documentation/book/translations/move-book-zh/src/vector.md new file mode 100644 index 0000000000..286892a280 --- /dev/null +++ b/language/documentation/book/translations/move-book-zh/src/vector.md @@ -0,0 +1,152 @@ +# 向量 + +`vector` 是 Move 提供的唯一原始集合类型。`vector` 是类型为 `T` 的同构集合,可以通过从"末端"推入/弹出(出栈/入栈,译者注)值来增长或缩小。 +*(与 Rust 一样,向量(vector)是一种可以存放任何类型的可变大小的容器,也可称为[动态数组](https://en.wikipedia.org/wiki/Dynamic_array),与 Python 中的[列表(list)](https://computersciencewiki.org/index.php/Lists)不同,译者注)* + +`vector` 可以用任何类型 `T` 实例化。例如,`vector`、`vector
`、`vector<0x42::MyModuel::MyResource>` 和 `vector>` 都是有效的向量类型。 + +## 字面量 + +### 通用 `vector` 字面量 + +任何类型的向量都可以通过 `vector` 字面量创建。 + +| 语法 | 类型 | 描述 | +|-----------------------|-------------------------------------------------------------------------------|-----------------------------------| +| `vector[]` | `vector[]: vector` 其中 `T` 是任何单一的非引用类型 | 一个空向量 | +| `vector[e1, ..., en]` | `vector[e1, ..., en]: vector` where `e_i: T` 满足 `0 < i <= n` and `n > 0` | 带有 `n` 个元素(长度为 n)的向量 | + +在这些情况下,`vector` 的类型是从元素类型或从向量的使用上推断出来的。如果无法推断类型或者只是为了更清楚地表示,则可以显式指定类型: + +```move +vector[]: vector +vector[e1, ..., en]: vector +``` + +#### 向量字面量示例 + +```move +(vector[]: vector); +(vector[0u8, 1u8, 2u8]: vector); +(vector[]: vector); +(vector
[@0x42, @0x100]: vector
); +``` + +### `vector` 字面量 + +Move 中向量的一个常见用例是表示“字节数组”,用 `vector` 表示。这些值通常用于加密目的,例如公钥或哈希结果。这些值非常常见,以至于提供了特定的语法以使值更具可读性,而不是必须使用 `vector[]`,其中每个单独的 `u8` 值都以数字形式指定。 + +目前支持两种类型的 `vector` 字面量,*字节字符串*和*十六进制字符串*。 + +#### 字节字符串 + +字节字符串是带引号的字符串字面量,以 `b` 为前缀,例如,`b"Hello!\n"`。 + +这些是允许转义序列的 ASCII 编码字符串。目前,支持的转义序列如下: + +| 转义序列 | 描述 | +|----------|---------------------------------------------| +| `\n` | 换行 | +| `\r` | 回车 | +| `\t` | 制表符 | +| `\\` | 反斜杠 | +| `\0` | Null | +| `\"` | 引号 | +| `\xHH` | 十六进制进制转义,插入十六进制字节序列 `HH` | + +#### 十六进制字符串 + +十六进制字符串是以 `x` 为前缀的带引号的字符串字面量,例如,`x"48656C6C6F210A"`。 + +每个字节对,范围从 `00` 到 `FF` 都被解析为十六进制编码的 `u8` 值。所以每个字节对对应于结果 `vector` 的单个条目。 + +#### 字符串字面量示例 + +```move +script { + fun byte_and_hex_strings() { + assert!(b"" == x"", 0); + assert!(b"Hello!\n" == x"48656C6C6F210A", 1); + assert!(b"\x48\x65\x6C\x6C\x6F\x21\x0A" == x"48656C6C6F210A", 2); + assert!( + b"\"Hello\tworld!\"\n \r \\Null=\0" == + x"2248656C6C6F09776F726C6421220A200D205C4E756C6C3D00", + 3 + ); + } +} +``` + +## 操作 + +`vector` 通过 Move 标准库里的 `std::vector` 模块支持以下操作: + +| 函数 | 描述 | 中止条件 | +|------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|----------------------| +| `vector::empty(): vector` | 创建一个可以存储 `T` 类型值的空向量 | 永不中止 | +| `vector::singleton(t: T): vector` | 创建一个包含 `t` 的大小为 1 的向量 | 永不中止 | +| `vector::push_back(v: &mut vector, t: T)` | 将 `t` 添加到 `v` 的尾部 | 永不中止 | +| `vector::pop_back(v: &mut vector): T` | 移除并返回 `v` 中的最后一个元素 | 如果 `v` 是空向量 | +| `vector::borrow(v: &vector, i: u64): &T` | 返回在索引 `i` 处对 `T` 的不可变引用 | 如果 `i` 越界 | +| `vector::borrow_mut(v: &mut vector, i: u64): &mut T` | 返回在索引 `i` 处对 `T` 的可变引用 | 如果 `i` 越界 | +| `vector::destroy_empty(v: vector)` | 销毁 `v` 向量 | 如果 `v` 不是空向量 | +| `vector::append(v1: &mut vector, v2: vector)` | 将 `v2` 中的元素添加到 `v1` 的末尾 | 永不中止 | +| `vector::contains(v: &vector, e: &T): bool` | 如果 `e` 在向量 `v` 里返回 true,否则返回 false | 永不中止 | +| `vector::swap(v: &mut vector, i: u64, j: u64)` | 交换向量 `v` 中第 `i` 个和第 `j` 个索引处的元素 | 如果 `i` 或 `j` 越界 | +| `vector::reverse(v: &mut vector)` | 反转向量 `v` 中元素的顺序 | 永不中止 | +| `vector::index_of(v: &vector, e: &T): (bool, u64)` | 如果 `e` 在索引 `i` 处的向量中,则返回 `(true, i)`。否则返回`(false, 0)` | 永不中止 | +| `vector::remove(v: &mut vector, i: u64): T` | 移除向量 `v` 中的第 `i` 个元素,移动所有后续元素。这里的时间复杂度是 O(n),并且保留了向量中元素的顺序 | 如果 `i` 越界 | +| `vector::swap_remove(v: &mut vector, i: u64): T` | 将向量中的第 `i` 个元素与最后一个元素交换,然后弹出该元素。这里的时间复杂度是 O(1),但是不保留向量中的元素顺序 | 如果 `i` 越界 | + +随着时间的推移可能会增加更多操作。 + +## 示例 + +```move +use std::vector; + +let v = vector::empty(); +vector::push_back(&mut v, 5); +vector::push_back(&mut v, 6); + +assert!(*vector::borrow(&v, 0) == 5, 42); +assert!(*vector::borrow(&v, 1) == 6, 42); +assert!(vector::pop_back(&mut v) == 6, 42); +assert!(vector::pop_back(&mut v) == 5, 42); +``` + +## 销毁和复制 `vector` + +`vector` 的某些行为取决于元素类型 `T` 的能力(ability),例如:如果向量中包含不具有 `drop` 能力的元素,那么不能像上面例子中的 `v` 一样隐式丢弃 —— 它们必须用 `vector::destroy_empty` 显式销毁。 + +请注意,除非向量 `vec` 包含零个元素,否则 `vector::destroy_empty` 将在运行时中止: + +```move +fun destroy_any_vector(vec: vector) { + vector::destroy_empty(vec) // 删除此行将导致编译器错误 +} +``` + +但是删除包含带有 `drop` 能力的元素的向量不会发生错误: + +```move +fun destroy_droppable_vector(vec: vector) { + // 有效! + // 不需要明确地做任何事情来销毁向量 +} +``` + +同样,除非元素类型具有 `copy` 能力,否则无法复制向量。换句话说,当且仅当 `T` 具有 `copy` 能力时,`vector` 才具有 `copy` 能力。然而,即使是可复制的向量也永远不会被隐式复制: + +```move +let x = vector::singleton(10); +let y = copy x; // 没有 copy 将导致编译器错误! +``` + +大向量的复制可能很昂贵,因此编译器需要显式 `copy` 以便更容易查看它们发生的位置。 + +有关更多详细信息,请参阅[类型能力](./abilities.md)和[泛型](./generics.md)部分。 + +## 所有权 + +[如上所述](#销毁和复制-vector),`vector` 值只有在元素值可以复制的时候才能复制。在这种情况下,复制必须通过显式 [`copy`](./variables.md#移动和复制) 或者[解引用 `*`](./references.md#通过引用读取和写入)。 diff --git a/language/documentation/examples/diem-framework/build_all.sh b/language/documentation/examples/diem-framework/build_all.sh index 934104ac32..cb5a07535a 100755 --- a/language/documentation/examples/diem-framework/build_all.sh +++ b/language/documentation/examples/diem-framework/build_all.sh @@ -5,6 +5,6 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -cd "${SCRIPT_DIR}/move-packages/DPN" && cargo run -p df-cli -- package build && -cd "${SCRIPT_DIR}/move-packages/core" && cargo run -p df-cli -- package build && -cd "${SCRIPT_DIR}/move-packages/experimental" && cargo run -p df-cli -- package build +cd "${SCRIPT_DIR}/move-packages/DPN" && cargo run -p df-cli -- build && +cd "${SCRIPT_DIR}/move-packages/core" && cargo run -p df-cli -- build && +cd "${SCRIPT_DIR}/move-packages/experimental" && cargo run -p df-cli -- build diff --git a/language/documentation/examples/diem-framework/crates/cli/Cargo.toml b/language/documentation/examples/diem-framework/crates/cli/Cargo.toml index 7976e01e29..f1223aa3d4 100644 --- a/language/documentation/examples/diem-framework/crates/cli/Cargo.toml +++ b/language/documentation/examples/diem-framework/crates/cli/Cargo.toml @@ -5,17 +5,19 @@ description = "CLI frontend for the Move compiler and VM (with Diem Framework)" authors = ["Diem Association "] license = "Apache-2.0" publish = false -edition = "2018" +edition = "2021" [dependencies] anyhow = "1.0.52" -bcs = "0.1.2" clap = { version = "3.1.8", features = ["derive"] } +bcs = "0.1.4" + move-stdlib = { path = "../../../../../move-stdlib" } move-core-types = { path = "../../../../../move-core/types" } move-vm-types = { path = "../../../../../move-vm/types" } move-cli = { path = "../../../../../tools/move-cli" } +move-vm-test-utils = { path = "../../../../../move-vm/test-utils" } diem-framework-natives = { path = "../natives" } diff --git a/language/documentation/examples/diem-framework/crates/cli/src/main.rs b/language/documentation/examples/diem-framework/crates/cli/src/main.rs index 354249d780..ec83cef143 100644 --- a/language/documentation/examples/diem-framework/crates/cli/src/main.rs +++ b/language/documentation/examples/diem-framework/crates/cli/src/main.rs @@ -5,12 +5,10 @@ use anyhow::Result; use clap::Parser; use move_cli::{Command, Move}; -use move_core_types::{ - errmap::ErrorMapping, - gas_schedule::{CostTable, GasCost}, - language_storage::CORE_CODE_ADDRESS, +use move_core_types::{errmap::ErrorMapping, language_storage::CORE_CODE_ADDRESS}; +use move_vm_test_utils::gas_schedule::{ + new_from_instructions, zero_cost_instruction_table, CostTable, }; -use move_vm_types::gas_schedule::{new_from_instructions, zero_cost_instruction_table}; #[derive(Parser)] pub struct DfCli { @@ -28,34 +26,39 @@ pub enum DfCommands { // extra commands available only in df-cli can be added below } -fn cost_table(num_natives: usize) -> CostTable { +fn cost_table() -> CostTable { let instruction_table = zero_cost_instruction_table(); - let native_table = std::iter::repeat_with(|| GasCost::new(0, 0)) - .take(num_natives) - .collect(); - - new_from_instructions(instruction_table, native_table) + new_from_instructions(instruction_table) } fn main() -> Result<()> { // let error_descriptions: ErrorMapping = // bcs::from_bytes(diem_framework_releases::current_error_descriptions())?; - let natives = move_stdlib::natives::all_natives(CORE_CODE_ADDRESS) - .into_iter() - .chain(diem_framework_natives::all_natives(CORE_CODE_ADDRESS)) - .collect::>(); - - let num_natives = natives.len(); + let natives = move_stdlib::natives::all_natives( + CORE_CODE_ADDRESS, + // We may want to switch to a different gas schedule in the future, but for now, + // the all-zero one should be enough. + move_stdlib::natives::GasParameters::zeros(), + ) + .into_iter() + .chain(move_stdlib::natives::nursery_natives( + CORE_CODE_ADDRESS, + // We may want to switch to a different gas schedule in the future, but for now, + // the all-zero one should be enough. + move_stdlib::natives::NurseryGasParameters::zeros(), + )) + .chain(diem_framework_natives::all_natives(CORE_CODE_ADDRESS)) + .collect::>(); let args = DfCli::parse(); - match &args.cmd { + match args.cmd { DfCommands::Command(cmd) => move_cli::run_cli( natives, - &cost_table(num_natives), + &cost_table(), // TODO: implement this &ErrorMapping::default(), - &args.move_args, + args.move_args, cmd, ), } diff --git a/language/documentation/examples/diem-framework/crates/crypto-derive/Cargo.toml b/language/documentation/examples/diem-framework/crates/crypto-derive/Cargo.toml index efae300ae2..cd5d74589c 100644 --- a/language/documentation/examples/diem-framework/crates/crypto-derive/Cargo.toml +++ b/language/documentation/examples/diem-framework/crates/crypto-derive/Cargo.toml @@ -3,7 +3,7 @@ name = "diem-crypto-derive" version = "0.0.3" authors = ["Diem Association "] publish = false -edition = "2018" +edition = "2021" license = "Apache-2.0" [lib] diff --git a/language/documentation/examples/diem-framework/crates/crypto/Cargo.toml b/language/documentation/examples/diem-framework/crates/crypto/Cargo.toml index ceba097221..2e9031677b 100644 --- a/language/documentation/examples/diem-framework/crates/crypto/Cargo.toml +++ b/language/documentation/examples/diem-framework/crates/crypto/Cargo.toml @@ -3,7 +3,7 @@ name = "diem-crypto" version = "0.0.3" authors = ["Diem Association "] publish = false -edition = "2018" +edition = "2021" license = "Apache-2.0" [dependencies] @@ -30,7 +30,8 @@ tiny-keccak = { version = "2.0.2", features = ["sha3"] } x25519-dalek = { version = "0.1.0", package = "x25519-dalek-fiat", default-features = false, features = ["std"] } aes-gcm = "0.8.0" diem-crypto-derive = { path = "../crypto-derive" } -bcs = "0.1.2" + +bcs = "0.1.4" [dev-dependencies] bitvec = "0.19.4" @@ -41,7 +42,8 @@ ripemd160 = "0.9.1" criterion = "0.3.4" sha3 = "0.9.1" serde_json = "1.0.64" -trybuild = "1.0.41" +# TODO: some tests will fail if this is set to 1.0.63 +trybuild = "=1.0.53" [features] default = ["fiat"] diff --git a/language/documentation/examples/diem-framework/crates/crypto/src/ed25519.rs b/language/documentation/examples/diem-framework/crates/crypto/src/ed25519.rs index f3d923a50f..1fd007bfa7 100644 --- a/language/documentation/examples/diem-framework/crates/crypto/src/ed25519.rs +++ b/language/documentation/examples/diem-framework/crates/crypto/src/ed25519.rs @@ -161,7 +161,7 @@ impl Ed25519PublicKey { bits }; let mtg_point = curve25519_dalek::montgomery::MontgomeryPoint(key_bits); - let sign = if negative { 1u8 } else { 0u8 }; + let sign = u8::from(negative); let ed_point = mtg_point .to_edwards(sign) .ok_or(CryptoMaterialError::DeserializationError)?; @@ -341,7 +341,7 @@ impl VerifyingKey for Ed25519PublicKey { impl fmt::Display for Ed25519PublicKey { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", hex::encode(&self.0.as_bytes())) + write!(f, "{}", hex::encode(self.0.as_bytes())) } } diff --git a/language/documentation/examples/diem-framework/crates/crypto/src/test_utils.rs b/language/documentation/examples/diem-framework/crates/crypto/src/test_utils.rs index 25e9386136..8bc36d2c65 100644 --- a/language/documentation/examples/diem-framework/crates/crypto/src/test_utils.rs +++ b/language/documentation/examples/diem-framework/crates/crypto/src/test_utils.rs @@ -140,7 +140,7 @@ impl ::core::clone::Clone for TestDiemCryptoHasher { fn clone(&self) -> TestDiemCryptoHasher { match *self { TestDiemCryptoHasher(ref __self_0_0) => { - TestDiemCryptoHasher(::core::clone::Clone::clone(&(*__self_0_0))) + TestDiemCryptoHasher(::core::clone::Clone::clone(__self_0_0)) } } } diff --git a/language/documentation/examples/diem-framework/crates/crypto/src/unit_tests/ed25519_test.rs b/language/documentation/examples/diem-framework/crates/crypto/src/unit_tests/ed25519_test.rs index 40fbee9acb..05feec195e 100644 --- a/language/documentation/examples/diem-framework/crates/crypto/src/unit_tests/ed25519_test.rs +++ b/language/documentation/examples/diem-framework/crates/crypto/src/unit_tests/ed25519_test.rs @@ -100,9 +100,9 @@ proptest! { // Compute k = H(R∥A∥m) // ////////////////////////// let mut h: Sha512 = Sha512::default(); - h.update(&mixed_r_point.compress().to_bytes()); - h.update(&mixed_pub_point.compress().to_bytes()); - h.update(&message); + h.update(mixed_r_point.compress().to_bytes()); + h.update(mixed_pub_point.compress().to_bytes()); + h.update(message); // curve25519_dalek is stuck on an old digest version, so we can't do // Scalar::from_hash let mut output = [0u8; 64]; @@ -120,7 +120,7 @@ proptest! { let nonce = &expanded_priv_key[32..]; let mut h: Sha512 = Sha512::default(); h.update(nonce); - h.update(&message); + h.update(message); // curve25519_dalek is stuck on an old digest version, so we can't do // Scalar::from_hash let mut output = [0u8; 64]; diff --git a/language/documentation/examples/diem-framework/crates/crypto/src/unit_tests/hkdf_test.rs b/language/documentation/examples/diem-framework/crates/crypto/src/unit_tests/hkdf_test.rs index 80d4085bdf..a211e6c062 100644 --- a/language/documentation/examples/diem-framework/crates/crypto/src/unit_tests/hkdf_test.rs +++ b/language/documentation/examples/diem-framework/crates/crypto/src/unit_tests/hkdf_test.rs @@ -11,9 +11,9 @@ use sha2::{Sha256, Sha512}; fn test_sha256_test_vectors() { let tests = test_vectors_sha256(); for t in tests.iter() { - let ikm = hex::decode(&t.ikm).unwrap(); - let salt = hex::decode(&t.salt).unwrap(); - let info = hex::decode(&t.info).unwrap(); + let ikm = hex::decode(t.ikm).unwrap(); + let salt = hex::decode(t.salt).unwrap(); + let info = hex::decode(t.info).unwrap(); let hkdf_extract = Hkdf::::extract(Option::from(&salt[..]), &ikm[..]).unwrap(); let hkdf_expand = Hkdf::::expand(&hkdf_extract, Some(&info[..]), t.length); @@ -29,9 +29,9 @@ fn test_sha256_test_vectors() { fn test_extract_then_expand() { let tests = test_vectors_sha256(); for t in tests.iter() { - let ikm = hex::decode(&t.ikm).unwrap(); - let salt = hex::decode(&t.salt).unwrap(); - let info = hex::decode(&t.info).unwrap(); + let ikm = hex::decode(t.ikm).unwrap(); + let salt = hex::decode(t.salt).unwrap(); + let info = hex::decode(t.info).unwrap(); let hkdf_full = Hkdf::::extract_then_expand( Option::from(&salt[..]), diff --git a/language/documentation/examples/diem-framework/crates/crypto/src/validatable.rs b/language/documentation/examples/diem-framework/crates/crypto/src/validatable.rs index e062e3ebdc..76d987b70a 100644 --- a/language/documentation/examples/diem-framework/crates/crypto/src/validatable.rs +++ b/language/documentation/examples/diem-framework/crates/crypto/src/validatable.rs @@ -158,7 +158,7 @@ impl Serialize for UnvalidatedEd25519PublicKey { S: serde::Serializer, { if serializer.is_human_readable() { - let encoded = ::hex::encode(&self.0); + let encoded = ::hex::encode(self.0); serializer.serialize_str(&encoded) } else { // See comment in deserialize_key. diff --git a/language/documentation/examples/diem-framework/crates/crypto/src/x25519.rs b/language/documentation/examples/diem-framework/crates/crypto/src/x25519.rs index 215dd992de..4f4f67136e 100644 --- a/language/documentation/examples/diem-framework/crates/crypto/src/x25519.rs +++ b/language/documentation/examples/diem-framework/crates/crypto/src/x25519.rs @@ -250,7 +250,7 @@ impl traits::ValidCryptoMaterial for PublicKey { impl std::fmt::Display for PublicKey { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", hex::encode(&self.0)) + write!(f, "{}", hex::encode(self.0)) } } diff --git a/language/documentation/examples/diem-framework/crates/natives/Cargo.toml b/language/documentation/examples/diem-framework/crates/natives/Cargo.toml index f59df07096..cc2867982a 100644 --- a/language/documentation/examples/diem-framework/crates/natives/Cargo.toml +++ b/language/documentation/examples/diem-framework/crates/natives/Cargo.toml @@ -3,7 +3,7 @@ name = "diem-framework-natives" version = "0.0.0" authors = ["Diem Association "] publish = false -edition = "2018" +edition = "2021" license = "Apache-2.0" [dependencies] diff --git a/language/documentation/examples/diem-framework/crates/natives/src/account.rs b/language/documentation/examples/diem-framework/crates/natives/src/account.rs index 00c063fa00..6794e22206 100644 --- a/language/documentation/examples/diem-framework/crates/natives/src/account.rs +++ b/language/documentation/examples/diem-framework/crates/natives/src/account.rs @@ -6,17 +6,13 @@ use move_binary_format::errors::PartialVMResult; use move_core_types::account_address::AccountAddress; use move_vm_runtime::native_functions::NativeContext; use move_vm_types::{ - gas_schedule::NativeCostIndex, - loaded_data::runtime_types::Type, - natives::function::{native_gas, NativeResult}, - pop_arg, - values::Value, + loaded_data::runtime_types::Type, natives::function::NativeResult, pop_arg, values::Value, }; use smallvec::smallvec; use std::collections::VecDeque; pub fn native_create_signer( - context: &mut NativeContext, + _context: &mut NativeContext, ty_args: Vec, mut arguments: VecDeque, ) -> PartialVMResult { @@ -24,20 +20,21 @@ pub fn native_create_signer( debug_assert!(arguments.len() == 1); let address = pop_arg!(arguments, AccountAddress); - let cost = native_gas(context.cost_table(), NativeCostIndex::CREATE_SIGNER, 0); - Ok(NativeResult::ok(cost, smallvec![Value::signer(address)])) + Ok(NativeResult::ok( + 25.into(), + smallvec![Value::signer(address)], + )) } /// NOTE: this function will be deprecated after the Diem v3 release, but must /// remain for replaying old transactions pub fn native_destroy_signer( - context: &mut NativeContext, + _context: &mut NativeContext, ty_args: Vec, arguments: VecDeque, ) -> PartialVMResult { debug_assert!(ty_args.is_empty()); debug_assert!(arguments.len() == 1); - let cost = native_gas(context.cost_table(), NativeCostIndex::DESTROY_SIGNER, 0); - Ok(NativeResult::ok(cost, smallvec![])) + Ok(NativeResult::ok(213.into(), smallvec![])) } diff --git a/language/documentation/examples/diem-framework/crates/natives/src/lib.rs b/language/documentation/examples/diem-framework/crates/natives/src/lib.rs index cc85249f32..bb8471f7cd 100644 --- a/language/documentation/examples/diem-framework/crates/natives/src/lib.rs +++ b/language/documentation/examples/diem-framework/crates/natives/src/lib.rs @@ -5,44 +5,42 @@ pub mod account; pub mod signature; -use move_core_types::{account_address::AccountAddress, identifier::Identifier}; -use move_vm_runtime::native_functions::{NativeFunction, NativeFunctionTable}; +use std::sync::Arc; + +use move_core_types::account_address::AccountAddress; +use move_vm_runtime::native_functions::{ + make_table_from_iter, NativeFunction, NativeFunctionTable, +}; pub fn all_natives(diem_framework_addr: AccountAddress) -> NativeFunctionTable { - const NATIVES: &[(&str, &str, NativeFunction)] = &[ + let natives: [(&str, &str, NativeFunction); 5] = [ // TODO: Remove once/if DPN is moved over to use the core framework ( "DiemAccount", "create_signer", - account::native_create_signer, + Arc::new(account::native_create_signer), ), ( "DiemAccount", "destroy_signer", - account::native_destroy_signer, + Arc::new(account::native_destroy_signer), ), ( "Signature", "ed25519_validate_pubkey", - signature::native_ed25519_publickey_validation, + Arc::new(signature::native_ed25519_publickey_validation), ), ( "Signature", "ed25519_verify", - signature::native_ed25519_signature_verification, + Arc::new(signature::native_ed25519_signature_verification), + ), + ( + "Account", + "create_signer", + Arc::new(account::native_create_signer), ), - ("Account", "create_signer", account::native_create_signer), ]; - NATIVES - .iter() - .cloned() - .map(|(module_name, func_name, func)| { - ( - diem_framework_addr, - Identifier::new(module_name).unwrap(), - Identifier::new(func_name).unwrap(), - func, - ) - }) - .collect() + + make_table_from_iter(diem_framework_addr, natives) } diff --git a/language/documentation/examples/diem-framework/crates/natives/src/signature.rs b/language/documentation/examples/diem-framework/crates/natives/src/signature.rs index 911ba1edde..0cc1311a62 100644 --- a/language/documentation/examples/diem-framework/crates/natives/src/signature.rs +++ b/language/documentation/examples/diem-framework/crates/natives/src/signature.rs @@ -6,17 +6,13 @@ use diem_crypto::{ed25519, traits::*}; use move_binary_format::errors::PartialVMResult; use move_vm_runtime::native_functions::NativeContext; use move_vm_types::{ - gas_schedule::NativeCostIndex, - loaded_data::runtime_types::Type, - natives::function::{native_gas, NativeResult}, - pop_arg, - values::Value, + loaded_data::runtime_types::Type, natives::function::NativeResult, pop_arg, values::Value, }; use smallvec::smallvec; use std::{collections::VecDeque, convert::TryFrom}; pub fn native_ed25519_publickey_validation( - context: &mut NativeContext, + _context: &mut NativeContext, _ty_args: Vec, mut arguments: VecDeque, ) -> PartialVMResult { @@ -25,19 +21,15 @@ pub fn native_ed25519_publickey_validation( let key_bytes = pop_arg!(arguments, Vec); - let cost = native_gas( - context.cost_table(), - NativeCostIndex::ED25519_VALIDATE_KEY, - key_bytes.len(), - ); + let cost = 26 * usize::max(key_bytes.len(), 1) as u64; // This deserialization performs point-on-curve and small subgroup checks let valid = ed25519::Ed25519PublicKey::try_from(&key_bytes[..]).is_ok(); - Ok(NativeResult::ok(cost, smallvec![Value::bool(valid)])) + Ok(NativeResult::ok(cost.into(), smallvec![Value::bool(valid)])) } pub fn native_ed25519_signature_verification( - context: &mut NativeContext, + _context: &mut NativeContext, _ty_args: Vec, mut arguments: VecDeque, ) -> PartialVMResult { @@ -48,28 +40,24 @@ pub fn native_ed25519_signature_verification( let pubkey = pop_arg!(arguments, Vec); let signature = pop_arg!(arguments, Vec); - let cost = native_gas( - context.cost_table(), - NativeCostIndex::ED25519_VERIFY, - msg.len(), - ); + let cost = 62 * usize::max(msg.len(), 1) as u64; let sig = match ed25519::Ed25519Signature::try_from(signature.as_slice()) { Ok(sig) => sig, Err(_) => { - return Ok(NativeResult::ok(cost, smallvec![Value::bool(false)])); + return Ok(NativeResult::ok(cost.into(), smallvec![Value::bool(false)])); } }; let pk = match ed25519::Ed25519PublicKey::try_from(pubkey.as_slice()) { Ok(pk) => pk, Err(_) => { - return Ok(NativeResult::ok(cost, smallvec![Value::bool(false)])); + return Ok(NativeResult::ok(cost.into(), smallvec![Value::bool(false)])); } }; let verify_result = sig.verify_arbitrary_msg(msg.as_slice(), &pk).is_ok(); Ok(NativeResult::ok( - cost, + cost.into(), smallvec![Value::bool(verify_result)], )) } diff --git a/language/documentation/examples/diem-framework/move-packages/DPN/sources/CRSN.move b/language/documentation/examples/diem-framework/move-packages/DPN/sources/CRSN.move index 9fabd60bd1..7880280dcc 100644 --- a/language/documentation/examples/diem-framework/move-packages/DPN/sources/CRSN.move +++ b/language/documentation/examples/diem-framework/move-packages/DPN/sources/CRSN.move @@ -194,8 +194,9 @@ module DiemFramework::CRSN { } spec force_expire { - let addr = signer::address_of(account); - ensures global(addr).min_nonce == old(global(addr)).min_nonce + shift_amount; + // TODO: this ensures may not hold + // let addr = signer::address_of(account); + // ensures global(addr).min_nonce == old(global(addr)).min_nonce + shift_amount; } /// Return whether this address has a CRSN resource published under it. public fun has_crsn(addr: address): bool { diff --git a/language/documentation/examples/diem-framework/move-packages/DPN/tests/AccountFreezingTests.move b/language/documentation/examples/diem-framework/move-packages/DPN/tests/AccountFreezingTests.move index 1d3f2a63cb..d7076726e5 100644 --- a/language/documentation/examples/diem-framework/move-packages/DPN/tests/AccountFreezingTests.move +++ b/language/documentation/examples/diem-framework/move-packages/DPN/tests/AccountFreezingTests.move @@ -5,7 +5,7 @@ module DiemFramework::AccountFreezingTests { use std::signer; #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = DiemFramework::DiemTimestamp)] fun account_freezing_double_init(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); AF::initialize(&dr); @@ -25,7 +25,7 @@ module DiemFramework::AccountFreezingTests { } #[test(a = @0x2)] - #[expected_failure(abort_code = 518)] + #[expected_failure(abort_code = 518, location = AF)] fun create_new_already_has_freezing_bit(a: signer) { AF::create_for_test(&a); AF::create_for_test(&a); @@ -39,7 +39,7 @@ module DiemFramework::AccountFreezingTests { } #[test(a = @0x2, tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 258)] + #[expected_failure(abort_code = 258, location = DiemFramework::CoreAddresses)] fun freeze_account_not_tc(a: signer, tc: signer, dr: signer) { Genesis::setup(&dr, &tc); AF::create_for_test(&a); @@ -47,28 +47,28 @@ module DiemFramework::AccountFreezingTests { } #[test(tc = @TreasuryCompliance, a = @0x2)] - #[expected_failure(abort_code = 257)] + #[expected_failure(abort_code = 257, location = DiemFramework::DiemTimestamp)] fun freeze_account_not_operating(tc: signer, a: signer) { AF::create_for_test(&a); AF::freeze_account(&tc, @0x2); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 775)] + #[expected_failure(abort_code = 775, location = AF)] fun cannot_freeze_diem_root(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); AF::freeze_account(&tc, @DiemRoot); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 1031)] + #[expected_failure(abort_code = 1031, location = AF)] fun cannot_freeze_treasury_compliance(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); AF::freeze_account(&tc, @TreasuryCompliance); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 517)] + #[expected_failure(abort_code = 517, location = AF)] fun freeze_no_freezing_bit(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); AF::freeze_account(&tc, @0x2); @@ -85,14 +85,14 @@ module DiemFramework::AccountFreezingTests { } #[test(tc = @TreasuryCompliance, a = @0x2)] - #[expected_failure(abort_code = 257)] + #[expected_failure(abort_code = 257, location = DiemFramework::DiemTimestamp)] fun unfreeze_account_not_operating(tc: signer, a: signer) { AF::create_for_test(&a); AF::unfreeze_account(&tc, @0x2); } #[test(a = @0x2, tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 258)] + #[expected_failure(abort_code = 258, location = DiemFramework::CoreAddresses)] fun unfreeze_account_not_tc(a: signer, tc: signer, dr: signer) { Genesis::setup(&dr, &tc); AF::create_for_test(&a); @@ -100,7 +100,7 @@ module DiemFramework::AccountFreezingTests { } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 517)] + #[expected_failure(abort_code = 517, location = AF)] fun unfreeze_no_freezing_bit(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); AF::unfreeze_account(&tc, @0x2); diff --git a/language/documentation/examples/diem-framework/move-packages/DPN/tests/AccountLimits.move b/language/documentation/examples/diem-framework/move-packages/DPN/tests/AccountLimits.move index 66789e2415..7201eeb88c 100644 --- a/language/documentation/examples/diem-framework/move-packages/DPN/tests/AccountLimits.move +++ b/language/documentation/examples/diem-framework/move-packages/DPN/tests/AccountLimits.move @@ -21,7 +21,7 @@ module DiemFramework::AccountLimitsTests { } #[test(dr = @DiemRoot, tc = @TreasuryCompliance, vasp = @0x2)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = DiemFramework::DiemTimestamp)] fun grant_mutation_capability_after_genesis(dr: signer, tc: signer, vasp: signer) { Genesis::setup(&dr, &tc); @@ -34,7 +34,7 @@ module DiemFramework::AccountLimitsTests { } #[test(dr = @DiemRoot, tc = @TreasuryCompliance, vasp = @0x2)] - #[expected_failure(abort_code = 262)] + #[expected_failure(abort_code = 262, location = AccountLimits)] fun publish_window_twice(dr: signer, tc: signer, vasp: signer) { setup(&dr, &tc, &vasp); @@ -42,21 +42,21 @@ module DiemFramework::AccountLimitsTests { } #[test(dr = @DiemRoot, tc = @TreasuryCompliance, vasp = @0x2)] - #[expected_failure(abort_code = 2)] + #[expected_failure(abort_code = 2, location = DiemFramework::CoreAddresses)] fun publish_window_non_diem_root(dr: signer, tc: signer, vasp: signer) { setup(&dr, &tc, &vasp); AccountLimits::publish_window(&vasp, &vasp, signer::address_of(&vasp)); } #[test(dr = @DiemRoot, tc = @TreasuryCompliance, vasp = @0x2)] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = AccountLimits)] fun publish_window_non_existent_limit_address(dr: signer, tc: signer, vasp: signer) { setup(&dr, &tc, &vasp); AccountLimits::publish_window(&dr, &vasp, @0x42 /* non-exsistent */); } #[test(dr = @DiemRoot, tc = @TreasuryCompliance, vasp = @0x2)] - #[expected_failure(abort_code = 6)] + #[expected_failure(abort_code = 6, location = AccountLimits)] fun publish_unrestricted_limits_for_testing_twice(dr: signer, tc: signer, vasp: signer) { setup(&dr, &tc, &vasp); AccountLimits::publish_unrestricted_limits_for_testing(&vasp); @@ -110,7 +110,7 @@ module DiemFramework::AccountLimitsTests { } #[test(dr = @DiemRoot, tc = @TreasuryCompliance, vasp = @0x2)] - #[expected_failure(abort_code = 258)] + #[expected_failure(abort_code = 258, location = DiemFramework::CoreAddresses)] fun update_limits_definition_non_tc(dr: signer, tc: signer, vasp: signer) { setup(&dr, &tc, &vasp); AccountLimits::update_limits_definition( @@ -124,7 +124,7 @@ module DiemFramework::AccountLimitsTests { } #[test(dr = @DiemRoot, tc = @TreasuryCompliance, vasp = @0x2)] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = AccountLimits)] fun update_limits_definition_non_exsistent(dr: signer, tc: signer, vasp: signer) { setup(&dr, &tc, &vasp); AccountLimits::update_limits_definition( @@ -162,7 +162,7 @@ module DiemFramework::AccountLimitsTests { } #[test(dr = @DiemRoot, tc = @TreasuryCompliance, vasp = @0x2)] - #[expected_failure(abort_code = 258)] + #[expected_failure(abort_code = 258, location = DiemFramework::CoreAddresses)] fun update_window_info_non_tc(dr: signer, tc: signer, vasp: signer) { setup(&dr, &tc, &vasp); let vasp_addr = signer::address_of(&vasp); diff --git a/language/documentation/examples/diem-framework/move-packages/DPN/tests/AuthenticatorTests.move b/language/documentation/examples/diem-framework/move-packages/DPN/tests/AuthenticatorTests.move index 8138ada6ed..c7633e3858 100644 --- a/language/documentation/examples/diem-framework/move-packages/DPN/tests/AuthenticatorTests.move +++ b/language/documentation/examples/diem-framework/move-packages/DPN/tests/AuthenticatorTests.move @@ -43,21 +43,21 @@ module DiemFramework::AuthenticatorTests { } #[test] - #[expected_failure(abort_code = 7)] + #[expected_failure(abort_code = 7, location = Authenticator)] fun empty_policy_should_be_rejected() { let keys = vector::empty>(); Authenticator::create_multi_ed25519(keys, 0); } #[test] - #[expected_failure(abort_code = 263)] + #[expected_failure(abort_code = 263, location = Authenticator)] fun bad_threshold_should_be_rejected_threshold_1_for_empty_keys() { let keys = vector::empty>(); Authenticator::create_multi_ed25519(keys, 1); } #[test] - #[expected_failure(abort_code = 519)] + #[expected_failure(abort_code = 519, location = Authenticator)] fun bad_threshold_should_be_rejected_threshold_3_for_34_keys() { let pubkey = x""; @@ -72,7 +72,7 @@ module DiemFramework::AuthenticatorTests { } #[test] - #[expected_failure(abort_code = 263)] + #[expected_failure(abort_code = 263, location = Authenticator)] fun bad_threshold_should_be_rejected_threshold_2_for_1_key() { let keys = vector::empty>(); vector::push_back( @@ -83,7 +83,7 @@ module DiemFramework::AuthenticatorTests { } #[test] - #[expected_failure(abort_code = 7)] + #[expected_failure(abort_code = 7, location = Authenticator)] fun bad_threshold_should_be_rejected_threshold_0_for_1_address() { let keys = vector::empty>(); vector::push_back( diff --git a/language/documentation/examples/diem-framework/move-packages/DPN/tests/CRSNTests.move b/language/documentation/examples/diem-framework/move-packages/DPN/tests/CRSNTests.move index bfd87cd8f9..62a37f7a8d 100644 --- a/language/documentation/examples/diem-framework/move-packages/DPN/tests/CRSNTests.move +++ b/language/documentation/examples/diem-framework/move-packages/DPN/tests/CRSNTests.move @@ -12,14 +12,14 @@ module DiemFramework::CRSNTests { } #[test(a=@0xCAFE, tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 1281)] + #[expected_failure(abort_code = 1281, location = CRSN)] public fun cant_publish_until_init(a: signer, tc: signer, dr: signer) { Genesis::setup(&dr, &tc); CRSN::test_publish(&a, 0, 10); } #[test(a=@0xCAFE, tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 1537)] + #[expected_failure(abort_code = 1537, location = CRSN)] public fun double_init(a: signer, tc: signer, dr: signer) { setup(&dr, &tc, &a); CRSN::allow_crsns(&dr); @@ -60,7 +60,7 @@ module DiemFramework::CRSNTests { #[test(a=@0xCAFE, tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 257)] + #[expected_failure(abort_code = 257, location = CRSN)] public fun double_publish(a: signer, tc: signer, dr: signer) { setup(&dr, &tc, &a); CRSN::test_publish(&a, 0, 10); @@ -68,7 +68,7 @@ module DiemFramework::CRSNTests { } #[test(a=@0xCAFE, tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 519)] + #[expected_failure(abort_code = 519, location = CRSN)] public fun publish_zero_size(a: signer, tc: signer, dr: signer) { setup(&dr, &tc, &a); CRSN::test_publish(&a, 10, 0); @@ -81,7 +81,7 @@ module DiemFramework::CRSNTests { } #[test(a=@0xCAFE, tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 775)] + #[expected_failure(abort_code = 775, location = CRSN)] public fun publish_above_max_size(a: signer, tc: signer, dr: signer) { setup(&dr, &tc, &a); CRSN::test_publish(&a, 10, CRSN::max_crsn_size() + 1); @@ -97,7 +97,7 @@ module DiemFramework::CRSNTests { } #[test(a=@0xCAFE)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = CRSN)] public fun record_no_crsn(a: signer) { CRSN::test_record(&a, 0); } @@ -171,7 +171,7 @@ module DiemFramework::CRSNTests { } #[test(a=@0xCAFE, tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 1031)] + #[expected_failure(abort_code = 1031, location = CRSN)] public fun force_expire_zero(a: signer, tc: signer, dr: signer) { setup(&dr, &tc, &a); CRSN::test_publish(&a, 100, 10); diff --git a/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemBlockTests.move b/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemBlockTests.move index b2786df976..2f5e1bf91d 100644 --- a/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemBlockTests.move +++ b/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemBlockTests.move @@ -5,7 +5,7 @@ module DiemFramework::DiemBlockTests { // TODO: the error code doesn't seem correct, juding by the name of the test. #[test(tc = @TreasuryCompliance, dr = @DiemRoot, account = @0x100)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = DiemFramework::DiemTimestamp)] fun invalid_initialization_address(account: signer, tc: signer, dr: signer) { Genesis::setup(&dr, &tc); DiemBlock::initialize_block_metadata(&account); diff --git a/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemConfigTests.move b/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemConfigTests.move index 7dd6fb463a..b648390932 100644 --- a/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemConfigTests.move +++ b/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemConfigTests.move @@ -4,34 +4,34 @@ module DiemFramework::OnChainConfigTests { use DiemFramework::Genesis; #[test(account = @0x1)] - #[expected_failure(abort_code = 2)] + #[expected_failure(abort_code = 2, location = DiemFramework::CoreAddresses)] fun init_before_genesis(account: signer) { DiemConfig::initialize(&account); } #[test(account = @0x2, tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = DiemFramework::DiemTimestamp)] fun invalid_address_init(account: signer, tc: signer, dr: signer) { Genesis::setup(&dr, &tc); DiemConfig::initialize(&account); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 261)] + #[expected_failure(abort_code = 261, location = DiemConfig)] fun invalid_get(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); DiemConfig::get(); } #[test(account = @0x1, tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 516)] + #[expected_failure(abort_code = 516, location = DiemConfig)] fun invalid_set(account: signer, tc: signer, dr: signer) { Genesis::setup(&dr, &tc); DiemConfig::set_for_testing(&account, 0); } #[test(account = @0x1, tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 2)] + #[expected_failure(abort_code = 2, location = DiemFramework::CoreAddresses)] fun invalid_publish(account: signer, tc: signer, dr: signer) { Genesis::setup(&dr, &tc); DiemConfig::publish_new_config_for_testing(&account, 0); diff --git a/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemTests.move b/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemTests.move index 72637ec63b..59b3f37195 100644 --- a/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemTests.move +++ b/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemTests.move @@ -39,7 +39,7 @@ module DiemFramework::DiemTests { } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = DiemFramework::DiemTimestamp)] fun cannot_initialize_after_genesis(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); diff --git a/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemTimestampTests.move b/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemTimestampTests.move index 9379eab3cb..189e8f35f3 100644 --- a/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemTimestampTests.move +++ b/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemTimestampTests.move @@ -10,7 +10,7 @@ module DiemFramework::DiemTimestampTests { } #[test] - #[expected_failure(abort_code = 2)] + #[expected_failure(abort_code = 2, location = DiemFramework::CoreAddresses)] fun set_time_has_started_non_dr_pre_genesis() { let s = get_signer(); DiemTimestamp::set_time_has_started_for_testing(&s); @@ -22,14 +22,14 @@ module DiemFramework::DiemTimestampTests { } #[test(dr = @DiemRoot, tc = @TreasuryCompliance)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = DiemTimestamp)] fun set_time_has_started_dr_post_genesis(dr: signer, tc: signer) { Genesis::setup(&dr, &tc); DiemTimestamp::set_time_has_started_for_testing(&dr); } #[test(dr = @DiemRoot, tc = @TreasuryCompliance)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = DiemTimestamp)] fun set_time_has_started_non_dr_post_genesis(dr: signer, tc: signer) { Genesis::setup(&dr, &tc); let s = get_signer(); @@ -37,14 +37,14 @@ module DiemFramework::DiemTimestampTests { } #[test] - #[expected_failure(abort_code = 257)] + #[expected_failure(abort_code = 257, location = DiemTimestamp)] fun update_global_time_pre_genesis() { let s = get_signer(); DiemTimestamp::update_global_time(&s, @0x0, 0); } #[test(dr = @DiemRoot, tc = @TreasuryCompliance)] - #[expected_failure(abort_code = 514)] + #[expected_failure(abort_code = 514, location = DiemFramework::CoreAddresses)] fun update_global_time_post_genesis_non_vm(dr: signer, tc: signer) { Genesis::setup(&dr, &tc); DiemTimestamp::update_global_time(&dr, @0x1, 0); @@ -59,7 +59,7 @@ module DiemFramework::DiemTimestampTests { } #[test(dr = @DiemRoot, tc = @TreasuryCompliance, vm = @VMReserved)] - #[expected_failure(abort_code = 519)] + #[expected_failure(abort_code = 519, location = DiemTimestamp)] fun update_global_time_post_genesis_vm_nil_proposer_increasing_timestamp(dr: signer, tc: signer, vm: signer) { Genesis::setup(&dr, &tc); assert!(DiemTimestamp::now_microseconds() == 0, 0); @@ -67,7 +67,7 @@ module DiemFramework::DiemTimestampTests { } #[test(dr = @DiemRoot, tc = @TreasuryCompliance, vm = @VMReserved)] - #[expected_failure(abort_code = 519)] + #[expected_failure(abort_code = 519, location = DiemTimestamp)] fun update_global_time_post_genesis_vm_not_nil_proposer_equal_timestamp(dr: signer, tc: signer, vm: signer) { Genesis::setup(&dr, &tc); assert!(DiemTimestamp::now_microseconds() == 0, 0); @@ -83,7 +83,7 @@ module DiemFramework::DiemTimestampTests { } #[test] - #[expected_failure(abort_code = 257)] + #[expected_failure(abort_code = 257, location = DiemTimestamp)] fun now_microseconds_pre_genesis() { DiemTimestamp::now_microseconds(); } @@ -95,7 +95,7 @@ module DiemFramework::DiemTimestampTests { } #[test] - #[expected_failure(abort_code = 257)] + #[expected_failure(abort_code = 257, location = DiemTimestamp)] fun now_seconds_pre_genesis() { DiemTimestamp::now_seconds(); } @@ -115,7 +115,7 @@ module DiemFramework::DiemTimestampTests { } #[test(dr = @DiemRoot, tc = @TreasuryCompliance)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = DiemTimestamp)] fun assert_genesis(dr: signer, tc: signer) { Genesis::setup(&dr, &tc); DiemTimestamp::assert_genesis(); @@ -130,7 +130,7 @@ module DiemFramework::DiemTimestampTests { } #[test] - #[expected_failure(abort_code = 257)] + #[expected_failure(abort_code = 257, location = DiemTimestamp)] fun assert_operating() { DiemTimestamp::assert_operating(); } diff --git a/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemVersionTests.move b/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemVersionTests.move index 6d43862522..41bdfa0489 100644 --- a/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemVersionTests.move +++ b/language/documentation/examples/diem-framework/move-packages/DPN/tests/DiemVersionTests.move @@ -4,33 +4,33 @@ module DiemFramework::DiemVersionTests { use DiemFramework::Genesis; #[test(account = @0x1)] - #[expected_failure(abort_code = 2)] + #[expected_failure(abort_code = 2, location = DiemFramework::CoreAddresses)] fun init_before_genesis(account: signer) { DiemVersion::initialize(&account, 0); } #[test(account = @0x1)] - #[expected_failure(abort_code = 257)] + #[expected_failure(abort_code = 257, location = DiemFramework::DiemTimestamp)] fun set_before_genesis(account: signer) { DiemVersion::set(&account, 0); } #[test(account = @0x2, tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = DiemFramework::DiemTimestamp)] fun invalid_address_init(account: signer, tc: signer, dr: signer) { Genesis::setup(&dr, &tc); DiemVersion::initialize(&account, 0); } #[test(account = @0x2, tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 2)] + #[expected_failure(abort_code = 2, location = DiemFramework::CoreAddresses)] fun invalid_setting_address(account: signer, tc: signer, dr: signer) { Genesis::setup(&dr, &tc); DiemVersion::set(&account, 0); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 7)] + #[expected_failure(abort_code = 7, location = DiemVersion)] fun non_increasing_version(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); DiemVersion::set(&dr, 0); diff --git a/language/documentation/examples/diem-framework/move-packages/DPN/tests/RegisteredCurrencyTests.move b/language/documentation/examples/diem-framework/move-packages/DPN/tests/RegisteredCurrencyTests.move index 7a2d28bfc4..35ad26c30a 100644 --- a/language/documentation/examples/diem-framework/move-packages/DPN/tests/RegisteredCurrencyTests.move +++ b/language/documentation/examples/diem-framework/move-packages/DPN/tests/RegisteredCurrencyTests.move @@ -4,21 +4,21 @@ module DiemFramework::RegisteredCurrencyTests { use DiemFramework::Genesis; #[test(dr = @DiemRoot, tc = @TreasuryCompliance, alice = @0x2)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = DiemFramework::DiemTimestamp)] fun cannot_call_initialize_as_non_diem_root(dr: signer, tc: signer, alice: signer) { Genesis::setup(&dr, &tc); RegisteredCurrencies::initialize(&alice); } #[test(dr = @DiemRoot, tc = @TreasuryCompliance)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = DiemFramework::DiemTimestamp)] fun cannot_call_initialize_outside_genesis(dr: signer, tc: signer) { Genesis::setup(&dr, &tc); RegisteredCurrencies::initialize(&dr); } #[test(dr = @DiemRoot, tc = @TreasuryCompliance)] - #[expected_failure(abort_code = 7)] + #[expected_failure(abort_code = 7, location = RegisteredCurrencies)] fun cannot_add_currency_whose_currency_code_has_already_been_taken(dr: signer, tc: signer) { Genesis::setup(&dr, &tc); RegisteredCurrencies::add_currency_code(&dr, b"XDX"); diff --git a/language/documentation/examples/diem-framework/move-packages/DPN/tests/RolesTests.move b/language/documentation/examples/diem-framework/move-packages/DPN/tests/RolesTests.move index f64660d8a9..41c020468a 100644 --- a/language/documentation/examples/diem-framework/move-packages/DPN/tests/RolesTests.move +++ b/language/documentation/examples/diem-framework/move-packages/DPN/tests/RolesTests.move @@ -11,20 +11,20 @@ module DiemFramework::RolesTests{ } #[test] - #[expected_failure(abort_code = 2)] + #[expected_failure(abort_code = 2, location = DiemFramework::CoreAddresses)] fun grant_diem_root_wrong_addr_pre_genesis() { let account = get_account(); Roles::grant_diem_root_role(&account); } #[test(tc = @TreasuryCompliance)] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = Roles)] fun tc_dne_pre_genesis(tc: signer) { Roles::assert_treasury_compliance(&tc); } #[test(dr = @DiemRoot)] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = Roles)] fun dr_dne_pre_genesis(dr: signer) { Roles::assert_diem_root(&dr); } @@ -40,21 +40,21 @@ module DiemFramework::RolesTests{ } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 2)] + #[expected_failure(abort_code = 2, location = DiemFramework::CoreAddresses)] fun tc_is_not_dr(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); Roles::assert_diem_root(&tc); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 258)] + #[expected_failure(abort_code = 258, location = DiemFramework::CoreAddresses)] fun dr_is_not_tc(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); Roles::assert_treasury_compliance(&dr); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = DiemFramework::DiemTimestamp)] fun grant_diem_root_wrong_addr_post_genesis(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let account = get_account(); @@ -62,21 +62,21 @@ module DiemFramework::RolesTests{ } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = DiemFramework::DiemTimestamp)] fun grant_diem_root_correct_addr_post_genesis(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); Roles::grant_diem_root_role(&dr); } #[test] - #[expected_failure(abort_code = 258)] + #[expected_failure(abort_code = 258, location = DiemFramework::CoreAddresses)] fun grant_treasury_compliance_wrong_addr_pre_genesis() { let account = get_account(); Roles::grant_treasury_compliance_role(&account, &account); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = DiemFramework::DiemTimestamp)] fun grant_treasury_compliance_wrong_addr_post_genesis(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let account = get_account(); @@ -84,35 +84,35 @@ module DiemFramework::RolesTests{ } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = DiemFramework::DiemTimestamp)] fun grant_treasury_compliance_wrong_granting_addr_post_genesis(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); Roles::grant_treasury_compliance_role(&tc, &tc); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = DiemFramework::DiemTimestamp)] fun grant_treasury_compliance_correct_addrs(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); Roles::grant_treasury_compliance_role(&dr, &tc); } #[test] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = Roles)] fun designated_dealer_role_dne() { let account = get_account(); Roles::assert_designated_dealer(&account); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 1539)] + #[expected_failure(abort_code = 1539, location = Roles)] fun designated_dealer_assert_wrong_role(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); Roles::assert_designated_dealer(&tc); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 258)] + #[expected_failure(abort_code = 258, location = DiemFramework::CoreAddresses)] fun grant_dd_role_non_tc_granter(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let account = get_account(); @@ -131,7 +131,7 @@ module DiemFramework::RolesTests{ } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 6)] + #[expected_failure(abort_code = 6, location = Roles)] fun double_grant_dd_role_tc_granter(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let account = get_account(); @@ -140,21 +140,21 @@ module DiemFramework::RolesTests{ } #[test] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = Roles)] fun validator_role_dne() { let account = get_account(); Roles::assert_validator(&account); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 1795)] + #[expected_failure(abort_code = 1795, location = Roles)] fun validator_assert_wrong_role(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); Roles::assert_validator(&tc); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 2)] + #[expected_failure(abort_code = 2, location = DiemFramework::CoreAddresses)] fun grant_validator_role_non_dr_granter(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let account = get_account(); @@ -172,7 +172,7 @@ module DiemFramework::RolesTests{ } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 6)] + #[expected_failure(abort_code = 6, location = Roles)] fun double_grant_validator_role_dr_granter(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let account = get_account(); @@ -181,21 +181,21 @@ module DiemFramework::RolesTests{ } #[test] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = Roles)] fun validator_operator_role_dne() { let account = get_account(); Roles::assert_validator_operator(&account); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 2051)] + #[expected_failure(abort_code = 2051, location = Roles)] fun validator_operator_assert_wrong_role(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); Roles::assert_validator_operator(&tc); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 2)] + #[expected_failure(abort_code = 2, location = DiemFramework::CoreAddresses)] fun grant_validator_operator_role_non_dr_granter(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let account = get_account(); @@ -213,7 +213,7 @@ module DiemFramework::RolesTests{ } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 6)] + #[expected_failure(abort_code = 6, location = Roles)] fun double_grant_validator_operator_role_dr_granter(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let account = get_account(); @@ -222,14 +222,14 @@ module DiemFramework::RolesTests{ } #[test] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = Roles)] fun parent_vasp_role_dne() { let account = get_account(); Roles::assert_parent_vasp_role(&account); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 258)] + #[expected_failure(abort_code = 258, location = DiemFramework::CoreAddresses)] fun grant_parent_vasp_role_non_tc_granter(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let account = get_account(); @@ -249,7 +249,7 @@ module DiemFramework::RolesTests{ } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 6)] + #[expected_failure(abort_code = 6, location = Roles)] fun double_grant_parent_vasp_role_tc_granter(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let account = get_account(); @@ -258,14 +258,14 @@ module DiemFramework::RolesTests{ } #[test] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = Roles)] fun child_vasp_role_dne() { let account = get_account(); Roles::assert_child_vasp_role(&account); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 2307)] + #[expected_failure(abort_code = 2307, location = Roles)] fun child_vasp_assert_wrong_role(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let account = get_account(); @@ -274,7 +274,7 @@ module DiemFramework::RolesTests{ } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 771)] + #[expected_failure(abort_code = 771, location = Roles)] fun grant_child_vasp_role_non_parent_vasp_granter(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let account = get_account(); @@ -297,7 +297,7 @@ module DiemFramework::RolesTests{ } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 6)] + #[expected_failure(abort_code = 6, location = Roles)] fun double_grant_child_vasp_role_tc_granter(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let (account, pvasp) = { @@ -361,21 +361,21 @@ module DiemFramework::RolesTests{ } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = Roles)] fun get_role_id_no_role(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); Roles::get_role_id(@0x1); } #[test] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = Roles)] fun assert_parent_or_designated_dealer_role_dne() { let account = get_account(); Roles::assert_parent_vasp_or_designated_dealer(&account); } #[test] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = Roles)] fun assert_parent_or_child_role_dne() { let account = get_account(); Roles::assert_parent_vasp_or_child_vasp(&account); diff --git a/language/documentation/examples/diem-framework/move-packages/DPN/tests/SharedEd25519PublicKeyTests.move b/language/documentation/examples/diem-framework/move-packages/DPN/tests/SharedEd25519PublicKeyTests.move index 20c01359d8..310aa1dd8c 100644 --- a/language/documentation/examples/diem-framework/move-packages/DPN/tests/SharedEd25519PublicKeyTests.move +++ b/language/documentation/examples/diem-framework/move-packages/DPN/tests/SharedEd25519PublicKeyTests.move @@ -49,7 +49,7 @@ module DiemFramework::SharedEd25519PublicKeyTests { } #[test(dr = @DiemRoot, tc = @TreasuryCompliance, account = @0x100)] - #[expected_failure(abort_code = 261)] + #[expected_failure(abort_code = 261, location = SharedEd25519PublicKey)] fun get_key_for_non_shared_account_should_fail(dr: signer, tc: signer, account: signer) { setup(&dr, &tc, &account); @@ -57,7 +57,7 @@ module DiemFramework::SharedEd25519PublicKeyTests { } #[test(dr = @DiemRoot, tc = @TreasuryCompliance, account = @0x100)] - #[expected_failure(abort_code = 7)] + #[expected_failure(abort_code = 7, location = SharedEd25519PublicKey)] fun publish_key_with_bad_length_1(dr: signer, tc: signer, account: signer) { setup(&dr, &tc, &account); @@ -66,7 +66,7 @@ module DiemFramework::SharedEd25519PublicKeyTests { } #[test(dr = @DiemRoot, tc = @TreasuryCompliance, account = @0x100)] - #[expected_failure(abort_code = 7)] + #[expected_failure(abort_code = 7, location = SharedEd25519PublicKey)] fun publish_key_with_bad_length_2(dr: signer, tc: signer, account: signer) { setup(&dr, &tc, &account); @@ -75,7 +75,7 @@ module DiemFramework::SharedEd25519PublicKeyTests { } #[test(dr = @DiemRoot, tc = @TreasuryCompliance, account = @0x100)] - #[expected_failure(abort_code = 7)] + #[expected_failure(abort_code = 7, location = SharedEd25519PublicKey)] fun rotate_to_key_with_bad_length(dr: signer, tc: signer, account: signer) { setup(&dr, &tc, &account); @@ -88,7 +88,7 @@ module DiemFramework::SharedEd25519PublicKeyTests { } #[test(dr = @DiemRoot, tc = @TreasuryCompliance, account = @0x100)] - #[expected_failure(abort_code = 7)] + #[expected_failure(abort_code = 7, location = SharedEd25519PublicKey)] fun rotate_to_key_with_good_length_but_bad_contents(dr: signer, tc: signer, account: signer) { setup(&dr, &tc, &account); @@ -100,7 +100,7 @@ module DiemFramework::SharedEd25519PublicKeyTests { } #[test(dr = @DiemRoot, tc = @TreasuryCompliance, account = @0x100)] - #[expected_failure(abort_code = 261)] + #[expected_failure(abort_code = 261, location = SharedEd25519PublicKey)] fun rotate_key_on_non_shared_account(dr: signer, tc: signer, account: signer) { setup(&dr, &tc, &account); diff --git a/language/documentation/examples/diem-framework/move-packages/DPN/tests/TransactionFeeTests.move b/language/documentation/examples/diem-framework/move-packages/DPN/tests/TransactionFeeTests.move index 5c543b8413..deb26c34c0 100644 --- a/language/documentation/examples/diem-framework/move-packages/DPN/tests/TransactionFeeTests.move +++ b/language/documentation/examples/diem-framework/move-packages/DPN/tests/TransactionFeeTests.move @@ -4,14 +4,14 @@ module DiemFramework::TransactionFeeTests { use DiemFramework::Genesis; #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = DiemFramework::DiemTimestamp)] fun cannot_initialize_after_genesis(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); TransactionFee::initialize(&tc); } #[test(account = @0x100)] - #[expected_failure(abort_code = 258)] + #[expected_failure(abort_code = 258, location = DiemFramework::CoreAddresses)] fun cannot_initialize_as_non_tc(account: signer) { TransactionFee::initialize(&account); } diff --git a/language/documentation/examples/diem-framework/move-packages/DPN/tests/ValidatorConfigTests.move b/language/documentation/examples/diem-framework/move-packages/DPN/tests/ValidatorConfigTests.move index b6eea1d436..b46e9d2813 100644 --- a/language/documentation/examples/diem-framework/move-packages/DPN/tests/ValidatorConfigTests.move +++ b/language/documentation/examples/diem-framework/move-packages/DPN/tests/ValidatorConfigTests.move @@ -16,14 +16,14 @@ module DiemFramework::ValidatorConfigTests { } #[test] - #[expected_failure(abort_code = 257)] + #[expected_failure(abort_code = 257, location = DiemFramework::DiemTimestamp)] fun publish_pre_genesis() { let s = signer_at(0); VC::publish(&s, &s, x""); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 2)] + #[expected_failure(abort_code = 2, location = DiemFramework::CoreAddresses)] fun publish_post_genesis_non_dr(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let s = signer_at(0); @@ -31,7 +31,7 @@ module DiemFramework::ValidatorConfigTests { } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = DiemFramework::Roles)] fun publish_post_genesis_non_validator(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let s = signer_at(0); @@ -47,7 +47,7 @@ module DiemFramework::ValidatorConfigTests { } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 6)] + #[expected_failure(abort_code = 6, location = VC)] fun publish_post_genesis_double_publish(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let s = signer_at(0); @@ -57,14 +57,14 @@ module DiemFramework::ValidatorConfigTests { } #[test] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = DiemFramework::Roles)] fun set_operator_not_validator() { let s = signer_at(0); VC::set_operator(&s, @0x1); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 775)] + #[expected_failure(abort_code = 775, location = VC)] fun set_operator_not_operator(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let s = signer_at(0); @@ -73,7 +73,7 @@ module DiemFramework::ValidatorConfigTests { } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = DiemFramework::Roles)] fun set_operator_no_validator_config_has_role(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let validator = signer_at(0); @@ -105,14 +105,14 @@ module DiemFramework::ValidatorConfigTests { } #[test] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = DiemFramework::Roles)] fun remove_operator_not_validator() { let s = signer_at(0); VC::remove_operator(&s); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = VC)] fun remove_operator_no_config(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let s = signer_at(0); @@ -121,7 +121,7 @@ module DiemFramework::ValidatorConfigTests { } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 7)] + #[expected_failure(abort_code = 7, location = VC)] fun remove_operator_correct(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let validator = signer_at(0); @@ -135,7 +135,7 @@ module DiemFramework::ValidatorConfigTests { } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 263)] + #[expected_failure(abort_code = 263, location = VC)] fun set_config_operator_neq_operator(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let validator = signer_at(0); @@ -147,7 +147,7 @@ module DiemFramework::ValidatorConfigTests { } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 519)] + #[expected_failure(abort_code = 519, location = VC)] fun set_config_invalid_consensus_pubkey(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let validator = signer_at(0); @@ -175,13 +175,13 @@ module DiemFramework::ValidatorConfigTests { } #[test] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = VC)] fun get_config_not_validator() { VC::get_config(@0x1); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 7)] + #[expected_failure(abort_code = 7, location = VC)] fun get_config_not_set(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let validator = signer_at(0); @@ -192,19 +192,19 @@ module DiemFramework::ValidatorConfigTests { } #[test] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = VC)] fun get_human_name_not_validator() { VC::get_human_name(@0x1); } #[test] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = VC)] fun get_operator_not_validator() { VC::get_operator(@0x1); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 7)] + #[expected_failure(abort_code = 7, location = VC)] fun get_operator_not_set(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let validator = signer_at(0); diff --git a/language/documentation/examples/diem-framework/move-packages/DPN/tests/ValidatorOperatorConfigTests.move b/language/documentation/examples/diem-framework/move-packages/DPN/tests/ValidatorOperatorConfigTests.move index dfe703d7b7..9ce2c05a91 100644 --- a/language/documentation/examples/diem-framework/move-packages/DPN/tests/ValidatorOperatorConfigTests.move +++ b/language/documentation/examples/diem-framework/move-packages/DPN/tests/ValidatorOperatorConfigTests.move @@ -12,14 +12,14 @@ module DiemFramework::ValidatorOperatorConfigTests { } #[test] - #[expected_failure(abort_code = 257)] + #[expected_failure(abort_code = 257, location = DiemFramework::DiemTimestamp)] fun publish_pre_genesis() { let s = get_signer(); VOC::publish(&s, &s, x""); } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 2)] + #[expected_failure(abort_code = 2, location = DiemFramework::CoreAddresses)] fun publish_post_genesis_non_dr(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let s = get_signer(); @@ -27,7 +27,7 @@ module DiemFramework::ValidatorOperatorConfigTests { } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = DiemFramework::Roles)] fun publish_post_genesis_non_validator_operator(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let s = get_signer(); @@ -44,7 +44,7 @@ module DiemFramework::ValidatorOperatorConfigTests { } #[test(tc = @TreasuryCompliance, dr = @DiemRoot)] - #[expected_failure(abort_code = 6)] + #[expected_failure(abort_code = 6, location = VOC)] fun publish_post_genesis_double_publish(tc: signer, dr: signer) { Genesis::setup(&dr, &tc); let s = get_signer(); @@ -54,7 +54,7 @@ module DiemFramework::ValidatorOperatorConfigTests { } #[test] - #[expected_failure(abort_code = 5)] + #[expected_failure(abort_code = 5, location = VOC)] fun get_human_name_not_validator_operator() { VOC::get_human_name(@0x1); } diff --git a/language/documentation/examples/diem-framework/move-packages/DPN/tests/XUSTests.move b/language/documentation/examples/diem-framework/move-packages/DPN/tests/XUSTests.move index 950a86a9ce..e69b265aa8 100644 --- a/language/documentation/examples/diem-framework/move-packages/DPN/tests/XUSTests.move +++ b/language/documentation/examples/diem-framework/move-packages/DPN/tests/XUSTests.move @@ -4,7 +4,7 @@ module DiemFramework::XUSTests { use DiemFramework::Genesis; #[test(tc = @TreasuryCompliance, dr = @DiemRoot, account = @0x100)] - #[expected_failure(abort_code = 1)] + #[expected_failure(abort_code = 1, location = DiemFramework::DiemTimestamp)] fun cannot_recreate_market_cap(tc: signer, dr: signer, account: signer) { Genesis::setup(&dr, &tc); XUS::initialize(&account, &account); diff --git a/language/documentation/examples/diem-framework/move-packages/experimental/sources/Vote.move b/language/documentation/examples/diem-framework/move-packages/experimental/sources/Vote.move index dd965d4d15..b3f55c9e0f 100644 --- a/language/documentation/examples/diem-framework/move-packages/experimental/sources/Vote.move +++ b/language/documentation/examples/diem-framework/move-packages/experimental/sources/Vote.move @@ -329,6 +329,7 @@ module ExperimentalFramework::Vote { let removed_ballots = vector::empty(); while ({ spec { + invariant unique_ballots(ballots); invariant no_expired_ballots(ballots, DiemTimestamp::spec_now_seconds(), i); invariant vector_subset(ballots, old(ballot_data).ballots); invariant i <= len(ballots); diff --git a/language/documentation/examples/diem-framework/move-packages/experimental/tests/VoteTests.move b/language/documentation/examples/diem-framework/move-packages/experimental/tests/VoteTests.move index 0584ae24da..af62356ea1 100644 --- a/language/documentation/examples/diem-framework/move-packages/experimental/tests/VoteTests.move +++ b/language/documentation/examples/diem-framework/move-packages/experimental/tests/VoteTests.move @@ -102,7 +102,7 @@ module ExperimentalFramework::VoteTests { } #[test(dr = @CoreResources)] - #[expected_failure(abort_code = 263)] + #[expected_failure(abort_code = 263, location = Vote)] fun create_ballot_expired_timestamp(dr: signer) { let (proposer, _, addr_bcs) = ballot_setup(&dr); Vote::create_ballot( @@ -174,7 +174,7 @@ module ExperimentalFramework::VoteTests { // TODO: test disabled due to timeout /* #[test(dr = @CoreResources)] - #[expected_failure(abort_code = 520)] + #[expected_failure(abort_code = 520, location = Vote)] fun create_ballots_too_many(dr: signer) { let (proposer, _, addr_bcs) = ballot_setup(&dr); let i = 0; @@ -196,7 +196,7 @@ module ExperimentalFramework::VoteTests { */ #[test(dr = @CoreResources)] - #[expected_failure(abort_code = 769)] + #[expected_failure(abort_code = 769, location = Vote)] fun remove_ballot(dr: signer) { let (voter1, _voter2, _voter3, ballot_id, proposal) = vote_test_helper(&dr, 10); Vote::remove_ballot_internal(get_proposer(), *(&ballot_id)); @@ -205,7 +205,7 @@ module ExperimentalFramework::VoteTests { } #[test(dr = @CoreResources)] - #[expected_failure(abort_code = 769)] + #[expected_failure(abort_code = 769, location = Vote)] fun vote_simple(dr: signer) { let (voter1, voter2, voter3, ballot_id, proposal) = vote_test_helper(&dr, 10); // First vote does not approve the ballot @@ -245,7 +245,7 @@ module ExperimentalFramework::VoteTests { } #[test(dr = @CoreResources)] - #[expected_failure(abort_code = 263)] + #[expected_failure(abort_code = 263, location = Vote)] fun vote_expired_ts(dr: signer) { let (voter1, _voter2, _voter3, ballot_id, proposal) = vote_test_helper(&dr, 0); // Ballot has expired @@ -253,7 +253,7 @@ module ExperimentalFramework::VoteTests { } #[test(dr = @CoreResources)] - #[expected_failure(abort_code = 2049)] + #[expected_failure(abort_code = 2049, location = Vote)] fun vote_repeat(dr: signer) { let (voter1, _voter2, _voter3, ballot_id, proposal) = vote_test_helper(&dr, 10); // First vote does not approve the ballot @@ -263,7 +263,7 @@ module ExperimentalFramework::VoteTests { } #[test(dr = @CoreResources)] - #[expected_failure(abort_code = 1031)] + #[expected_failure(abort_code = 1031, location = Vote)] fun vote_invalid_proposal_type(dr: signer) { let (voter1, _voter2, _voter3, ballot_id, proposal) = vote_test_helper(&dr, 10); // Invalid proposal type @@ -271,7 +271,7 @@ module ExperimentalFramework::VoteTests { } #[test(dr = @CoreResources)] - #[expected_failure(abort_code = 1031)] + #[expected_failure(abort_code = 1031, location = Vote)] fun vote_invalid_proposal(dr: signer) { let (voter1, _voter2, _voter3, ballot_id, _proposal) = vote_test_helper(&dr, 10); let invalid_proposal = TestProposal { @@ -282,7 +282,7 @@ module ExperimentalFramework::VoteTests { } #[test(dr = @CoreResources)] - #[expected_failure(abort_code = 769)] + #[expected_failure(abort_code = 769, location = Vote)] fun vote_invalid_ballotid(dr: signer) { let proposer = get_proposer(); let (voter1, _voter2, _voter3, _ballot_id, proposal) = vote_test_helper(&dr, 10); @@ -292,7 +292,7 @@ module ExperimentalFramework::VoteTests { } #[test(dr = @CoreResources)] - #[expected_failure(abort_code = 1281)] + #[expected_failure(abort_code = 1281, location = Vote)] fun vote_invalid_voter(dr: signer) { let (_voter1, _voter2, _voter3, ballot_id, proposal) = vote_test_helper(&dr, 10); let invalid_voter = vector::pop_back(&mut unit_test::create_signers_for_testing(4)); diff --git a/language/documentation/examples/diem-framework/prove_all.sh b/language/documentation/examples/diem-framework/prove_all.sh index bf3c64939c..d5ed1a864d 100755 --- a/language/documentation/examples/diem-framework/prove_all.sh +++ b/language/documentation/examples/diem-framework/prove_all.sh @@ -5,6 +5,6 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -cd "${SCRIPT_DIR}/move-packages/DPN" && cargo run -p df-cli -- package prove && -cd "${SCRIPT_DIR}/move-packages/core" && cargo run -p df-cli -- package prove && -cd "${SCRIPT_DIR}/move-packages/experimental" && cargo run -p df-cli -- package prove +cd "${SCRIPT_DIR}/move-packages/DPN" && cargo run -p df-cli -- prove && +cd "${SCRIPT_DIR}/move-packages/core" && cargo run -p df-cli -- prove && +cd "${SCRIPT_DIR}/move-packages/experimental" && cargo run -p df-cli -- prove diff --git a/language/documentation/examples/diem-framework/test_all.sh b/language/documentation/examples/diem-framework/test_all.sh index ff78267b8c..d82ab2ce3e 100755 --- a/language/documentation/examples/diem-framework/test_all.sh +++ b/language/documentation/examples/diem-framework/test_all.sh @@ -5,6 +5,6 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -cd "${SCRIPT_DIR}/move-packages/DPN" && cargo run -p df-cli -- package test && -cd "${SCRIPT_DIR}/move-packages/core" && cargo run -p df-cli -- package test && -cd "${SCRIPT_DIR}/move-packages/experimental" && cargo run -p df-cli -- package test +cd "${SCRIPT_DIR}/move-packages/DPN" && cargo run -p df-cli -- test && +cd "${SCRIPT_DIR}/move-packages/core" && cargo run -p df-cli -- test && +cd "${SCRIPT_DIR}/move-packages/experimental" && cargo run -p df-cli -- test diff --git a/language/documentation/examples/experimental/basic-coin/sources/BasicCoin.move b/language/documentation/examples/experimental/basic-coin/sources/BasicCoin.move index a6aa8d2008..07afeca9a6 100644 --- a/language/documentation/examples/experimental/basic-coin/sources/BasicCoin.move +++ b/language/documentation/examples/experimental/basic-coin/sources/BasicCoin.move @@ -1,6 +1,6 @@ /// This module defines a minimal and generic Coin and Balance. module BasicCoin::BasicCoin { - use std::errors; + use std::error; use std::signer; /// Error codes @@ -20,7 +20,7 @@ module BasicCoin::BasicCoin { public fun publish_balance(account: &signer) { let empty_coin = Coin { value: 0 }; - assert!(!exists>(signer::address_of(account)), errors::already_published(EALREADY_HAS_BALANCE)); + assert!(!exists>(signer::address_of(account)), error::already_exists(EALREADY_HAS_BALANCE)); move_to(account, Balance { coin: empty_coin }); } diff --git a/language/documentation/examples/experimental/coin-swap/sources/CoinSwap.move b/language/documentation/examples/experimental/coin-swap/sources/CoinSwap.move index 6d92a57a5b..e97b7112ad 100644 --- a/language/documentation/examples/experimental/coin-swap/sources/CoinSwap.move +++ b/language/documentation/examples/experimental/coin-swap/sources/CoinSwap.move @@ -1,6 +1,6 @@ module CoinSwap::CoinSwap { use std::signer; - use std::errors; + use std::error; use BasicCoin::BasicCoin; use CoinSwap::PoolToken; @@ -27,8 +27,8 @@ module CoinSwap::CoinSwap { // TODO: Alternatively, `struct LiquidityPool` could be refactored to actually hold the coin (e.g., coin1: CoinType1). BasicCoin::publish_balance(coinswap); BasicCoin::publish_balance(coinswap); - assert!(signer::address_of(coinswap) == @CoinSwap, errors::invalid_argument(ECOINSWAP_ADDRESS)); - assert!(!exists>(signer::address_of(coinswap)), errors::already_published(EPOOL)); + assert!(signer::address_of(coinswap) == @CoinSwap, error::invalid_argument(ECOINSWAP_ADDRESS)); + assert!(!exists>(signer::address_of(coinswap)), error::already_exists(EPOOL)); move_to(coinswap, LiquidityPool{coin1, coin2, share}); // Transfer the initial liquidity of CoinType1 and CoinType2 to the pool under @CoinSwap. @@ -53,8 +53,8 @@ module CoinSwap::CoinSwap { witness1: CoinType1, witness2: CoinType2 ) acquires LiquidityPool { - assert!(signer::address_of(coinswap) == @CoinSwap, errors::invalid_argument(ECOINSWAP_ADDRESS)); - assert!(exists>(signer::address_of(coinswap)), errors::not_published(EPOOL)); + assert!(signer::address_of(coinswap) == @CoinSwap, error::invalid_argument(ECOINSWAP_ADDRESS)); + assert!(exists>(signer::address_of(coinswap)), error::not_found(EPOOL)); let pool = borrow_global_mut>(signer::address_of(coinswap)); let coin2 = get_input_price(coin1, pool.coin1, pool.coin2); pool.coin1 = pool.coin1 + coin1; diff --git a/language/documentation/examples/experimental/math-puzzle/README.md b/language/documentation/examples/experimental/math-puzzle/README.md index 5bcf7e01df..a272614299 100644 --- a/language/documentation/examples/experimental/math-puzzle/README.md +++ b/language/documentation/examples/experimental/math-puzzle/README.md @@ -30,7 +30,7 @@ In `sources/puzzlie.move`, the function `Puzzle::puzzle` is constructed to take Use the following command to run Move Prover: ``` -move package prove +move prove ``` The following is the expected output of Move Prover: diff --git a/language/documentation/spec/vm.md b/language/documentation/spec/vm.md index 7b4588f1c5..fea24adb6b 100644 --- a/language/documentation/spec/vm.md +++ b/language/documentation/spec/vm.md @@ -75,7 +75,7 @@ pub fn publish_module( &mut self, module: Vec, sender: AccountAddress, - gas_status: &mut GasStatus, + gas_status: &mut impl GasMeter, ) -> VMResult<()>; ``` @@ -91,7 +91,7 @@ the module](#References-to-Data-and-Code). If the two addresses do not match, an error with `StatusCode::MODULE_ADDRESS_DOES_NOT_MATCH_SENDER` is returned. * Check that the module is not already published: Code is immutable in -Move. An attempt to overwrite an exiting module results in an error with +Move. An attempt to overwrite an existing module results in an error with `StatusCode::DUPLICATE_MODULE_NAME`. * Verify loading: The VM performs [verification](#Verification) of the @@ -120,7 +120,7 @@ pub fn execute_script( ty_args: Vec, args: Vec>, senders: Vec, - gas_status: &mut GasStatus, + gas_status: &mut impl GasMeter, ) -> VMResult<()>; ``` @@ -170,7 +170,7 @@ pub fn execute_script_function( ty_args: Vec, args: Vec>, senders: Vec, - gas_status: &mut GasStatus, + gas_status: &mut impl GasMeter, ) -> VMResult<()>; ``` @@ -201,7 +201,7 @@ pub fn execute_function( function_name: &IdentStr, ty_args: Vec, args: Vec>, - gas_status: &mut GasStatus, + gas_status: &mut impl GasMeter, ) -> VMResult<()>; ``` @@ -485,6 +485,9 @@ into the `STRUCT_HANDLES` table for the generic type of the instantiation, and a vector describing the substitution types, that is, a vector of SignatureTokens * `0xC`: `SIGNER` - a signer type, which is a special type for the VM representing the "entity" that signed the transaction. Signer is a resource type +* `0xD`: `U16` - a 16-bit unsigned integer +* `0xE`: `U32` - a 32-bit unsigned integer +* `0xF`: `U256` - a 256-bit unsigned integer Signature tokens examples: diff --git a/language/documentation/tutorial/README.md b/language/documentation/tutorial/README.md index e8a6a1625b..d15fce32b8 100644 --- a/language/documentation/tutorial/README.md +++ b/language/documentation/tutorial/README.md @@ -55,18 +55,20 @@ cargo install --path language/tools/move-cli You can check that it is working by running the following command: ```bash -move package --help +move --help ``` You should see something like this along with a list and description of a number of commands: ``` -move-package -Execute a package command. Executed in the current directory or the closest containing Move package +move-cli 0.1.0 +Diem Association +MoveCLI is the CLI that will be executed by the `move-cli` command The `cmd` argument is added here +rather than in `Move` to make it easier for other crates to extend `move-cli` USAGE: - move package [OPTIONS] + move [OPTIONS] OPTIONS: --abi Generate ABIs for packages @@ -120,7 +122,7 @@ module 0xCAFE::BasicCoin { This is defining a Move [module](https://move-language.github.io/move/modules-and-scripts.html). Modules are the -building block of Move code, and are defined with a specific address -- the +building blocks of Move code, and are defined with a specific address -- the address that the module can be published under. In this case, the `BasicCoin` module can only be published under `0xCAFE`. @@ -158,10 +160,10 @@ Let's take a look at this function and what it's saying: * It creates a `Coin` with the given value and stores it under the `account` using the `move_to` operator. -Let's make sure it builds! This can be done with the `package build` command from within the package folder ([`step_1/BasicCoin`](./step_1/BasicCoin/)): +Let's make sure it builds! This can be done with the `build` command from within the package folder ([`step_1/BasicCoin`](./step_1/BasicCoin/)): ```bash -move package build +move build ```
@@ -169,7 +171,7 @@ move package build * You can create an empty Move package by calling: ```bash - move package new + move new ``` * Move code can also live a number of other places. More information on the Move package system can be found in the [Move @@ -215,10 +217,10 @@ to [`step_2/BasicCoin`](./step_2/BasicCoin). Unit tests in Move are similar to unit tests in Rust if you're familiar with them -- tests are annotated with `#[test]` and written like normal Move functions. -You can run the tests with the `package test` command: +You can run the tests with the `move test` command: ```bash -move package test +move test ``` Let's now take a look at the contents of the [`FirstModule.move` @@ -232,7 +234,7 @@ module 0xCAFE::BasicCoin { // address value of `0xC0FFEE`. #[test(account = @0xC0FFEE)] fun test_mint_10(account: signer) acquires Coin { - let addr = signer::address_of(&account); + let addr = 0x1::signer::address_of(&account); mint(account, 10); // Make sure there is a `Coin` resource under `addr` with a value of `10`. // We can access this resource and its value since we are in the @@ -260,7 +262,7 @@ assertion fails the unit test will fail. ```toml [dependencies] - MoveStdlib = { local = "../../../../move-stdlib/", addr_subst = { "Std" = "0x1" } } + MoveStdlib = { local = "../../../../move-stdlib/", addr_subst = { "std" = "0x1" } } ``` Note that you may need to alter the path to point to the `move-stdlib` directory under @@ -270,30 +272,29 @@ assertion fails the unit test will fail. #### Exercises * Change the assertion to `11` so that the test fails. Find a flag that you can - pass to the `move package test` command that will show you the global state when + pass to the `move test` command that will show you the global state when the test fails. It should look something like this: ``` - ┌── test_mint_10 ────── - │ error[E11001]: test failure - │ ┌─ ./sources/FirstModule.move:24:9 - │ │ - │ 18 │ fun test_mint_10(account: signer) acquires Coin { - │ │ ------------ In this function in 0xcafe::BasicCoin - │ · - │ 24 │ assert!(borrow_global(addr).value == 11, 0); - │ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Test was not expected to abort but it aborted with 0 here - │ - │ - │ ────── Storage state at point of failure ────── - │ 0xc0ffee: - │ => key 0xcafe::BasicCoin::Coin { - │ value: 10 - │ } - │ - └────────────────── + ┌── test_mint_10 ────── + │ error[E11001]: test failure + │ ┌─ ./sources/FirstModule.move:24:9 + │ │ + │ 18 │ fun test_mint_10(account: signer) acquires Coin { + │ │ ------------ In this function in 0xcafe::BasicCoin + │ · + │ 24 │ assert!(borrow_global(addr).value == 11, 0); + │ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Test was not expected to abort but it aborted with 0 here + │ + │ + │ ────── Storage state at point of failure ────── + │ 0xc0ffee: + │ => key 0xcafe::BasicCoin::Coin { + │ value: 10 + │ } + └────────────────── ``` * Find a flag that allows you to gather test coverage information, and - then play around with using the `move package coverage` command to look at + then play around with using the `move coverage` command to look at coverage statistics and source coverage.
@@ -383,7 +384,7 @@ implementation of the methods inside [`BasicCoin.move`](./step_4/sources/BasicCo Let's first try building the code using Move package by running the following command in [`step_4/BasicCoin`](./step_4/BasicCoin) folder: ```bash -move package build +move build ``` ### Implementation of methods @@ -409,15 +410,17 @@ move_to(account, Balance { coin: empty_coin }); `mint` method mints coins to a given account. Here we require that `mint` must be approved by the module owner. We enforce this using the assert statement: ``` -assert!(signer::address_of(&module_owner) == MODULE_OWNER, errors::requires_address(ENOT_MODULE_OWNER)); +assert!(signer::address_of(&module_owner) == MODULE_OWNER, ENOT_MODULE_OWNER); ``` Assert statements in Move can be used in this way: `assert!(, );`. This means that if the `` is false, then abort the transaction with ``. Here `MODULE_OWNER` and `ENOT_MODULE_OWNER` are both constants -defined at the beginning of the module. And `errors` module defines common error categories we can use. +defined at the beginning of the module. The standard library's [`error` module] also defines common error categories we can use. It is important to note that Move is transactional in its execution -- so if an [abort](https://move-language.github.io/move/abort-and-assert.html) is raised no unwinding of state needs to be performed, as no changes from that transaction will be persisted to the blockchain. +[`error` module]: https://github.com/move-language/move/blob/main/language/move-stdlib/docs/error.md + We then deposit a coin with value `amount` to the balance of `mint_addr`. ``` deposit(mint_addr, Coin { value: amount }); @@ -473,7 +476,7 @@ take a look at some tools we can use to help us write tests. To get started, run the `package test` command in the [`step_5/BasicCoin`](./step_5/BasicCoin) folder ```bash -move package test +move test ``` You should see something like this: @@ -571,7 +574,7 @@ source ~/.profile ``` ## Step 7: Use the Move prover -Smart contracts deployed on the blockchain may maniputate high-value assets. As a technique that uses strict +Smart contracts deployed on the blockchain may manipulate high-value assets. As a technique that uses strict mathematical methods to describe behavior and reason correctness of computer systems, formal verification has been used in blockchains to prevent bugs in smart contracts. [ The Move prover](https://github.com/move-language/move/blob/main/language/move-prover/doc/user/prover-guide.md) @@ -592,7 +595,7 @@ Informally speaking, the block `spec balance_of {...}` contains the property spe Let's first run the prover using the following command inside [`BasicCoin` directory](./step_7/BasicCoin/): ```bash -move package prove +move prove ``` which outputs the following error information: @@ -627,7 +630,7 @@ The prover basically tells us that we need to explicitly specify the condition u ``` After adding this condition, try running the `prove` command again to confirm that there are no verification errors: ```bash -move package prove +move prove ``` Apart from the abort condition, we also want to define the functional properties. In Step 8, we will give more detailed introduction to the prover by specifying properties for the methods defined the `BasicCoin` module. diff --git a/language/documentation/tutorial/step_2_sol/solution_commands b/language/documentation/tutorial/step_2_sol/solution_commands index 6aa18e3ce1..54ab34115e 100644 --- a/language/documentation/tutorial/step_2_sol/solution_commands +++ b/language/documentation/tutorial/step_2_sol/solution_commands @@ -1,11 +1,11 @@ # Exercise 1 -move package test -g +move test -g # Exercise 2 -move package test --coverage +move test --coverage Followed by: -move package coverage summary -move package coverage summary --summarize-functions -move package coverage source --module BasicCoin +move coverage summary +move coverage summary --summarize-functions +move coverage source --module BasicCoin diff --git a/language/documentation/tutorial/step_4/BasicCoin/sources/BasicCoin.move b/language/documentation/tutorial/step_4/BasicCoin/sources/BasicCoin.move index f3a83d3df9..ad469bcf15 100644 --- a/language/documentation/tutorial/step_4/BasicCoin/sources/BasicCoin.move +++ b/language/documentation/tutorial/step_4/BasicCoin/sources/BasicCoin.move @@ -1,6 +1,5 @@ /// This module defines a minimal Coin and Balance. module NamedAddr::BasicCoin { - use std::errors; use std::signer; /// Address of the owner of this module @@ -31,7 +30,7 @@ module NamedAddr::BasicCoin { /// Initialize this module. public fun mint(module_owner: &signer, mint_addr: address, amount: u64) { // Only the owner of the module can initialize this module - assert!(signer::address_of(module_owner) == MODULE_OWNER, errors::requires_address(ENOT_MODULE_OWNER)); + assert!(signer::address_of(module_owner) == MODULE_OWNER, ENOT_MODULE_OWNER); // Deposit `amount` of tokens to `mint_addr`'s balance deposit(mint_addr, Coin { value: amount }); @@ -52,7 +51,7 @@ module NamedAddr::BasicCoin { fun withdraw(addr: address, amount: u64) : Coin acquires Balance { let balance = balance_of(addr); // balance must be greater than the withdraw amount - assert!(balance >= amount, errors::limit_exceeded(EINSUFFICIENT_BALANCE)); + assert!(balance >= amount, EINSUFFICIENT_BALANCE); let balance_ref = &mut borrow_global_mut(addr).coin.value; *balance_ref = balance - amount; Coin { value: amount } diff --git a/language/documentation/tutorial/step_4_sol/BasicCoin/sources/BasicCoin.move b/language/documentation/tutorial/step_4_sol/BasicCoin/sources/BasicCoin.move index e6678ab9cf..3b41ce5938 100644 --- a/language/documentation/tutorial/step_4_sol/BasicCoin/sources/BasicCoin.move +++ b/language/documentation/tutorial/step_4_sol/BasicCoin/sources/BasicCoin.move @@ -1,6 +1,5 @@ /// This module defines a minimal Coin and Balance. module NamedAddr::BasicCoin { - use std::errors; use std::signer; /// Address of the owner of this module @@ -24,14 +23,14 @@ module NamedAddr::BasicCoin { /// minting or transferring to the account. public fun publish_balance(account: &signer) { let empty_coin = Coin { value: 0 }; - assert!(!exists(signer::address_of(account)), errors::already_published(EALREADY_HAS_BALANCE)); + assert!(!exists(signer::address_of(account)), EALREADY_HAS_BALANCE); move_to(account, Balance { coin: empty_coin }); } /// Mint `amount` tokens to `mint_addr`. Mint must be approved by the module owner. public fun mint(module_owner: &signer, mint_addr: address, amount: u64) acquires Balance { // Only the owner of the module can initialize this module - assert!(signer::address_of(module_owner) == MODULE_OWNER, errors::requires_address(ENOT_MODULE_OWNER)); + assert!(signer::address_of(module_owner) == MODULE_OWNER, ENOT_MODULE_OWNER); // Deposit `amount` of tokens to `mint_addr`'s balance deposit(mint_addr, Coin { value: amount }); @@ -52,14 +51,14 @@ module NamedAddr::BasicCoin { fun withdraw(addr: address, amount: u64) : Coin acquires Balance { let balance = balance_of(addr); // balance must be greater than the withdraw amount - assert!(balance >= amount, errors::limit_exceeded(EINSUFFICIENT_BALANCE)); + assert!(balance >= amount, EINSUFFICIENT_BALANCE); let balance_ref = &mut borrow_global_mut(addr).coin.value; *balance_ref = balance - amount; Coin { value: amount } } /// Deposit `amount` number of tokens to the balance under `addr`. - fun deposit(addr: address, check: Coin) acquires Balance{ + fun deposit(addr: address, check: Coin) acquires Balance { let balance = balance_of(addr); let balance_ref = &mut borrow_global_mut(addr).coin.value; let Coin { value } = check; diff --git a/language/documentation/tutorial/step_5/BasicCoin/sources/BasicCoin.move b/language/documentation/tutorial/step_5/BasicCoin/sources/BasicCoin.move index 024c1c0ffe..46f5d6d645 100644 --- a/language/documentation/tutorial/step_5/BasicCoin/sources/BasicCoin.move +++ b/language/documentation/tutorial/step_5/BasicCoin/sources/BasicCoin.move @@ -1,6 +1,5 @@ /// This module defines a minimal Coin and Balance. module NamedAddr::BasicCoin { - use std::errors; use std::signer; /// Address of the owner of this module @@ -24,14 +23,14 @@ module NamedAddr::BasicCoin { /// minting or transferring to the account. public fun publish_balance(account: &signer) { let empty_coin = Coin { value: 0 }; - assert!(!exists(signer::address_of(account)), errors::already_published(EALREADY_HAS_BALANCE)); + assert!(!exists(signer::address_of(account)), EALREADY_HAS_BALANCE); move_to(account, Balance { coin: empty_coin }); } /// Mint `amount` tokens to `mint_addr`. Mint must be approved by the module owner. public fun mint(module_owner: &signer, mint_addr: address, amount: u64) acquires Balance { // Only the owner of the module can initialize this module - assert!(signer::address_of(module_owner) == MODULE_OWNER, errors::requires_address(ENOT_MODULE_OWNER)); + assert!(signer::address_of(module_owner) == MODULE_OWNER, ENOT_MODULE_OWNER); // Deposit `amount` of tokens to `mint_addr`'s balance deposit(mint_addr, Coin { value: amount }); @@ -52,7 +51,7 @@ module NamedAddr::BasicCoin { fun withdraw(addr: address, amount: u64) : Coin acquires Balance { let balance = balance_of(addr); // balance must be greater than the withdraw amount - assert!(balance >= amount, errors::limit_exceeded(EINSUFFICIENT_BALANCE)); + assert!(balance >= amount, EINSUFFICIENT_BALANCE); let balance_ref = &mut borrow_global_mut(addr).coin.value; *balance_ref = balance - amount; Coin { value: amount } @@ -92,13 +91,13 @@ module NamedAddr::BasicCoin { } #[test(account = @0x1)] - #[expected_failure(abort_code = 518)] // Can specify an abort code + #[expected_failure(abort_code = EALREADY_HAS_BALANCE)] // Can specify an abort code fun publish_balance_already_exists(account: signer) { publish_balance(&account); publish_balance(&account); } - // EXERCISE: Write `balance_dne` test here! + // EXERCISE: Write `balance_of_dne` test here! #[test] #[expected_failure] diff --git a/language/documentation/tutorial/step_5_sol/BasicCoin/sources/BasicCoin.move b/language/documentation/tutorial/step_5_sol/BasicCoin/sources/BasicCoin.move index 53627a8eb2..a6e31ba552 100644 --- a/language/documentation/tutorial/step_5_sol/BasicCoin/sources/BasicCoin.move +++ b/language/documentation/tutorial/step_5_sol/BasicCoin/sources/BasicCoin.move @@ -1,6 +1,5 @@ /// This module defines a minimal Coin and Balance. module NamedAddr::BasicCoin { - use std::errors; use std::signer; /// Address of the owner of this module @@ -24,14 +23,14 @@ module NamedAddr::BasicCoin { /// minting or transferring to the account. public fun publish_balance(account: &signer) { let empty_coin = Coin { value: 0 }; - assert!(!exists(signer::address_of(account)), errors::already_published(EALREADY_HAS_BALANCE)); + assert!(!exists(signer::address_of(account)), EALREADY_HAS_BALANCE); move_to(account, Balance { coin: empty_coin }); } /// Mint `amount` tokens to `mint_addr`. Mint must be approved by the module owner. public fun mint(module_owner: &signer, mint_addr: address, amount: u64) acquires Balance { // Only the owner of the module can initialize this module - assert!(signer::address_of(module_owner) == MODULE_OWNER, errors::requires_address(ENOT_MODULE_OWNER)); + assert!(signer::address_of(module_owner) == MODULE_OWNER, ENOT_MODULE_OWNER); // Deposit `amount` of tokens to `mint_addr`'s balance deposit(mint_addr, Coin { value: amount }); @@ -52,7 +51,7 @@ module NamedAddr::BasicCoin { fun withdraw(addr: address, amount: u64) : Coin acquires Balance { let balance = balance_of(addr); // balance must be greater than the withdraw amount - assert!(balance >= amount, errors::limit_exceeded(EINSUFFICIENT_BALANCE)); + assert!(balance >= amount, EINSUFFICIENT_BALANCE); let balance_ref = &mut borrow_global_mut(addr).coin.value; *balance_ref = balance - amount; Coin { value: amount } @@ -92,7 +91,7 @@ module NamedAddr::BasicCoin { } #[test(account = @0x1)] - #[expected_failure(abort_code = 518)] // Can specify an abort code + #[expected_failure(abort_code = 2)] // Can specify an abort code fun publish_balance_already_exists(account: signer) { publish_balance(&account); publish_balance(&account); diff --git a/language/documentation/tutorial/step_6/BasicCoin/sources/BasicCoin.move b/language/documentation/tutorial/step_6/BasicCoin/sources/BasicCoin.move index 417094f3c6..d7354c6ecc 100644 --- a/language/documentation/tutorial/step_6/BasicCoin/sources/BasicCoin.move +++ b/language/documentation/tutorial/step_6/BasicCoin/sources/BasicCoin.move @@ -1,6 +1,5 @@ /// This module defines a minimal and generic Coin and Balance. module NamedAddr::BasicCoin { - use std::errors; use std::signer; /// Error codes @@ -20,7 +19,7 @@ module NamedAddr::BasicCoin { /// minting or transferring to the account. public fun publish_balance(account: &signer) { let empty_coin = Coin { value: 0 }; - assert!(!exists>(signer::address_of(account)), errors::already_published(EALREADY_HAS_BALANCE)); + assert!(!exists>(signer::address_of(account)), EALREADY_HAS_BALANCE); move_to(account, Balance { coin: empty_coin }); } diff --git a/language/documentation/tutorial/step_7/BasicCoin/sources/BasicCoin.move b/language/documentation/tutorial/step_7/BasicCoin/sources/BasicCoin.move index ace18ab0b3..3a5ec81e3a 100644 --- a/language/documentation/tutorial/step_7/BasicCoin/sources/BasicCoin.move +++ b/language/documentation/tutorial/step_7/BasicCoin/sources/BasicCoin.move @@ -1,6 +1,5 @@ /// This module defines a minimal and generic Coin and Balance. module NamedAddr::BasicCoin { - use std::errors; use std::signer; /// Error codes @@ -20,7 +19,7 @@ module NamedAddr::BasicCoin { /// minting or transferring to the account. public fun publish_balance(account: &signer) { let empty_coin = Coin { value: 0 }; - assert!(!exists>(signer::address_of(account)), errors::already_published(EALREADY_HAS_BALANCE)); + assert!(!exists>(signer::address_of(account)), EALREADY_HAS_BALANCE); move_to(account, Balance { coin: empty_coin }); } diff --git a/language/documentation/tutorial/step_8/BasicCoin/sources/BasicCoin.move b/language/documentation/tutorial/step_8/BasicCoin/sources/BasicCoin.move index adade442ef..d936ca43f3 100644 --- a/language/documentation/tutorial/step_8/BasicCoin/sources/BasicCoin.move +++ b/language/documentation/tutorial/step_8/BasicCoin/sources/BasicCoin.move @@ -1,6 +1,5 @@ /// This module defines a minimal and generic Coin and Balance. module NamedAddr::BasicCoin { - use std::errors; use std::signer; /// Error codes @@ -21,7 +20,7 @@ module NamedAddr::BasicCoin { /// minting or transferring to the account. public fun publish_balance(account: &signer) { let empty_coin = Coin { value: 0 }; - assert!(!exists>(signer::address_of(account)), errors::already_published(EALREADY_HAS_BALANCE)); + assert!(!exists>(signer::address_of(account)), EALREADY_HAS_BALANCE); move_to(account, Balance { coin: empty_coin }); } diff --git a/language/documentation/tutorial/step_8_sol/BasicCoin/sources/BasicCoin.move b/language/documentation/tutorial/step_8_sol/BasicCoin/sources/BasicCoin.move index cad1d3e785..921ffa36c5 100644 --- a/language/documentation/tutorial/step_8_sol/BasicCoin/sources/BasicCoin.move +++ b/language/documentation/tutorial/step_8_sol/BasicCoin/sources/BasicCoin.move @@ -1,6 +1,5 @@ /// This module defines a minimal and generic Coin and Balance. module NamedAddr::BasicCoin { - use std::errors; use std::signer; /// Error codes @@ -20,7 +19,7 @@ module NamedAddr::BasicCoin { public fun publish_balance(account: &signer) { let empty_coin = Coin { value: 0 }; - assert!(!exists>(signer::address_of(account)), errors::already_published(EALREADY_HAS_BALANCE)); + assert!(!exists>(signer::address_of(account)), EALREADY_HAS_BALANCE); move_to(account, Balance { coin: empty_coin }); } diff --git a/language/evm/README.md b/language/evm/README.md index 375bd8dee0..883e3bd883 100644 --- a/language/evm/README.md +++ b/language/evm/README.md @@ -1,11 +1,15 @@ # Move-on-EVM +> NOTE: this tree contains an experimental version of Move which runs on the EVM. The programming model is +> different from regular Move. The examples in this directory do not work with the usual Move +> tools and blockchains. + "Move-on-EVM" is a programming model in Move for EVM. In the current model, *each Move EVM contract has its own isolated address space*. This reflects the setup of the EVM most naturally, where storage between contracts cannot be shared apart from via accessor contract functions. Move EVM contracts use attributes to indicate the usage of structs for storage and events, and for functions to be callable from other contracts. It is expected that there is some codegen of Move from these attributes. For example, functions marked as `callable` have a generated API for cross-contract EVM call and delegate invocations. The module [Evm.move](./stdlib/sources/Evm.move) contains the API of a Move contract to the EVM. It encapsulates access to the transaction context and other EVM builtins This directory contains the following sub-directories: -- [move-to-yul](./sources/move-to-yul) is a cross compiler that compiles Move contracts to the intermediate language Yul. -- [stdlib](./sources/stdlib) is the standard library for Move-on-EVM. -- [examples](./sources/examples) contains multiple Move-on-EVM examples including ERC20, ERC721 and ERC1155. -- [hardhat-examples](./sources/hardhat-examples) is a Hardhat project to demonstrate Move-on-EVM. -- [hardhat-move](./sources/hardhat-move) is a Hardhat plugin to support the Move language. -- [exec-utils](./sources/exec-utils) contains EVM execution utils. +- [move-to-yul](./move-to-yul) is a cross compiler that compiles Move contracts to the intermediate language Yul. +- [stdlib](./stdlib) is the standard library for Move-on-EVM. +- [examples](./examples) contains multiple Move-on-EVM examples including ERC20, ERC721 and ERC1155. +- [hardhat-examples](./hardhat-examples) is a Hardhat project to demonstrate Move-on-EVM. +- [hardhat-move](./hardhat-move) is a Hardhat plugin to support the Move language. +- [exec-utils](./exec-utils) contains EVM execution utils. diff --git a/language/evm/examples/README.md b/language/evm/examples/README.md index fa67872429..1098286dbe 100644 --- a/language/evm/examples/README.md +++ b/language/evm/examples/README.md @@ -11,4 +11,4 @@ This directory contains (a growing set of) examples of "Move-on-EVM", a programm - [ERC1155.move](./sources/ERC1155.move) contains an implementation of ERC1155 which is the standard for multi-tokens. - [TestUniswap.move](./sources/TestUniswap.move) and [TestUniswapLiquidity.move](./sources/TestUniswapLiquidity.move) are the sample client modules of `Uniswap`. -This directory is a Move package. To build the source files, use `move package build`. Moreover, use `move package test` to run the unit tests located in the `tests` directory. +This directory is a Move package. To build the source files, use `move build`. Moreover, use `move test` to run the unit tests located in the `tests` directory. diff --git a/language/evm/exec-utils/src/compile.rs b/language/evm/exec-utils/src/compile.rs index 59f4992f5d..801ef41fb9 100644 --- a/language/evm/exec-utils/src/compile.rs +++ b/language/evm/exec-utils/src/compile.rs @@ -114,13 +114,13 @@ pub fn solc_yul(source: &str, return_optimized_yul: bool) -> Result<(Vec, Op } let yul = if return_optimized_yul { Some( - (&out_str[(start_of_yul.unwrap() + OPTIMIZED_YUL_MARKER.len())..start_of_hex.unwrap()]) + out_str[(start_of_yul.unwrap() + OPTIMIZED_YUL_MARKER.len())..start_of_hex.unwrap()] .trim() .to_string(), ) } else { None }; - let bin = hex::decode(&out_str[(start_of_hex.unwrap() + HEX_OUTPUT_MARKER.len())..].trim())?; + let bin = hex::decode(out_str[(start_of_hex.unwrap() + HEX_OUTPUT_MARKER.len())..].trim())?; Ok((bin, yul)) } diff --git a/language/evm/extract-ethereum-abi/Cargo.toml b/language/evm/extract-ethereum-abi/Cargo.toml index d40acabe04..7ae124f1be 100644 --- a/language/evm/extract-ethereum-abi/Cargo.toml +++ b/language/evm/extract-ethereum-abi/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" authors = ["Diem Association "] description = "Extract Etherem ABI" publish = false -edition = "2018" +edition = "2021" license = "Apache-2.0" [dependencies] diff --git a/language/evm/hardhat-examples/contracts/AsyncEvent/Move.toml b/language/evm/hardhat-examples/contracts/AsyncEvent/Move.toml new file mode 100644 index 0000000000..e0c21d6f0f --- /dev/null +++ b/language/evm/hardhat-examples/contracts/AsyncEvent/Move.toml @@ -0,0 +1,13 @@ +[package] +name = "AsyncEvent" +version = "0.0.0" + +[addresses] +std = "0x1" +Evm = "0x2" +Async = "0x1" + +[dependencies] +EvmStdlib = { local = "../../../stdlib" } +MoveStdlib = { local = "../../../../move-stdlib" } +MoveAsyncLib = { local = "../../../../extensions/async/move-async-lib" } diff --git a/language/evm/hardhat-examples/contracts/AsyncEvent/sources/AccountStateMachine.move b/language/evm/hardhat-examples/contracts/AsyncEvent/sources/AccountStateMachine.move new file mode 100644 index 0000000000..01fd6c13b7 --- /dev/null +++ b/language/evm/hardhat-examples/contracts/AsyncEvent/sources/AccountStateMachine.move @@ -0,0 +1,102 @@ +#[actor] +/// This is an instance of the Account example using an explicit state machine and one-way message passing. +/// +/// In this example, we need to manage rpc state explicitly, remembering any outstanding transfers in the +/// actors state. This creates a little more code, but also is somehow more transparent and true to the +/// transactional semantics of Move. This version implements an additional `cleanup` message which cancels +/// pending transactions over a certain age. +module 0x3::AccountStateMachine { + + use Async::Actor::{self, virtual_time}; + use std::vector; + + const MAX: u64 = 43; + const MAX_TRANSFER_AGE: u128 = 100000000; + + #[state] + struct Account { + value: u64, + xfer_id_counter: u64, + pending: vector + } + + struct PendingTransfer has drop { + xfer_id: u64, + amount: u64, + initiated_at: u128, + } + + #[init] + fun init(): Account { + Account{value: 0, xfer_id_counter: 0, pending: vector::empty()} + } + + #[message] + fun deposit(this: &mut Account, v: u64) { + assert!(MAX - this.value >= v, 1); + this.value = this.value + v; + } + + #[message] + fun withdraw(this: &mut Account, v: u64) { + assert!(this.value >= v, 2); + this.value = this.value - v; + } + + #[message] + fun xfer(this: &mut Account, dest: address, v: u64) { + // Do not initiate the transfer if there are not enough funds + // Remove this assert to test event + // assert!(this.value >= v, 1); + let xfer_id = new_xfer_id(this); + vector::push_back(&mut this.pending, PendingTransfer{xfer_id, amount: v, initiated_at: virtual_time()}); + // Call into a special version of deposit which calls us back once done. + send_xfer_deposit(dest, v, self(), xfer_id); + } + + fun new_xfer_id(this: &mut Account): u64 { + let counter = &mut this.xfer_id_counter; + let xfer_id = *counter; + *counter = *counter + 1; + xfer_id + } + + #[message] + fun xfer_deposit(this: &mut Account, v: u64, caller_: address, xfer_id: u64) { + deposit(this, v); + send_xfer_finish(caller_, xfer_id); + } + + #[message] + fun xfer_finish(this: &mut Account, xfer_id: u64) { + let i = find_xfer(this, xfer_id); + let amount = vector::borrow(&this.pending, i).amount; + vector::remove(&mut this.pending, i); + withdraw(this, amount) + } + + fun find_xfer(this: &Account, xfer_id: u64): u64 { + let pending = &this.pending; + let i = 0; + while (i < vector::length(pending) && vector::borrow(pending, i).xfer_id != xfer_id) { + i = i + 1; + }; + assert!(i < vector::length(pending), 3); + i + } + + #[message] + /// A periodical cleanup which removes dated pending transfers. + fun cleanup(this: &mut Account) { + let pending = &mut this.pending; + let i = 0; + while (i < vector::length(pending)) { + let p = vector::borrow(pending, i); + if (virtual_time() - p.initiated_at >= MAX_TRANSFER_AGE) { + vector::remove(pending, i); + } else { + i = i + 1; + } + } + } +} diff --git a/language/evm/hardhat-examples/test/AsyncEvent.test.js b/language/evm/hardhat-examples/test/AsyncEvent.test.js new file mode 100644 index 0000000000..00f319b907 --- /dev/null +++ b/language/evm/hardhat-examples/test/AsyncEvent.test.js @@ -0,0 +1,22 @@ +const { expect } = require("chai"); +const { ethers } = require("hardhat"); + +const make_test = function (contract_name) { + return function () { + before(async function () { + this.Event = await ethers.getContractFactory(contract_name); + this.event = await this.Event.deploy(); + await this.event.deployed(); + }); + it("AsyncEvent_xfer_deposit", async function () { + const tx = this.event.xfer(this.event.address,42); + await expect(tx).to.emit(this.event, 'Xfer_deposit').withArgs(this.event.address, 0x0b32e0fa, 42, this.event.address, 0); + }); + it("AsyncEvent_xfer_finish", async function () { + const tx = this.event.xfer_deposit(42,this.event.address,1); + await expect(tx).to.emit(this.event, 'Xfer_finish').withArgs(this.event.address, 0xb8229d65, 1); + }); + } +}; + +describe("Async Event (the Async Move contract)", make_test('AsyncEvent')); diff --git a/language/evm/hardhat-move/src/index.ts b/language/evm/hardhat-move/src/index.ts index a8b5eb0b7e..1784b03017 100644 --- a/language/evm/hardhat-move/src/index.ts +++ b/language/evm/hardhat-move/src/index.ts @@ -153,7 +153,7 @@ async function locateMoveExecutablePath(): Promise> { class MoveBuildError { exec_err: ChildProcess.ExecException; - // TODO: right now, `move package build` outputs its build errors to stdout instead of stderr. + // TODO: right now, `move build` outputs its build errors to stdout instead of stderr. // This may not be ideal and we may want to fix it and then revisit the error definition here. stdout: string; stderr: string; @@ -166,7 +166,7 @@ class MoveBuildError { } async function movePackageBuild(movePath: string, packagePath: string): Promise> { - let cmd = `${movePath} package build --path ${packagePath} --arch ethereum`; + let cmd = `${movePath} build --path ${packagePath} --arch ethereum`; let [e, stdout, stderr] = await executeChildProcess(cmd); diff --git a/language/evm/move-ethereum-abi/Cargo.toml b/language/evm/move-ethereum-abi/Cargo.toml index c837746ad9..329e78cec5 100644 --- a/language/evm/move-ethereum-abi/Cargo.toml +++ b/language/evm/move-ethereum-abi/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" authors = ["Diem Association "] description = "Move Ethereum ABI" publish = false -edition = "2018" +edition = "2021" license = "Apache-2.0" [dependencies] diff --git a/language/evm/move-to-yul/Cargo.toml b/language/evm/move-to-yul/Cargo.toml index 34f28a7dcf..40b2798ec6 100644 --- a/language/evm/move-to-yul/Cargo.toml +++ b/language/evm/move-to-yul/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" authors = ["Diem Association "] description = "Move Solidity Generator" publish = false -edition = "2018" +edition = "2021" license = "Apache-2.0" [dependencies] diff --git a/language/evm/move-to-yul/src/abi_move_metadata.rs b/language/evm/move-to-yul/src/abi_move_metadata.rs index d709309752..9d1b42908c 100644 --- a/language/evm/move-to-yul/src/abi_move_metadata.rs +++ b/language/evm/move-to-yul/src/abi_move_metadata.rs @@ -26,7 +26,7 @@ pub(crate) fn generate_abi_move_metadata(ctx: &Context, receive: bool, fallback: let st_env = ctx.env.get_struct(key.to_qualified_id()); event_map.insert( st_env.get_identifier().unwrap().to_string(), - from_event_sig(ctx.event_signature_map.borrow().get(&key).unwrap()), + from_event_sig(ctx.event_signature_map.borrow().get(key).unwrap()), ); } @@ -34,7 +34,7 @@ pub(crate) fn generate_abi_move_metadata(ctx: &Context, receive: bool, fallback: let mut func_map = BTreeMap::new(); for (key, (solidity_sig, attr)) in ctx.callable_function_map.borrow().iter() { let fun = ctx.env.get_function(key.to_qualified_id()); - let abi_sig = from_solidity_sig(&solidity_sig, Some(*attr), "function"); + let abi_sig = from_solidity_sig(solidity_sig, Some(*attr), "function"); func_map.insert(fun.get_identifier().to_string(), abi_sig); } diff --git a/language/evm/move-to-yul/src/attributes.rs b/language/evm/move-to-yul/src/attributes.rs index 14c12724f0..3a82877a4a 100644 --- a/language/evm/move-to-yul/src/attributes.rs +++ b/language/evm/move-to-yul/src/attributes.rs @@ -29,6 +29,12 @@ const ENCODE_ATTR: &str = "encode"; const ENCODE_PACKED_ATTR: &str = "encode_packed"; const ABI_STRUCT_ATTR: &str = "abi_struct"; +// For async move contracts +const ACTOR_ATTR: &str = "actor"; +const STATE_ATTR: &str = "state"; +const INIT_ATTR: &str = "init"; +const MESSAGE_ATTR: &str = "message"; + #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub(crate) enum FunctionAttribute { Payable, @@ -141,19 +147,13 @@ pub fn has_attr(env: &GlobalEnv, attrs: &[Attribute], name: &str, simple_flag: b true } }; - attrs.iter().any(|a| match a { - Attribute::Apply(_, s, args) - if is_empty(args) && env.symbol_pool().string(*s).as_str() == name => - { - true - } - _ => false, - }) + attrs.iter().any(|a| matches!(a, Attribute::Apply(_, s, args) if is_empty(args) && env.symbol_pool().string(*s).as_str() == name)) } /// Check whether the module has a `#[evm_contract]` attribute. pub fn is_evm_contract_module(module: &ModuleEnv) -> bool { has_attr(module.env, module.get_attributes(), CONTRACT_ATTR, false) + || has_attr(module.env, module.get_attributes(), ACTOR_ATTR, false) } /// Check whether the module has a `#[evm_arith]` attribute. @@ -168,7 +168,7 @@ pub fn is_storage_struct(str: &StructEnv) -> bool { str.get_attributes(), STORAGE_ATTR, false, - ) + ) || has_attr(str.module_env.env, str.get_attributes(), STATE_ATTR, false) } /// Check whether the struct has a `#[event]` attribute. @@ -183,12 +183,18 @@ pub fn is_callable_fun(fun: &FunctionEnv<'_>) -> bool { fun.get_attributes(), CALLABLE_ATTR, false, + ) || has_attr( + fun.module_env.env, + fun.get_attributes(), + MESSAGE_ATTR, + false, ) } -/// Check whether the function has a `#[create]` attribute. +/// Check whether the function has a `#[create]` or `#[init]` attribute. pub fn is_create_fun(fun: &FunctionEnv<'_>) -> bool { has_attr(fun.module_env.env, fun.get_attributes(), CREATE_ATTR, false) + || has_attr(fun.module_env.env, fun.get_attributes(), INIT_ATTR, false) } /// Check whether the function has a `#[payable]` attribute. diff --git a/language/evm/move-to-yul/src/context.rs b/language/evm/move-to-yul/src/context.rs index 2b717349e3..231b6db011 100644 --- a/language/evm/move-to-yul/src/context.rs +++ b/language/evm/move-to-yul/src/context.rs @@ -292,7 +292,7 @@ impl<'a> Context<'a> { } }; // Identify special functions. - let constructor = self.identify_function(module, is_create_fun, "#[create]"); + let constructor = self.identify_function(module, is_create_fun, "#[create]/#[init]"); let receive = self.identify_function(module, is_receive_fun, "#[receive]"); let fallback = self.identify_function(module, is_fallback_fun, "#[fallback]"); @@ -354,8 +354,7 @@ impl<'a> Context<'a> { fn get_target_structs(&self, p: impl Fn(&StructEnv) -> bool) -> Vec> { self.env .get_modules() - .map(|m| m.into_structs().filter(|f| p(f))) - .flatten() + .flat_map(|m| m.into_structs().filter(|f| p(f))) .collect() } @@ -563,8 +562,11 @@ impl<'a> Context<'a> { match ty { Primitive(p) => match p { U8 => "u8".to_string(), + // U16 => "u16".to_string(), + // U32 => "u32".to_string(), U64 => "u64".to_string(), U128 => "u128".to_string(), + // U256 => "u256".to_string(), Num => "num".to_string(), Address => "address".to_string(), Signer => "signer".to_string(), @@ -608,7 +610,7 @@ impl<'a> Context<'a> { .get_local_name(idx) .display(target.symbol_pool()) .to_string() - .replace("#", "_") + .replace('#', "_") } /// Make name for a result. @@ -770,7 +772,7 @@ impl<'a> Context<'a> { U128 => 16, // TODO: optimize for 20 bytes? Then we need primitives like LoadU160 etc. Address | Signer => 32, - Num | Range | EventStore => { + Num | Range | EventStore | U16 | U32 | U256 => { panic!("unexpected field type") } }, diff --git a/language/evm/move-to-yul/src/dispatcher_generator.rs b/language/evm/move-to-yul/src/dispatcher_generator.rs index 64c9e5be29..2ecc93d8b8 100644 --- a/language/evm/move-to-yul/src/dispatcher_generator.rs +++ b/language/evm/move-to-yul/src/dispatcher_generator.rs @@ -261,8 +261,8 @@ impl Generator { /// Generate optional receive function. fn optional_receive(&mut self, ctx: &Context, receive: &Option>) -> bool { if let Some(receive) = receive { - ctx.check_no_generics(&receive); - if !attributes::is_payable_fun(&receive) { + ctx.check_no_generics(receive); + if !attributes::is_payable_fun(receive) { ctx.env .error(&receive.get_loc(), "receive function must be payable") } @@ -309,8 +309,8 @@ impl Generator { fallback: &Option>, ) { if let Some(fallback) = fallback { - ctx.check_no_generics(&fallback); - if !attributes::is_payable_fun(&fallback) { + ctx.check_no_generics(fallback); + if !attributes::is_payable_fun(fallback) { self.generate_call_value_check(ctx, REVERT_ERR_NON_PAYABLE_FUN); } let fun_id = &fallback @@ -560,7 +560,7 @@ impl Generator { ); }); head_pos += ty_size; - let memory_func = ctx.memory_store_builtin_fun(&move_ty); + let memory_func = ctx.memory_store_builtin_fun(move_ty); if local_typ_var.len() == 1 { gen.call_builtin( ctx, @@ -1454,7 +1454,7 @@ impl Generator { { let is_static = ty.is_static(); let local_typ_var = vec![ret_var[stack_pos].clone()]; - let memory_func = ctx.memory_load_builtin_fun(&move_ty); + let memory_func = ctx.memory_load_builtin_fun(move_ty); if local_typ_var.len() == 1 { emitln!( ctx.writer, @@ -1474,7 +1474,7 @@ impl Generator { ctx, &ty.clone(), &SignatureDataLocation::Memory, - &move_ty, + move_ty, sub_option.clone() ), local_typ_var[0].clone() @@ -1488,7 +1488,7 @@ impl Generator { ctx, &ty.clone(), &SignatureDataLocation::Memory, - &move_ty, + move_ty, sub_option.clone() ), local_typ_var[0].clone(), @@ -1507,7 +1507,7 @@ impl Generator { ctx, &ty.clone(), &SignatureDataLocation::Memory, - &move_ty, + move_ty, sub_option.clone() ), local_typ_var[0].clone() diff --git a/language/evm/move-to-yul/src/events.rs b/language/evm/move-to-yul/src/events.rs index 3845f46e9c..6353be5b07 100644 --- a/language/evm/move-to-yul/src/events.rs +++ b/language/evm/move-to-yul/src/events.rs @@ -21,7 +21,7 @@ use move_model::{ ty::Type, }; use move_stackless_bytecode::function_target_pipeline::FunctionVariant; -use sha3::{Digest, Keccak256}; +use sha3::{Digest, Keccak256, Sha3_256}; pub(crate) const COMPATIBILITY_ERROR: &str = "event signature is not compatible with the move struct"; @@ -186,6 +186,173 @@ impl EventSignature { } } +/// Generate event emit functions for send_ in async move contracts +/// example: the function send_foo(actor: address, args) will emit an ethereum event +/// Foo(actor, message_hash, args) where encoding follows the ethereum standard +/// TODO: add a sequence number to the event to help perform deduplication on the listener side +pub(crate) fn define_emit_fun_for_send( + gen: &mut FunctionGenerator, + ctx: &Context, + event_sig: &EventSignature, + fun_id: &QualifiedInstId, +) { + let fun = ctx.env.get_function(fun_id.to_qualified_id()); + let target = &ctx.targets.get_target(&fun, &FunctionVariant::Baseline); + + // Emit function header + let params = (0..target.get_parameter_count()).map(|idx| ctx.make_local_name(target, idx)); + let params_str = params.clone().join(","); + let params_vec = params.collect_vec(); + + let mut local_name_idx = target.get_parameter_count(); + + emit!( + ctx.writer, + "function {}({}) ", + ctx.make_function_name(fun_id), + params_str + ); + + // Generate the function body + ctx.emit_block(|| { + let signature_types = &event_sig.para_types; + let topic_0_var = ctx.make_local_name(target, local_name_idx); + local_name_idx += 1; + let event_sig_str = event_sig.to_string(); + let topic_0_hash = format!("0x{:x}", Keccak256::digest(event_sig_str.as_bytes())); + + emitln!(ctx.writer, "let {} := {}", topic_0_var, topic_0_hash); + + // Compute the message hash following the logic in move_compiler::attr_derivation::async_deriver::message_hash + // message_hash is the first 8 bytes of Sha3_256::digest(address::module_name::foo) + // example: 0x00000000000000000000000000000003::AccountStateMachine::deposit + let message_str = format!( + "0x{}::{}", + fun.module_env.self_address(), + fun.get_full_name_str().replace("send_", "") + ); + let hash_bytes = Sha3_256::digest(message_str.as_bytes()); + let message_hash_str = &format!("0x{:x}", hash_bytes)[0..10]; + let message_hash_var = ctx.make_local_name(target, local_name_idx); + local_name_idx += 1; + emitln!( + ctx.writer, + "let {} := {}", + message_hash_var, + message_hash_str + ); + + let mut indexed_paras = vec![]; + let mut indexed_vars = vec![topic_0_var]; + let mut unindexed_paras = vec![]; + let mut unindexed_vars = vec![]; + + // For async move, there is no index for any parameters + // TODO: consider index receipient address and hash_messages by default + // TODO: consider add a sig to the attribute #[message] to specify index other parameters, e.g. + // #message[sig=b"xfer(address indexed, address indexed, uint128 indexed)] + for (i, (_, solidity_ty, move_ty, indexed_flag, _)) in signature_types.iter().enumerate() { + let mut var = if i == 0 { + params_vec.get(0).unwrap().to_string() + } else if i == 1 { + message_hash_var.clone() + } else { + params_vec.get(i - 1).unwrap().to_string() + }; + + if *indexed_flag { + indexed_paras.push((solidity_ty.clone(), move_ty.clone())); + if !solidity_ty.is_value_type() { + // for non-value type + let new_var = ctx.make_local_name(target, local_name_idx); + local_name_idx += 1; + emitln!( + ctx.writer, + "let {} := {}({})", + new_var, + gen.parent.generate_packed_hashed( + ctx, + vec![solidity_ty.clone()], + vec![SignatureDataLocation::Memory], + vec![move_ty.clone()] + ), + var + ); + var = new_var; + } + indexed_vars.push(var.clone()); + } else { + unindexed_paras.push((solidity_ty.clone(), move_ty.clone())); + unindexed_vars.push(var.clone()); + } + } + + ctx.emit_block(|| { + let pos_var = ctx.make_local_name(target, local_name_idx); + local_name_idx += 1; + let end_var = ctx.make_local_name(target, local_name_idx); + local_name_idx += 1; + emitln!( + ctx.writer, + "let {} := mload({})", + pos_var, + substitute_placeholders("${MEM_SIZE_LOC}").unwrap() + ); + // Create dummy signature location + let sig_para_locs = vec![SignatureDataLocation::Memory; unindexed_paras.len()]; + let para_types = unindexed_paras + .iter() + .map(|(_, move_ty)| move_ty.clone()) + .collect_vec(); + let sig_para_vec = unindexed_paras + .iter() + .map(|(solidity_ty, _)| solidity_ty.clone()) + .collect_vec(); + // Generate encoding function for unindexed parameters + let encode_unindexed = gen.parent.generate_abi_tuple_encoding( + ctx, + sig_para_vec, + sig_para_locs, + para_types, + ); + let unindexed_str = if !unindexed_vars.is_empty() { + format!(", {}", unindexed_vars.join(",")) + } else { + "".to_string() + }; + emitln!( + ctx.writer, + "let {} := {}({}{})", + end_var, + encode_unindexed, + pos_var, + unindexed_str + ); + // Generate the code to call log opcode + let indexed_str = if !indexed_vars.is_empty() { + format!(", {}", indexed_vars.join(",")) + } else { + "".to_string() + }; + emitln!( + ctx.writer, + "log{}({}, sub({}, {}){})", + event_sig.indexed_count, + pos_var, + end_var, + pos_var, + indexed_str + ); + emitln!( + ctx.writer, + "mstore({}, {})", + substitute_placeholders("${MEM_SIZE_LOC}").unwrap(), + end_var + ); + }); + }); +} + /// Generate emit functions pub(crate) fn define_emit_fun( gen: &mut FunctionGenerator, diff --git a/language/evm/move-to-yul/src/evm_transformation.rs b/language/evm/move-to-yul/src/evm_transformation.rs index 66cb7a5f53..7e52b69c08 100644 --- a/language/evm/move-to-yul/src/evm_transformation.rs +++ b/language/evm/move-to-yul/src/evm_transformation.rs @@ -28,8 +28,9 @@ impl FunctionTargetProcessor for EvmTransformationProcessor { fn process( &self, _targets: &mut FunctionTargetsHolder, - func_env: &FunctionEnv<'_>, + func_env: &FunctionEnv, mut data: FunctionData, + _scc_opt: Option<&[FunctionEnv]>, ) -> FunctionData { if func_env.is_native() || func_env.is_intrinsic() { return data; diff --git a/language/evm/move-to-yul/src/functions.rs b/language/evm/move-to-yul/src/functions.rs index 7fb78bee00..47b319180f 100644 --- a/language/evm/move-to-yul/src/functions.rs +++ b/language/evm/move-to-yul/src/functions.rs @@ -43,11 +43,13 @@ impl<'a> FunctionGenerator<'a> { let fun = &ctx.env.get_function(fun_id.to_qualified_id()); // TODO: change back to is_native_or_intrinsic if we decide to implement // intrinsic functions (such as reverse, contains, is_empty) in the Vector module as well - if fun.is_native() { + // TODO: create a compilation flag to gate "send_" + if fun.is_native() || fun.get_full_name_str().contains("send_") { // Special treatment for native functions, which have custom generators. ctx.native_funs.gen_native_function(self, ctx, fun_id); return; } + let target = &ctx.targets.get_target(fun, &FunctionVariant::Baseline); // Emit function header @@ -341,14 +343,16 @@ impl<'a> FunctionGenerator<'a> { // Move function call Function(m, f, inst) => { print_loc(); - self.move_call( - ctx, - target, - dest, - m.qualified(*f) - .instantiate(Type::instantiate_slice(inst, &fun_id.inst)), - srcs.iter().map(local), - ) + let fun_id = m + .qualified(*f) + .instantiate(Type::instantiate_slice(inst, &fun_id.inst)); + let fun = &ctx.env.get_function(fun_id.to_qualified_id()); + if fun.get_name_string().contains("send__") + || fun.get_name_string().contains("bcs::to_bytes") + { + return; + } + self.move_call(ctx, target, dest, fun_id, srcs.iter().map(local)) } // Packing and unpacking of structs @@ -558,9 +562,12 @@ impl<'a> FunctionGenerator<'a> { | EventStoreDiverge | OpaqueCallBegin(_, _, _) | OpaqueCallEnd(_, _, _) + | Uninit | Havoc(_) | Stop - | TraceGlobalMem(_) => {} + | TraceGlobalMem(_) + | CastU16 + | CastU32 => {} } } @@ -609,6 +616,9 @@ impl<'a> FunctionGenerator<'a> { format!("0x{}", a.to_str_radix(16)) } Constant::ByteArray(_) => "".to_string(), + Constant::AddressArray(_) => "".to_string(), + Constant::Vector(_) => "".to_string(), + Constant::U16(_) | Constant::U32(_) => panic!("unexpected field type"), }; if !val_str.is_empty() { emitln!(ctx.writer, "{} := {}", dest, val_str); diff --git a/language/evm/move-to-yul/src/lib.rs b/language/evm/move-to-yul/src/lib.rs index 6d9e134fb0..ae577e1d7a 100644 --- a/language/evm/move-to-yul/src/lib.rs +++ b/language/evm/move-to-yul/src/lib.rs @@ -31,11 +31,11 @@ use codespan_reporting::{ diagnostic::Severity, term::termcolor::{ColorChoice, StandardStream, WriteColor}, }; -use move_compiler::shared::PackagePaths; +use move_compiler::{shared::PackagePaths, Flags}; use move_core_types::metadata::Metadata; use move_model::{ model::GlobalEnv, options::ModelBuilderOptions, parse_addresses_from_options, - run_model_builder_with_options, + run_model_builder_with_options_and_compilation_flags, }; use std::fs; @@ -49,7 +49,7 @@ pub fn run_to_yul_errors_to_stderr(options: Options) -> anyhow::Result<()> { pub fn run_to_yul(error_writer: &mut W, mut options: Options) -> anyhow::Result<()> { // Run the model builder. let addrs = parse_addresses_from_options(options.named_address_mapping.clone())?; - let env = run_model_builder_with_options( + let env = run_model_builder_with_options_and_compilation_flags( vec![PackagePaths { name: None, paths: options.sources.clone(), @@ -61,6 +61,7 @@ pub fn run_to_yul(error_writer: &mut W, mut options: Options) -> named_address_map: addrs, }], ModelBuilderOptions::default(), + Flags::empty().set_flavor("async"), )?; // If the model contains any errors, report them now and exit. check_errors( @@ -101,7 +102,7 @@ pub fn run_to_abi_metadata( ) -> anyhow::Result> { // Run the model builder. let addrs = parse_addresses_from_options(options.named_address_mapping.clone())?; - let env = run_model_builder_with_options( + let env = run_model_builder_with_options_and_compilation_flags( vec![PackagePaths { name: None, paths: options.sources.clone(), @@ -113,6 +114,7 @@ pub fn run_to_abi_metadata( named_address_map: addrs, }], ModelBuilderOptions::default(), + Flags::empty().set_flavor("async"), )?; // If the model contains any errors, report them now and exit. check_errors( diff --git a/language/evm/move-to-yul/src/native_functions.rs b/language/evm/move-to-yul/src/native_functions.rs index 88eab32c42..453897c7dc 100644 --- a/language/evm/move-to-yul/src/native_functions.rs +++ b/language/evm/move-to-yul/src/native_functions.rs @@ -83,6 +83,25 @@ impl NativeFunctions { ) } } + } else if fun.get_full_name_str().contains("send_") + && attributes::has_attr( + fun.module_env.env, + fun.module_env.get_attributes(), + "actor", + false, + ) + { + let fun_name = fun.get_full_name_str(); + let mut st_name = String::from(&fun_name[fun_name.find("send_").unwrap() + 5..]); + st_name.replace_range(0..1, &st_name[0..1].to_uppercase()); + let ev_signature_map = ctx.event_signature_map.borrow(); + for (st_id, sig) in ev_signature_map.iter() { + let st_env = ctx.env.get_struct(st_id.to_qualified_id()); + if st_name == st_env.get_name().display(st_env.symbol_pool()).to_string() { + events::define_emit_fun_for_send(gen, ctx, sig, fun_id); + break; + } + } } else if attributes::is_decode(fun) { self.define_decode_fun(gen, ctx, fun_id, attributes::extract_decode_signature(fun)); } else if attributes::is_encode(fun) { @@ -164,6 +183,7 @@ impl NativeFunctions { fn define_evm_functions(&mut self, ctx: &Context) { // TODO: may want to have symbolic representation of addr (which is 'Eth') let evm = &self.find_module(ctx, "0x2", "Evm"); + let async_actor_lib = &self.find_module(ctx, "0x1", "Actor"); self.define(ctx, evm, "sign", |_, ctx: &Context, _| { emitln!( @@ -185,6 +205,31 @@ impl NativeFunctions { ); }); + self.define(ctx, async_actor_lib, "self", |_, ctx: &Context, _| { + emitln!( + ctx.writer, + "\ +() -> addr { + addr := address() +}" + ); + }); + + self.define( + ctx, + async_actor_lib, + "virtual_time", + |_, ctx: &Context, _| { + emitln!( + ctx.writer, + "\ +() -> virtual_time { + virtual_time := timestamp() +}" + ); + }, + ); + self.define(ctx, evm, "abort_with", |gen, ctx: &Context, _| { emitln!( ctx.writer, diff --git a/language/evm/move-to-yul/src/solidity_ty.rs b/language/evm/move-to-yul/src/solidity_ty.rs index 56b608bf22..25190968c7 100644 --- a/language/evm/move-to-yul/src/solidity_ty.rs +++ b/language/evm/move-to-yul/src/solidity_ty.rs @@ -337,7 +337,7 @@ impl SolidityType { U128 => SolidityType::Primitive(SolidityPrimitiveType::Uint(128)), Address => SolidityType::Primitive(SolidityPrimitiveType::Address(false)), Signer => SolidityType::Primitive(SolidityPrimitiveType::Address(false)), - Num | Range | EventStore => { + Num | Range | EventStore | U16 | U32 | U256 => { panic!("unexpected field type") } }, @@ -398,7 +398,7 @@ impl SolidityType { let error_msg = "illegal type name"; return Err(anyhow!(error_msg)); } - ctx.check_or_create_struct_abi(&trimmed_ty_str) + ctx.check_or_create_struct_abi(trimmed_ty_str) } } diff --git a/language/evm/move-to-yul/src/storage.rs b/language/evm/move-to-yul/src/storage.rs index 4832fb5a17..0643afc2ca 100644 --- a/language/evm/move-to-yul/src/storage.rs +++ b/language/evm/move-to-yul/src/storage.rs @@ -379,7 +379,8 @@ impl Generator { ); // Skip the existence flag and create a pointer. - let make_ptr = self.call_builtin_str( + + self.call_builtin_str( ctx, YulFunction::MakePtr, vec![ @@ -387,8 +388,7 @@ impl Generator { format!("add({}, ${{RESOURCE_EXISTS_FLAG_SIZE}})", base_offset), ] .into_iter(), - ); - make_ptr + ) } /// Returns an expression for checking whether a resource exists. diff --git a/language/evm/move-to-yul/src/vectors.rs b/language/evm/move-to-yul/src/vectors.rs index df3fe9f41d..551330d5b9 100644 --- a/language/evm/move-to-yul/src/vectors.rs +++ b/language/evm/move-to-yul/src/vectors.rs @@ -1051,7 +1051,7 @@ fn define_destroy_empty_fun( /// Generate equality method for the vector type. pub(crate) fn equality_fun(gen: &mut Generator, ctx: &Context, ty: &Type) { - let elem_type = get_elem_type(&ty).unwrap(); + let elem_type = get_elem_type(ty).unwrap(); if ctx.type_allocates_memory(&elem_type) { emitln!( ctx.writer, diff --git a/language/evm/move-to-yul/tests/AccountStateMachine.exp b/language/evm/move-to-yul/tests/AccountStateMachine.exp new file mode 100644 index 0000000000..60d877df09 --- /dev/null +++ b/language/evm/move-to-yul/tests/AccountStateMachine.exp @@ -0,0 +1,1138 @@ +/* ======================================= + * Generated by Move-To-Yul compiler v0.0 + * ======================================= */ + + +object "A3_AccountStateMachine" { + code { + mstore(0, memoryguard(160)) + let $new_value := A3_AccountStateMachine_init() + { + let $base_offset := $MakeTypeStorageBase(0, 0x330750a9, address()) + if $AlignedStorageLoad($base_offset) { + $AbortBuiltin() + } + $AlignedStorageStore($base_offset, true) + { + let $dst := add($base_offset, 32) + let $src := $new_value + { + let $linked_src_37500119 := mload(add($src, 0)) + let $linked_dst_37500119 := $NewLinkedStorageBase(0x23c34d7) + let $size_37500119 := $MemoryLoadU64($linked_src_37500119) + let $data_size_37500119 := mul($size_37500119, 32) + $AlignedStorageStore($linked_dst_37500119, mload($linked_src_37500119)) + let $data_src_37500119 := add($linked_src_37500119, 32) + let $data_dst_37500119 := add($linked_dst_37500119, 32) + for { let $offs_37500119 := 0 } lt($offs_37500119, $data_size_37500119) { $offs_37500119 := add($offs_37500119, 32)} { + { + let $linked_src_1341933877 := mload(add($offs_37500119, $data_src_37500119)) + let $linked_dst_1341933877 := $NewLinkedStorageBase(0x4ffc4935) + $AlignedStorageStore(add($linked_dst_1341933877, 0), mload(add($linked_src_1341933877, 0))) + $Free($linked_src_1341933877, 32) + $AlignedStorageStore(add($data_dst_37500119, $offs_37500119), $linked_dst_1341933877) + } + $Free($linked_src_37500119, add($data_size_37500119, 32)) + } + $AlignedStorageStore(add($dst, 0), $linked_dst_37500119) + } + $AlignedStorageStore(add($dst, 32), mload(add($src, 32))) + $Free($src, 48) + } + } + codecopy(0, dataoffset("A3_AccountStateMachine_deployed"), datasize("A3_AccountStateMachine_deployed")) + return(0, datasize("A3_AccountStateMachine_deployed")) + function A3_AccountStateMachine_init() -> $result { + let $t0, $t1, $t2, $t3 + // $t0 := 0 + $t0 := 0 + // $t1 := 0 + $t1 := 0 + // $t2 := vector::empty() + $t2 := A1_vector_empty$A3_AccountStateMachine_PendingTransfer$() + // $t3 := pack AccountStateMachine::Account($t0, $t1, $t2) + { + let $mem := $Malloc(48) + $MemoryStoreU64(add($mem, 32), $t0) + $MemoryStoreU64(add($mem, 40), $t1) + $MemoryStoreU256(add($mem, 0), $t2) + $t3 := $mem + } + // return $t3 + $result := $t3 + } + + function A1_vector_empty$A3_AccountStateMachine_PendingTransfer$() -> vector { + vector := $Malloc(96) + $MemoryStoreU64(add(vector, 8), 2) + } + function $Abort(code) { + mstore(0, code) + revert(24, 8) // TODO: store code as a string? + } + function $AbortBuiltin() { + $Abort(sub(0, 1)) + } + function $Malloc(size) -> offs { + offs := mload(0) + // pad to word size + mstore(0, add(offs, shl(5, shr(5, add(size, 31))))) + } + function $Free(offs, size) { + } + function $MaskForSize(size) -> mask { + mask := sub(shl(shl(3, size), 1), 1) + } + function $MemoryLoadBytes(offs, size) -> val { + // Lower bit where the value in the higher bytes ends + let bit_end := shl(3, sub(32, size)) + val := shr(bit_end, mload(offs)) + } + function $MemoryStoreBytes(offs, size, val) { + let bit_end := shl(3, sub(32, size)) + let mask := shl(bit_end, $MaskForSize(size)) + mstore(offs, or(and(mload(offs), not(mask)), shl(bit_end, val))) + } + function $StorageKey(group, word) -> key { + mstore(32, word) + mstore(64, shl(224, group)) + key := keccak256(32, 36) + } + function $MakeTypeStorageBase(category, type_hash, id) -> offs { + offs := or(shl(252, category), or(shl(220, type_hash), shl(60, id))) + } + function $NewLinkedStorageBase(type_hash) -> offs { + let key := $StorageKey(1, 1) + let handle := sload(key) + sstore(key, add(handle, 1)) + offs := $MakeTypeStorageBase(1, type_hash, handle) + } + function $MemoryLoadU64(offs) -> val { + val := $MemoryLoadBytes(offs, 8) + } + function $MemoryStoreU64(offs, val) { + $MemoryStoreBytes(offs, 8, val) + } + function $MemoryStoreU256(offs, val) { + $MemoryStoreBytes(offs, 32, val) + } + function $AlignedStorageLoad(offs) -> val { + let word_offs := shr(5, offs) + val := sload($StorageKey(0, word_offs)) + } + function $AlignedStorageStore(offs, val) { + let word_offs := shr(5, offs) + sstore($StorageKey(0, word_offs), val) + } + } + object "A3_AccountStateMachine_deployed" { + code { + mstore(0, memoryguard(160)) + if iszero(lt(calldatasize(), 4)) + { + let selector := $Shr(calldataload(0), 224) + switch selector + case 0x3cecd719 + { + // cleanup() + if callvalue() + { + $Abort(99) + } + let $base_offset := $MakeTypeStorageBase(0, 0x330750a9, address()) + if iszero($AlignedStorageLoad($base_offset)) { + $AbortBuiltin() + } + A3_AccountStateMachine_cleanup($MakePtr(true, add($base_offset, 32))) + let memPos := mload(0) + let memEnd := abi_encode_tuple__(memPos) + return(memPos, sub(memEnd, memPos)) + } + case 0x13765838 + { + // deposit(uint64) + if callvalue() + { + $Abort(99) + } + let param_0 := abi_decode_tuple_$uint64$_$u64$(4, calldatasize()) + let $base_offset := $MakeTypeStorageBase(0, 0x330750a9, address()) + if iszero($AlignedStorageLoad($base_offset)) { + $AbortBuiltin() + } + A3_AccountStateMachine_deposit($MakePtr(true, add($base_offset, 32)), param_0) + let memPos := mload(0) + let memEnd := abi_encode_tuple__(memPos) + return(memPos, sub(memEnd, memPos)) + } + case 0x750f0acc + { + // withdraw(uint64) + if callvalue() + { + $Abort(99) + } + let param_0 := abi_decode_tuple_$uint64$_$u64$(4, calldatasize()) + let $base_offset := $MakeTypeStorageBase(0, 0x330750a9, address()) + if iszero($AlignedStorageLoad($base_offset)) { + $AbortBuiltin() + } + A3_AccountStateMachine_withdraw($MakePtr(true, add($base_offset, 32)), param_0) + let memPos := mload(0) + let memEnd := abi_encode_tuple__(memPos) + return(memPos, sub(memEnd, memPos)) + } + case 0x2bcc3f98 + { + // xfer(address,uint64) + if callvalue() + { + $Abort(99) + } + let param_0, param_1 := abi_decode_tuple_$address_uint64$_$address_u64$(4, calldatasize()) + let $base_offset := $MakeTypeStorageBase(0, 0x330750a9, address()) + if iszero($AlignedStorageLoad($base_offset)) { + $AbortBuiltin() + } + A3_AccountStateMachine_xfer($MakePtr(true, add($base_offset, 32)), param_0, param_1) + let memPos := mload(0) + let memEnd := abi_encode_tuple__(memPos) + return(memPos, sub(memEnd, memPos)) + } + case 0x02852d52 + { + // xfer_deposit(uint64,address,uint64) + if callvalue() + { + $Abort(99) + } + let param_0, param_1, param_2 := abi_decode_tuple_$uint64_address_uint64$_$u64_address_u64$(4, calldatasize()) + let $base_offset := $MakeTypeStorageBase(0, 0x330750a9, address()) + if iszero($AlignedStorageLoad($base_offset)) { + $AbortBuiltin() + } + A3_AccountStateMachine_xfer_deposit($MakePtr(true, add($base_offset, 32)), param_0, param_1, param_2) + let memPos := mload(0) + let memEnd := abi_encode_tuple__(memPos) + return(memPos, sub(memEnd, memPos)) + } + case 0x8c38542c + { + // xfer_finish(uint64) + if callvalue() + { + $Abort(99) + } + let param_0 := abi_decode_tuple_$uint64$_$u64$(4, calldatasize()) + let $base_offset := $MakeTypeStorageBase(0, 0x330750a9, address()) + if iszero($AlignedStorageLoad($base_offset)) { + $AbortBuiltin() + } + A3_AccountStateMachine_xfer_finish($MakePtr(true, add($base_offset, 32)), param_0) + let memPos := mload(0) + let memEnd := abi_encode_tuple__(memPos) + return(memPos, sub(memEnd, memPos)) + } + default {} + } + $Abort(97) + function A3_AccountStateMachine_cleanup(this) { + let tmp_$1, i, p, pending, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19 + let $block := 3 + for {} true {} { + switch $block + case 2 { + // label L6 + // $t7 := freeze_ref($t5) + $t7 := $t5 + // $t8 := vector::length($t7) + $t8 := A1_vector_length$A3_AccountStateMachine_PendingTransfer$($t7) + // $t9 := <($t2, $t8) + $t9 := $Lt(i, $t8) + // if ($t9) goto L1 else goto L0 + switch $t9 + case 0 { $block := 5 } + default { $block := 4 } + } + case 3 { + // $t5 := borrow_field.pending($t0) + $t5 := this + // $t6 := 0 + $t6 := 0 + // $t2 := $t6 + i := $t6 + // goto L6 + $block := 2 + } + case 4 { + // label L1 + // goto L2 + $block := 6 + } + case 5 { + // label L0 + // destroy($t5) + // return () + leave + } + case 6 { + // label L2 + // $t10 := freeze_ref($t5) + $t10 := $t5 + // $t11 := vector::borrow($t10, $t2) + $t11 := A1_vector_borrow$A3_AccountStateMachine_PendingTransfer$($t10, i) + // $t12 := Actor::virtual_time() + $t12 := A1_Actor_virtual_time() + // $t13 := borrow_field.initiated_at($t11) + $t13 := $t11 + // $t14 := read_ref($t13) + $t14 := $LoadU128($t13) + // $t15 := -($t12, $t14) + $t15 := $Sub($t12, $t14) + // $t16 := 100000000 + $t16 := 100000000 + // $t17 := >=($t15, $t16) + $t17 := $GtEq($t15, $t16) + // if ($t17) goto L4 else goto L3 + switch $t17 + case 0 { $block := 8 } + default { $block := 7 } + } + case 7 { + // label L4 + // $t18 := vector::remove($t5, $t2) + $t18 := A1_vector_remove$A3_AccountStateMachine_PendingTransfer$($t5, i) + // destroy($t18) + $Free($t18, 32) + // goto L5 + $block := 9 + } + case 8 { + // label L3 + // $t19 := 1 + $t19 := 1 + // $t2 := +($t2, $t19) + i := $AddU64(i, $t19) + // goto L5 + $block := 9 + } + case 9 { + // label L5 + // goto L6 + $block := 2 + } + } + } + + function A3_AccountStateMachine_deposit(this, v) { + let $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11 + let $block := 4 + for {} true {} { + switch $block + case 2 { + // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 + // destroy($t0) + // $t7 := 1 + $t7 := 1 + // abort($t7) + $Abort($t7) + } + case 4 { + // $t2 := 43 + $t2 := 43 + // $t3 := borrow_field.value($t0) + $t3 := $IndexPtr(this, 32) + // $t4 := read_ref($t3) + $t4 := $LoadU64($t3) + // $t5 := -($t2, $t4) + $t5 := $Sub($t2, $t4) + // $t6 := >=($t5, $t1) + $t6 := $GtEq($t5, v) + // if ($t6) goto L1 else goto L0 + switch $t6 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t8 := borrow_field.value($t0) + $t8 := $IndexPtr(this, 32) + // $t9 := read_ref($t8) + $t9 := $LoadU64($t8) + // $t10 := +($t9, $t1) + $t10 := $AddU64($t9, v) + // $t11 := borrow_field.value($t0) + $t11 := $IndexPtr(this, 32) + // write_ref($t11, $t10) + $StoreU64($t11, $t10) + // return () + leave + } + } + } + + function A3_AccountStateMachine_withdraw(this, v) { + let $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 + let $block := 4 + for {} true {} { + switch $block + case 2 { + // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 + // destroy($t0) + // $t5 := 2 + $t5 := 2 + // abort($t5) + $Abort($t5) + } + case 4 { + // $t2 := borrow_field.value($t0) + $t2 := $IndexPtr(this, 32) + // $t3 := read_ref($t2) + $t3 := $LoadU64($t2) + // $t4 := >=($t3, $t1) + $t4 := $GtEq($t3, v) + // if ($t4) goto L1 else goto L0 + switch $t4 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t6 := borrow_field.value($t0) + $t6 := $IndexPtr(this, 32) + // $t7 := read_ref($t6) + $t7 := $LoadU64($t6) + // $t8 := -($t7, $t1) + $t8 := $Sub($t7, v) + // $t9 := borrow_field.value($t0) + $t9 := $IndexPtr(this, 32) + // write_ref($t9, $t8) + $StoreU64($t9, $t8) + // return () + leave + } + } + } + + function A3_AccountStateMachine_xfer(this, dest, v) { + let xfer_id, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12 + let $block := 4 + for {} true {} { + switch $block + case 2 { + // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 + // destroy($t0) + // $t7 := 1 + $t7 := 1 + // abort($t7) + $Abort($t7) + } + case 4 { + // $t4 := borrow_field.value($t0) + $t4 := $IndexPtr(this, 32) + // $t5 := read_ref($t4) + $t5 := $LoadU64($t4) + // $t6 := >=($t5, $t2) + $t6 := $GtEq($t5, v) + // if ($t6) goto L1 else goto L0 + switch $t6 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t8 := AccountStateMachine::new_xfer_id($t0) + $t8 := A3_AccountStateMachine_new_xfer_id(this) + // $t9 := borrow_field.pending($t0) + $t9 := this + // $t10 := Actor::virtual_time() + $t10 := A1_Actor_virtual_time() + // $t11 := pack AccountStateMachine::PendingTransfer($t8, $t2, $t10) + { + let $mem := $Malloc(32) + $MemoryStoreU64(add($mem, 16), $t8) + $MemoryStoreU64(add($mem, 24), v) + $MemoryStoreU128(add($mem, 0), $t10) + $t11 := $mem + } + // vector::push_back($t9, $t11) + A1_vector_push_back$A3_AccountStateMachine_PendingTransfer$($t9, $t11) + // $t12 := Actor::self() + $t12 := A1_Actor_self() + // AccountStateMachine::send_xfer_deposit($t1, $t2, $t12, $t8) + A3_AccountStateMachine_send_xfer_deposit(dest, v, $t12, $t8) + // return () + leave + } + } + } + + function A3_AccountStateMachine_xfer_deposit(this, v, caller_, xfer_id) { + // AccountStateMachine::deposit($t0, $t1) + A3_AccountStateMachine_deposit(this, v) + // AccountStateMachine::send_xfer_finish($t2, $t3) + A3_AccountStateMachine_send_xfer_finish(caller_, xfer_id) + // return () + } + + function A3_AccountStateMachine_xfer_finish(this, xfer_id) { + let tmp_$2, amount, i, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12 + // $t5 := freeze_ref($t0) + $t5 := this + // $t6 := AccountStateMachine::find_xfer($t5, $t1) + $t6 := A3_AccountStateMachine_find_xfer($t5, xfer_id) + // $t7 := borrow_field.pending($t0) + $t7 := this + // $t8 := vector::borrow($t7, $t6) + $t8 := A1_vector_borrow$A3_AccountStateMachine_PendingTransfer$($t7, $t6) + // $t9 := borrow_field.amount($t8) + $t9 := $IndexPtr($t8, 24) + // $t10 := read_ref($t9) + $t10 := $LoadU64($t9) + // $t11 := borrow_field.pending($t0) + $t11 := this + // $t12 := vector::remove($t11, $t6) + $t12 := A1_vector_remove$A3_AccountStateMachine_PendingTransfer$($t11, $t6) + // destroy($t12) + $Free($t12, 32) + // AccountStateMachine::withdraw($t0, $t10) + A3_AccountStateMachine_withdraw(this, $t10) + // return () + } + + function A1_vector_remove$A3_AccountStateMachine_PendingTransfer$(v, i) -> $result { + let tmp_$2, tmp_$3, len, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15 + let $block := 4 + for {} true {} { + switch $block + case 2 { + // label L1 + // destroy($t0) + // $t8 := 131072 + $t8 := 131072 + // abort($t8) + $Abort($t8) + } + case 3 { + // label L0 + // $t9 := 1 + $t9 := 1 + // $t10 := -($t6, $t9) + $t10 := $Sub($t6, $t9) + // goto L5 + $block := 5 + } + case 4 { + // $t5 := freeze_ref($t0) + $t5 := v + // $t6 := vector::length<#0>($t5) + $t6 := A1_vector_length$A3_AccountStateMachine_PendingTransfer$($t5) + // $t7 := >=($t1, $t6) + $t7 := $GtEq(i, $t6) + // if ($t7) goto L1 else goto L0 + switch $t7 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L5 + // $t11 := <($t1, $t10) + $t11 := $Lt(i, $t10) + // if ($t11) goto L3 else goto L2 + switch $t11 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L3 + // goto L4 + $block := 8 + } + case 7 { + // label L2 + // $t15 := vector::pop_back<#0>($t0) + $t15 := A1_vector_pop_back$A3_AccountStateMachine_PendingTransfer$(v) + // return $t15 + $result := $t15 + leave + } + case 8 { + // label L4 + // $t12 := copy($t1) + $t12 := i + // $t13 := 1 + $t13 := 1 + // $t14 := +($t1, $t13) + $t14 := $AddU64(i, $t13) + // $t1 := $t14 + i := $t14 + // vector::swap<#0>($t0, $t12, $t14) + A1_vector_swap$A3_AccountStateMachine_PendingTransfer$(v, $t12, $t14) + // goto L5 + $block := 5 + } + } + } + + function A1_vector_swap$A3_AccountStateMachine_PendingTransfer$(v_ref, i, j) { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + let size := $LoadU64(v_ptr) + if or($GtEq(i, size), $GtEq(j, size)) { $AbortBuiltin() } + let i_ptr := $IndexPtr(v_ptr, add(32, mul(i, 32))) + let j_ptr := $IndexPtr(v_ptr, add(32, mul(j, 32))) + let i_val := $LoadU256(i_ptr) + let j_val := $LoadU256(j_ptr) + $StoreU256(i_ptr, j_val) + $StoreU256(j_ptr, i_val) + } + function A1_vector_pop_back$A3_AccountStateMachine_PendingTransfer$(v_ref) -> e { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + let size := $LoadU64(v_ptr) + if iszero(size) { $AbortBuiltin() } + let e_ptr := $IndexPtr(v_ptr, add(32, mul(sub(size, 1), 32))) + e := $LoadU256(e_ptr) + if $IsStoragePtr(e_ptr) { + let e_offs := $OffsetPtr(e_ptr) + let linked_src := $AlignedStorageLoad(e_offs) + e := $Malloc(32) + mstore(add(e, 0), $AlignedStorageLoad(add(linked_src, 0))) + $AlignedStorageStore(add(linked_src, 0), 0) + $AlignedStorageStore(e_offs, 0) + } + $StoreU64(v_ptr, sub(size, 1)) + } + function A1_vector_length$A3_AccountStateMachine_PendingTransfer$(v_ref) -> len { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + len := $LoadU64(v_ptr) + } + function A1_vector_borrow$A3_AccountStateMachine_PendingTransfer$(v_ref, i) -> e_ptr { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + let size := $LoadU64(v_ptr) + if $GtEq(i, size) { $AbortBuiltin() } + e_ptr := $IndexPtr(v_ptr, add(32, mul(i, 32))) + let e := $LoadU256(e_ptr) + e_ptr := $MakePtr($IsStoragePtr(v_ref), e) + } + function A3_AccountStateMachine_find_xfer(this, xfer_id) -> $result { + let tmp_$2, i, pending, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16 + let $block := 3 + for {} true {} { + switch $block + case 2 { + // label L6 + // $t7 := vector::length($t5) + $t7 := A1_vector_length$A3_AccountStateMachine_PendingTransfer$($t5) + // $t8 := <($t3, $t7) + $t8 := $Lt(i, $t7) + // if ($t8) goto L1 else goto L0 + switch $t8 + case 0 { $block := 5 } + default { $block := 4 } + } + case 3 { + // $t5 := borrow_field.pending($t0) + $t5 := this + // $t6 := 0 + $t6 := 0 + // $t3 := $t6 + i := $t6 + // goto L6 + $block := 2 + } + case 4 { + // label L1 + // goto L2 + $block := 6 + } + case 5 { + // label L0 + // $t12 := false + $t12 := false + // $t2 := $t12 + tmp_$2 := $t12 + // goto L3 + $block := 7 + } + case 6 { + // label L2 + // $t9 := vector::borrow($t5, $t3) + $t9 := A1_vector_borrow$A3_AccountStateMachine_PendingTransfer$($t5, i) + // $t10 := borrow_field.xfer_id($t9) + $t10 := $IndexPtr($t9, 16) + // $t11 := read_ref($t10) + $t11 := $LoadU64($t10) + // $t2 := !=($t11, $t1) + tmp_$2 := $Neq($t11, xfer_id) + // goto L3 + $block := 7 + } + case 7 { + // label L3 + // if ($t2) goto L5 else goto L4 + switch tmp_$2 + case 0 { $block := 9 } + default { $block := 8 } + } + case 8 { + // label L5 + // $t13 := 1 + $t13 := 1 + // $t3 := +($t3, $t13) + i := $AddU64(i, $t13) + // goto L6 + $block := 2 + } + case 9 { + // label L4 + // $t14 := vector::length($t5) + $t14 := A1_vector_length$A3_AccountStateMachine_PendingTransfer$($t5) + // $t15 := <($t3, $t14) + $t15 := $Lt(i, $t14) + // if ($t15) goto L8 else goto L7 + switch $t15 + case 0 { $block := 11 } + default { $block := 10 } + } + case 10 { + // label L8 + // goto L9 + $block := 12 + } + case 11 { + // label L7 + // $t16 := 3 + $t16 := 3 + // abort($t16) + $Abort($t16) + } + case 12 { + // label L9 + // return $t3 + $result := i + leave + } + } + } + + function A3_AccountStateMachine_send_xfer_finish(actor,xfer_id) { + let $t2 := 0x6a51b363524e1e502dbe8698bec5f165b6cf490a68c4ee9063f2c2f0653ff0dd + let $t3 := 0xb8229d65 + { + let $t4 := mload(0) + let $t5 := abi_encode_tuple_$address_uint64_uint64$_$address_u64_u64$($t4, actor,$t3,xfer_id) + log1($t4, sub($t5, $t4), $t2) + mstore(0, $t5) + } + } + function A3_AccountStateMachine_send_xfer_deposit(actor,v,caller_,xfer_id) { + let $t4 := 0x5163aa8ed9d57dbb55d2433f534c881e8fec62da43488c756dbd1ac604ce9c1b + let $t5 := 0x0b32e0fa + { + let $t6 := mload(0) + let $t7 := abi_encode_tuple_$address_uint64_uint64_address_uint64$_$address_u64_u64_address_u64$($t6, actor,$t5,v,caller_,xfer_id) + log1($t6, sub($t7, $t6), $t4) + mstore(0, $t7) + } + } + function A1_Actor_self() -> addr { + addr := address() + } + function A1_vector_push_back$A3_AccountStateMachine_PendingTransfer$(v_ref, e) { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + let size := $LoadU64(v_ptr) + let e_ptr := $IndexPtr(v_ptr, add(32, mul(size, 32))) + $StoreU256(e_ptr, e) + if $IsStoragePtr(e_ptr) { + let e_offs := $OffsetPtr(e_ptr) + let $linked_dst_1341933877 := $NewLinkedStorageBase(0x4ffc4935) + $AlignedStorageStore(add($linked_dst_1341933877, 0), mload(add(e, 0))) + $Free(e, 32) + $AlignedStorageStore(e_offs, $linked_dst_1341933877) + } + size := add(size, 1) + $StoreU64(v_ptr, size) + let capacity := $LoadU64($IndexPtr(v_ptr, 8)) + if and(iszero($IsStoragePtr(v_ptr)), eq(size, capacity)) { + let new_v_offs := $ResizeVector(v_offs, capacity, 32) + $StoreU256(v_ref, new_v_offs) + } + } + function A1_Actor_virtual_time() -> virtual_time { + virtual_time := timestamp() + } + function A3_AccountStateMachine_new_xfer_id(this) -> $result { + let counter, xfer_id, $t3, $t4, $t5, $t6, $t7 + // $t3 := borrow_field.xfer_id_counter($t0) + $t3 := $IndexPtr(this, 40) + // $t4 := read_ref($t3) + $t4 := $LoadU64($t3) + // $t5 := read_ref($t3) + $t5 := $LoadU64($t3) + // $t6 := 1 + $t6 := 1 + // $t7 := +($t5, $t6) + $t7 := $AddU64($t5, $t6) + // write_ref($t3, $t7) + $StoreU64($t3, $t7) + // return $t4 + $result := $t4 + } + + function abi_encode_tuple_$address_uint64_uint64_address_uint64$_$address_u64_u64_address_u64$(headStart ,value_0, value_1, value_2, value_3, value_4) -> tail { + tail := add(headStart, 160) + abi_encode_address(value_0, add(headStart, 0)) + abi_encode_uint64(value_1, add(headStart, 32)) + abi_encode_uint64(value_2, add(headStart, 64)) + abi_encode_address(value_3, add(headStart, 96)) + abi_encode_uint64(value_4, add(headStart, 128)) + } + function abi_encode_uint64(value, pos) { + mstore(pos, cleanup_uint64(value)) + } + function cleanup_uint64(value) -> cleaned { + cleaned := and(value, 0xffffffffffffffff) + } + function abi_encode_address(value, pos) { + mstore(pos, cleanup_address(value)) + } + function cleanup_address(value) -> cleaned { + cleaned := and(value, 0xffffffffffffffffffffffffffffffffffffffff) + } + function abi_encode_tuple_$address_uint64_uint64$_$address_u64_u64$(headStart ,value_0, value_1, value_2) -> tail { + tail := add(headStart, 96) + abi_encode_address(value_0, add(headStart, 0)) + abi_encode_uint64(value_1, add(headStart, 32)) + abi_encode_uint64(value_2, add(headStart, 64)) + } + function abi_encode_tuple__(headStart ) -> tail { + tail := add(headStart, 0) + } + function abi_decode_tuple_$uint64$_$u64$(headStart, dataEnd) -> value_0 { + if slt(sub(dataEnd, headStart), 32) { $Abort(96) } + { + let offset := 0 + value_0 := abi_decode_uint64(add(headStart, offset), dataEnd) + } + } + function abi_decode_uint64(offset, end) -> value { + value := calldataload(offset) + validator_uint64(value) + } + function validator_uint64(value) { + if iszero(eq(value, cleanup_uint64(value))) { $Abort(95) } + } + function abi_decode_tuple_$uint64_address_uint64$_$u64_address_u64$(headStart, dataEnd) -> value_0, value_1, value_2 { + if slt(sub(dataEnd, headStart), 96) { $Abort(96) } + { + let offset := 0 + value_0 := abi_decode_uint64(add(headStart, offset), dataEnd) + } + { + let offset := 32 + value_1 := abi_decode_address(add(headStart, offset), dataEnd) + } + { + let offset := 64 + value_2 := abi_decode_uint64(add(headStart, offset), dataEnd) + } + } + function abi_decode_address(offset, end) -> value { + value := calldataload(offset) + validator_address(value) + } + function validator_address(value) { + if iszero(eq(value, cleanup_address(value))) { $Abort(95) } + } + function abi_decode_tuple_$address_uint64$_$address_u64$(headStart, dataEnd) -> value_0, value_1 { + if slt(sub(dataEnd, headStart), 64) { $Abort(96) } + { + let offset := 0 + value_0 := abi_decode_address(add(headStart, offset), dataEnd) + } + { + let offset := 32 + value_1 := abi_decode_uint64(add(headStart, offset), dataEnd) + } + } + function $Abort(code) { + mstore(0, code) + revert(24, 8) // TODO: store code as a string? + } + function $AbortBuiltin() { + $Abort(sub(0, 1)) + } + function $Malloc(size) -> offs { + offs := mload(0) + // pad to word size + mstore(0, add(offs, shl(5, shr(5, add(size, 31))))) + } + function $Free(offs, size) { + } + function $MakePtr(is_storage, offs) -> ptr { + ptr := or(is_storage, shl(1, offs)) + } + function $IsStoragePtr(ptr) -> b { + b := and(ptr, 0x1) + } + function $OffsetPtr(ptr) -> offs { + offs := shr(1, ptr) + } + function $MaskForSize(size) -> mask { + mask := sub(shl(shl(3, size), 1), 1) + } + function $ExtractBytes(word, start, size) -> bytes { + switch size + case 1 { + // use the faster byte primitive + bytes := byte(start, word) + } + default { + // As we have big endian, we need to right shift the value from + // where the highest byte starts in the word (32 - start), minus + // the size. + let shift_bits := shl(3, sub(sub(32, start), size)) + bytes := and(shr(shift_bits, word), $MaskForSize(size)) + } + } + function $InjectBytes(word, start, size, bytes) -> new_word { + let shift_bits := shl(3, sub(sub(32, start), size)) + // Blend out the bits which we inject + let neg_mask := not(shl(shift_bits, $MaskForSize(size))) + word := and(word, neg_mask) + // Overlay the bits we inject + new_word := or(word, shl(shift_bits, bytes)) + } + function $ToWordOffs(offs) -> word_offs, byte_offset { + word_offs := shr(5, offs) + byte_offset := and(offs, 0x1F) + } + function $OverflowBytes(byte_offset, size) -> overflow_bytes { + let available_bytes := sub(32, byte_offset) + switch gt(size, available_bytes) + case 0 { + overflow_bytes := 0 + } + default { + overflow_bytes := sub(size, available_bytes) + } + } + function $MemoryLoadBytes(offs, size) -> val { + // Lower bit where the value in the higher bytes ends + let bit_end := shl(3, sub(32, size)) + val := shr(bit_end, mload(offs)) + } + function $MemoryStoreBytes(offs, size, val) { + let bit_end := shl(3, sub(32, size)) + let mask := shl(bit_end, $MaskForSize(size)) + mstore(offs, or(and(mload(offs), not(mask)), shl(bit_end, val))) + } + function $StorageLoadBytes(offs, size) -> val { + let word_offs, byte_offs := $ToWordOffs(offs) + let key := $StorageKey(0, word_offs) + val := $ExtractBytes(sload(key), byte_offs, size) + let overflow_bytes := $OverflowBytes(byte_offs, size) + if $LogicalNot(iszero(overflow_bytes)) { + key := $StorageKey(0, add(word_offs, 1)) + let extra_bytes := $ExtractBytes(sload(key), 0, overflow_bytes) + val := or(shl(shl(3, overflow_bytes), val), extra_bytes) + } + } + function $StorageStoreBytes(offs, size, bytes) { + let word_offs, byte_offs := $ToWordOffs(offs) + let key := $StorageKey(0, word_offs) + let overflow_bytes := $OverflowBytes(byte_offs, size) + switch overflow_bytes + case 0 { + sstore(key, $InjectBytes(sload(key), byte_offs, size, bytes)) + } + default { + // Shift the higher bytes to the right + let used_bytes := sub(size, overflow_bytes) + let higher_bytes := shr(used_bytes, bytes) + let lower_bytes := and(bytes, $MaskForSize(overflow_bytes)) + sstore(key, $InjectBytes(sload(key), byte_offs, used_bytes, higher_bytes)) + key := $StorageKey(0, add(word_offs, 1)) + sstore(key, $InjectBytes(sload(key), 0, overflow_bytes, lower_bytes)) + } + } + function $StorageKey(group, word) -> key { + mstore(32, word) + mstore(64, shl(224, group)) + key := keccak256(32, 36) + } + function $MakeTypeStorageBase(category, type_hash, id) -> offs { + offs := or(shl(252, category), or(shl(220, type_hash), shl(60, id))) + } + function $NewLinkedStorageBase(type_hash) -> offs { + let key := $StorageKey(1, 1) + let handle := sload(key) + sstore(key, add(handle, 1)) + offs := $MakeTypeStorageBase(1, type_hash, handle) + } + function $IndexPtr(ptr, offs) -> new_ptr { + new_ptr := $MakePtr($IsStoragePtr(ptr), add($OffsetPtr(ptr), offs)) + } + function $LoadU64(ptr) -> val { + let offs := $OffsetPtr(ptr) + switch $IsStoragePtr(ptr) + case 0 { + val := $MemoryLoadU64(offs) + } + default { + val := $StorageLoadU64(offs) + } + } + function $MemoryLoadU64(offs) -> val { + val := $MemoryLoadBytes(offs, 8) + } + function $StorageLoadU64(offs) -> val { + val := $StorageLoadBytes(offs, 8) + } + function $StoreU64(ptr, val) { + let offs := $OffsetPtr(ptr) + switch $IsStoragePtr(ptr) + case 0 { + $MemoryStoreU64(offs, val) + } + default { + $StorageStoreU64(offs, val) + } + } + function $MemoryStoreU64(offs, val) { + $MemoryStoreBytes(offs, 8, val) + } + function $StorageStoreU64(offs, val) { + $StorageStoreBytes(offs, 8, val) + } + function $LoadU128(ptr) -> val { + let offs := $OffsetPtr(ptr) + switch $IsStoragePtr(ptr) + case 0 { + val := $MemoryLoadU128(offs) + } + default { + val := $StorageLoadU128(offs) + } + } + function $MemoryLoadU128(offs) -> val { + val := $MemoryLoadBytes(offs, 16) + } + function $StorageLoadU128(offs) -> val { + val := $StorageLoadBytes(offs, 16) + } + function $MemoryStoreU128(offs, val) { + $MemoryStoreBytes(offs, 16, val) + } + function $LoadU256(ptr) -> val { + let offs := $OffsetPtr(ptr) + switch $IsStoragePtr(ptr) + case 0 { + val := $MemoryLoadU256(offs) + } + default { + val := $StorageLoadU256(offs) + } + } + function $MemoryLoadU256(offs) -> val { + val := $MemoryLoadBytes(offs, 32) + } + function $StorageLoadU256(offs) -> val { + val := $StorageLoadBytes(offs, 32) + } + function $StoreU256(ptr, val) { + let offs := $OffsetPtr(ptr) + switch $IsStoragePtr(ptr) + case 0 { + $MemoryStoreU256(offs, val) + } + default { + $StorageStoreU256(offs, val) + } + } + function $MemoryStoreU256(offs, val) { + $MemoryStoreBytes(offs, 32, val) + } + function $StorageStoreU256(offs, val) { + $StorageStoreBytes(offs, 32, val) + } + function $AlignedStorageLoad(offs) -> val { + let word_offs := shr(5, offs) + val := sload($StorageKey(0, word_offs)) + } + function $AlignedStorageStore(offs, val) { + let word_offs := shr(5, offs) + sstore($StorageKey(0, word_offs), val) + } + function $CopyMemory(src, dst, size) { + let num_words, overflow_bytes := $ToWordOffs(size) + let i := 0 + for { } lt(i, mul(num_words, 32)) { i := add(i, 32) } { + mstore(add(dst, i), mload(add(src, i))) + } + if overflow_bytes { + let mask := $MaskForSize(sub(32, overflow_bytes)) + let overflow_offs := mul(num_words, 32) + let dst_word := and(mload(add(dst, overflow_offs)), mask) + let src_word := and(mload(add(src, overflow_offs)), not(mask)) + mstore(add(dst, overflow_offs), or(dst_word, src_word)) + } + } + function $ResizeVector(v_offs, capacity, type_size) -> new_v_offs { + let new_capacity := mul(capacity, 2) + let data_size := add(32, mul(capacity, type_size)) + let new_data_size := add(32, mul(new_capacity, type_size)) + new_v_offs := $Malloc(new_data_size) + $CopyMemory(v_offs, new_v_offs, data_size) + // update capacity at new location + $MemoryStoreU64(add(new_v_offs, 8), new_capacity) + $Free(v_offs, data_size) + } + function $AddU64(x, y) -> r { + if lt(sub(0xffffffffffffffff, x), y) { $AbortBuiltin() } + r := add(x, y) + } + function $Sub(x, y) -> r { + if lt(x, y) { $AbortBuiltin() } + r := sub(x, y) + } + function $Shr(x, y) -> r { + r := shr(y, x) + } + function $Lt(x, y) -> r { + r := lt(x, y) + } + function $GtEq(x, y) -> r { + r := or(gt(x, y), eq(x, y)) + } + function $Neq(x, y) -> r { + r := $LogicalNot(eq(x, y)) + } + function $LogicalNot(x) -> r { + r := iszero(x) + } + } + } +} + + +!! Succeeded compiling Yul diff --git a/language/evm/move-to-yul/tests/AccountStateMachine.move b/language/evm/move-to-yul/tests/AccountStateMachine.move new file mode 100644 index 0000000000..8eeae6733f --- /dev/null +++ b/language/evm/move-to-yul/tests/AccountStateMachine.move @@ -0,0 +1,101 @@ +#[actor] +/// This is an instance of the Account example using an explicit state machine and one-way message passing. +/// +/// In this example, we need to manage rpc state explicitly, remembering any outstanding transfers in the +/// actors state. This creates a little more code, but also is somehow more transparent and true to the +/// transactional semantics of Move. This version implements an additional `cleanup` message which cancels +/// pending transactions over a certain age. +module 0x3::AccountStateMachine { + + use Async::Actor::{self, virtual_time}; + use std::vector; + + const MAX: u64 = 43; + const MAX_TRANSFER_AGE: u128 = 100000000; + + #[state] + struct Account { + value: u64, + xfer_id_counter: u64, + pending: vector + } + + struct PendingTransfer has drop { + xfer_id: u64, + amount: u64, + initiated_at: u128, + } + + #[init] + fun init(): Account { + Account{value: 0, xfer_id_counter: 0, pending: vector::empty()} + } + + #[message] + fun deposit(this: &mut Account, v: u64) { + assert!(MAX - this.value >= v, 1); + this.value = this.value + v; + } + + #[message] + fun withdraw(this: &mut Account, v: u64) { + assert!(this.value >= v, 2); + this.value = this.value - v; + } + + #[message] + fun xfer(this: &mut Account, dest: address, v: u64) { + // Do not initiate the transfer if there are not enough funds. + assert!(this.value >= v, 1); + let xfer_id = new_xfer_id(this); + vector::push_back(&mut this.pending, PendingTransfer{xfer_id, amount: v, initiated_at: virtual_time()}); + // Call into a special version of deposit which calls us back once done. + send_xfer_deposit(dest, v, self(), xfer_id); + } + + fun new_xfer_id(this: &mut Account): u64 { + let counter = &mut this.xfer_id_counter; + let xfer_id = *counter; + *counter = *counter + 1; + xfer_id + } + + #[message] + fun xfer_deposit(this: &mut Account, v: u64, caller_: address, xfer_id: u64) { + deposit(this, v); + send_xfer_finish(caller_, xfer_id); + } + + #[message] + fun xfer_finish(this: &mut Account, xfer_id: u64) { + let i = find_xfer(this, xfer_id); + let amount = vector::borrow(&this.pending, i).amount; + vector::remove(&mut this.pending, i); + withdraw(this, amount) + } + + fun find_xfer(this: &Account, xfer_id: u64): u64 { + let pending = &this.pending; + let i = 0; + while (i < vector::length(pending) && vector::borrow(pending, i).xfer_id != xfer_id) { + i = i + 1; + }; + assert!(i < vector::length(pending), 3); + i + } + + #[message] + /// A periodical cleanup which removes dated pending transfers. + fun cleanup(this: &mut Account) { + let pending = &mut this.pending; + let i = 0; + while (i < vector::length(pending)) { + let p = vector::borrow(pending, i); + if (virtual_time() - p.initiated_at >= MAX_TRANSFER_AGE) { + vector::remove(pending, i); + } else { + i = i + 1; + } + } + } +} diff --git a/language/evm/move-to-yul/tests/Arithm.exp b/language/evm/move-to-yul/tests/Arithm.exp index f688b61a9f..ed4e735fec 100644 --- a/language/evm/move-to-yul/tests/Arithm.exp +++ b/language/evm/move-to-yul/tests/Arithm.exp @@ -96,14 +96,14 @@ object "A2_M" { } $Abort(97) function A2_M_add_two_number(x, y) -> $result0, $result1 { - let res, z, $t4, $t5 - // $t4 := +($t0, $t1) - $t4 := $AddU64(x, y) - // $t5 := 3 - $t5 := 3 - // return ($t5, $t4) - $result0 := $t5 - $result1 := $t4 + let res, $t3, $t4 + // $t3 := +($t0, $t1) + $t3 := $AddU64(x, y) + // $t4 := 3 + $t4 := 3 + // return ($t4, $t3) + $result0 := $t4 + $result1 := $t3 } function A2_M_arithmetic_ops(a) -> $result0, $result1 { @@ -112,14 +112,14 @@ object "A2_M" { for {} true {} { switch $block case 2 { - // label L0 + // label L1 // $t5 := 42 $t5 := 42 // abort($t5) $Abort($t5) } case 3 { - // label L2 + // label L0 // return ($t2, $t0) $result0 := $t2 $result1 := a @@ -132,7 +132,7 @@ object "A2_M" { $t3 := 2 // $t4 := !=($t2, $t3) $t4 := $Neq($t2, $t3) - // if ($t4) goto L0 else goto L2 + // if ($t4) goto L1 else goto L0 switch $t4 case 0 { $block := 3 } default { $block := 2 } @@ -146,34 +146,34 @@ object "A2_M" { for {} true {} { switch $block case 2 { - // label L0 + // label L1 // $t2 := >=($t0, $t1) tmp_$2 := $GtEq(a, b) - // goto L3 + // goto L2 $block := 5 } case 3 { - // label L2 + // label L0 // $t7 := false $t7 := false // $t2 := $t7 tmp_$2 := $t7 - // goto L3 + // goto L2 $block := 5 } case 4 { // $t6 := >($t0, $t1) $t6 := $Gt(a, b) - // if ($t6) goto L0 else goto L2 + // if ($t6) goto L1 else goto L0 switch $t6 case 0 { $block := 3 } default { $block := 2 } } case 5 { - // label L3 + // label L2 // $t8 := <($t0, $t1) $t8 := $Lt(a, b) - // if ($t8) goto L4 else goto L6 + // if ($t8) goto L4 else goto L3 switch $t8 case 0 { $block := 7 } default { $block := 6 } @@ -184,36 +184,36 @@ object "A2_M" { $t9 := true // $t3 := $t9 tmp_$3 := $t9 - // goto L7 + // goto L5 $block := 8 } case 7 { - // label L6 + // label L3 // $t3 := <=($t0, $t1) tmp_$3 := $LtEq(a, b) - // goto L7 + // goto L5 $block := 8 } case 8 { - // label L7 + // label L5 // $t10 := !=($t2, $t3) $t10 := $Neq(tmp_$2, tmp_$3) // $t11 := !($t10) $t11 := $LogicalNot($t10) - // if ($t11) goto L8 else goto L10 + // if ($t11) goto L7 else goto L6 switch $t11 case 0 { $block := 10 } default { $block := 9 } } case 9 { - // label L8 + // label L7 // $t12 := 42 $t12 := 42 // abort($t12) $Abort($t12) } case 10 { - // label L10 + // label L6 // return ($t2, $t3) $result0 := tmp_$2 $result1 := tmp_$3 @@ -244,15 +244,15 @@ object "A2_M" { } function A2_M_underflow() -> $result { - let x, $t1, $t2, $t3 - // $t1 := 0 - $t1 := 0 - // $t2 := 1 - $t2 := 1 - // $t3 := -($t1, $t2) - $t3 := $Sub($t1, $t2) - // return $t3 - $result := $t3 + let $t0, $t1, $t2 + // $t0 := 0 + $t0 := 0 + // $t1 := 1 + $t1 := 1 + // $t2 := -($t0, $t1) + $t2 := $Sub($t0, $t1) + // return $t2 + $result := $t2 } function abi_encode_tuple_$uint64$_$u64$(headStart ,value_0) -> tail { @@ -391,53 +391,63 @@ object "test_A2_M_test_add_two_number" { A2_M_test_add_two_number() return (0, 0) function A2_M_test_add_two_number() { - let res, z, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11 + let res, $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t8 := 100 - $t8 := 100 - // abort($t8) - $Abort($t8) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t9 := 7 - $t9 := 7 - // $t10 := ==($t5, $t9) - $t10 := $Eq($t5, $t9) - // if ($t10) goto L2 else goto L3 - switch $t10 - case 0 { $block := 5 } - default { $block := 6 } + // $t7 := 100 + $t7 := 100 + // abort($t7) + $Abort($t7) } case 4 { - // $t2 := 2 - $t2 := 2 - // $t3 := 5 - $t3 := 5 - // ($t4, $t5) := M::add_two_number($t2, $t3) - $t4, $t5 := A2_M_add_two_number($t2, $t3) - // $t6 := 3 - $t6 := 3 - // $t7 := ==($t4, $t6) - $t7 := $Eq($t4, $t6) - // if ($t7) goto L0 else goto L1 - switch $t7 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := 2 + $t1 := 2 + // $t2 := 5 + $t2 := 5 + // ($t3, $t4) := M::add_two_number($t1, $t2) + $t3, $t4 := A2_M_add_two_number($t1, $t2) + // $t5 := 3 + $t5 := 3 + // $t6 := ==($t3, $t5) + $t6 := $Eq($t3, $t5) + // if ($t6) goto L1 else goto L0 + switch $t6 + case 0 { $block := 3 } + default { $block := 2 } } case 5 { - // label L3 - // $t11 := 101 - $t11 := 101 - // abort($t11) - $Abort($t11) + // label L2 + // $t8 := 7 + $t8 := 7 + // $t9 := ==($t4, $t8) + $t9 := $Eq($t4, $t8) + // if ($t9) goto L4 else goto L3 + switch $t9 + case 0 { $block := 7 } + default { $block := 6 } } case 6 { - // label L2 + // label L4 + // goto L5 + $block := 8 + } + case 7 { + // label L3 + // $t10 := 101 + $t10 := 101 + // abort($t10) + $Abort($t10) + } + case 8 { + // label L5 // return () leave } @@ -445,14 +455,14 @@ object "test_A2_M_test_add_two_number" { } function A2_M_add_two_number(x, y) -> $result0, $result1 { - let res, z, $t4, $t5 - // $t4 := +($t0, $t1) - $t4 := $AddU64(x, y) - // $t5 := 3 - $t5 := 3 - // return ($t5, $t4) - $result0 := $t5 - $result1 := $t4 + let res, $t3, $t4 + // $t3 := +($t0, $t1) + $t3 := $AddU64(x, y) + // $t4 := 3 + $t4 := 3 + // return ($t4, $t3) + $result0 := $t4 + $result1 := $t3 } function $Abort(code) { @@ -471,7 +481,7 @@ object "test_A2_M_test_add_two_number" { } } } -===> Test result of M::test_add_two_number: Succeed(Stopped) (used_gas=355): [] +===> Test result of M::test_add_two_number: Succeed(Stopped) (used_gas=677): [] // test of M::test_add_two_number_overflow /* ======================================= @@ -485,27 +495,27 @@ object "test_A2_M_test_add_two_number_overflow" { A2_M_test_add_two_number_overflow() return (0, 0) function A2_M_test_add_two_number_overflow() { - let _res, _z, $t2, $t3, $t4, $t5 - // $t2 := 18446744073709551615 - $t2 := 18446744073709551615 - // $t3 := 1 - $t3 := 1 - // ($t4, $t5) := M::add_two_number($t2, $t3) - $t4, $t5 := A2_M_add_two_number($t2, $t3) - // destroy($t5) - // destroy($t4) + let $t0, $t1, $t2, $t3 + // $t0 := 18446744073709551615 + $t0 := 18446744073709551615 + // $t1 := 1 + $t1 := 1 + // ($t2, $t3) := M::add_two_number($t0, $t1) + $t2, $t3 := A2_M_add_two_number($t0, $t1) + // destroy($t3) + // destroy($t2) // return () } function A2_M_add_two_number(x, y) -> $result0, $result1 { - let res, z, $t4, $t5 - // $t4 := +($t0, $t1) - $t4 := $AddU64(x, y) - // $t5 := 3 - $t5 := 3 - // return ($t5, $t4) - $result0 := $t5 - $result1 := $t4 + let res, $t3, $t4 + // $t3 := +($t0, $t1) + $t3 := $AddU64(x, y) + // $t4 := 3 + $t4 := 3 + // return ($t4, $t3) + $result0 := $t4 + $result1 := $t3 } function $Abort(code) { @@ -535,53 +545,63 @@ object "test_A2_M_test_add_two_number_wrong_assert" { A2_M_test_add_two_number_wrong_assert() return (0, 0) function A2_M_test_add_two_number_wrong_assert() { - let res, z, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11 + let res, $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t8 := 100 - $t8 := 100 - // abort($t8) - $Abort($t8) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t9 := 6 - $t9 := 6 - // $t10 := ==($t5, $t9) - $t10 := $Eq($t5, $t9) - // if ($t10) goto L2 else goto L3 - switch $t10 - case 0 { $block := 5 } - default { $block := 6 } + // $t7 := 100 + $t7 := 100 + // abort($t7) + $Abort($t7) } case 4 { - // $t2 := 2 - $t2 := 2 - // $t3 := 5 - $t3 := 5 - // ($t4, $t5) := M::add_two_number($t2, $t3) - $t4, $t5 := A2_M_add_two_number($t2, $t3) - // $t6 := 3 - $t6 := 3 - // $t7 := ==($t4, $t6) - $t7 := $Eq($t4, $t6) - // if ($t7) goto L0 else goto L1 - switch $t7 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := 2 + $t1 := 2 + // $t2 := 5 + $t2 := 5 + // ($t3, $t4) := M::add_two_number($t1, $t2) + $t3, $t4 := A2_M_add_two_number($t1, $t2) + // $t5 := 3 + $t5 := 3 + // $t6 := ==($t3, $t5) + $t6 := $Eq($t3, $t5) + // if ($t6) goto L1 else goto L0 + switch $t6 + case 0 { $block := 3 } + default { $block := 2 } } case 5 { - // label L3 - // $t11 := 101 - $t11 := 101 - // abort($t11) - $Abort($t11) + // label L2 + // $t8 := 6 + $t8 := 6 + // $t9 := ==($t4, $t8) + $t9 := $Eq($t4, $t8) + // if ($t9) goto L4 else goto L3 + switch $t9 + case 0 { $block := 7 } + default { $block := 6 } } case 6 { - // label L2 + // label L4 + // goto L5 + $block := 8 + } + case 7 { + // label L3 + // $t10 := 101 + $t10 := 101 + // abort($t10) + $Abort($t10) + } + case 8 { + // label L5 // return () leave } @@ -589,14 +609,14 @@ object "test_A2_M_test_add_two_number_wrong_assert" { } function A2_M_add_two_number(x, y) -> $result0, $result1 { - let res, z, $t4, $t5 - // $t4 := +($t0, $t1) - $t4 := $AddU64(x, y) - // $t5 := 3 - $t5 := 3 - // return ($t5, $t4) - $result0 := $t5 - $result1 := $t4 + let res, $t3, $t4 + // $t3 := +($t0, $t1) + $t3 := $AddU64(x, y) + // $t4 := 3 + $t4 := 3 + // return ($t4, $t3) + $result0 := $t4 + $result1 := $t3 } function $Abort(code) { @@ -615,7 +635,7 @@ object "test_A2_M_test_add_two_number_wrong_assert" { } } } -===> Test result of M::test_add_two_number_wrong_assert: Revert(Reverted) (used_gas=356): [0, 0, 0, 0, 0, 0, 0, 101] +===> Test result of M::test_add_two_number_wrong_assert: Revert(Reverted) (used_gas=545): [0, 0, 0, 0, 0, 0, 0, 101] // test of M::test_arithmetic_ops_aborts /* ======================================= @@ -629,51 +649,61 @@ object "test_A2_M_test_arithmetic_ops_aborts" { A2_M_test_arithmetic_ops_aborts() return (0, 0) function A2_M_test_arithmetic_ops_aborts() { - let r1, r2, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10 + let r2, $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t7 := 100 - $t7 := 100 - // abort($t7) - $Abort($t7) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t8 := 3 - $t8 := 3 - // $t9 := ==($t4, $t8) - $t9 := $Eq($t4, $t8) - // if ($t9) goto L2 else goto L3 - switch $t9 - case 0 { $block := 5 } - default { $block := 6 } + // $t6 := 100 + $t6 := 100 + // abort($t6) + $Abort($t6) } case 4 { - // $t2 := 3 - $t2 := 3 - // ($t3, $t4) := M::arithmetic_ops($t2) - $t3, $t4 := A2_M_arithmetic_ops($t2) - // $t5 := 1 - $t5 := 1 - // $t6 := ==($t3, $t5) - $t6 := $Eq($t3, $t5) - // if ($t6) goto L0 else goto L1 - switch $t6 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := 3 + $t1 := 3 + // ($t2, $t3) := M::arithmetic_ops($t1) + $t2, $t3 := A2_M_arithmetic_ops($t1) + // $t4 := 1 + $t4 := 1 + // $t5 := ==($t2, $t4) + $t5 := $Eq($t2, $t4) + // if ($t5) goto L1 else goto L0 + switch $t5 + case 0 { $block := 3 } + default { $block := 2 } } case 5 { - // label L3 - // $t10 := 101 - $t10 := 101 - // abort($t10) - $Abort($t10) + // label L2 + // $t7 := 3 + $t7 := 3 + // $t8 := ==($t3, $t7) + $t8 := $Eq($t3, $t7) + // if ($t8) goto L4 else goto L3 + switch $t8 + case 0 { $block := 7 } + default { $block := 6 } } case 6 { - // label L2 + // label L4 + // goto L5 + $block := 8 + } + case 7 { + // label L3 + // $t9 := 101 + $t9 := 101 + // abort($t9) + $Abort($t9) + } + case 8 { + // label L5 // return () leave } @@ -686,14 +716,14 @@ object "test_A2_M_test_arithmetic_ops_aborts" { for {} true {} { switch $block case 2 { - // label L0 + // label L1 // $t5 := 42 $t5 := 42 // abort($t5) $Abort($t5) } case 3 { - // label L2 + // label L0 // return ($t2, $t0) $result0 := $t2 $result1 := a @@ -706,7 +736,7 @@ object "test_A2_M_test_arithmetic_ops_aborts" { $t3 := 2 // $t4 := !=($t2, $t3) $t4 := $Neq($t2, $t3) - // if ($t4) goto L0 else goto L2 + // if ($t4) goto L1 else goto L0 switch $t4 case 0 { $block := 3 } default { $block := 2 } @@ -729,7 +759,7 @@ object "test_A2_M_test_arithmetic_ops_aborts" { } } } -===> Test result of M::test_arithmetic_ops_aborts: Revert(Reverted) (used_gas=404): [0, 0, 0, 0, 0, 0, 0, 100] +===> Test result of M::test_arithmetic_ops_aborts: Revert(Reverted) (used_gas=420): [0, 0, 0, 0, 0, 0, 0, 100] // test of M::test_bool_ops /* ======================================= @@ -743,53 +773,63 @@ object "test_A2_M_test_bool_ops" { A2_M_test_bool_ops() return (0, 0) function A2_M_test_bool_ops() { - let r1, r2, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11 + let r2, $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t8 := 100 - $t8 := 100 - // abort($t8) - $Abort($t8) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t9 := false - $t9 := false - // $t10 := ==($t5, $t9) - $t10 := $Eq($t5, $t9) - // if ($t10) goto L2 else goto L3 - switch $t10 - case 0 { $block := 5 } - default { $block := 6 } + // $t7 := 100 + $t7 := 100 + // abort($t7) + $Abort($t7) } case 4 { - // $t2 := 3 - $t2 := 3 - // $t3 := 2 - $t3 := 2 - // ($t4, $t5) := M::bool_ops($t2, $t3) - $t4, $t5 := A2_M_bool_ops($t2, $t3) - // $t6 := true - $t6 := true - // $t7 := ==($t4, $t6) - $t7 := $Eq($t4, $t6) - // if ($t7) goto L0 else goto L1 - switch $t7 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := 3 + $t1 := 3 + // $t2 := 2 + $t2 := 2 + // ($t3, $t4) := M::bool_ops($t1, $t2) + $t3, $t4 := A2_M_bool_ops($t1, $t2) + // $t5 := true + $t5 := true + // $t6 := ==($t3, $t5) + $t6 := $Eq($t3, $t5) + // if ($t6) goto L1 else goto L0 + switch $t6 + case 0 { $block := 3 } + default { $block := 2 } } case 5 { - // label L3 - // $t11 := 101 - $t11 := 101 - // abort($t11) - $Abort($t11) + // label L2 + // $t8 := false + $t8 := false + // $t9 := ==($t4, $t8) + $t9 := $Eq($t4, $t8) + // if ($t9) goto L4 else goto L3 + switch $t9 + case 0 { $block := 7 } + default { $block := 6 } } case 6 { - // label L2 + // label L4 + // goto L5 + $block := 8 + } + case 7 { + // label L3 + // $t10 := 101 + $t10 := 101 + // abort($t10) + $Abort($t10) + } + case 8 { + // label L5 // return () leave } @@ -802,34 +842,34 @@ object "test_A2_M_test_bool_ops" { for {} true {} { switch $block case 2 { - // label L0 + // label L1 // $t2 := >=($t0, $t1) tmp_$2 := $GtEq(a, b) - // goto L3 + // goto L2 $block := 5 } case 3 { - // label L2 + // label L0 // $t7 := false $t7 := false // $t2 := $t7 tmp_$2 := $t7 - // goto L3 + // goto L2 $block := 5 } case 4 { // $t6 := >($t0, $t1) $t6 := $Gt(a, b) - // if ($t6) goto L0 else goto L2 + // if ($t6) goto L1 else goto L0 switch $t6 case 0 { $block := 3 } default { $block := 2 } } case 5 { - // label L3 + // label L2 // $t8 := <($t0, $t1) $t8 := $Lt(a, b) - // if ($t8) goto L4 else goto L6 + // if ($t8) goto L4 else goto L3 switch $t8 case 0 { $block := 7 } default { $block := 6 } @@ -840,36 +880,36 @@ object "test_A2_M_test_bool_ops" { $t9 := true // $t3 := $t9 tmp_$3 := $t9 - // goto L7 + // goto L5 $block := 8 } case 7 { - // label L6 + // label L3 // $t3 := <=($t0, $t1) tmp_$3 := $LtEq(a, b) - // goto L7 + // goto L5 $block := 8 } case 8 { - // label L7 + // label L5 // $t10 := !=($t2, $t3) $t10 := $Neq(tmp_$2, tmp_$3) // $t11 := !($t10) $t11 := $LogicalNot($t10) - // if ($t11) goto L8 else goto L10 + // if ($t11) goto L7 else goto L6 switch $t11 case 0 { $block := 10 } default { $block := 9 } } case 9 { - // label L8 + // label L7 // $t12 := 42 $t12 := 42 // abort($t12) $Abort($t12) } case 10 { - // label L10 + // label L6 // return ($t2, $t3) $result0 := tmp_$2 $result1 := tmp_$3 @@ -905,7 +945,7 @@ object "test_A2_M_test_bool_ops" { } } } -===> Test result of M::test_bool_ops: Succeed(Stopped) (used_gas=1228): [] +===> Test result of M::test_bool_ops: Succeed(Stopped) (used_gas=1491): [] // test of M::test_bool_ops_aborts /* ======================================= @@ -925,20 +965,16 @@ object "test_A2_M_test_bool_ops_aborts" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t6 := 100 $t6 := 100 // abort($t6) $Abort($t6) } - case 3 { - // label L0 - // $t7 := !=($t2, $t3) - $t7 := $Neq($t2, $t3) - // if ($t7) goto L2 else goto L3 - switch $t7 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t2 := true $t2 := true @@ -948,72 +984,101 @@ object "test_A2_M_test_bool_ops_aborts" { $t4 := $Eq($t2, $t3) // $t5 := !($t4) $t5 := $LogicalNot($t4) - // if ($t5) goto L0 else goto L1 + // if ($t5) goto L1 else goto L0 switch $t5 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t7 := !=($t2, $t3) + $t7 := $Neq($t2, $t3) + // if ($t7) goto L4 else goto L3 + switch $t7 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t8 := 101 $t8 := 101 // abort($t8) $Abort($t8) } - case 6 { - // label L2 + case 8 { + // label L5 // $t9 := !($t2) $t9 := $LogicalNot($t2) // $t10 := !($t3) $t10 := $LogicalNot($t3) // $t11 := !=($t9, $t10) $t11 := $Neq($t9, $t10) - // if ($t11) goto L4 else goto L5 + // if ($t11) goto L7 else goto L6 switch $t11 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t12 := 102 $t12 := 102 // abort($t12) $Abort($t12) } - case 8 { - // label L4 + case 11 { + // label L8 // $t13 := !($t3) $t13 := $LogicalNot($t3) - // if ($t13) goto L6 else goto L7 + // if ($t13) goto L10 else goto L9 switch $t13 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t14 := 103 $t14 := 103 // abort($t14) $Abort($t14) } - case 10 { - // label L6 + case 14 { + // label L11 // $t15 := !($t2) $t15 := $LogicalNot($t2) - // if ($t15) goto L8 else goto L9 + // if ($t15) goto L13 else goto L12 switch $t15 - case 0 { $block := 11 } - default { $block := 12 } + case 0 { $block := 16 } + default { $block := 15 } } - case 11 { - // label L9 + case 15 { + // label L13 + // goto L14 + $block := 17 + } + case 16 { + // label L12 // $t16 := 104 $t16 := 104 // abort($t16) $Abort($t16) } - case 12 { - // label L8 + case 17 { + // label L14 // return () leave } @@ -1035,7 +1100,7 @@ object "test_A2_M_test_bool_ops_aborts" { } } } -===> Test result of M::test_bool_ops_aborts: Revert(Reverted) (used_gas=1081): [0, 0, 0, 0, 0, 0, 0, 104] +===> Test result of M::test_bool_ops_aborts: Revert(Reverted) (used_gas=2075): [0, 0, 0, 0, 0, 0, 0, 104] // test of M::test_div /* ======================================= @@ -1049,53 +1114,63 @@ object "test_A2_M_test_div" { A2_M_test_div() return (0, 0) function A2_M_test_div() { - let r1, r2, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11 + let r2, $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t8 := 100 - $t8 := 100 - // abort($t8) - $Abort($t8) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t9 := 3 - $t9 := 3 - // $t10 := ==($t5, $t9) - $t10 := $Eq($t5, $t9) - // if ($t10) goto L2 else goto L3 - switch $t10 - case 0 { $block := 5 } - default { $block := 6 } + // $t7 := 100 + $t7 := 100 + // abort($t7) + $Abort($t7) } case 4 { - // $t2 := 7 - $t2 := 7 - // $t3 := 4 - $t3 := 4 - // ($t4, $t5) := M::div($t2, $t3) - $t4, $t5 := A2_M_div($t2, $t3) - // $t6 := 1 - $t6 := 1 - // $t7 := ==($t4, $t6) - $t7 := $Eq($t4, $t6) - // if ($t7) goto L0 else goto L1 - switch $t7 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := 7 + $t1 := 7 + // $t2 := 4 + $t2 := 4 + // ($t3, $t4) := M::div($t1, $t2) + $t3, $t4 := A2_M_div($t1, $t2) + // $t5 := 1 + $t5 := 1 + // $t6 := ==($t3, $t5) + $t6 := $Eq($t3, $t5) + // if ($t6) goto L1 else goto L0 + switch $t6 + case 0 { $block := 3 } + default { $block := 2 } } case 5 { - // label L3 - // $t11 := 101 - $t11 := 101 - // abort($t11) - $Abort($t11) + // label L2 + // $t8 := 3 + $t8 := 3 + // $t9 := ==($t4, $t8) + $t9 := $Eq($t4, $t8) + // if ($t9) goto L4 else goto L3 + switch $t9 + case 0 { $block := 7 } + default { $block := 6 } } case 6 { - // label L2 + // label L4 + // goto L5 + $block := 8 + } + case 7 { + // label L3 + // $t10 := 101 + $t10 := 101 + // abort($t10) + $Abort($t10) + } + case 8 { + // label L5 // return () leave } @@ -1133,7 +1208,7 @@ object "test_A2_M_test_div" { } } } -===> Test result of M::test_div: Succeed(Stopped) (used_gas=355): [] +===> Test result of M::test_div: Succeed(Stopped) (used_gas=661): [] // test of M::test_div_by_zero /* ======================================= @@ -1147,15 +1222,15 @@ object "test_A2_M_test_div_by_zero" { A2_M_test_div_by_zero() return (0, 0) function A2_M_test_div_by_zero() { - let _r1, _r2, $t2, $t3, $t4, $t5 - // $t2 := 7 - $t2 := 7 - // $t3 := 0 - $t3 := 0 - // ($t4, $t5) := M::div($t2, $t3) - $t4, $t5 := A2_M_div($t2, $t3) - // destroy($t5) - // destroy($t4) + let $t0, $t1, $t2, $t3 + // $t0 := 7 + $t0 := 7 + // $t1 := 0 + $t1 := 0 + // ($t2, $t3) := M::div($t0, $t1) + $t2, $t3 := A2_M_div($t0, $t1) + // destroy($t3) + // destroy($t2) // return () } @@ -1201,53 +1276,63 @@ object "test_A2_M_test_div_wrong_assert" { A2_M_test_div_wrong_assert() return (0, 0) function A2_M_test_div_wrong_assert() { - let r1, r2, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11 + let r2, $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t8 := 100 - $t8 := 100 - // abort($t8) - $Abort($t8) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t9 := 2 - $t9 := 2 - // $t10 := ==($t5, $t9) - $t10 := $Eq($t5, $t9) - // if ($t10) goto L2 else goto L3 - switch $t10 - case 0 { $block := 5 } - default { $block := 6 } + // $t7 := 100 + $t7 := 100 + // abort($t7) + $Abort($t7) } case 4 { - // $t2 := 7 - $t2 := 7 - // $t3 := 4 - $t3 := 4 - // ($t4, $t5) := M::div($t2, $t3) - $t4, $t5 := A2_M_div($t2, $t3) - // $t6 := 1 - $t6 := 1 - // $t7 := ==($t4, $t6) - $t7 := $Eq($t4, $t6) - // if ($t7) goto L0 else goto L1 - switch $t7 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := 7 + $t1 := 7 + // $t2 := 4 + $t2 := 4 + // ($t3, $t4) := M::div($t1, $t2) + $t3, $t4 := A2_M_div($t1, $t2) + // $t5 := 1 + $t5 := 1 + // $t6 := ==($t3, $t5) + $t6 := $Eq($t3, $t5) + // if ($t6) goto L1 else goto L0 + switch $t6 + case 0 { $block := 3 } + default { $block := 2 } } case 5 { - // label L3 - // $t11 := 101 - $t11 := 101 - // abort($t11) - $Abort($t11) + // label L2 + // $t8 := 2 + $t8 := 2 + // $t9 := ==($t4, $t8) + $t9 := $Eq($t4, $t8) + // if ($t9) goto L4 else goto L3 + switch $t9 + case 0 { $block := 7 } + default { $block := 6 } } case 6 { - // label L2 + // label L4 + // goto L5 + $block := 8 + } + case 7 { + // label L3 + // $t10 := 101 + $t10 := 101 + // abort($t10) + $Abort($t10) + } + case 8 { + // label L5 // return () leave } @@ -1285,7 +1370,7 @@ object "test_A2_M_test_div_wrong_assert" { } } } -===> Test result of M::test_div_wrong_assert: Revert(Reverted) (used_gas=348): [0, 0, 0, 0, 0, 0, 0, 101] +===> Test result of M::test_div_wrong_assert: Revert(Reverted) (used_gas=529): [0, 0, 0, 0, 0, 0, 0, 101] // test of M::test_multiple_ops /* ======================================= @@ -1299,39 +1384,44 @@ object "test_A2_M_test_multiple_ops" { A2_M_test_multiple_ops() return (0, 0) function A2_M_test_multiple_ops() { - let r, $t1, $t2, $t3, $t4, $t5, $t6, $t7 + let $t0, $t1, $t2, $t3, $t4, $t5, $t6 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t7 := 100 - $t7 := 100 - // abort($t7) - $Abort($t7) + // goto L2 + $block := 5 } case 3 { // label L0 - // return () - leave + // $t6 := 100 + $t6 := 100 + // abort($t6) + $Abort($t6) } case 4 { - // $t1 := 3 - $t1 := 3 - // $t2 := 2 - $t2 := 2 - // $t3 := 5 - $t3 := 5 - // $t4 := M::multiple_ops($t1, $t2, $t3) - $t4 := A2_M_multiple_ops($t1, $t2, $t3) - // $t5 := 13 - $t5 := 13 - // $t6 := ==($t4, $t5) - $t6 := $Eq($t4, $t5) - // if ($t6) goto L0 else goto L1 - switch $t6 - case 0 { $block := 2 } - default { $block := 3 } + // $t0 := 3 + $t0 := 3 + // $t1 := 2 + $t1 := 2 + // $t2 := 5 + $t2 := 5 + // $t3 := M::multiple_ops($t0, $t1, $t2) + $t3 := A2_M_multiple_ops($t0, $t1, $t2) + // $t4 := 13 + $t4 := 13 + // $t5 := ==($t3, $t4) + $t5 := $Eq($t3, $t4) + // if ($t5) goto L1 else goto L0 + switch $t5 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // return () + leave } } } @@ -1366,7 +1456,7 @@ object "test_A2_M_test_multiple_ops" { } } } -===> Test result of M::test_multiple_ops: Succeed(Stopped) (used_gas=176): [] +===> Test result of M::test_multiple_ops: Succeed(Stopped) (used_gas=265): [] // test of M::test_multiple_overflow /* ======================================= @@ -1380,39 +1470,44 @@ object "test_A2_M_test_multiple_overflow" { A2_M_test_multiple_overflow() return (0, 0) function A2_M_test_multiple_overflow() { - let r, $t1, $t2, $t3, $t4, $t5, $t6, $t7 + let $t0, $t1, $t2, $t3, $t4, $t5, $t6 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t7 := 100 - $t7 := 100 - // abort($t7) - $Abort($t7) + // goto L2 + $block := 5 } case 3 { // label L0 - // return () - leave + // $t6 := 100 + $t6 := 100 + // abort($t6) + $Abort($t6) } case 4 { - // $t1 := 0 - $t1 := 0 - // $t2 := 18446744073709551615 - $t2 := 18446744073709551615 - // $t3 := 2 - $t3 := 2 - // $t4 := M::multiple_ops($t1, $t2, $t3) - $t4 := A2_M_multiple_ops($t1, $t2, $t3) - // $t5 := 0 - $t5 := 0 - // $t6 := ==($t4, $t5) - $t6 := $Eq($t4, $t5) - // if ($t6) goto L0 else goto L1 - switch $t6 - case 0 { $block := 2 } - default { $block := 3 } + // $t0 := 0 + $t0 := 0 + // $t1 := 18446744073709551615 + $t1 := 18446744073709551615 + // $t2 := 2 + $t2 := 2 + // $t3 := M::multiple_ops($t0, $t1, $t2) + $t3 := A2_M_multiple_ops($t0, $t1, $t2) + // $t4 := 0 + $t4 := 0 + // $t5 := ==($t3, $t4) + $t5 := $Eq($t3, $t4) + // if ($t5) goto L1 else goto L0 + switch $t5 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // return () + leave } } } @@ -1447,7 +1542,7 @@ object "test_A2_M_test_multiple_overflow" { } } } -===> Test result of M::test_multiple_overflow: Revert(Reverted) (used_gas=21): [255, 255, 255, 255, 255, 255, 255, 255] +===> Test result of M::test_multiple_overflow: Revert(Reverted) (used_gas=125): [255, 255, 255, 255, 255, 255, 255, 255] // test of M::test_underflow /* ======================================= @@ -1461,23 +1556,23 @@ object "test_A2_M_test_underflow" { A2_M_test_underflow() return (0, 0) function A2_M_test_underflow() { - let _r, $t1 - // $t1 := M::underflow() - $t1 := A2_M_underflow() - // destroy($t1) + let $t0 + // $t0 := M::underflow() + $t0 := A2_M_underflow() + // destroy($t0) // return () } function A2_M_underflow() -> $result { - let x, $t1, $t2, $t3 - // $t1 := 0 - $t1 := 0 - // $t2 := 1 - $t2 := 1 - // $t3 := -($t1, $t2) - $t3 := $Sub($t1, $t2) - // return $t3 - $result := $t3 + let $t0, $t1, $t2 + // $t0 := 0 + $t0 := 0 + // $t1 := 1 + $t1 := 1 + // $t2 := -($t0, $t1) + $t2 := $Sub($t0, $t1) + // return $t2 + $result := $t2 } function $Abort(code) { diff --git a/language/evm/move-to-yul/tests/ControlStructures.exp b/language/evm/move-to-yul/tests/ControlStructures.exp index 91e40dfac2..f2832b853d 100644 --- a/language/evm/move-to-yul/tests/ControlStructures.exp +++ b/language/evm/move-to-yul/tests/ControlStructures.exp @@ -76,57 +76,62 @@ object "A2_M" { for {} true {} { switch $block case 2 { - // label L0 - // $t3 := 2 - $t3 := 2 - // $t4 := %($t0, $t3) - $t4 := $Mod(x, $t3) - // $t5 := 0 - $t5 := 0 - // $t6 := ==($t4, $t5) - $t6 := $Eq($t4, $t5) - // if ($t6) goto L3 else goto L5 - switch $t6 - case 0 { $block := 6 } - default { $block := 5 } + // label L1 + // goto L2 + $block := 5 } case 3 { - // label L2 + // label L0 // return () leave } case 4 { - // label L7 + // label L6 // $t1 := 0 $t1 := 0 // $t2 := >($t0, $t1) $t2 := $Gt(x, $t1) - // if ($t2) goto L0 else goto L2 + // if ($t2) goto L1 else goto L0 switch $t2 case 0 { $block := 3 } default { $block := 2 } } case 5 { - // label L3 + // label L2 + // $t3 := 2 + $t3 := 2 + // $t4 := %($t0, $t3) + $t4 := $Mod(x, $t3) + // $t5 := 0 + $t5 := 0 + // $t6 := ==($t4, $t5) + $t6 := $Eq($t4, $t5) + // if ($t6) goto L4 else goto L3 + switch $t6 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 // $t7 := 1 $t7 := 1 // $t0 := +($t0, $t7) x := $AddU64(x, $t7) - // goto L6 - $block := 7 + // goto L5 + $block := 8 } - case 6 { - // label L5 + case 7 { + // label L3 // $t8 := 2 $t8 := 2 // $t0 := -($t0, $t8) x := $Sub(x, $t8) - // goto L6 - $block := 7 + // goto L5 + $block := 8 } - case 7 { - // label L6 - // goto L7 + case 8 { + // label L5 + // goto L6 $block := 4 } } @@ -138,24 +143,20 @@ object "A2_M" { for {} true {} { switch $block case 2 { - // label L0 - // $t3 := 1 - $t3 := 1 - // $t0 := -($t0, $t3) - x := $Sub(x, $t3) - // goto L3 - $block := 4 + // label L1 + // goto L2 + $block := 5 } case 3 { - // label L2 + // label L0 // $t4 := 0 $t4 := 0 // $t5 := ==($t0, $t4) $t5 := $Eq(x, $t4) - // if ($t5) goto L4 else goto L3 + // if ($t5) goto L5 else goto L4 switch $t5 - case 0 { $block := 4 } - default { $block := 5 } + case 0 { $block := 7 } + default { $block := 6 } } case 4 { // label L3 @@ -163,13 +164,32 @@ object "A2_M" { $t1 := 1 // $t2 := >=($t0, $t1) $t2 := $GtEq(x, $t1) - // if ($t2) goto L0 else goto L2 + // if ($t2) goto L1 else goto L0 switch $t2 case 0 { $block := 3 } default { $block := 2 } } case 5 { + // label L2 + // $t3 := 1 + $t3 := 1 + // $t0 := -($t0, $t3) + x := $Sub(x, $t3) + // goto L3 + $block := 4 + } + case 6 { + // label L5 + // goto L6 + $block := 8 + } + case 7 { // label L4 + // goto L3 + $block := 4 + } + case 8 { + // label L6 // return () leave } @@ -182,21 +202,21 @@ object "A2_M" { for {} true {} { switch $block case 2 { - // label L0 + // label L1 // $t4 := 1 $t4 := 1 // $t1 := $t4 tmp_$1 := $t4 - // goto L3 + // goto L2 $block := 5 } case 3 { - // label L2 + // label L0 // $t5 := 2 $t5 := 2 // $t1 := $t5 tmp_$1 := $t5 - // goto L3 + // goto L2 $block := 5 } case 4 { @@ -204,13 +224,13 @@ object "A2_M" { $t2 := 0 // $t3 := >($t0, $t2) $t3 := $Gt(x, $t2) - // if ($t3) goto L0 else goto L2 + // if ($t3) goto L1 else goto L0 switch $t3 case 0 { $block := 3 } default { $block := 2 } } case 5 { - // label L3 + // label L2 // return $t1 $result := tmp_$1 leave @@ -224,14 +244,14 @@ object "A2_M" { for {} true {} { switch $block case 2 { - // label L0 + // label L1 // $t3 := 1 $t3 := 1 // abort($t3) $Abort($t3) } case 3 { - // label L2 + // label L0 // return () leave } @@ -240,7 +260,7 @@ object "A2_M" { $t1 := 0 // $t2 := >($t0, $t1) $t2 := $Gt(x, $t1) - // if ($t2) goto L0 else goto L2 + // if ($t2) goto L1 else goto L0 switch $t2 case 0 { $block := 3 } default { $block := 2 } diff --git a/language/evm/move-to-yul/tests/GlobalVectors.exp b/language/evm/move-to-yul/tests/GlobalVectors.exp index 35221656ad..fcee1e13c2 100644 --- a/language/evm/move-to-yul/tests/GlobalVectors.exp +++ b/language/evm/move-to-yul/tests/GlobalVectors.exp @@ -54,17 +54,16 @@ object "test_A2_GlobalVectors_test_borrow_mut_global" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t27 := 102 $t27 := 102 // abort($t27) $Abort($t27) } - case 3 { - // label L0 - // return () - $Free($locals, 64) - leave - } case 4 { // $t2 := vector::empty() mstore($locals, A1_vector_empty$u64$()) @@ -169,10 +168,16 @@ object "test_A2_GlobalVectors_test_borrow_mut_global" { $t25 := 12 // $t26 := ==($t24, $t25) $t26 := $Eq($t24, $t25) - // if ($t26) goto L0 else goto L1 + // if ($t26) goto L1 else goto L0 switch $t26 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // return () + $Free($locals, 64) + leave } } } @@ -437,7 +442,7 @@ object "test_A2_GlobalVectors_test_borrow_mut_global" { } } } -===> Test result of GlobalVectors::test_borrow_mut_global: Succeed(Stopped) (used_gas=117306): [] +===> Test result of GlobalVectors::test_borrow_mut_global: Succeed(Stopped) (used_gas=117389): [] // test of GlobalVectors::test_move_from /* ======================================= @@ -451,82 +456,68 @@ object "test_A2_GlobalVectors_test_move_from" { A2_GlobalVectors_test_move_from() return (0, 0) function A2_GlobalVectors_test_move_from() { - let local_t, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20, $t21, $t22, $t23, $t24, $t25, $t26, $t27, $t28, $t29, $t30, $t31, $t32, $t33, $t34, $t35, $t36, $t37, $t38, $t39, $t40, $t41, $t42, $t43, $t44, $t45, $t46, $t47, $t48, $t49, $t50, $t51, $t52, $t53, $t54, $t55, $t56, $t57, $t58, $t59 + let $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20, $t21, $t22, $t23, $t24, $t25, $t26, $t27, $t28, $t29, $t30, $t31, $t32, $t33, $t34, $t35, $t36, $t37, $t38, $t39, $t40, $t41, $t42, $t43, $t44, $t45, $t46, $t47, $t48, $t49, $t50, $t51, $t52, $t53, $t54, $t55, $t56, $t57, $t58 let $locals := $Malloc(96) let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t20 := 101 - $t20 := 101 - // abort($t20) - $Abort($t20) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t21 := borrow_local($t3) - $t21 := $MakePtr(false, add($locals, 64)) - // $t22 := 0 - $t22 := 0 - // $t23 := vector::borrow($t21, $t22) - $t23 := A1_vector_borrow$u64$($t21, $t22) - // $t24 := read_ref($t23) - $t24 := $LoadU64($t23) - // $t25 := 10 - $t25 := 10 - // $t26 := ==($t24, $t25) - $t26 := $Eq($t24, $t25) - // if ($t26) goto L2 else goto L3 - switch $t26 - case 0 { $block := 5 } - default { $block := 6 } + // $t19 := 101 + $t19 := 101 + // abort($t19) + $Abort($t19) } case 4 { - // $t2 := vector::empty() + // $t1 := vector::empty() mstore($locals, A1_vector_empty$u64$()) - // $t4 := borrow_local($t2) - $t4 := $MakePtr(false, $locals) - // $t5 := 10 - $t5 := 10 - // vector::push_back($t4, $t5) - A1_vector_push_back$u64$($t4, $t5) - // $t6 := borrow_local($t2) - $t6 := $MakePtr(false, $locals) - // $t7 := 11 - $t7 := 11 - // vector::push_back($t6, $t7) - A1_vector_push_back$u64$($t6, $t7) - // $t8 := borrow_local($t2) - $t8 := $MakePtr(false, $locals) - // $t9 := 12 - $t9 := 12 - // vector::push_back($t8, $t9) - A1_vector_push_back$u64$($t8, $t9) - // $t10 := 0x42 - $t10 := 0x42 - // $t0 := Evm::sign($t10) - mstore(add($locals, 32), A2_Evm_sign($t10)) - // $t11 := borrow_local($t0) - $t11 := $MakePtr(false, add($locals, 32)) - // $t12 := move($t2) - $t12 := mload($locals) - // $t13 := pack GlobalVectors::T($t12) + // $t3 := borrow_local($t1) + $t3 := $MakePtr(false, $locals) + // $t4 := 10 + $t4 := 10 + // vector::push_back($t3, $t4) + A1_vector_push_back$u64$($t3, $t4) + // $t5 := borrow_local($t1) + $t5 := $MakePtr(false, $locals) + // $t6 := 11 + $t6 := 11 + // vector::push_back($t5, $t6) + A1_vector_push_back$u64$($t5, $t6) + // $t7 := borrow_local($t1) + $t7 := $MakePtr(false, $locals) + // $t8 := 12 + $t8 := 12 + // vector::push_back($t7, $t8) + A1_vector_push_back$u64$($t7, $t8) + // $t9 := 0x42 + $t9 := 0x42 + // $t0 := Evm::sign($t9) + mstore(add($locals, 32), A2_Evm_sign($t9)) + // $t10 := borrow_local($t0) + $t10 := $MakePtr(false, add($locals, 32)) + // $t11 := move($t1) + $t11 := mload($locals) + // $t12 := pack GlobalVectors::T($t11) { let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t12) - $t13 := $mem + $MemoryStoreU256(add($mem, 0), $t11) + $t12 := $mem } - // move_to>($t13, $t11) + // move_to>($t12, $t10) { - let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $LoadU256($t11)) + let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $LoadU256($t10)) if $AlignedStorageLoad($base_offset) { $AbortBuiltin() } $AlignedStorageStore($base_offset, true) { let $dst := add($base_offset, 32) - let $src := $t13 + let $src := $t12 { let $linked_src_814019441 := mload(add($src, 0)) let $linked_dst_814019441 := $NewLinkedStorageBase(0x3084f371) @@ -544,11 +535,11 @@ object "test_A2_GlobalVectors_test_move_from" { $Free($src, 32) } } - // $t14 := 0x42 - $t14 := 0x42 - // $t15 := move_from>($t14) + // $t13 := 0x42 + $t13 := 0x42 + // $t14 := move_from>($t13) { - let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $t14) + let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $t13) if iszero($AlignedStorageLoad($base_offset)) { $AbortBuiltin() } @@ -575,150 +566,194 @@ object "test_A2_GlobalVectors_test_move_from" { mstore(add($dst, 0), $linked_dst_814019441) $AlignedStorageStore(add($src, 0), 0) } - $t15 := $dst + $t14 := $dst } } - // $t3 := unpack GlobalVectors::T($t15) - mstore(add($locals, 64), $MemoryLoadU256(add($t15, 0))) - $Free($t15, 32) - // $t16 := borrow_local($t3) - $t16 := $MakePtr(false, add($locals, 64)) - // $t17 := vector::length($t16) - $t17 := A1_vector_length$u64$($t16) - // $t18 := 3 - $t18 := 3 - // $t19 := ==($t17, $t18) - $t19 := $Eq($t17, $t18) - // if ($t19) goto L0 else goto L1 - switch $t19 - case 0 { $block := 2 } - default { $block := 3 } + // $t2 := unpack GlobalVectors::T($t14) + mstore(add($locals, 64), $MemoryLoadU256(add($t14, 0))) + $Free($t14, 32) + // $t15 := borrow_local($t2) + $t15 := $MakePtr(false, add($locals, 64)) + // $t16 := vector::length($t15) + $t16 := A1_vector_length$u64$($t15) + // $t17 := 3 + $t17 := 3 + // $t18 := ==($t16, $t17) + $t18 := $Eq($t16, $t17) + // if ($t18) goto L1 else goto L0 + switch $t18 + case 0 { $block := 3 } + default { $block := 2 } } case 5 { - // label L3 - // $t27 := 102 - $t27 := 102 - // abort($t27) - $Abort($t27) - } - case 6 { // label L2 - // $t28 := borrow_local($t3) - $t28 := $MakePtr(false, add($locals, 64)) - // $t29 := 1 - $t29 := 1 - // $t30 := vector::borrow($t28, $t29) - $t30 := A1_vector_borrow$u64$($t28, $t29) - // $t31 := read_ref($t30) - $t31 := $LoadU64($t30) - // $t32 := 11 - $t32 := 11 - // $t33 := ==($t31, $t32) - $t33 := $Eq($t31, $t32) - // if ($t33) goto L4 else goto L5 - switch $t33 + // $t20 := borrow_local($t2) + $t20 := $MakePtr(false, add($locals, 64)) + // $t21 := 0 + $t21 := 0 + // $t22 := vector::borrow($t20, $t21) + $t22 := A1_vector_borrow$u64$($t20, $t21) + // $t23 := read_ref($t22) + $t23 := $LoadU64($t22) + // $t24 := 10 + $t24 := 10 + // $t25 := ==($t23, $t24) + $t25 := $Eq($t23, $t24) + // if ($t25) goto L4 else goto L3 + switch $t25 case 0 { $block := 7 } - default { $block := 8 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 } case 7 { - // label L5 - // $t34 := 103 - $t34 := 103 - // abort($t34) - $Abort($t34) + // label L3 + // $t26 := 102 + $t26 := 102 + // abort($t26) + $Abort($t26) } case 8 { - // label L4 - // $t35 := borrow_local($t3) - $t35 := $MakePtr(false, add($locals, 64)) - // $t36 := 2 - $t36 := 2 - // $t37 := vector::borrow($t35, $t36) - $t37 := A1_vector_borrow$u64$($t35, $t36) - // $t38 := read_ref($t37) - $t38 := $LoadU64($t37) - // $t39 := 12 - $t39 := 12 - // $t40 := ==($t38, $t39) - $t40 := $Eq($t38, $t39) - // if ($t40) goto L6 else goto L7 - switch $t40 - case 0 { $block := 9 } - default { $block := 10 } + // label L5 + // $t27 := borrow_local($t2) + $t27 := $MakePtr(false, add($locals, 64)) + // $t28 := 1 + $t28 := 1 + // $t29 := vector::borrow($t27, $t28) + $t29 := A1_vector_borrow$u64$($t27, $t28) + // $t30 := read_ref($t29) + $t30 := $LoadU64($t29) + // $t31 := 11 + $t31 := 11 + // $t32 := ==($t30, $t31) + $t32 := $Eq($t30, $t31) + // if ($t32) goto L7 else goto L6 + switch $t32 + case 0 { $block := 10 } + default { $block := 9 } } case 9 { // label L7 - // $t41 := 104 - $t41 := 104 - // abort($t41) - $Abort($t41) + // goto L8 + $block := 11 } case 10 { // label L6 - // $t42 := borrow_local($t3) - $t42 := $MakePtr(false, add($locals, 64)) - // $t43 := 13 - $t43 := 13 - // vector::push_back($t42, $t43) - A1_vector_push_back$u64$($t42, $t43) - // $t44 := borrow_local($t3) - $t44 := $MakePtr(false, add($locals, 64)) - // $t45 := 14 - $t45 := 14 - // vector::push_back($t44, $t45) - A1_vector_push_back$u64$($t44, $t45) - // $t46 := borrow_local($t3) - $t46 := $MakePtr(false, add($locals, 64)) - // $t47 := 3 - $t47 := 3 - // $t48 := vector::borrow($t46, $t47) - $t48 := A1_vector_borrow$u64$($t46, $t47) - // $t49 := read_ref($t48) - $t49 := $LoadU64($t48) - // $t50 := 13 - $t50 := 13 - // $t51 := ==($t49, $t50) - $t51 := $Eq($t49, $t50) - // if ($t51) goto L8 else goto L9 - switch $t51 - case 0 { $block := 11 } - default { $block := 12 } + // $t33 := 103 + $t33 := 103 + // abort($t33) + $Abort($t33) } case 11 { - // label L9 - // $t52 := 105 - $t52 := 105 - // abort($t52) - $Abort($t52) - } - case 12 { // label L8 - // $t53 := borrow_local($t3) - $t53 := $MakePtr(false, add($locals, 64)) - // $t54 := 4 - $t54 := 4 - // $t55 := vector::borrow($t53, $t54) - $t55 := A1_vector_borrow$u64$($t53, $t54) - // $t56 := read_ref($t55) - $t56 := $LoadU64($t55) - // $t57 := 14 - $t57 := 14 - // $t58 := ==($t56, $t57) - $t58 := $Eq($t56, $t57) - // if ($t58) goto L10 else goto L11 - switch $t58 + // $t34 := borrow_local($t2) + $t34 := $MakePtr(false, add($locals, 64)) + // $t35 := 2 + $t35 := 2 + // $t36 := vector::borrow($t34, $t35) + $t36 := A1_vector_borrow$u64$($t34, $t35) + // $t37 := read_ref($t36) + $t37 := $LoadU64($t36) + // $t38 := 12 + $t38 := 12 + // $t39 := ==($t37, $t38) + $t39 := $Eq($t37, $t38) + // if ($t39) goto L10 else goto L9 + switch $t39 case 0 { $block := 13 } - default { $block := 14 } + default { $block := 12 } + } + case 12 { + // label L10 + // goto L11 + $block := 14 } case 13 { - // label L11 - // $t59 := 106 - $t59 := 106 - // abort($t59) - $Abort($t59) + // label L9 + // $t40 := 104 + $t40 := 104 + // abort($t40) + $Abort($t40) } case 14 { - // label L10 + // label L11 + // $t41 := borrow_local($t2) + $t41 := $MakePtr(false, add($locals, 64)) + // $t42 := 13 + $t42 := 13 + // vector::push_back($t41, $t42) + A1_vector_push_back$u64$($t41, $t42) + // $t43 := borrow_local($t2) + $t43 := $MakePtr(false, add($locals, 64)) + // $t44 := 14 + $t44 := 14 + // vector::push_back($t43, $t44) + A1_vector_push_back$u64$($t43, $t44) + // $t45 := borrow_local($t2) + $t45 := $MakePtr(false, add($locals, 64)) + // $t46 := 3 + $t46 := 3 + // $t47 := vector::borrow($t45, $t46) + $t47 := A1_vector_borrow$u64$($t45, $t46) + // $t48 := read_ref($t47) + $t48 := $LoadU64($t47) + // $t49 := 13 + $t49 := 13 + // $t50 := ==($t48, $t49) + $t50 := $Eq($t48, $t49) + // if ($t50) goto L13 else goto L12 + switch $t50 + case 0 { $block := 16 } + default { $block := 15 } + } + case 15 { + // label L13 + // goto L14 + $block := 17 + } + case 16 { + // label L12 + // $t51 := 105 + $t51 := 105 + // abort($t51) + $Abort($t51) + } + case 17 { + // label L14 + // $t52 := borrow_local($t2) + $t52 := $MakePtr(false, add($locals, 64)) + // $t53 := 4 + $t53 := 4 + // $t54 := vector::borrow($t52, $t53) + $t54 := A1_vector_borrow$u64$($t52, $t53) + // $t55 := read_ref($t54) + $t55 := $LoadU64($t54) + // $t56 := 14 + $t56 := 14 + // $t57 := ==($t55, $t56) + $t57 := $Eq($t55, $t56) + // if ($t57) goto L16 else goto L15 + switch $t57 + case 0 { $block := 19 } + default { $block := 18 } + } + case 18 { + // label L16 + // goto L17 + $block := 20 + } + case 19 { + // label L15 + // $t58 := 106 + $t58 := 106 + // abort($t58) + $Abort($t58) + } + case 20 { + // label L17 // return () $Free($locals, 96) leave @@ -993,7 +1028,7 @@ object "test_A2_GlobalVectors_test_move_from" { } } } -===> Test result of GlobalVectors::test_move_from: Succeed(Stopped) (used_gas=97011): [] +===> Test result of GlobalVectors::test_move_from: Succeed(Stopped) (used_gas=98498): [] // test of GlobalVectors::test_move_from_vector_of_struct /* ======================================= @@ -1014,34 +1049,16 @@ object "test_A2_GlobalVectors_test_move_from_vector_of_struct" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t25 := 101 $t25 := 101 // abort($t25) $Abort($t25) } - case 3 { - // label L0 - // $t26 := borrow_local($t1) - $t26 := $MakePtr(false, local_t) - // $t27 := borrow_field>.v($t26) - $t27 := $t26 - // $t28 := 0 - $t28 := 0 - // $t29 := vector::borrow($t27, $t28) - $t29 := A1_vector_borrow$A2_GlobalVectors_S$($t27, $t28) - // $t30 := borrow_field.x($t29) - $t30 := $t29 - // $t31 := read_ref($t30) - $t31 := $LoadU128($t30) - // $t32 := 10 - $t32 := 10 - // $t33 := ==($t31, $t32) - $t33 := $Eq($t31, $t32) - // if ($t33) goto L2 else goto L3 - switch $t33 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t2 := vector::empty() mstore($locals, A1_vector_empty$A2_GlobalVectors_S$()) @@ -1188,20 +1205,48 @@ object "test_A2_GlobalVectors_test_move_from_vector_of_struct" { $t23 := 3 // $t24 := ==($t22, $t23) $t24 := $Eq($t22, $t23) - // if ($t24) goto L0 else goto L1 + // if ($t24) goto L1 else goto L0 switch $t24 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t26 := borrow_local($t1) + $t26 := $MakePtr(false, local_t) + // $t27 := borrow_field>.v($t26) + $t27 := $t26 + // $t28 := 0 + $t28 := 0 + // $t29 := vector::borrow($t27, $t28) + $t29 := A1_vector_borrow$A2_GlobalVectors_S$($t27, $t28) + // $t30 := borrow_field.x($t29) + $t30 := $t29 + // $t31 := read_ref($t30) + $t31 := $LoadU128($t30) + // $t32 := 10 + $t32 := 10 + // $t33 := ==($t31, $t32) + $t33 := $Eq($t31, $t32) + // if ($t33) goto L4 else goto L3 + switch $t33 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t34 := 102 $t34 := 102 // abort($t34) $Abort($t34) } - case 6 { - // label L2 + case 8 { + // label L5 // $t35 := borrow_local($t1) $t35 := $MakePtr(false, local_t) // $t36 := borrow_field>.v($t35) @@ -1218,20 +1263,25 @@ object "test_A2_GlobalVectors_test_move_from_vector_of_struct" { $t41 := 11 // $t42 := ==($t40, $t41) $t42 := $Eq($t40, $t41) - // if ($t42) goto L4 else goto L5 + // if ($t42) goto L7 else goto L6 switch $t42 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t43 := 103 $t43 := 103 // abort($t43) $Abort($t43) } - case 8 { - // label L4 + case 11 { + // label L8 // $t44 := borrow_local($t1) $t44 := $MakePtr(false, local_t) // $t45 := borrow_field>.v($t44) @@ -1248,20 +1298,25 @@ object "test_A2_GlobalVectors_test_move_from_vector_of_struct" { $t50 := 12 // $t51 := ==($t49, $t50) $t51 := $Eq($t49, $t50) - // if ($t51) goto L6 else goto L7 + // if ($t51) goto L10 else goto L9 switch $t51 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 - // $t52 := 104 - $t52 := 104 - // abort($t52) - $Abort($t52) + case 12 { + // label L10 + // goto L11 + $block := 14 } - case 10 { - // label L6 + case 13 { + // label L9 + // $t52 := 104 + $t52 := 104 + // abort($t52) + $Abort($t52) + } + case 14 { + // label L11 // return () $Free($locals, 64) leave @@ -1564,7 +1619,7 @@ object "test_A2_GlobalVectors_test_move_from_vector_of_struct" { } } } -===> Test result of GlobalVectors::test_move_from_vector_of_struct: Succeed(Stopped) (used_gas=186329): [] +===> Test result of GlobalVectors::test_move_from_vector_of_struct: Succeed(Stopped) (used_gas=187040): [] // test of GlobalVectors::test_move_from_vector_of_vector /* ======================================= @@ -1585,36 +1640,16 @@ object "test_A2_GlobalVectors_test_move_from_vector_of_vector" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t22 := 101 $t22 := 101 // abort($t22) $Abort($t22) } - case 3 { - // label L0 - // $t23 := borrow_local($t1) - $t23 := $MakePtr(false, local_t) - // $t24 := borrow_field>>.v($t23) - $t24 := $t23 - // $t25 := 0 - $t25 := 0 - // $t26 := vector::borrow>($t24, $t25) - $t26 := A1_vector_borrow$vec$u64$$($t24, $t25) - // $t27 := 0 - $t27 := 0 - // $t28 := vector::borrow($t26, $t27) - $t28 := A1_vector_borrow$u64$($t26, $t27) - // $t29 := read_ref($t28) - $t29 := $LoadU64($t28) - // $t30 := 10 - $t30 := 10 - // $t31 := ==($t29, $t30) - $t31 := $Eq($t29, $t30) - // if ($t31) goto L2 else goto L3 - switch $t31 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t2 := vector::empty>() mstore($locals, A1_vector_empty$vec$u64$$()) @@ -1756,20 +1791,50 @@ object "test_A2_GlobalVectors_test_move_from_vector_of_vector" { $t20 := 3 // $t21 := ==($t19, $t20) $t21 := $Eq($t19, $t20) - // if ($t21) goto L0 else goto L1 + // if ($t21) goto L1 else goto L0 switch $t21 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t23 := borrow_local($t1) + $t23 := $MakePtr(false, local_t) + // $t24 := borrow_field>>.v($t23) + $t24 := $t23 + // $t25 := 0 + $t25 := 0 + // $t26 := vector::borrow>($t24, $t25) + $t26 := A1_vector_borrow$vec$u64$$($t24, $t25) + // $t27 := 0 + $t27 := 0 + // $t28 := vector::borrow($t26, $t27) + $t28 := A1_vector_borrow$u64$($t26, $t27) + // $t29 := read_ref($t28) + $t29 := $LoadU64($t28) + // $t30 := 10 + $t30 := 10 + // $t31 := ==($t29, $t30) + $t31 := $Eq($t29, $t30) + // if ($t31) goto L4 else goto L3 + switch $t31 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t32 := 102 $t32 := 102 // abort($t32) $Abort($t32) } - case 6 { - // label L2 + case 8 { + // label L5 // $t33 := borrow_local($t1) $t33 := $MakePtr(false, local_t) // $t34 := borrow_field>>.v($t33) @@ -1788,20 +1853,25 @@ object "test_A2_GlobalVectors_test_move_from_vector_of_vector" { $t40 := 11 // $t41 := ==($t39, $t40) $t41 := $Eq($t39, $t40) - // if ($t41) goto L4 else goto L5 + // if ($t41) goto L7 else goto L6 switch $t41 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t42 := 102 $t42 := 102 // abort($t42) $Abort($t42) } - case 8 { - // label L4 + case 11 { + // label L8 // $t43 := borrow_local($t1) $t43 := $MakePtr(false, local_t) // $t44 := borrow_field>>.v($t43) @@ -1820,20 +1890,25 @@ object "test_A2_GlobalVectors_test_move_from_vector_of_vector" { $t50 := 12 // $t51 := ==($t49, $t50) $t51 := $Eq($t49, $t50) - // if ($t51) goto L6 else goto L7 + // if ($t51) goto L10 else goto L9 switch $t51 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t52 := 102 $t52 := 102 // abort($t52) $Abort($t52) } - case 10 { - // label L6 + case 14 { + // label L11 // return () $Free($locals, 64) leave @@ -2163,7 +2238,7 @@ object "test_A2_GlobalVectors_test_move_from_vector_of_vector" { } } } -===> Test result of GlobalVectors::test_move_from_vector_of_vector: Succeed(Stopped) (used_gas=243928): [] +===> Test result of GlobalVectors::test_move_from_vector_of_vector: Succeed(Stopped) (used_gas=244640): [] // test of GlobalVectors::test_move_to /* ======================================= @@ -2184,40 +2259,16 @@ object "test_A2_GlobalVectors_test_move_to" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t18 := 101 $t18 := 101 // abort($t18) $Abort($t18) } - case 3 { - // label L0 - // $t19 := 0x42 - $t19 := 0x42 - // $t20 := borrow_global>($t19) - { - let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $t19) - if iszero($AlignedStorageLoad($base_offset)) { - $AbortBuiltin() - } - $t20 := $MakePtr(true, add($base_offset, 32)) - } - // $t21 := borrow_field>.v($t20) - $t21 := $t20 - // $t22 := 0 - $t22 := 0 - // $t23 := vector::borrow($t21, $t22) - $t23 := A1_vector_borrow$u64$($t21, $t22) - // $t24 := read_ref($t23) - $t24 := $LoadU64($t23) - // $t25 := 10 - $t25 := 10 - // $t26 := ==($t24, $t25) - $t26 := $Eq($t24, $t25) - // if ($t26) goto L2 else goto L3 - switch $t26 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t1 := vector::empty() mstore($locals, A1_vector_empty$u64$()) @@ -2298,20 +2349,54 @@ object "test_A2_GlobalVectors_test_move_to" { $t16 := 3 // $t17 := ==($t15, $t16) $t17 := $Eq($t15, $t16) - // if ($t17) goto L0 else goto L1 + // if ($t17) goto L1 else goto L0 switch $t17 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t19 := 0x42 + $t19 := 0x42 + // $t20 := borrow_global>($t19) + { + let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $t19) + if iszero($AlignedStorageLoad($base_offset)) { + $AbortBuiltin() + } + $t20 := $MakePtr(true, add($base_offset, 32)) + } + // $t21 := borrow_field>.v($t20) + $t21 := $t20 + // $t22 := 0 + $t22 := 0 + // $t23 := vector::borrow($t21, $t22) + $t23 := A1_vector_borrow$u64$($t21, $t22) + // $t24 := read_ref($t23) + $t24 := $LoadU64($t23) + // $t25 := 10 + $t25 := 10 + // $t26 := ==($t24, $t25) + $t26 := $Eq($t24, $t25) + // if ($t26) goto L4 else goto L3 + switch $t26 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t27 := 102 $t27 := 102 // abort($t27) $Abort($t27) } - case 6 { - // label L2 + case 8 { + // label L5 // $t28 := 0x42 $t28 := 0x42 // $t29 := borrow_global>($t28) @@ -2334,20 +2419,25 @@ object "test_A2_GlobalVectors_test_move_to" { $t34 := 11 // $t35 := ==($t33, $t34) $t35 := $Eq($t33, $t34) - // if ($t35) goto L4 else goto L5 + // if ($t35) goto L7 else goto L6 switch $t35 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t36 := 103 $t36 := 103 // abort($t36) $Abort($t36) } - case 8 { - // label L4 + case 11 { + // label L8 // $t37 := 0x42 $t37 := 0x42 // $t38 := borrow_global>($t37) @@ -2370,20 +2460,25 @@ object "test_A2_GlobalVectors_test_move_to" { $t43 := 12 // $t44 := ==($t42, $t43) $t44 := $Eq($t42, $t43) - // if ($t44) goto L6 else goto L7 + // if ($t44) goto L10 else goto L9 switch $t44 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t45 := 104 $t45 := 104 // abort($t45) $Abort($t45) } - case 10 { - // label L6 + case 14 { + // label L11 // return () $Free($locals, 64) leave @@ -2649,7 +2744,7 @@ object "test_A2_GlobalVectors_test_move_to" { } } } -===> Test result of GlobalVectors::test_move_to: Succeed(Stopped) (used_gas=120223): [] +===> Test result of GlobalVectors::test_move_to: Succeed(Stopped) (used_gas=121112): [] // test of GlobalVectors::test_move_to_vector_of_struct /* ======================================= @@ -2670,42 +2765,16 @@ object "test_A2_GlobalVectors_test_move_to_vector_of_struct" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t24 := 101 $t24 := 101 // abort($t24) $Abort($t24) } - case 3 { - // label L0 - // $t25 := 0x42 - $t25 := 0x42 - // $t26 := borrow_global>($t25) - { - let $base_offset := $MakeTypeStorageBase(0, 0x27c9b6b7, $t25) - if iszero($AlignedStorageLoad($base_offset)) { - $AbortBuiltin() - } - $t26 := $MakePtr(true, add($base_offset, 32)) - } - // $t27 := borrow_field>.v($t26) - $t27 := $t26 - // $t28 := 0 - $t28 := 0 - // $t29 := vector::borrow($t27, $t28) - $t29 := A1_vector_borrow$A2_GlobalVectors_S$($t27, $t28) - // $t30 := borrow_field.x($t29) - $t30 := $t29 - // $t31 := read_ref($t30) - $t31 := $LoadU128($t30) - // $t32 := 10 - $t32 := 10 - // $t33 := ==($t31, $t32) - $t33 := $Eq($t31, $t32) - // if ($t33) goto L2 else goto L3 - switch $t33 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t1 := vector::empty() mstore($locals, A1_vector_empty$A2_GlobalVectors_S$()) @@ -2819,20 +2888,56 @@ object "test_A2_GlobalVectors_test_move_to_vector_of_struct" { $t22 := 3 // $t23 := ==($t21, $t22) $t23 := $Eq($t21, $t22) - // if ($t23) goto L0 else goto L1 + // if ($t23) goto L1 else goto L0 switch $t23 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t25 := 0x42 + $t25 := 0x42 + // $t26 := borrow_global>($t25) + { + let $base_offset := $MakeTypeStorageBase(0, 0x27c9b6b7, $t25) + if iszero($AlignedStorageLoad($base_offset)) { + $AbortBuiltin() + } + $t26 := $MakePtr(true, add($base_offset, 32)) + } + // $t27 := borrow_field>.v($t26) + $t27 := $t26 + // $t28 := 0 + $t28 := 0 + // $t29 := vector::borrow($t27, $t28) + $t29 := A1_vector_borrow$A2_GlobalVectors_S$($t27, $t28) + // $t30 := borrow_field.x($t29) + $t30 := $t29 + // $t31 := read_ref($t30) + $t31 := $LoadU128($t30) + // $t32 := 10 + $t32 := 10 + // $t33 := ==($t31, $t32) + $t33 := $Eq($t31, $t32) + // if ($t33) goto L4 else goto L3 + switch $t33 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t34 := 102 $t34 := 102 // abort($t34) $Abort($t34) } - case 6 { - // label L2 + case 8 { + // label L5 // $t35 := 0x42 $t35 := 0x42 // $t36 := borrow_global>($t35) @@ -2857,20 +2962,25 @@ object "test_A2_GlobalVectors_test_move_to_vector_of_struct" { $t42 := 11 // $t43 := ==($t41, $t42) $t43 := $Eq($t41, $t42) - // if ($t43) goto L4 else goto L5 + // if ($t43) goto L7 else goto L6 switch $t43 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t44 := 103 $t44 := 103 // abort($t44) $Abort($t44) } - case 8 { - // label L4 + case 11 { + // label L8 // $t45 := 0x42 $t45 := 0x42 // $t46 := borrow_global>($t45) @@ -2895,20 +3005,25 @@ object "test_A2_GlobalVectors_test_move_to_vector_of_struct" { $t52 := 12 // $t53 := ==($t51, $t52) $t53 := $Eq($t51, $t52) - // if ($t53) goto L6 else goto L7 + // if ($t53) goto L10 else goto L9 switch $t53 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t54 := 104 $t54 := 104 // abort($t54) $Abort($t54) } - case 10 { - // label L6 + case 14 { + // label L11 // return () $Free($locals, 64) leave @@ -3202,7 +3317,7 @@ object "test_A2_GlobalVectors_test_move_to_vector_of_struct" { } } } -===> Test result of GlobalVectors::test_move_to_vector_of_struct: Succeed(Stopped) (used_gas=233788): [] +===> Test result of GlobalVectors::test_move_to_vector_of_struct: Succeed(Stopped) (used_gas=234677): [] // test of GlobalVectors::test_move_to_vector_of_vector /* ======================================= @@ -3223,44 +3338,16 @@ object "test_A2_GlobalVectors_test_move_to_vector_of_vector" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t21 := 101 $t21 := 101 // abort($t21) $Abort($t21) } - case 3 { - // label L0 - // $t22 := 0x42 - $t22 := 0x42 - // $t23 := borrow_global>>($t22) - { - let $base_offset := $MakeTypeStorageBase(0, 0x9947b477, $t22) - if iszero($AlignedStorageLoad($base_offset)) { - $AbortBuiltin() - } - $t23 := $MakePtr(true, add($base_offset, 32)) - } - // $t24 := borrow_field>>.v($t23) - $t24 := $t23 - // $t25 := 0 - $t25 := 0 - // $t26 := vector::borrow>($t24, $t25) - $t26 := A1_vector_borrow$vec$u64$$($t24, $t25) - // $t27 := 0 - $t27 := 0 - // $t28 := vector::borrow($t26, $t27) - $t28 := A1_vector_borrow$u64$($t26, $t27) - // $t29 := read_ref($t28) - $t29 := $LoadU64($t28) - // $t30 := 10 - $t30 := 10 - // $t31 := ==($t29, $t30) - $t31 := $Eq($t29, $t30) - // if ($t31) goto L2 else goto L3 - switch $t31 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t1 := vector::empty>() mstore($locals, A1_vector_empty$vec$u64$$()) @@ -3360,20 +3447,58 @@ object "test_A2_GlobalVectors_test_move_to_vector_of_vector" { $t19 := 3 // $t20 := ==($t18, $t19) $t20 := $Eq($t18, $t19) - // if ($t20) goto L0 else goto L1 + // if ($t20) goto L1 else goto L0 switch $t20 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t22 := 0x42 + $t22 := 0x42 + // $t23 := borrow_global>>($t22) + { + let $base_offset := $MakeTypeStorageBase(0, 0x9947b477, $t22) + if iszero($AlignedStorageLoad($base_offset)) { + $AbortBuiltin() + } + $t23 := $MakePtr(true, add($base_offset, 32)) + } + // $t24 := borrow_field>>.v($t23) + $t24 := $t23 + // $t25 := 0 + $t25 := 0 + // $t26 := vector::borrow>($t24, $t25) + $t26 := A1_vector_borrow$vec$u64$$($t24, $t25) + // $t27 := 0 + $t27 := 0 + // $t28 := vector::borrow($t26, $t27) + $t28 := A1_vector_borrow$u64$($t26, $t27) + // $t29 := read_ref($t28) + $t29 := $LoadU64($t28) + // $t30 := 10 + $t30 := 10 + // $t31 := ==($t29, $t30) + $t31 := $Eq($t29, $t30) + // if ($t31) goto L4 else goto L3 + switch $t31 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t32 := 102 $t32 := 102 // abort($t32) $Abort($t32) } - case 6 { - // label L2 + case 8 { + // label L5 // $t33 := 0x42 $t33 := 0x42 // $t34 := borrow_global>>($t33) @@ -3400,20 +3525,25 @@ object "test_A2_GlobalVectors_test_move_to_vector_of_vector" { $t41 := 11 // $t42 := ==($t40, $t41) $t42 := $Eq($t40, $t41) - // if ($t42) goto L4 else goto L5 + // if ($t42) goto L7 else goto L6 switch $t42 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t43 := 102 $t43 := 102 // abort($t43) $Abort($t43) } - case 8 { - // label L4 + case 11 { + // label L8 // $t44 := 0x42 $t44 := 0x42 // $t45 := borrow_global>>($t44) @@ -3440,20 +3570,25 @@ object "test_A2_GlobalVectors_test_move_to_vector_of_vector" { $t52 := 12 // $t53 := ==($t51, $t52) $t53 := $Eq($t51, $t52) - // if ($t53) goto L6 else goto L7 + // if ($t53) goto L10 else goto L9 switch $t53 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t54 := 102 $t54 := 102 // abort($t54) $Abort($t54) } - case 10 { - // label L6 + case 14 { + // label L11 // return () $Free($locals, 64) leave @@ -3774,7 +3909,7 @@ object "test_A2_GlobalVectors_test_move_to_vector_of_vector" { } } } -===> Test result of GlobalVectors::test_move_to_vector_of_vector: Succeed(Stopped) (used_gas=304390): [] +===> Test result of GlobalVectors::test_move_to_vector_of_vector: Succeed(Stopped) (used_gas=305279): [] // test of GlobalVectors::test_pop_back_global /* ======================================= @@ -3788,88 +3923,68 @@ object "test_A2_GlobalVectors_test_pop_back_global" { A2_GlobalVectors_test_pop_back_global() return (0, 0) function A2_GlobalVectors_test_pop_back_global() { - let e, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20, $t21, $t22, $t23, $t24, $t25, $t26, $t27, $t28, $t29, $t30, $t31, $t32, $t33, $t34, $t35, $t36, $t37, $t38, $t39, $t40 + let $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20, $t21, $t22, $t23, $t24, $t25, $t26, $t27, $t28, $t29, $t30, $t31, $t32, $t33, $t34, $t35, $t36, $t37, $t38, $t39 let $locals := $Malloc(64) let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t19 := 101 - $t19 := 101 - // abort($t19) - $Abort($t19) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t20 := 0x42 - $t20 := 0x42 - // $t21 := borrow_global>($t20) - { - let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $t20) - if iszero($AlignedStorageLoad($base_offset)) { - $AbortBuiltin() - } - $t21 := $MakePtr(true, add($base_offset, 32)) - } - // $t22 := borrow_field>.v($t21) - $t22 := $t21 - // $t23 := vector::length($t22) - $t23 := A1_vector_length$u64$($t22) - // $t24 := 2 - $t24 := 2 - // $t25 := ==($t23, $t24) - $t25 := $Eq($t23, $t24) - // if ($t25) goto L2 else goto L3 - switch $t25 - case 0 { $block := 5 } - default { $block := 6 } + // $t18 := 101 + $t18 := 101 + // abort($t18) + $Abort($t18) } case 4 { - // $t2 := vector::empty() + // $t1 := vector::empty() mstore($locals, A1_vector_empty$u64$()) - // $t3 := borrow_local($t2) - $t3 := $MakePtr(false, $locals) - // $t4 := 10 - $t4 := 10 - // vector::push_back($t3, $t4) - A1_vector_push_back$u64$($t3, $t4) - // $t5 := borrow_local($t2) - $t5 := $MakePtr(false, $locals) - // $t6 := 11 - $t6 := 11 - // vector::push_back($t5, $t6) - A1_vector_push_back$u64$($t5, $t6) - // $t7 := borrow_local($t2) - $t7 := $MakePtr(false, $locals) - // $t8 := 12 - $t8 := 12 - // vector::push_back($t7, $t8) - A1_vector_push_back$u64$($t7, $t8) - // $t9 := 0x42 - $t9 := 0x42 - // $t0 := Evm::sign($t9) - mstore(add($locals, 32), A2_Evm_sign($t9)) - // $t10 := borrow_local($t0) - $t10 := $MakePtr(false, add($locals, 32)) - // $t11 := move($t2) - $t11 := mload($locals) - // $t12 := pack GlobalVectors::T($t11) + // $t2 := borrow_local($t1) + $t2 := $MakePtr(false, $locals) + // $t3 := 10 + $t3 := 10 + // vector::push_back($t2, $t3) + A1_vector_push_back$u64$($t2, $t3) + // $t4 := borrow_local($t1) + $t4 := $MakePtr(false, $locals) + // $t5 := 11 + $t5 := 11 + // vector::push_back($t4, $t5) + A1_vector_push_back$u64$($t4, $t5) + // $t6 := borrow_local($t1) + $t6 := $MakePtr(false, $locals) + // $t7 := 12 + $t7 := 12 + // vector::push_back($t6, $t7) + A1_vector_push_back$u64$($t6, $t7) + // $t8 := 0x42 + $t8 := 0x42 + // $t0 := Evm::sign($t8) + mstore(add($locals, 32), A2_Evm_sign($t8)) + // $t9 := borrow_local($t0) + $t9 := $MakePtr(false, add($locals, 32)) + // $t10 := move($t1) + $t10 := mload($locals) + // $t11 := pack GlobalVectors::T($t10) { let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t11) - $t12 := $mem + $MemoryStoreU256(add($mem, 0), $t10) + $t11 := $mem } - // move_to>($t12, $t10) + // move_to>($t11, $t9) { - let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $LoadU256($t10)) + let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $LoadU256($t9)) if $AlignedStorageLoad($base_offset) { $AbortBuiltin() } $AlignedStorageStore($base_offset, true) { let $dst := add($base_offset, 32) - let $src := $t12 + let $src := $t11 { let $linked_src_814019441 := mload(add($src, 0)) let $linked_dst_814019441 := $NewLinkedStorageBase(0x3084f371) @@ -3887,102 +4002,142 @@ object "test_A2_GlobalVectors_test_pop_back_global" { $Free($src, 32) } } - // $t13 := 0x42 - $t13 := 0x42 - // $t14 := borrow_global>($t13) + // $t12 := 0x42 + $t12 := 0x42 + // $t13 := borrow_global>($t12) { - let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $t13) + let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $t12) if iszero($AlignedStorageLoad($base_offset)) { $AbortBuiltin() } - $t14 := $MakePtr(true, add($base_offset, 32)) + $t13 := $MakePtr(true, add($base_offset, 32)) } - // $t15 := borrow_field>.v($t14) - $t15 := $t14 - // $t16 := vector::pop_back($t15) - $t16 := A1_vector_pop_back$u64$($t15) - // $t17 := 12 - $t17 := 12 - // $t18 := ==($t16, $t17) - $t18 := $Eq($t16, $t17) - // if ($t18) goto L0 else goto L1 - switch $t18 - case 0 { $block := 2 } - default { $block := 3 } + // $t14 := borrow_field>.v($t13) + $t14 := $t13 + // $t15 := vector::pop_back($t14) + $t15 := A1_vector_pop_back$u64$($t14) + // $t16 := 12 + $t16 := 12 + // $t17 := ==($t15, $t16) + $t17 := $Eq($t15, $t16) + // if ($t17) goto L1 else goto L0 + switch $t17 + case 0 { $block := 3 } + default { $block := 2 } } case 5 { - // label L3 - // $t26 := 102 - $t26 := 102 - // abort($t26) - $Abort($t26) - } - case 6 { // label L2 - // $t27 := 0x42 - $t27 := 0x42 - // $t28 := borrow_global>($t27) + // $t19 := 0x42 + $t19 := 0x42 + // $t20 := borrow_global>($t19) { - let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $t27) + let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $t19) if iszero($AlignedStorageLoad($base_offset)) { $AbortBuiltin() } - $t28 := $MakePtr(true, add($base_offset, 32)) + $t20 := $MakePtr(true, add($base_offset, 32)) } - // $t29 := borrow_field>.v($t28) - $t29 := $t28 - // $t30 := vector::pop_back($t29) - $t30 := A1_vector_pop_back$u64$($t29) - // $t31 := 11 - $t31 := 11 - // $t32 := ==($t30, $t31) - $t32 := $Eq($t30, $t31) - // if ($t32) goto L4 else goto L5 - switch $t32 + // $t21 := borrow_field>.v($t20) + $t21 := $t20 + // $t22 := vector::length($t21) + $t22 := A1_vector_length$u64$($t21) + // $t23 := 2 + $t23 := 2 + // $t24 := ==($t22, $t23) + $t24 := $Eq($t22, $t23) + // if ($t24) goto L4 else goto L3 + switch $t24 case 0 { $block := 7 } - default { $block := 8 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 } case 7 { - // label L5 - // $t33 := 103 - $t33 := 103 - // abort($t33) - $Abort($t33) + // label L3 + // $t25 := 102 + $t25 := 102 + // abort($t25) + $Abort($t25) } case 8 { - // label L4 - // $t34 := 0x42 - $t34 := 0x42 - // $t35 := borrow_global>($t34) + // label L5 + // $t26 := 0x42 + $t26 := 0x42 + // $t27 := borrow_global>($t26) { - let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $t34) + let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $t26) if iszero($AlignedStorageLoad($base_offset)) { $AbortBuiltin() } - $t35 := $MakePtr(true, add($base_offset, 32)) + $t27 := $MakePtr(true, add($base_offset, 32)) } - // $t36 := borrow_field>.v($t35) - $t36 := $t35 - // $t37 := vector::length($t36) - $t37 := A1_vector_length$u64$($t36) - // $t38 := 1 - $t38 := 1 - // $t39 := ==($t37, $t38) - $t39 := $Eq($t37, $t38) - // if ($t39) goto L6 else goto L7 - switch $t39 - case 0 { $block := 9 } - default { $block := 10 } + // $t28 := borrow_field>.v($t27) + $t28 := $t27 + // $t29 := vector::pop_back($t28) + $t29 := A1_vector_pop_back$u64$($t28) + // $t30 := 11 + $t30 := 11 + // $t31 := ==($t29, $t30) + $t31 := $Eq($t29, $t30) + // if ($t31) goto L7 else goto L6 + switch $t31 + case 0 { $block := 10 } + default { $block := 9 } } case 9 { // label L7 - // $t40 := 104 - $t40 := 104 - // abort($t40) - $Abort($t40) + // goto L8 + $block := 11 } case 10 { // label L6 + // $t32 := 103 + $t32 := 103 + // abort($t32) + $Abort($t32) + } + case 11 { + // label L8 + // $t33 := 0x42 + $t33 := 0x42 + // $t34 := borrow_global>($t33) + { + let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $t33) + if iszero($AlignedStorageLoad($base_offset)) { + $AbortBuiltin() + } + $t34 := $MakePtr(true, add($base_offset, 32)) + } + // $t35 := borrow_field>.v($t34) + $t35 := $t34 + // $t36 := vector::length($t35) + $t36 := A1_vector_length$u64$($t35) + // $t37 := 1 + $t37 := 1 + // $t38 := ==($t36, $t37) + $t38 := $Eq($t36, $t37) + // if ($t38) goto L10 else goto L9 + switch $t38 + case 0 { $block := 13 } + default { $block := 12 } + } + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 + // $t39 := 104 + $t39 := 104 + // abort($t39) + $Abort($t39) + } + case 14 { + // label L11 // return () $Free($locals, 64) leave @@ -4247,7 +4402,7 @@ object "test_A2_GlobalVectors_test_pop_back_global" { } } } -===> Test result of GlobalVectors::test_pop_back_global: Succeed(Stopped) (used_gas=120871): [] +===> Test result of GlobalVectors::test_pop_back_global: Succeed(Stopped) (used_gas=121755): [] // test of GlobalVectors::test_pop_back_struct_global /* ======================================= @@ -4267,7 +4422,7 @@ object "test_A2_GlobalVectors_test_pop_back_struct_global" { for {} true {} { switch $block case 2 { - // label L0 + // label L1 // $t29 := borrow_local($t3) $t29 := $MakePtr(false, e) // $t30 := borrow_field.y($t29) @@ -4278,16 +4433,16 @@ object "test_A2_GlobalVectors_test_pop_back_struct_global" { $t32 := 42 // $t1 := ==($t31, $t32) tmp_$1 := $Eq($t31, $t32) - // goto L3 + // goto L2 $block := 5 } case 3 { - // label L2 + // label L0 // $t33 := false $t33 := false // $t1 := $t33 tmp_$1 := $t33 - // goto L3 + // goto L2 $block := 5 } case 4 { @@ -4409,27 +4564,32 @@ object "test_A2_GlobalVectors_test_pop_back_struct_global" { $t27 := 12 // $t28 := ==($t26, $t27) $t28 := $Eq($t26, $t27) - // if ($t28) goto L0 else goto L2 + // if ($t28) goto L1 else goto L0 switch $t28 case 0 { $block := 3 } default { $block := 2 } } case 5 { - // label L3 - // if ($t1) goto L4 else goto L5 + // label L2 + // if ($t1) goto L4 else goto L3 switch tmp_$1 - case 0 { $block := 6 } - default { $block := 7 } + case 0 { $block := 7 } + default { $block := 6 } } case 6 { - // label L5 + // label L4 + // goto L5 + $block := 8 + } + case 7 { + // label L3 // $t34 := 101 $t34 := 101 // abort($t34) $Abort($t34) } - case 7 { - // label L4 + case 8 { + // label L5 // $t35 := 0x42 $t35 := 0x42 // $t36 := borrow_global>($t35) @@ -4448,20 +4608,25 @@ object "test_A2_GlobalVectors_test_pop_back_struct_global" { $t39 := 2 // $t40 := ==($t38, $t39) $t40 := $Eq($t38, $t39) - // if ($t40) goto L6 else goto L7 + // if ($t40) goto L7 else goto L6 switch $t40 - case 0 { $block := 8 } + case 0 { $block := 10 } default { $block := 9 } } - case 8 { + case 9 { // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t41 := 102 $t41 := 102 // abort($t41) $Abort($t41) } - case 9 { - // label L6 + case 11 { + // label L8 // $t42 := 0x42 $t42 := 0x42 // $t43 := borrow_global>($t42) @@ -4486,13 +4651,13 @@ object "test_A2_GlobalVectors_test_pop_back_struct_global" { $t48 := 11 // $t49 := ==($t47, $t48) $t49 := $Eq($t47, $t48) - // if ($t49) goto L8 else goto L10 + // if ($t49) goto L10 else goto L9 switch $t49 - case 0 { $block := 11 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 10 { - // label L8 + case 12 { + // label L10 // $t50 := borrow_local($t3) $t50 := $MakePtr(false, e) // $t51 := borrow_field.y($t50) @@ -4504,33 +4669,38 @@ object "test_A2_GlobalVectors_test_pop_back_struct_global" { // $t2 := ==($t52, $t53) tmp_$2 := $Eq($t52, $t53) // goto L11 - $block := 12 + $block := 14 } - case 11 { - // label L10 + case 13 { + // label L9 // $t54 := false $t54 := false // $t2 := $t54 tmp_$2 := $t54 // goto L11 - $block := 12 + $block := 14 } - case 12 { + case 14 { // label L11 - // if ($t2) goto L12 else goto L13 + // if ($t2) goto L13 else goto L12 switch tmp_$2 - case 0 { $block := 13 } - default { $block := 14 } + case 0 { $block := 16 } + default { $block := 15 } } - case 13 { + case 15 { // label L13 + // goto L14 + $block := 17 + } + case 16 { + // label L12 // $t55 := 103 $t55 := 103 // abort($t55) $Abort($t55) } - case 14 { - // label L12 + case 17 { + // label L14 // $t56 := 0x42 $t56 := 0x42 // $t57 := borrow_global>($t56) @@ -4549,20 +4719,25 @@ object "test_A2_GlobalVectors_test_pop_back_struct_global" { $t60 := 1 // $t61 := ==($t59, $t60) $t61 := $Eq($t59, $t60) - // if ($t61) goto L14 else goto L15 + // if ($t61) goto L16 else goto L15 switch $t61 - case 0 { $block := 15 } - default { $block := 16 } + case 0 { $block := 19 } + default { $block := 18 } } - case 15 { + case 18 { + // label L16 + // goto L17 + $block := 20 + } + case 19 { // label L15 // $t62 := 104 $t62 := 104 // abort($t62) $Abort($t62) } - case 16 { - // label L14 + case 20 { + // label L17 // return () $Free($locals, 64) leave @@ -4861,7 +5036,7 @@ object "test_A2_GlobalVectors_test_pop_back_struct_global" { } } } -===> Test result of GlobalVectors::test_pop_back_struct_global: Succeed(Stopped) (used_gas=189371): [] +===> Test result of GlobalVectors::test_pop_back_struct_global: Succeed(Stopped) (used_gas=190461): [] // test of GlobalVectors::test_push_back_global /* ======================================= @@ -4882,40 +5057,16 @@ object "test_A2_GlobalVectors_test_push_back_global" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t26 := 101 $t26 := 101 // abort($t26) $Abort($t26) } - case 3 { - // label L0 - // $t27 := 0x42 - $t27 := 0x42 - // $t28 := borrow_global>($t27) - { - let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $t27) - if iszero($AlignedStorageLoad($base_offset)) { - $AbortBuiltin() - } - $t28 := $MakePtr(true, add($base_offset, 32)) - } - // $t29 := borrow_field>.v($t28) - $t29 := $t28 - // $t30 := 0 - $t30 := 0 - // $t31 := vector::borrow($t29, $t30) - $t31 := A1_vector_borrow$u64$($t29, $t30) - // $t32 := read_ref($t31) - $t32 := $LoadU64($t31) - // $t33 := 10 - $t33 := 10 - // $t34 := ==($t32, $t33) - $t34 := $Eq($t32, $t33) - // if ($t34) goto L2 else goto L3 - switch $t34 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t1 := vector::empty() mstore($locals, A1_vector_empty$u64$()) @@ -5028,20 +5179,54 @@ object "test_A2_GlobalVectors_test_push_back_global" { $t24 := 5 // $t25 := ==($t23, $t24) $t25 := $Eq($t23, $t24) - // if ($t25) goto L0 else goto L1 + // if ($t25) goto L1 else goto L0 switch $t25 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t27 := 0x42 + $t27 := 0x42 + // $t28 := borrow_global>($t27) + { + let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $t27) + if iszero($AlignedStorageLoad($base_offset)) { + $AbortBuiltin() + } + $t28 := $MakePtr(true, add($base_offset, 32)) + } + // $t29 := borrow_field>.v($t28) + $t29 := $t28 + // $t30 := 0 + $t30 := 0 + // $t31 := vector::borrow($t29, $t30) + $t31 := A1_vector_borrow$u64$($t29, $t30) + // $t32 := read_ref($t31) + $t32 := $LoadU64($t31) + // $t33 := 10 + $t33 := 10 + // $t34 := ==($t32, $t33) + $t34 := $Eq($t32, $t33) + // if ($t34) goto L4 else goto L3 + switch $t34 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t35 := 102 $t35 := 102 // abort($t35) $Abort($t35) } - case 6 { - // label L2 + case 8 { + // label L5 // $t36 := 0x42 $t36 := 0x42 // $t37 := borrow_global>($t36) @@ -5064,20 +5249,25 @@ object "test_A2_GlobalVectors_test_push_back_global" { $t42 := 11 // $t43 := ==($t41, $t42) $t43 := $Eq($t41, $t42) - // if ($t43) goto L4 else goto L5 + // if ($t43) goto L7 else goto L6 switch $t43 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t44 := 103 $t44 := 103 // abort($t44) $Abort($t44) } - case 8 { - // label L4 + case 11 { + // label L8 // $t45 := 0x42 $t45 := 0x42 // $t46 := borrow_global>($t45) @@ -5100,20 +5290,25 @@ object "test_A2_GlobalVectors_test_push_back_global" { $t51 := 12 // $t52 := ==($t50, $t51) $t52 := $Eq($t50, $t51) - // if ($t52) goto L6 else goto L7 + // if ($t52) goto L10 else goto L9 switch $t52 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t53 := 104 $t53 := 104 // abort($t53) $Abort($t53) } - case 10 { - // label L6 + case 14 { + // label L11 // $t54 := 0x42 $t54 := 0x42 // $t55 := borrow_global>($t54) @@ -5136,20 +5331,25 @@ object "test_A2_GlobalVectors_test_push_back_global" { $t60 := 13 // $t61 := ==($t59, $t60) $t61 := $Eq($t59, $t60) - // if ($t61) goto L8 else goto L9 + // if ($t61) goto L13 else goto L12 switch $t61 - case 0 { $block := 11 } - default { $block := 12 } + case 0 { $block := 16 } + default { $block := 15 } } - case 11 { - // label L9 + case 15 { + // label L13 + // goto L14 + $block := 17 + } + case 16 { + // label L12 // $t62 := 105 $t62 := 105 // abort($t62) $Abort($t62) } - case 12 { - // label L8 + case 17 { + // label L14 // $t63 := 0x42 $t63 := 0x42 // $t64 := borrow_global>($t63) @@ -5172,20 +5372,25 @@ object "test_A2_GlobalVectors_test_push_back_global" { $t69 := 14 // $t70 := ==($t68, $t69) $t70 := $Eq($t68, $t69) - // if ($t70) goto L10 else goto L11 + // if ($t70) goto L16 else goto L15 switch $t70 - case 0 { $block := 13 } - default { $block := 14 } + case 0 { $block := 19 } + default { $block := 18 } } - case 13 { - // label L11 + case 18 { + // label L16 + // goto L17 + $block := 20 + } + case 19 { + // label L15 // $t71 := 106 $t71 := 106 // abort($t71) $Abort($t71) } - case 14 { - // label L10 + case 20 { + // label L17 // return () $Free($locals, 64) leave @@ -5451,7 +5656,7 @@ object "test_A2_GlobalVectors_test_push_back_global" { } } } -===> Test result of GlobalVectors::test_push_back_global: Succeed(Stopped) (used_gas=150884): [] +===> Test result of GlobalVectors::test_push_back_global: Succeed(Stopped) (used_gas=152738): [] // test of GlobalVectors::test_push_back_struct_global /* ======================================= @@ -5472,42 +5677,16 @@ object "test_A2_GlobalVectors_test_push_back_struct_global" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t36 := 101 $t36 := 101 // abort($t36) $Abort($t36) } - case 3 { - // label L0 - // $t37 := 0x42 - $t37 := 0x42 - // $t38 := borrow_global>($t37) - { - let $base_offset := $MakeTypeStorageBase(0, 0x27c9b6b7, $t37) - if iszero($AlignedStorageLoad($base_offset)) { - $AbortBuiltin() - } - $t38 := $MakePtr(true, add($base_offset, 32)) - } - // $t39 := borrow_field>.v($t38) - $t39 := $t38 - // $t40 := 0 - $t40 := 0 - // $t41 := vector::borrow($t39, $t40) - $t41 := A1_vector_borrow$A2_GlobalVectors_S$($t39, $t40) - // $t42 := borrow_field.x($t41) - $t42 := $t41 - // $t43 := read_ref($t42) - $t43 := $LoadU128($t42) - // $t44 := 10 - $t44 := 10 - // $t45 := ==($t43, $t44) - $t45 := $Eq($t43, $t44) - // if ($t45) goto L2 else goto L3 - switch $t45 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t1 := vector::empty() mstore($locals, A1_vector_empty$A2_GlobalVectors_S$()) @@ -5671,20 +5850,56 @@ object "test_A2_GlobalVectors_test_push_back_struct_global" { $t34 := 5 // $t35 := ==($t33, $t34) $t35 := $Eq($t33, $t34) - // if ($t35) goto L0 else goto L1 + // if ($t35) goto L1 else goto L0 switch $t35 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t37 := 0x42 + $t37 := 0x42 + // $t38 := borrow_global>($t37) + { + let $base_offset := $MakeTypeStorageBase(0, 0x27c9b6b7, $t37) + if iszero($AlignedStorageLoad($base_offset)) { + $AbortBuiltin() + } + $t38 := $MakePtr(true, add($base_offset, 32)) + } + // $t39 := borrow_field>.v($t38) + $t39 := $t38 + // $t40 := 0 + $t40 := 0 + // $t41 := vector::borrow($t39, $t40) + $t41 := A1_vector_borrow$A2_GlobalVectors_S$($t39, $t40) + // $t42 := borrow_field.x($t41) + $t42 := $t41 + // $t43 := read_ref($t42) + $t43 := $LoadU128($t42) + // $t44 := 10 + $t44 := 10 + // $t45 := ==($t43, $t44) + $t45 := $Eq($t43, $t44) + // if ($t45) goto L4 else goto L3 + switch $t45 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t46 := 102 $t46 := 102 // abort($t46) $Abort($t46) } - case 6 { - // label L2 + case 8 { + // label L5 // $t47 := 0x42 $t47 := 0x42 // $t48 := borrow_global>($t47) @@ -5709,20 +5924,25 @@ object "test_A2_GlobalVectors_test_push_back_struct_global" { $t54 := 11 // $t55 := ==($t53, $t54) $t55 := $Eq($t53, $t54) - // if ($t55) goto L4 else goto L5 + // if ($t55) goto L7 else goto L6 switch $t55 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t56 := 103 $t56 := 103 // abort($t56) $Abort($t56) } - case 8 { - // label L4 + case 11 { + // label L8 // $t57 := 0x42 $t57 := 0x42 // $t58 := borrow_global>($t57) @@ -5747,20 +5967,25 @@ object "test_A2_GlobalVectors_test_push_back_struct_global" { $t64 := 12 // $t65 := ==($t63, $t64) $t65 := $Eq($t63, $t64) - // if ($t65) goto L6 else goto L7 + // if ($t65) goto L10 else goto L9 switch $t65 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t66 := 104 $t66 := 104 // abort($t66) $Abort($t66) } - case 10 { - // label L6 + case 14 { + // label L11 // return () $Free($locals, 64) leave @@ -6054,7 +6279,7 @@ object "test_A2_GlobalVectors_test_push_back_struct_global" { } } } -===> Test result of GlobalVectors::test_push_back_struct_global: Succeed(Stopped) (used_gas=328457): [] +===> Test result of GlobalVectors::test_push_back_struct_global: Succeed(Stopped) (used_gas=329341): [] // test of GlobalVectors::test_read_ref_copy /* ======================================= @@ -6075,30 +6300,16 @@ object "test_A2_GlobalVectors_test_read_ref_copy" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t16 := 101 $t16 := 101 // abort($t16) $Abort($t16) } - case 3 { - // label L0 - // $t17 := borrow_local($t2) - $t17 := $MakePtr(false, add($locals, 64)) - // $t18 := 0 - $t18 := 0 - // $t19 := vector::borrow($t17, $t18) - $t19 := A1_vector_borrow$u8$($t17, $t18) - // $t20 := read_ref($t19) - $t20 := $LoadU8($t19) - // $t21 := 65 - $t21 := 65 - // $t22 := ==($t20, $t21) - $t22 := $Eq($t20, $t21) - // if ($t22) goto L2 else goto L3 - switch $t22 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t1 := vector::empty() mstore($locals, A1_vector_empty$u8$()) @@ -6186,20 +6397,44 @@ object "test_A2_GlobalVectors_test_read_ref_copy" { $t14 := 1 // $t15 := ==($t13, $t14) $t15 := $Eq($t13, $t14) - // if ($t15) goto L0 else goto L1 + // if ($t15) goto L1 else goto L0 switch $t15 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t17 := borrow_local($t2) + $t17 := $MakePtr(false, add($locals, 64)) + // $t18 := 0 + $t18 := 0 + // $t19 := vector::borrow($t17, $t18) + $t19 := A1_vector_borrow$u8$($t17, $t18) + // $t20 := read_ref($t19) + $t20 := $LoadU8($t19) + // $t21 := 65 + $t21 := 65 + // $t22 := ==($t20, $t21) + $t22 := $Eq($t20, $t21) + // if ($t22) goto L4 else goto L3 + switch $t22 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t23 := 102 $t23 := 102 // abort($t23) $Abort($t23) } - case 6 { - // label L2 + case 8 { + // label L5 // return () $Free($locals, 96) leave @@ -6207,6 +6442,13 @@ object "test_A2_GlobalVectors_test_read_ref_copy" { } } + function A1_vector_borrow$u8$(v_ref, i) -> e_ptr { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + let size := $LoadU64(v_ptr) + if $GtEq(i, size) { $AbortBuiltin() } + e_ptr := $IndexPtr(v_ptr, add(32, mul(i, 1))) + } function A1_vector_length$u8$(v_ref) -> len { let v_offs := $LoadU256(v_ref) let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) @@ -6233,13 +6475,6 @@ object "test_A2_GlobalVectors_test_read_ref_copy" { vector := $Malloc(34) $MemoryStoreU64(add(vector, 8), 2) } - function A1_vector_borrow$u8$(v_ref, i) -> e_ptr { - let v_offs := $LoadU256(v_ref) - let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) - let size := $LoadU64(v_ptr) - if $GtEq(i, size) { $AbortBuiltin() } - e_ptr := $IndexPtr(v_ptr, add(32, mul(i, 1))) - } function $Abort(code) { mstore(0, code) revert(24, 8) // TODO: store code as a string? @@ -6507,7 +6742,7 @@ object "test_A2_GlobalVectors_test_read_ref_copy" { } } } -===> Test result of GlobalVectors::test_read_ref_copy: Succeed(Stopped) (used_gas=114561): [] +===> Test result of GlobalVectors::test_read_ref_copy: Succeed(Stopped) (used_gas=114827): [] // test of GlobalVectors::test_swap_global /* ======================================= @@ -6528,40 +6763,16 @@ object "test_A2_GlobalVectors_test_swap_global" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t23 := 101 $t23 := 101 // abort($t23) $Abort($t23) } - case 3 { - // label L0 - // $t24 := 0x42 - $t24 := 0x42 - // $t25 := borrow_global>($t24) - { - let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $t24) - if iszero($AlignedStorageLoad($base_offset)) { - $AbortBuiltin() - } - $t25 := $MakePtr(true, add($base_offset, 32)) - } - // $t26 := borrow_field>.v($t25) - $t26 := $t25 - // $t27 := 0 - $t27 := 0 - // $t28 := vector::borrow($t26, $t27) - $t28 := A1_vector_borrow$u64$($t26, $t27) - // $t29 := read_ref($t28) - $t29 := $LoadU64($t28) - // $t30 := 44 - $t30 := 44 - // $t31 := ==($t29, $t30) - $t31 := $Eq($t29, $t30) - // if ($t31) goto L2 else goto L3 - switch $t31 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t1 := vector::empty() mstore($locals, A1_vector_empty$u64$()) @@ -6660,20 +6871,54 @@ object "test_A2_GlobalVectors_test_swap_global" { $t21 := 3 // $t22 := ==($t20, $t21) $t22 := $Eq($t20, $t21) - // if ($t22) goto L0 else goto L1 + // if ($t22) goto L1 else goto L0 switch $t22 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t24 := 0x42 + $t24 := 0x42 + // $t25 := borrow_global>($t24) + { + let $base_offset := $MakeTypeStorageBase(0, 0x7da2a540, $t24) + if iszero($AlignedStorageLoad($base_offset)) { + $AbortBuiltin() + } + $t25 := $MakePtr(true, add($base_offset, 32)) + } + // $t26 := borrow_field>.v($t25) + $t26 := $t25 + // $t27 := 0 + $t27 := 0 + // $t28 := vector::borrow($t26, $t27) + $t28 := A1_vector_borrow$u64$($t26, $t27) + // $t29 := read_ref($t28) + $t29 := $LoadU64($t28) + // $t30 := 44 + $t30 := 44 + // $t31 := ==($t29, $t30) + $t31 := $Eq($t29, $t30) + // if ($t31) goto L4 else goto L3 + switch $t31 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t32 := 102 $t32 := 102 // abort($t32) $Abort($t32) } - case 6 { - // label L2 + case 8 { + // label L5 // $t33 := 0x42 $t33 := 0x42 // $t34 := borrow_global>($t33) @@ -6696,20 +6941,25 @@ object "test_A2_GlobalVectors_test_swap_global" { $t39 := 43 // $t40 := ==($t38, $t39) $t40 := $Eq($t38, $t39) - // if ($t40) goto L4 else goto L5 + // if ($t40) goto L7 else goto L6 switch $t40 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t41 := 103 $t41 := 103 // abort($t41) $Abort($t41) } - case 8 { - // label L4 + case 11 { + // label L8 // $t42 := 0x42 $t42 := 0x42 // $t43 := borrow_global>($t42) @@ -6732,20 +6982,25 @@ object "test_A2_GlobalVectors_test_swap_global" { $t48 := 42 // $t49 := ==($t47, $t48) $t49 := $Eq($t47, $t48) - // if ($t49) goto L6 else goto L7 + // if ($t49) goto L10 else goto L9 switch $t49 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t50 := 104 $t50 := 104 // abort($t50) $Abort($t50) } - case 10 { - // label L6 + case 14 { + // label L11 // return () $Free($locals, 64) leave @@ -7023,4 +7278,4 @@ object "test_A2_GlobalVectors_test_swap_global" { } } } -===> Test result of GlobalVectors::test_swap_global: Succeed(Stopped) (used_gas=123197): [] +===> Test result of GlobalVectors::test_swap_global: Succeed(Stopped) (used_gas=124086): [] diff --git a/language/evm/move-to-yul/tests/Locals.exp b/language/evm/move-to-yul/tests/Locals.exp index d8d7628cde..62b4cb4f57 100644 --- a/language/evm/move-to-yul/tests/Locals.exp +++ b/language/evm/move-to-yul/tests/Locals.exp @@ -32,38 +32,38 @@ object "A2_M" { } $Abort(97) function A2_M_evaded(a, b) -> $result0, $result1, $result2, $result3 { - let ar, cr, d, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15 + let ar, d, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14 let $locals := $Malloc(64) mstore($locals, a) - // $t6 := copy($t0) - $t6 := mload($locals) - // $t3 := $t6 - mstore(add($locals, 32), $t6) - // $t7 := copy($t3) - $t7 := mload(add($locals, 32)) - // $t8 := +($t7, $t1) - $t8 := $AddU64($t7, b) - // $t9 := borrow_local($t0) - $t9 := $MakePtr(false, add($locals, 24)) - // $t10 := borrow_local($t3) - $t10 := $MakePtr(false, add($locals, 56)) - // $t11 := read_ref($t10) - $t11 := $LoadU64($t10) - // $t12 := 1 - $t12 := 1 - // $t13 := +($t11, $t12) - $t13 := $AddU64($t11, $t12) - // write_ref($t9, $t13) - $StoreU64($t9, $t13) - // $t14 := move($t0) - $t14 := mload($locals) - // $t15 := move($t3) - $t15 := mload(add($locals, 32)) - // return ($t14, $t1, $t15, $t8) - $result0 := $t14 + // $t5 := copy($t0) + $t5 := mload($locals) + // $t3 := $t5 + mstore(add($locals, 32), $t5) + // $t6 := copy($t3) + $t6 := mload(add($locals, 32)) + // $t7 := +($t6, $t1) + $t7 := $AddU64($t6, b) + // $t8 := borrow_local($t0) + $t8 := $MakePtr(false, add($locals, 24)) + // $t9 := borrow_local($t3) + $t9 := $MakePtr(false, add($locals, 56)) + // $t10 := read_ref($t9) + $t10 := $LoadU64($t9) + // $t11 := 1 + $t11 := 1 + // $t12 := +($t10, $t11) + $t12 := $AddU64($t10, $t11) + // write_ref($t8, $t12) + $StoreU64($t8, $t12) + // $t13 := move($t0) + $t13 := mload($locals) + // $t14 := move($t3) + $t14 := mload(add($locals, 32)) + // return ($t13, $t1, $t14, $t7) + $result0 := $t13 $result1 := b - $result2 := $t15 - $result3 := $t8 + $result2 := $t14 + $result3 := $t7 $Free($locals, 64) } @@ -275,17 +275,16 @@ object "test_A2_M_test_call_by_ref" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t6 := 101 $t6 := 101 // abort($t6) $Abort($t6) } - case 3 { - // label L0 - // return () - $Free($locals, 32) - leave - } case 4 { // $t1 := 1 $t1 := 1 @@ -301,10 +300,16 @@ object "test_A2_M_test_call_by_ref" { $t4 := 2 // $t5 := ==($t3, $t4) $t5 := $Eq($t3, $t4) - // if ($t5) goto L0 else goto L1 + // if ($t5) goto L1 else goto L0 switch $t5 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // return () + $Free($locals, 32) + leave } } } @@ -412,7 +417,7 @@ object "test_A2_M_test_call_by_ref" { } } } -===> Test result of M::test_call_by_ref: Succeed(Stopped) (used_gas=410): [] +===> Test result of M::test_call_by_ref: Succeed(Stopped) (used_gas=488): [] // test of M::test_evaded /* ======================================= @@ -426,89 +431,109 @@ object "test_A2_M_test_evaded" { A2_M_test_evaded() return (0, 0) function A2_M_test_evaded() { - let a, b, c, d, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20, $t21 + let b, c, d, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t12 := 100 - $t12 := 100 - // abort($t12) - $Abort($t12) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t13 := 2 - $t13 := 2 - // $t14 := ==($t7, $t13) - $t14 := $Eq($t7, $t13) - // if ($t14) goto L2 else goto L3 - switch $t14 - case 0 { $block := 5 } - default { $block := 6 } + // $t11 := 100 + $t11 := 100 + // abort($t11) + $Abort($t11) } case 4 { - // $t4 := 1 - $t4 := 1 - // $t5 := 2 - $t5 := 2 - // ($t6, $t7, $t8, $t9) := M::evaded($t4, $t5) - $t6, $t7, $t8, $t9 := A2_M_evaded($t4, $t5) - // $t10 := 2 - $t10 := 2 - // $t11 := ==($t6, $t10) - $t11 := $Eq($t6, $t10) - // if ($t11) goto L0 else goto L1 - switch $t11 - case 0 { $block := 2 } - default { $block := 3 } + // $t3 := 1 + $t3 := 1 + // $t4 := 2 + $t4 := 2 + // ($t5, $t6, $t7, $t8) := M::evaded($t3, $t4) + $t5, $t6, $t7, $t8 := A2_M_evaded($t3, $t4) + // $t9 := 2 + $t9 := 2 + // $t10 := ==($t5, $t9) + $t10 := $Eq($t5, $t9) + // if ($t10) goto L1 else goto L0 + switch $t10 + case 0 { $block := 3 } + default { $block := 2 } } case 5 { - // label L3 - // $t15 := 101 - $t15 := 101 - // abort($t15) - $Abort($t15) - } - case 6 { // label L2 - // $t16 := 1 - $t16 := 1 - // $t17 := ==($t8, $t16) - $t17 := $Eq($t8, $t16) - // if ($t17) goto L4 else goto L5 - switch $t17 + // $t12 := 2 + $t12 := 2 + // $t13 := ==($t6, $t12) + $t13 := $Eq($t6, $t12) + // if ($t13) goto L4 else goto L3 + switch $t13 case 0 { $block := 7 } - default { $block := 8 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 } case 7 { - // label L5 - // $t18 := 102 - $t18 := 102 - // abort($t18) - $Abort($t18) + // label L3 + // $t14 := 101 + $t14 := 101 + // abort($t14) + $Abort($t14) } case 8 { - // label L4 - // $t19 := 3 - $t19 := 3 - // $t20 := ==($t9, $t19) - $t20 := $Eq($t9, $t19) - // if ($t20) goto L6 else goto L7 - switch $t20 - case 0 { $block := 9 } - default { $block := 10 } + // label L5 + // $t15 := 1 + $t15 := 1 + // $t16 := ==($t7, $t15) + $t16 := $Eq($t7, $t15) + // if ($t16) goto L7 else goto L6 + switch $t16 + case 0 { $block := 10 } + default { $block := 9 } } case 9 { // label L7 - // $t21 := 103 - $t21 := 103 - // abort($t21) - $Abort($t21) + // goto L8 + $block := 11 } case 10 { // label L6 + // $t17 := 102 + $t17 := 102 + // abort($t17) + $Abort($t17) + } + case 11 { + // label L8 + // $t18 := 3 + $t18 := 3 + // $t19 := ==($t8, $t18) + $t19 := $Eq($t8, $t18) + // if ($t19) goto L10 else goto L9 + switch $t19 + case 0 { $block := 13 } + default { $block := 12 } + } + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 + // $t20 := 103 + $t20 := 103 + // abort($t20) + $Abort($t20) + } + case 14 { + // label L11 // return () leave } @@ -516,38 +541,38 @@ object "test_A2_M_test_evaded" { } function A2_M_evaded(a, b) -> $result0, $result1, $result2, $result3 { - let ar, cr, d, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15 + let ar, d, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14 let $locals := $Malloc(64) mstore($locals, a) - // $t6 := copy($t0) - $t6 := mload($locals) - // $t3 := $t6 - mstore(add($locals, 32), $t6) - // $t7 := copy($t3) - $t7 := mload(add($locals, 32)) - // $t8 := +($t7, $t1) - $t8 := $AddU64($t7, b) - // $t9 := borrow_local($t0) - $t9 := $MakePtr(false, add($locals, 24)) - // $t10 := borrow_local($t3) - $t10 := $MakePtr(false, add($locals, 56)) - // $t11 := read_ref($t10) - $t11 := $LoadU64($t10) - // $t12 := 1 - $t12 := 1 - // $t13 := +($t11, $t12) - $t13 := $AddU64($t11, $t12) - // write_ref($t9, $t13) - $StoreU64($t9, $t13) - // $t14 := move($t0) - $t14 := mload($locals) - // $t15 := move($t3) - $t15 := mload(add($locals, 32)) - // return ($t14, $t1, $t15, $t8) - $result0 := $t14 + // $t5 := copy($t0) + $t5 := mload($locals) + // $t3 := $t5 + mstore(add($locals, 32), $t5) + // $t6 := copy($t3) + $t6 := mload(add($locals, 32)) + // $t7 := +($t6, $t1) + $t7 := $AddU64($t6, b) + // $t8 := borrow_local($t0) + $t8 := $MakePtr(false, add($locals, 24)) + // $t9 := borrow_local($t3) + $t9 := $MakePtr(false, add($locals, 56)) + // $t10 := read_ref($t9) + $t10 := $LoadU64($t9) + // $t11 := 1 + $t11 := 1 + // $t12 := +($t10, $t11) + $t12 := $AddU64($t10, $t11) + // write_ref($t8, $t12) + $StoreU64($t8, $t12) + // $t13 := move($t0) + $t13 := mload($locals) + // $t14 := move($t3) + $t14 := mload(add($locals, 32)) + // return ($t13, $t1, $t14, $t7) + $result0 := $t13 $result1 := b - $result2 := $t15 - $result3 := $t8 + $result2 := $t14 + $result3 := $t7 $Free($locals, 64) } @@ -701,7 +726,7 @@ object "test_A2_M_test_evaded" { } } } -===> Test result of M::test_evaded: Succeed(Stopped) (used_gas=1261): [] +===> Test result of M::test_evaded: Succeed(Stopped) (used_gas=2140): [] // test of M::test_freeze_ref /* ======================================= @@ -722,17 +747,16 @@ object "test_A2_M_test_freeze_ref" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t7 := 101 $t7 := 101 // abort($t7) $Abort($t7) } - case 3 { - // label L0 - // return () - $Free($locals, 32) - leave - } case 4 { // $t1 := 1 $t1 := 1 @@ -742,18 +766,22 @@ object "test_A2_M_test_freeze_ref" { $t2 := $MakePtr(false, add($locals, 24)) // $t3 := freeze_ref($t2) $t3 := $t2 - // $t0 := M::call_by_immut_ref($t3) - mstore($locals, A2_M_call_by_immut_ref($t3)) - // $t4 := move($t0) - $t4 := mload($locals) + // $t4 := M::call_by_immut_ref($t3) + $t4 := A2_M_call_by_immut_ref($t3) // $t5 := 1 $t5 := 1 // $t6 := ==($t4, $t5) $t6 := $Eq($t4, $t5) - // if ($t6) goto L0 else goto L1 + // if ($t6) goto L1 else goto L0 switch $t6 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // return () + $Free($locals, 32) + leave } } } @@ -862,4 +890,4 @@ object "test_A2_M_test_freeze_ref" { } } } -===> Test result of M::test_freeze_ref: Succeed(Stopped) (used_gas=364): [] +===> Test result of M::test_freeze_ref: Succeed(Stopped) (used_gas=438): [] diff --git a/language/evm/move-to-yul/tests/NativeFunctions.exp b/language/evm/move-to-yul/tests/NativeFunctions.exp index 28654c4e0b..30c64eeeeb 100644 --- a/language/evm/move-to-yul/tests/NativeFunctions.exp +++ b/language/evm/move-to-yul/tests/NativeFunctions.exp @@ -312,37 +312,16 @@ object "test_A2_NativeFunctions_test_concat" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t5 := 100 $t5 := 100 // abort($t5) $Abort($t5) } - case 3 { - // label L0 - // $t6 := [49] - $t6 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(1))) - $MemoryStoreU64($t6, 1) - $MemoryStoreU64(add($t6, 8), $ClosestGreaterPowerOfTwo(1)) - copy_literal_string_to_memory_2868747976(add($t6, 32)) - // $t7 := [50] - $t7 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(1))) - $MemoryStoreU64($t7, 1) - $MemoryStoreU64(add($t7, 8), $ClosestGreaterPowerOfTwo(1)) - copy_literal_string_to_memory_4015750317(add($t7, 32)) - // $t8 := Evm::concat($t6, $t7) - $t8 := A2_Evm_concat($t6, $t7) - // $t9 := [49, 50] - $t9 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(2))) - $MemoryStoreU64($t9, 2) - $MemoryStoreU64(add($t9, 8), $ClosestGreaterPowerOfTwo(2)) - copy_literal_string_to_memory_141265791(add($t9, 32)) - // $t10 := ==($t8, $t9) - $t10 := $Eq_$vec$u8$$($t8, $t9) - // if ($t10) goto L2 else goto L3 - switch $t10 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t0 := [] $t0 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(0))) @@ -363,20 +342,51 @@ object "test_A2_NativeFunctions_test_concat" { copy_literal_string_to_memory_21418693(add($t3, 32)) // $t4 := ==($t2, $t3) $t4 := $Eq_$vec$u8$$($t2, $t3) - // if ($t4) goto L0 else goto L1 + // if ($t4) goto L1 else goto L0 switch $t4 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t6 := [49] + $t6 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(1))) + $MemoryStoreU64($t6, 1) + $MemoryStoreU64(add($t6, 8), $ClosestGreaterPowerOfTwo(1)) + copy_literal_string_to_memory_2868747976(add($t6, 32)) + // $t7 := [50] + $t7 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(1))) + $MemoryStoreU64($t7, 1) + $MemoryStoreU64(add($t7, 8), $ClosestGreaterPowerOfTwo(1)) + copy_literal_string_to_memory_4015750317(add($t7, 32)) + // $t8 := Evm::concat($t6, $t7) + $t8 := A2_Evm_concat($t6, $t7) + // $t9 := [49, 50] + $t9 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(2))) + $MemoryStoreU64($t9, 2) + $MemoryStoreU64(add($t9, 8), $ClosestGreaterPowerOfTwo(2)) + copy_literal_string_to_memory_141265791(add($t9, 32)) + // $t10 := ==($t8, $t9) + $t10 := $Eq_$vec$u8$$($t8, $t9) + // if ($t10) goto L4 else goto L3 + switch $t10 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t11 := 101 $t11 := 101 // abort($t11) $Abort($t11) } - case 6 { - // label L2 + case 8 { + // label L5 // $t12 := [] $t12 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(0))) $MemoryStoreU64($t12, 0) @@ -396,20 +406,25 @@ object "test_A2_NativeFunctions_test_concat" { copy_literal_string_to_memory_2053440334(add($t15, 32)) // $t16 := ==($t14, $t15) $t16 := $Eq_$vec$u8$$($t14, $t15) - // if ($t16) goto L4 else goto L5 + // if ($t16) goto L7 else goto L6 switch $t16 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t17 := 102 $t17 := 102 // abort($t17) $Abort($t17) } - case 8 { - // label L4 + case 11 { + // label L8 // $t18 := [97] $t18 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(1))) $MemoryStoreU64($t18, 1) @@ -436,20 +451,25 @@ object "test_A2_NativeFunctions_test_concat" { copy_literal_string_to_memory_3871831907(add($t23, 32)) // $t24 := ==($t22, $t23) $t24 := $Eq_$vec$u8$$($t22, $t23) - // if ($t24) goto L6 else goto L7 + // if ($t24) goto L10 else goto L9 switch $t24 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t25 := 103 $t25 := 103 // abort($t25) $Abort($t25) } - case 10 { - // label L6 + case 14 { + // label L11 // $t26 := [116, 101, 115, 116] $t26 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(4))) $MemoryStoreU64($t26, 4) @@ -469,20 +489,25 @@ object "test_A2_NativeFunctions_test_concat" { copy_literal_string_to_memory_1610556060(add($t29, 32)) // $t30 := ==($t28, $t29) $t30 := $Eq_$vec$u8$$($t28, $t29) - // if ($t30) goto L8 else goto L9 + // if ($t30) goto L13 else goto L12 switch $t30 - case 0 { $block := 11 } - default { $block := 12 } + case 0 { $block := 16 } + default { $block := 15 } } - case 11 { - // label L9 + case 15 { + // label L13 + // goto L14 + $block := 17 + } + case 16 { + // label L12 // $t31 := 104 $t31 := 104 // abort($t31) $Abort($t31) } - case 12 { - // label L8 + case 17 { + // label L14 // return () leave } @@ -667,7 +692,7 @@ object "test_A2_NativeFunctions_test_concat" { } } } -===> Test result of NativeFunctions::test_concat: Succeed(Stopped) (used_gas=9535): [] +===> Test result of NativeFunctions::test_concat: Succeed(Stopped) (used_gas=10872): [] // test of NativeFunctions::test_signer_address_of /* ======================================= @@ -688,17 +713,16 @@ object "test_A2_NativeFunctions_test_signer_address_of" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t6 := 101 $t6 := 101 // abort($t6) $Abort($t6) } - case 3 { - // label L0 - // return () - $Free($locals, 32) - leave - } case 4 { // $t1 := 0x42 $t1 := 0x42 @@ -712,10 +736,16 @@ object "test_A2_NativeFunctions_test_signer_address_of" { $t4 := 0x42 // $t5 := ==($t3, $t4) $t5 := $Eq($t3, $t4) - // if ($t5) goto L0 else goto L1 + // if ($t5) goto L1 else goto L0 switch $t5 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // return () + $Free($locals, 32) + leave } } } @@ -832,7 +862,7 @@ object "test_A2_NativeFunctions_test_signer_address_of" { } } } -===> Test result of NativeFunctions::test_signer_address_of: Succeed(Stopped) (used_gas=345): [] +===> Test result of NativeFunctions::test_signer_address_of: Succeed(Stopped) (used_gas=431): [] // test of NativeFunctions::test_to_string /* ======================================= @@ -852,29 +882,16 @@ object "test_A2_NativeFunctions_test_to_string" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t4 := 101 $t4 := 101 // abort($t4) $Abort($t4) } - case 3 { - // label L0 - // $t5 := U256::one() - $t5 := A2_U256_one() - // $t6 := Evm::to_string($t5) - $t6 := A2_Evm_to_string($t5) - // $t7 := [49] - $t7 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(1))) - $MemoryStoreU64($t7, 1) - $MemoryStoreU64(add($t7, 8), $ClosestGreaterPowerOfTwo(1)) - copy_literal_string_to_memory_2868747976(add($t7, 32)) - // $t8 := ==($t6, $t7) - $t8 := $Eq_$vec$u8$$($t6, $t7) - // if ($t8) goto L2 else goto L3 - switch $t8 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t0 := U256::zero() $t0 := A2_U256_zero() @@ -887,20 +904,43 @@ object "test_A2_NativeFunctions_test_to_string" { copy_literal_string_to_memory_2991736836(add($t2, 32)) // $t3 := ==($t1, $t2) $t3 := $Eq_$vec$u8$$($t1, $t2) - // if ($t3) goto L0 else goto L1 + // if ($t3) goto L1 else goto L0 switch $t3 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t5 := U256::one() + $t5 := A2_U256_one() + // $t6 := Evm::to_string($t5) + $t6 := A2_Evm_to_string($t5) + // $t7 := [49] + $t7 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(1))) + $MemoryStoreU64($t7, 1) + $MemoryStoreU64(add($t7, 8), $ClosestGreaterPowerOfTwo(1)) + copy_literal_string_to_memory_2868747976(add($t7, 32)) + // $t8 := ==($t6, $t7) + $t8 := $Eq_$vec$u8$$($t6, $t7) + // if ($t8) goto L4 else goto L3 + switch $t8 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t9 := 102 $t9 := 102 // abort($t9) $Abort($t9) } - case 6 { - // label L2 + case 8 { + // label L5 // $t10 := 42 $t10 := 42 // $t11 := U256::u256_from_u128($t10) @@ -914,20 +954,25 @@ object "test_A2_NativeFunctions_test_to_string" { copy_literal_string_to_memory_402108876(add($t13, 32)) // $t14 := ==($t12, $t13) $t14 := $Eq_$vec$u8$$($t12, $t13) - // if ($t14) goto L4 else goto L5 + // if ($t14) goto L7 else goto L6 switch $t14 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t15 := 103 $t15 := 103 // abort($t15) $Abort($t15) } - case 8 { - // label L4 + case 11 { + // label L8 // $t16 := 7008 $t16 := 7008 // $t17 := U256::u256_from_u128($t16) @@ -941,20 +986,25 @@ object "test_A2_NativeFunctions_test_to_string" { copy_literal_string_to_memory_2919365730(add($t19, 32)) // $t20 := ==($t18, $t19) $t20 := $Eq_$vec$u8$$($t18, $t19) - // if ($t20) goto L6 else goto L7 + // if ($t20) goto L10 else goto L9 switch $t20 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t21 := 104 $t21 := 104 // abort($t21) $Abort($t21) } - case 10 { - // label L6 + case 14 { + // label L11 // $t22 := 340282366920938463463374607431768211458 $t22 := 340282366920938463463374607431768211458 // $t23 := Evm::to_string($t22) @@ -966,20 +1016,25 @@ object "test_A2_NativeFunctions_test_to_string" { copy_literal_string_to_memory_767927084(add($t24, 32)) // $t25 := ==($t23, $t24) $t25 := $Eq_$vec$u8$$($t23, $t24) - // if ($t25) goto L8 else goto L9 + // if ($t25) goto L13 else goto L12 switch $t25 - case 0 { $block := 11 } - default { $block := 12 } + case 0 { $block := 16 } + default { $block := 15 } } - case 11 { - // label L9 + case 15 { + // label L13 + // goto L14 + $block := 17 + } + case 16 { + // label L12 // $t26 := 105 $t26 := 105 // abort($t26) $Abort($t26) } - case 12 { - // label L8 + case 17 { + // label L14 // return () leave } @@ -999,18 +1054,18 @@ object "test_A2_NativeFunctions_test_to_string" { $result := $t2 } - function A2_U256_zero() -> $result { + function A2_U256_one() -> $result { let $t0 - // $t0 := 0 - $t0 := 0 + // $t0 := 1 + $t0 := 1 // return $t0 $result := $t0 } - function A2_U256_one() -> $result { + function A2_U256_zero() -> $result { let $t0 - // $t0 := 1 - $t0 := 1 + // $t0 := 0 + $t0 := 0 // return $t0 $result := $t0 } @@ -1115,14 +1170,14 @@ object "test_A2_NativeFunctions_test_to_string" { $MemoryStoreU8(value, 50) value := add(value, 1) } - function copy_literal_string_to_memory_2991736836(value) { - $MemoryStoreU8(value, 48) - value := add(value, 1) - } function copy_literal_string_to_memory_2868747976(value) { $MemoryStoreU8(value, 49) value := add(value, 1) } + function copy_literal_string_to_memory_2991736836(value) { + $MemoryStoreU8(value, 48) + value := add(value, 1) + } function $Abort(code) { mstore(0, code) revert(24, 8) // TODO: store code as a string? @@ -1231,4 +1286,4 @@ object "test_A2_NativeFunctions_test_to_string" { } } } -===> Test result of NativeFunctions::test_to_string: Succeed(Stopped) (used_gas=11916): [] +===> Test result of NativeFunctions::test_to_string: Succeed(Stopped) (used_gas=13241): [] diff --git a/language/evm/move-to-yul/tests/Resources.exp b/language/evm/move-to-yul/tests/Resources.exp index 2a6a55ee6a..e75268ee3b 100644 --- a/language/evm/move-to-yul/tests/Resources.exp +++ b/language/evm/move-to-yul/tests/Resources.exp @@ -54,17 +54,16 @@ object "test_A2_M_test_increment_a" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t11 := 100 $t11 := 100 // abort($t11) $Abort($t11) } - case 3 { - // label L0 - // return () - $Free($locals, 32) - leave - } case 4 { // $t1 := 0x3 $t1 := 0x3 @@ -98,10 +97,16 @@ object "test_A2_M_test_increment_a" { $t9 := 511 // $t10 := ==($t8, $t9) $t10 := $Eq($t8, $t9) - // if ($t10) goto L0 else goto L1 + // if ($t10) goto L1 else goto L0 switch $t10 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // return () + $Free($locals, 32) + leave } } } @@ -392,7 +397,7 @@ object "test_A2_M_test_increment_a" { } } } -===> Test result of M::test_increment_a: Succeed(Stopped) (used_gas=113444): [] +===> Test result of M::test_increment_a: Succeed(Stopped) (used_gas=113532): [] // test of M::test_publish /* ======================================= @@ -413,13 +418,38 @@ object "test_A2_M_test_publish" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t6 := 100 $t6 := 100 // abort($t6) $Abort($t6) } - case 3 { - // label L0 + case 4 { + // $t1 := 0x3 + $t1 := 0x3 + // $t0 := Evm::sign($t1) + mstore($locals, A2_Evm_sign($t1)) + // $t2 := borrow_local($t0) + $t2 := $MakePtr(false, $locals) + // $t3 := 22 + $t3 := 22 + // M::publish($t2, $t3) + A2_M_publish($t2, $t3) + // $t4 := 0x3 + $t4 := 0x3 + // $t5 := exists($t4) + $t5 := $AlignedStorageLoad($MakeTypeStorageBase(0, 0x698265eb, $t4)) + // if ($t5) goto L1 else goto L0 + switch $t5 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t7 := 0x3 $t7 := 0x3 // $t8 := borrow_global($t7) @@ -438,40 +468,25 @@ object "test_A2_M_test_publish" { $t11 := 22 // $t12 := ==($t10, $t11) $t12 := $Eq($t10, $t11) - // if ($t12) goto L2 else goto L3 + // if ($t12) goto L4 else goto L3 switch $t12 - case 0 { $block := 5 } + case 0 { $block := 7 } default { $block := 6 } } - case 4 { - // $t1 := 0x3 - $t1 := 0x3 - // $t0 := Evm::sign($t1) - mstore($locals, A2_Evm_sign($t1)) - // $t2 := borrow_local($t0) - $t2 := $MakePtr(false, $locals) - // $t3 := 22 - $t3 := 22 - // M::publish($t2, $t3) - A2_M_publish($t2, $t3) - // $t4 := 0x3 - $t4 := 0x3 - // $t5 := exists($t4) - $t5 := $AlignedStorageLoad($MakeTypeStorageBase(0, 0x698265eb, $t4)) - // if ($t5) goto L0 else goto L1 - switch $t5 - case 0 { $block := 2 } - default { $block := 3 } + case 6 { + // label L4 + // goto L5 + $block := 8 } - case 5 { + case 7 { // label L3 // $t13 := 101 $t13 := 101 // abort($t13) $Abort($t13) } - case 6 { - // label L2 + case 8 { + // label L5 // $t14 := 0x3 $t14 := 0x3 // $t15 := borrow_global($t14) @@ -490,20 +505,25 @@ object "test_A2_M_test_publish" { $t18 := 11 // $t19 := ==($t17, $t18) $t19 := $Eq($t17, $t18) - // if ($t19) goto L4 else goto L5 + // if ($t19) goto L7 else goto L6 switch $t19 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t20 := 102 $t20 := 102 // abort($t20) $Abort($t20) } - case 8 { - // label L4 + case 11 { + // label L8 // $t21 := 0x3 $t21 := 0x3 // $t22 := borrow_global($t21) @@ -526,20 +546,25 @@ object "test_A2_M_test_publish" { $t26 := 44 // $t27 := ==($t25, $t26) $t27 := $Eq($t25, $t26) - // if ($t27) goto L6 else goto L7 + // if ($t27) goto L10 else goto L9 switch $t27 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t28 := 103 $t28 := 103 // abort($t28) $Abort($t28) } - case 10 { - // label L6 + case 14 { + // label L11 // return () $Free($locals, 32) leave @@ -801,7 +826,7 @@ object "test_A2_M_test_publish" { } } } -===> Test result of M::test_publish: Succeed(Stopped) (used_gas=114429): [] +===> Test result of M::test_publish: Succeed(Stopped) (used_gas=115318): [] // test of M::test_publish_t /* ======================================= @@ -822,13 +847,38 @@ object "test_A2_M_test_publish_t" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t6 := 100 $t6 := 100 // abort($t6) $Abort($t6) } - case 3 { - // label L0 + case 4 { + // $t1 := 0x3 + $t1 := 0x3 + // $t0 := Evm::sign($t1) + mstore($locals, A2_Evm_sign($t1)) + // $t2 := borrow_local($t0) + $t2 := $MakePtr(false, $locals) + // $t3 := 22 + $t3 := 22 + // M::publish_t($t2, $t3) + A2_M_publish_t($t2, $t3) + // $t4 := 0x3 + $t4 := 0x3 + // $t5 := exists($t4) + $t5 := $AlignedStorageLoad($MakeTypeStorageBase(0, 0x3948ca0a, $t4)) + // if ($t5) goto L1 else goto L0 + switch $t5 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t7 := 0x3 $t7 := 0x3 // $t8 := borrow_global($t7) @@ -851,40 +901,25 @@ object "test_A2_M_test_publish_t" { $t12 := 22 // $t13 := ==($t11, $t12) $t13 := $Eq($t11, $t12) - // if ($t13) goto L2 else goto L3 + // if ($t13) goto L4 else goto L3 switch $t13 - case 0 { $block := 5 } + case 0 { $block := 7 } default { $block := 6 } } - case 4 { - // $t1 := 0x3 - $t1 := 0x3 - // $t0 := Evm::sign($t1) - mstore($locals, A2_Evm_sign($t1)) - // $t2 := borrow_local($t0) - $t2 := $MakePtr(false, $locals) - // $t3 := 22 - $t3 := 22 - // M::publish_t($t2, $t3) - A2_M_publish_t($t2, $t3) - // $t4 := 0x3 - $t4 := 0x3 - // $t5 := exists($t4) - $t5 := $AlignedStorageLoad($MakeTypeStorageBase(0, 0x3948ca0a, $t4)) - // if ($t5) goto L0 else goto L1 - switch $t5 - case 0 { $block := 2 } - default { $block := 3 } + case 6 { + // label L4 + // goto L5 + $block := 8 } - case 5 { + case 7 { // label L3 // $t14 := 101 $t14 := 101 // abort($t14) $Abort($t14) } - case 6 { - // label L2 + case 8 { + // label L5 // $t15 := 0x3 $t15 := 0x3 // $t16 := borrow_global($t15) @@ -907,20 +942,25 @@ object "test_A2_M_test_publish_t" { $t20 := 11 // $t21 := ==($t19, $t20) $t21 := $Eq($t19, $t20) - // if ($t21) goto L4 else goto L5 + // if ($t21) goto L7 else goto L6 switch $t21 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t22 := 102 $t22 := 102 // abort($t22) $Abort($t22) } - case 8 { - // label L4 + case 11 { + // label L8 // $t23 := 0x3 $t23 := 0x3 // $t24 := borrow_global($t23) @@ -947,20 +987,25 @@ object "test_A2_M_test_publish_t" { $t29 := 44 // $t30 := ==($t28, $t29) $t30 := $Eq($t28, $t29) - // if ($t30) goto L6 else goto L7 + // if ($t30) goto L10 else goto L9 switch $t30 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t31 := 103 $t31 := 103 // abort($t31) $Abort($t31) } - case 10 { - // label L6 + case 14 { + // label L11 // return () $Free($locals, 32) leave @@ -1234,7 +1279,7 @@ object "test_A2_M_test_publish_t" { } } } -===> Test result of M::test_publish_t: Succeed(Stopped) (used_gas=138059): [] +===> Test result of M::test_publish_t: Succeed(Stopped) (used_gas=138948): [] // test of M::test_unpublish /* ======================================= @@ -1248,88 +1293,103 @@ object "test_A2_M_test_unpublish" { A2_M_test_unpublish() return (0, 0) function A2_M_test_unpublish() { - let a, b, x, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20, $t21 + let b, x, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20 let $locals := $Malloc(32) let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t15 := 101 - $t15 := 101 - // abort($t15) - $Abort($t15) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t16 := 16 - $t16 := 16 - // $t17 := ==($t10, $t16) - $t17 := $Eq($t10, $t16) - // if ($t17) goto L2 else goto L3 - switch $t17 - case 0 { $block := 5 } - default { $block := 6 } + // $t14 := 101 + $t14 := 101 + // abort($t14) + $Abort($t14) } case 4 { - // $t4 := 0x3 - $t4 := 0x3 - // $t0 := Evm::sign($t4) - mstore($locals, A2_Evm_sign($t4)) - // $t5 := borrow_local($t0) - $t5 := $MakePtr(false, $locals) - // $t6 := 33 - $t6 := 33 - // M::publish($t5, $t6) - A2_M_publish($t5, $t6) - // $t7 := 0x3 - $t7 := 0x3 - // $t8 := M::unpublish($t7) - $t8 := A2_M_unpublish($t7) - // ($t9, $t10, $t11) := unpack M::S($t8) - $t9 := $MemoryLoadU64(add($t8, 32)) - $t10 := $MemoryLoadU8(add($t8, 40)) - $t11 := $MemoryLoadU256(add($t8, 0)) - $Free($t8, 41) - // $t12 := unpack M::S2($t11) - $t12 := $MemoryLoadU128(add($t11, 0)) - $Free($t11, 16) - // $t13 := 33 - $t13 := 33 - // $t14 := ==($t9, $t13) - $t14 := $Eq($t9, $t13) - // if ($t14) goto L0 else goto L1 - switch $t14 - case 0 { $block := 2 } - default { $block := 3 } + // $t3 := 0x3 + $t3 := 0x3 + // $t0 := Evm::sign($t3) + mstore($locals, A2_Evm_sign($t3)) + // $t4 := borrow_local($t0) + $t4 := $MakePtr(false, $locals) + // $t5 := 33 + $t5 := 33 + // M::publish($t4, $t5) + A2_M_publish($t4, $t5) + // $t6 := 0x3 + $t6 := 0x3 + // $t7 := M::unpublish($t6) + $t7 := A2_M_unpublish($t6) + // ($t8, $t9, $t10) := unpack M::S($t7) + $t8 := $MemoryLoadU64(add($t7, 32)) + $t9 := $MemoryLoadU8(add($t7, 40)) + $t10 := $MemoryLoadU256(add($t7, 0)) + $Free($t7, 41) + // $t11 := unpack M::S2($t10) + $t11 := $MemoryLoadU128(add($t10, 0)) + $Free($t10, 16) + // $t12 := 33 + $t12 := 33 + // $t13 := ==($t8, $t12) + $t13 := $Eq($t8, $t12) + // if ($t13) goto L1 else goto L0 + switch $t13 + case 0 { $block := 3 } + default { $block := 2 } } case 5 { - // label L3 - // $t18 := 102 - $t18 := 102 - // abort($t18) - $Abort($t18) - } - case 6 { // label L2 - // $t19 := 66 - $t19 := 66 - // $t20 := ==($t12, $t19) - $t20 := $Eq($t12, $t19) - // if ($t20) goto L4 else goto L5 - switch $t20 + // $t15 := 16 + $t15 := 16 + // $t16 := ==($t9, $t15) + $t16 := $Eq($t9, $t15) + // if ($t16) goto L4 else goto L3 + switch $t16 case 0 { $block := 7 } - default { $block := 8 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 } case 7 { - // label L5 - // $t21 := 103 - $t21 := 103 - // abort($t21) - $Abort($t21) + // label L3 + // $t17 := 102 + $t17 := 102 + // abort($t17) + $Abort($t17) } case 8 { - // label L4 + // label L5 + // $t18 := 66 + $t18 := 66 + // $t19 := ==($t11, $t18) + $t19 := $Eq($t11, $t18) + // if ($t19) goto L7 else goto L6 + switch $t19 + case 0 { $block := 10 } + default { $block := 9 } + } + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 + // $t20 := 103 + $t20 := 103 + // abort($t20) + $Abort($t20) + } + case 11 { + // label L8 // return () $Free($locals, 32) leave @@ -1580,4 +1640,4 @@ object "test_A2_M_test_unpublish" { } } } -===> Test result of M::test_unpublish: Succeed(Stopped) (used_gas=90786): [] +===> Test result of M::test_unpublish: Succeed(Stopped) (used_gas=91212): [] diff --git a/language/evm/move-to-yul/tests/Resources.exp.capture-source-info b/language/evm/move-to-yul/tests/Resources.exp.capture-source-info index b2e2898faa..c04def6d75 100644 --- a/language/evm/move-to-yul/tests/Resources.exp.capture-source-info +++ b/language/evm/move-to-yul/tests/Resources.exp.capture-source-info @@ -58,6 +58,12 @@ object "test_A2_M_test_increment_a" { switch $block case 2 { // label L1 + // goto L2 + /// @src 1:1284:1327 + $block := 5 + } + case 3 { + // label L0 // $t11 := 100 /// @src 1:1323:1326 $t11 := 100 @@ -65,13 +71,6 @@ object "test_A2_M_test_increment_a" { /// @src 1:1284:1327 $Abort($t11) } - case 3 { - // label L0 - // return () - /// @src 1:1327:1328 - $Free($locals, 32) - leave - } case 4 { // $t1 := 0x3 /// @src 1:1240:1242 @@ -118,11 +117,18 @@ object "test_A2_M_test_increment_a" { // $t10 := ==($t8, $t9) /// @src 1:1315:1317 $t10 := $Eq($t8, $t9) - // if ($t10) goto L0 else goto L1 + // if ($t10) goto L1 else goto L0 /// @src 1:1284:1327 switch $t10 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // return () + /// @src 1:1327:1328 + $Free($locals, 32) + leave } } } @@ -430,7 +436,7 @@ object "test_A2_M_test_increment_a" { } } } -===> Test result of M::test_increment_a: Succeed(Stopped) (used_gas=113444): [] +===> Test result of M::test_increment_a: Succeed(Stopped) (used_gas=113532): [] // test of M::test_publish /* ======================================= @@ -454,6 +460,12 @@ object "test_A2_M_test_publish" { switch $block case 2 { // label L1 + // goto L2 + /// @src 1:548:575 + $block := 5 + } + case 3 { + // label L0 // $t6 := 100 /// @src 1:571:574 $t6 := 100 @@ -461,8 +473,36 @@ object "test_A2_M_test_publish" { /// @src 1:548:575 $Abort($t6) } - case 3 { - // label L0 + case 4 { + // $t1 := 0x3 + /// @src 1:531:533 + $t1 := 0x3 + // $t0 := Evm::sign($t1) + /// @src 1:526:534 + mstore($locals, A2_Evm_sign($t1)) + // $t2 := borrow_local($t0) + /// @src 1:525:534 + $t2 := $MakePtr(false, $locals) + // $t3 := 22 + /// @src 1:536:538 + $t3 := 22 + // M::publish($t2, $t3) + /// @src 1:517:539 + A2_M_publish($t2, $t3) + // $t4 := 0x3 + /// @src 1:566:568 + $t4 := 0x3 + // $t5 := exists($t4) + /// @src 1:556:562 + $t5 := $AlignedStorageLoad($MakeTypeStorageBase(0, 0x698265eb, $t4)) + // if ($t5) goto L1 else goto L0 + /// @src 1:548:575 + switch $t5 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t7 := 0x3 /// @src 1:609:611 $t7 := 0x3 @@ -487,41 +527,19 @@ object "test_A2_M_test_publish" { // $t12 := ==($t10, $t11) /// @src 1:615:617 $t12 := $Eq($t10, $t11) - // if ($t12) goto L2 else goto L3 + // if ($t12) goto L4 else goto L3 /// @src 1:584:626 switch $t12 - case 0 { $block := 5 } + case 0 { $block := 7 } default { $block := 6 } } - case 4 { - // $t1 := 0x3 - /// @src 1:531:533 - $t1 := 0x3 - // $t0 := Evm::sign($t1) - /// @src 1:526:534 - mstore($locals, A2_Evm_sign($t1)) - // $t2 := borrow_local($t0) - /// @src 1:525:534 - $t2 := $MakePtr(false, $locals) - // $t3 := 22 - /// @src 1:536:538 - $t3 := 22 - // M::publish($t2, $t3) - /// @src 1:517:539 - A2_M_publish($t2, $t3) - // $t4 := 0x3 - /// @src 1:566:568 - $t4 := 0x3 - // $t5 := exists($t4) - /// @src 1:556:562 - $t5 := $AlignedStorageLoad($MakeTypeStorageBase(0, 0x698265eb, $t4)) - // if ($t5) goto L0 else goto L1 - /// @src 1:548:575 - switch $t5 - case 0 { $block := 2 } - default { $block := 3 } + case 6 { + // label L4 + // goto L5 + /// @src 1:584:626 + $block := 8 } - case 5 { + case 7 { // label L3 // $t13 := 101 /// @src 1:622:625 @@ -530,8 +548,8 @@ object "test_A2_M_test_publish" { /// @src 1:584:626 $Abort($t13) } - case 6 { - // label L2 + case 8 { + // label L5 // $t14 := 0x3 /// @src 1:660:662 $t14 := 0x3 @@ -556,14 +574,20 @@ object "test_A2_M_test_publish" { // $t19 := ==($t17, $t18) /// @src 1:666:668 $t19 := $Eq($t17, $t18) - // if ($t19) goto L4 else goto L5 + // if ($t19) goto L7 else goto L6 /// @src 1:635:677 switch $t19 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + /// @src 1:635:677 + $block := 11 + } + case 10 { + // label L6 // $t20 := 102 /// @src 1:673:676 $t20 := 102 @@ -571,8 +595,8 @@ object "test_A2_M_test_publish" { /// @src 1:635:677 $Abort($t20) } - case 8 { - // label L4 + case 11 { + // label L8 // $t21 := 0x3 /// @src 1:711:713 $t21 := 0x3 @@ -602,14 +626,20 @@ object "test_A2_M_test_publish" { // $t27 := ==($t25, $t26) /// @src 1:719:721 $t27 := $Eq($t25, $t26) - // if ($t27) goto L6 else goto L7 + // if ($t27) goto L10 else goto L9 /// @src 1:686:730 switch $t27 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + /// @src 1:686:730 + $block := 14 + } + case 13 { + // label L9 // $t28 := 103 /// @src 1:726:729 $t28 := 103 @@ -617,8 +647,8 @@ object "test_A2_M_test_publish" { /// @src 1:686:730 $Abort($t28) } - case 10 { - // label L6 + case 14 { + // label L11 // return () /// @src 1:730:731 $Free($locals, 32) @@ -890,7 +920,7 @@ object "test_A2_M_test_publish" { } } } -===> Test result of M::test_publish: Succeed(Stopped) (used_gas=114429): [] +===> Test result of M::test_publish: Succeed(Stopped) (used_gas=115318): [] // test of M::test_publish_t /* ======================================= @@ -914,6 +944,12 @@ object "test_A2_M_test_publish_t" { switch $block case 2 { // label L1 + // goto L2 + /// @src 1:1584:1611 + $block := 5 + } + case 3 { + // label L0 // $t6 := 100 /// @src 1:1607:1610 $t6 := 100 @@ -921,8 +957,36 @@ object "test_A2_M_test_publish_t" { /// @src 1:1584:1611 $Abort($t6) } - case 3 { - // label L0 + case 4 { + // $t1 := 0x3 + /// @src 1:1566:1568 + $t1 := 0x3 + // $t0 := Evm::sign($t1) + /// @src 1:1561:1569 + mstore($locals, A2_Evm_sign($t1)) + // $t2 := borrow_local($t0) + /// @src 1:1560:1569 + $t2 := $MakePtr(false, $locals) + // $t3 := 22 + /// @src 1:1571:1573 + $t3 := 22 + // M::publish_t($t2, $t3) + /// @src 1:1550:1574 + A2_M_publish_t($t2, $t3) + // $t4 := 0x3 + /// @src 1:1602:1604 + $t4 := 0x3 + // $t5 := exists($t4) + /// @src 1:1592:1598 + $t5 := $AlignedStorageLoad($MakeTypeStorageBase(0, 0x3948ca0a, $t4)) + // if ($t5) goto L1 else goto L0 + /// @src 1:1584:1611 + switch $t5 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t7 := 0x3 /// @src 1:1646:1648 $t7 := 0x3 @@ -952,41 +1016,19 @@ object "test_A2_M_test_publish_t" { // $t13 := ==($t11, $t12) /// @src 1:1654:1656 $t13 := $Eq($t11, $t12) - // if ($t13) goto L2 else goto L3 + // if ($t13) goto L4 else goto L3 /// @src 1:1621:1665 switch $t13 - case 0 { $block := 5 } + case 0 { $block := 7 } default { $block := 6 } } - case 4 { - // $t1 := 0x3 - /// @src 1:1566:1568 - $t1 := 0x3 - // $t0 := Evm::sign($t1) - /// @src 1:1561:1569 - mstore($locals, A2_Evm_sign($t1)) - // $t2 := borrow_local($t0) - /// @src 1:1560:1569 - $t2 := $MakePtr(false, $locals) - // $t3 := 22 - /// @src 1:1571:1573 - $t3 := 22 - // M::publish_t($t2, $t3) - /// @src 1:1550:1574 - A2_M_publish_t($t2, $t3) - // $t4 := 0x3 - /// @src 1:1602:1604 - $t4 := 0x3 - // $t5 := exists($t4) - /// @src 1:1592:1598 - $t5 := $AlignedStorageLoad($MakeTypeStorageBase(0, 0x3948ca0a, $t4)) - // if ($t5) goto L0 else goto L1 - /// @src 1:1584:1611 - switch $t5 - case 0 { $block := 2 } - default { $block := 3 } + case 6 { + // label L4 + // goto L5 + /// @src 1:1621:1665 + $block := 8 } - case 5 { + case 7 { // label L3 // $t14 := 101 /// @src 1:1661:1664 @@ -995,8 +1037,8 @@ object "test_A2_M_test_publish_t" { /// @src 1:1621:1665 $Abort($t14) } - case 6 { - // label L2 + case 8 { + // label L5 // $t15 := 0x3 /// @src 1:1700:1702 $t15 := 0x3 @@ -1026,14 +1068,20 @@ object "test_A2_M_test_publish_t" { // $t21 := ==($t19, $t20) /// @src 1:1708:1710 $t21 := $Eq($t19, $t20) - // if ($t21) goto L4 else goto L5 + // if ($t21) goto L7 else goto L6 /// @src 1:1675:1719 switch $t21 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + /// @src 1:1675:1719 + $block := 11 + } + case 10 { + // label L6 // $t22 := 102 /// @src 1:1715:1718 $t22 := 102 @@ -1041,8 +1089,8 @@ object "test_A2_M_test_publish_t" { /// @src 1:1675:1719 $Abort($t22) } - case 8 { - // label L4 + case 11 { + // label L8 // $t23 := 0x3 /// @src 1:1754:1756 $t23 := 0x3 @@ -1077,14 +1125,20 @@ object "test_A2_M_test_publish_t" { // $t30 := ==($t28, $t29) /// @src 1:1764:1766 $t30 := $Eq($t28, $t29) - // if ($t30) goto L6 else goto L7 + // if ($t30) goto L10 else goto L9 /// @src 1:1729:1775 switch $t30 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + /// @src 1:1729:1775 + $block := 14 + } + case 13 { + // label L9 // $t31 := 103 /// @src 1:1771:1774 $t31 := 103 @@ -1092,8 +1146,8 @@ object "test_A2_M_test_publish_t" { /// @src 1:1729:1775 $Abort($t31) } - case 10 { - // label L6 + case 14 { + // label L11 // return () /// @src 1:1775:1776 $Free($locals, 32) @@ -1378,7 +1432,7 @@ object "test_A2_M_test_publish_t" { } } } -===> Test result of M::test_publish_t: Succeed(Stopped) (used_gas=138059): [] +===> Test result of M::test_publish_t: Succeed(Stopped) (used_gas=138948): [] // test of M::test_unpublish /* ======================================= @@ -1395,112 +1449,130 @@ object "test_A2_M_test_unpublish" { A2_M_test_unpublish() return (0, 0) function A2_M_test_unpublish() { - let a, b, x, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20, $t21 + let b, x, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20 let $locals := $Malloc(32) let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t15 := 101 - /// @src 1:970:973 - $t15 := 101 - // abort($t15) + // goto L2 /// @src 1:953:974 - $Abort($t15) + $block := 5 } case 3 { // label L0 - // $t16 := 16 - /// @src 1:996:998 - $t16 := 16 - // $t17 := ==($t10, $t16) - /// @src 1:993:995 - $t17 := $Eq($t10, $t16) - // if ($t17) goto L2 else goto L3 - /// @src 1:983:1004 - switch $t17 - case 0 { $block := 5 } - default { $block := 6 } + // $t14 := 101 + /// @src 1:970:973 + $t14 := 101 + // abort($t14) + /// @src 1:953:974 + $Abort($t14) } case 4 { - // $t4 := 0x3 + // $t3 := 0x3 /// @src 1:890:892 - $t4 := 0x3 - // $t0 := Evm::sign($t4) + $t3 := 0x3 + // $t0 := Evm::sign($t3) /// @src 1:885:893 - mstore($locals, A2_Evm_sign($t4)) - // $t5 := borrow_local($t0) + mstore($locals, A2_Evm_sign($t3)) + // $t4 := borrow_local($t0) /// @src 1:884:893 - $t5 := $MakePtr(false, $locals) - // $t6 := 33 + $t4 := $MakePtr(false, $locals) + // $t5 := 33 /// @src 1:895:897 - $t6 := 33 - // M::publish($t5, $t6) + $t5 := 33 + // M::publish($t4, $t5) /// @src 1:876:898 - A2_M_publish($t5, $t6) - // $t7 := 0x3 + A2_M_publish($t4, $t5) + // $t6 := 0x3 /// @src 1:941:943 - $t7 := 0x3 - // $t8 := M::unpublish($t7) + $t6 := 0x3 + // $t7 := M::unpublish($t6) /// @src 1:931:944 - $t8 := A2_M_unpublish($t7) - // ($t9, $t10, $t11) := unpack M::S($t8) + $t7 := A2_M_unpublish($t6) + // ($t8, $t9, $t10) := unpack M::S($t7) /// @src 1:911:928 - $t9 := $MemoryLoadU64(add($t8, 32)) - $t10 := $MemoryLoadU8(add($t8, 40)) - $t11 := $MemoryLoadU256(add($t8, 0)) - $Free($t8, 41) - // $t12 := unpack M::S2($t11) + $t8 := $MemoryLoadU64(add($t7, 32)) + $t9 := $MemoryLoadU8(add($t7, 40)) + $t10 := $MemoryLoadU256(add($t7, 0)) + $Free($t7, 41) + // $t11 := unpack M::S2($t10) /// @src 1:922:927 - $t12 := $MemoryLoadU128(add($t11, 0)) - $Free($t11, 16) - // $t13 := 33 + $t11 := $MemoryLoadU128(add($t10, 0)) + $Free($t10, 16) + // $t12 := 33 /// @src 1:966:968 - $t13 := 33 - // $t14 := ==($t9, $t13) + $t12 := 33 + // $t13 := ==($t8, $t12) /// @src 1:963:965 - $t14 := $Eq($t9, $t13) - // if ($t14) goto L0 else goto L1 + $t13 := $Eq($t8, $t12) + // if ($t13) goto L1 else goto L0 /// @src 1:953:974 - switch $t14 - case 0 { $block := 2 } - default { $block := 3 } + switch $t13 + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t15 := 16 + /// @src 1:996:998 + $t15 := 16 + // $t16 := ==($t9, $t15) + /// @src 1:993:995 + $t16 := $Eq($t9, $t15) + // if ($t16) goto L4 else goto L3 + /// @src 1:983:1004 + switch $t16 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + /// @src 1:983:1004 + $block := 8 + } + case 7 { // label L3 - // $t18 := 102 + // $t17 := 102 /// @src 1:1000:1003 - $t18 := 102 - // abort($t18) + $t17 := 102 + // abort($t17) /// @src 1:983:1004 - $Abort($t18) + $Abort($t17) } - case 6 { - // label L2 - // $t19 := 66 + case 8 { + // label L5 + // $t18 := 66 /// @src 1:1026:1028 - $t19 := 66 - // $t20 := ==($t12, $t19) + $t18 := 66 + // $t19 := ==($t11, $t18) /// @src 1:1023:1025 - $t20 := $Eq($t12, $t19) - // if ($t20) goto L4 else goto L5 + $t19 := $Eq($t11, $t18) + // if ($t19) goto L7 else goto L6 /// @src 1:1013:1034 - switch $t20 - case 0 { $block := 7 } - default { $block := 8 } + switch $t19 + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 - // $t21 := 103 + case 9 { + // label L7 + // goto L8 + /// @src 1:1013:1034 + $block := 11 + } + case 10 { + // label L6 + // $t20 := 103 /// @src 1:1030:1033 - $t21 := 103 - // abort($t21) + $t20 := 103 + // abort($t20) /// @src 1:1013:1034 - $Abort($t21) + $Abort($t20) } - case 8 { - // label L4 + case 11 { + // label L8 // return () /// @src 1:1034:1035 $Free($locals, 32) @@ -1763,4 +1835,4 @@ object "test_A2_M_test_unpublish" { } } } -===> Test result of M::test_unpublish: Succeed(Stopped) (used_gas=90786): [] +===> Test result of M::test_unpublish: Succeed(Stopped) (used_gas=91212): [] diff --git a/language/evm/move-to-yul/tests/Structs.exp b/language/evm/move-to-yul/tests/Structs.exp index bd7953a5ec..f30ce71b26 100644 --- a/language/evm/move-to-yul/tests/Structs.exp +++ b/language/evm/move-to-yul/tests/Structs.exp @@ -47,29 +47,29 @@ object "test_A2_M_test_drop" { A2_M_test_drop() return (0, 0) function A2_M_test_drop() { - let _s3, $t1, $t2, $t3, $t4 - // $t1 := 33 - $t1 := 33 - // $t2 := false - $t2 := false - // $t3 := M::pack_S($t1, $t2) - $t3 := A2_M_pack_S($t1, $t2) - // $t4 := pack M::S3($t3) + let $t0, $t1, $t2, $t3 + // $t0 := 33 + $t0 := 33 + // $t1 := false + $t1 := false + // $t2 := M::pack_S($t0, $t1) + $t2 := A2_M_pack_S($t0, $t1) + // $t3 := pack M::S3($t2) { let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t3) - $t4 := $mem + $MemoryStoreU256(add($mem, 0), $t2) + $t3 := $mem } - // destroy($t4) + // destroy($t3) { - let $field_ptr_1770153451 := $LoadU256(add($t4, 0)) + let $field_ptr_1770153451 := $LoadU256(add($t3, 0)) { let $field_ptr_1602512591 := $LoadU256(add($field_ptr_1770153451, 0)) $Free($field_ptr_1602512591, 16) } $Free($field_ptr_1770153451, 41) } - $Free($t4, 32) + $Free($t3, 32) // return () } @@ -238,20 +238,16 @@ object "test_A2_M_test_equality" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t13 := 101 $t13 := 101 // abort($t13) $Abort($t13) } - case 3 { - // label L0 - // $t14 := !=($t5, $t11) - $t14 := $LogicalNot($Eq_$A2_M_S$($t5, $t11)) - // if ($t14) goto L2 else goto L3 - switch $t14 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t3 := 23 $t3 := 23 @@ -273,36 +269,55 @@ object "test_A2_M_test_equality" { $t11 := A2_M_pack_S($t9, $t10) // $t12 := ==($t5, $t8) $t12 := $Eq_$A2_M_S$($t5, $t8) - // if ($t12) goto L0 else goto L1 + // if ($t12) goto L1 else goto L0 switch $t12 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t14 := !=($t5, $t11) + $t14 := $LogicalNot($Eq_$A2_M_S$($t5, $t11)) + // if ($t14) goto L4 else goto L3 + switch $t14 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t15 := 102 $t15 := 102 // abort($t15) $Abort($t15) } - case 6 { - // label L2 + case 8 { + // label L5 // $t16 := !=($t8, $t11) $t16 := $LogicalNot($Eq_$A2_M_S$($t8, $t11)) - // if ($t16) goto L4 else goto L5 + // if ($t16) goto L7 else goto L6 switch $t16 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t17 := 103 $t17 := 103 // abort($t17) $Abort($t17) } - case 8 { - // label L4 + case 11 { + // label L8 // return () leave } @@ -406,7 +421,7 @@ object "test_A2_M_test_equality" { } } } -===> Test result of M::test_equality: Succeed(Stopped) (used_gas=1606): [] +===> Test result of M::test_equality: Succeed(Stopped) (used_gas=2137): [] // test of M::test_pack_S /* ======================================= @@ -426,28 +441,16 @@ object "test_A2_M_test_pack_S" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t8 := 100 $t8 := 100 // abort($t8) $Abort($t8) } - case 3 { - // label L0 - // $t9 := borrow_local($t0) - $t9 := $MakePtr(false, s) - // $t10 := borrow_field.b($t9) - $t10 := $IndexPtr($t9, 40) - // $t11 := read_ref($t10) - $t11 := $LoadU8($t10) - // $t12 := true - $t12 := true - // $t13 := ==($t11, $t12) - $t13 := $Eq($t11, $t12) - // if ($t13) goto L2 else goto L3 - switch $t13 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t1 := 42 $t1 := 42 @@ -465,20 +468,42 @@ object "test_A2_M_test_pack_S" { $t6 := 42 // $t7 := ==($t5, $t6) $t7 := $Eq($t5, $t6) - // if ($t7) goto L0 else goto L1 + // if ($t7) goto L1 else goto L0 switch $t7 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t9 := borrow_local($t0) + $t9 := $MakePtr(false, s) + // $t10 := borrow_field.b($t9) + $t10 := $IndexPtr($t9, 40) + // $t11 := read_ref($t10) + $t11 := $LoadU8($t10) + // $t12 := true + $t12 := true + // $t13 := ==($t11, $t12) + $t13 := $Eq($t11, $t12) + // if ($t13) goto L4 else goto L3 + switch $t13 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t14 := 101 $t14 := 101 // abort($t14) $Abort($t14) } - case 6 { - // label L2 + case 8 { + // label L5 // $t15 := borrow_local($t0) $t15 := $MakePtr(false, s) // $t16 := borrow_field.c($t15) @@ -493,20 +518,25 @@ object "test_A2_M_test_pack_S" { $t19 := 42 // $t20 := ==($t18, $t19) $t20 := $Eq($t18, $t19) - // if ($t20) goto L4 else goto L5 + // if ($t20) goto L7 else goto L6 switch $t20 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t21 := 102 $t21 := 102 // abort($t21) $Abort($t21) } - case 8 { - // label L4 + case 11 { + // label L8 // return () leave } @@ -713,7 +743,7 @@ object "test_A2_M_test_pack_S" { } } } -===> Test result of M::test_pack_S: Succeed(Stopped) (used_gas=1244): [] +===> Test result of M::test_pack_S: Succeed(Stopped) (used_gas=1775): [] // test of M::test_pack_S2 /* ======================================= @@ -733,16 +763,16 @@ object "test_A2_M_test_pack_S2" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t7 := 100 $t7 := 100 // abort($t7) $Abort($t7) } - case 3 { - // label L0 - // return () - leave - } case 4 { // $t1 := 42 $t1 := 42 @@ -758,10 +788,15 @@ object "test_A2_M_test_pack_S2" { $t5 := 42 // $t6 := ==($t4, $t5) $t6 := $Eq($t4, $t5) - // if ($t6) goto L0 else goto L1 + // if ($t6) goto L1 else goto L0 switch $t6 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // return () + leave } } } @@ -880,7 +915,7 @@ object "test_A2_M_test_pack_S2" { } } } -===> Test result of M::test_pack_S2: Succeed(Stopped) (used_gas=382): [] +===> Test result of M::test_pack_S2: Succeed(Stopped) (used_gas=471): [] // test of M::test_pack_S2_fail /* ======================================= @@ -900,16 +935,16 @@ object "test_A2_M_test_pack_S2_fail" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t7 := 100 $t7 := 100 // abort($t7) $Abort($t7) } - case 3 { - // label L0 - // return () - leave - } case 4 { // $t1 := 42 $t1 := 42 @@ -925,10 +960,15 @@ object "test_A2_M_test_pack_S2_fail" { $t5 := 41 // $t6 := ==($t4, $t5) $t6 := $Eq($t4, $t5) - // if ($t6) goto L0 else goto L1 + // if ($t6) goto L1 else goto L0 switch $t6 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // return () + leave } } } @@ -1047,7 +1087,7 @@ object "test_A2_M_test_pack_S2_fail" { } } } -===> Test result of M::test_pack_S2_fail: Revert(Reverted) (used_gas=369): [0, 0, 0, 0, 0, 0, 0, 100] +===> Test result of M::test_pack_S2_fail: Revert(Reverted) (used_gas=396): [0, 0, 0, 0, 0, 0, 0, 100] // test of M::test_read_S /* ======================================= @@ -1067,16 +1107,16 @@ object "test_A2_M_test_read_S" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t7 := 100 $t7 := 100 // abort($t7) $Abort($t7) } - case 3 { - // label L0 - // return () - leave - } case 4 { // $t1 := 42 $t1 := 42 @@ -1092,10 +1132,15 @@ object "test_A2_M_test_read_S" { $t5 := 84 // $t6 := ==($t4, $t5) $t6 := $Eq($t4, $t5) - // if ($t6) goto L0 else goto L1 + // if ($t6) goto L1 else goto L0 switch $t6 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // return () + leave } } } @@ -1314,7 +1359,7 @@ object "test_A2_M_test_read_S" { } } } -===> Test result of M::test_read_S: Succeed(Stopped) (used_gas=836): [] +===> Test result of M::test_read_S: Succeed(Stopped) (used_gas=925): [] // test of M::test_read_and_write_S /* ======================================= @@ -1334,13 +1379,36 @@ object "test_A2_M_test_read_and_write_S" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t6 := 100 $t6 := 100 // abort($t6) $Abort($t6) } - case 3 { - // label L0 + case 4 { + // $t0 := M::read_and_write_S() + s := A2_M_read_and_write_S() + // $t1 := borrow_local($t0) + $t1 := $MakePtr(false, s) + // $t2 := borrow_field.a($t1) + $t2 := $IndexPtr($t1, 32) + // $t3 := read_ref($t2) + $t3 := $LoadU64($t2) + // $t4 := 2 + $t4 := 2 + // $t5 := ==($t3, $t4) + $t5 := $Eq($t3, $t4) + // if ($t5) goto L1 else goto L0 + switch $t5 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t7 := borrow_local($t0) $t7 := $MakePtr(false, s) // $t8 := borrow_field.c($t7) @@ -1355,38 +1423,25 @@ object "test_A2_M_test_read_and_write_S" { $t11 := 2 // $t12 := ==($t10, $t11) $t12 := $Eq($t10, $t11) - // if ($t12) goto L2 else goto L3 + // if ($t12) goto L4 else goto L3 switch $t12 - case 0 { $block := 5 } + case 0 { $block := 7 } default { $block := 6 } } - case 4 { - // $t0 := M::read_and_write_S() - s := A2_M_read_and_write_S() - // $t1 := borrow_local($t0) - $t1 := $MakePtr(false, s) - // $t2 := borrow_field.a($t1) - $t2 := $IndexPtr($t1, 32) - // $t3 := read_ref($t2) - $t3 := $LoadU64($t2) - // $t4 := 2 - $t4 := 2 - // $t5 := ==($t3, $t4) - $t5 := $Eq($t3, $t4) - // if ($t5) goto L0 else goto L1 - switch $t5 - case 0 { $block := 2 } - default { $block := 3 } + case 6 { + // label L4 + // goto L5 + $block := 8 } - case 5 { + case 7 { // label L3 // $t13 := 101 $t13 := 101 // abort($t13) $Abort($t13) } - case 6 { - // label L2 + case 8 { + // label L5 // return () leave } @@ -1704,7 +1759,7 @@ object "test_A2_M_test_read_and_write_S" { } } } -===> Test result of M::test_read_and_write_S: Succeed(Stopped) (used_gas=1794): [] +===> Test result of M::test_read_and_write_S: Succeed(Stopped) (used_gas=2055): [] // test of M::test_unpack /* ======================================= @@ -1718,60 +1773,65 @@ object "test_A2_M_test_unpack" { A2_M_test_unpack() return (0, 0) function A2_M_test_unpack() { - let s, s1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10 + let s1, $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t10 := 101 - $t10 := 101 - // abort($t10) - $Abort($t10) + // goto L2 + $block := 5 } case 3 { // label L0 - // return () - leave + // $t9 := 101 + $t9 := 101 + // abort($t9) + $Abort($t9) } case 4 { - // $t2 := 33 - $t2 := 33 - // $t3 := false - $t3 := false - // $t4 := M::pack_S($t2, $t3) - $t4 := A2_M_pack_S($t2, $t3) - // $t1 := M::unpack($t4) - s1 := A2_M_unpack($t4) - // $t5 := borrow_local($t1) - $t5 := $MakePtr(false, s1) - // $t6 := borrow_field.x($t5) - $t6 := $t5 - // $t7 := read_ref($t6) - $t7 := $LoadU128($t6) - // $t8 := 33 - $t8 := 33 - // $t9 := ==($t7, $t8) - $t9 := $Eq($t7, $t8) - // if ($t9) goto L0 else goto L1 - switch $t9 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := 33 + $t1 := 33 + // $t2 := false + $t2 := false + // $t3 := M::pack_S($t1, $t2) + $t3 := A2_M_pack_S($t1, $t2) + // $t0 := M::unpack($t3) + s1 := A2_M_unpack($t3) + // $t4 := borrow_local($t0) + $t4 := $MakePtr(false, s1) + // $t5 := borrow_field.x($t4) + $t5 := $t4 + // $t6 := read_ref($t5) + $t6 := $LoadU128($t5) + // $t7 := 33 + $t7 := 33 + // $t8 := ==($t6, $t7) + $t8 := $Eq($t6, $t7) + // if ($t8) goto L1 else goto L0 + switch $t8 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // return () + leave } } } function A2_M_unpack(s) -> $result { - let _a, _b, c, $t4, $t5, $t6 - // ($t4, $t5, $t6) := unpack M::S($t0) - $t4 := $MemoryLoadU64(add(s, 32)) - $t5 := $MemoryLoadU8(add(s, 40)) - $t6 := $MemoryLoadU256(add(s, 0)) + let c, $t2, $t3, $t4 + // ($t2, $t3, $t4) := unpack M::S($t0) + $t2 := $MemoryLoadU64(add(s, 32)) + $t3 := $MemoryLoadU8(add(s, 40)) + $t4 := $MemoryLoadU256(add(s, 0)) $Free(s, 41) - // destroy($t5) - // destroy($t4) - // return $t6 - $result := $t6 + // destroy($t3) + // destroy($t2) + // return $t4 + $result := $t4 } function A2_M_pack_S(a, b) -> $result { @@ -1934,7 +1994,7 @@ object "test_A2_M_test_unpack" { } } } -===> Test result of M::test_unpack: Succeed(Stopped) (used_gas=502): [] +===> Test result of M::test_unpack: Succeed(Stopped) (used_gas=591): [] // test of M::test_write_S /* ======================================= @@ -1954,32 +2014,16 @@ object "test_A2_M_test_write_S" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t10 := 100 $t10 := 100 // abort($t10) $Abort($t10) } - case 3 { - // label L0 - // $t11 := borrow_local($t0) - $t11 := $MakePtr(false, s) - // $t12 := borrow_field.c($t11) - { - $t12 := $MakePtr($IsStoragePtr($t11), $LoadU256($t11)) - } - // $t13 := borrow_field.x($t12) - $t13 := $t12 - // $t14 := read_ref($t13) - $t14 := $LoadU128($t13) - // $t15 := 43 - $t15 := 43 - // $t16 := ==($t14, $t15) - $t16 := $Eq($t14, $t15) - // if ($t16) goto L2 else goto L3 - switch $t16 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t1 := 42 $t1 := 42 @@ -2003,20 +2047,46 @@ object "test_A2_M_test_write_S" { $t8 := 43 // $t9 := ==($t7, $t8) $t9 := $Eq($t7, $t8) - // if ($t9) goto L0 else goto L1 + // if ($t9) goto L1 else goto L0 switch $t9 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t11 := borrow_local($t0) + $t11 := $MakePtr(false, s) + // $t12 := borrow_field.c($t11) + { + $t12 := $MakePtr($IsStoragePtr($t11), $LoadU256($t11)) + } + // $t13 := borrow_field.x($t12) + $t13 := $t12 + // $t14 := read_ref($t13) + $t14 := $LoadU128($t13) + // $t15 := 43 + $t15 := 43 + // $t16 := ==($t14, $t15) + $t16 := $Eq($t14, $t15) + // if ($t16) goto L4 else goto L3 + switch $t16 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t17 := 101 $t17 := 101 // abort($t17) $Abort($t17) } - case 6 { - // label L2 + case 8 { + // label L5 // return () leave } @@ -2282,4 +2352,4 @@ object "test_A2_M_test_write_S" { } } } -===> Test result of M::test_write_S: Succeed(Stopped) (used_gas=1371): [] +===> Test result of M::test_write_S: Succeed(Stopped) (used_gas=1637): [] diff --git a/language/evm/move-to-yul/tests/Tables.exp b/language/evm/move-to-yul/tests/Tables.exp index 7d631d762a..b2a95d3261 100644 --- a/language/evm/move-to-yul/tests/Tables.exp +++ b/language/evm/move-to-yul/tests/Tables.exp @@ -54,13 +54,38 @@ object "test_A2_Tables_test_borrow_fail" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t12 := 100 $t12 := 100 // abort($t12) $Abort($t12) } - case 3 { - // label L0 + case 4 { + // $t6 := Table::empty() + mstore($locals, A2_Table_empty$u64_u128$()) + // $t7 := borrow_local($t6) + $t7 := $MakePtr(false, $locals) + // $t8 := 42 + $t8 := 42 + // $t0 := $t8 + mstore(add($locals, 32), $t8) + // $t9 := borrow_local($t0) + $t9 := $MakePtr(false, add($locals, 56)) + // $t10 := Table::contains($t7, $t9) + $t10 := A2_Table_contains$u64_u128$($t7, $t9) + // $t11 := !($t10) + $t11 := $LogicalNot($t10) + // if ($t11) goto L1 else goto L0 + switch $t11 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t13 := borrow_local($t6) $t13 := $MakePtr(false, $locals) // $t14 := 42 @@ -107,39 +132,9 @@ object "test_A2_Tables_test_borrow_fail" { $Free($locals, 128) leave } - case 4 { - // $t6 := Table::empty() - mstore($locals, A2_Table_empty$u64_u128$()) - // $t7 := borrow_local($t6) - $t7 := $MakePtr(false, $locals) - // $t8 := 42 - $t8 := 42 - // $t0 := $t8 - mstore(add($locals, 32), $t8) - // $t9 := borrow_local($t0) - $t9 := $MakePtr(false, add($locals, 56)) - // $t10 := Table::contains($t7, $t9) - $t10 := A2_Table_contains$u64_u128$($t7, $t9) - // $t11 := !($t10) - $t11 := $LogicalNot($t10) - // if ($t11) goto L0 else goto L1 - switch $t11 - case 0 { $block := 2 } - default { $block := 3 } - } } } - function A2_Table_contains$u64_u128$(table_ref, key_ref) -> res { - let key := $LoadU64(key_ref) - let table_handle := $LoadU256(table_ref) - let storage_key := $StorageKey(table_handle, key) - let word := sload(storage_key) - res := $LogicalNot(iszero(word)) - } - function A2_Table_empty$u64_u128$() -> table { - table := $NewTableHandle() - } function A2_Evm_sign(addr) -> signer { signer := addr } @@ -153,6 +148,16 @@ object "test_A2_Tables_test_borrow_fail" { } value_ref := $MakePtr(true, value_offs) } + function A2_Table_contains$u64_u128$(table_ref, key_ref) -> res { + let key := $LoadU64(key_ref) + let table_handle := $LoadU256(table_ref) + let storage_key := $StorageKey(table_handle, key) + let word := sload(storage_key) + res := $LogicalNot(iszero(word)) + } + function A2_Table_empty$u64_u128$() -> table { + table := $NewTableHandle() + } function $Abort(code) { mstore(0, code) revert(24, 8) // TODO: store code as a string? @@ -337,7 +342,7 @@ object "test_A2_Tables_test_borrow_fail" { } } } -===> Test result of Tables::test_borrow_fail: Revert(Reverted) (used_gas=25325): [255, 255, 255, 255, 255, 255, 255, 255] +===> Test result of Tables::test_borrow_fail: Revert(Reverted) (used_gas=25408): [255, 255, 255, 255, 255, 255, 255, 255] // test of Tables::test_insert_fail /* ======================================= @@ -358,13 +363,38 @@ object "test_A2_Tables_test_insert_fail" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t15 := 100 $t15 := 100 // abort($t15) $Abort($t15) } - case 3 { - // label L0 + case 4 { + // $t9 := Table::empty() + mstore($locals, A2_Table_empty$u64_u128$()) + // $t10 := borrow_local($t9) + $t10 := $MakePtr(false, $locals) + // $t11 := 42 + $t11 := 42 + // $t0 := $t11 + mstore(add($locals, 32), $t11) + // $t12 := borrow_local($t0) + $t12 := $MakePtr(false, add($locals, 56)) + // $t13 := Table::contains($t10, $t12) + $t13 := A2_Table_contains$u64_u128$($t10, $t12) + // $t14 := !($t13) + $t14 := $LogicalNot($t13) + // if ($t14) goto L1 else goto L0 + switch $t14 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t16 := borrow_local($t9) $t16 := $MakePtr(false, $locals) // $t17 := 42 @@ -387,40 +417,25 @@ object "test_A2_Tables_test_insert_fail" { $t22 := $MakePtr(false, add($locals, 120)) // $t23 := Table::contains($t20, $t22) $t23 := A2_Table_contains$u64_u128$($t20, $t22) - // if ($t23) goto L2 else goto L3 + // if ($t23) goto L4 else goto L3 switch $t23 - case 0 { $block := 5 } + case 0 { $block := 7 } default { $block := 6 } } - case 4 { - // $t9 := Table::empty() - mstore($locals, A2_Table_empty$u64_u128$()) - // $t10 := borrow_local($t9) - $t10 := $MakePtr(false, $locals) - // $t11 := 42 - $t11 := 42 - // $t0 := $t11 - mstore(add($locals, 32), $t11) - // $t12 := borrow_local($t0) - $t12 := $MakePtr(false, add($locals, 56)) - // $t13 := Table::contains($t10, $t12) - $t13 := A2_Table_contains$u64_u128$($t10, $t12) - // $t14 := !($t13) - $t14 := $LogicalNot($t13) - // if ($t14) goto L0 else goto L1 - switch $t14 - case 0 { $block := 2 } - default { $block := 3 } + case 6 { + // label L4 + // goto L5 + $block := 8 } - case 5 { + case 7 { // label L3 // $t24 := 101 $t24 := 101 // abort($t24) $Abort($t24) } - case 6 { - // label L2 + case 8 { + // label L5 // $t25 := borrow_local($t9) $t25 := $MakePtr(false, $locals) // $t26 := 42 @@ -670,7 +685,7 @@ object "test_A2_Tables_test_insert_fail" { } } } -===> Test result of Tables::test_insert_fail: Revert(Reverted) (used_gas=90854): [255, 255, 255, 255, 255, 255, 255, 255] +===> Test result of Tables::test_insert_fail: Revert(Reverted) (used_gas=91120): [255, 255, 255, 255, 255, 255, 255, 255] // test of Tables::test_primitive /* ======================================= @@ -684,374 +699,429 @@ object "test_A2_Tables_test_primitive" { A2_Tables_test_primitive() return (0, 0) function A2_Tables_test_primitive() { - let tmp_$1, tmp_$3, tmp_$5, tmp_$7, tmp_$9, tmp_$11, tmp_$12, tmp_$14, tmp_$17, tmp_$19, tmp_$22, tmp_$24, tmp_$26, tmp_$28, t_ref, v, v_28, $t35, $t36, $t37, $t38, $t39, $t40, $t41, $t42, $t43, $t44, $t45, $t46, $t47, $t48, $t49, $t50, $t51, $t52, $t53, $t54, $t55, $t56, $t57, $t58, $t59, $t60, $t61, $t62, $t63, $t64, $t65, $t66, $t67, $t68, $t69, $t70, $t71, $t72, $t73, $t74, $t75, $t76, $t77, $t78, $t79, $t80, $t81, $t82, $t83, $t84, $t85, $t86, $t87, $t88, $t89, $t90, $t91, $t92, $t93, $t94, $t95, $t96, $t97, $t98, $t99, $t100, $t101, $t102, $t103, $t104, $t105, $t106, $t107, $t108, $t109, $t110, $t111, $t112, $t113, $t114, $t115, $t116, $t117, $t118, $t119, $t120, $t121, $t122, $t123, $t124, $t125, $t126, $t127, $t128, $t129, $t130, $t131 + let tmp_$1, tmp_$3, tmp_$5, tmp_$7, tmp_$9, tmp_$11, tmp_$12, tmp_$14, tmp_$17, tmp_$19, tmp_$22, tmp_$24, tmp_$26, tmp_$28, t_ref, $t33, $t34, $t35, $t36, $t37, $t38, $t39, $t40, $t41, $t42, $t43, $t44, $t45, $t46, $t47, $t48, $t49, $t50, $t51, $t52, $t53, $t54, $t55, $t56, $t57, $t58, $t59, $t60, $t61, $t62, $t63, $t64, $t65, $t66, $t67, $t68, $t69, $t70, $t71, $t72, $t73, $t74, $t75, $t76, $t77, $t78, $t79, $t80, $t81, $t82, $t83, $t84, $t85, $t86, $t87, $t88, $t89, $t90, $t91, $t92, $t93, $t94, $t95, $t96, $t97, $t98, $t99, $t100, $t101, $t102, $t103, $t104, $t105, $t106, $t107, $t108, $t109, $t110, $t111, $t112, $t113, $t114, $t115, $t116, $t117, $t118, $t119, $t120, $t121, $t122, $t123, $t124, $t125, $t126, $t127, $t128, $t129 let $locals := $Malloc(576) let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t40 := 100 - $t40 := 100 - // abort($t40) - $Abort($t40) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t41 := borrow_local($t31) - $t41 := $MakePtr(false, $locals) - // $t42 := 42 - $t42 := 42 - // $t21 := $t42 - mstore(add($locals, 64), $t42) - // $t43 := borrow_local($t21) - $t43 := $MakePtr(false, add($locals, 88)) - // $t44 := 1012 - $t44 := 1012 - // Table::insert($t41, $t43, $t44) - A2_Table_insert$u64_u128$($t41, $t43, $t44) - // $t45 := borrow_local($t31) - $t45 := $MakePtr(false, $locals) - // $t46 := 42 - $t46 := 42 - // $t25 := $t46 - mstore(add($locals, 96), $t46) - // $t47 := borrow_local($t25) - $t47 := $MakePtr(false, add($locals, 120)) - // $t48 := Table::contains($t45, $t47) - $t48 := A2_Table_contains$u64_u128$($t45, $t47) - // if ($t48) goto L2 else goto L3 - switch $t48 - case 0 { $block := 5 } - default { $block := 6 } + // $t38 := 100 + $t38 := 100 + // abort($t38) + $Abort($t38) } case 4 { // $t31 := Table::empty() mstore($locals, A2_Table_empty$u64_u128$()) - // $t35 := borrow_local($t31) - $t35 := $MakePtr(false, $locals) - // $t36 := 42 - $t36 := 42 - // $t0 := $t36 - mstore(add($locals, 32), $t36) - // $t37 := borrow_local($t0) - $t37 := $MakePtr(false, add($locals, 56)) - // $t38 := Table::contains($t35, $t37) - $t38 := A2_Table_contains$u64_u128$($t35, $t37) - // $t39 := !($t38) - $t39 := $LogicalNot($t38) - // if ($t39) goto L0 else goto L1 - switch $t39 - case 0 { $block := 2 } - default { $block := 3 } + // $t33 := borrow_local($t31) + $t33 := $MakePtr(false, $locals) + // $t34 := 42 + $t34 := 42 + // $t0 := $t34 + mstore(add($locals, 32), $t34) + // $t35 := borrow_local($t0) + $t35 := $MakePtr(false, add($locals, 56)) + // $t36 := Table::contains($t33, $t35) + $t36 := A2_Table_contains$u64_u128$($t33, $t35) + // $t37 := !($t36) + $t37 := $LogicalNot($t36) + // if ($t37) goto L1 else goto L0 + switch $t37 + case 0 { $block := 3 } + default { $block := 2 } } case 5 { - // label L3 - // $t49 := 101 - $t49 := 101 - // abort($t49) - $Abort($t49) - } - case 6 { // label L2 - // $t50 := borrow_local($t31) - $t50 := $MakePtr(false, $locals) - // $t51 := 0 - $t51 := 0 - // $t27 := $t51 - mstore(add($locals, 128), $t51) - // $t52 := borrow_local($t27) - $t52 := $MakePtr(false, add($locals, 152)) - // $t53 := Table::contains($t50, $t52) - $t53 := A2_Table_contains$u64_u128$($t50, $t52) - // $t54 := !($t53) - $t54 := $LogicalNot($t53) - // if ($t54) goto L4 else goto L5 - switch $t54 + // $t39 := borrow_local($t31) + $t39 := $MakePtr(false, $locals) + // $t40 := 42 + $t40 := 42 + // $t21 := $t40 + mstore(add($locals, 64), $t40) + // $t41 := borrow_local($t21) + $t41 := $MakePtr(false, add($locals, 88)) + // $t42 := 1012 + $t42 := 1012 + // Table::insert($t39, $t41, $t42) + A2_Table_insert$u64_u128$($t39, $t41, $t42) + // $t43 := borrow_local($t31) + $t43 := $MakePtr(false, $locals) + // $t44 := 42 + $t44 := 42 + // $t25 := $t44 + mstore(add($locals, 96), $t44) + // $t45 := borrow_local($t25) + $t45 := $MakePtr(false, add($locals, 120)) + // $t46 := Table::contains($t43, $t45) + $t46 := A2_Table_contains$u64_u128$($t43, $t45) + // if ($t46) goto L4 else goto L3 + switch $t46 case 0 { $block := 7 } - default { $block := 8 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 } case 7 { - // label L5 - // $t55 := 102 - $t55 := 102 - // abort($t55) - $Abort($t55) + // label L3 + // $t47 := 101 + $t47 := 101 + // abort($t47) + $Abort($t47) } case 8 { - // label L4 - // $t56 := borrow_local($t31) - $t56 := $MakePtr(false, $locals) - // $t57 := 42 - $t57 := 42 - // $t29 := $t57 - mstore(add($locals, 160), $t57) - // $t58 := borrow_local($t29) - $t58 := $MakePtr(false, add($locals, 184)) - // $t59 := Table::borrow($t56, $t58) - $t59 := A2_Table_borrow$u64_u128$($t56, $t58) - // $t60 := read_ref($t59) - $t60 := $LoadU128($t59) - // $t61 := 1012 - $t61 := 1012 - // $t62 := ==($t60, $t61) - $t62 := $Eq($t60, $t61) - // if ($t62) goto L6 else goto L7 - switch $t62 - case 0 { $block := 9 } - default { $block := 10 } + // label L5 + // $t48 := borrow_local($t31) + $t48 := $MakePtr(false, $locals) + // $t49 := 0 + $t49 := 0 + // $t27 := $t49 + mstore(add($locals, 128), $t49) + // $t50 := borrow_local($t27) + $t50 := $MakePtr(false, add($locals, 152)) + // $t51 := Table::contains($t48, $t50) + $t51 := A2_Table_contains$u64_u128$($t48, $t50) + // $t52 := !($t51) + $t52 := $LogicalNot($t51) + // if ($t52) goto L7 else goto L6 + switch $t52 + case 0 { $block := 10 } + default { $block := 9 } } case 9 { // label L7 - // $t63 := 103 - $t63 := 103 - // abort($t63) - $Abort($t63) + // goto L8 + $block := 11 } case 10 { // label L6 - // $t64 := borrow_local($t31) - $t64 := $MakePtr(false, $locals) - // $t65 := 43 - $t65 := 43 - // $t2 := $t65 - mstore(add($locals, 192), $t65) - // $t66 := borrow_local($t2) - $t66 := $MakePtr(false, add($locals, 216)) - // $t67 := 1013 - $t67 := 1013 - // Table::insert($t64, $t66, $t67) - A2_Table_insert$u64_u128$($t64, $t66, $t67) - // $t68 := borrow_local($t31) - $t68 := $MakePtr(false, $locals) - // $t69 := 42 - $t69 := 42 - // $t4 := $t69 - mstore(add($locals, 224), $t69) - // $t70 := borrow_local($t4) - $t70 := $MakePtr(false, add($locals, 248)) - // $t71 := Table::contains($t68, $t70) - $t71 := A2_Table_contains$u64_u128$($t68, $t70) - // if ($t71) goto L8 else goto L9 - switch $t71 - case 0 { $block := 11 } - default { $block := 12 } + // $t53 := 102 + $t53 := 102 + // abort($t53) + $Abort($t53) } case 11 { - // label L9 - // $t72 := 104 - $t72 := 104 - // abort($t72) - $Abort($t72) - } - case 12 { // label L8 - // $t73 := borrow_local($t31) - $t73 := $MakePtr(false, $locals) - // $t74 := 0 - $t74 := 0 - // $t6 := $t74 - mstore(add($locals, 256), $t74) - // $t75 := borrow_local($t6) - $t75 := $MakePtr(false, add($locals, 280)) - // $t76 := Table::contains($t73, $t75) - $t76 := A2_Table_contains$u64_u128$($t73, $t75) - // $t77 := !($t76) - $t77 := $LogicalNot($t76) - // if ($t77) goto L10 else goto L11 - switch $t77 + // $t54 := borrow_local($t31) + $t54 := $MakePtr(false, $locals) + // $t55 := 42 + $t55 := 42 + // $t29 := $t55 + mstore(add($locals, 160), $t55) + // $t56 := borrow_local($t29) + $t56 := $MakePtr(false, add($locals, 184)) + // $t57 := Table::borrow($t54, $t56) + $t57 := A2_Table_borrow$u64_u128$($t54, $t56) + // $t58 := read_ref($t57) + $t58 := $LoadU128($t57) + // $t59 := 1012 + $t59 := 1012 + // $t60 := ==($t58, $t59) + $t60 := $Eq($t58, $t59) + // if ($t60) goto L10 else goto L9 + switch $t60 case 0 { $block := 13 } - default { $block := 14 } + default { $block := 12 } + } + case 12 { + // label L10 + // goto L11 + $block := 14 } case 13 { - // label L11 - // $t78 := 105 - $t78 := 105 - // abort($t78) - $Abort($t78) + // label L9 + // $t61 := 103 + $t61 := 103 + // abort($t61) + $Abort($t61) } case 14 { - // label L10 - // $t79 := borrow_local($t31) - $t79 := $MakePtr(false, $locals) - // $t80 := 43 - $t80 := 43 - // $t8 := $t80 - mstore(add($locals, 288), $t80) - // $t81 := borrow_local($t8) - $t81 := $MakePtr(false, add($locals, 312)) - // $t82 := Table::contains($t79, $t81) - $t82 := A2_Table_contains$u64_u128$($t79, $t81) - // if ($t82) goto L12 else goto L13 - switch $t82 - case 0 { $block := 15 } - default { $block := 16 } + // label L11 + // $t62 := borrow_local($t31) + $t62 := $MakePtr(false, $locals) + // $t63 := 43 + $t63 := 43 + // $t2 := $t63 + mstore(add($locals, 192), $t63) + // $t64 := borrow_local($t2) + $t64 := $MakePtr(false, add($locals, 216)) + // $t65 := 1013 + $t65 := 1013 + // Table::insert($t62, $t64, $t65) + A2_Table_insert$u64_u128$($t62, $t64, $t65) + // $t66 := borrow_local($t31) + $t66 := $MakePtr(false, $locals) + // $t67 := 42 + $t67 := 42 + // $t4 := $t67 + mstore(add($locals, 224), $t67) + // $t68 := borrow_local($t4) + $t68 := $MakePtr(false, add($locals, 248)) + // $t69 := Table::contains($t66, $t68) + $t69 := A2_Table_contains$u64_u128$($t66, $t68) + // if ($t69) goto L13 else goto L12 + switch $t69 + case 0 { $block := 16 } + default { $block := 15 } } case 15 { // label L13 - // $t83 := 106 - $t83 := 106 - // abort($t83) - $Abort($t83) + // goto L14 + $block := 17 } case 16 { // label L12 - // $t84 := borrow_local($t31) - $t84 := $MakePtr(false, $locals) - // $t85 := 43 - $t85 := 43 - // $t10 := $t85 - mstore(add($locals, 320), $t85) - // $t86 := borrow_local($t10) - $t86 := $MakePtr(false, add($locals, 344)) - // $t87 := Table::borrow($t84, $t86) - $t87 := A2_Table_borrow$u64_u128$($t84, $t86) - // $t88 := read_ref($t87) - $t88 := $LoadU128($t87) - // $t89 := 1013 - $t89 := 1013 - // $t90 := ==($t88, $t89) - $t90 := $Eq($t88, $t89) - // if ($t90) goto L14 else goto L15 - switch $t90 - case 0 { $block := 17 } - default { $block := 18 } + // $t70 := 104 + $t70 := 104 + // abort($t70) + $Abort($t70) } case 17 { - // label L15 - // $t91 := 107 - $t91 := 107 - // abort($t91) - $Abort($t91) - } - case 18 { // label L14 - // $t92 := borrow_local($t31) - $t92 := $MakePtr(false, $locals) - // $t93 := 42 - $t93 := 42 - // $t13 := $t93 - mstore(add($locals, 352), $t93) - // $t94 := borrow_local($t13) - $t94 := $MakePtr(false, add($locals, 376)) - // $t95 := Table::remove($t92, $t94) - $t95 := A2_Table_remove$u64_u128$($t92, $t94) - // $t96 := 1012 - $t96 := 1012 - // $t97 := ==($t95, $t96) - $t97 := $Eq($t95, $t96) - // if ($t97) goto L16 else goto L17 - switch $t97 + // $t71 := borrow_local($t31) + $t71 := $MakePtr(false, $locals) + // $t72 := 0 + $t72 := 0 + // $t6 := $t72 + mstore(add($locals, 256), $t72) + // $t73 := borrow_local($t6) + $t73 := $MakePtr(false, add($locals, 280)) + // $t74 := Table::contains($t71, $t73) + $t74 := A2_Table_contains$u64_u128$($t71, $t73) + // $t75 := !($t74) + $t75 := $LogicalNot($t74) + // if ($t75) goto L16 else goto L15 + switch $t75 case 0 { $block := 19 } - default { $block := 20 } + default { $block := 18 } + } + case 18 { + // label L16 + // goto L17 + $block := 20 } case 19 { - // label L17 - // $t98 := 108 - $t98 := 108 - // abort($t98) - $Abort($t98) + // label L15 + // $t76 := 105 + $t76 := 105 + // abort($t76) + $Abort($t76) } case 20 { - // label L16 - // $t99 := 0x42 - $t99 := 0x42 - // $t15 := Evm::sign($t99) - mstore(add($locals, 384), A2_Evm_sign($t99)) - // $t100 := borrow_local($t15) - $t100 := $MakePtr(false, add($locals, 384)) - // $t101 := move($t31) - $t101 := mload($locals) - // $t102 := pack Tables::S($t101) + // label L17 + // $t77 := borrow_local($t31) + $t77 := $MakePtr(false, $locals) + // $t78 := 43 + $t78 := 43 + // $t8 := $t78 + mstore(add($locals, 288), $t78) + // $t79 := borrow_local($t8) + $t79 := $MakePtr(false, add($locals, 312)) + // $t80 := Table::contains($t77, $t79) + $t80 := A2_Table_contains$u64_u128$($t77, $t79) + // if ($t80) goto L19 else goto L18 + switch $t80 + case 0 { $block := 22 } + default { $block := 21 } + } + case 21 { + // label L19 + // goto L20 + $block := 23 + } + case 22 { + // label L18 + // $t81 := 106 + $t81 := 106 + // abort($t81) + $Abort($t81) + } + case 23 { + // label L20 + // $t82 := borrow_local($t31) + $t82 := $MakePtr(false, $locals) + // $t83 := 43 + $t83 := 43 + // $t10 := $t83 + mstore(add($locals, 320), $t83) + // $t84 := borrow_local($t10) + $t84 := $MakePtr(false, add($locals, 344)) + // $t85 := Table::borrow($t82, $t84) + $t85 := A2_Table_borrow$u64_u128$($t82, $t84) + // $t86 := read_ref($t85) + $t86 := $LoadU128($t85) + // $t87 := 1013 + $t87 := 1013 + // $t88 := ==($t86, $t87) + $t88 := $Eq($t86, $t87) + // if ($t88) goto L22 else goto L21 + switch $t88 + case 0 { $block := 25 } + default { $block := 24 } + } + case 24 { + // label L22 + // goto L23 + $block := 26 + } + case 25 { + // label L21 + // $t89 := 107 + $t89 := 107 + // abort($t89) + $Abort($t89) + } + case 26 { + // label L23 + // $t90 := borrow_local($t31) + $t90 := $MakePtr(false, $locals) + // $t91 := 42 + $t91 := 42 + // $t13 := $t91 + mstore(add($locals, 352), $t91) + // $t92 := borrow_local($t13) + $t92 := $MakePtr(false, add($locals, 376)) + // $t93 := Table::remove($t90, $t92) + $t93 := A2_Table_remove$u64_u128$($t90, $t92) + // $t94 := 1012 + $t94 := 1012 + // $t95 := ==($t93, $t94) + $t95 := $Eq($t93, $t94) + // if ($t95) goto L25 else goto L24 + switch $t95 + case 0 { $block := 28 } + default { $block := 27 } + } + case 27 { + // label L25 + // goto L26 + $block := 29 + } + case 28 { + // label L24 + // $t96 := 108 + $t96 := 108 + // abort($t96) + $Abort($t96) + } + case 29 { + // label L26 + // $t97 := 0x42 + $t97 := 0x42 + // $t15 := Evm::sign($t97) + mstore(add($locals, 384), A2_Evm_sign($t97)) + // $t98 := borrow_local($t15) + $t98 := $MakePtr(false, add($locals, 384)) + // $t99 := move($t31) + $t99 := mload($locals) + // $t100 := pack Tables::S($t99) { let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t101) - $t102 := $mem + $MemoryStoreU256(add($mem, 0), $t99) + $t100 := $mem } - // move_to>($t102, $t100) + // move_to>($t100, $t98) { - let $base_offset := $MakeTypeStorageBase(0, 0x8a475b1c, $LoadU256($t100)) + let $base_offset := $MakeTypeStorageBase(0, 0x8a475b1c, $LoadU256($t98)) if $AlignedStorageLoad($base_offset) { $AbortBuiltin() } $AlignedStorageStore($base_offset, true) { let $dst := add($base_offset, 32) - let $src := $t102 + let $src := $t100 $AlignedStorageStore(add($dst, 0), mload(add($src, 0))) $Free($src, 32) } } - // $t103 := 0x42 - $t103 := 0x42 - // $t104 := borrow_global>($t103) + // $t101 := 0x42 + $t101 := 0x42 + // $t102 := borrow_global>($t101) { - let $base_offset := $MakeTypeStorageBase(0, 0x8a475b1c, $t103) + let $base_offset := $MakeTypeStorageBase(0, 0x8a475b1c, $t101) if iszero($AlignedStorageLoad($base_offset)) { $AbortBuiltin() } - $t104 := $MakePtr(true, add($base_offset, 32)) + $t102 := $MakePtr(true, add($base_offset, 32)) } - // $t105 := borrow_field>.t($t104) - $t105 := $t104 - // $t106 := 42 - $t106 := 42 - // $t16 := $t106 - mstore(add($locals, 416), $t106) - // $t107 := borrow_local($t16) - $t107 := $MakePtr(false, add($locals, 440)) - // $t108 := Table::contains($t105, $t107) - $t108 := A2_Table_contains$u64_u128$($t105, $t107) - // $t109 := !($t108) - $t109 := $LogicalNot($t108) - // if ($t109) goto L18 else goto L19 - switch $t109 - case 0 { $block := 21 } - default { $block := 22 } + // $t103 := borrow_field>.t($t102) + $t103 := $t102 + // $t104 := 42 + $t104 := 42 + // $t16 := $t104 + mstore(add($locals, 416), $t104) + // $t105 := borrow_local($t16) + $t105 := $MakePtr(false, add($locals, 440)) + // $t106 := Table::contains($t103, $t105) + $t106 := A2_Table_contains$u64_u128$($t103, $t105) + // $t107 := !($t106) + $t107 := $LogicalNot($t106) + // if ($t107) goto L28 else goto L27 + switch $t107 + case 0 { $block := 31 } + default { $block := 30 } } - case 21 { - // label L19 - // destroy($t105) - // $t110 := 109 - $t110 := 109 - // abort($t110) - $Abort($t110) + case 30 { + // label L28 + // goto L29 + $block := 32 } - case 22 { - // label L18 - // $t111 := 43 - $t111 := 43 - // $t18 := $t111 - mstore(add($locals, 448), $t111) - // $t112 := borrow_local($t18) - $t112 := $MakePtr(false, add($locals, 472)) - // $t113 := Table::borrow($t105, $t112) - $t113 := A2_Table_borrow$u64_u128$($t105, $t112) - // $t114 := read_ref($t113) - $t114 := $LoadU128($t113) - // $t115 := 1013 - $t115 := 1013 - // $t116 := ==($t114, $t115) - $t116 := $Eq($t114, $t115) - // if ($t116) goto L20 else goto L21 - switch $t116 - case 0 { $block := 23 } - default { $block := 24 } + case 31 { + // label L27 + // destroy($t103) + // $t108 := 109 + $t108 := 109 + // abort($t108) + $Abort($t108) } - case 23 { - // label L21 - // $t117 := 110 - $t117 := 110 - // abort($t117) - $Abort($t117) + case 32 { + // label L29 + // $t109 := 43 + $t109 := 43 + // $t18 := $t109 + mstore(add($locals, 448), $t109) + // $t110 := borrow_local($t18) + $t110 := $MakePtr(false, add($locals, 472)) + // $t111 := Table::borrow($t103, $t110) + $t111 := A2_Table_borrow$u64_u128$($t103, $t110) + // $t112 := read_ref($t111) + $t112 := $LoadU128($t111) + // $t113 := 1013 + $t113 := 1013 + // $t114 := ==($t112, $t113) + $t114 := $Eq($t112, $t113) + // if ($t114) goto L31 else goto L30 + switch $t114 + case 0 { $block := 34 } + default { $block := 33 } } - case 24 { - // label L20 - // $t118 := 0x42 - $t118 := 0x42 - // $t119 := move_from>($t118) + case 33 { + // label L31 + // goto L32 + $block := 35 + } + case 34 { + // label L30 + // $t115 := 110 + $t115 := 110 + // abort($t115) + $Abort($t115) + } + case 35 { + // label L32 + // $t116 := 0x42 + $t116 := 0x42 + // $t117 := move_from>($t116) { - let $base_offset := $MakeTypeStorageBase(0, 0x8a475b1c, $t118) + let $base_offset := $MakeTypeStorageBase(0, 0x8a475b1c, $t116) if iszero($AlignedStorageLoad($base_offset)) { $AbortBuiltin() } @@ -1062,66 +1132,71 @@ object "test_A2_Tables_test_primitive" { $dst := $Malloc(32) mstore(add($dst, 0), $AlignedStorageLoad(add($src, 0))) $AlignedStorageStore(add($src, 0), 0) - $t119 := $dst + $t117 := $dst } } - // $t30 := unpack Tables::S($t119) - mstore(add($locals, 480), $MemoryLoadU256(add($t119, 0))) - $Free($t119, 32) - // $t120 := borrow_local($t30) - $t120 := $MakePtr(false, add($locals, 480)) - // $t121 := 43 - $t121 := 43 - // $t20 := $t121 - mstore(add($locals, 512), $t121) - // $t122 := borrow_local($t20) - $t122 := $MakePtr(false, add($locals, 536)) - // $t123 := Table::borrow($t120, $t122) - $t123 := A2_Table_borrow$u64_u128$($t120, $t122) - // $t124 := read_ref($t123) - $t124 := $LoadU128($t123) - // $t125 := 1013 - $t125 := 1013 - // $t126 := ==($t124, $t125) - $t126 := $Eq($t124, $t125) - // if ($t126) goto L22 else goto L23 - switch $t126 - case 0 { $block := 25 } - default { $block := 26 } + // $t30 := unpack Tables::S($t117) + mstore(add($locals, 480), $MemoryLoadU256(add($t117, 0))) + $Free($t117, 32) + // $t118 := borrow_local($t30) + $t118 := $MakePtr(false, add($locals, 480)) + // $t119 := 43 + $t119 := 43 + // $t20 := $t119 + mstore(add($locals, 512), $t119) + // $t120 := borrow_local($t20) + $t120 := $MakePtr(false, add($locals, 536)) + // $t121 := Table::borrow($t118, $t120) + $t121 := A2_Table_borrow$u64_u128$($t118, $t120) + // $t122 := read_ref($t121) + $t122 := $LoadU128($t121) + // $t123 := 1013 + $t123 := 1013 + // $t124 := ==($t122, $t123) + $t124 := $Eq($t122, $t123) + // if ($t124) goto L34 else goto L33 + switch $t124 + case 0 { $block := 37 } + default { $block := 36 } } - case 25 { - // label L23 - // $t127 := 111 - $t127 := 111 - // abort($t127) - $Abort($t127) + case 36 { + // label L34 + // goto L35 + $block := 38 } - case 26 { - // label L22 - // $t128 := 0x43 - $t128 := 0x43 - // $t23 := Evm::sign($t128) - mstore(add($locals, 544), A2_Evm_sign($t128)) - // $t129 := borrow_local($t23) - $t129 := $MakePtr(false, add($locals, 544)) - // $t130 := move($t30) - $t130 := mload(add($locals, 480)) - // $t131 := pack Tables::S($t130) + case 37 { + // label L33 + // $t125 := 111 + $t125 := 111 + // abort($t125) + $Abort($t125) + } + case 38 { + // label L35 + // $t126 := 0x43 + $t126 := 0x43 + // $t23 := Evm::sign($t126) + mstore(add($locals, 544), A2_Evm_sign($t126)) + // $t127 := borrow_local($t23) + $t127 := $MakePtr(false, add($locals, 544)) + // $t128 := move($t30) + $t128 := mload(add($locals, 480)) + // $t129 := pack Tables::S($t128) { let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t130) - $t131 := $mem + $MemoryStoreU256(add($mem, 0), $t128) + $t129 := $mem } - // move_to>($t131, $t129) + // move_to>($t129, $t127) { - let $base_offset := $MakeTypeStorageBase(0, 0x8a475b1c, $LoadU256($t129)) + let $base_offset := $MakeTypeStorageBase(0, 0x8a475b1c, $LoadU256($t127)) if $AlignedStorageLoad($base_offset) { $AbortBuiltin() } $AlignedStorageStore($base_offset, true) { let $dst := add($base_offset, 32) - let $src := $t131 + let $src := $t129 $AlignedStorageStore(add($dst, 0), mload(add($src, 0))) $Free($src, 32) } @@ -1376,7 +1451,7 @@ object "test_A2_Tables_test_primitive" { } } } -===> Test result of Tables::test_primitive: Succeed(Stopped) (used_gas=190947): [] +===> Test result of Tables::test_primitive: Succeed(Stopped) (used_gas=196448): [] // test of Tables::test_remove_fail /* ======================================= @@ -1390,44 +1465,74 @@ object "test_A2_Tables_test_remove_fail" { A2_Tables_test_remove_fail() return (0, 0) function A2_Tables_test_remove_fail() { - let tmp_$1, value, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16 + let tmp_$1, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15 let $locals := $Malloc(96) let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t12 := 101 - $t12 := 101 - // abort($t12) - $Abort($t12) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t13 := 0x42 - $t13 := 0x42 - // $t2 := Evm::sign($t13) - mstore(add($locals, 64), A2_Evm_sign($t13)) - // $t14 := borrow_local($t2) - $t14 := $MakePtr(false, add($locals, 64)) - // $t15 := move($t3) - $t15 := mload($locals) - // $t16 := pack Tables::S($t15) + // $t11 := 101 + $t11 := 101 + // abort($t11) + $Abort($t11) + } + case 4 { + // $t3 := Table::empty() + mstore($locals, A2_Table_empty$u64_A2_Tables_Balance$()) + // $t4 := borrow_local($t3) + $t4 := $MakePtr(false, $locals) + // $t5 := 42 + $t5 := 42 + // $t0 := $t5 + mstore(add($locals, 32), $t5) + // $t6 := borrow_local($t0) + $t6 := $MakePtr(false, add($locals, 56)) + // $t7 := Table::remove($t4, $t6) + $t7 := A2_Table_remove$u64_A2_Tables_Balance$($t4, $t6) + // $t8 := unpack Tables::Balance($t7) + $t8 := $MemoryLoadU256(add($t7, 0)) + $Free($t7, 32) + // $t9 := U256::zero() + $t9 := A2_U256_zero() + // $t10 := ==($t8, $t9) + $t10 := $Eq($t8, $t9) + // if ($t10) goto L1 else goto L0 + switch $t10 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t12 := 0x42 + $t12 := 0x42 + // $t2 := Evm::sign($t12) + mstore(add($locals, 64), A2_Evm_sign($t12)) + // $t13 := borrow_local($t2) + $t13 := $MakePtr(false, add($locals, 64)) + // $t14 := move($t3) + $t14 := mload($locals) + // $t15 := pack Tables::S($t14) { let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t15) - $t16 := $mem + $MemoryStoreU256(add($mem, 0), $t14) + $t15 := $mem } - // move_to>($t16, $t14) + // move_to>($t15, $t13) { - let $base_offset := $MakeTypeStorageBase(0, 0x6f98bffd, $LoadU256($t14)) + let $base_offset := $MakeTypeStorageBase(0, 0x6f98bffd, $LoadU256($t13)) if $AlignedStorageLoad($base_offset) { $AbortBuiltin() } $AlignedStorageStore($base_offset, true) { let $dst := add($base_offset, 32) - let $src := $t16 + let $src := $t15 $AlignedStorageStore(add($dst, 0), mload(add($src, 0))) $Free($src, 32) } @@ -1436,34 +1541,12 @@ object "test_A2_Tables_test_remove_fail" { $Free($locals, 96) leave } - case 4 { - // $t3 := Table::empty() - mstore($locals, A2_Table_empty$u64_A2_Tables_Balance$()) - // $t5 := borrow_local($t3) - $t5 := $MakePtr(false, $locals) - // $t6 := 42 - $t6 := 42 - // $t0 := $t6 - mstore(add($locals, 32), $t6) - // $t7 := borrow_local($t0) - $t7 := $MakePtr(false, add($locals, 56)) - // $t8 := Table::remove($t5, $t7) - $t8 := A2_Table_remove$u64_A2_Tables_Balance$($t5, $t7) - // $t9 := unpack Tables::Balance($t8) - $t9 := $MemoryLoadU256(add($t8, 0)) - $Free($t8, 32) - // $t10 := U256::zero() - $t10 := A2_U256_zero() - // $t11 := ==($t9, $t10) - $t11 := $Eq($t9, $t10) - // if ($t11) goto L0 else goto L1 - switch $t11 - case 0 { $block := 2 } - default { $block := 3 } - } } } + function A2_Evm_sign(addr) -> signer { + signer := addr + } function A2_U256_zero() -> $result { let $t0 // $t0 := 0 @@ -1489,9 +1572,6 @@ object "test_A2_Tables_test_remove_fail" { function A2_Table_empty$u64_A2_Tables_Balance$() -> table { table := $NewTableHandle() } - function A2_Evm_sign(addr) -> signer { - signer := addr - } function $Abort(code) { mstore(0, code) revert(24, 8) // TODO: store code as a string? @@ -1637,7 +1717,7 @@ object "test_A2_Tables_test_remove_fail" { } } } -===> Test result of Tables::test_remove_fail: Revert(Reverted) (used_gas=24809): [255, 255, 255, 255, 255, 255, 255, 255] +===> Test result of Tables::test_remove_fail: Revert(Reverted) (used_gas=24811): [255, 255, 255, 255, 255, 255, 255, 255] // test of Tables::test_struct /* ======================================= @@ -1651,311 +1731,346 @@ object "test_A2_Tables_test_struct" { A2_Tables_test_struct() return (0, 0) function A2_Tables_test_struct() { - let tmp_$2, tmp_$3, tmp_$4, tmp_$6, tmp_$7, tmp_$8, tmp_$10, tmp_$11, tmp_$13, tmp_$14, tmp_$15, tmp_$17, tmp_$19, tmp_$20, tmp_$21, tmp_$23, tmp_$25, tmp_$28, entry_mut_ref, global_t, val_1, val_2, value, $t35, $t36, $t37, $t38, $t39, $t40, $t41, $t42, $t43, $t44, $t45, $t46, $t47, $t48, $t49, $t50, $t51, $t52, $t53, $t54, $t55, $t56, $t57, $t58, $t59, $t60, $t61, $t62, $t63, $t64, $t65, $t66, $t67, $t68, $t69, $t70, $t71, $t72, $t73, $t74, $t75, $t76, $t77, $t78, $t79, $t80, $t81, $t82, $t83, $t84, $t85, $t86, $t87, $t88, $t89, $t90, $t91, $t92, $t93, $t94, $t95, $t96, $t97, $t98, $t99, $t100, $t101, $t102, $t103, $t104, $t105, $t106, $t107, $t108 + let tmp_$2, tmp_$3, tmp_$5, tmp_$6, tmp_$8, tmp_$9, tmp_$11, tmp_$12, tmp_$14, tmp_$16, tmp_$17, tmp_$19, tmp_$21, tmp_$24, entry_mut_ref, global_t, val_1, val_2, $t30, $t31, $t32, $t33, $t34, $t35, $t36, $t37, $t38, $t39, $t40, $t41, $t42, $t43, $t44, $t45, $t46, $t47, $t48, $t49, $t50, $t51, $t52, $t53, $t54, $t55, $t56, $t57, $t58, $t59, $t60, $t61, $t62, $t63, $t64, $t65, $t66, $t67, $t68, $t69, $t70, $t71, $t72, $t73, $t74, $t75, $t76, $t77, $t78, $t79, $t80, $t81, $t82, $t83, $t84, $t85, $t86, $t87, $t88, $t89, $t90, $t91, $t92, $t93, $t94, $t95, $t96, $t97, $t98, $t99, $t100, $t101, $t102, $t103 let $locals := $Malloc(384) let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t45 := 101 - $t45 := 101 - // abort($t45) - $Abort($t45) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t46 := borrow_local($t31) - $t46 := $MakePtr(false, $locals) - // $t47 := 0xab - $t47 := 0xab - // $t24 := $t47 - mstore(add($locals, 96), $t47) - // $t48 := borrow_local($t24) - $t48 := $MakePtr(false, add($locals, 96)) - // $t49 := Table::borrow($t46, $t48) - $t49 := A2_Table_borrow$address_A2_Tables_Balance$($t46, $t48) - // $t50 := borrow_field.value($t49) - $t50 := $t49 - // $t51 := read_ref($t50) - $t51 := $LoadU256($t50) - // $t52 := ==($t51, $t35) - $t52 := $Eq($t51, $t35) - // if ($t52) goto L2 else goto L3 - switch $t52 - case 0 { $block := 5 } - default { $block := 6 } + // $t40 := 101 + $t40 := 101 + // abort($t40) + $Abort($t40) } case 4 { - // $t31 := Table::empty() + // $t27 := Table::empty() mstore($locals, A2_Table_empty$address_A2_Tables_Balance$()) - // $t35 := 3743106036130323098097120681749450326028 - $t35 := 3743106036130323098097120681749450326028 - // $t36 := 15312706511442230855851857334429569515566 - $t36 := 15312706511442230855851857334429569515566 - // $t37 := borrow_local($t31) - $t37 := $MakePtr(false, $locals) - // $t38 := 0xab - $t38 := 0xab - // $t0 := $t38 - mstore(add($locals, 32), $t38) - // $t39 := borrow_local($t0) - $t39 := $MakePtr(false, add($locals, 32)) - // $t40 := pack Tables::Balance($t35) + // $t30 := 3743106036130323098097120681749450326028 + $t30 := 3743106036130323098097120681749450326028 + // $t31 := 15312706511442230855851857334429569515566 + $t31 := 15312706511442230855851857334429569515566 + // $t32 := borrow_local($t27) + $t32 := $MakePtr(false, $locals) + // $t33 := 0xab + $t33 := 0xab + // $t0 := $t33 + mstore(add($locals, 32), $t33) + // $t34 := borrow_local($t0) + $t34 := $MakePtr(false, add($locals, 32)) + // $t35 := pack Tables::Balance($t30) { let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t35) - $t40 := $mem + $MemoryStoreU256(add($mem, 0), $t30) + $t35 := $mem } - // Table::insert($t37, $t39, $t40) - A2_Table_insert$address_A2_Tables_Balance$($t37, $t39, $t40) - // $t41 := borrow_local($t31) + // Table::insert($t32, $t34, $t35) + A2_Table_insert$address_A2_Tables_Balance$($t32, $t34, $t35) + // $t36 := borrow_local($t27) + $t36 := $MakePtr(false, $locals) + // $t37 := 0xab + $t37 := 0xab + // $t18 := $t37 + mstore(add($locals, 64), $t37) + // $t38 := borrow_local($t18) + $t38 := $MakePtr(false, add($locals, 64)) + // $t39 := Table::contains($t36, $t38) + $t39 := A2_Table_contains$address_A2_Tables_Balance$($t36, $t38) + // if ($t39) goto L1 else goto L0 + switch $t39 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t41 := borrow_local($t27) $t41 := $MakePtr(false, $locals) // $t42 := 0xab $t42 := 0xab - // $t22 := $t42 - mstore(add($locals, 64), $t42) - // $t43 := borrow_local($t22) - $t43 := $MakePtr(false, add($locals, 64)) - // $t44 := Table::contains($t41, $t43) - $t44 := A2_Table_contains$address_A2_Tables_Balance$($t41, $t43) - // if ($t44) goto L0 else goto L1 - switch $t44 - case 0 { $block := 2 } - default { $block := 3 } - } - case 5 { - // label L3 - // $t53 := 102 - $t53 := 102 - // abort($t53) - $Abort($t53) + // $t20 := $t42 + mstore(add($locals, 96), $t42) + // $t43 := borrow_local($t20) + $t43 := $MakePtr(false, add($locals, 96)) + // $t44 := Table::borrow($t41, $t43) + $t44 := A2_Table_borrow$address_A2_Tables_Balance$($t41, $t43) + // $t45 := borrow_field.value($t44) + $t45 := $t44 + // $t46 := read_ref($t45) + $t46 := $LoadU256($t45) + // $t47 := ==($t46, $t30) + $t47 := $Eq($t46, $t30) + // if ($t47) goto L4 else goto L3 + switch $t47 + case 0 { $block := 7 } + default { $block := 6 } } case 6 { - // label L2 - // $t54 := 0x42 - $t54 := 0x42 - // $t26 := Evm::sign($t54) - mstore(add($locals, 128), A2_Evm_sign($t54)) - // $t55 := borrow_local($t26) - $t55 := $MakePtr(false, add($locals, 128)) - // $t56 := move($t31) - $t56 := mload($locals) - // $t57 := pack Tables::S($t56) + // label L4 + // goto L5 + $block := 8 + } + case 7 { + // label L3 + // $t48 := 102 + $t48 := 102 + // abort($t48) + $Abort($t48) + } + case 8 { + // label L5 + // $t49 := 0x42 + $t49 := 0x42 + // $t22 := Evm::sign($t49) + mstore(add($locals, 128), A2_Evm_sign($t49)) + // $t50 := borrow_local($t22) + $t50 := $MakePtr(false, add($locals, 128)) + // $t51 := move($t27) + $t51 := mload($locals) + // $t52 := pack Tables::S($t51) { let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t56) - $t57 := $mem + $MemoryStoreU256(add($mem, 0), $t51) + $t52 := $mem } - // move_to>($t57, $t55) + // move_to>($t52, $t50) { - let $base_offset := $MakeTypeStorageBase(0, 0x7dd56ec3, $LoadU256($t55)) + let $base_offset := $MakeTypeStorageBase(0, 0x7dd56ec3, $LoadU256($t50)) if $AlignedStorageLoad($base_offset) { $AbortBuiltin() } $AlignedStorageStore($base_offset, true) { let $dst := add($base_offset, 32) - let $src := $t57 + let $src := $t52 $AlignedStorageStore(add($dst, 0), mload(add($src, 0))) $Free($src, 32) } } - // $t58 := 0x42 - $t58 := 0x42 - // $t59 := borrow_global>($t58) + // $t53 := 0x42 + $t53 := 0x42 + // $t54 := borrow_global>($t53) { - let $base_offset := $MakeTypeStorageBase(0, 0x7dd56ec3, $t58) + let $base_offset := $MakeTypeStorageBase(0, 0x7dd56ec3, $t53) if iszero($AlignedStorageLoad($base_offset)) { $AbortBuiltin() } - $t59 := $MakePtr(true, add($base_offset, 32)) + $t54 := $MakePtr(true, add($base_offset, 32)) } - // $t60 := borrow_field>.t($t59) - $t60 := $t59 - // $t61 := 0xcd - $t61 := 0xcd - // $t27 := $t61 - mstore(add($locals, 160), $t61) - // $t62 := borrow_local($t27) - $t62 := $MakePtr(false, add($locals, 160)) - // $t63 := pack Tables::Balance($t36) + // $t55 := borrow_field>.t($t54) + $t55 := $t54 + // $t56 := 0xcd + $t56 := 0xcd + // $t23 := $t56 + mstore(add($locals, 160), $t56) + // $t57 := borrow_local($t23) + $t57 := $MakePtr(false, add($locals, 160)) + // $t58 := pack Tables::Balance($t31) { let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t36) - $t63 := $mem + $MemoryStoreU256(add($mem, 0), $t31) + $t58 := $mem } - // Table::insert($t60, $t62, $t63) - A2_Table_insert$address_A2_Tables_Balance$($t60, $t62, $t63) - // $t64 := 0xab - $t64 := 0xab - // $t1 := $t64 - mstore(add($locals, 192), $t64) - // $t65 := borrow_local($t1) - $t65 := $MakePtr(false, add($locals, 192)) - // $t66 := freeze_ref($t60) - $t66 := $t60 - // $t67 := Table::borrow($t66, $t65) - $t67 := A2_Table_borrow$address_A2_Tables_Balance$($t66, $t65) - // $t68 := borrow_field.value($t67) - $t68 := $t67 - // $t69 := read_ref($t68) - $t69 := $LoadU256($t68) - // $t70 := ==($t69, $t35) - $t70 := $Eq($t69, $t35) - // if ($t70) goto L4 else goto L5 - switch $t70 - case 0 { $block := 7 } - default { $block := 8 } - } - case 7 { - // label L5 - // destroy($t60) - // $t71 := 103 - $t71 := 103 - // abort($t71) - $Abort($t71) - } - case 8 { - // label L4 - // $t72 := 0xcd - $t72 := 0xcd - // $t5 := $t72 - mstore(add($locals, 224), $t72) - // $t73 := borrow_local($t5) - $t73 := $MakePtr(false, add($locals, 224)) - // $t74 := freeze_ref($t60) - $t74 := $t60 - // $t75 := Table::borrow($t74, $t73) - $t75 := A2_Table_borrow$address_A2_Tables_Balance$($t74, $t73) - // $t76 := borrow_field.value($t75) - $t76 := $t75 - // $t77 := read_ref($t76) - $t77 := $LoadU256($t76) - // $t78 := ==($t77, $t36) - $t78 := $Eq($t77, $t36) - // if ($t78) goto L6 else goto L7 - switch $t78 - case 0 { $block := 9 } - default { $block := 10 } + // Table::insert($t55, $t57, $t58) + A2_Table_insert$address_A2_Tables_Balance$($t55, $t57, $t58) + // $t59 := 0xab + $t59 := 0xab + // $t1 := $t59 + mstore(add($locals, 192), $t59) + // $t60 := borrow_local($t1) + $t60 := $MakePtr(false, add($locals, 192)) + // $t61 := freeze_ref($t55) + $t61 := $t55 + // $t62 := Table::borrow($t61, $t60) + $t62 := A2_Table_borrow$address_A2_Tables_Balance$($t61, $t60) + // $t63 := borrow_field.value($t62) + $t63 := $t62 + // $t64 := read_ref($t63) + $t64 := $LoadU256($t63) + // $t65 := ==($t64, $t30) + $t65 := $Eq($t64, $t30) + // if ($t65) goto L7 else goto L6 + switch $t65 + case 0 { $block := 10 } + default { $block := 9 } } case 9 { // label L7 - // destroy($t60) - // $t79 := 104 - $t79 := 104 - // abort($t79) - $Abort($t79) + // goto L8 + $block := 11 } case 10 { // label L6 - // $t80 := 0xcd - $t80 := 0xcd - // $t9 := $t80 - mstore(add($locals, 256), $t80) - // $t81 := borrow_local($t9) - $t81 := $MakePtr(false, add($locals, 256)) - // $t82 := Table::borrow_mut($t60, $t81) - $t82 := A2_Table_borrow_mut$address_A2_Tables_Balance$($t60, $t81) - // $t83 := borrow_field.value($t82) - $t83 := $t82 - // $t84 := read_ref($t83) - $t84 := $LoadU256($t83) - // $t85 := U256::one() - $t85 := A2_U256_one() - // $t86 := -($t84, $t85) - $t86 := $Sub($t84, $t85) - // $t87 := borrow_field.value($t82) - $t87 := $t82 - // write_ref($t87, $t86) - $StoreU256($t87, $t86) - // $t88 := 0xcd - $t88 := 0xcd - // $t12 := $t88 - mstore(add($locals, 288), $t88) - // $t89 := borrow_local($t12) - $t89 := $MakePtr(false, add($locals, 288)) - // $t90 := freeze_ref($t60) - $t90 := $t60 - // $t91 := Table::borrow($t90, $t89) - $t91 := A2_Table_borrow$address_A2_Tables_Balance$($t90, $t89) - // $t92 := borrow_field.value($t91) - $t92 := $t91 - // $t93 := read_ref($t92) - $t93 := $LoadU256($t92) - // $t94 := 15312706511442230855851857334429569515565 - $t94 := 15312706511442230855851857334429569515565 - // $t95 := ==($t93, $t94) - $t95 := $Eq($t93, $t94) - // if ($t95) goto L8 else goto L9 - switch $t95 - case 0 { $block := 11 } - default { $block := 12 } + // destroy($t55) + // $t66 := 103 + $t66 := 103 + // abort($t66) + $Abort($t66) } case 11 { - // label L9 - // destroy($t60) - // $t96 := 105 - $t96 := 105 - // abort($t96) - $Abort($t96) - } - case 12 { // label L8 - // $t97 := 0xab - $t97 := 0xab - // $t16 := $t97 - mstore(add($locals, 320), $t97) - // $t98 := borrow_local($t16) - $t98 := $MakePtr(false, add($locals, 320)) - // $t99 := Table::remove($t60, $t98) - $t99 := A2_Table_remove$address_A2_Tables_Balance$($t60, $t98) - // $t100 := unpack Tables::Balance($t99) - $t100 := $MemoryLoadU256(add($t99, 0)) - $Free($t99, 32) - // $t101 := ==($t100, $t35) - $t101 := $Eq($t100, $t35) - // if ($t101) goto L10 else goto L11 - switch $t101 + // $t67 := 0xcd + $t67 := 0xcd + // $t4 := $t67 + mstore(add($locals, 224), $t67) + // $t68 := borrow_local($t4) + $t68 := $MakePtr(false, add($locals, 224)) + // $t69 := freeze_ref($t55) + $t69 := $t55 + // $t70 := Table::borrow($t69, $t68) + $t70 := A2_Table_borrow$address_A2_Tables_Balance$($t69, $t68) + // $t71 := borrow_field.value($t70) + $t71 := $t70 + // $t72 := read_ref($t71) + $t72 := $LoadU256($t71) + // $t73 := ==($t72, $t31) + $t73 := $Eq($t72, $t31) + // if ($t73) goto L10 else goto L9 + switch $t73 case 0 { $block := 13 } - default { $block := 14 } + default { $block := 12 } + } + case 12 { + // label L10 + // goto L11 + $block := 14 } case 13 { - // label L11 - // destroy($t60) - // $t102 := 106 - $t102 := 106 - // abort($t102) - $Abort($t102) + // label L9 + // destroy($t55) + // $t74 := 104 + $t74 := 104 + // abort($t74) + $Abort($t74) } case 14 { - // label L10 - // $t103 := 0xab - $t103 := 0xab - // $t18 := $t103 - mstore(add($locals, 352), $t103) - // $t104 := borrow_local($t18) - $t104 := $MakePtr(false, add($locals, 352)) - // $t105 := freeze_ref($t60) - $t105 := $t60 - // $t106 := Table::contains($t105, $t104) - $t106 := A2_Table_contains$address_A2_Tables_Balance$($t105, $t104) - // $t107 := !($t106) - $t107 := $LogicalNot($t106) - // if ($t107) goto L12 else goto L13 - switch $t107 - case 0 { $block := 15 } - default { $block := 16 } + // label L11 + // $t75 := 0xcd + $t75 := 0xcd + // $t7 := $t75 + mstore(add($locals, 256), $t75) + // $t76 := borrow_local($t7) + $t76 := $MakePtr(false, add($locals, 256)) + // $t77 := Table::borrow_mut($t55, $t76) + $t77 := A2_Table_borrow_mut$address_A2_Tables_Balance$($t55, $t76) + // $t78 := borrow_field.value($t77) + $t78 := $t77 + // $t79 := read_ref($t78) + $t79 := $LoadU256($t78) + // $t80 := U256::one() + $t80 := A2_U256_one() + // $t81 := -($t79, $t80) + $t81 := $Sub($t79, $t80) + // $t82 := borrow_field.value($t77) + $t82 := $t77 + // write_ref($t82, $t81) + $StoreU256($t82, $t81) + // $t83 := 0xcd + $t83 := 0xcd + // $t10 := $t83 + mstore(add($locals, 288), $t83) + // $t84 := borrow_local($t10) + $t84 := $MakePtr(false, add($locals, 288)) + // $t85 := freeze_ref($t55) + $t85 := $t55 + // $t86 := Table::borrow($t85, $t84) + $t86 := A2_Table_borrow$address_A2_Tables_Balance$($t85, $t84) + // $t87 := borrow_field.value($t86) + $t87 := $t86 + // $t88 := read_ref($t87) + $t88 := $LoadU256($t87) + // $t89 := 15312706511442230855851857334429569515565 + $t89 := 15312706511442230855851857334429569515565 + // $t90 := ==($t88, $t89) + $t90 := $Eq($t88, $t89) + // if ($t90) goto L13 else goto L12 + switch $t90 + case 0 { $block := 16 } + default { $block := 15 } } case 15 { // label L13 - // $t108 := 107 - $t108 := 107 - // abort($t108) - $Abort($t108) + // goto L14 + $block := 17 } case 16 { // label L12 + // destroy($t55) + // $t91 := 105 + $t91 := 105 + // abort($t91) + $Abort($t91) + } + case 17 { + // label L14 + // $t92 := 0xab + $t92 := 0xab + // $t13 := $t92 + mstore(add($locals, 320), $t92) + // $t93 := borrow_local($t13) + $t93 := $MakePtr(false, add($locals, 320)) + // $t94 := Table::remove($t55, $t93) + $t94 := A2_Table_remove$address_A2_Tables_Balance$($t55, $t93) + // $t95 := unpack Tables::Balance($t94) + $t95 := $MemoryLoadU256(add($t94, 0)) + $Free($t94, 32) + // $t96 := ==($t95, $t30) + $t96 := $Eq($t95, $t30) + // if ($t96) goto L16 else goto L15 + switch $t96 + case 0 { $block := 19 } + default { $block := 18 } + } + case 18 { + // label L16 + // goto L17 + $block := 20 + } + case 19 { + // label L15 + // destroy($t55) + // $t97 := 106 + $t97 := 106 + // abort($t97) + $Abort($t97) + } + case 20 { + // label L17 + // $t98 := 0xab + $t98 := 0xab + // $t15 := $t98 + mstore(add($locals, 352), $t98) + // $t99 := borrow_local($t15) + $t99 := $MakePtr(false, add($locals, 352)) + // $t100 := freeze_ref($t55) + $t100 := $t55 + // $t101 := Table::contains($t100, $t99) + $t101 := A2_Table_contains$address_A2_Tables_Balance$($t100, $t99) + // $t102 := !($t101) + $t102 := $LogicalNot($t101) + // if ($t102) goto L19 else goto L18 + switch $t102 + case 0 { $block := 22 } + default { $block := 21 } + } + case 21 { + // label L19 + // goto L20 + $block := 23 + } + case 22 { + // label L18 + // $t103 := 107 + $t103 := 107 + // abort($t103) + $Abort($t103) + } + case 23 { + // label L20 // return () $Free($locals, 384) leave @@ -2209,7 +2324,7 @@ object "test_A2_Tables_test_struct" { } } } -===> Test result of Tables::test_struct: Succeed(Stopped) (used_gas=151439): [] +===> Test result of Tables::test_struct: Succeed(Stopped) (used_gas=153416): [] // test of Tables::test_table_of_tables /* ======================================= @@ -2223,386 +2338,426 @@ object "test_A2_Tables_test_table_of_tables" { A2_Tables_test_table_of_tables() return (0, 0) function A2_Tables_test_table_of_tables() { - let tmp_$2, tmp_$3, tmp_$6, tmp_$7, tmp_$10, tmp_$11, tmp_$12, tmp_$15, tmp_$16, tmp_$19, tmp_$20, tmp_$24, tmp_$25, tmp_$28, tmp_$29, tmp_$32, tmp_$33, tmp_$34, tmp_$37, tmp_$38, tmp_$41, tmp_$43, val, val_1, val_2, val_3, $t52, $t53, $t54, $t55, $t56, $t57, $t58, $t59, $t60, $t61, $t62, $t63, $t64, $t65, $t66, $t67, $t68, $t69, $t70, $t71, $t72, $t73, $t74, $t75, $t76, $t77, $t78, $t79, $t80, $t81, $t82, $t83, $t84, $t85, $t86, $t87, $t88, $t89, $t90, $t91, $t92, $t93, $t94, $t95, $t96, $t97, $t98, $t99, $t100, $t101, $t102, $t103, $t104, $t105, $t106, $t107, $t108, $t109, $t110, $t111, $t112, $t113, $t114, $t115, $t116, $t117, $t118, $t119, $t120, $t121, $t122, $t123, $t124, $t125, $t126, $t127, $t128, $t129, $t130, $t131, $t132, $t133, $t134, $t135, $t136, $t137, $t138, $t139, $t140, $t141, $t142, $t143, $t144, $t145, $t146, $t147, $t148, $t149, $t150, $t151, $t152 + let tmp_$2, tmp_$3, tmp_$6, tmp_$7, tmp_$10, tmp_$11, tmp_$12, tmp_$15, tmp_$16, tmp_$19, tmp_$20, tmp_$24, tmp_$25, tmp_$28, tmp_$29, tmp_$32, tmp_$33, tmp_$34, tmp_$37, tmp_$38, tmp_$41, tmp_$43, val_1, val_2, val_3, $t51, $t52, $t53, $t54, $t55, $t56, $t57, $t58, $t59, $t60, $t61, $t62, $t63, $t64, $t65, $t66, $t67, $t68, $t69, $t70, $t71, $t72, $t73, $t74, $t75, $t76, $t77, $t78, $t79, $t80, $t81, $t82, $t83, $t84, $t85, $t86, $t87, $t88, $t89, $t90, $t91, $t92, $t93, $t94, $t95, $t96, $t97, $t98, $t99, $t100, $t101, $t102, $t103, $t104, $t105, $t106, $t107, $t108, $t109, $t110, $t111, $t112, $t113, $t114, $t115, $t116, $t117, $t118, $t119, $t120, $t121, $t122, $t123, $t124, $t125, $t126, $t127, $t128, $t129, $t130, $t131, $t132, $t133, $t134, $t135, $t136, $t137, $t138, $t139, $t140, $t141, $t142, $t143, $t144, $t145, $t146, $t147, $t148, $t149, $t150, $t151 let $locals := $Malloc(832) let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t76 := 101 - $t76 := 101 - // abort($t76) - $Abort($t76) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t77 := borrow_local($t45) - $t77 := $MakePtr(false, add($locals, 128)) - // $t78 := 0x34 - $t78 := 0x34 - // $t5 := $t78 - mstore(add($locals, 288), $t78) - // $t79 := borrow_local($t5) - $t79 := $MakePtr(false, add($locals, 288)) - // $t80 := Table::borrow>($t77, $t79) - $t80 := A2_Table_borrow$address_A2_Table_Table$address_A2_U256_U256$$($t77, $t79) - // $t81 := 0xcd - $t81 := 0xcd - // $t4 := $t81 - mstore(add($locals, 320), $t81) - // $t82 := borrow_local($t4) - $t82 := $MakePtr(false, add($locals, 320)) - // $t83 := Table::contains($t80, $t82) - $t83 := A2_Table_contains$address_A2_U256_U256$($t80, $t82) - // if ($t83) goto L2 else goto L3 - switch $t83 - case 0 { $block := 5 } - default { $block := 6 } + // $t75 := 101 + $t75 := 101 + // abort($t75) + $Abort($t75) } case 4 { // $t45 := Table::empty>() mstore(add($locals, 128), A2_Table_empty$address_A2_Table_Table$address_A2_U256_U256$$()) - // $t52 := 3743106036130323098097120681749450326028 - $t52 := 3743106036130323098097120681749450326028 - // $t53 := 15312706511442230855851857334429569515566 - $t53 := 15312706511442230855851857334429569515566 - // $t54 := 26542024619833200150143219379677920493647 - $t54 := 26542024619833200150143219379677920493647 + // $t51 := 3743106036130323098097120681749450326028 + $t51 := 3743106036130323098097120681749450326028 + // $t52 := 15312706511442230855851857334429569515566 + $t52 := 15312706511442230855851857334429569515566 + // $t53 := 26542024619833200150143219379677920493647 + $t53 := 26542024619833200150143219379677920493647 // $t46 := Table::empty() mstore($locals, A2_Table_empty$address_A2_U256_U256$()) - // $t55 := borrow_local($t46) - $t55 := $MakePtr(false, $locals) - // $t56 := 0xab - $t56 := 0xab - // $t0 := $t56 - mstore(add($locals, 32), $t56) - // $t57 := borrow_local($t0) - $t57 := $MakePtr(false, add($locals, 32)) - // Table::insert($t55, $t57, $t52) - A2_Table_insert$address_A2_U256_U256$($t55, $t57, $t52) + // $t54 := borrow_local($t46) + $t54 := $MakePtr(false, $locals) + // $t55 := 0xab + $t55 := 0xab + // $t0 := $t55 + mstore(add($locals, 32), $t55) + // $t56 := borrow_local($t0) + $t56 := $MakePtr(false, add($locals, 32)) + // Table::insert($t54, $t56, $t51) + A2_Table_insert$address_A2_U256_U256$($t54, $t56, $t51) // $t47 := Table::empty() mstore(add($locals, 64), A2_Table_empty$address_A2_U256_U256$()) - // $t58 := borrow_local($t47) - $t58 := $MakePtr(false, add($locals, 64)) - // $t59 := 0xcd - $t59 := 0xcd - // $t22 := $t59 - mstore(add($locals, 96), $t59) - // $t60 := borrow_local($t22) - $t60 := $MakePtr(false, add($locals, 96)) - // Table::insert($t58, $t60, $t53) - A2_Table_insert$address_A2_U256_U256$($t58, $t60, $t53) - // $t61 := borrow_local($t45) - $t61 := $MakePtr(false, add($locals, 128)) - // $t62 := 0x12 - $t62 := 0x12 - // $t40 := $t62 - mstore(add($locals, 160), $t62) - // $t63 := borrow_local($t40) - $t63 := $MakePtr(false, add($locals, 160)) - // $t64 := move($t46) - $t64 := mload($locals) - // Table::insert>($t61, $t63, $t64) - A2_Table_insert$address_A2_Table_Table$address_A2_U256_U256$$($t61, $t63, $t64) - // $t65 := borrow_local($t45) - $t65 := $MakePtr(false, add($locals, 128)) - // $t66 := 0x34 - $t66 := 0x34 - // $t42 := $t66 - mstore(add($locals, 192), $t66) - // $t67 := borrow_local($t42) - $t67 := $MakePtr(false, add($locals, 192)) - // $t68 := move($t47) - $t68 := mload(add($locals, 64)) - // Table::insert>($t65, $t67, $t68) - A2_Table_insert$address_A2_Table_Table$address_A2_U256_U256$$($t65, $t67, $t68) - // $t69 := borrow_local($t45) - $t69 := $MakePtr(false, add($locals, 128)) - // $t70 := 0x12 - $t70 := 0x12 - // $t1 := $t70 - mstore(add($locals, 224), $t70) - // $t71 := borrow_local($t1) - $t71 := $MakePtr(false, add($locals, 224)) - // $t72 := Table::borrow>($t69, $t71) - $t72 := A2_Table_borrow$address_A2_Table_Table$address_A2_U256_U256$$($t69, $t71) - // $t73 := 0xab - $t73 := 0xab - // $t44 := $t73 - mstore(add($locals, 256), $t73) - // $t74 := borrow_local($t44) - $t74 := $MakePtr(false, add($locals, 256)) - // $t75 := Table::contains($t72, $t74) - $t75 := A2_Table_contains$address_A2_U256_U256$($t72, $t74) - // if ($t75) goto L0 else goto L1 - switch $t75 - case 0 { $block := 2 } - default { $block := 3 } + // $t57 := borrow_local($t47) + $t57 := $MakePtr(false, add($locals, 64)) + // $t58 := 0xcd + $t58 := 0xcd + // $t22 := $t58 + mstore(add($locals, 96), $t58) + // $t59 := borrow_local($t22) + $t59 := $MakePtr(false, add($locals, 96)) + // Table::insert($t57, $t59, $t52) + A2_Table_insert$address_A2_U256_U256$($t57, $t59, $t52) + // $t60 := borrow_local($t45) + $t60 := $MakePtr(false, add($locals, 128)) + // $t61 := 0x12 + $t61 := 0x12 + // $t40 := $t61 + mstore(add($locals, 160), $t61) + // $t62 := borrow_local($t40) + $t62 := $MakePtr(false, add($locals, 160)) + // $t63 := move($t46) + $t63 := mload($locals) + // Table::insert>($t60, $t62, $t63) + A2_Table_insert$address_A2_Table_Table$address_A2_U256_U256$$($t60, $t62, $t63) + // $t64 := borrow_local($t45) + $t64 := $MakePtr(false, add($locals, 128)) + // $t65 := 0x34 + $t65 := 0x34 + // $t42 := $t65 + mstore(add($locals, 192), $t65) + // $t66 := borrow_local($t42) + $t66 := $MakePtr(false, add($locals, 192)) + // $t67 := move($t47) + $t67 := mload(add($locals, 64)) + // Table::insert>($t64, $t66, $t67) + A2_Table_insert$address_A2_Table_Table$address_A2_U256_U256$$($t64, $t66, $t67) + // $t68 := borrow_local($t45) + $t68 := $MakePtr(false, add($locals, 128)) + // $t69 := 0x12 + $t69 := 0x12 + // $t1 := $t69 + mstore(add($locals, 224), $t69) + // $t70 := borrow_local($t1) + $t70 := $MakePtr(false, add($locals, 224)) + // $t71 := Table::borrow>($t68, $t70) + $t71 := A2_Table_borrow$address_A2_Table_Table$address_A2_U256_U256$$($t68, $t70) + // $t72 := 0xab + $t72 := 0xab + // $t44 := $t72 + mstore(add($locals, 256), $t72) + // $t73 := borrow_local($t44) + $t73 := $MakePtr(false, add($locals, 256)) + // $t74 := Table::contains($t71, $t73) + $t74 := A2_Table_contains$address_A2_U256_U256$($t71, $t73) + // if ($t74) goto L1 else goto L0 + switch $t74 + case 0 { $block := 3 } + default { $block := 2 } } case 5 { - // label L3 - // $t84 := 102 - $t84 := 102 - // abort($t84) - $Abort($t84) - } - case 6 { // label L2 - // $t85 := borrow_local($t45) - $t85 := $MakePtr(false, add($locals, 128)) - // $t86 := 0x12 - $t86 := 0x12 - // $t9 := $t86 - mstore(add($locals, 352), $t86) - // $t87 := borrow_local($t9) - $t87 := $MakePtr(false, add($locals, 352)) - // $t88 := Table::borrow>($t85, $t87) - $t88 := A2_Table_borrow$address_A2_Table_Table$address_A2_U256_U256$$($t85, $t87) - // $t89 := 0xab - $t89 := 0xab - // $t8 := $t89 - mstore(add($locals, 384), $t89) - // $t90 := borrow_local($t8) - $t90 := $MakePtr(false, add($locals, 384)) - // $t91 := Table::borrow($t88, $t90) - $t91 := A2_Table_borrow$address_A2_U256_U256$($t88, $t90) - // $t92 := read_ref($t91) - $t92 := $LoadU256($t91) - // $t93 := ==($t92, $t52) - $t93 := $Eq($t92, $t52) - // if ($t93) goto L4 else goto L5 - switch $t93 + // $t76 := borrow_local($t45) + $t76 := $MakePtr(false, add($locals, 128)) + // $t77 := 0x34 + $t77 := 0x34 + // $t5 := $t77 + mstore(add($locals, 288), $t77) + // $t78 := borrow_local($t5) + $t78 := $MakePtr(false, add($locals, 288)) + // $t79 := Table::borrow>($t76, $t78) + $t79 := A2_Table_borrow$address_A2_Table_Table$address_A2_U256_U256$$($t76, $t78) + // $t80 := 0xcd + $t80 := 0xcd + // $t4 := $t80 + mstore(add($locals, 320), $t80) + // $t81 := borrow_local($t4) + $t81 := $MakePtr(false, add($locals, 320)) + // $t82 := Table::contains($t79, $t81) + $t82 := A2_Table_contains$address_A2_U256_U256$($t79, $t81) + // if ($t82) goto L4 else goto L3 + switch $t82 case 0 { $block := 7 } - default { $block := 8 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 } case 7 { - // label L5 - // $t94 := 103 - $t94 := 103 - // abort($t94) - $Abort($t94) + // label L3 + // $t83 := 102 + $t83 := 102 + // abort($t83) + $Abort($t83) } case 8 { - // label L4 - // $t95 := borrow_local($t45) - $t95 := $MakePtr(false, add($locals, 128)) - // $t96 := 0x34 - $t96 := 0x34 - // $t14 := $t96 - mstore(add($locals, 416), $t96) - // $t97 := borrow_local($t14) - $t97 := $MakePtr(false, add($locals, 416)) - // $t98 := Table::borrow>($t95, $t97) - $t98 := A2_Table_borrow$address_A2_Table_Table$address_A2_U256_U256$$($t95, $t97) - // $t99 := 0xcd - $t99 := 0xcd - // $t13 := $t99 - mstore(add($locals, 448), $t99) - // $t100 := borrow_local($t13) - $t100 := $MakePtr(false, add($locals, 448)) - // $t101 := Table::borrow($t98, $t100) - $t101 := A2_Table_borrow$address_A2_U256_U256$($t98, $t100) - // $t102 := read_ref($t101) - $t102 := $LoadU256($t101) - // $t103 := ==($t102, $t53) - $t103 := $Eq($t102, $t53) - // if ($t103) goto L6 else goto L7 - switch $t103 - case 0 { $block := 9 } - default { $block := 10 } + // label L5 + // $t84 := borrow_local($t45) + $t84 := $MakePtr(false, add($locals, 128)) + // $t85 := 0x12 + $t85 := 0x12 + // $t9 := $t85 + mstore(add($locals, 352), $t85) + // $t86 := borrow_local($t9) + $t86 := $MakePtr(false, add($locals, 352)) + // $t87 := Table::borrow>($t84, $t86) + $t87 := A2_Table_borrow$address_A2_Table_Table$address_A2_U256_U256$$($t84, $t86) + // $t88 := 0xab + $t88 := 0xab + // $t8 := $t88 + mstore(add($locals, 384), $t88) + // $t89 := borrow_local($t8) + $t89 := $MakePtr(false, add($locals, 384)) + // $t90 := Table::borrow($t87, $t89) + $t90 := A2_Table_borrow$address_A2_U256_U256$($t87, $t89) + // $t91 := read_ref($t90) + $t91 := $LoadU256($t90) + // $t92 := ==($t91, $t51) + $t92 := $Eq($t91, $t51) + // if ($t92) goto L7 else goto L6 + switch $t92 + case 0 { $block := 10 } + default { $block := 9 } } case 9 { // label L7 - // $t104 := 104 - $t104 := 104 - // abort($t104) - $Abort($t104) + // goto L8 + $block := 11 } case 10 { // label L6 - // $t105 := borrow_local($t45) - $t105 := $MakePtr(false, add($locals, 128)) - // $t106 := 0x12 - $t106 := 0x12 - // $t18 := $t106 - mstore(add($locals, 480), $t106) - // $t107 := borrow_local($t18) - $t107 := $MakePtr(false, add($locals, 480)) - // $t108 := Table::borrow_mut>($t105, $t107) - $t108 := A2_Table_borrow_mut$address_A2_Table_Table$address_A2_U256_U256$$($t105, $t107) - // $t109 := 0xef - $t109 := 0xef - // $t17 := $t109 - mstore(add($locals, 512), $t109) - // $t110 := borrow_local($t17) - $t110 := $MakePtr(false, add($locals, 512)) - // Table::insert($t108, $t110, $t54) - A2_Table_insert$address_A2_U256_U256$($t108, $t110, $t54) - // $t111 := borrow_local($t45) - $t111 := $MakePtr(false, add($locals, 128)) - // $t112 := 0x12 - $t112 := 0x12 - // $t23 := $t112 - mstore(add($locals, 544), $t112) - // $t113 := borrow_local($t23) - $t113 := $MakePtr(false, add($locals, 544)) - // $t114 := Table::borrow>($t111, $t113) - $t114 := A2_Table_borrow$address_A2_Table_Table$address_A2_U256_U256$$($t111, $t113) - // $t115 := 0xef - $t115 := 0xef - // $t21 := $t115 - mstore(add($locals, 576), $t115) - // $t116 := borrow_local($t21) - $t116 := $MakePtr(false, add($locals, 576)) - // $t117 := Table::borrow($t114, $t116) - $t117 := A2_Table_borrow$address_A2_U256_U256$($t114, $t116) - // $t118 := read_ref($t117) - $t118 := $LoadU256($t117) - // $t119 := ==($t118, $t54) - $t119 := $Eq($t118, $t54) - // if ($t119) goto L8 else goto L9 - switch $t119 - case 0 { $block := 11 } - default { $block := 12 } + // $t93 := 103 + $t93 := 103 + // abort($t93) + $Abort($t93) } case 11 { - // label L9 - // $t120 := 105 - $t120 := 105 - // abort($t120) - $Abort($t120) - } - case 12 { // label L8 - // $t121 := borrow_local($t45) - $t121 := $MakePtr(false, add($locals, 128)) - // $t122 := 0x12 - $t122 := 0x12 - // $t27 := $t122 - mstore(add($locals, 608), $t122) - // $t123 := borrow_local($t27) - $t123 := $MakePtr(false, add($locals, 608)) - // $t124 := Table::borrow>($t121, $t123) - $t124 := A2_Table_borrow$address_A2_Table_Table$address_A2_U256_U256$$($t121, $t123) - // $t125 := 0xab - $t125 := 0xab - // $t26 := $t125 - mstore(add($locals, 640), $t125) - // $t126 := borrow_local($t26) - $t126 := $MakePtr(false, add($locals, 640)) - // $t127 := Table::borrow($t124, $t126) - $t127 := A2_Table_borrow$address_A2_U256_U256$($t124, $t126) - // $t128 := read_ref($t127) - $t128 := $LoadU256($t127) - // $t129 := ==($t128, $t52) - $t129 := $Eq($t128, $t52) - // if ($t129) goto L10 else goto L11 - switch $t129 + // $t94 := borrow_local($t45) + $t94 := $MakePtr(false, add($locals, 128)) + // $t95 := 0x34 + $t95 := 0x34 + // $t14 := $t95 + mstore(add($locals, 416), $t95) + // $t96 := borrow_local($t14) + $t96 := $MakePtr(false, add($locals, 416)) + // $t97 := Table::borrow>($t94, $t96) + $t97 := A2_Table_borrow$address_A2_Table_Table$address_A2_U256_U256$$($t94, $t96) + // $t98 := 0xcd + $t98 := 0xcd + // $t13 := $t98 + mstore(add($locals, 448), $t98) + // $t99 := borrow_local($t13) + $t99 := $MakePtr(false, add($locals, 448)) + // $t100 := Table::borrow($t97, $t99) + $t100 := A2_Table_borrow$address_A2_U256_U256$($t97, $t99) + // $t101 := read_ref($t100) + $t101 := $LoadU256($t100) + // $t102 := ==($t101, $t52) + $t102 := $Eq($t101, $t52) + // if ($t102) goto L10 else goto L9 + switch $t102 case 0 { $block := 13 } - default { $block := 14 } + default { $block := 12 } + } + case 12 { + // label L10 + // goto L11 + $block := 14 } case 13 { - // label L11 - // $t130 := 106 - $t130 := 106 - // abort($t130) - $Abort($t130) + // label L9 + // $t103 := 104 + $t103 := 104 + // abort($t103) + $Abort($t103) } case 14 { - // label L10 - // $t131 := borrow_local($t45) - $t131 := $MakePtr(false, add($locals, 128)) - // $t132 := 0x34 - $t132 := 0x34 - // $t31 := $t132 - mstore(add($locals, 672), $t132) - // $t133 := borrow_local($t31) - $t133 := $MakePtr(false, add($locals, 672)) - // $t134 := Table::borrow_mut>($t131, $t133) - $t134 := A2_Table_borrow_mut$address_A2_Table_Table$address_A2_U256_U256$$($t131, $t133) - // $t135 := 0xcd - $t135 := 0xcd - // $t30 := $t135 - mstore(add($locals, 704), $t135) - // $t136 := borrow_local($t30) - $t136 := $MakePtr(false, add($locals, 704)) - // $t137 := Table::remove($t134, $t136) - $t137 := A2_Table_remove$address_A2_U256_U256$($t134, $t136) - // $t138 := ==($t137, $t53) - $t138 := $Eq($t137, $t53) - // if ($t138) goto L12 else goto L13 - switch $t138 - case 0 { $block := 15 } - default { $block := 16 } + // label L11 + // $t104 := borrow_local($t45) + $t104 := $MakePtr(false, add($locals, 128)) + // $t105 := 0x12 + $t105 := 0x12 + // $t18 := $t105 + mstore(add($locals, 480), $t105) + // $t106 := borrow_local($t18) + $t106 := $MakePtr(false, add($locals, 480)) + // $t107 := Table::borrow_mut>($t104, $t106) + $t107 := A2_Table_borrow_mut$address_A2_Table_Table$address_A2_U256_U256$$($t104, $t106) + // $t108 := 0xef + $t108 := 0xef + // $t17 := $t108 + mstore(add($locals, 512), $t108) + // $t109 := borrow_local($t17) + $t109 := $MakePtr(false, add($locals, 512)) + // Table::insert($t107, $t109, $t53) + A2_Table_insert$address_A2_U256_U256$($t107, $t109, $t53) + // $t110 := borrow_local($t45) + $t110 := $MakePtr(false, add($locals, 128)) + // $t111 := 0x12 + $t111 := 0x12 + // $t23 := $t111 + mstore(add($locals, 544), $t111) + // $t112 := borrow_local($t23) + $t112 := $MakePtr(false, add($locals, 544)) + // $t113 := Table::borrow>($t110, $t112) + $t113 := A2_Table_borrow$address_A2_Table_Table$address_A2_U256_U256$$($t110, $t112) + // $t114 := 0xef + $t114 := 0xef + // $t21 := $t114 + mstore(add($locals, 576), $t114) + // $t115 := borrow_local($t21) + $t115 := $MakePtr(false, add($locals, 576)) + // $t116 := Table::borrow($t113, $t115) + $t116 := A2_Table_borrow$address_A2_U256_U256$($t113, $t115) + // $t117 := read_ref($t116) + $t117 := $LoadU256($t116) + // $t118 := ==($t117, $t53) + $t118 := $Eq($t117, $t53) + // if ($t118) goto L13 else goto L12 + switch $t118 + case 0 { $block := 16 } + default { $block := 15 } } case 15 { // label L13 - // $t139 := 107 - $t139 := 107 - // abort($t139) - $Abort($t139) + // goto L14 + $block := 17 } case 16 { // label L12 - // $t140 := borrow_local($t45) - $t140 := $MakePtr(false, add($locals, 128)) - // $t141 := 0x34 - $t141 := 0x34 - // $t36 := $t141 - mstore(add($locals, 736), $t141) - // $t142 := borrow_local($t36) - $t142 := $MakePtr(false, add($locals, 736)) - // $t143 := Table::borrow>($t140, $t142) - $t143 := A2_Table_borrow$address_A2_Table_Table$address_A2_U256_U256$$($t140, $t142) - // $t144 := 0xcd - $t144 := 0xcd - // $t35 := $t144 - mstore(add($locals, 768), $t144) - // $t145 := borrow_local($t35) - $t145 := $MakePtr(false, add($locals, 768)) - // $t146 := Table::contains($t143, $t145) - $t146 := A2_Table_contains$address_A2_U256_U256$($t143, $t145) - // $t147 := !($t146) - $t147 := $LogicalNot($t146) - // if ($t147) goto L14 else goto L15 - switch $t147 - case 0 { $block := 17 } - default { $block := 18 } + // $t119 := 105 + $t119 := 105 + // abort($t119) + $Abort($t119) } case 17 { - // label L15 - // $t148 := 108 - $t148 := 108 - // abort($t148) - $Abort($t148) + // label L14 + // $t120 := borrow_local($t45) + $t120 := $MakePtr(false, add($locals, 128)) + // $t121 := 0x12 + $t121 := 0x12 + // $t27 := $t121 + mstore(add($locals, 608), $t121) + // $t122 := borrow_local($t27) + $t122 := $MakePtr(false, add($locals, 608)) + // $t123 := Table::borrow>($t120, $t122) + $t123 := A2_Table_borrow$address_A2_Table_Table$address_A2_U256_U256$$($t120, $t122) + // $t124 := 0xab + $t124 := 0xab + // $t26 := $t124 + mstore(add($locals, 640), $t124) + // $t125 := borrow_local($t26) + $t125 := $MakePtr(false, add($locals, 640)) + // $t126 := Table::borrow($t123, $t125) + $t126 := A2_Table_borrow$address_A2_U256_U256$($t123, $t125) + // $t127 := read_ref($t126) + $t127 := $LoadU256($t126) + // $t128 := ==($t127, $t51) + $t128 := $Eq($t127, $t51) + // if ($t128) goto L16 else goto L15 + switch $t128 + case 0 { $block := 19 } + default { $block := 18 } } case 18 { - // label L14 - // $t149 := 0x42 - $t149 := 0x42 - // $t39 := Evm::sign($t149) - mstore(add($locals, 800), A2_Evm_sign($t149)) - // $t150 := borrow_local($t39) - $t150 := $MakePtr(false, add($locals, 800)) - // $t151 := move($t45) - $t151 := mload(add($locals, 128)) - // $t152 := pack Tables::S>($t151) + // label L16 + // goto L17 + $block := 20 + } + case 19 { + // label L15 + // $t129 := 106 + $t129 := 106 + // abort($t129) + $Abort($t129) + } + case 20 { + // label L17 + // $t130 := borrow_local($t45) + $t130 := $MakePtr(false, add($locals, 128)) + // $t131 := 0x34 + $t131 := 0x34 + // $t31 := $t131 + mstore(add($locals, 672), $t131) + // $t132 := borrow_local($t31) + $t132 := $MakePtr(false, add($locals, 672)) + // $t133 := Table::borrow_mut>($t130, $t132) + $t133 := A2_Table_borrow_mut$address_A2_Table_Table$address_A2_U256_U256$$($t130, $t132) + // $t134 := 0xcd + $t134 := 0xcd + // $t30 := $t134 + mstore(add($locals, 704), $t134) + // $t135 := borrow_local($t30) + $t135 := $MakePtr(false, add($locals, 704)) + // $t136 := Table::remove($t133, $t135) + $t136 := A2_Table_remove$address_A2_U256_U256$($t133, $t135) + // $t137 := ==($t136, $t52) + $t137 := $Eq($t136, $t52) + // if ($t137) goto L19 else goto L18 + switch $t137 + case 0 { $block := 22 } + default { $block := 21 } + } + case 21 { + // label L19 + // goto L20 + $block := 23 + } + case 22 { + // label L18 + // $t138 := 107 + $t138 := 107 + // abort($t138) + $Abort($t138) + } + case 23 { + // label L20 + // $t139 := borrow_local($t45) + $t139 := $MakePtr(false, add($locals, 128)) + // $t140 := 0x34 + $t140 := 0x34 + // $t36 := $t140 + mstore(add($locals, 736), $t140) + // $t141 := borrow_local($t36) + $t141 := $MakePtr(false, add($locals, 736)) + // $t142 := Table::borrow>($t139, $t141) + $t142 := A2_Table_borrow$address_A2_Table_Table$address_A2_U256_U256$$($t139, $t141) + // $t143 := 0xcd + $t143 := 0xcd + // $t35 := $t143 + mstore(add($locals, 768), $t143) + // $t144 := borrow_local($t35) + $t144 := $MakePtr(false, add($locals, 768)) + // $t145 := Table::contains($t142, $t144) + $t145 := A2_Table_contains$address_A2_U256_U256$($t142, $t144) + // $t146 := !($t145) + $t146 := $LogicalNot($t145) + // if ($t146) goto L22 else goto L21 + switch $t146 + case 0 { $block := 25 } + default { $block := 24 } + } + case 24 { + // label L22 + // goto L23 + $block := 26 + } + case 25 { + // label L21 + // $t147 := 108 + $t147 := 108 + // abort($t147) + $Abort($t147) + } + case 26 { + // label L23 + // $t148 := 0x42 + $t148 := 0x42 + // $t39 := Evm::sign($t148) + mstore(add($locals, 800), A2_Evm_sign($t148)) + // $t149 := borrow_local($t39) + $t149 := $MakePtr(false, add($locals, 800)) + // $t150 := move($t45) + $t150 := mload(add($locals, 128)) + // $t151 := pack Tables::S>($t150) { let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t151) - $t152 := $mem + $MemoryStoreU256(add($mem, 0), $t150) + $t151 := $mem } - // move_to>>($t152, $t150) + // move_to>>($t151, $t149) { - let $base_offset := $MakeTypeStorageBase(0, 0xc5110c9a, $LoadU256($t150)) + let $base_offset := $MakeTypeStorageBase(0, 0xc5110c9a, $LoadU256($t149)) if $AlignedStorageLoad($base_offset) { $AbortBuiltin() } $AlignedStorageStore($base_offset, true) { let $dst := add($base_offset, 32) - let $src := $t152 + let $src := $t151 $AlignedStorageStore(add($dst, 0), mload(add($src, 0))) $Free($src, 32) } @@ -2860,7 +3015,7 @@ object "test_A2_Tables_test_table_of_tables" { } } } -===> Test result of Tables::test_table_of_tables: Succeed(Stopped) (used_gas=289488): [] +===> Test result of Tables::test_table_of_tables: Succeed(Stopped) (used_gas=292670): [] // test of Tables::test_u256 /* ======================================= @@ -2881,30 +3036,16 @@ object "test_A2_Tables_test_u256" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t14 := 101 $t14 := 101 // abort($t14) $Abort($t14) } - case 3 { - // label L0 - // $t15 := borrow_local($t3) - $t15 := $MakePtr(false, $locals) - // $t16 := borrow_local($t2) - $t16 := $MakePtr(false, add($locals, 32)) - // $t17 := Table::borrow($t15, $t16) - $t17 := A2_Table_borrow$A2_U256_U256_A2_U256_U256$($t15, $t16) - // $t18 := read_ref($t17) - $t18 := $LoadU256($t17) - // $t19 := 3743106036130323098097120681749450326028 - $t19 := 3743106036130323098097120681749450326028 - // $t20 := ==($t18, $t19) - $t20 := $Eq($t18, $t19) - // if ($t20) goto L2 else goto L3 - switch $t20 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t3 := Table::empty() mstore($locals, A2_Table_empty$A2_U256_U256_A2_U256_U256$()) @@ -2928,20 +3069,44 @@ object "test_A2_Tables_test_u256" { $t12 := $MakePtr(false, add($locals, 32)) // $t13 := Table::contains($t11, $t12) $t13 := A2_Table_contains$A2_U256_U256_A2_U256_U256$($t11, $t12) - // if ($t13) goto L0 else goto L1 + // if ($t13) goto L1 else goto L0 switch $t13 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t15 := borrow_local($t3) + $t15 := $MakePtr(false, $locals) + // $t16 := borrow_local($t2) + $t16 := $MakePtr(false, add($locals, 32)) + // $t17 := Table::borrow($t15, $t16) + $t17 := A2_Table_borrow$A2_U256_U256_A2_U256_U256$($t15, $t16) + // $t18 := read_ref($t17) + $t18 := $LoadU256($t17) + // $t19 := 3743106036130323098097120681749450326028 + $t19 := 3743106036130323098097120681749450326028 + // $t20 := ==($t18, $t19) + $t20 := $Eq($t18, $t19) + // if ($t20) goto L4 else goto L3 + switch $t20 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t21 := 102 $t21 := 102 // abort($t21) $Abort($t21) } - case 6 { - // label L2 + case 8 { + // label L5 // $t22 := borrow_local($t3) $t22 := $MakePtr(false, $locals) // $t23 := borrow_local($t2) @@ -2960,20 +3125,25 @@ object "test_A2_Tables_test_u256" { $t28 := $LoadU256($t27) // $t29 := ==($t28, $t8) $t29 := $Eq($t28, $t8) - // if ($t29) goto L4 else goto L5 + // if ($t29) goto L7 else goto L6 switch $t29 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t30 := 103 $t30 := 103 // abort($t30) $Abort($t30) } - case 8 { - // label L4 + case 11 { + // label L8 // $t31 := 0x42 $t31 := 0x42 // $t0 := Evm::sign($t31) @@ -3228,7 +3398,7 @@ object "test_A2_Tables_test_u256" { } } } -===> Test result of Tables::test_u256: Succeed(Stopped) (used_gas=137324): [] +===> Test result of Tables::test_u256: Succeed(Stopped) (used_gas=137855): [] // test of Tables::test_vector /* ======================================= @@ -3242,373 +3412,423 @@ object "test_A2_Tables_test_vector" { A2_Tables_test_vector() return (0, 0) function A2_Tables_test_vector() { - let tmp_$1, tmp_$4, tmp_$6, tmp_$8, tmp_$10, tmp_$11, tmp_$13, tmp_$15, tmp_$17, tmp_$19, s, v_mut_ref, $t25, $t26, $t27, $t28, $t29, $t30, $t31, $t32, $t33, $t34, $t35, $t36, $t37, $t38, $t39, $t40, $t41, $t42, $t43, $t44, $t45, $t46, $t47, $t48, $t49, $t50, $t51, $t52, $t53, $t54, $t55, $t56, $t57, $t58, $t59, $t60, $t61, $t62, $t63, $t64, $t65, $t66, $t67, $t68, $t69, $t70, $t71, $t72, $t73, $t74, $t75, $t76, $t77, $t78, $t79, $t80, $t81, $t82, $t83, $t84, $t85, $t86, $t87, $t88, $t89, $t90, $t91, $t92, $t93, $t94, $t95, $t96, $t97, $t98, $t99, $t100, $t101, $t102, $t103, $t104, $t105, $t106, $t107, $t108, $t109, $t110, $t111, $t112, $t113, $t114, $t115 + let tmp_$1, tmp_$4, tmp_$6, tmp_$8, tmp_$10, tmp_$11, tmp_$13, tmp_$15, tmp_$17, tmp_$19, s, $t24, $t25, $t26, $t27, $t28, $t29, $t30, $t31, $t32, $t33, $t34, $t35, $t36, $t37, $t38, $t39, $t40, $t41, $t42, $t43, $t44, $t45, $t46, $t47, $t48, $t49, $t50, $t51, $t52, $t53, $t54, $t55, $t56, $t57, $t58, $t59, $t60, $t61, $t62, $t63, $t64, $t65, $t66, $t67, $t68, $t69, $t70, $t71, $t72, $t73, $t74, $t75, $t76, $t77, $t78, $t79, $t80, $t81, $t82, $t83, $t84, $t85, $t86, $t87, $t88, $t89, $t90, $t91, $t92, $t93, $t94, $t95, $t96, $t97, $t98, $t99, $t100, $t101, $t102, $t103, $t104, $t105, $t106, $t107, $t108, $t109, $t110, $t111, $t112, $t113, $t114 let $locals := $Malloc(416) let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t34 := 101 - $t34 := 101 - // abort($t34) - $Abort($t34) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t35 := borrow_local($t22) - $t35 := $MakePtr(false, $locals) - // $t36 := 0 - $t36 := 0 - // $t16 := $t36 - mstore(add($locals, 96), $t36) - // $t37 := borrow_local($t16) - $t37 := $MakePtr(false, add($locals, 127)) - // $t38 := Table::contains>($t35, $t37) - $t38 := A2_Table_contains$u8_vec$address$$($t35, $t37) - // $t39 := !($t38) - $t39 := $LogicalNot($t38) - // if ($t39) goto L2 else goto L3 - switch $t39 - case 0 { $block := 5 } - default { $block := 6 } + // $t33 := 101 + $t33 := 101 + // abort($t33) + $Abort($t33) } case 4 { // $t22 := Table::empty>() mstore($locals, A2_Table_empty$u8_vec$address$$()) - // $t25 := borrow_local($t22) - $t25 := $MakePtr(false, $locals) - // $t26 := 42 - $t26 := 42 - // $t0 := $t26 - mstore(add($locals, 32), $t26) - // $t27 := borrow_local($t0) - $t27 := $MakePtr(false, add($locals, 63)) - // $t28 := 0x1012 - $t28 := 0x1012 - // $t29 := vector::singleton
($t28) - $t29 := A1_vector_singleton$address$($t28) - // Table::insert>($t25, $t27, $t29) - A2_Table_insert$u8_vec$address$$($t25, $t27, $t29) - // $t30 := borrow_local($t22) - $t30 := $MakePtr(false, $locals) - // $t31 := 42 - $t31 := 42 - // $t14 := $t31 - mstore(add($locals, 64), $t31) - // $t32 := borrow_local($t14) - $t32 := $MakePtr(false, add($locals, 95)) - // $t33 := Table::contains>($t30, $t32) - $t33 := A2_Table_contains$u8_vec$address$$($t30, $t32) - // if ($t33) goto L0 else goto L1 - switch $t33 - case 0 { $block := 2 } - default { $block := 3 } + // $t24 := borrow_local($t22) + $t24 := $MakePtr(false, $locals) + // $t25 := 42 + $t25 := 42 + // $t0 := $t25 + mstore(add($locals, 32), $t25) + // $t26 := borrow_local($t0) + $t26 := $MakePtr(false, add($locals, 63)) + // $t27 := 0x1012 + $t27 := 0x1012 + // $t28 := vector::singleton
($t27) + $t28 := A1_vector_singleton$address$($t27) + // Table::insert>($t24, $t26, $t28) + A2_Table_insert$u8_vec$address$$($t24, $t26, $t28) + // $t29 := borrow_local($t22) + $t29 := $MakePtr(false, $locals) + // $t30 := 42 + $t30 := 42 + // $t14 := $t30 + mstore(add($locals, 64), $t30) + // $t31 := borrow_local($t14) + $t31 := $MakePtr(false, add($locals, 95)) + // $t32 := Table::contains>($t29, $t31) + $t32 := A2_Table_contains$u8_vec$address$$($t29, $t31) + // if ($t32) goto L1 else goto L0 + switch $t32 + case 0 { $block := 3 } + default { $block := 2 } } case 5 { - // label L3 - // $t40 := 102 - $t40 := 102 - // abort($t40) - $Abort($t40) - } - case 6 { // label L2 - // $t41 := borrow_local($t22) - $t41 := $MakePtr(false, $locals) - // $t42 := 42 - $t42 := 42 - // $t18 := $t42 - mstore(add($locals, 128), $t42) - // $t43 := borrow_local($t18) - $t43 := $MakePtr(false, add($locals, 159)) - // $t44 := Table::borrow>($t41, $t43) - $t44 := A2_Table_borrow$u8_vec$address$$($t41, $t43) - // $t45 := vector::length
($t44) - $t45 := A1_vector_length$address$($t44) - // $t46 := 1 - $t46 := 1 - // $t47 := ==($t45, $t46) - $t47 := $Eq($t45, $t46) - // if ($t47) goto L4 else goto L5 - switch $t47 + // $t34 := borrow_local($t22) + $t34 := $MakePtr(false, $locals) + // $t35 := 0 + $t35 := 0 + // $t16 := $t35 + mstore(add($locals, 96), $t35) + // $t36 := borrow_local($t16) + $t36 := $MakePtr(false, add($locals, 127)) + // $t37 := Table::contains>($t34, $t36) + $t37 := A2_Table_contains$u8_vec$address$$($t34, $t36) + // $t38 := !($t37) + $t38 := $LogicalNot($t37) + // if ($t38) goto L4 else goto L3 + switch $t38 case 0 { $block := 7 } - default { $block := 8 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 } case 7 { - // label L5 - // $t48 := 103 - $t48 := 103 - // abort($t48) - $Abort($t48) + // label L3 + // $t39 := 102 + $t39 := 102 + // abort($t39) + $Abort($t39) } case 8 { - // label L4 - // $t49 := borrow_local($t22) - $t49 := $MakePtr(false, $locals) - // $t50 := 42 - $t50 := 42 - // $t20 := $t50 - mstore(add($locals, 160), $t50) - // $t51 := borrow_local($t20) - $t51 := $MakePtr(false, add($locals, 191)) - // $t52 := Table::borrow>($t49, $t51) - $t52 := A2_Table_borrow$u8_vec$address$$($t49, $t51) - // $t53 := 0 - $t53 := 0 - // $t54 := vector::borrow
($t52, $t53) - $t54 := A1_vector_borrow$address$($t52, $t53) - // $t55 := read_ref($t54) - $t55 := $LoadU256($t54) - // $t56 := 0x1012 - $t56 := 0x1012 - // $t57 := ==($t55, $t56) - $t57 := $Eq($t55, $t56) - // if ($t57) goto L6 else goto L7 - switch $t57 - case 0 { $block := 9 } - default { $block := 10 } + // label L5 + // $t40 := borrow_local($t22) + $t40 := $MakePtr(false, $locals) + // $t41 := 42 + $t41 := 42 + // $t18 := $t41 + mstore(add($locals, 128), $t41) + // $t42 := borrow_local($t18) + $t42 := $MakePtr(false, add($locals, 159)) + // $t43 := Table::borrow>($t40, $t42) + $t43 := A2_Table_borrow$u8_vec$address$$($t40, $t42) + // $t44 := vector::length
($t43) + $t44 := A1_vector_length$address$($t43) + // $t45 := 1 + $t45 := 1 + // $t46 := ==($t44, $t45) + $t46 := $Eq($t44, $t45) + // if ($t46) goto L7 else goto L6 + switch $t46 + case 0 { $block := 10 } + default { $block := 9 } } case 9 { // label L7 - // $t58 := 104 - $t58 := 104 - // abort($t58) - $Abort($t58) + // goto L8 + $block := 11 } case 10 { // label L6 - // $t59 := 0x42 - $t59 := 0x42 - // $t2 := Evm::sign($t59) - mstore(add($locals, 192), A2_Evm_sign($t59)) - // $t60 := borrow_local($t2) - $t60 := $MakePtr(false, add($locals, 192)) - // $t61 := move($t22) - $t61 := mload($locals) - // $t62 := pack Tables::S>($t61) + // $t47 := 103 + $t47 := 103 + // abort($t47) + $Abort($t47) + } + case 11 { + // label L8 + // $t48 := borrow_local($t22) + $t48 := $MakePtr(false, $locals) + // $t49 := 42 + $t49 := 42 + // $t20 := $t49 + mstore(add($locals, 160), $t49) + // $t50 := borrow_local($t20) + $t50 := $MakePtr(false, add($locals, 191)) + // $t51 := Table::borrow>($t48, $t50) + $t51 := A2_Table_borrow$u8_vec$address$$($t48, $t50) + // $t52 := 0 + $t52 := 0 + // $t53 := vector::borrow
($t51, $t52) + $t53 := A1_vector_borrow$address$($t51, $t52) + // $t54 := read_ref($t53) + $t54 := $LoadU256($t53) + // $t55 := 0x1012 + $t55 := 0x1012 + // $t56 := ==($t54, $t55) + $t56 := $Eq($t54, $t55) + // if ($t56) goto L10 else goto L9 + switch $t56 + case 0 { $block := 13 } + default { $block := 12 } + } + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 + // $t57 := 104 + $t57 := 104 + // abort($t57) + $Abort($t57) + } + case 14 { + // label L11 + // $t58 := 0x42 + $t58 := 0x42 + // $t2 := Evm::sign($t58) + mstore(add($locals, 192), A2_Evm_sign($t58)) + // $t59 := borrow_local($t2) + $t59 := $MakePtr(false, add($locals, 192)) + // $t60 := move($t22) + $t60 := mload($locals) + // $t61 := pack Tables::S>($t60) { let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t61) - $t62 := $mem + $MemoryStoreU256(add($mem, 0), $t60) + $t61 := $mem } - // move_to>>($t62, $t60) + // move_to>>($t61, $t59) { - let $base_offset := $MakeTypeStorageBase(0, 0xa0362133, $LoadU256($t60)) + let $base_offset := $MakeTypeStorageBase(0, 0xa0362133, $LoadU256($t59)) if $AlignedStorageLoad($base_offset) { $AbortBuiltin() } $AlignedStorageStore($base_offset, true) { let $dst := add($base_offset, 32) - let $src := $t62 + let $src := $t61 $AlignedStorageStore(add($dst, 0), mload(add($src, 0))) $Free($src, 32) } } - // $t63 := 0x42 - $t63 := 0x42 - // $t64 := borrow_global>>($t63) + // $t62 := 0x42 + $t62 := 0x42 + // $t63 := borrow_global>>($t62) { - let $base_offset := $MakeTypeStorageBase(0, 0xa0362133, $t63) + let $base_offset := $MakeTypeStorageBase(0, 0xa0362133, $t62) if iszero($AlignedStorageLoad($base_offset)) { $AbortBuiltin() } - $t64 := $MakePtr(true, add($base_offset, 32)) + $t63 := $MakePtr(true, add($base_offset, 32)) } - // $t65 := borrow_field>>.t($t64) - $t65 := $t64 - // $t66 := 42 - $t66 := 42 - // $t3 := $t66 - mstore(add($locals, 224), $t66) - // $t67 := borrow_local($t3) - $t67 := $MakePtr(false, add($locals, 255)) - // $t68 := Table::borrow_mut>($t65, $t67) - $t68 := A2_Table_borrow_mut$u8_vec$address$$($t65, $t67) - // $t69 := 0x1013 - $t69 := 0x1013 - // vector::push_back
($t68, $t69) - A1_vector_push_back$address$($t68, $t69) - // $t70 := borrow_field>>.t($t64) - $t70 := $t64 - // $t71 := 42 - $t71 := 42 - // $t5 := $t71 - mstore(add($locals, 256), $t71) - // $t72 := borrow_local($t5) - $t72 := $MakePtr(false, add($locals, 287)) - // $t73 := Table::borrow>($t70, $t72) - $t73 := A2_Table_borrow$u8_vec$address$$($t70, $t72) - // $t74 := vector::length
($t73) - $t74 := A1_vector_length$address$($t73) - // $t75 := 2 - $t75 := 2 - // $t76 := ==($t74, $t75) - $t76 := $Eq($t74, $t75) - // if ($t76) goto L8 else goto L9 - switch $t76 - case 0 { $block := 11 } - default { $block := 12 } - } - case 11 { - // label L9 - // destroy($t64) - // $t77 := 105 - $t77 := 105 - // abort($t77) - $Abort($t77) - } - case 12 { - // label L8 - // $t78 := borrow_field>>.t($t64) - $t78 := $t64 - // $t79 := 42 - $t79 := 42 - // $t7 := $t79 - mstore(add($locals, 288), $t79) - // $t80 := borrow_local($t7) - $t80 := $MakePtr(false, add($locals, 319)) - // $t81 := Table::borrow>($t78, $t80) - $t81 := A2_Table_borrow$u8_vec$address$$($t78, $t80) - // $t82 := 1 - $t82 := 1 - // $t83 := vector::borrow
($t81, $t82) - $t83 := A1_vector_borrow$address$($t81, $t82) - // $t84 := read_ref($t83) - $t84 := $LoadU256($t83) - // $t85 := 0x1013 - $t85 := 0x1013 - // $t86 := ==($t84, $t85) - $t86 := $Eq($t84, $t85) - // if ($t86) goto L10 else goto L11 - switch $t86 - case 0 { $block := 13 } - default { $block := 14 } - } - case 13 { - // label L11 - // destroy($t64) - // $t87 := 106 - $t87 := 106 - // abort($t87) - $Abort($t87) - } - case 14 { - // label L10 - // $t88 := borrow_field>>.t($t64) - $t88 := $t64 - // $t89 := 42 - $t89 := 42 - // $t9 := $t89 - mstore(add($locals, 320), $t89) - // $t90 := borrow_local($t9) - $t90 := $MakePtr(false, add($locals, 351)) - // $t23 := Table::remove>($t88, $t90) - mstore(add($locals, 352), A2_Table_remove$u8_vec$address$$($t88, $t90)) - // $t91 := borrow_local($t23) - $t91 := $MakePtr(false, add($locals, 352)) - // $t92 := vector::length
($t91) - $t92 := A1_vector_length$address$($t91) - // $t93 := 2 - $t93 := 2 - // $t94 := ==($t92, $t93) - $t94 := $Eq($t92, $t93) - // if ($t94) goto L12 else goto L13 - switch $t94 - case 0 { $block := 15 } - default { $block := 16 } + // $t64 := borrow_field>>.t($t63) + $t64 := $t63 + // $t65 := 42 + $t65 := 42 + // $t3 := $t65 + mstore(add($locals, 224), $t65) + // $t66 := borrow_local($t3) + $t66 := $MakePtr(false, add($locals, 255)) + // $t67 := Table::borrow_mut>($t64, $t66) + $t67 := A2_Table_borrow_mut$u8_vec$address$$($t64, $t66) + // $t68 := 0x1013 + $t68 := 0x1013 + // vector::push_back
($t67, $t68) + A1_vector_push_back$address$($t67, $t68) + // $t69 := borrow_field>>.t($t63) + $t69 := $t63 + // $t70 := 42 + $t70 := 42 + // $t5 := $t70 + mstore(add($locals, 256), $t70) + // $t71 := borrow_local($t5) + $t71 := $MakePtr(false, add($locals, 287)) + // $t72 := Table::borrow>($t69, $t71) + $t72 := A2_Table_borrow$u8_vec$address$$($t69, $t71) + // $t73 := vector::length
($t72) + $t73 := A1_vector_length$address$($t72) + // $t74 := 2 + $t74 := 2 + // $t75 := ==($t73, $t74) + $t75 := $Eq($t73, $t74) + // if ($t75) goto L13 else goto L12 + switch $t75 + case 0 { $block := 16 } + default { $block := 15 } } case 15 { // label L13 - // destroy($t64) - // $t95 := 107 - $t95 := 107 - // abort($t95) - $Abort($t95) + // goto L14 + $block := 17 } case 16 { // label L12 - // $t96 := borrow_local($t23) - $t96 := $MakePtr(false, add($locals, 352)) - // $t97 := 0 - $t97 := 0 - // $t98 := vector::borrow
($t96, $t97) - $t98 := A1_vector_borrow$address$($t96, $t97) - // $t99 := read_ref($t98) - $t99 := $LoadU256($t98) - // $t100 := 0x1012 - $t100 := 0x1012 - // $t101 := ==($t99, $t100) - $t101 := $Eq($t99, $t100) - // if ($t101) goto L14 else goto L15 - switch $t101 - case 0 { $block := 17 } - default { $block := 18 } + // destroy($t63) + // $t76 := 105 + $t76 := 105 + // abort($t76) + $Abort($t76) } case 17 { - // label L15 - // destroy($t64) - // $t102 := 108 - $t102 := 108 - // abort($t102) - $Abort($t102) - } - case 18 { // label L14 - // $t103 := borrow_local($t23) - $t103 := $MakePtr(false, add($locals, 352)) - // $t104 := 1 - $t104 := 1 - // $t105 := vector::borrow
($t103, $t104) - $t105 := A1_vector_borrow$address$($t103, $t104) - // $t106 := read_ref($t105) - $t106 := $LoadU256($t105) - // $t107 := 0x1013 - $t107 := 0x1013 - // $t108 := ==($t106, $t107) - $t108 := $Eq($t106, $t107) - // if ($t108) goto L16 else goto L17 - switch $t108 + // $t77 := borrow_field>>.t($t63) + $t77 := $t63 + // $t78 := 42 + $t78 := 42 + // $t7 := $t78 + mstore(add($locals, 288), $t78) + // $t79 := borrow_local($t7) + $t79 := $MakePtr(false, add($locals, 319)) + // $t80 := Table::borrow>($t77, $t79) + $t80 := A2_Table_borrow$u8_vec$address$$($t77, $t79) + // $t81 := 1 + $t81 := 1 + // $t82 := vector::borrow
($t80, $t81) + $t82 := A1_vector_borrow$address$($t80, $t81) + // $t83 := read_ref($t82) + $t83 := $LoadU256($t82) + // $t84 := 0x1013 + $t84 := 0x1013 + // $t85 := ==($t83, $t84) + $t85 := $Eq($t83, $t84) + // if ($t85) goto L16 else goto L15 + switch $t85 case 0 { $block := 19 } - default { $block := 20 } + default { $block := 18 } + } + case 18 { + // label L16 + // goto L17 + $block := 20 } case 19 { - // label L17 - // destroy($t64) - // $t109 := 109 - $t109 := 109 - // abort($t109) - $Abort($t109) + // label L15 + // destroy($t63) + // $t86 := 106 + $t86 := 106 + // abort($t86) + $Abort($t86) } case 20 { - // label L16 - // $t110 := borrow_field>>.t($t64) - $t110 := $t64 - // $t111 := 42 - $t111 := 42 - // $t12 := $t111 - mstore(add($locals, 384), $t111) - // $t112 := borrow_local($t12) - $t112 := $MakePtr(false, add($locals, 415)) - // $t113 := Table::contains>($t110, $t112) - $t113 := A2_Table_contains$u8_vec$address$$($t110, $t112) - // $t114 := !($t113) - $t114 := $LogicalNot($t113) - // if ($t114) goto L18 else goto L19 - switch $t114 - case 0 { $block := 21 } - default { $block := 22 } + // label L17 + // $t87 := borrow_field>>.t($t63) + $t87 := $t63 + // $t88 := 42 + $t88 := 42 + // $t9 := $t88 + mstore(add($locals, 320), $t88) + // $t89 := borrow_local($t9) + $t89 := $MakePtr(false, add($locals, 351)) + // $t23 := Table::remove>($t87, $t89) + mstore(add($locals, 352), A2_Table_remove$u8_vec$address$$($t87, $t89)) + // $t90 := borrow_local($t23) + $t90 := $MakePtr(false, add($locals, 352)) + // $t91 := vector::length
($t90) + $t91 := A1_vector_length$address$($t90) + // $t92 := 2 + $t92 := 2 + // $t93 := ==($t91, $t92) + $t93 := $Eq($t91, $t92) + // if ($t93) goto L19 else goto L18 + switch $t93 + case 0 { $block := 22 } + default { $block := 21 } } case 21 { // label L19 - // $t115 := 110 - $t115 := 110 - // abort($t115) - $Abort($t115) + // goto L20 + $block := 23 } case 22 { // label L18 + // destroy($t63) + // $t94 := 107 + $t94 := 107 + // abort($t94) + $Abort($t94) + } + case 23 { + // label L20 + // $t95 := borrow_local($t23) + $t95 := $MakePtr(false, add($locals, 352)) + // $t96 := 0 + $t96 := 0 + // $t97 := vector::borrow
($t95, $t96) + $t97 := A1_vector_borrow$address$($t95, $t96) + // $t98 := read_ref($t97) + $t98 := $LoadU256($t97) + // $t99 := 0x1012 + $t99 := 0x1012 + // $t100 := ==($t98, $t99) + $t100 := $Eq($t98, $t99) + // if ($t100) goto L22 else goto L21 + switch $t100 + case 0 { $block := 25 } + default { $block := 24 } + } + case 24 { + // label L22 + // goto L23 + $block := 26 + } + case 25 { + // label L21 + // destroy($t63) + // $t101 := 108 + $t101 := 108 + // abort($t101) + $Abort($t101) + } + case 26 { + // label L23 + // $t102 := borrow_local($t23) + $t102 := $MakePtr(false, add($locals, 352)) + // $t103 := 1 + $t103 := 1 + // $t104 := vector::borrow
($t102, $t103) + $t104 := A1_vector_borrow$address$($t102, $t103) + // $t105 := read_ref($t104) + $t105 := $LoadU256($t104) + // $t106 := 0x1013 + $t106 := 0x1013 + // $t107 := ==($t105, $t106) + $t107 := $Eq($t105, $t106) + // if ($t107) goto L25 else goto L24 + switch $t107 + case 0 { $block := 28 } + default { $block := 27 } + } + case 27 { + // label L25 + // goto L26 + $block := 29 + } + case 28 { + // label L24 + // destroy($t63) + // $t108 := 109 + $t108 := 109 + // abort($t108) + $Abort($t108) + } + case 29 { + // label L26 + // $t109 := borrow_field>>.t($t63) + $t109 := $t63 + // $t110 := 42 + $t110 := 42 + // $t12 := $t110 + mstore(add($locals, 384), $t110) + // $t111 := borrow_local($t12) + $t111 := $MakePtr(false, add($locals, 415)) + // $t112 := Table::contains>($t109, $t111) + $t112 := A2_Table_contains$u8_vec$address$$($t109, $t111) + // $t113 := !($t112) + $t113 := $LogicalNot($t112) + // if ($t113) goto L28 else goto L27 + switch $t113 + case 0 { $block := 31 } + default { $block := 30 } + } + case 30 { + // label L28 + // goto L29 + $block := 32 + } + case 31 { + // label L27 + // $t114 := 110 + $t114 := 110 + // abort($t114) + $Abort($t114) + } + case 32 { + // label L29 // return () $Free($locals, 416) leave @@ -4004,4 +4224,4 @@ object "test_A2_Tables_test_vector" { } } } -===> Test result of Tables::test_vector: Succeed(Stopped) (used_gas=177564): [] +===> Test result of Tables::test_vector: Succeed(Stopped) (used_gas=181444): [] diff --git a/language/evm/move-to-yul/tests/TestABINative.exp b/language/evm/move-to-yul/tests/TestABINative.exp index e38fd0bc67..262139247a 100644 --- a/language/evm/move-to-yul/tests/TestABINative.exp +++ b/language/evm/move-to-yul/tests/TestABINative.exp @@ -58,7 +58,7 @@ object "test_A2_M_test_decode_two_bytes1" { $t8 := 31 // $t9 := <=($t0, $t8) $t9 := $LtEq(i, $t8) - // if ($t9) goto L0 else goto L2 + // if ($t9) goto L1 else goto L0 switch $t9 case 0 { $block := 5 } default { $block := 4 } @@ -80,22 +80,12 @@ object "test_A2_M_test_decode_two_bytes1" { $block := 2 } case 4 { - // label L0 - // $t10 := borrow_local($t2) - $t10 := $MakePtr(false, $locals) - // $t11 := 0 - $t11 := 0 - // vector::push_back($t10, $t11) - A1_vector_push_back$u8$($t10, $t11) - // $t12 := 1 - $t12 := 1 - // $t0 := +($t0, $t12) - i := $AddU64(i, $t12) - // goto L3 - $block := 2 + // label L1 + // goto L2 + $block := 6 } case 5 { - // label L2 + // label L0 // $t13 := borrow_local($t2) $t13 := $MakePtr(false, $locals) // $t14 := 43 @@ -107,36 +97,41 @@ object "test_A2_M_test_decode_two_bytes1" { // $t1 := $t15 i_1 := $t15 // goto L7 - $block := 6 + $block := 7 } case 6 { + // label L2 + // $t10 := borrow_local($t2) + $t10 := $MakePtr(false, $locals) + // $t11 := 0 + $t11 := 0 + // vector::push_back($t10, $t11) + A1_vector_push_back$u8$($t10, $t11) + // $t12 := 1 + $t12 := 1 + // $t0 := +($t0, $t12) + i := $AddU64(i, $t12) + // goto L3 + $block := 2 + } + case 7 { // label L7 // $t16 := 31 $t16 := 31 // $t17 := <=($t1, $t16) $t17 := $LtEq(i_1, $t16) - // if ($t17) goto L4 else goto L6 + // if ($t17) goto L5 else goto L4 switch $t17 - case 0 { $block := 8 } - default { $block := 7 } - } - case 7 { - // label L4 - // $t18 := borrow_local($t2) - $t18 := $MakePtr(false, $locals) - // $t19 := 0 - $t19 := 0 - // vector::push_back($t18, $t19) - A1_vector_push_back$u8$($t18, $t19) - // $t20 := 1 - $t20 := 1 - // $t1 := +($t1, $t20) - i_1 := $AddU64(i_1, $t20) - // goto L7 - $block := 6 + case 0 { $block := 9 } + default { $block := 8 } } case 8 { - // label L6 + // label L5 + // goto L6 + $block := 10 + } + case 9 { + // label L4 // $t21 := move($t2) $t21 := mload($locals) // ($t22, $t23) := M::decode_two_bytes1($t21) @@ -153,25 +148,40 @@ object "test_A2_M_test_decode_two_bytes1" { $t26 := 1 // $t27 := ==($t25, $t26) $t27 := $Eq($t25, $t26) - // if ($t27) goto L8 else goto L10 + // if ($t27) goto L9 else goto L8 switch $t27 - case 0 { $block := 10 } - default { $block := 9 } - } - case 9 { - // label L8 - // goto L11 - $block := 11 + case 0 { $block := 12 } + default { $block := 11 } } case 10 { - // label L10 + // label L6 + // $t18 := borrow_local($t2) + $t18 := $MakePtr(false, $locals) + // $t19 := 0 + $t19 := 0 + // vector::push_back($t18, $t19) + A1_vector_push_back$u8$($t18, $t19) + // $t20 := 1 + $t20 := 1 + // $t1 := +($t1, $t20) + i_1 := $AddU64(i_1, $t20) + // goto L7 + $block := 7 + } + case 11 { + // label L9 + // goto L10 + $block := 13 + } + case 12 { + // label L8 // $t28 := 101 $t28 := 101 // abort($t28) $Abort($t28) } - case 11 { - // label L11 + case 13 { + // label L10 // $t29 := borrow_local($t4) $t29 := $MakePtr(false, add($locals, 64)) // $t30 := vector::length($t29) @@ -180,25 +190,25 @@ object "test_A2_M_test_decode_two_bytes1" { $t31 := 1 // $t32 := ==($t30, $t31) $t32 := $Eq($t30, $t31) - // if ($t32) goto L12 else goto L14 + // if ($t32) goto L12 else goto L11 switch $t32 - case 0 { $block := 13 } - default { $block := 12 } + case 0 { $block := 15 } + default { $block := 14 } } - case 12 { + case 14 { // label L12 - // goto L15 - $block := 14 + // goto L13 + $block := 16 } - case 13 { - // label L14 + case 15 { + // label L11 // $t33 := 102 $t33 := 102 // abort($t33) $Abort($t33) } - case 14 { - // label L15 + case 16 { + // label L13 // $t34 := borrow_local($t3) $t34 := $MakePtr(false, add($locals, 32)) // $t35 := 0 @@ -211,25 +221,25 @@ object "test_A2_M_test_decode_two_bytes1" { $t38 := 42 // $t39 := ==($t37, $t38) $t39 := $Eq($t37, $t38) - // if ($t39) goto L16 else goto L18 + // if ($t39) goto L15 else goto L14 switch $t39 - case 0 { $block := 16 } - default { $block := 15 } + case 0 { $block := 18 } + default { $block := 17 } } - case 15 { - // label L16 - // goto L19 - $block := 17 + case 17 { + // label L15 + // goto L16 + $block := 19 } - case 16 { - // label L18 + case 18 { + // label L14 // $t40 := 103 $t40 := 103 // abort($t40) $Abort($t40) } - case 17 { - // label L19 + case 19 { + // label L16 // $t41 := borrow_local($t4) $t41 := $MakePtr(false, add($locals, 64)) // $t42 := 0 @@ -242,25 +252,25 @@ object "test_A2_M_test_decode_two_bytes1" { $t45 := 43 // $t46 := ==($t44, $t45) $t46 := $Eq($t44, $t45) - // if ($t46) goto L20 else goto L22 + // if ($t46) goto L18 else goto L17 switch $t46 - case 0 { $block := 19 } - default { $block := 18 } + case 0 { $block := 21 } + default { $block := 20 } } - case 18 { - // label L20 - // goto L23 - $block := 20 + case 20 { + // label L18 + // goto L19 + $block := 22 } - case 19 { - // label L22 + case 21 { + // label L17 // $t47 := 104 $t47 := 104 // abort($t47) $Abort($t47) } - case 20 { - // label L23 + case 22 { + // label L19 // return () $Free($locals, 96) leave @@ -280,14 +290,6 @@ object "test_A2_M_test_decode_two_bytes1" { let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) len := $LoadU64(v_ptr) } - function A2_M_decode_two_bytes1(input) -> $result0, $result1 { - let $t1 := add(input, 32) - let $t2 := $MemoryLoadU64(input) - let $t3 := add($t1, $t2) - if gt($t1, 0xffffffffffffffff) { $AbortBuiltin() } - if gt($t3, 0xffffffffffffffff) { $AbortBuiltin() } - $result0, $result1 := abi_decode_tuple_$bytes1_bytes1$_$vec$u8$_vec$u8$$_from_memory($t1, $t3) - } function A1_vector_push_back$u8$(v_ref, e) { let v_offs := $LoadU256(v_ref) let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) @@ -302,6 +304,14 @@ object "test_A2_M_test_decode_two_bytes1" { $StoreU256(v_ref, new_v_offs) } } + function A2_M_decode_two_bytes1(input) -> $result0, $result1 { + let $t1 := add(input, 32) + let $t2 := $MemoryLoadU64(input) + let $t3 := add($t1, $t2) + if gt($t1, 0xffffffffffffffff) { $AbortBuiltin() } + if gt($t3, 0xffffffffffffffff) { $AbortBuiltin() } + $result0, $result1 := abi_decode_tuple_$bytes1_bytes1$_$vec$u8$_vec$u8$$_from_memory($t1, $t3) + } function A1_vector_empty$u8$() -> vector { vector := $Malloc(34) $MemoryStoreU64(add(vector, 8), 2) @@ -604,7 +614,7 @@ object "test_A2_M_test_decode_two_bytes1" { } } } -===> Test result of M::test_decode_two_bytes1: Succeed(Stopped) (used_gas=66864): [] +===> Test result of M::test_decode_two_bytes1: Succeed(Stopped) (used_gas=79598): [] // test of M::test_decode_two_u8 /* ======================================= @@ -618,146 +628,156 @@ object "test_A2_M_test_decode_two_u8" { A2_M_test_decode_two_u8() return (0, 0) function A2_M_test_decode_two_u8() { - let i, i_1, v1, v2, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20, $t21, $t22, $t23, $t24, $t25, $t26, $t27, $t28, $t29 + let i, i_1, v2, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20, $t21, $t22, $t23, $t24, $t25, $t26, $t27, $t28 let $locals := $Malloc(32) let $block := 3 for {} true {} { switch $block case 2 { // label L3 - // $t6 := 31 - $t6 := 31 - // $t7 := <=($t0, $t6) - $t7 := $LtEq(i, $t6) - // if ($t7) goto L0 else goto L2 - switch $t7 + // $t5 := 31 + $t5 := 31 + // $t6 := <=($t0, $t5) + $t6 := $LtEq(i, $t5) + // if ($t6) goto L1 else goto L0 + switch $t6 case 0 { $block := 5 } default { $block := 4 } } case 3 { // $t2 := vector::empty() mstore($locals, A1_vector_empty$u8$()) - // $t5 := 1 - $t5 := 1 - // $t0 := $t5 - i := $t5 + // $t4 := 1 + $t4 := 1 + // $t0 := $t4 + i := $t4 // goto L3 $block := 2 } case 4 { - // label L0 - // $t8 := borrow_local($t2) - $t8 := $MakePtr(false, $locals) - // $t9 := 0 - $t9 := 0 - // vector::push_back($t8, $t9) - A1_vector_push_back$u8$($t8, $t9) - // $t10 := 1 - $t10 := 1 - // $t0 := +($t0, $t10) - i := $AddU64(i, $t10) - // goto L3 - $block := 2 + // label L1 + // goto L2 + $block := 6 } case 5 { - // label L2 - // $t11 := borrow_local($t2) - $t11 := $MakePtr(false, $locals) - // $t12 := 42 - $t12 := 42 - // vector::push_back($t11, $t12) - A1_vector_push_back$u8$($t11, $t12) - // $t13 := 1 - $t13 := 1 - // $t1 := $t13 - i_1 := $t13 + // label L0 + // $t10 := borrow_local($t2) + $t10 := $MakePtr(false, $locals) + // $t11 := 42 + $t11 := 42 + // vector::push_back($t10, $t11) + A1_vector_push_back$u8$($t10, $t11) + // $t12 := 1 + $t12 := 1 + // $t1 := $t12 + i_1 := $t12 // goto L7 - $block := 6 + $block := 7 } case 6 { - // label L7 - // $t14 := 31 - $t14 := 31 - // $t15 := <=($t1, $t14) - $t15 := $LtEq(i_1, $t14) - // if ($t15) goto L4 else goto L6 - switch $t15 - case 0 { $block := 8 } - default { $block := 7 } + // label L2 + // $t7 := borrow_local($t2) + $t7 := $MakePtr(false, $locals) + // $t8 := 0 + $t8 := 0 + // vector::push_back($t7, $t8) + A1_vector_push_back$u8$($t7, $t8) + // $t9 := 1 + $t9 := 1 + // $t0 := +($t0, $t9) + i := $AddU64(i, $t9) + // goto L3 + $block := 2 } case 7 { - // label L4 - // $t16 := borrow_local($t2) - $t16 := $MakePtr(false, $locals) - // $t17 := 0 - $t17 := 0 - // vector::push_back($t16, $t17) - A1_vector_push_back$u8$($t16, $t17) - // $t18 := 1 - $t18 := 1 - // $t1 := +($t1, $t18) - i_1 := $AddU64(i_1, $t18) - // goto L7 - $block := 6 + // label L7 + // $t13 := 31 + $t13 := 31 + // $t14 := <=($t1, $t13) + $t14 := $LtEq(i_1, $t13) + // if ($t14) goto L5 else goto L4 + switch $t14 + case 0 { $block := 9 } + default { $block := 8 } } case 8 { - // label L6 - // $t19 := borrow_local($t2) - $t19 := $MakePtr(false, $locals) - // $t20 := 43 - $t20 := 43 - // vector::push_back($t19, $t20) - A1_vector_push_back$u8$($t19, $t20) - // $t21 := move($t2) - $t21 := mload($locals) - // ($t22, $t23) := M::decode_two_u8($t21) - $t22, $t23 := A2_M_decode_two_u8($t21) - // $t24 := 42 - $t24 := 42 - // $t25 := ==($t22, $t24) - $t25 := $Eq($t22, $t24) - // if ($t25) goto L8 else goto L10 - switch $t25 - case 0 { $block := 10 } - default { $block := 9 } + // label L5 + // goto L6 + $block := 10 } case 9 { - // label L8 - // goto L11 - $block := 11 + // label L4 + // $t18 := borrow_local($t2) + $t18 := $MakePtr(false, $locals) + // $t19 := 43 + $t19 := 43 + // vector::push_back($t18, $t19) + A1_vector_push_back$u8$($t18, $t19) + // $t20 := move($t2) + $t20 := mload($locals) + // ($t21, $t22) := M::decode_two_u8($t20) + $t21, $t22 := A2_M_decode_two_u8($t20) + // $t23 := 42 + $t23 := 42 + // $t24 := ==($t21, $t23) + $t24 := $Eq($t21, $t23) + // if ($t24) goto L9 else goto L8 + switch $t24 + case 0 { $block := 12 } + default { $block := 11 } } case 10 { - // label L10 - // $t26 := 101 - $t26 := 101 - // abort($t26) - $Abort($t26) + // label L6 + // $t15 := borrow_local($t2) + $t15 := $MakePtr(false, $locals) + // $t16 := 0 + $t16 := 0 + // vector::push_back($t15, $t16) + A1_vector_push_back$u8$($t15, $t16) + // $t17 := 1 + $t17 := 1 + // $t1 := +($t1, $t17) + i_1 := $AddU64(i_1, $t17) + // goto L7 + $block := 7 } case 11 { - // label L11 - // $t27 := 43 - $t27 := 43 - // $t28 := ==($t23, $t27) - $t28 := $Eq($t23, $t27) - // if ($t28) goto L12 else goto L14 - switch $t28 - case 0 { $block := 13 } - default { $block := 12 } + // label L9 + // goto L10 + $block := 13 } case 12 { - // label L12 - // goto L15 - $block := 14 + // label L8 + // $t25 := 101 + $t25 := 101 + // abort($t25) + $Abort($t25) } case 13 { - // label L14 - // $t29 := 102 - $t29 := 102 - // abort($t29) - $Abort($t29) + // label L10 + // $t26 := 43 + $t26 := 43 + // $t27 := ==($t22, $t26) + $t27 := $Eq($t22, $t26) + // if ($t27) goto L12 else goto L11 + switch $t27 + case 0 { $block := 15 } + default { $block := 14 } } case 14 { - // label L15 + // label L12 + // goto L13 + $block := 16 + } + case 15 { + // label L11 + // $t28 := 102 + $t28 := 102 + // abort($t28) + $Abort($t28) + } + case 16 { + // label L13 // return () $Free($locals, 32) leave @@ -765,14 +785,6 @@ object "test_A2_M_test_decode_two_u8" { } } - function A2_M_decode_two_u8(input) -> $result0, $result1 { - let $t1 := add(input, 32) - let $t2 := $MemoryLoadU64(input) - let $t3 := add($t1, $t2) - if gt($t1, 0xffffffffffffffff) { $AbortBuiltin() } - if gt($t3, 0xffffffffffffffff) { $AbortBuiltin() } - $result0, $result1 := abi_decode_tuple_$uint8_uint8$_$u8_u8$_from_memory($t1, $t3) - } function A1_vector_push_back$u8$(v_ref, e) { let v_offs := $LoadU256(v_ref) let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) @@ -787,6 +799,14 @@ object "test_A2_M_test_decode_two_u8" { $StoreU256(v_ref, new_v_offs) } } + function A2_M_decode_two_u8(input) -> $result0, $result1 { + let $t1 := add(input, 32) + let $t2 := $MemoryLoadU64(input) + let $t3 := add($t1, $t2) + if gt($t1, 0xffffffffffffffff) { $AbortBuiltin() } + if gt($t3, 0xffffffffffffffff) { $AbortBuiltin() } + $result0, $result1 := abi_decode_tuple_$uint8_uint8$_$u8_u8$_from_memory($t1, $t3) + } function A1_vector_empty$u8$() -> vector { vector := $Malloc(34) $MemoryStoreU64(add(vector, 8), 2) @@ -1041,7 +1061,7 @@ object "test_A2_M_test_decode_two_u8" { } } } -===> Test result of M::test_decode_two_u8: Succeed(Stopped) (used_gas=64646): [] +===> Test result of M::test_decode_two_u8: Succeed(Stopped) (used_gas=77393): [] // test of M::test_encode_packed_string /* ======================================= @@ -1060,12 +1080,12 @@ object "test_A2_M_test_encode_packed_string" { for {} true {} { switch $block case 2 { - // label L0 - // goto L3 + // label L1 + // goto L2 $block := 5 } case 3 { - // label L2 + // label L0 // $t5 := 100 $t5 := 100 // abort($t5) @@ -1091,13 +1111,13 @@ object "test_A2_M_test_encode_packed_string" { copy_literal_string_to_memory_21418693(add($t3, 32)) // $t4 := ==($t2, $t3) $t4 := $Eq_$vec$u8$$($t2, $t3) - // if ($t4) goto L0 else goto L2 + // if ($t4) goto L1 else goto L0 switch $t4 case 0 { $block := 3 } default { $block := 2 } } case 5 { - // label L3 + // label L2 // $t6 := [49] $t6 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(1))) $MemoryStoreU64($t6, 1) @@ -1117,25 +1137,25 @@ object "test_A2_M_test_encode_packed_string" { copy_literal_string_to_memory_141265791(add($t9, 32)) // $t10 := ==($t8, $t9) $t10 := $Eq_$vec$u8$$($t8, $t9) - // if ($t10) goto L4 else goto L6 + // if ($t10) goto L4 else goto L3 switch $t10 case 0 { $block := 7 } default { $block := 6 } } case 6 { // label L4 - // goto L7 + // goto L5 $block := 8 } case 7 { - // label L6 + // label L3 // $t11 := 101 $t11 := 101 // abort($t11) $Abort($t11) } case 8 { - // label L7 + // label L5 // $t12 := [] $t12 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(0))) $MemoryStoreU64($t12, 0) @@ -1155,25 +1175,25 @@ object "test_A2_M_test_encode_packed_string" { copy_literal_string_to_memory_2053440334(add($t15, 32)) // $t16 := ==($t14, $t15) $t16 := $Eq_$vec$u8$$($t14, $t15) - // if ($t16) goto L8 else goto L10 + // if ($t16) goto L7 else goto L6 switch $t16 case 0 { $block := 10 } default { $block := 9 } } case 9 { - // label L8 - // goto L11 + // label L7 + // goto L8 $block := 11 } case 10 { - // label L10 + // label L6 // $t17 := 102 $t17 := 102 // abort($t17) $Abort($t17) } case 11 { - // label L11 + // label L8 // $t18 := [97] $t18 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(1))) $MemoryStoreU64($t18, 1) @@ -1200,25 +1220,25 @@ object "test_A2_M_test_encode_packed_string" { copy_literal_string_to_memory_3871831907(add($t23, 32)) // $t24 := ==($t22, $t23) $t24 := $Eq_$vec$u8$$($t22, $t23) - // if ($t24) goto L12 else goto L14 + // if ($t24) goto L10 else goto L9 switch $t24 case 0 { $block := 13 } default { $block := 12 } } case 12 { - // label L12 - // goto L15 + // label L10 + // goto L11 $block := 14 } case 13 { - // label L14 + // label L9 // $t25 := 103 $t25 := 103 // abort($t25) $Abort($t25) } case 14 { - // label L15 + // label L11 // $t26 := [116, 101, 115, 116] $t26 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(4))) $MemoryStoreU64($t26, 4) @@ -1238,25 +1258,25 @@ object "test_A2_M_test_encode_packed_string" { copy_literal_string_to_memory_1610556060(add($t29, 32)) // $t30 := ==($t28, $t29) $t30 := $Eq_$vec$u8$$($t28, $t29) - // if ($t30) goto L16 else goto L18 + // if ($t30) goto L13 else goto L12 switch $t30 case 0 { $block := 16 } default { $block := 15 } } case 15 { - // label L16 - // goto L19 + // label L13 + // goto L14 $block := 17 } case 16 { - // label L18 + // label L12 // $t31 := 104 $t31 := 104 // abort($t31) $Abort($t31) } case 17 { - // label L19 + // label L14 // return () leave } @@ -1457,45 +1477,45 @@ object "test_A2_M_test_encode_packed_uint16" { A2_M_test_encode_packed_uint16() return (0, 0) function A2_M_test_encode_packed_uint16() { - let v1, v2, $t3, $t4, $t5, $t6, $t7, $t8, $t9 + let $t1, $t2, $t3, $t4, $t5, $t6, $t7 let $locals := $Malloc(32) let $block := 4 for {} true {} { switch $block case 2 { - // label L0 - // goto L3 + // label L1 + // goto L2 $block := 5 } case 3 { - // label L2 - // $t9 := 101 - $t9 := 101 - // abort($t9) - $Abort($t9) + // label L0 + // $t7 := 101 + $t7 := 101 + // abort($t7) + $Abort($t7) } case 4 { - // $t3 := 41 - $t3 := 41 - // $t4 := 42 - $t4 := 42 - // $t0 := M::encode_packed($t3, $t4) - mstore($locals, A2_M_encode_packed($t3, $t4)) - // $t5 := borrow_local($t0) - $t5 := $MakePtr(false, $locals) - // $t6 := vector::length($t5) - $t6 := A1_vector_length$u8$($t5) - // $t7 := 4 - $t7 := 4 - // $t8 := ==($t6, $t7) - $t8 := $Eq($t6, $t7) - // if ($t8) goto L0 else goto L2 - switch $t8 + // $t1 := 41 + $t1 := 41 + // $t2 := 42 + $t2 := 42 + // $t0 := M::encode_packed($t1, $t2) + mstore($locals, A2_M_encode_packed($t1, $t2)) + // $t3 := borrow_local($t0) + $t3 := $MakePtr(false, $locals) + // $t4 := vector::length($t3) + $t4 := A1_vector_length$u8$($t3) + // $t5 := 4 + $t5 := 4 + // $t6 := ==($t4, $t5) + $t6 := $Eq($t4, $t5) + // if ($t6) goto L1 else goto L0 + switch $t6 case 0 { $block := 3 } default { $block := 2 } } case 5 { - // label L3 + // label L2 // return () $Free($locals, 32) leave @@ -1682,125 +1702,135 @@ object "test_A2_M_test_marshalling_two_bytes1" { A2_M_test_marshalling_two_bytes1() return (0, 0) function A2_M_test_marshalling_two_bytes1() { - let i, i_1, v1, v2, v_, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20, $t21, $t22, $t23, $t24, $t25, $t26, $t27, $t28 + let i, i_1, v_, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20, $t21, $t22, $t23, $t24, $t25, $t26 let $locals := $Malloc(32) let $block := 3 for {} true {} { switch $block case 2 { // label L3 - // $t9 := 31 - $t9 := 31 - // $t10 := <=($t0, $t9) - $t10 := $LtEq(i, $t9) - // if ($t10) goto L0 else goto L2 - switch $t10 + // $t7 := 31 + $t7 := 31 + // $t8 := <=($t0, $t7) + $t8 := $LtEq(i, $t7) + // if ($t8) goto L1 else goto L0 + switch $t8 case 0 { $block := 5 } default { $block := 4 } } case 3 { // $t2 := vector::empty() mstore($locals, A1_vector_empty$u8$()) - // $t6 := borrow_local($t2) - $t6 := $MakePtr(false, $locals) - // $t7 := 42 - $t7 := 42 - // vector::push_back($t6, $t7) - A1_vector_push_back$u8$($t6, $t7) - // $t8 := 1 - $t8 := 1 - // $t0 := $t8 - i := $t8 + // $t4 := borrow_local($t2) + $t4 := $MakePtr(false, $locals) + // $t5 := 42 + $t5 := 42 + // vector::push_back($t4, $t5) + A1_vector_push_back$u8$($t4, $t5) + // $t6 := 1 + $t6 := 1 + // $t0 := $t6 + i := $t6 // goto L3 $block := 2 } case 4 { - // label L0 - // $t11 := borrow_local($t2) - $t11 := $MakePtr(false, $locals) - // $t12 := 0 - $t12 := 0 - // vector::push_back($t11, $t12) - A1_vector_push_back$u8$($t11, $t12) - // $t13 := 1 - $t13 := 1 - // $t0 := +($t0, $t13) - i := $AddU64(i, $t13) - // goto L3 - $block := 2 + // label L1 + // goto L2 + $block := 6 } case 5 { - // label L2 - // $t14 := borrow_local($t2) - $t14 := $MakePtr(false, $locals) - // $t15 := 43 - $t15 := 43 - // vector::push_back($t14, $t15) - A1_vector_push_back$u8$($t14, $t15) - // $t16 := 1 - $t16 := 1 - // $t1 := $t16 - i_1 := $t16 + // label L0 + // $t12 := borrow_local($t2) + $t12 := $MakePtr(false, $locals) + // $t13 := 43 + $t13 := 43 + // vector::push_back($t12, $t13) + A1_vector_push_back$u8$($t12, $t13) + // $t14 := 1 + $t14 := 1 + // $t1 := $t14 + i_1 := $t14 // goto L7 - $block := 6 + $block := 7 } case 6 { - // label L7 - // $t17 := 31 - $t17 := 31 - // $t18 := <=($t1, $t17) - $t18 := $LtEq(i_1, $t17) - // if ($t18) goto L4 else goto L6 - switch $t18 - case 0 { $block := 8 } - default { $block := 7 } + // label L2 + // $t9 := borrow_local($t2) + $t9 := $MakePtr(false, $locals) + // $t10 := 0 + $t10 := 0 + // vector::push_back($t9, $t10) + A1_vector_push_back$u8$($t9, $t10) + // $t11 := 1 + $t11 := 1 + // $t0 := +($t0, $t11) + i := $AddU64(i, $t11) + // goto L3 + $block := 2 } case 7 { - // label L4 - // $t19 := borrow_local($t2) - $t19 := $MakePtr(false, $locals) - // $t20 := 0 - $t20 := 0 - // vector::push_back($t19, $t20) - A1_vector_push_back$u8$($t19, $t20) - // $t21 := 1 - $t21 := 1 - // $t1 := +($t1, $t21) - i_1 := $AddU64(i_1, $t21) - // goto L7 - $block := 6 + // label L7 + // $t15 := 31 + $t15 := 31 + // $t16 := <=($t1, $t15) + $t16 := $LtEq(i_1, $t15) + // if ($t16) goto L5 else goto L4 + switch $t16 + case 0 { $block := 9 } + default { $block := 8 } } case 8 { - // label L6 - // $t22 := copy($t2) - $t22 := mload($locals) - // ($t23, $t24) := M::decode_two_bytes1($t22) - $t23, $t24 := A2_M_decode_two_bytes1($t22) - // $t25 := M::encode_two_bytes1($t23, $t24) - $t25 := A2_M_encode_two_bytes1($t23, $t24) - // $t26 := move($t2) - $t26 := mload($locals) - // $t27 := ==($t26, $t25) - $t27 := $Eq_$vec$u8$$($t26, $t25) - // if ($t27) goto L8 else goto L10 - switch $t27 - case 0 { $block := 10 } - default { $block := 9 } + // label L5 + // goto L6 + $block := 10 } case 9 { - // label L8 - // goto L11 - $block := 11 + // label L4 + // $t20 := copy($t2) + $t20 := mload($locals) + // ($t21, $t22) := M::decode_two_bytes1($t20) + $t21, $t22 := A2_M_decode_two_bytes1($t20) + // $t23 := M::encode_two_bytes1($t21, $t22) + $t23 := A2_M_encode_two_bytes1($t21, $t22) + // $t24 := move($t2) + $t24 := mload($locals) + // $t25 := ==($t24, $t23) + $t25 := $Eq_$vec$u8$$($t24, $t23) + // if ($t25) goto L9 else goto L8 + switch $t25 + case 0 { $block := 12 } + default { $block := 11 } } case 10 { - // label L10 - // $t28 := 101 - $t28 := 101 - // abort($t28) - $Abort($t28) + // label L6 + // $t17 := borrow_local($t2) + $t17 := $MakePtr(false, $locals) + // $t18 := 0 + $t18 := 0 + // vector::push_back($t17, $t18) + A1_vector_push_back$u8$($t17, $t18) + // $t19 := 1 + $t19 := 1 + // $t1 := +($t1, $t19) + i_1 := $AddU64(i_1, $t19) + // goto L7 + $block := 7 } case 11 { - // label L11 + // label L9 + // goto L10 + $block := 13 + } + case 12 { + // label L8 + // $t26 := 101 + $t26 := 101 + // abort($t26) + $Abort($t26) + } + case 13 { + // label L10 // return () $Free($locals, 32) leave @@ -1808,6 +1838,20 @@ object "test_A2_M_test_marshalling_two_bytes1" { } } + function A1_vector_push_back$u8$(v_ref, e) { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + let size := $LoadU64(v_ptr) + let e_ptr := $IndexPtr(v_ptr, add(32, mul(size, 1))) + $StoreU8(e_ptr, e) + size := add(size, 1) + $StoreU64(v_ptr, size) + let capacity := $LoadU64($IndexPtr(v_ptr, 8)) + if and(iszero($IsStoragePtr(v_ptr)), eq(size, capacity)) { + let new_v_offs := $ResizeVector(v_offs, capacity, 1) + $StoreU256(v_ref, new_v_offs) + } + } function A2_M_encode_two_bytes1(input_1,input_2) -> $result { $result := mload(0) let $t2 := add($result, 32) @@ -1828,20 +1872,6 @@ object "test_A2_M_test_marshalling_two_bytes1" { if gt($t3, 0xffffffffffffffff) { $AbortBuiltin() } $result0, $result1 := abi_decode_tuple_$bytes1_bytes1$_$vec$u8$_vec$u8$$_from_memory($t1, $t3) } - function A1_vector_push_back$u8$(v_ref, e) { - let v_offs := $LoadU256(v_ref) - let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) - let size := $LoadU64(v_ptr) - let e_ptr := $IndexPtr(v_ptr, add(32, mul(size, 1))) - $StoreU8(e_ptr, e) - size := add(size, 1) - $StoreU64(v_ptr, size) - let capacity := $LoadU64($IndexPtr(v_ptr, 8)) - if and(iszero($IsStoragePtr(v_ptr)), eq(size, capacity)) { - let new_v_offs := $ResizeVector(v_offs, capacity, 1) - $StoreU256(v_ref, new_v_offs) - } - } function A1_vector_empty$u8$() -> vector { vector := $Malloc(34) $MemoryStoreU64(add(vector, 8), 2) @@ -2161,7 +2191,7 @@ object "test_A2_M_test_marshalling_two_bytes1" { } } } -===> Test result of M::test_marshalling_two_bytes1: Succeed(Stopped) (used_gas=66247): [] +===> Test result of M::test_marshalling_two_bytes1: Succeed(Stopped) (used_gas=78906): [] // test of M::test_marshalling_two_u8 /* ======================================= @@ -2186,7 +2216,7 @@ object "test_A2_M_test_marshalling_two_u8" { $t7 := 31 // $t8 := <=($t0, $t7) $t8 := $LtEq(i, $t7) - // if ($t8) goto L0 else goto L2 + // if ($t8) goto L1 else goto L0 switch $t8 case 0 { $block := 5 } default { $block := 4 } @@ -2202,22 +2232,12 @@ object "test_A2_M_test_marshalling_two_u8" { $block := 2 } case 4 { - // label L0 - // $t9 := borrow_local($t2) - $t9 := $MakePtr(false, $locals) - // $t10 := 0 - $t10 := 0 - // vector::push_back($t9, $t10) - A1_vector_push_back$u8$($t9, $t10) - // $t11 := 1 - $t11 := 1 - // $t0 := +($t0, $t11) - i := $AddU64(i, $t11) - // goto L3 - $block := 2 + // label L1 + // goto L2 + $block := 6 } case 5 { - // label L2 + // label L0 // $t12 := borrow_local($t2) $t12 := $MakePtr(false, $locals) // $t13 := 42 @@ -2229,36 +2249,41 @@ object "test_A2_M_test_marshalling_two_u8" { // $t1 := $t14 i_1 := $t14 // goto L7 - $block := 6 + $block := 7 } case 6 { + // label L2 + // $t9 := borrow_local($t2) + $t9 := $MakePtr(false, $locals) + // $t10 := 0 + $t10 := 0 + // vector::push_back($t9, $t10) + A1_vector_push_back$u8$($t9, $t10) + // $t11 := 1 + $t11 := 1 + // $t0 := +($t0, $t11) + i := $AddU64(i, $t11) + // goto L3 + $block := 2 + } + case 7 { // label L7 // $t15 := 31 $t15 := 31 // $t16 := <=($t1, $t15) $t16 := $LtEq(i_1, $t15) - // if ($t16) goto L4 else goto L6 + // if ($t16) goto L5 else goto L4 switch $t16 - case 0 { $block := 8 } - default { $block := 7 } - } - case 7 { - // label L4 - // $t17 := borrow_local($t2) - $t17 := $MakePtr(false, $locals) - // $t18 := 0 - $t18 := 0 - // vector::push_back($t17, $t18) - A1_vector_push_back$u8$($t17, $t18) - // $t19 := 1 - $t19 := 1 - // $t1 := +($t1, $t19) - i_1 := $AddU64(i_1, $t19) - // goto L7 - $block := 6 + case 0 { $block := 9 } + default { $block := 8 } } case 8 { - // label L6 + // label L5 + // goto L6 + $block := 10 + } + case 9 { + // label L4 // $t20 := borrow_local($t2) $t20 := $MakePtr(false, $locals) // $t21 := 43 @@ -2273,73 +2298,88 @@ object "test_A2_M_test_marshalling_two_u8" { $t25 := 42 // $t26 := ==($t23, $t25) $t26 := $Eq($t23, $t25) - // if ($t26) goto L8 else goto L10 + // if ($t26) goto L9 else goto L8 switch $t26 - case 0 { $block := 10 } - default { $block := 9 } - } - case 9 { - // label L8 - // goto L11 - $block := 11 + case 0 { $block := 12 } + default { $block := 11 } } case 10 { - // label L10 + // label L6 + // $t17 := borrow_local($t2) + $t17 := $MakePtr(false, $locals) + // $t18 := 0 + $t18 := 0 + // vector::push_back($t17, $t18) + A1_vector_push_back$u8$($t17, $t18) + // $t19 := 1 + $t19 := 1 + // $t1 := +($t1, $t19) + i_1 := $AddU64(i_1, $t19) + // goto L7 + $block := 7 + } + case 11 { + // label L9 + // goto L10 + $block := 13 + } + case 12 { + // label L8 // $t27 := 101 $t27 := 101 // abort($t27) $Abort($t27) } - case 11 { - // label L11 + case 13 { + // label L10 // $t28 := 43 $t28 := 43 // $t29 := ==($t24, $t28) $t29 := $Eq($t24, $t28) - // if ($t29) goto L12 else goto L14 + // if ($t29) goto L12 else goto L11 switch $t29 - case 0 { $block := 13 } - default { $block := 12 } + case 0 { $block := 15 } + default { $block := 14 } } - case 12 { + case 14 { // label L12 - // goto L15 - $block := 14 + // goto L13 + $block := 16 } - case 13 { - // label L14 + case 15 { + // label L11 // $t30 := 102 $t30 := 102 // abort($t30) $Abort($t30) } - case 14 { - // label L15 + case 16 { + // label L13 // $t31 := M::encode_two_u8($t23, $t24) $t31 := A2_M_encode_two_u8($t23, $t24) // $t32 := move($t2) $t32 := mload($locals) // $t33 := ==($t32, $t31) $t33 := $Eq_$vec$u8$$($t32, $t31) - // if ($t33) goto L16 else goto L18 + // if ($t33) goto L15 else goto L14 switch $t33 - case 0 { $block := 16 } - default { $block := 15 } + case 0 { $block := 18 } + default { $block := 17 } } - case 15 { - // label L16 - // goto L19 - $block := 17 + case 17 { + // label L15 + // goto L16 + $block := 19 } - case 16 { - // label L18 + case 18 { + // label L14 // $t34 := 103 $t34 := 103 // abort($t34) $Abort($t34) } - case 17 { - // label L19 + case 19 { + // label L16 // return () $Free($locals, 32) leave @@ -2359,14 +2399,6 @@ object "test_A2_M_test_marshalling_two_u8" { $MemoryStoreU64(add($result, 8), $t5) mstore(0, $t3) } - function A2_M_decode_two_u8(input) -> $result0, $result1 { - let $t1 := add(input, 32) - let $t2 := $MemoryLoadU64(input) - let $t3 := add($t1, $t2) - if gt($t1, 0xffffffffffffffff) { $AbortBuiltin() } - if gt($t3, 0xffffffffffffffff) { $AbortBuiltin() } - $result0, $result1 := abi_decode_tuple_$uint8_uint8$_$u8_u8$_from_memory($t1, $t3) - } function A1_vector_push_back$u8$(v_ref, e) { let v_offs := $LoadU256(v_ref) let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) @@ -2381,6 +2413,14 @@ object "test_A2_M_test_marshalling_two_u8" { $StoreU256(v_ref, new_v_offs) } } + function A2_M_decode_two_u8(input) -> $result0, $result1 { + let $t1 := add(input, 32) + let $t2 := $MemoryLoadU64(input) + let $t3 := add($t1, $t2) + if gt($t1, 0xffffffffffffffff) { $AbortBuiltin() } + if gt($t3, 0xffffffffffffffff) { $AbortBuiltin() } + $result0, $result1 := abi_decode_tuple_$uint8_uint8$_$u8_u8$_from_memory($t1, $t3) + } function A1_vector_empty$u8$() -> vector { vector := $Malloc(34) $MemoryStoreU64(add(vector, 8), 2) @@ -2681,7 +2721,7 @@ object "test_A2_M_test_marshalling_two_u8" { } } } -===> Test result of M::test_marshalling_two_u8: Succeed(Stopped) (used_gas=66157): [] +===> Test result of M::test_marshalling_two_u8: Succeed(Stopped) (used_gas=78803): [] diff --git a/language/evm/move-to-yul/tests/TestABIStructs.exp b/language/evm/move-to-yul/tests/TestABIStructs.exp index e511f092fc..af572c9561 100644 --- a/language/evm/move-to-yul/tests/TestABIStructs.exp +++ b/language/evm/move-to-yul/tests/TestABIStructs.exp @@ -94,21 +94,21 @@ object "A2_M" { } $Abort(97) function A2_M_do_transfer() { - let s, $t1, $t2, $t3, $t4 - // $t1 := 42 - $t1 := 42 - // $t2 := true - $t2 := true - // $t3 := M::pack_S($t1, $t2) - $t3 := A2_M_pack_S($t1, $t2) - // $t4 := pack M::Event_S($t3) + let $t0, $t1, $t2, $t3 + // $t0 := 42 + $t0 := 42 + // $t1 := true + $t1 := true + // $t2 := M::pack_S($t0, $t1) + $t2 := A2_M_pack_S($t0, $t1) + // $t3 := pack M::Event_S($t2) { let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t3) - $t4 := $mem + $MemoryStoreU256(add($mem, 0), $t2) + $t3 := $mem } - // Evm::emit($t4) - A2_Evm_emit$A2_M_Event_S$($t4) + // Evm::emit($t3) + A2_Evm_emit$A2_M_Event_S$($t3) // return () } @@ -210,19 +210,19 @@ object "A2_M" { } function A2_M_test_safe_transfer_from() -> $result { - let contract_addr, s, $t2, $t3, $t4, $t5, $t6 - // $t2 := 42 - $t2 := 42 - // $t3 := true - $t3 := true - // $t4 := M::pack_S($t2, $t3) - $t4 := A2_M_pack_S($t2, $t3) - // $t5 := 0x3 - $t5 := 0x3 - // $t6 := M::safe_transfer_form($t5, $t4) - $t6 := A2_M_safe_transfer_form($t5, $t4) - // return $t6 - $result := $t6 + let s, $t1, $t2, $t3, $t4, $t5 + // $t1 := 42 + $t1 := 42 + // $t2 := true + $t2 := true + // $t3 := M::pack_S($t1, $t2) + $t3 := A2_M_pack_S($t1, $t2) + // $t4 := 0x3 + $t4 := 0x3 + // $t5 := M::safe_transfer_form($t4, $t3) + $t5 := A2_M_safe_transfer_form($t4, $t3) + // return $t5 + $result := $t5 } function A2_M_safe_transfer_form(contract, s) -> $result { @@ -1036,135 +1036,155 @@ object "test_A2_M_test_abi_S" { A2_M_test_abi_S() return (0, 0) function A2_M_test_abi_S() { - let _s, _s2x, s, v, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20, $t21, $t22, $t23, $t24, $t25, $t26, $t27, $t28, $t29, $t30, $t31, $t32, $t33, $t34, $t35, $t36, $t37, $t38, $t39, $t40, $t41, $t42, $t43, $t44, $t45, $t46, $t47, $t48, $t49, $t50, $t51, $t52, $t53, $t54, $t55, $t56, $t57, $t58, $t59, $t60, $t61 + let _s, s, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20, $t21, $t22, $t23, $t24, $t25, $t26, $t27, $t28, $t29, $t30, $t31, $t32, $t33, $t34, $t35, $t36, $t37, $t38, $t39, $t40, $t41, $t42, $t43, $t44, $t45, $t46, $t47, $t48, $t49, $t50, $t51, $t52, $t53, $t54, $t55, $t56, $t57, $t58, $t59 let $locals := $Malloc(64) let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t17 := 100 - $t17 := 100 - // abort($t17) - $Abort($t17) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t18 := borrow_local($t0) - $t18 := $MakePtr(false, _s) - // $t19 := borrow_field.a($t18) - $t19 := $IndexPtr($t18, 32) - // $t20 := read_ref($t19) - $t20 := $LoadU64($t19) - // $t21 := 42 - $t21 := 42 - // $t22 := ==($t20, $t21) - $t22 := $Eq($t20, $t21) - // if ($t22) goto L2 else goto L3 - switch $t22 - case 0 { $block := 5 } - default { $block := 6 } + // $t15 := 100 + $t15 := 100 + // abort($t15) + $Abort($t15) } case 4 { - // $t6 := 42 - $t6 := 42 - // $t7 := true - $t7 := true - // $t3 := M::pack_S($t6, $t7) - s := A2_M_pack_S($t6, $t7) - // $t8 := copy($t3) - $t8 := s - // $t9 := M::encode_S($t8) - $t9 := A2_M_encode_S($t8) - // $t0 := M::decode_S($t9) - _s := A2_M_decode_S($t9) - // $t10 := borrow_local($t3) - $t10 := $MakePtr(false, s) - // $t11 := borrow_field.a($t10) - $t11 := $IndexPtr($t10, 32) - // $t12 := read_ref($t11) - $t12 := $LoadU64($t11) - // $t13 := borrow_local($t0) - $t13 := $MakePtr(false, _s) - // $t14 := borrow_field.a($t13) - $t14 := $IndexPtr($t13, 32) - // $t15 := read_ref($t14) - $t15 := $LoadU64($t14) - // $t16 := ==($t12, $t15) - $t16 := $Eq($t12, $t15) - // if ($t16) goto L0 else goto L1 - switch $t16 - case 0 { $block := 2 } - default { $block := 3 } + // $t4 := 42 + $t4 := 42 + // $t5 := true + $t5 := true + // $t2 := M::pack_S($t4, $t5) + s := A2_M_pack_S($t4, $t5) + // $t6 := copy($t2) + $t6 := s + // $t7 := M::encode_S($t6) + $t7 := A2_M_encode_S($t6) + // $t0 := M::decode_S($t7) + _s := A2_M_decode_S($t7) + // $t8 := borrow_local($t2) + $t8 := $MakePtr(false, s) + // $t9 := borrow_field.a($t8) + $t9 := $IndexPtr($t8, 32) + // $t10 := read_ref($t9) + $t10 := $LoadU64($t9) + // $t11 := borrow_local($t0) + $t11 := $MakePtr(false, _s) + // $t12 := borrow_field.a($t11) + $t12 := $IndexPtr($t11, 32) + // $t13 := read_ref($t12) + $t13 := $LoadU64($t12) + // $t14 := ==($t10, $t13) + $t14 := $Eq($t10, $t13) + // if ($t14) goto L1 else goto L0 + switch $t14 + case 0 { $block := 3 } + default { $block := 2 } } case 5 { - // label L3 - // $t23 := 101 - $t23 := 101 - // abort($t23) - $Abort($t23) - } - case 6 { // label L2 - // $t24 := borrow_local($t3) - $t24 := $MakePtr(false, s) - // $t25 := borrow_field.b($t24) - $t25 := $IndexPtr($t24, 40) - // $t26 := read_ref($t25) - $t26 := $LoadU8($t25) - // $t27 := borrow_local($t0) - $t27 := $MakePtr(false, _s) - // $t28 := borrow_field.b($t27) - $t28 := $IndexPtr($t27, 40) - // $t29 := read_ref($t28) - $t29 := $LoadU8($t28) - // $t30 := ==($t26, $t29) - $t30 := $Eq($t26, $t29) - // if ($t30) goto L4 else goto L5 - switch $t30 + // $t16 := borrow_local($t0) + $t16 := $MakePtr(false, _s) + // $t17 := borrow_field.a($t16) + $t17 := $IndexPtr($t16, 32) + // $t18 := read_ref($t17) + $t18 := $LoadU64($t17) + // $t19 := 42 + $t19 := 42 + // $t20 := ==($t18, $t19) + $t20 := $Eq($t18, $t19) + // if ($t20) goto L4 else goto L3 + switch $t20 case 0 { $block := 7 } - default { $block := 8 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 } case 7 { - // label L5 - // $t31 := 102 - $t31 := 102 - // abort($t31) - $Abort($t31) + // label L3 + // $t21 := 101 + $t21 := 101 + // abort($t21) + $Abort($t21) } case 8 { - // label L4 - // $t32 := borrow_local($t0) - $t32 := $MakePtr(false, _s) - // $t33 := borrow_field.b($t32) - $t33 := $IndexPtr($t32, 40) - // $t34 := read_ref($t33) - $t34 := $LoadU8($t33) - // $t35 := true - $t35 := true - // $t36 := ==($t34, $t35) - $t36 := $Eq($t34, $t35) - // if ($t36) goto L6 else goto L7 - switch $t36 - case 0 { $block := 9 } - default { $block := 10 } + // label L5 + // $t22 := borrow_local($t2) + $t22 := $MakePtr(false, s) + // $t23 := borrow_field.b($t22) + $t23 := $IndexPtr($t22, 40) + // $t24 := read_ref($t23) + $t24 := $LoadU8($t23) + // $t25 := borrow_local($t0) + $t25 := $MakePtr(false, _s) + // $t26 := borrow_field.b($t25) + $t26 := $IndexPtr($t25, 40) + // $t27 := read_ref($t26) + $t27 := $LoadU8($t26) + // $t28 := ==($t24, $t27) + $t28 := $Eq($t24, $t27) + // if ($t28) goto L7 else goto L6 + switch $t28 + case 0 { $block := 10 } + default { $block := 9 } } case 9 { // label L7 - // $t37 := 103 - $t37 := 103 - // abort($t37) - $Abort($t37) + // goto L8 + $block := 11 } case 10 { // label L6 - // $t38 := borrow_local($t3) - $t38 := $MakePtr(false, s) - // $t39 := borrow_field.c($t38) - $t39 := $t38 - // $t4 := read_ref($t39) - mstore($locals, $LoadU256($t39)) - if $IsStoragePtr($t39){ + // $t29 := 102 + $t29 := 102 + // abort($t29) + $Abort($t29) + } + case 11 { + // label L8 + // $t30 := borrow_local($t0) + $t30 := $MakePtr(false, _s) + // $t31 := borrow_field.b($t30) + $t31 := $IndexPtr($t30, 40) + // $t32 := read_ref($t31) + $t32 := $LoadU8($t31) + // $t33 := true + $t33 := true + // $t34 := ==($t32, $t33) + $t34 := $Eq($t32, $t33) + // if ($t34) goto L10 else goto L9 + switch $t34 + case 0 { $block := 13 } + default { $block := 12 } + } + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 + // $t35 := 103 + $t35 := 103 + // abort($t35) + $Abort($t35) + } + case 14 { + // label L11 + // $t36 := borrow_local($t2) + $t36 := $MakePtr(false, s) + // $t37 := borrow_field.c($t36) + $t37 := $t36 + // $t3 := read_ref($t37) + mstore($locals, $LoadU256($t37)) + if $IsStoragePtr($t37){ let $storage_ptr_894856441 let $size_894856441 := $StorageLoadU64(mload($locals)) let $capacity_894856441 := $ClosestGreaterPowerOfTwo($size_894856441) @@ -1200,13 +1220,13 @@ object "test_A2_M_test_abi_S" { } mstore($locals, $storage_ptr_894856441) } - // $t40 := borrow_local($t0) - $t40 := $MakePtr(false, _s) - // $t41 := borrow_field.c($t40) - $t41 := $t40 - // $t1 := read_ref($t41) - mstore(add($locals, 32), $LoadU256($t41)) - if $IsStoragePtr($t41){ + // $t38 := borrow_local($t0) + $t38 := $MakePtr(false, _s) + // $t39 := borrow_field.c($t38) + $t39 := $t38 + // $t1 := read_ref($t39) + mstore(add($locals, 32), $LoadU256($t39)) + if $IsStoragePtr($t39){ let $storage_ptr_894856441 let $size_894856441 := $StorageLoadU64(mload(add($locals, 32))) let $capacity_894856441 := $ClosestGreaterPowerOfTwo($size_894856441) @@ -1242,82 +1262,97 @@ object "test_A2_M_test_abi_S" { } mstore(add($locals, 32), $storage_ptr_894856441) } - // $t42 := borrow_local($t4) - $t42 := $MakePtr(false, $locals) - // $t43 := vector::length($t42) - $t43 := A1_vector_length$A2_M_S2$($t42) - // $t44 := 1 - $t44 := 1 - // $t45 := ==($t43, $t44) - $t45 := $Eq($t43, $t44) - // if ($t45) goto L8 else goto L9 - switch $t45 - case 0 { $block := 11 } - default { $block := 12 } - } - case 11 { - // label L9 - // $t46 := 104 - $t46 := 104 - // abort($t46) - $Abort($t46) - } - case 12 { - // label L8 - // $t47 := borrow_local($t1) - $t47 := $MakePtr(false, add($locals, 32)) - // $t48 := vector::length($t47) - $t48 := A1_vector_length$A2_M_S2$($t47) - // $t49 := 1 - $t49 := 1 - // $t50 := ==($t48, $t49) - $t50 := $Eq($t48, $t49) - // if ($t50) goto L10 else goto L11 - switch $t50 - case 0 { $block := 13 } - default { $block := 14 } - } - case 13 { - // label L11 - // $t51 := 105 - $t51 := 105 - // abort($t51) - $Abort($t51) - } - case 14 { - // label L10 - // $t52 := borrow_local($t1) - $t52 := $MakePtr(false, add($locals, 32)) - // $t53 := 0 - $t53 := 0 - // $t54 := vector::borrow($t52, $t53) - $t54 := A1_vector_borrow$A2_M_S2$($t52, $t53) - // $t55 := borrow_field.x($t54) - $t55 := $t54 - // $t56 := 0 - $t56 := 0 - // $t57 := vector::borrow($t55, $t56) - $t57 := A1_vector_borrow$u128$($t55, $t56) - // $t58 := read_ref($t57) - $t58 := $LoadU128($t57) - // $t59 := 42 - $t59 := 42 - // $t60 := ==($t58, $t59) - $t60 := $Eq($t58, $t59) - // if ($t60) goto L12 else goto L13 - switch $t60 - case 0 { $block := 15 } - default { $block := 16 } + // $t40 := borrow_local($t3) + $t40 := $MakePtr(false, $locals) + // $t41 := vector::length($t40) + $t41 := A1_vector_length$A2_M_S2$($t40) + // $t42 := 1 + $t42 := 1 + // $t43 := ==($t41, $t42) + $t43 := $Eq($t41, $t42) + // if ($t43) goto L13 else goto L12 + switch $t43 + case 0 { $block := 16 } + default { $block := 15 } } case 15 { // label L13 - // $t61 := 106 - $t61 := 106 - // abort($t61) - $Abort($t61) + // goto L14 + $block := 17 } case 16 { // label L12 + // $t44 := 104 + $t44 := 104 + // abort($t44) + $Abort($t44) + } + case 17 { + // label L14 + // $t45 := borrow_local($t1) + $t45 := $MakePtr(false, add($locals, 32)) + // $t46 := vector::length($t45) + $t46 := A1_vector_length$A2_M_S2$($t45) + // $t47 := 1 + $t47 := 1 + // $t48 := ==($t46, $t47) + $t48 := $Eq($t46, $t47) + // if ($t48) goto L16 else goto L15 + switch $t48 + case 0 { $block := 19 } + default { $block := 18 } + } + case 18 { + // label L16 + // goto L17 + $block := 20 + } + case 19 { + // label L15 + // $t49 := 105 + $t49 := 105 + // abort($t49) + $Abort($t49) + } + case 20 { + // label L17 + // $t50 := borrow_local($t1) + $t50 := $MakePtr(false, add($locals, 32)) + // $t51 := 0 + $t51 := 0 + // $t52 := vector::borrow($t50, $t51) + $t52 := A1_vector_borrow$A2_M_S2$($t50, $t51) + // $t53 := borrow_field.x($t52) + $t53 := $t52 + // $t54 := 0 + $t54 := 0 + // $t55 := vector::borrow($t53, $t54) + $t55 := A1_vector_borrow$u128$($t53, $t54) + // $t56 := read_ref($t55) + $t56 := $LoadU128($t55) + // $t57 := 42 + $t57 := 42 + // $t58 := ==($t56, $t57) + $t58 := $Eq($t56, $t57) + // if ($t58) goto L19 else goto L18 + switch $t58 + case 0 { $block := 22 } + default { $block := 21 } + } + case 21 { + // label L19 + // goto L20 + $block := 23 + } + case 22 { + // label L18 + // $t59 := 106 + $t59 := 106 + // abort($t59) + $Abort($t59) + } + case 23 { + // label L20 // return () $Free($locals, 64) leave @@ -1950,7 +1985,7 @@ object "test_A2_M_test_abi_S" { } } } -===> Test result of M::test_abi_S: Succeed(Stopped) (used_gas=8318): [] +===> Test result of M::test_abi_S: Succeed(Stopped) (used_gas=10789): [] // test of M::test_abi_String /* ======================================= @@ -1964,175 +1999,205 @@ object "test_A2_M_test_abi_String" { A2_M_test_abi_String() return (0, 0) function A2_M_test_abi_String() { - let _str, end, i, str, v, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20, $t21, $t22, $t23, $t24, $t25, $t26, $t27, $t28, $t29, $t30, $t31, $t32, $t33, $t34, $t35, $t36, $t37 + let _str, end, i, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20, $t21, $t22, $t23, $t24, $t25, $t26, $t27, $t28, $t29, $t30, $t31, $t32, $t33, $t34, $t35 let $locals := $Malloc(64) let $block := 3 for {} true {} { switch $block case 2 { - // label L5 - // $t9 := <($t3, $t8) - $t9 := $Lt(i, $t8) - // if ($t9) goto L0 else goto L2 - switch $t9 + // label L6 + // $t7 := <($t3, $t6) + $t7 := $Lt(i, $t6) + // if ($t7) goto L1 else goto L0 + switch $t7 case 0 { $block := 5 } default { $block := 4 } } case 3 { - // $t7 := 0 - $t7 := 0 - // $t3 := $t7 - i := $t7 - // $t8 := 128 - $t8 := 128 - // $t6 := vector::empty() + // $t5 := 0 + $t5 := 0 + // $t3 := $t5 + i := $t5 + // $t6 := 128 + $t6 := 128 + // $t4 := vector::empty() mstore($locals, A1_vector_empty$u8$()) - // goto L5 + // goto L6 $block := 2 } case 4 { - // label L0 - // $t10 := ascii::is_valid_char($t3) - $t10 := A1_ascii_is_valid_char(i) - // if ($t10) goto L3 else goto L4 - switch $t10 - case 0 { $block := 6 } - default { $block := 7 } + // label L1 + // goto L2 + $block := 6 } case 5 { - // label L2 - // $t14 := move($t6) - $t14 := mload($locals) - // $t15 := ascii::string($t14) - $t15 := A1_ascii_string($t14) - // $t16 := M::encode_String($t15) - $t16 := A2_M_encode_String($t15) - // $t0 := M::decode_String($t16) - _str := A2_M_decode_String($t16) - // $t17 := borrow_local($t0) - $t17 := $MakePtr(false, _str) - // $t18 := ascii::as_bytes($t17) - $t18 := A1_ascii_as_bytes($t17) - // $t19 := vector::length($t18) - $t19 := A1_vector_length$u8$($t18) - // $t20 := 128 - $t20 := 128 - // $t21 := ==($t19, $t20) - $t21 := $Eq($t19, $t20) - // if ($t21) goto L6 else goto L7 - switch $t21 - case 0 { $block := 8 } - default { $block := 9 } + // label L0 + // $t12 := move($t4) + $t12 := mload($locals) + // $t13 := ascii::string($t12) + $t13 := A1_ascii_string($t12) + // $t14 := M::encode_String($t13) + $t14 := A2_M_encode_String($t13) + // $t0 := M::decode_String($t14) + _str := A2_M_decode_String($t14) + // $t15 := borrow_local($t0) + $t15 := $MakePtr(false, _str) + // $t16 := ascii::as_bytes($t15) + $t16 := A1_ascii_as_bytes($t15) + // $t17 := vector::length($t16) + $t17 := A1_vector_length$u8$($t16) + // $t18 := 128 + $t18 := 128 + // $t19 := ==($t17, $t18) + $t19 := $Eq($t17, $t18) + // if ($t19) goto L8 else goto L7 + switch $t19 + case 0 { $block := 11 } + default { $block := 10 } } case 6 { - // label L4 - // $t11 := 0 - $t11 := 0 - // abort($t11) - $Abort($t11) + // label L2 + // $t8 := ascii::is_valid_char($t3) + $t8 := A1_ascii_is_valid_char(i) + // if ($t8) goto L4 else goto L3 + switch $t8 + case 0 { $block := 8 } + default { $block := 7 } } case 7 { - // label L3 - // $t12 := borrow_local($t6) - $t12 := $MakePtr(false, $locals) - // vector::push_back($t12, $t3) - A1_vector_push_back$u8$($t12, i) - // $t13 := 1 - $t13 := 1 - // $t3 := +($t3, $t13) - i := $AddU8(i, $t13) + // label L4 // goto L5 - $block := 2 + $block := 9 } case 8 { - // label L7 - // $t22 := 100 - $t22 := 100 - // abort($t22) - $Abort($t22) + // label L3 + // $t9 := 0 + $t9 := 0 + // abort($t9) + $Abort($t9) } case 9 { - // label L6 - // $t23 := move($t0) - $t23 := _str - // $t1 := ascii::into_bytes($t23) - mstore(add($locals, 32), A1_ascii_into_bytes($t23)) - // $t24 := borrow_local($t1) - $t24 := $MakePtr(false, add($locals, 32)) - // $t25 := vector::length($t24) - $t25 := A1_vector_length$u8$($t24) - // $t26 := 128 - $t26 := 128 - // $t27 := ==($t25, $t26) - $t27 := $Eq($t25, $t26) - // if ($t27) goto L8 else goto L9 - switch $t27 - case 0 { $block := 10 } - default { $block := 11 } + // label L5 + // $t10 := borrow_local($t4) + $t10 := $MakePtr(false, $locals) + // vector::push_back($t10, $t3) + A1_vector_push_back$u8$($t10, i) + // $t11 := 1 + $t11 := 1 + // $t3 := +($t3, $t11) + i := $AddU8(i, $t11) + // goto L6 + $block := 2 } case 10 { - // label L9 - // $t28 := 99 - $t28 := 99 - // abort($t28) - $Abort($t28) - } - case 11 { // label L8 - // $t29 := 0 - $t29 := 0 - // $t3 := $t29 - i := $t29 - // goto L15 + // goto L9 $block := 12 } + case 11 { + // label L7 + // $t20 := 100 + $t20 := 100 + // abort($t20) + $Abort($t20) + } case 12 { - // label L15 - // $t30 := <($t3, $t8) - $t30 := $Lt(i, $t8) - // if ($t30) goto L10 else goto L12 - switch $t30 + // label L9 + // $t21 := move($t0) + $t21 := _str + // $t1 := ascii::into_bytes($t21) + mstore(add($locals, 32), A1_ascii_into_bytes($t21)) + // $t22 := borrow_local($t1) + $t22 := $MakePtr(false, add($locals, 32)) + // $t23 := vector::length($t22) + $t23 := A1_vector_length$u8$($t22) + // $t24 := 128 + $t24 := 128 + // $t25 := ==($t23, $t24) + $t25 := $Eq($t23, $t24) + // if ($t25) goto L11 else goto L10 + switch $t25 case 0 { $block := 14 } default { $block := 13 } } case 13 { - // label L10 - // $t31 := borrow_local($t1) - $t31 := $MakePtr(false, add($locals, 32)) - // $t32 := (u64)($t3) - $t32 := $CastU64(i) - // $t33 := vector::borrow($t31, $t32) - $t33 := A1_vector_borrow$u8$($t31, $t32) - // $t34 := read_ref($t33) - $t34 := $LoadU8($t33) - // $t35 := ==($t34, $t3) - $t35 := $Eq($t34, i) - // if ($t35) goto L13 else goto L14 - switch $t35 - case 0 { $block := 15 } - default { $block := 16 } + // label L11 + // goto L12 + $block := 15 } case 14 { - // label L12 - // return () - $Free($locals, 64) - leave + // label L10 + // $t26 := 99 + $t26 := 99 + // abort($t26) + $Abort($t26) } case 15 { - // label L14 - // $t36 := (u64)($t3) - $t36 := $CastU64(i) - // abort($t36) - $Abort($t36) + // label L12 + // $t27 := 0 + $t27 := 0 + // $t3 := $t27 + i := $t27 + // goto L19 + $block := 16 } case 16 { - // label L13 - // $t37 := 1 - $t37 := 1 - // $t3 := +($t3, $t37) - i := $AddU8(i, $t37) + // label L19 + // $t28 := <($t3, $t6) + $t28 := $Lt(i, $t6) + // if ($t28) goto L14 else goto L13 + switch $t28 + case 0 { $block := 18 } + default { $block := 17 } + } + case 17 { + // label L14 // goto L15 - $block := 12 + $block := 19 + } + case 18 { + // label L13 + // return () + $Free($locals, 64) + leave + } + case 19 { + // label L15 + // $t29 := borrow_local($t1) + $t29 := $MakePtr(false, add($locals, 32)) + // $t30 := (u64)($t3) + $t30 := $CastU64(i) + // $t31 := vector::borrow($t29, $t30) + $t31 := A1_vector_borrow$u8$($t29, $t30) + // $t32 := read_ref($t31) + $t32 := $LoadU8($t31) + // $t33 := ==($t32, $t3) + $t33 := $Eq($t32, i) + // if ($t33) goto L17 else goto L16 + switch $t33 + case 0 { $block := 21 } + default { $block := 20 } + } + case 20 { + // label L17 + // goto L18 + $block := 22 + } + case 21 { + // label L16 + // $t34 := (u64)($t3) + $t34 := $CastU64(i) + // abort($t34) + $Abort($t34) + } + case 22 { + // label L18 + // $t35 := 1 + $t35 := 1 + // $t3 := +($t3, $t35) + i := $AddU8(i, $t35) + // goto L19 + $block := 16 } } } @@ -2150,12 +2215,12 @@ object "test_A2_M_test_abi_String" { len := $LoadU64(v_ptr) } function A1_ascii_into_bytes(string) -> $result { - let bytes, $t2 - // $t2 := unpack ascii::String($t0) - $t2 := $MemoryLoadU256(add(string, 0)) + let $t1 + // $t1 := unpack ascii::String($t0) + $t1 := $MemoryLoadU256(add(string, 0)) $Free(string, 32) - // return $t2 - $result := $t2 + // return $t1 + $result := $t1 } function A1_vector_push_back$u8$(v_ref, e) { @@ -2172,6 +2237,16 @@ object "test_A2_M_test_abi_String" { $StoreU256(v_ref, new_v_offs) } } + function A1_ascii_is_valid_char(b) -> $result { + let $t1, $t2 + // $t1 := 127 + $t1 := 127 + // $t2 := <=($t0, $t1) + $t2 := $LtEq(b, $t1) + // return $t2 + $result := $t2 + } + function A1_ascii_as_bytes(string) -> $result { let $t1 // $t1 := borrow_field.bytes($t0) @@ -2207,20 +2282,15 @@ object "test_A2_M_test_abi_String" { switch $block case 2 { // label L1 - // $t4 := 0 - $t4 := 0 - // abort($t4) - $Abort($t4) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t5 := move($t1) - $t5 := x - // $t6 := option::destroy_some($t5) - $t6 := A1_option_destroy_some$A1_ascii_String$($t5) - // return $t6 - $result := $t6 - leave + // $t4 := 65536 + $t4 := 65536 + // abort($t4) + $Abort($t4) } case 4 { // $t1 := ascii::try_string($t0) @@ -2229,14 +2299,114 @@ object "test_A2_M_test_abi_String" { $t2 := $MakePtr(false, x) // $t3 := option::is_some($t2) $t3 := A1_option_is_some$A1_ascii_String$($t2) - // if ($t3) goto L0 else goto L1 + // if ($t3) goto L1 else goto L0 switch $t3 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t5 := move($t1) + $t5 := x + // $t6 := option::destroy_some($t5) + $t6 := A1_option_destroy_some$A1_ascii_String$($t5) + // return $t6 + $result := $t6 + leave + } + } + } + + function A1_option_destroy_some$A1_ascii_String$(t) -> $result { + let elem, $t3, $t4, $t5, $t6, $t7, $t8, $t9 + let $locals := $Malloc(32) + let $block := 4 + for {} true {} { + switch $block + case 2 { + // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 + // $t5 := 262145 + $t5 := 262145 + // abort($t5) + $Abort($t5) + } + case 4 { + // $t3 := borrow_local($t0) + $t3 := $MakePtr(false, t) + // $t4 := option::is_some<#0>($t3) + $t4 := A1_option_is_some$A1_ascii_String$($t3) + // if ($t4) goto L1 else goto L0 + switch $t4 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t6 := move($t0) + $t6 := t + // $t2 := unpack option::Option<#0>($t6) + mstore($locals, $MemoryLoadU256(add($t6, 0))) + $Free($t6, 32) + // $t7 := borrow_local($t2) + $t7 := $MakePtr(false, $locals) + // $t8 := vector::pop_back<#0>($t7) + $t8 := A1_vector_pop_back$A1_ascii_String$($t7) + // $t9 := move($t2) + $t9 := mload($locals) + // vector::destroy_empty<#0>($t9) + A1_vector_destroy_empty$A1_ascii_String$($t9) + // return $t8 + $result := $t8 + $Free($locals, 32) + leave } } } + function A1_vector_destroy_empty$A1_ascii_String$(v) { + let size := $MemoryLoadU64(v) + if $LogicalNot(iszero(size)) { $AbortBuiltin() } + let capacity := $MemoryLoadU64(add(v, 8)) + $Free(v, add(32, mul(capacity, 32))) + } + function A1_vector_pop_back$A1_ascii_String$(v_ref) -> e { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + let size := $LoadU64(v_ptr) + if iszero(size) { $AbortBuiltin() } + let e_ptr := $IndexPtr(v_ptr, add(32, mul(sub(size, 1), 32))) + e := $LoadU256(e_ptr) + if $IsStoragePtr(e_ptr) { + let e_offs := $OffsetPtr(e_ptr) + let linked_src := $AlignedStorageLoad(e_offs) + e := $Malloc(32) + { + let $linked_src_2300595445 := $AlignedStorageLoad(add(linked_src, 0)) + let $linked_dst_2300595445 + let $size_2300595445 := $StorageLoadU64($linked_src_2300595445) + let $capacity_2300595445 := $ClosestGreaterPowerOfTwo($size_2300595445) + $linked_dst_2300595445 := $Malloc(add(32, mul($capacity_2300595445, 1))) + let $data_size_2300595445 := mul($size_2300595445, 1) + mstore($linked_dst_2300595445, $AlignedStorageLoad($linked_src_2300595445)) + $MemoryStoreU64(add($linked_dst_2300595445, 8), $capacity_2300595445) + let $data_src_2300595445 := add($linked_src_2300595445, 32) + let $data_dst_2300595445 := add($linked_dst_2300595445, 32) + for { let $offs_2300595445 := 0 } lt($offs_2300595445, $data_size_2300595445) { $offs_2300595445 := add($offs_2300595445, 32)} { + mstore(add($data_dst_2300595445, $offs_2300595445), $AlignedStorageLoad(add($data_src_2300595445, $offs_2300595445))) + $AlignedStorageStore(add($data_src_2300595445, $offs_2300595445), 0) + } + mstore(add(e, 0), $linked_dst_2300595445) + $AlignedStorageStore(add(linked_src, 0), 0) + } + $AlignedStorageStore(e_offs, 0) + } + $StoreU64(v_ptr, sub(size, 1)) + } function A1_option_is_some$A1_ascii_String$(t) -> $result { let $t1, $t2, $t3 // $t1 := borrow_field>.vec($t0) @@ -2267,87 +2437,92 @@ object "test_A2_M_test_abi_String" { len := $LoadU64(v_ptr) } function A1_ascii_try_string(bytes) -> $result { - let i, len, possible_byte, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17 + let i, len, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16 let $locals := $Malloc(32) mstore($locals, bytes) let $block := 3 for {} true {} { switch $block case 2 { - // label L6 - // assert Le($t1, $t5) + // label L5 + // assert Le($t1, $t4) // assert forall j: Range(0, $t1): ascii::$is_valid_char(Index($t0, j)) - // $t7 := <($t1, $t5) - $t7 := $Lt(i, $t5) - // if ($t7) goto L0 else goto L2 - switch $t7 + // $t6 := <($t1, $t4) + $t6 := $Lt(i, $t4) + // if ($t6) goto L1 else goto L0 + switch $t6 case 0 { $block := 5 } default { $block := 4 } } case 3 { - // $t4 := borrow_local($t0) - $t4 := $MakePtr(false, $locals) - // $t5 := vector::length($t4) - $t5 := A1_vector_length$u8$($t4) - // $t6 := 0 - $t6 := 0 - // $t1 := $t6 - i := $t6 - // goto L6 + // $t3 := borrow_local($t0) + $t3 := $MakePtr(false, $locals) + // $t4 := vector::length($t3) + $t4 := A1_vector_length$u8$($t3) + // $t5 := 0 + $t5 := 0 + // $t1 := $t5 + i := $t5 + // goto L5 $block := 2 } case 4 { - // label L0 - // $t8 := borrow_local($t0) - $t8 := $MakePtr(false, $locals) - // $t9 := vector::borrow($t8, $t1) - $t9 := A1_vector_borrow$u8$($t8, i) - // $t10 := read_ref($t9) - $t10 := $LoadU8($t9) - // $t11 := ascii::is_valid_char($t10) - $t11 := A1_ascii_is_valid_char($t10) - // $t12 := !($t11) - $t12 := $LogicalNot($t11) - // if ($t12) goto L3 else goto L5 - switch $t12 - case 0 { $block := 7 } - default { $block := 6 } + // label L1 + // goto L2 + $block := 6 } case 5 { - // label L2 - // assert Eq($t1, $t5) - // assert forall j: Range(0, $t5): ascii::$is_valid_char(Index($t0, j)) - // $t15 := move($t0) - $t15 := mload($locals) - // $t16 := pack ascii::String($t15) + // label L0 + // assert Eq($t1, $t4) + // assert forall j: Range(0, $t4): ascii::$is_valid_char(Index($t0, j)) + // $t14 := move($t0) + $t14 := mload($locals) + // $t15 := pack ascii::String($t14) { let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t15) - $t16 := $mem + $MemoryStoreU256(add($mem, 0), $t14) + $t15 := $mem } - // $t17 := option::some($t16) - $t17 := A1_option_some$A1_ascii_String$($t16) - // return $t17 - $result := $t17 + // $t16 := option::some($t15) + $t16 := A1_option_some$A1_ascii_String$($t15) + // return $t16 + $result := $t16 $Free($locals, 32) leave } case 6 { - // label L3 - // $t13 := option::none() - $t13 := A1_option_none$A1_ascii_String$() - // return $t13 - $result := $t13 + // label L2 + // $t7 := borrow_local($t0) + $t7 := $MakePtr(false, $locals) + // $t8 := vector::borrow($t7, $t1) + $t8 := A1_vector_borrow$u8$($t7, i) + // $t9 := read_ref($t8) + $t9 := $LoadU8($t8) + // $t10 := ascii::is_valid_char($t9) + $t10 := A1_ascii_is_valid_char($t9) + // $t11 := !($t10) + $t11 := $LogicalNot($t10) + // if ($t11) goto L4 else goto L3 + switch $t11 + case 0 { $block := 8 } + default { $block := 7 } + } + case 7 { + // label L4 + // $t12 := option::none() + $t12 := A1_option_none$A1_ascii_String$() + // return $t12 + $result := $t12 $Free($locals, 32) leave } - case 7 { - // label L5 - // $t14 := 1 - $t14 := 1 - // $t1 := +($t1, $t14) - i := $AddU64(i, $t14) - // goto L6 + case 8 { + // label L3 + // $t13 := 1 + $t13 := 1 + // $t1 := +($t1, $t13) + i := $AddU64(i, $t13) + // goto L5 $block := 2 } } @@ -2435,101 +2610,6 @@ object "test_A2_M_test_abi_String" { $StoreU256(v_ref, new_v_offs) } } - function A1_ascii_is_valid_char(b) -> $result { - let $t1, $t2 - // $t1 := 127 - $t1 := 127 - // $t2 := <=($t0, $t1) - $t2 := $LtEq(b, $t1) - // return $t2 - $result := $t2 - } - - function A1_option_destroy_some$A1_ascii_String$(t) -> $result { - let elem, $t3, $t4, $t5, $t6, $t7, $t8, $t9 - let $locals := $Malloc(32) - let $block := 4 - for {} true {} { - switch $block - case 2 { - // label L1 - // $t5 := 1 - $t5 := 1 - // abort($t5) - $Abort($t5) - } - case 3 { - // label L0 - // $t6 := move($t0) - $t6 := t - // $t2 := unpack option::Option<#0>($t6) - mstore($locals, $MemoryLoadU256(add($t6, 0))) - $Free($t6, 32) - // $t7 := borrow_local($t2) - $t7 := $MakePtr(false, $locals) - // $t8 := vector::pop_back<#0>($t7) - $t8 := A1_vector_pop_back$A1_ascii_String$($t7) - // $t9 := move($t2) - $t9 := mload($locals) - // vector::destroy_empty<#0>($t9) - A1_vector_destroy_empty$A1_ascii_String$($t9) - // return $t8 - $result := $t8 - $Free($locals, 32) - leave - } - case 4 { - // $t3 := borrow_local($t0) - $t3 := $MakePtr(false, t) - // $t4 := option::is_some<#0>($t3) - $t4 := A1_option_is_some$A1_ascii_String$($t3) - // if ($t4) goto L0 else goto L1 - switch $t4 - case 0 { $block := 2 } - default { $block := 3 } - } - } - } - - function A1_vector_destroy_empty$A1_ascii_String$(v) { - let size := $MemoryLoadU64(v) - if $LogicalNot(iszero(size)) { $AbortBuiltin() } - let capacity := $MemoryLoadU64(add(v, 8)) - $Free(v, add(32, mul(capacity, 32))) - } - function A1_vector_pop_back$A1_ascii_String$(v_ref) -> e { - let v_offs := $LoadU256(v_ref) - let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) - let size := $LoadU64(v_ptr) - if iszero(size) { $AbortBuiltin() } - let e_ptr := $IndexPtr(v_ptr, add(32, mul(sub(size, 1), 32))) - e := $LoadU256(e_ptr) - if $IsStoragePtr(e_ptr) { - let e_offs := $OffsetPtr(e_ptr) - let linked_src := $AlignedStorageLoad(e_offs) - e := $Malloc(32) - { - let $linked_src_2300595445 := $AlignedStorageLoad(add(linked_src, 0)) - let $linked_dst_2300595445 - let $size_2300595445 := $StorageLoadU64($linked_src_2300595445) - let $capacity_2300595445 := $ClosestGreaterPowerOfTwo($size_2300595445) - $linked_dst_2300595445 := $Malloc(add(32, mul($capacity_2300595445, 1))) - let $data_size_2300595445 := mul($size_2300595445, 1) - mstore($linked_dst_2300595445, $AlignedStorageLoad($linked_src_2300595445)) - $MemoryStoreU64(add($linked_dst_2300595445, 8), $capacity_2300595445) - let $data_src_2300595445 := add($linked_src_2300595445, 32) - let $data_dst_2300595445 := add($linked_dst_2300595445, 32) - for { let $offs_2300595445 := 0 } lt($offs_2300595445, $data_size_2300595445) { $offs_2300595445 := add($offs_2300595445, 32)} { - mstore(add($data_dst_2300595445, $offs_2300595445), $AlignedStorageLoad(add($data_src_2300595445, $offs_2300595445))) - $AlignedStorageStore(add($data_src_2300595445, $offs_2300595445), 0) - } - mstore(add(e, 0), $linked_dst_2300595445) - $AlignedStorageStore(add(linked_src, 0), 0) - } - $AlignedStorageStore(e_offs, 0) - } - $StoreU64(v_ptr, sub(size, 1)) - } function A1_vector_empty$u8$() -> vector { vector := $Malloc(34) $MemoryStoreU64(add(vector, 8), 2) @@ -2891,4 +2971,4 @@ object "test_A2_M_test_abi_String" { } } } -===> Test result of M::test_abi_String: Succeed(Stopped) (used_gas=435789): [] +===> Test result of M::test_abi_String: Succeed(Stopped) (used_gas=646767): [] diff --git a/language/evm/move-to-yul/tests/TestExternalResult.exp b/language/evm/move-to-yul/tests/TestExternalResult.exp index f1b5be79cc..0efdfd0066 100644 --- a/language/evm/move-to-yul/tests/TestExternalResult.exp +++ b/language/evm/move-to-yul/tests/TestExternalResult.exp @@ -54,30 +54,16 @@ object "test_A2_M_extract_err_data" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t8 := 102 $t8 := 102 // abort($t8) $Abort($t8) } - case 3 { - // label L0 - // $t9 := move($t1) - $t9 := v2 - // $t2 := ExternalResult::unwrap_err_data($t9) - mstore(add($locals, 32), A2_ExternalResult_unwrap_err_data$u64$($t9)) - // $t10 := borrow_local($t2) - $t10 := $MakePtr(false, add($locals, 32)) - // $t11 := vector::length($t10) - $t11 := A1_vector_length$u8$($t10) - // $t12 := 1 - $t12 := 1 - // $t13 := ==($t11, $t12) - $t13 := $Eq($t11, $t12) - // if ($t13) goto L2 else goto L3 - switch $t13 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t0 := vector::empty() mstore($locals, A1_vector_empty$u8$()) @@ -95,20 +81,44 @@ object "test_A2_M_extract_err_data" { $t6 := $MakePtr(false, v2) // $t7 := ExternalResult::is_err_data($t6) $t7 := A2_ExternalResult_is_err_data$u64$($t6) - // if ($t7) goto L0 else goto L1 + // if ($t7) goto L1 else goto L0 switch $t7 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t9 := move($t1) + $t9 := v2 + // $t2 := ExternalResult::unwrap_err_data($t9) + mstore(add($locals, 32), A2_ExternalResult_unwrap_err_data$u64$($t9)) + // $t10 := borrow_local($t2) + $t10 := $MakePtr(false, add($locals, 32)) + // $t11 := vector::length($t10) + $t11 := A1_vector_length$u8$($t10) + // $t12 := 1 + $t12 := 1 + // $t13 := ==($t11, $t12) + $t13 := $Eq($t11, $t12) + // if ($t13) goto L4 else goto L3 + switch $t13 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t14 := 103 $t14 := 103 // abort($t14) $Abort($t14) } - case 6 { - // label L2 + case 8 { + // label L5 // $t15 := borrow_local($t2) $t15 := $MakePtr(false, add($locals, 32)) // $t16 := 0 @@ -121,20 +131,25 @@ object "test_A2_M_extract_err_data" { $t19 := 42 // $t20 := ==($t18, $t19) $t20 := $Eq($t18, $t19) - // if ($t20) goto L4 else goto L5 + // if ($t20) goto L7 else goto L6 switch $t20 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t21 := 104 $t21 := 104 // abort($t21) $Abort($t21) } - case 8 { - // label L4 + case 11 { + // label L8 // return () $Free($locals, 64) leave @@ -149,232 +164,29 @@ object "test_A2_M_extract_err_data" { if $GtEq(i, size) { $AbortBuiltin() } e_ptr := $IndexPtr(v_ptr, add(32, mul(i, 1))) } - function A2_ExternalResult_is_err_data$u64$(result) -> $result { - let $t1, $t2 - // $t1 := borrow_field>.err_data($t0) - { - let $field_ptr := $IndexPtr(result, 32) - $t1 := $MakePtr($IsStoragePtr($field_ptr), $LoadU256($field_ptr)) - } - // $t2 := option::is_some>($t1) - $t2 := A1_option_is_some$vec$u8$$($t1) - // return $t2 - $result := $t2 - } - - function A1_option_is_some$vec$u8$$(t) -> $result { - let $t1, $t2, $t3 - // $t1 := borrow_field>.vec($t0) - $t1 := t - // $t2 := vector::is_empty<#0>($t1) - $t2 := A1_vector_is_empty$vec$u8$$($t1) - // $t3 := !($t2) - $t3 := $LogicalNot($t2) - // return $t3 - $result := $t3 - } - - function A1_vector_is_empty$vec$u8$$(v) -> $result { - let $t1, $t2, $t3 - // $t1 := vector::length<#0>($t0) - $t1 := A1_vector_length$vec$u8$$(v) - // $t2 := 0 - $t2 := 0 - // $t3 := ==($t1, $t2) - $t3 := $Eq($t1, $t2) - // return $t3 - $result := $t3 - } - - function A1_vector_length$vec$u8$$(v_ref) -> len { - let v_offs := $LoadU256(v_ref) - let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) - len := $LoadU64(v_ptr) - } - function A2_M_pack_err_data$u64$(v) -> $result { - let $t1 - // $t1 := ExternalResult::err_data<#0>($t0) - $t1 := A2_ExternalResult_err_data$u64$(v) - // return $t1 - $result := $t1 - } - - function A2_ExternalResult_err_data$u64$(error) -> $result { - let $t1, $t2, $t3, $t4, $t5 - // $t1 := option::none<#0>() - $t1 := A1_option_none$u64$() - // $t2 := option::some>($t0) - $t2 := A1_option_some$vec$u8$$(error) - // $t3 := option::none>() - $t3 := A1_option_none$vec$u8$$() - // $t4 := option::none() - $t4 := A1_option_none$A2_U256_U256$() - // $t5 := pack ExternalResult::ExternalResult<#0>($t1, $t2, $t3, $t4) - { - let $mem := $Malloc(128) - $MemoryStoreU256(add($mem, 0), $t1) - $MemoryStoreU256(add($mem, 32), $t2) - $MemoryStoreU256(add($mem, 64), $t3) - $MemoryStoreU256(add($mem, 96), $t4) - $t5 := $mem - } - // return $t5 - $result := $t5 - } - - function A1_option_none$A2_U256_U256$() -> $result { - let $t0, $t1 - // $t0 := vector::empty<#0>() - $t0 := A1_vector_empty$A2_U256_U256$() - // $t1 := pack option::Option<#0>($t0) - { - let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t0) - $t1 := $mem - } - // return $t1 - $result := $t1 - } - - function A1_vector_empty$A2_U256_U256$() -> vector { - vector := $Malloc(96) - $MemoryStoreU64(add(vector, 8), 2) - } - function A1_option_none$vec$u8$$() -> $result { - let $t0, $t1 - // $t0 := vector::empty<#0>() - $t0 := A1_vector_empty$vec$u8$$() - // $t1 := pack option::Option<#0>($t0) - { - let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t0) - $t1 := $mem - } - // return $t1 - $result := $t1 - } - - function A1_vector_empty$vec$u8$$() -> vector { - vector := $Malloc(96) - $MemoryStoreU64(add(vector, 8), 2) - } - function A1_option_some$vec$u8$$(e) -> $result { - let $t1, $t2 - // $t1 := vector::singleton<#0>($t0) - $t1 := A1_vector_singleton$vec$u8$$(e) - // $t2 := pack option::Option<#0>($t1) - { - let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t1) - $t2 := $mem - } - // return $t2 - $result := $t2 - } - - function A1_vector_singleton$vec$u8$$(e) -> $result { - let $t2, $t3 - let $locals := $Malloc(32) - // $t1 := vector::empty<#0>() - mstore($locals, A1_vector_empty$vec$u8$$()) - // $t2 := borrow_local($t1) - $t2 := $MakePtr(false, $locals) - // vector::push_back<#0>($t2, $t0) - A1_vector_push_back$vec$u8$$($t2, e) - // $t3 := move($t1) - $t3 := mload($locals) - // return $t3 - $result := $t3 - $Free($locals, 32) - } - - function A1_vector_push_back$vec$u8$$(v_ref, e) { - let v_offs := $LoadU256(v_ref) - let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) - let size := $LoadU64(v_ptr) - let e_ptr := $IndexPtr(v_ptr, add(32, mul(size, 32))) - $StoreU256(e_ptr, e) - if $IsStoragePtr(e_ptr) { - let e_offs := $OffsetPtr(e_ptr) - let $linked_dst_2300595445 := $NewLinkedStorageBase(0x89204cf5) - let $size_2300595445 := $MemoryLoadU64(e) - let $data_size_2300595445 := mul($size_2300595445, 1) - $AlignedStorageStore($linked_dst_2300595445, mload(e)) - let $data_src_2300595445 := add(e, 32) - let $data_dst_2300595445 := add($linked_dst_2300595445, 32) - for { let $offs_2300595445 := 0 } lt($offs_2300595445, $data_size_2300595445) { $offs_2300595445 := add($offs_2300595445, 32)} { - $AlignedStorageStore(add($data_dst_2300595445, $offs_2300595445), mload(add($data_src_2300595445, $offs_2300595445))) - $Free(e, add($data_size_2300595445, 32)) - } - $AlignedStorageStore(e_offs, $linked_dst_2300595445) - } - size := add(size, 1) - $StoreU64(v_ptr, size) - let capacity := $LoadU64($IndexPtr(v_ptr, 8)) - if and(iszero($IsStoragePtr(v_ptr)), eq(size, capacity)) { - let new_v_offs := $ResizeVector(v_offs, capacity, 32) - $StoreU256(v_ref, new_v_offs) - } - } - function A1_option_none$u64$() -> $result { - let $t0, $t1 - // $t0 := vector::empty<#0>() - $t0 := A1_vector_empty$u64$() - // $t1 := pack option::Option<#0>($t0) - { - let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t0) - $t1 := $mem - } - // return $t1 - $result := $t1 - } - - function A1_vector_empty$u64$() -> vector { - vector := $Malloc(48) - $MemoryStoreU64(add(vector, 8), 2) - } - function A1_vector_push_back$u8$(v_ref, e) { - let v_offs := $LoadU256(v_ref) - let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) - let size := $LoadU64(v_ptr) - let e_ptr := $IndexPtr(v_ptr, add(32, mul(size, 1))) - $StoreU8(e_ptr, e) - size := add(size, 1) - $StoreU64(v_ptr, size) - let capacity := $LoadU64($IndexPtr(v_ptr, 8)) - if and(iszero($IsStoragePtr(v_ptr)), eq(size, capacity)) { - let new_v_offs := $ResizeVector(v_offs, capacity, 1) - $StoreU256(v_ref, new_v_offs) - } - } - function A1_vector_empty$u8$() -> vector { - vector := $Malloc(34) - $MemoryStoreU64(add(vector, 8), 2) - } function A1_vector_length$u8$(v_ref) -> len { let v_offs := $LoadU256(v_ref) let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) len := $LoadU64(v_ptr) } function A2_ExternalResult_unwrap_err_data$u64$(result) -> $result { - let err_data, err_reason, panic_code, value, $t5, $t6, $t7, $t8, $t9 - // ($t5, $t6, $t7, $t8) := unpack ExternalResult::ExternalResult<#0>($t0) - $t5 := $MemoryLoadU256(add(result, 0)) - $t6 := $MemoryLoadU256(add(result, 32)) - $t7 := $MemoryLoadU256(add(result, 64)) - $t8 := $MemoryLoadU256(add(result, 96)) + let err_data, err_reason, panic_code, $t4, $t5, $t6, $t7, $t8 + // ($t4, $t5, $t6, $t7) := unpack ExternalResult::ExternalResult<#0>($t0) + $t4 := $MemoryLoadU256(add(result, 0)) + $t5 := $MemoryLoadU256(add(result, 32)) + $t6 := $MemoryLoadU256(add(result, 64)) + $t7 := $MemoryLoadU256(add(result, 96)) $Free(result, 128) - // option::destroy_none<#0>($t5) - A1_option_destroy_none$u64$($t5) - // option::destroy_none>($t7) - A1_option_destroy_none$vec$u8$$($t7) - // option::destroy_none($t8) - A1_option_destroy_none$A2_U256_U256$($t8) - // $t9 := option::destroy_some>($t6) - $t9 := A1_option_destroy_some$vec$u8$$($t6) - // return $t9 - $result := $t9 + // option::destroy_none<#0>($t4) + A1_option_destroy_none$u64$($t4) + // option::destroy_none>($t6) + A1_option_destroy_none$vec$u8$$($t6) + // option::destroy_none($t7) + A1_option_destroy_none$A2_U256_U256$($t7) + // $t8 := option::destroy_some>($t5) + $t8 := A1_option_destroy_some$vec$u8$$($t5) + // return $t8 + $result := $t8 } function A1_option_destroy_some$vec$u8$$(t) -> $result { @@ -385,13 +197,28 @@ object "test_A2_M_extract_err_data" { switch $block case 2 { // label L1 - // $t5 := 1 - $t5 := 1 - // abort($t5) - $Abort($t5) + // goto L2 + $block := 5 } case 3 { // label L0 + // $t5 := 262145 + $t5 := 262145 + // abort($t5) + $Abort($t5) + } + case 4 { + // $t3 := borrow_local($t0) + $t3 := $MakePtr(false, t) + // $t4 := option::is_some<#0>($t3) + $t4 := A1_option_is_some$vec$u8$$($t3) + // if ($t4) goto L1 else goto L0 + switch $t4 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t6 := move($t0) $t6 := t // $t2 := unpack option::Option<#0>($t6) @@ -410,16 +237,6 @@ object "test_A2_M_extract_err_data" { $Free($locals, 32) leave } - case 4 { - // $t3 := borrow_local($t0) - $t3 := $MakePtr(false, t) - // $t4 := option::is_some<#0>($t3) - $t4 := A1_option_is_some$vec$u8$$($t3) - // if ($t4) goto L0 else goto L1 - switch $t4 - case 0 { $block := 2 } - default { $block := 3 } - } } } @@ -455,43 +272,83 @@ object "test_A2_M_extract_err_data" { } $StoreU64(v_ptr, sub(size, 1)) } + function A1_option_is_some$vec$u8$$(t) -> $result { + let $t1, $t2, $t3 + // $t1 := borrow_field>.vec($t0) + $t1 := t + // $t2 := vector::is_empty<#0>($t1) + $t2 := A1_vector_is_empty$vec$u8$$($t1) + // $t3 := !($t2) + $t3 := $LogicalNot($t2) + // return $t3 + $result := $t3 + } + + function A1_vector_is_empty$vec$u8$$(v) -> $result { + let $t1, $t2, $t3 + // $t1 := vector::length<#0>($t0) + $t1 := A1_vector_length$vec$u8$$(v) + // $t2 := 0 + $t2 := 0 + // $t3 := ==($t1, $t2) + $t3 := $Eq($t1, $t2) + // return $t3 + $result := $t3 + } + + function A1_vector_length$vec$u8$$(v_ref) -> len { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + len := $LoadU64(v_ptr) + } function A1_option_destroy_none$A2_U256_U256$(t) { - let vec, $t2, $t3, $t4, $t5, $t6 + let $t1, $t2, $t3, $t4, $t5 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t4 := 0 - $t4 := 0 - // abort($t4) - $Abort($t4) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t5 := move($t0) - $t5 := t - // $t6 := unpack option::Option<#0>($t5) - $t6 := $MemoryLoadU256(add($t5, 0)) - $Free($t5, 32) - // vector::destroy_empty<#0>($t6) - A1_vector_destroy_empty$A2_U256_U256$($t6) - // return () - leave + // $t3 := 262144 + $t3 := 262144 + // abort($t3) + $Abort($t3) } case 4 { - // $t2 := borrow_local($t0) - $t2 := $MakePtr(false, t) - // $t3 := option::is_none<#0>($t2) - $t3 := A1_option_is_none$A2_U256_U256$($t2) - // if ($t3) goto L0 else goto L1 - switch $t3 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := borrow_local($t0) + $t1 := $MakePtr(false, t) + // $t2 := option::is_none<#0>($t1) + $t2 := A1_option_is_none$A2_U256_U256$($t1) + // if ($t2) goto L1 else goto L0 + switch $t2 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t4 := move($t0) + $t4 := t + // $t5 := unpack option::Option<#0>($t4) + $t5 := $MemoryLoadU256(add($t4, 0)) + $Free($t4, 32) + // vector::destroy_empty<#0>($t5) + A1_vector_destroy_empty$A2_U256_U256$($t5) + // return () + leave } } } + function A1_vector_destroy_empty$A2_U256_U256$(v) { + let size := $MemoryLoadU64(v) + if $LogicalNot(iszero(size)) { $AbortBuiltin() } + let capacity := $MemoryLoadU64(add(v, 8)) + $Free(v, add(32, mul(capacity, 32))) + } function A1_option_is_none$A2_U256_U256$(t) -> $result { let $t1, $t2 // $t1 := borrow_field>.vec($t0) @@ -519,45 +376,44 @@ object "test_A2_M_extract_err_data" { let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) len := $LoadU64(v_ptr) } - function A1_vector_destroy_empty$A2_U256_U256$(v) { - let size := $MemoryLoadU64(v) - if $LogicalNot(iszero(size)) { $AbortBuiltin() } - let capacity := $MemoryLoadU64(add(v, 8)) - $Free(v, add(32, mul(capacity, 32))) - } function A1_option_destroy_none$vec$u8$$(t) { - let vec, $t2, $t3, $t4, $t5, $t6 + let $t1, $t2, $t3, $t4, $t5 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t4 := 0 - $t4 := 0 - // abort($t4) - $Abort($t4) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t5 := move($t0) - $t5 := t - // $t6 := unpack option::Option<#0>($t5) - $t6 := $MemoryLoadU256(add($t5, 0)) - $Free($t5, 32) - // vector::destroy_empty<#0>($t6) - A1_vector_destroy_empty$vec$u8$$($t6) - // return () - leave + // $t3 := 262144 + $t3 := 262144 + // abort($t3) + $Abort($t3) } case 4 { - // $t2 := borrow_local($t0) - $t2 := $MakePtr(false, t) - // $t3 := option::is_none<#0>($t2) - $t3 := A1_option_is_none$vec$u8$$($t2) - // if ($t3) goto L0 else goto L1 - switch $t3 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := borrow_local($t0) + $t1 := $MakePtr(false, t) + // $t2 := option::is_none<#0>($t1) + $t2 := A1_option_is_none$vec$u8$$($t1) + // if ($t2) goto L1 else goto L0 + switch $t2 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t4 := move($t0) + $t4 := t + // $t5 := unpack option::Option<#0>($t4) + $t5 := $MemoryLoadU256(add($t4, 0)) + $Free($t4, 32) + // vector::destroy_empty<#0>($t5) + A1_vector_destroy_empty$vec$u8$$($t5) + // return () + leave } } } @@ -573,42 +429,53 @@ object "test_A2_M_extract_err_data" { } function A1_option_destroy_none$u64$(t) { - let vec, $t2, $t3, $t4, $t5, $t6 + let $t1, $t2, $t3, $t4, $t5 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t4 := 0 - $t4 := 0 - // abort($t4) - $Abort($t4) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t5 := move($t0) - $t5 := t - // $t6 := unpack option::Option<#0>($t5) - $t6 := $MemoryLoadU256(add($t5, 0)) - $Free($t5, 32) - // vector::destroy_empty<#0>($t6) - A1_vector_destroy_empty$u64$($t6) - // return () - leave + // $t3 := 262144 + $t3 := 262144 + // abort($t3) + $Abort($t3) } case 4 { - // $t2 := borrow_local($t0) - $t2 := $MakePtr(false, t) - // $t3 := option::is_none<#0>($t2) - $t3 := A1_option_is_none$u64$($t2) - // if ($t3) goto L0 else goto L1 - switch $t3 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := borrow_local($t0) + $t1 := $MakePtr(false, t) + // $t2 := option::is_none<#0>($t1) + $t2 := A1_option_is_none$u64$($t1) + // if ($t2) goto L1 else goto L0 + switch $t2 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t4 := move($t0) + $t4 := t + // $t5 := unpack option::Option<#0>($t4) + $t5 := $MemoryLoadU256(add($t4, 0)) + $Free($t4, 32) + // vector::destroy_empty<#0>($t5) + A1_vector_destroy_empty$u64$($t5) + // return () + leave } } } + function A1_vector_destroy_empty$u64$(v) { + let size := $MemoryLoadU64(v) + if $LogicalNot(iszero(size)) { $AbortBuiltin() } + let capacity := $MemoryLoadU64(add(v, 8)) + $Free(v, add(32, mul(capacity, 8))) + } function A1_option_is_none$u64$(t) -> $result { let $t1, $t2 // $t1 := borrow_field>.vec($t0) @@ -636,11 +503,179 @@ object "test_A2_M_extract_err_data" { let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) len := $LoadU64(v_ptr) } - function A1_vector_destroy_empty$u64$(v) { - let size := $MemoryLoadU64(v) - if $LogicalNot(iszero(size)) { $AbortBuiltin() } - let capacity := $MemoryLoadU64(add(v, 8)) - $Free(v, add(32, mul(capacity, 8))) + function A2_ExternalResult_is_err_data$u64$(result) -> $result { + let $t1, $t2 + // $t1 := borrow_field>.err_data($t0) + { + let $field_ptr := $IndexPtr(result, 32) + $t1 := $MakePtr($IsStoragePtr($field_ptr), $LoadU256($field_ptr)) + } + // $t2 := option::is_some>($t1) + $t2 := A1_option_is_some$vec$u8$$($t1) + // return $t2 + $result := $t2 + } + + function A2_M_pack_err_data$u64$(v) -> $result { + let $t1 + // $t1 := ExternalResult::err_data<#0>($t0) + $t1 := A2_ExternalResult_err_data$u64$(v) + // return $t1 + $result := $t1 + } + + function A2_ExternalResult_err_data$u64$(error) -> $result { + let $t1, $t2, $t3, $t4, $t5 + // $t1 := option::none<#0>() + $t1 := A1_option_none$u64$() + // $t2 := option::some>($t0) + $t2 := A1_option_some$vec$u8$$(error) + // $t3 := option::none>() + $t3 := A1_option_none$vec$u8$$() + // $t4 := option::none() + $t4 := A1_option_none$A2_U256_U256$() + // $t5 := pack ExternalResult::ExternalResult<#0>($t1, $t2, $t3, $t4) + { + let $mem := $Malloc(128) + $MemoryStoreU256(add($mem, 0), $t1) + $MemoryStoreU256(add($mem, 32), $t2) + $MemoryStoreU256(add($mem, 64), $t3) + $MemoryStoreU256(add($mem, 96), $t4) + $t5 := $mem + } + // return $t5 + $result := $t5 + } + + function A1_option_none$A2_U256_U256$() -> $result { + let $t0, $t1 + // $t0 := vector::empty<#0>() + $t0 := A1_vector_empty$A2_U256_U256$() + // $t1 := pack option::Option<#0>($t0) + { + let $mem := $Malloc(32) + $MemoryStoreU256(add($mem, 0), $t0) + $t1 := $mem + } + // return $t1 + $result := $t1 + } + + function A1_vector_empty$A2_U256_U256$() -> vector { + vector := $Malloc(96) + $MemoryStoreU64(add(vector, 8), 2) + } + function A1_option_none$vec$u8$$() -> $result { + let $t0, $t1 + // $t0 := vector::empty<#0>() + $t0 := A1_vector_empty$vec$u8$$() + // $t1 := pack option::Option<#0>($t0) + { + let $mem := $Malloc(32) + $MemoryStoreU256(add($mem, 0), $t0) + $t1 := $mem + } + // return $t1 + $result := $t1 + } + + function A1_vector_empty$vec$u8$$() -> vector { + vector := $Malloc(96) + $MemoryStoreU64(add(vector, 8), 2) + } + function A1_option_some$vec$u8$$(e) -> $result { + let $t1, $t2 + // $t1 := vector::singleton<#0>($t0) + $t1 := A1_vector_singleton$vec$u8$$(e) + // $t2 := pack option::Option<#0>($t1) + { + let $mem := $Malloc(32) + $MemoryStoreU256(add($mem, 0), $t1) + $t2 := $mem + } + // return $t2 + $result := $t2 + } + + function A1_vector_singleton$vec$u8$$(e) -> $result { + let $t2, $t3 + let $locals := $Malloc(32) + // $t1 := vector::empty<#0>() + mstore($locals, A1_vector_empty$vec$u8$$()) + // $t2 := borrow_local($t1) + $t2 := $MakePtr(false, $locals) + // vector::push_back<#0>($t2, $t0) + A1_vector_push_back$vec$u8$$($t2, e) + // $t3 := move($t1) + $t3 := mload($locals) + // return $t3 + $result := $t3 + $Free($locals, 32) + } + + function A1_vector_push_back$vec$u8$$(v_ref, e) { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + let size := $LoadU64(v_ptr) + let e_ptr := $IndexPtr(v_ptr, add(32, mul(size, 32))) + $StoreU256(e_ptr, e) + if $IsStoragePtr(e_ptr) { + let e_offs := $OffsetPtr(e_ptr) + let $linked_dst_2300595445 := $NewLinkedStorageBase(0x89204cf5) + let $size_2300595445 := $MemoryLoadU64(e) + let $data_size_2300595445 := mul($size_2300595445, 1) + $AlignedStorageStore($linked_dst_2300595445, mload(e)) + let $data_src_2300595445 := add(e, 32) + let $data_dst_2300595445 := add($linked_dst_2300595445, 32) + for { let $offs_2300595445 := 0 } lt($offs_2300595445, $data_size_2300595445) { $offs_2300595445 := add($offs_2300595445, 32)} { + $AlignedStorageStore(add($data_dst_2300595445, $offs_2300595445), mload(add($data_src_2300595445, $offs_2300595445))) + $Free(e, add($data_size_2300595445, 32)) + } + $AlignedStorageStore(e_offs, $linked_dst_2300595445) + } + size := add(size, 1) + $StoreU64(v_ptr, size) + let capacity := $LoadU64($IndexPtr(v_ptr, 8)) + if and(iszero($IsStoragePtr(v_ptr)), eq(size, capacity)) { + let new_v_offs := $ResizeVector(v_offs, capacity, 32) + $StoreU256(v_ref, new_v_offs) + } + } + function A1_option_none$u64$() -> $result { + let $t0, $t1 + // $t0 := vector::empty<#0>() + $t0 := A1_vector_empty$u64$() + // $t1 := pack option::Option<#0>($t0) + { + let $mem := $Malloc(32) + $MemoryStoreU256(add($mem, 0), $t0) + $t1 := $mem + } + // return $t1 + $result := $t1 + } + + function A1_vector_empty$u64$() -> vector { + vector := $Malloc(48) + $MemoryStoreU64(add(vector, 8), 2) + } + function A1_vector_push_back$u8$(v_ref, e) { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + let size := $LoadU64(v_ptr) + let e_ptr := $IndexPtr(v_ptr, add(32, mul(size, 1))) + $StoreU8(e_ptr, e) + size := add(size, 1) + $StoreU64(v_ptr, size) + let capacity := $LoadU64($IndexPtr(v_ptr, 8)) + if and(iszero($IsStoragePtr(v_ptr)), eq(size, capacity)) { + let new_v_offs := $ResizeVector(v_offs, capacity, 1) + $StoreU256(v_ref, new_v_offs) + } + } + function A1_vector_empty$u8$() -> vector { + vector := $Malloc(34) + $MemoryStoreU64(add(vector, 8), 2) } function $Abort(code) { mstore(0, code) @@ -909,7 +944,7 @@ object "test_A2_M_extract_err_data" { } } } -===> Test result of M::extract_err_data: Succeed(Stopped) (used_gas=6011): [] +===> Test result of M::extract_err_data: Succeed(Stopped) (used_gas=6994): [] // test of M::extract_err_reason /* ======================================= @@ -930,30 +965,16 @@ object "test_A2_M_extract_err_reason" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t8 := 105 $t8 := 105 // abort($t8) $Abort($t8) } - case 3 { - // label L0 - // $t9 := move($t1) - $t9 := v2 - // $t2 := ExternalResult::unwrap_err_reason($t9) - mstore(add($locals, 32), A2_ExternalResult_unwrap_err_reason$u64$($t9)) - // $t10 := borrow_local($t2) - $t10 := $MakePtr(false, add($locals, 32)) - // $t11 := vector::length($t10) - $t11 := A1_vector_length$u8$($t10) - // $t12 := 1 - $t12 := 1 - // $t13 := ==($t11, $t12) - $t13 := $Eq($t11, $t12) - // if ($t13) goto L2 else goto L3 - switch $t13 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t0 := vector::empty() mstore($locals, A1_vector_empty$u8$()) @@ -971,20 +992,44 @@ object "test_A2_M_extract_err_reason" { $t6 := $MakePtr(false, v2) // $t7 := ExternalResult::is_err_reason($t6) $t7 := A2_ExternalResult_is_err_reason$u64$($t6) - // if ($t7) goto L0 else goto L1 + // if ($t7) goto L1 else goto L0 switch $t7 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t9 := move($t1) + $t9 := v2 + // $t2 := ExternalResult::unwrap_err_reason($t9) + mstore(add($locals, 32), A2_ExternalResult_unwrap_err_reason$u64$($t9)) + // $t10 := borrow_local($t2) + $t10 := $MakePtr(false, add($locals, 32)) + // $t11 := vector::length($t10) + $t11 := A1_vector_length$u8$($t10) + // $t12 := 1 + $t12 := 1 + // $t13 := ==($t11, $t12) + $t13 := $Eq($t11, $t12) + // if ($t13) goto L4 else goto L3 + switch $t13 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t14 := 106 $t14 := 106 // abort($t14) $Abort($t14) } - case 6 { - // label L2 + case 8 { + // label L5 // $t15 := borrow_local($t2) $t15 := $MakePtr(false, add($locals, 32)) // $t16 := 0 @@ -997,236 +1042,38 @@ object "test_A2_M_extract_err_reason" { $t19 := 42 // $t20 := ==($t18, $t19) $t20 := $Eq($t18, $t19) - // if ($t20) goto L4 else goto L5 + // if ($t20) goto L7 else goto L6 switch $t20 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t21 := 107 $t21 := 107 // abort($t21) $Abort($t21) } - case 8 { - // label L4 + case 11 { + // label L8 // return () - $Free($locals, 64) - leave - } - } - } - - function A1_vector_borrow$u8$(v_ref, i) -> e_ptr { - let v_offs := $LoadU256(v_ref) - let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) - let size := $LoadU64(v_ptr) - if $GtEq(i, size) { $AbortBuiltin() } - e_ptr := $IndexPtr(v_ptr, add(32, mul(i, 1))) - } - function A2_ExternalResult_is_err_reason$u64$(result) -> $result { - let $t1, $t2 - // $t1 := borrow_field>.err_reason($t0) - { - let $field_ptr := $IndexPtr(result, 64) - $t1 := $MakePtr($IsStoragePtr($field_ptr), $LoadU256($field_ptr)) - } - // $t2 := option::is_some>($t1) - $t2 := A1_option_is_some$vec$u8$$($t1) - // return $t2 - $result := $t2 - } - - function A1_option_is_some$vec$u8$$(t) -> $result { - let $t1, $t2, $t3 - // $t1 := borrow_field>.vec($t0) - $t1 := t - // $t2 := vector::is_empty<#0>($t1) - $t2 := A1_vector_is_empty$vec$u8$$($t1) - // $t3 := !($t2) - $t3 := $LogicalNot($t2) - // return $t3 - $result := $t3 - } - - function A1_vector_is_empty$vec$u8$$(v) -> $result { - let $t1, $t2, $t3 - // $t1 := vector::length<#0>($t0) - $t1 := A1_vector_length$vec$u8$$(v) - // $t2 := 0 - $t2 := 0 - // $t3 := ==($t1, $t2) - $t3 := $Eq($t1, $t2) - // return $t3 - $result := $t3 - } - - function A1_vector_length$vec$u8$$(v_ref) -> len { - let v_offs := $LoadU256(v_ref) - let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) - len := $LoadU64(v_ptr) - } - function A2_M_pack_err_reason$u64$(v) -> $result { - let $t1 - // $t1 := ExternalResult::err_reason<#0>($t0) - $t1 := A2_ExternalResult_err_reason$u64$(v) - // return $t1 - $result := $t1 - } - - function A2_ExternalResult_err_reason$u64$(error) -> $result { - let tmp_$1, tmp_$2, tmp_$3, tmp_$4, $t5, $t6, $t7, $t8, $t9 - // $t5 := option::none<#0>() - $t5 := A1_option_none$u64$() - // $t6 := option::some>($t0) - $t6 := A1_option_some$vec$u8$$(error) - // $t7 := option::none>() - $t7 := A1_option_none$vec$u8$$() - // $t8 := option::none() - $t8 := A1_option_none$A2_U256_U256$() - // $t9 := pack ExternalResult::ExternalResult<#0>($t5, $t7, $t6, $t8) - { - let $mem := $Malloc(128) - $MemoryStoreU256(add($mem, 0), $t5) - $MemoryStoreU256(add($mem, 32), $t7) - $MemoryStoreU256(add($mem, 64), $t6) - $MemoryStoreU256(add($mem, 96), $t8) - $t9 := $mem - } - // return $t9 - $result := $t9 - } - - function A1_option_none$A2_U256_U256$() -> $result { - let $t0, $t1 - // $t0 := vector::empty<#0>() - $t0 := A1_vector_empty$A2_U256_U256$() - // $t1 := pack option::Option<#0>($t0) - { - let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t0) - $t1 := $mem - } - // return $t1 - $result := $t1 - } - - function A1_vector_empty$A2_U256_U256$() -> vector { - vector := $Malloc(96) - $MemoryStoreU64(add(vector, 8), 2) - } - function A1_option_none$vec$u8$$() -> $result { - let $t0, $t1 - // $t0 := vector::empty<#0>() - $t0 := A1_vector_empty$vec$u8$$() - // $t1 := pack option::Option<#0>($t0) - { - let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t0) - $t1 := $mem - } - // return $t1 - $result := $t1 - } - - function A1_vector_empty$vec$u8$$() -> vector { - vector := $Malloc(96) - $MemoryStoreU64(add(vector, 8), 2) - } - function A1_option_some$vec$u8$$(e) -> $result { - let $t1, $t2 - // $t1 := vector::singleton<#0>($t0) - $t1 := A1_vector_singleton$vec$u8$$(e) - // $t2 := pack option::Option<#0>($t1) - { - let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t1) - $t2 := $mem - } - // return $t2 - $result := $t2 - } - - function A1_vector_singleton$vec$u8$$(e) -> $result { - let $t2, $t3 - let $locals := $Malloc(32) - // $t1 := vector::empty<#0>() - mstore($locals, A1_vector_empty$vec$u8$$()) - // $t2 := borrow_local($t1) - $t2 := $MakePtr(false, $locals) - // vector::push_back<#0>($t2, $t0) - A1_vector_push_back$vec$u8$$($t2, e) - // $t3 := move($t1) - $t3 := mload($locals) - // return $t3 - $result := $t3 - $Free($locals, 32) - } - - function A1_vector_push_back$vec$u8$$(v_ref, e) { - let v_offs := $LoadU256(v_ref) - let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) - let size := $LoadU64(v_ptr) - let e_ptr := $IndexPtr(v_ptr, add(32, mul(size, 32))) - $StoreU256(e_ptr, e) - if $IsStoragePtr(e_ptr) { - let e_offs := $OffsetPtr(e_ptr) - let $linked_dst_2300595445 := $NewLinkedStorageBase(0x89204cf5) - let $size_2300595445 := $MemoryLoadU64(e) - let $data_size_2300595445 := mul($size_2300595445, 1) - $AlignedStorageStore($linked_dst_2300595445, mload(e)) - let $data_src_2300595445 := add(e, 32) - let $data_dst_2300595445 := add($linked_dst_2300595445, 32) - for { let $offs_2300595445 := 0 } lt($offs_2300595445, $data_size_2300595445) { $offs_2300595445 := add($offs_2300595445, 32)} { - $AlignedStorageStore(add($data_dst_2300595445, $offs_2300595445), mload(add($data_src_2300595445, $offs_2300595445))) - $Free(e, add($data_size_2300595445, 32)) - } - $AlignedStorageStore(e_offs, $linked_dst_2300595445) - } - size := add(size, 1) - $StoreU64(v_ptr, size) - let capacity := $LoadU64($IndexPtr(v_ptr, 8)) - if and(iszero($IsStoragePtr(v_ptr)), eq(size, capacity)) { - let new_v_offs := $ResizeVector(v_offs, capacity, 32) - $StoreU256(v_ref, new_v_offs) - } - } - function A1_option_none$u64$() -> $result { - let $t0, $t1 - // $t0 := vector::empty<#0>() - $t0 := A1_vector_empty$u64$() - // $t1 := pack option::Option<#0>($t0) - { - let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t0) - $t1 := $mem + $Free($locals, 64) + leave + } } - // return $t1 - $result := $t1 } - function A1_vector_empty$u64$() -> vector { - vector := $Malloc(48) - $MemoryStoreU64(add(vector, 8), 2) - } - function A1_vector_push_back$u8$(v_ref, e) { + function A1_vector_borrow$u8$(v_ref, i) -> e_ptr { let v_offs := $LoadU256(v_ref) let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) let size := $LoadU64(v_ptr) - let e_ptr := $IndexPtr(v_ptr, add(32, mul(size, 1))) - $StoreU8(e_ptr, e) - size := add(size, 1) - $StoreU64(v_ptr, size) - let capacity := $LoadU64($IndexPtr(v_ptr, 8)) - if and(iszero($IsStoragePtr(v_ptr)), eq(size, capacity)) { - let new_v_offs := $ResizeVector(v_offs, capacity, 1) - $StoreU256(v_ref, new_v_offs) - } - } - function A1_vector_empty$u8$() -> vector { - vector := $Malloc(34) - $MemoryStoreU64(add(vector, 8), 2) + if $GtEq(i, size) { $AbortBuiltin() } + e_ptr := $IndexPtr(v_ptr, add(32, mul(i, 1))) } function A1_vector_length$u8$(v_ref) -> len { let v_offs := $LoadU256(v_ref) @@ -1234,23 +1081,23 @@ object "test_A2_M_extract_err_reason" { len := $LoadU64(v_ptr) } function A2_ExternalResult_unwrap_err_reason$u64$(result) -> $result { - let err_data, err_reason, panic_code, value, $t5, $t6, $t7, $t8, $t9 - // ($t5, $t6, $t7, $t8) := unpack ExternalResult::ExternalResult<#0>($t0) - $t5 := $MemoryLoadU256(add(result, 0)) - $t6 := $MemoryLoadU256(add(result, 32)) - $t7 := $MemoryLoadU256(add(result, 64)) - $t8 := $MemoryLoadU256(add(result, 96)) + let err_data, err_reason, panic_code, $t4, $t5, $t6, $t7, $t8 + // ($t4, $t5, $t6, $t7) := unpack ExternalResult::ExternalResult<#0>($t0) + $t4 := $MemoryLoadU256(add(result, 0)) + $t5 := $MemoryLoadU256(add(result, 32)) + $t6 := $MemoryLoadU256(add(result, 64)) + $t7 := $MemoryLoadU256(add(result, 96)) $Free(result, 128) - // option::destroy_none<#0>($t5) - A1_option_destroy_none$u64$($t5) - // option::destroy_none>($t6) - A1_option_destroy_none$vec$u8$$($t6) - // option::destroy_none($t8) - A1_option_destroy_none$A2_U256_U256$($t8) - // $t9 := option::destroy_some>($t7) - $t9 := A1_option_destroy_some$vec$u8$$($t7) - // return $t9 - $result := $t9 + // option::destroy_none<#0>($t4) + A1_option_destroy_none$u64$($t4) + // option::destroy_none>($t5) + A1_option_destroy_none$vec$u8$$($t5) + // option::destroy_none($t7) + A1_option_destroy_none$A2_U256_U256$($t7) + // $t8 := option::destroy_some>($t6) + $t8 := A1_option_destroy_some$vec$u8$$($t6) + // return $t8 + $result := $t8 } function A1_option_destroy_some$vec$u8$$(t) -> $result { @@ -1261,13 +1108,28 @@ object "test_A2_M_extract_err_reason" { switch $block case 2 { // label L1 - // $t5 := 1 - $t5 := 1 - // abort($t5) - $Abort($t5) + // goto L2 + $block := 5 } case 3 { // label L0 + // $t5 := 262145 + $t5 := 262145 + // abort($t5) + $Abort($t5) + } + case 4 { + // $t3 := borrow_local($t0) + $t3 := $MakePtr(false, t) + // $t4 := option::is_some<#0>($t3) + $t4 := A1_option_is_some$vec$u8$$($t3) + // if ($t4) goto L1 else goto L0 + switch $t4 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t6 := move($t0) $t6 := t // $t2 := unpack option::Option<#0>($t6) @@ -1286,16 +1148,6 @@ object "test_A2_M_extract_err_reason" { $Free($locals, 32) leave } - case 4 { - // $t3 := borrow_local($t0) - $t3 := $MakePtr(false, t) - // $t4 := option::is_some<#0>($t3) - $t4 := A1_option_is_some$vec$u8$$($t3) - // if ($t4) goto L0 else goto L1 - switch $t4 - case 0 { $block := 2 } - default { $block := 3 } - } } } @@ -1331,43 +1183,83 @@ object "test_A2_M_extract_err_reason" { } $StoreU64(v_ptr, sub(size, 1)) } + function A1_option_is_some$vec$u8$$(t) -> $result { + let $t1, $t2, $t3 + // $t1 := borrow_field>.vec($t0) + $t1 := t + // $t2 := vector::is_empty<#0>($t1) + $t2 := A1_vector_is_empty$vec$u8$$($t1) + // $t3 := !($t2) + $t3 := $LogicalNot($t2) + // return $t3 + $result := $t3 + } + + function A1_vector_is_empty$vec$u8$$(v) -> $result { + let $t1, $t2, $t3 + // $t1 := vector::length<#0>($t0) + $t1 := A1_vector_length$vec$u8$$(v) + // $t2 := 0 + $t2 := 0 + // $t3 := ==($t1, $t2) + $t3 := $Eq($t1, $t2) + // return $t3 + $result := $t3 + } + + function A1_vector_length$vec$u8$$(v_ref) -> len { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + len := $LoadU64(v_ptr) + } function A1_option_destroy_none$A2_U256_U256$(t) { - let vec, $t2, $t3, $t4, $t5, $t6 + let $t1, $t2, $t3, $t4, $t5 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t4 := 0 - $t4 := 0 - // abort($t4) - $Abort($t4) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t5 := move($t0) - $t5 := t - // $t6 := unpack option::Option<#0>($t5) - $t6 := $MemoryLoadU256(add($t5, 0)) - $Free($t5, 32) - // vector::destroy_empty<#0>($t6) - A1_vector_destroy_empty$A2_U256_U256$($t6) - // return () - leave + // $t3 := 262144 + $t3 := 262144 + // abort($t3) + $Abort($t3) } case 4 { - // $t2 := borrow_local($t0) - $t2 := $MakePtr(false, t) - // $t3 := option::is_none<#0>($t2) - $t3 := A1_option_is_none$A2_U256_U256$($t2) - // if ($t3) goto L0 else goto L1 - switch $t3 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := borrow_local($t0) + $t1 := $MakePtr(false, t) + // $t2 := option::is_none<#0>($t1) + $t2 := A1_option_is_none$A2_U256_U256$($t1) + // if ($t2) goto L1 else goto L0 + switch $t2 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t4 := move($t0) + $t4 := t + // $t5 := unpack option::Option<#0>($t4) + $t5 := $MemoryLoadU256(add($t4, 0)) + $Free($t4, 32) + // vector::destroy_empty<#0>($t5) + A1_vector_destroy_empty$A2_U256_U256$($t5) + // return () + leave } } } + function A1_vector_destroy_empty$A2_U256_U256$(v) { + let size := $MemoryLoadU64(v) + if $LogicalNot(iszero(size)) { $AbortBuiltin() } + let capacity := $MemoryLoadU64(add(v, 8)) + $Free(v, add(32, mul(capacity, 32))) + } function A1_option_is_none$A2_U256_U256$(t) -> $result { let $t1, $t2 // $t1 := borrow_field>.vec($t0) @@ -1395,45 +1287,44 @@ object "test_A2_M_extract_err_reason" { let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) len := $LoadU64(v_ptr) } - function A1_vector_destroy_empty$A2_U256_U256$(v) { - let size := $MemoryLoadU64(v) - if $LogicalNot(iszero(size)) { $AbortBuiltin() } - let capacity := $MemoryLoadU64(add(v, 8)) - $Free(v, add(32, mul(capacity, 32))) - } function A1_option_destroy_none$vec$u8$$(t) { - let vec, $t2, $t3, $t4, $t5, $t6 + let $t1, $t2, $t3, $t4, $t5 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t4 := 0 - $t4 := 0 - // abort($t4) - $Abort($t4) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t5 := move($t0) - $t5 := t - // $t6 := unpack option::Option<#0>($t5) - $t6 := $MemoryLoadU256(add($t5, 0)) - $Free($t5, 32) - // vector::destroy_empty<#0>($t6) - A1_vector_destroy_empty$vec$u8$$($t6) - // return () - leave + // $t3 := 262144 + $t3 := 262144 + // abort($t3) + $Abort($t3) } case 4 { - // $t2 := borrow_local($t0) - $t2 := $MakePtr(false, t) - // $t3 := option::is_none<#0>($t2) - $t3 := A1_option_is_none$vec$u8$$($t2) - // if ($t3) goto L0 else goto L1 - switch $t3 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := borrow_local($t0) + $t1 := $MakePtr(false, t) + // $t2 := option::is_none<#0>($t1) + $t2 := A1_option_is_none$vec$u8$$($t1) + // if ($t2) goto L1 else goto L0 + switch $t2 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t4 := move($t0) + $t4 := t + // $t5 := unpack option::Option<#0>($t4) + $t5 := $MemoryLoadU256(add($t4, 0)) + $Free($t4, 32) + // vector::destroy_empty<#0>($t5) + A1_vector_destroy_empty$vec$u8$$($t5) + // return () + leave } } } @@ -1449,42 +1340,53 @@ object "test_A2_M_extract_err_reason" { } function A1_option_destroy_none$u64$(t) { - let vec, $t2, $t3, $t4, $t5, $t6 + let $t1, $t2, $t3, $t4, $t5 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t4 := 0 - $t4 := 0 - // abort($t4) - $Abort($t4) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t5 := move($t0) - $t5 := t - // $t6 := unpack option::Option<#0>($t5) - $t6 := $MemoryLoadU256(add($t5, 0)) - $Free($t5, 32) - // vector::destroy_empty<#0>($t6) - A1_vector_destroy_empty$u64$($t6) - // return () - leave + // $t3 := 262144 + $t3 := 262144 + // abort($t3) + $Abort($t3) } case 4 { - // $t2 := borrow_local($t0) - $t2 := $MakePtr(false, t) - // $t3 := option::is_none<#0>($t2) - $t3 := A1_option_is_none$u64$($t2) - // if ($t3) goto L0 else goto L1 - switch $t3 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := borrow_local($t0) + $t1 := $MakePtr(false, t) + // $t2 := option::is_none<#0>($t1) + $t2 := A1_option_is_none$u64$($t1) + // if ($t2) goto L1 else goto L0 + switch $t2 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t4 := move($t0) + $t4 := t + // $t5 := unpack option::Option<#0>($t4) + $t5 := $MemoryLoadU256(add($t4, 0)) + $Free($t4, 32) + // vector::destroy_empty<#0>($t5) + A1_vector_destroy_empty$u64$($t5) + // return () + leave } } } + function A1_vector_destroy_empty$u64$(v) { + let size := $MemoryLoadU64(v) + if $LogicalNot(iszero(size)) { $AbortBuiltin() } + let capacity := $MemoryLoadU64(add(v, 8)) + $Free(v, add(32, mul(capacity, 8))) + } function A1_option_is_none$u64$(t) -> $result { let $t1, $t2 // $t1 := borrow_field>.vec($t0) @@ -1495,28 +1397,196 @@ object "test_A2_M_extract_err_reason" { $result := $t2 } - function A1_vector_is_empty$u64$(v) -> $result { - let $t1, $t2, $t3 - // $t1 := vector::length<#0>($t0) - $t1 := A1_vector_length$u64$(v) - // $t2 := 0 - $t2 := 0 - // $t3 := ==($t1, $t2) - $t3 := $Eq($t1, $t2) + function A1_vector_is_empty$u64$(v) -> $result { + let $t1, $t2, $t3 + // $t1 := vector::length<#0>($t0) + $t1 := A1_vector_length$u64$(v) + // $t2 := 0 + $t2 := 0 + // $t3 := ==($t1, $t2) + $t3 := $Eq($t1, $t2) + // return $t3 + $result := $t3 + } + + function A1_vector_length$u64$(v_ref) -> len { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + len := $LoadU64(v_ptr) + } + function A2_ExternalResult_is_err_reason$u64$(result) -> $result { + let $t1, $t2 + // $t1 := borrow_field>.err_reason($t0) + { + let $field_ptr := $IndexPtr(result, 64) + $t1 := $MakePtr($IsStoragePtr($field_ptr), $LoadU256($field_ptr)) + } + // $t2 := option::is_some>($t1) + $t2 := A1_option_is_some$vec$u8$$($t1) + // return $t2 + $result := $t2 + } + + function A2_M_pack_err_reason$u64$(v) -> $result { + let $t1 + // $t1 := ExternalResult::err_reason<#0>($t0) + $t1 := A2_ExternalResult_err_reason$u64$(v) + // return $t1 + $result := $t1 + } + + function A2_ExternalResult_err_reason$u64$(error) -> $result { + let tmp_$1, tmp_$2, tmp_$3, tmp_$4, $t5, $t6, $t7, $t8, $t9 + // $t5 := option::none<#0>() + $t5 := A1_option_none$u64$() + // $t6 := option::some>($t0) + $t6 := A1_option_some$vec$u8$$(error) + // $t7 := option::none>() + $t7 := A1_option_none$vec$u8$$() + // $t8 := option::none() + $t8 := A1_option_none$A2_U256_U256$() + // $t9 := pack ExternalResult::ExternalResult<#0>($t5, $t7, $t6, $t8) + { + let $mem := $Malloc(128) + $MemoryStoreU256(add($mem, 0), $t5) + $MemoryStoreU256(add($mem, 32), $t7) + $MemoryStoreU256(add($mem, 64), $t6) + $MemoryStoreU256(add($mem, 96), $t8) + $t9 := $mem + } + // return $t9 + $result := $t9 + } + + function A1_option_none$A2_U256_U256$() -> $result { + let $t0, $t1 + // $t0 := vector::empty<#0>() + $t0 := A1_vector_empty$A2_U256_U256$() + // $t1 := pack option::Option<#0>($t0) + { + let $mem := $Malloc(32) + $MemoryStoreU256(add($mem, 0), $t0) + $t1 := $mem + } + // return $t1 + $result := $t1 + } + + function A1_vector_empty$A2_U256_U256$() -> vector { + vector := $Malloc(96) + $MemoryStoreU64(add(vector, 8), 2) + } + function A1_option_none$vec$u8$$() -> $result { + let $t0, $t1 + // $t0 := vector::empty<#0>() + $t0 := A1_vector_empty$vec$u8$$() + // $t1 := pack option::Option<#0>($t0) + { + let $mem := $Malloc(32) + $MemoryStoreU256(add($mem, 0), $t0) + $t1 := $mem + } + // return $t1 + $result := $t1 + } + + function A1_vector_empty$vec$u8$$() -> vector { + vector := $Malloc(96) + $MemoryStoreU64(add(vector, 8), 2) + } + function A1_option_some$vec$u8$$(e) -> $result { + let $t1, $t2 + // $t1 := vector::singleton<#0>($t0) + $t1 := A1_vector_singleton$vec$u8$$(e) + // $t2 := pack option::Option<#0>($t1) + { + let $mem := $Malloc(32) + $MemoryStoreU256(add($mem, 0), $t1) + $t2 := $mem + } + // return $t2 + $result := $t2 + } + + function A1_vector_singleton$vec$u8$$(e) -> $result { + let $t2, $t3 + let $locals := $Malloc(32) + // $t1 := vector::empty<#0>() + mstore($locals, A1_vector_empty$vec$u8$$()) + // $t2 := borrow_local($t1) + $t2 := $MakePtr(false, $locals) + // vector::push_back<#0>($t2, $t0) + A1_vector_push_back$vec$u8$$($t2, e) + // $t3 := move($t1) + $t3 := mload($locals) // return $t3 $result := $t3 + $Free($locals, 32) } - function A1_vector_length$u64$(v_ref) -> len { + function A1_vector_push_back$vec$u8$$(v_ref, e) { let v_offs := $LoadU256(v_ref) let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) - len := $LoadU64(v_ptr) + let size := $LoadU64(v_ptr) + let e_ptr := $IndexPtr(v_ptr, add(32, mul(size, 32))) + $StoreU256(e_ptr, e) + if $IsStoragePtr(e_ptr) { + let e_offs := $OffsetPtr(e_ptr) + let $linked_dst_2300595445 := $NewLinkedStorageBase(0x89204cf5) + let $size_2300595445 := $MemoryLoadU64(e) + let $data_size_2300595445 := mul($size_2300595445, 1) + $AlignedStorageStore($linked_dst_2300595445, mload(e)) + let $data_src_2300595445 := add(e, 32) + let $data_dst_2300595445 := add($linked_dst_2300595445, 32) + for { let $offs_2300595445 := 0 } lt($offs_2300595445, $data_size_2300595445) { $offs_2300595445 := add($offs_2300595445, 32)} { + $AlignedStorageStore(add($data_dst_2300595445, $offs_2300595445), mload(add($data_src_2300595445, $offs_2300595445))) + $Free(e, add($data_size_2300595445, 32)) + } + $AlignedStorageStore(e_offs, $linked_dst_2300595445) + } + size := add(size, 1) + $StoreU64(v_ptr, size) + let capacity := $LoadU64($IndexPtr(v_ptr, 8)) + if and(iszero($IsStoragePtr(v_ptr)), eq(size, capacity)) { + let new_v_offs := $ResizeVector(v_offs, capacity, 32) + $StoreU256(v_ref, new_v_offs) + } } - function A1_vector_destroy_empty$u64$(v) { - let size := $MemoryLoadU64(v) - if $LogicalNot(iszero(size)) { $AbortBuiltin() } - let capacity := $MemoryLoadU64(add(v, 8)) - $Free(v, add(32, mul(capacity, 8))) + function A1_option_none$u64$() -> $result { + let $t0, $t1 + // $t0 := vector::empty<#0>() + $t0 := A1_vector_empty$u64$() + // $t1 := pack option::Option<#0>($t0) + { + let $mem := $Malloc(32) + $MemoryStoreU256(add($mem, 0), $t0) + $t1 := $mem + } + // return $t1 + $result := $t1 + } + + function A1_vector_empty$u64$() -> vector { + vector := $Malloc(48) + $MemoryStoreU64(add(vector, 8), 2) + } + function A1_vector_push_back$u8$(v_ref, e) { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + let size := $LoadU64(v_ptr) + let e_ptr := $IndexPtr(v_ptr, add(32, mul(size, 1))) + $StoreU8(e_ptr, e) + size := add(size, 1) + $StoreU64(v_ptr, size) + let capacity := $LoadU64($IndexPtr(v_ptr, 8)) + if and(iszero($IsStoragePtr(v_ptr)), eq(size, capacity)) { + let new_v_offs := $ResizeVector(v_offs, capacity, 1) + $StoreU256(v_ref, new_v_offs) + } + } + function A1_vector_empty$u8$() -> vector { + vector := $Malloc(34) + $MemoryStoreU64(add(vector, 8), 2) } function $Abort(code) { mstore(0, code) @@ -1768,253 +1838,106 @@ object "test_A2_M_extract_err_reason" { function $GtEq(x, y) -> r { r := or(gt(x, y), eq(x, y)) } - function $Eq(x, y) -> r { - r := eq(x, y) - } - function $LogicalNot(x) -> r { - r := iszero(x) - } - function $ClosestGreaterPowerOfTwo(x) -> r { - r := or(r, shr(1, x)) - r := or(r, shr(2, r)) - r := or(r, shr(4, r)) - r := or(r, shr(8, r)) - r := or(r, shr(16, r)) - r := or(r, shr(32, r)) - r := add(x, 1) - } - } -} -===> Test result of M::extract_err_reason: Succeed(Stopped) (used_gas=6005): [] - -// test of M::extract_panic_code -/* ======================================= - * Generated by Move-To-Yul compiler v0.0 - * ======================================= */ - - -object "test_A2_M_extract_panic_code" { - code { - mstore(0, memoryguard(160)) - A2_M_extract_panic_code() - return (0, 0) - function A2_M_extract_panic_code() { - let v, v2, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12 - let $block := 4 - for {} true {} { - switch $block - case 2 { - // label L1 - // $t6 := 108 - $t6 := 108 - // abort($t6) - $Abort($t6) - } - case 3 { - // label L0 - // $t7 := move($t1) - $t7 := v2 - // $t8 := ExternalResult::unwrap_panic($t7) - $t8 := A2_ExternalResult_unwrap_panic$u64$($t7) - // $t9 := 42 - $t9 := 42 - // $t10 := U256::u256_from_u128($t9) - $t10 := A2_U256_u256_from_u128($t9) - // $t11 := ==($t8, $t10) - $t11 := $Eq($t8, $t10) - // if ($t11) goto L2 else goto L3 - switch $t11 - case 0 { $block := 5 } - default { $block := 6 } - } - case 4 { - // $t2 := 42 - $t2 := 42 - // $t3 := U256::u256_from_u128($t2) - $t3 := A2_U256_u256_from_u128($t2) - // $t1 := M::pack_panic_code($t3) - v2 := A2_M_pack_panic_code$u64$($t3) - // $t4 := borrow_local($t1) - $t4 := $MakePtr(false, v2) - // $t5 := ExternalResult::is_panic($t4) - $t5 := A2_ExternalResult_is_panic$u64$($t4) - // if ($t5) goto L0 else goto L1 - switch $t5 - case 0 { $block := 2 } - default { $block := 3 } - } - case 5 { - // label L3 - // $t12 := 109 - $t12 := 109 - // abort($t12) - $Abort($t12) - } - case 6 { - // label L2 - // return () - leave - } - } - } - - function A2_ExternalResult_is_panic$u64$(result) -> $result { - let $t1, $t2 - // $t1 := borrow_field>.panic_code($t0) - { - let $field_ptr := $IndexPtr(result, 96) - $t1 := $MakePtr($IsStoragePtr($field_ptr), $LoadU256($field_ptr)) - } - // $t2 := option::is_some($t1) - $t2 := A1_option_is_some$A2_U256_U256$($t1) - // return $t2 - $result := $t2 - } - - function A1_option_is_some$A2_U256_U256$(t) -> $result { - let $t1, $t2, $t3 - // $t1 := borrow_field>.vec($t0) - $t1 := t - // $t2 := vector::is_empty<#0>($t1) - $t2 := A1_vector_is_empty$A2_U256_U256$($t1) - // $t3 := !($t2) - $t3 := $LogicalNot($t2) - // return $t3 - $result := $t3 - } - - function A1_vector_is_empty$A2_U256_U256$(v) -> $result { - let $t1, $t2, $t3 - // $t1 := vector::length<#0>($t0) - $t1 := A1_vector_length$A2_U256_U256$(v) - // $t2 := 0 - $t2 := 0 - // $t3 := ==($t1, $t2) - $t3 := $Eq($t1, $t2) - // return $t3 - $result := $t3 - } - - function A1_vector_length$A2_U256_U256$(v_ref) -> len { - let v_offs := $LoadU256(v_ref) - let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) - len := $LoadU64(v_ptr) - } - function A2_M_pack_panic_code$u64$(v) -> $result { - let $t1 - // $t1 := ExternalResult::panic<#0>($t0) - $t1 := A2_ExternalResult_panic$u64$(v) - // return $t1 - $result := $t1 - } - - function A2_ExternalResult_panic$u64$(panic_code) -> $result { - let tmp_$1, tmp_$2, tmp_$3, tmp_$4, $t5, $t6, $t7, $t8, $t9 - // $t5 := option::none<#0>() - $t5 := A1_option_none$u64$() - // $t6 := option::none>() - $t6 := A1_option_none$vec$u8$$() - // $t7 := option::none>() - $t7 := A1_option_none$vec$u8$$() - // $t8 := option::some($t0) - $t8 := A1_option_some$A2_U256_U256$(panic_code) - // $t9 := pack ExternalResult::ExternalResult<#0>($t5, $t7, $t6, $t8) - { - let $mem := $Malloc(128) - $MemoryStoreU256(add($mem, 0), $t5) - $MemoryStoreU256(add($mem, 32), $t7) - $MemoryStoreU256(add($mem, 64), $t6) - $MemoryStoreU256(add($mem, 96), $t8) - $t9 := $mem - } - // return $t9 - $result := $t9 - } - - function A1_option_some$A2_U256_U256$(e) -> $result { - let $t1, $t2 - // $t1 := vector::singleton<#0>($t0) - $t1 := A1_vector_singleton$A2_U256_U256$(e) - // $t2 := pack option::Option<#0>($t1) - { - let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t1) - $t2 := $mem - } - // return $t2 - $result := $t2 - } - - function A1_vector_singleton$A2_U256_U256$(e) -> $result { - let $t2, $t3 - let $locals := $Malloc(32) - // $t1 := vector::empty<#0>() - mstore($locals, A1_vector_empty$A2_U256_U256$()) - // $t2 := borrow_local($t1) - $t2 := $MakePtr(false, $locals) - // vector::push_back<#0>($t2, $t0) - A1_vector_push_back$A2_U256_U256$($t2, e) - // $t3 := move($t1) - $t3 := mload($locals) - // return $t3 - $result := $t3 - $Free($locals, 32) - } - - function A1_vector_push_back$A2_U256_U256$(v_ref, e) { - let v_offs := $LoadU256(v_ref) - let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) - let size := $LoadU64(v_ptr) - let e_ptr := $IndexPtr(v_ptr, add(32, mul(size, 32))) - $StoreU256(e_ptr, e) - size := add(size, 1) - $StoreU64(v_ptr, size) - let capacity := $LoadU64($IndexPtr(v_ptr, 8)) - if and(iszero($IsStoragePtr(v_ptr)), eq(size, capacity)) { - let new_v_offs := $ResizeVector(v_offs, capacity, 32) - $StoreU256(v_ref, new_v_offs) - } + function $Eq(x, y) -> r { + r := eq(x, y) } - function A1_vector_empty$A2_U256_U256$() -> vector { - vector := $Malloc(96) - $MemoryStoreU64(add(vector, 8), 2) + function $LogicalNot(x) -> r { + r := iszero(x) } - function A1_option_none$vec$u8$$() -> $result { - let $t0, $t1 - // $t0 := vector::empty<#0>() - $t0 := A1_vector_empty$vec$u8$$() - // $t1 := pack option::Option<#0>($t0) - { - let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t0) - $t1 := $mem - } - // return $t1 - $result := $t1 + function $ClosestGreaterPowerOfTwo(x) -> r { + r := or(r, shr(1, x)) + r := or(r, shr(2, r)) + r := or(r, shr(4, r)) + r := or(r, shr(8, r)) + r := or(r, shr(16, r)) + r := or(r, shr(32, r)) + r := add(x, 1) } + } +} +===> Test result of M::extract_err_reason: Succeed(Stopped) (used_gas=6988): [] - function A1_vector_empty$vec$u8$$() -> vector { - vector := $Malloc(96) - $MemoryStoreU64(add(vector, 8), 2) - } - function A1_option_none$u64$() -> $result { - let $t0, $t1 - // $t0 := vector::empty<#0>() - $t0 := A1_vector_empty$u64$() - // $t1 := pack option::Option<#0>($t0) - { - let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t0) - $t1 := $mem +// test of M::extract_panic_code +/* ======================================= + * Generated by Move-To-Yul compiler v0.0 + * ======================================= */ + + +object "test_A2_M_extract_panic_code" { + code { + mstore(0, memoryguard(160)) + A2_M_extract_panic_code() + return (0, 0) + function A2_M_extract_panic_code() { + let v2, $t1, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11 + let $block := 4 + for {} true {} { + switch $block + case 2 { + // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 + // $t5 := 108 + $t5 := 108 + // abort($t5) + $Abort($t5) + } + case 4 { + // $t1 := 42 + $t1 := 42 + // $t2 := U256::u256_from_u128($t1) + $t2 := A2_U256_u256_from_u128($t1) + // $t0 := M::pack_panic_code($t2) + v2 := A2_M_pack_panic_code$u64$($t2) + // $t3 := borrow_local($t0) + $t3 := $MakePtr(false, v2) + // $t4 := ExternalResult::is_panic($t3) + $t4 := A2_ExternalResult_is_panic$u64$($t3) + // if ($t4) goto L1 else goto L0 + switch $t4 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t6 := move($t0) + $t6 := v2 + // $t7 := ExternalResult::unwrap_panic($t6) + $t7 := A2_ExternalResult_unwrap_panic$u64$($t6) + // $t8 := 42 + $t8 := 42 + // $t9 := U256::u256_from_u128($t8) + $t9 := A2_U256_u256_from_u128($t8) + // $t10 := ==($t7, $t9) + $t10 := $Eq($t7, $t9) + // if ($t10) goto L4 else goto L3 + switch $t10 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { + // label L3 + // $t11 := 109 + $t11 := 109 + // abort($t11) + $Abort($t11) + } + case 8 { + // label L5 + // return () + leave + } } - // return $t1 - $result := $t1 } - function A1_vector_empty$u64$() -> vector { - vector := $Malloc(48) - $MemoryStoreU64(add(vector, 8), 2) - } function A2_U256_u256_from_u128(lo) -> $result { let $t1, $t2 // $t1 := 0 @@ -2026,23 +1949,23 @@ object "test_A2_M_extract_panic_code" { } function A2_ExternalResult_unwrap_panic$u64$(result) -> $result { - let err_data, err_reason, panic_code, value, $t5, $t6, $t7, $t8, $t9 - // ($t5, $t6, $t7, $t8) := unpack ExternalResult::ExternalResult<#0>($t0) - $t5 := $MemoryLoadU256(add(result, 0)) - $t6 := $MemoryLoadU256(add(result, 32)) - $t7 := $MemoryLoadU256(add(result, 64)) - $t8 := $MemoryLoadU256(add(result, 96)) + let err_data, err_reason, panic_code, $t4, $t5, $t6, $t7, $t8 + // ($t4, $t5, $t6, $t7) := unpack ExternalResult::ExternalResult<#0>($t0) + $t4 := $MemoryLoadU256(add(result, 0)) + $t5 := $MemoryLoadU256(add(result, 32)) + $t6 := $MemoryLoadU256(add(result, 64)) + $t7 := $MemoryLoadU256(add(result, 96)) $Free(result, 128) - // option::destroy_none<#0>($t5) - A1_option_destroy_none$u64$($t5) - // option::destroy_none>($t7) - A1_option_destroy_none$vec$u8$$($t7) + // option::destroy_none<#0>($t4) + A1_option_destroy_none$u64$($t4) // option::destroy_none>($t6) A1_option_destroy_none$vec$u8$$($t6) - // $t9 := option::destroy_some($t8) - $t9 := A1_option_destroy_some$A2_U256_U256$($t8) - // return $t9 - $result := $t9 + // option::destroy_none>($t5) + A1_option_destroy_none$vec$u8$$($t5) + // $t8 := option::destroy_some($t7) + $t8 := A1_option_destroy_some$A2_U256_U256$($t7) + // return $t8 + $result := $t8 } function A1_option_destroy_some$A2_U256_U256$(t) -> $result { @@ -2053,13 +1976,28 @@ object "test_A2_M_extract_panic_code" { switch $block case 2 { // label L1 - // $t5 := 1 - $t5 := 1 - // abort($t5) - $Abort($t5) + // goto L2 + $block := 5 } case 3 { // label L0 + // $t5 := 262145 + $t5 := 262145 + // abort($t5) + $Abort($t5) + } + case 4 { + // $t3 := borrow_local($t0) + $t3 := $MakePtr(false, t) + // $t4 := option::is_some<#0>($t3) + $t4 := A1_option_is_some$A2_U256_U256$($t3) + // if ($t4) goto L1 else goto L0 + switch $t4 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t6 := move($t0) $t6 := t // $t2 := unpack option::Option<#0>($t6) @@ -2078,16 +2016,6 @@ object "test_A2_M_extract_panic_code" { $Free($locals, 32) leave } - case 4 { - // $t3 := borrow_local($t0) - $t3 := $MakePtr(false, t) - // $t4 := option::is_some<#0>($t3) - $t4 := A1_option_is_some$A2_U256_U256$($t3) - // if ($t4) goto L0 else goto L1 - switch $t4 - case 0 { $block := 2 } - default { $block := 3 } - } } } @@ -2106,43 +2034,83 @@ object "test_A2_M_extract_panic_code" { e := $LoadU256(e_ptr) $StoreU64(v_ptr, sub(size, 1)) } + function A1_option_is_some$A2_U256_U256$(t) -> $result { + let $t1, $t2, $t3 + // $t1 := borrow_field>.vec($t0) + $t1 := t + // $t2 := vector::is_empty<#0>($t1) + $t2 := A1_vector_is_empty$A2_U256_U256$($t1) + // $t3 := !($t2) + $t3 := $LogicalNot($t2) + // return $t3 + $result := $t3 + } + + function A1_vector_is_empty$A2_U256_U256$(v) -> $result { + let $t1, $t2, $t3 + // $t1 := vector::length<#0>($t0) + $t1 := A1_vector_length$A2_U256_U256$(v) + // $t2 := 0 + $t2 := 0 + // $t3 := ==($t1, $t2) + $t3 := $Eq($t1, $t2) + // return $t3 + $result := $t3 + } + + function A1_vector_length$A2_U256_U256$(v_ref) -> len { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + len := $LoadU64(v_ptr) + } function A1_option_destroy_none$vec$u8$$(t) { - let vec, $t2, $t3, $t4, $t5, $t6 + let $t1, $t2, $t3, $t4, $t5 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t4 := 0 - $t4 := 0 - // abort($t4) - $Abort($t4) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t5 := move($t0) - $t5 := t - // $t6 := unpack option::Option<#0>($t5) - $t6 := $MemoryLoadU256(add($t5, 0)) - $Free($t5, 32) - // vector::destroy_empty<#0>($t6) - A1_vector_destroy_empty$vec$u8$$($t6) - // return () - leave + // $t3 := 262144 + $t3 := 262144 + // abort($t3) + $Abort($t3) } case 4 { - // $t2 := borrow_local($t0) - $t2 := $MakePtr(false, t) - // $t3 := option::is_none<#0>($t2) - $t3 := A1_option_is_none$vec$u8$$($t2) - // if ($t3) goto L0 else goto L1 - switch $t3 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := borrow_local($t0) + $t1 := $MakePtr(false, t) + // $t2 := option::is_none<#0>($t1) + $t2 := A1_option_is_none$vec$u8$$($t1) + // if ($t2) goto L1 else goto L0 + switch $t2 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t4 := move($t0) + $t4 := t + // $t5 := unpack option::Option<#0>($t4) + $t5 := $MemoryLoadU256(add($t4, 0)) + $Free($t4, 32) + // vector::destroy_empty<#0>($t5) + A1_vector_destroy_empty$vec$u8$$($t5) + // return () + leave } } } + function A1_vector_destroy_empty$vec$u8$$(v) { + let size := $MemoryLoadU64(v) + if $LogicalNot(iszero(size)) { $AbortBuiltin() } + let capacity := $MemoryLoadU64(add(v, 8)) + $Free(v, add(32, mul(capacity, 32))) + } function A1_option_is_none$vec$u8$$(t) -> $result { let $t1, $t2 // $t1 := borrow_field>.vec($t0) @@ -2170,49 +2138,54 @@ object "test_A2_M_extract_panic_code" { let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) len := $LoadU64(v_ptr) } - function A1_vector_destroy_empty$vec$u8$$(v) { - let size := $MemoryLoadU64(v) - if $LogicalNot(iszero(size)) { $AbortBuiltin() } - let capacity := $MemoryLoadU64(add(v, 8)) - $Free(v, add(32, mul(capacity, 32))) - } function A1_option_destroy_none$u64$(t) { - let vec, $t2, $t3, $t4, $t5, $t6 + let $t1, $t2, $t3, $t4, $t5 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t4 := 0 - $t4 := 0 - // abort($t4) - $Abort($t4) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t5 := move($t0) - $t5 := t - // $t6 := unpack option::Option<#0>($t5) - $t6 := $MemoryLoadU256(add($t5, 0)) - $Free($t5, 32) - // vector::destroy_empty<#0>($t6) - A1_vector_destroy_empty$u64$($t6) - // return () - leave + // $t3 := 262144 + $t3 := 262144 + // abort($t3) + $Abort($t3) } case 4 { - // $t2 := borrow_local($t0) - $t2 := $MakePtr(false, t) - // $t3 := option::is_none<#0>($t2) - $t3 := A1_option_is_none$u64$($t2) - // if ($t3) goto L0 else goto L1 - switch $t3 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := borrow_local($t0) + $t1 := $MakePtr(false, t) + // $t2 := option::is_none<#0>($t1) + $t2 := A1_option_is_none$u64$($t1) + // if ($t2) goto L1 else goto L0 + switch $t2 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t4 := move($t0) + $t4 := t + // $t5 := unpack option::Option<#0>($t4) + $t5 := $MemoryLoadU256(add($t4, 0)) + $Free($t4, 32) + // vector::destroy_empty<#0>($t5) + A1_vector_destroy_empty$u64$($t5) + // return () + leave } } } + function A1_vector_destroy_empty$u64$(v) { + let size := $MemoryLoadU64(v) + if $LogicalNot(iszero(size)) { $AbortBuiltin() } + let capacity := $MemoryLoadU64(add(v, 8)) + $Free(v, add(32, mul(capacity, 8))) + } function A1_option_is_none$u64$(t) -> $result { let $t1, $t2 // $t1 := borrow_field>.vec($t0) @@ -2235,16 +2208,138 @@ object "test_A2_M_extract_panic_code" { $result := $t3 } - function A1_vector_length$u64$(v_ref) -> len { + function A1_vector_length$u64$(v_ref) -> len { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + len := $LoadU64(v_ptr) + } + function A2_ExternalResult_is_panic$u64$(result) -> $result { + let $t1, $t2 + // $t1 := borrow_field>.panic_code($t0) + { + let $field_ptr := $IndexPtr(result, 96) + $t1 := $MakePtr($IsStoragePtr($field_ptr), $LoadU256($field_ptr)) + } + // $t2 := option::is_some($t1) + $t2 := A1_option_is_some$A2_U256_U256$($t1) + // return $t2 + $result := $t2 + } + + function A2_M_pack_panic_code$u64$(v) -> $result { + let $t1 + // $t1 := ExternalResult::panic<#0>($t0) + $t1 := A2_ExternalResult_panic$u64$(v) + // return $t1 + $result := $t1 + } + + function A2_ExternalResult_panic$u64$(panic_code) -> $result { + let tmp_$1, tmp_$2, tmp_$3, tmp_$4, $t5, $t6, $t7, $t8, $t9 + // $t5 := option::none<#0>() + $t5 := A1_option_none$u64$() + // $t6 := option::none>() + $t6 := A1_option_none$vec$u8$$() + // $t7 := option::none>() + $t7 := A1_option_none$vec$u8$$() + // $t8 := option::some($t0) + $t8 := A1_option_some$A2_U256_U256$(panic_code) + // $t9 := pack ExternalResult::ExternalResult<#0>($t5, $t7, $t6, $t8) + { + let $mem := $Malloc(128) + $MemoryStoreU256(add($mem, 0), $t5) + $MemoryStoreU256(add($mem, 32), $t7) + $MemoryStoreU256(add($mem, 64), $t6) + $MemoryStoreU256(add($mem, 96), $t8) + $t9 := $mem + } + // return $t9 + $result := $t9 + } + + function A1_option_some$A2_U256_U256$(e) -> $result { + let $t1, $t2 + // $t1 := vector::singleton<#0>($t0) + $t1 := A1_vector_singleton$A2_U256_U256$(e) + // $t2 := pack option::Option<#0>($t1) + { + let $mem := $Malloc(32) + $MemoryStoreU256(add($mem, 0), $t1) + $t2 := $mem + } + // return $t2 + $result := $t2 + } + + function A1_vector_singleton$A2_U256_U256$(e) -> $result { + let $t2, $t3 + let $locals := $Malloc(32) + // $t1 := vector::empty<#0>() + mstore($locals, A1_vector_empty$A2_U256_U256$()) + // $t2 := borrow_local($t1) + $t2 := $MakePtr(false, $locals) + // vector::push_back<#0>($t2, $t0) + A1_vector_push_back$A2_U256_U256$($t2, e) + // $t3 := move($t1) + $t3 := mload($locals) + // return $t3 + $result := $t3 + $Free($locals, 32) + } + + function A1_vector_push_back$A2_U256_U256$(v_ref, e) { let v_offs := $LoadU256(v_ref) let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) - len := $LoadU64(v_ptr) + let size := $LoadU64(v_ptr) + let e_ptr := $IndexPtr(v_ptr, add(32, mul(size, 32))) + $StoreU256(e_ptr, e) + size := add(size, 1) + $StoreU64(v_ptr, size) + let capacity := $LoadU64($IndexPtr(v_ptr, 8)) + if and(iszero($IsStoragePtr(v_ptr)), eq(size, capacity)) { + let new_v_offs := $ResizeVector(v_offs, capacity, 32) + $StoreU256(v_ref, new_v_offs) + } } - function A1_vector_destroy_empty$u64$(v) { - let size := $MemoryLoadU64(v) - if $LogicalNot(iszero(size)) { $AbortBuiltin() } - let capacity := $MemoryLoadU64(add(v, 8)) - $Free(v, add(32, mul(capacity, 8))) + function A1_vector_empty$A2_U256_U256$() -> vector { + vector := $Malloc(96) + $MemoryStoreU64(add(vector, 8), 2) + } + function A1_option_none$vec$u8$$() -> $result { + let $t0, $t1 + // $t0 := vector::empty<#0>() + $t0 := A1_vector_empty$vec$u8$$() + // $t1 := pack option::Option<#0>($t0) + { + let $mem := $Malloc(32) + $MemoryStoreU256(add($mem, 0), $t0) + $t1 := $mem + } + // return $t1 + $result := $t1 + } + + function A1_vector_empty$vec$u8$$() -> vector { + vector := $Malloc(96) + $MemoryStoreU64(add(vector, 8), 2) + } + function A1_option_none$u64$() -> $result { + let $t0, $t1 + // $t0 := vector::empty<#0>() + $t0 := A1_vector_empty$u64$() + // $t1 := pack option::Option<#0>($t0) + { + let $mem := $Malloc(32) + $MemoryStoreU256(add($mem, 0), $t0) + $t1 := $mem + } + // return $t1 + $result := $t1 + } + + function A1_vector_empty$u64$() -> vector { + vector := $Malloc(48) + $MemoryStoreU64(add(vector, 8), 2) } function $Abort(code) { mstore(0, code) @@ -2456,7 +2551,7 @@ object "test_A2_M_extract_panic_code" { } } } -===> Test result of M::extract_panic_code: Succeed(Stopped) (used_gas=4470): [] +===> Test result of M::extract_panic_code: Succeed(Stopped) (used_gas=5168): [] // test of M::extract_value /* ======================================= @@ -2476,26 +2571,16 @@ object "test_A2_M_extract_value" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t4 := 100 $t4 := 100 // abort($t4) $Abort($t4) } - case 3 { - // label L0 - // $t5 := move($t0) - $t5 := v2 - // $t6 := ExternalResult::unwrap($t5) - $t6 := A2_ExternalResult_unwrap$u64$($t5) - // $t7 := 100 - $t7 := 100 - // $t8 := ==($t6, $t7) - $t8 := $Eq($t6, $t7) - // if ($t8) goto L2 else goto L3 - switch $t8 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t1 := 100 $t1 := 100 @@ -2505,182 +2590,46 @@ object "test_A2_M_extract_value" { $t2 := $MakePtr(false, v2) // $t3 := ExternalResult::is_ok($t2) $t3 := A2_ExternalResult_is_ok$u64$($t2) - // if ($t3) goto L0 else goto L1 + // if ($t3) goto L1 else goto L0 switch $t3 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { - // label L3 - // $t9 := 101 - $t9 := 101 - // abort($t9) - $Abort($t9) - } - case 6 { // label L2 - // return () - leave - } - } - } - - function A2_ExternalResult_is_ok$u64$(result) -> $result { - let $t1, $t2 - // $t1 := borrow_field>.value($t0) - { - $t1 := $MakePtr($IsStoragePtr(result), $LoadU256(result)) - } - // $t2 := option::is_some<#0>($t1) - $t2 := A1_option_is_some$u64$($t1) - // return $t2 - $result := $t2 - } - - function A1_option_is_some$u64$(t) -> $result { - let $t1, $t2, $t3 - // $t1 := borrow_field>.vec($t0) - $t1 := t - // $t2 := vector::is_empty<#0>($t1) - $t2 := A1_vector_is_empty$u64$($t1) - // $t3 := !($t2) - $t3 := $LogicalNot($t2) - // return $t3 - $result := $t3 - } - - function A1_vector_is_empty$u64$(v) -> $result { - let $t1, $t2, $t3 - // $t1 := vector::length<#0>($t0) - $t1 := A1_vector_length$u64$(v) - // $t2 := 0 - $t2 := 0 - // $t3 := ==($t1, $t2) - $t3 := $Eq($t1, $t2) - // return $t3 - $result := $t3 - } - - function A1_vector_length$u64$(v_ref) -> len { - let v_offs := $LoadU256(v_ref) - let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) - len := $LoadU64(v_ptr) - } - function A2_M_pack_value$u64$(v) -> $result { - let $t1 - // $t1 := ExternalResult::ok<#0>($t0) - $t1 := A2_ExternalResult_ok$u64$(v) - // return $t1 - $result := $t1 - } - - function A2_ExternalResult_ok$u64$(value) -> $result { - let $t1, $t2, $t3, $t4, $t5 - // $t1 := option::some<#0>($t0) - $t1 := A1_option_some$u64$(value) - // $t2 := option::none>() - $t2 := A1_option_none$vec$u8$$() - // $t3 := option::none>() - $t3 := A1_option_none$vec$u8$$() - // $t4 := option::none() - $t4 := A1_option_none$A2_U256_U256$() - // $t5 := pack ExternalResult::ExternalResult<#0>($t1, $t2, $t3, $t4) - { - let $mem := $Malloc(128) - $MemoryStoreU256(add($mem, 0), $t1) - $MemoryStoreU256(add($mem, 32), $t2) - $MemoryStoreU256(add($mem, 64), $t3) - $MemoryStoreU256(add($mem, 96), $t4) - $t5 := $mem - } - // return $t5 - $result := $t5 - } - - function A1_option_none$A2_U256_U256$() -> $result { - let $t0, $t1 - // $t0 := vector::empty<#0>() - $t0 := A1_vector_empty$A2_U256_U256$() - // $t1 := pack option::Option<#0>($t0) - { - let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t0) - $t1 := $mem - } - // return $t1 - $result := $t1 - } - - function A1_vector_empty$A2_U256_U256$() -> vector { - vector := $Malloc(96) - $MemoryStoreU64(add(vector, 8), 2) - } - function A1_option_none$vec$u8$$() -> $result { - let $t0, $t1 - // $t0 := vector::empty<#0>() - $t0 := A1_vector_empty$vec$u8$$() - // $t1 := pack option::Option<#0>($t0) - { - let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t0) - $t1 := $mem - } - // return $t1 - $result := $t1 - } - - function A1_vector_empty$vec$u8$$() -> vector { - vector := $Malloc(96) - $MemoryStoreU64(add(vector, 8), 2) - } - function A1_option_some$u64$(e) -> $result { - let $t1, $t2 - // $t1 := vector::singleton<#0>($t0) - $t1 := A1_vector_singleton$u64$(e) - // $t2 := pack option::Option<#0>($t1) - { - let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t1) - $t2 := $mem - } - // return $t2 - $result := $t2 - } - - function A1_vector_singleton$u64$(e) -> $result { - let $t2, $t3 - let $locals := $Malloc(32) - // $t1 := vector::empty<#0>() - mstore($locals, A1_vector_empty$u64$()) - // $t2 := borrow_local($t1) - $t2 := $MakePtr(false, $locals) - // vector::push_back<#0>($t2, $t0) - A1_vector_push_back$u64$($t2, e) - // $t3 := move($t1) - $t3 := mload($locals) - // return $t3 - $result := $t3 - $Free($locals, 32) - } - - function A1_vector_push_back$u64$(v_ref, e) { - let v_offs := $LoadU256(v_ref) - let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) - let size := $LoadU64(v_ptr) - let e_ptr := $IndexPtr(v_ptr, add(32, mul(size, 8))) - $StoreU64(e_ptr, e) - size := add(size, 1) - $StoreU64(v_ptr, size) - let capacity := $LoadU64($IndexPtr(v_ptr, 8)) - if and(iszero($IsStoragePtr(v_ptr)), eq(size, capacity)) { - let new_v_offs := $ResizeVector(v_offs, capacity, 8) - $StoreU256(v_ref, new_v_offs) + // $t5 := move($t0) + $t5 := v2 + // $t6 := ExternalResult::unwrap($t5) + $t6 := A2_ExternalResult_unwrap$u64$($t5) + // $t7 := 100 + $t7 := 100 + // $t8 := ==($t6, $t7) + $t8 := $Eq($t6, $t7) + // if ($t8) goto L4 else goto L3 + switch $t8 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { + // label L3 + // $t9 := 101 + $t9 := 101 + // abort($t9) + $Abort($t9) + } + case 8 { + // label L5 + // return () + leave + } } } - function A1_vector_empty$u64$() -> vector { - vector := $Malloc(48) - $MemoryStoreU64(add(vector, 8), 2) - } + function A2_ExternalResult_unwrap$u64$(result) -> $result { let err_data, err_reason, panic_code, value, $t5, $t6, $t7, $t8, $t9 // ($t5, $t6, $t7, $t8) := unpack ExternalResult::ExternalResult<#0>($t0) @@ -2709,13 +2658,28 @@ object "test_A2_M_extract_value" { switch $block case 2 { // label L1 - // $t5 := 1 - $t5 := 1 - // abort($t5) - $Abort($t5) + // goto L2 + $block := 5 } case 3 { // label L0 + // $t5 := 262145 + $t5 := 262145 + // abort($t5) + $Abort($t5) + } + case 4 { + // $t3 := borrow_local($t0) + $t3 := $MakePtr(false, t) + // $t4 := option::is_some<#0>($t3) + $t4 := A1_option_is_some$u64$($t3) + // if ($t4) goto L1 else goto L0 + switch $t4 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t6 := move($t0) $t6 := t // $t2 := unpack option::Option<#0>($t6) @@ -2734,16 +2698,6 @@ object "test_A2_M_extract_value" { $Free($locals, 32) leave } - case 4 { - // $t3 := borrow_local($t0) - $t3 := $MakePtr(false, t) - // $t4 := option::is_some<#0>($t3) - $t4 := A1_option_is_some$u64$($t3) - // if ($t4) goto L0 else goto L1 - switch $t4 - case 0 { $block := 2 } - default { $block := 3 } - } } } @@ -2762,43 +2716,83 @@ object "test_A2_M_extract_value" { e := $LoadU64(e_ptr) $StoreU64(v_ptr, sub(size, 1)) } + function A1_option_is_some$u64$(t) -> $result { + let $t1, $t2, $t3 + // $t1 := borrow_field>.vec($t0) + $t1 := t + // $t2 := vector::is_empty<#0>($t1) + $t2 := A1_vector_is_empty$u64$($t1) + // $t3 := !($t2) + $t3 := $LogicalNot($t2) + // return $t3 + $result := $t3 + } + + function A1_vector_is_empty$u64$(v) -> $result { + let $t1, $t2, $t3 + // $t1 := vector::length<#0>($t0) + $t1 := A1_vector_length$u64$(v) + // $t2 := 0 + $t2 := 0 + // $t3 := ==($t1, $t2) + $t3 := $Eq($t1, $t2) + // return $t3 + $result := $t3 + } + + function A1_vector_length$u64$(v_ref) -> len { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + len := $LoadU64(v_ptr) + } function A1_option_destroy_none$A2_U256_U256$(t) { - let vec, $t2, $t3, $t4, $t5, $t6 + let $t1, $t2, $t3, $t4, $t5 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t4 := 0 - $t4 := 0 - // abort($t4) - $Abort($t4) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t5 := move($t0) - $t5 := t - // $t6 := unpack option::Option<#0>($t5) - $t6 := $MemoryLoadU256(add($t5, 0)) - $Free($t5, 32) - // vector::destroy_empty<#0>($t6) - A1_vector_destroy_empty$A2_U256_U256$($t6) - // return () - leave + // $t3 := 262144 + $t3 := 262144 + // abort($t3) + $Abort($t3) } case 4 { - // $t2 := borrow_local($t0) - $t2 := $MakePtr(false, t) - // $t3 := option::is_none<#0>($t2) - $t3 := A1_option_is_none$A2_U256_U256$($t2) - // if ($t3) goto L0 else goto L1 - switch $t3 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := borrow_local($t0) + $t1 := $MakePtr(false, t) + // $t2 := option::is_none<#0>($t1) + $t2 := A1_option_is_none$A2_U256_U256$($t1) + // if ($t2) goto L1 else goto L0 + switch $t2 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t4 := move($t0) + $t4 := t + // $t5 := unpack option::Option<#0>($t4) + $t5 := $MemoryLoadU256(add($t4, 0)) + $Free($t4, 32) + // vector::destroy_empty<#0>($t5) + A1_vector_destroy_empty$A2_U256_U256$($t5) + // return () + leave } } } + function A1_vector_destroy_empty$A2_U256_U256$(v) { + let size := $MemoryLoadU64(v) + if $LogicalNot(iszero(size)) { $AbortBuiltin() } + let capacity := $MemoryLoadU64(add(v, 8)) + $Free(v, add(32, mul(capacity, 32))) + } function A1_option_is_none$A2_U256_U256$(t) -> $result { let $t1, $t2 // $t1 := borrow_field>.vec($t0) @@ -2826,49 +2820,54 @@ object "test_A2_M_extract_value" { let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) len := $LoadU64(v_ptr) } - function A1_vector_destroy_empty$A2_U256_U256$(v) { - let size := $MemoryLoadU64(v) - if $LogicalNot(iszero(size)) { $AbortBuiltin() } - let capacity := $MemoryLoadU64(add(v, 8)) - $Free(v, add(32, mul(capacity, 32))) - } function A1_option_destroy_none$vec$u8$$(t) { - let vec, $t2, $t3, $t4, $t5, $t6 + let $t1, $t2, $t3, $t4, $t5 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t4 := 0 - $t4 := 0 - // abort($t4) - $Abort($t4) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t5 := move($t0) - $t5 := t - // $t6 := unpack option::Option<#0>($t5) - $t6 := $MemoryLoadU256(add($t5, 0)) - $Free($t5, 32) - // vector::destroy_empty<#0>($t6) - A1_vector_destroy_empty$vec$u8$$($t6) - // return () - leave + // $t3 := 262144 + $t3 := 262144 + // abort($t3) + $Abort($t3) } case 4 { - // $t2 := borrow_local($t0) - $t2 := $MakePtr(false, t) - // $t3 := option::is_none<#0>($t2) - $t3 := A1_option_is_none$vec$u8$$($t2) - // if ($t3) goto L0 else goto L1 - switch $t3 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := borrow_local($t0) + $t1 := $MakePtr(false, t) + // $t2 := option::is_none<#0>($t1) + $t2 := A1_option_is_none$vec$u8$$($t1) + // if ($t2) goto L1 else goto L0 + switch $t2 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t4 := move($t0) + $t4 := t + // $t5 := unpack option::Option<#0>($t4) + $t5 := $MemoryLoadU256(add($t4, 0)) + $Free($t4, 32) + // vector::destroy_empty<#0>($t5) + A1_vector_destroy_empty$vec$u8$$($t5) + // return () + leave } } } + function A1_vector_destroy_empty$vec$u8$$(v) { + let size := $MemoryLoadU64(v) + if $LogicalNot(iszero(size)) { $AbortBuiltin() } + let capacity := $MemoryLoadU64(add(v, 8)) + $Free(v, add(32, mul(capacity, 32))) + } function A1_option_is_none$vec$u8$$(t) -> $result { let $t1, $t2 // $t1 := borrow_field>.vec($t0) @@ -2896,11 +2895,132 @@ object "test_A2_M_extract_value" { let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) len := $LoadU64(v_ptr) } - function A1_vector_destroy_empty$vec$u8$$(v) { - let size := $MemoryLoadU64(v) - if $LogicalNot(iszero(size)) { $AbortBuiltin() } - let capacity := $MemoryLoadU64(add(v, 8)) - $Free(v, add(32, mul(capacity, 32))) + function A2_ExternalResult_is_ok$u64$(result) -> $result { + let $t1, $t2 + // $t1 := borrow_field>.value($t0) + { + $t1 := $MakePtr($IsStoragePtr(result), $LoadU256(result)) + } + // $t2 := option::is_some<#0>($t1) + $t2 := A1_option_is_some$u64$($t1) + // return $t2 + $result := $t2 + } + + function A2_M_pack_value$u64$(v) -> $result { + let $t1 + // $t1 := ExternalResult::ok<#0>($t0) + $t1 := A2_ExternalResult_ok$u64$(v) + // return $t1 + $result := $t1 + } + + function A2_ExternalResult_ok$u64$(value) -> $result { + let $t1, $t2, $t3, $t4, $t5 + // $t1 := option::some<#0>($t0) + $t1 := A1_option_some$u64$(value) + // $t2 := option::none>() + $t2 := A1_option_none$vec$u8$$() + // $t3 := option::none>() + $t3 := A1_option_none$vec$u8$$() + // $t4 := option::none() + $t4 := A1_option_none$A2_U256_U256$() + // $t5 := pack ExternalResult::ExternalResult<#0>($t1, $t2, $t3, $t4) + { + let $mem := $Malloc(128) + $MemoryStoreU256(add($mem, 0), $t1) + $MemoryStoreU256(add($mem, 32), $t2) + $MemoryStoreU256(add($mem, 64), $t3) + $MemoryStoreU256(add($mem, 96), $t4) + $t5 := $mem + } + // return $t5 + $result := $t5 + } + + function A1_option_none$A2_U256_U256$() -> $result { + let $t0, $t1 + // $t0 := vector::empty<#0>() + $t0 := A1_vector_empty$A2_U256_U256$() + // $t1 := pack option::Option<#0>($t0) + { + let $mem := $Malloc(32) + $MemoryStoreU256(add($mem, 0), $t0) + $t1 := $mem + } + // return $t1 + $result := $t1 + } + + function A1_vector_empty$A2_U256_U256$() -> vector { + vector := $Malloc(96) + $MemoryStoreU64(add(vector, 8), 2) + } + function A1_option_none$vec$u8$$() -> $result { + let $t0, $t1 + // $t0 := vector::empty<#0>() + $t0 := A1_vector_empty$vec$u8$$() + // $t1 := pack option::Option<#0>($t0) + { + let $mem := $Malloc(32) + $MemoryStoreU256(add($mem, 0), $t0) + $t1 := $mem + } + // return $t1 + $result := $t1 + } + + function A1_vector_empty$vec$u8$$() -> vector { + vector := $Malloc(96) + $MemoryStoreU64(add(vector, 8), 2) + } + function A1_option_some$u64$(e) -> $result { + let $t1, $t2 + // $t1 := vector::singleton<#0>($t0) + $t1 := A1_vector_singleton$u64$(e) + // $t2 := pack option::Option<#0>($t1) + { + let $mem := $Malloc(32) + $MemoryStoreU256(add($mem, 0), $t1) + $t2 := $mem + } + // return $t2 + $result := $t2 + } + + function A1_vector_singleton$u64$(e) -> $result { + let $t2, $t3 + let $locals := $Malloc(32) + // $t1 := vector::empty<#0>() + mstore($locals, A1_vector_empty$u64$()) + // $t2 := borrow_local($t1) + $t2 := $MakePtr(false, $locals) + // vector::push_back<#0>($t2, $t0) + A1_vector_push_back$u64$($t2, e) + // $t3 := move($t1) + $t3 := mload($locals) + // return $t3 + $result := $t3 + $Free($locals, 32) + } + + function A1_vector_push_back$u64$(v_ref, e) { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + let size := $LoadU64(v_ptr) + let e_ptr := $IndexPtr(v_ptr, add(32, mul(size, 8))) + $StoreU64(e_ptr, e) + size := add(size, 1) + $StoreU64(v_ptr, size) + let capacity := $LoadU64($IndexPtr(v_ptr, 8)) + if and(iszero($IsStoragePtr(v_ptr)), eq(size, capacity)) { + let new_v_offs := $ResizeVector(v_offs, capacity, 8) + $StoreU256(v_ref, new_v_offs) + } + } + function A1_vector_empty$u64$() -> vector { + vector := $Malloc(48) + $MemoryStoreU64(add(vector, 8), 2) } function $Abort(code) { mstore(0, code) @@ -3107,4 +3227,4 @@ object "test_A2_M_extract_value" { } } } -===> Test result of M::extract_value: Succeed(Stopped) (used_gas=4408): [] +===> Test result of M::extract_value: Succeed(Stopped) (used_gas=5103): [] diff --git a/language/evm/move-to-yul/tests/TestStringLiteral.exp b/language/evm/move-to-yul/tests/TestStringLiteral.exp index 78d191c3b8..7ff6ff55a5 100644 --- a/language/evm/move-to-yul/tests/TestStringLiteral.exp +++ b/language/evm/move-to-yul/tests/TestStringLiteral.exp @@ -47,65 +47,51 @@ object "test_A2_M_h1" { A2_M_h1() return (0, 0) function A2_M_h1() { - let t, x, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20, $t21, $t22, $t23, $t24, $t25, $t26, $t27, $t28, $t29, $t30, $t31, $t32, $t33, $t34, $t35, $t36, $t37, $t38, $t39, $t40, $t41, $t42, $t43, $t44, $t45, $t46, $t47, $t48, $t49, $t50, $t51, $t52, $t53, $t54, $t55, $t56, $t57, $t58, $t59, $t60, $t61, $t62, $t63, $t64, $t65, $t66, $t67, $t68, $t69, $t70, $t71, $t72, $t73, $t74, $t75, $t76, $t77 + let $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14, $t15, $t16, $t17, $t18, $t19, $t20, $t21, $t22, $t23, $t24, $t25, $t26, $t27, $t28, $t29, $t30, $t31, $t32, $t33, $t34, $t35, $t36, $t37, $t38, $t39, $t40, $t41, $t42, $t43, $t44, $t45, $t46, $t47, $t48, $t49, $t50, $t51, $t52, $t53, $t54, $t55, $t56, $t57, $t58, $t59, $t60, $t61, $t62, $t63, $t64, $t65, $t66, $t67, $t68, $t69, $t70, $t71, $t72, $t73, $t74, $t75 let $locals := $Malloc(96) let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t16 := 96 - $t16 := 96 - // abort($t16) - $Abort($t16) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t17 := borrow_local($t2) - $t17 := $MakePtr(false, add($locals, 32)) - // $t18 := 0 - $t18 := 0 - // $t19 := vector::borrow($t17, $t18) - $t19 := A1_vector_borrow$u8$($t17, $t18) - // $t20 := read_ref($t19) - $t20 := $LoadU8($t19) - // $t21 := 97 - $t21 := 97 - // $t22 := ==($t20, $t21) - $t22 := $Eq($t20, $t21) - // if ($t22) goto L2 else goto L3 - switch $t22 - case 0 { $block := 5 } - default { $block := 6 } + // $t14 := 96 + $t14 := 96 + // abort($t14) + $Abort($t14) } case 4 { - // $t5 := 0x3 - $t5 := 0x3 - // $t0 := Evm::sign($t5) - mstore($locals, A2_Evm_sign($t5)) - // $t6 := borrow_local($t0) - $t6 := $MakePtr(false, $locals) - // $t7 := [97, 98, 99] - $t7 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(3))) - $MemoryStoreU64($t7, 3) - $MemoryStoreU64(add($t7, 8), $ClosestGreaterPowerOfTwo(3)) - copy_literal_string_to_memory_2053440334(add($t7, 32)) - // $t8 := pack M::T($t7) + // $t3 := 0x3 + $t3 := 0x3 + // $t0 := Evm::sign($t3) + mstore($locals, A2_Evm_sign($t3)) + // $t4 := borrow_local($t0) + $t4 := $MakePtr(false, $locals) + // $t5 := [97, 98, 99] + $t5 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(3))) + $MemoryStoreU64($t5, 3) + $MemoryStoreU64(add($t5, 8), $ClosestGreaterPowerOfTwo(3)) + copy_literal_string_to_memory_2053440334(add($t5, 32)) + // $t6 := pack M::T($t5) { let $mem := $Malloc(32) - $MemoryStoreU256(add($mem, 0), $t7) - $t8 := $mem + $MemoryStoreU256(add($mem, 0), $t5) + $t6 := $mem } - // move_to($t8, $t6) + // move_to($t6, $t4) { - let $base_offset := $MakeTypeStorageBase(0, 0x3948ca0a, $LoadU256($t6)) + let $base_offset := $MakeTypeStorageBase(0, 0x3948ca0a, $LoadU256($t4)) if $AlignedStorageLoad($base_offset) { $AbortBuiltin() } $AlignedStorageStore($base_offset, true) { let $dst := add($base_offset, 32) - let $src := $t8 + let $src := $t6 { let $linked_src_2300595445 := mload(add($src, 0)) let $linked_dst_2300595445 := $NewLinkedStorageBase(0x89204cf5) @@ -123,21 +109,21 @@ object "test_A2_M_h1" { $Free($src, 32) } } - // $t9 := 0x3 - $t9 := 0x3 - // $t10 := borrow_global($t9) + // $t7 := 0x3 + $t7 := 0x3 + // $t8 := borrow_global($t7) { - let $base_offset := $MakeTypeStorageBase(0, 0x3948ca0a, $t9) + let $base_offset := $MakeTypeStorageBase(0, 0x3948ca0a, $t7) if iszero($AlignedStorageLoad($base_offset)) { $AbortBuiltin() } - $t10 := $MakePtr(true, add($base_offset, 32)) + $t8 := $MakePtr(true, add($base_offset, 32)) } - // $t11 := borrow_field.s($t10) - $t11 := $t10 - // $t2 := read_ref($t11) - mstore(add($locals, 32), $LoadU256($t11)) - if $IsStoragePtr($t11){ + // $t9 := borrow_field.s($t8) + $t9 := $t8 + // $t1 := read_ref($t9) + mstore(add($locals, 32), $LoadU256($t9)) + if $IsStoragePtr($t9){ let $storage_ptr_2300595445 let $size_2300595445 := $StorageLoadU64(mload(add($locals, 32))) let $capacity_2300595445 := $ClosestGreaterPowerOfTwo($size_2300595445) @@ -152,126 +138,160 @@ object "test_A2_M_h1" { } mstore(add($locals, 32), $storage_ptr_2300595445) } - // $t12 := borrow_local($t2) - $t12 := $MakePtr(false, add($locals, 32)) - // $t13 := vector::length($t12) - $t13 := A1_vector_length$u8$($t12) - // $t14 := 3 - $t14 := 3 - // $t15 := ==($t13, $t14) - $t15 := $Eq($t13, $t14) - // if ($t15) goto L0 else goto L1 - switch $t15 - case 0 { $block := 2 } - default { $block := 3 } + // $t10 := borrow_local($t1) + $t10 := $MakePtr(false, add($locals, 32)) + // $t11 := vector::length($t10) + $t11 := A1_vector_length$u8$($t10) + // $t12 := 3 + $t12 := 3 + // $t13 := ==($t11, $t12) + $t13 := $Eq($t11, $t12) + // if ($t13) goto L1 else goto L0 + switch $t13 + case 0 { $block := 3 } + default { $block := 2 } } case 5 { - // label L3 - // $t23 := 97 - $t23 := 97 - // abort($t23) - $Abort($t23) - } - case 6 { // label L2 - // $t24 := borrow_local($t2) - $t24 := $MakePtr(false, add($locals, 32)) - // $t25 := 1 - $t25 := 1 - // $t26 := vector::borrow($t24, $t25) - $t26 := A1_vector_borrow$u8$($t24, $t25) - // $t27 := read_ref($t26) - $t27 := $LoadU8($t26) - // $t28 := 98 - $t28 := 98 - // $t29 := ==($t27, $t28) - $t29 := $Eq($t27, $t28) - // if ($t29) goto L4 else goto L5 - switch $t29 + // $t15 := borrow_local($t1) + $t15 := $MakePtr(false, add($locals, 32)) + // $t16 := 0 + $t16 := 0 + // $t17 := vector::borrow($t15, $t16) + $t17 := A1_vector_borrow$u8$($t15, $t16) + // $t18 := read_ref($t17) + $t18 := $LoadU8($t17) + // $t19 := 97 + $t19 := 97 + // $t20 := ==($t18, $t19) + $t20 := $Eq($t18, $t19) + // if ($t20) goto L4 else goto L3 + switch $t20 case 0 { $block := 7 } - default { $block := 8 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 } case 7 { - // label L5 - // $t30 := 98 - $t30 := 98 - // abort($t30) - $Abort($t30) + // label L3 + // $t21 := 97 + $t21 := 97 + // abort($t21) + $Abort($t21) } case 8 { - // label L4 - // $t31 := borrow_local($t2) - $t31 := $MakePtr(false, add($locals, 32)) - // $t32 := 2 - $t32 := 2 - // $t33 := vector::borrow($t31, $t32) - $t33 := A1_vector_borrow$u8$($t31, $t32) - // $t34 := read_ref($t33) - $t34 := $LoadU8($t33) - // $t35 := 99 - $t35 := 99 - // $t36 := ==($t34, $t35) - $t36 := $Eq($t34, $t35) - // if ($t36) goto L6 else goto L7 - switch $t36 - case 0 { $block := 9 } - default { $block := 10 } + // label L5 + // $t22 := borrow_local($t1) + $t22 := $MakePtr(false, add($locals, 32)) + // $t23 := 1 + $t23 := 1 + // $t24 := vector::borrow($t22, $t23) + $t24 := A1_vector_borrow$u8$($t22, $t23) + // $t25 := read_ref($t24) + $t25 := $LoadU8($t24) + // $t26 := 98 + $t26 := 98 + // $t27 := ==($t25, $t26) + $t27 := $Eq($t25, $t26) + // if ($t27) goto L7 else goto L6 + switch $t27 + case 0 { $block := 10 } + default { $block := 9 } } case 9 { // label L7 - // $t37 := 99 - $t37 := 99 - // abort($t37) - $Abort($t37) + // goto L8 + $block := 11 } case 10 { // label L6 - // $t38 := [101, 102, 103, 104] - $t38 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(4))) - $MemoryStoreU64($t38, 4) - $MemoryStoreU64(add($t38, 8), $ClosestGreaterPowerOfTwo(4)) - copy_literal_string_to_memory_2788570470(add($t38, 32)) - // $t39 := 0x3 - $t39 := 0x3 - // $t40 := borrow_global($t39) + // $t28 := 98 + $t28 := 98 + // abort($t28) + $Abort($t28) + } + case 11 { + // label L8 + // $t29 := borrow_local($t1) + $t29 := $MakePtr(false, add($locals, 32)) + // $t30 := 2 + $t30 := 2 + // $t31 := vector::borrow($t29, $t30) + $t31 := A1_vector_borrow$u8$($t29, $t30) + // $t32 := read_ref($t31) + $t32 := $LoadU8($t31) + // $t33 := 99 + $t33 := 99 + // $t34 := ==($t32, $t33) + $t34 := $Eq($t32, $t33) + // if ($t34) goto L10 else goto L9 + switch $t34 + case 0 { $block := 13 } + default { $block := 12 } + } + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 + // $t35 := 99 + $t35 := 99 + // abort($t35) + $Abort($t35) + } + case 14 { + // label L11 + // $t36 := [101, 102, 103, 104] + $t36 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(4))) + $MemoryStoreU64($t36, 4) + $MemoryStoreU64(add($t36, 8), $ClosestGreaterPowerOfTwo(4)) + copy_literal_string_to_memory_2788570470(add($t36, 32)) + // $t37 := 0x3 + $t37 := 0x3 + // $t38 := borrow_global($t37) { - let $base_offset := $MakeTypeStorageBase(0, 0x3948ca0a, $t39) + let $base_offset := $MakeTypeStorageBase(0, 0x3948ca0a, $t37) if iszero($AlignedStorageLoad($base_offset)) { $AbortBuiltin() } - $t40 := $MakePtr(true, add($base_offset, 32)) + $t38 := $MakePtr(true, add($base_offset, 32)) } - // $t41 := borrow_field.s($t40) - $t41 := $t40 - // write_ref($t41, $t38) - if $IsStoragePtr($t41){ + // $t39 := borrow_field.s($t38) + $t39 := $t38 + // write_ref($t39, $t36) + if $IsStoragePtr($t39){ let $storage_ptr_2300595445 := $NewLinkedStorageBase(0x89204cf5) - let $size_2300595445 := $MemoryLoadU64($t38) + let $size_2300595445 := $MemoryLoadU64($t36) let $data_size_2300595445 := mul($size_2300595445, 1) - $AlignedStorageStore($storage_ptr_2300595445, mload($t38)) - let $data_src_2300595445 := add($t38, 32) + $AlignedStorageStore($storage_ptr_2300595445, mload($t36)) + let $data_src_2300595445 := add($t36, 32) let $data_dst_2300595445 := add($storage_ptr_2300595445, 32) for { let $offs_2300595445 := 0 } lt($offs_2300595445, $data_size_2300595445) { $offs_2300595445 := add($offs_2300595445, 32)} { $AlignedStorageStore(add($data_dst_2300595445, $offs_2300595445), mload(add($data_src_2300595445, $offs_2300595445))) } - $t38 := $storage_ptr_2300595445 + $t36 := $storage_ptr_2300595445 } - $StoreU256($t41, $t38) - // $t42 := 0x3 - $t42 := 0x3 - // $t43 := borrow_global($t42) + $StoreU256($t39, $t36) + // $t40 := 0x3 + $t40 := 0x3 + // $t41 := borrow_global($t40) { - let $base_offset := $MakeTypeStorageBase(0, 0x3948ca0a, $t42) + let $base_offset := $MakeTypeStorageBase(0, 0x3948ca0a, $t40) if iszero($AlignedStorageLoad($base_offset)) { $AbortBuiltin() } - $t43 := $MakePtr(true, add($base_offset, 32)) + $t41 := $MakePtr(true, add($base_offset, 32)) } - // $t44 := borrow_field.s($t43) - $t44 := $t43 - // $t3 := read_ref($t44) - mstore(add($locals, 64), $LoadU256($t44)) - if $IsStoragePtr($t44){ + // $t42 := borrow_field.s($t41) + $t42 := $t41 + // $t2 := read_ref($t42) + mstore(add($locals, 64), $LoadU256($t42)) + if $IsStoragePtr($t42){ let $storage_ptr_2300595445 let $size_2300595445 := $StorageLoadU64(mload(add($locals, 64))) let $capacity_2300595445 := $ClosestGreaterPowerOfTwo($size_2300595445) @@ -286,132 +306,157 @@ object "test_A2_M_h1" { } mstore(add($locals, 64), $storage_ptr_2300595445) } - // $t45 := borrow_local($t3) - $t45 := $MakePtr(false, add($locals, 64)) - // $t46 := vector::length($t45) - $t46 := A1_vector_length$u8$($t45) - // $t47 := 4 - $t47 := 4 - // $t48 := ==($t46, $t47) - $t48 := $Eq($t46, $t47) - // if ($t48) goto L8 else goto L9 - switch $t48 - case 0 { $block := 11 } - default { $block := 12 } + // $t43 := borrow_local($t2) + $t43 := $MakePtr(false, add($locals, 64)) + // $t44 := vector::length($t43) + $t44 := A1_vector_length$u8$($t43) + // $t45 := 4 + $t45 := 4 + // $t46 := ==($t44, $t45) + $t46 := $Eq($t44, $t45) + // if ($t46) goto L13 else goto L12 + switch $t46 + case 0 { $block := 16 } + default { $block := 15 } } - case 11 { - // label L9 - // $t49 := 100 - $t49 := 100 - // abort($t49) - $Abort($t49) + case 15 { + // label L13 + // goto L14 + $block := 17 } - case 12 { - // label L8 - // $t50 := borrow_local($t3) - $t50 := $MakePtr(false, add($locals, 64)) - // $t51 := 0 - $t51 := 0 - // $t52 := vector::borrow($t50, $t51) - $t52 := A1_vector_borrow$u8$($t50, $t51) - // $t53 := read_ref($t52) - $t53 := $LoadU8($t52) + case 16 { + // label L12 + // $t47 := 100 + $t47 := 100 + // abort($t47) + $Abort($t47) + } + case 17 { + // label L14 + // $t48 := borrow_local($t2) + $t48 := $MakePtr(false, add($locals, 64)) + // $t49 := 0 + $t49 := 0 + // $t50 := vector::borrow($t48, $t49) + $t50 := A1_vector_borrow$u8$($t48, $t49) + // $t51 := read_ref($t50) + $t51 := $LoadU8($t50) + // $t52 := 101 + $t52 := 101 + // $t53 := ==($t51, $t52) + $t53 := $Eq($t51, $t52) + // if ($t53) goto L16 else goto L15 + switch $t53 + case 0 { $block := 19 } + default { $block := 18 } + } + case 18 { + // label L16 + // goto L17 + $block := 20 + } + case 19 { + // label L15 // $t54 := 101 $t54 := 101 - // $t55 := ==($t53, $t54) - $t55 := $Eq($t53, $t54) - // if ($t55) goto L10 else goto L11 - switch $t55 - case 0 { $block := 13 } - default { $block := 14 } + // abort($t54) + $Abort($t54) } - case 13 { - // label L11 - // $t56 := 101 - $t56 := 101 - // abort($t56) - $Abort($t56) + case 20 { + // label L17 + // $t55 := borrow_local($t2) + $t55 := $MakePtr(false, add($locals, 64)) + // $t56 := 1 + $t56 := 1 + // $t57 := vector::borrow($t55, $t56) + $t57 := A1_vector_borrow$u8$($t55, $t56) + // $t58 := read_ref($t57) + $t58 := $LoadU8($t57) + // $t59 := 102 + $t59 := 102 + // $t60 := ==($t58, $t59) + $t60 := $Eq($t58, $t59) + // if ($t60) goto L19 else goto L18 + switch $t60 + case 0 { $block := 22 } + default { $block := 21 } } - case 14 { - // label L10 - // $t57 := borrow_local($t3) - $t57 := $MakePtr(false, add($locals, 64)) - // $t58 := 1 - $t58 := 1 - // $t59 := vector::borrow($t57, $t58) - $t59 := A1_vector_borrow$u8$($t57, $t58) - // $t60 := read_ref($t59) - $t60 := $LoadU8($t59) + case 21 { + // label L19 + // goto L20 + $block := 23 + } + case 22 { + // label L18 // $t61 := 102 $t61 := 102 - // $t62 := ==($t60, $t61) - $t62 := $Eq($t60, $t61) - // if ($t62) goto L12 else goto L13 - switch $t62 - case 0 { $block := 15 } - default { $block := 16 } + // abort($t61) + $Abort($t61) } - case 15 { - // label L13 - // $t63 := 102 - $t63 := 102 - // abort($t63) - $Abort($t63) + case 23 { + // label L20 + // $t62 := borrow_local($t2) + $t62 := $MakePtr(false, add($locals, 64)) + // $t63 := 2 + $t63 := 2 + // $t64 := vector::borrow($t62, $t63) + $t64 := A1_vector_borrow$u8$($t62, $t63) + // $t65 := read_ref($t64) + $t65 := $LoadU8($t64) + // $t66 := 103 + $t66 := 103 + // $t67 := ==($t65, $t66) + $t67 := $Eq($t65, $t66) + // if ($t67) goto L22 else goto L21 + switch $t67 + case 0 { $block := 25 } + default { $block := 24 } } - case 16 { - // label L12 - // $t64 := borrow_local($t3) - $t64 := $MakePtr(false, add($locals, 64)) - // $t65 := 2 - $t65 := 2 - // $t66 := vector::borrow($t64, $t65) - $t66 := A1_vector_borrow$u8$($t64, $t65) - // $t67 := read_ref($t66) - $t67 := $LoadU8($t66) + case 24 { + // label L22 + // goto L23 + $block := 26 + } + case 25 { + // label L21 // $t68 := 103 $t68 := 103 - // $t69 := ==($t67, $t68) - $t69 := $Eq($t67, $t68) - // if ($t69) goto L14 else goto L15 - switch $t69 - case 0 { $block := 17 } - default { $block := 18 } + // abort($t68) + $Abort($t68) } - case 17 { - // label L15 - // $t70 := 103 - $t70 := 103 - // abort($t70) - $Abort($t70) + case 26 { + // label L23 + // $t69 := borrow_local($t2) + $t69 := $MakePtr(false, add($locals, 64)) + // $t70 := 3 + $t70 := 3 + // $t71 := vector::borrow($t69, $t70) + $t71 := A1_vector_borrow$u8$($t69, $t70) + // $t72 := read_ref($t71) + $t72 := $LoadU8($t71) + // $t73 := 104 + $t73 := 104 + // $t74 := ==($t72, $t73) + $t74 := $Eq($t72, $t73) + // if ($t74) goto L25 else goto L24 + switch $t74 + case 0 { $block := 28 } + default { $block := 27 } } - case 18 { - // label L14 - // $t71 := borrow_local($t3) - $t71 := $MakePtr(false, add($locals, 64)) - // $t72 := 3 - $t72 := 3 - // $t73 := vector::borrow($t71, $t72) - $t73 := A1_vector_borrow$u8$($t71, $t72) - // $t74 := read_ref($t73) - $t74 := $LoadU8($t73) + case 27 { + // label L25 + // goto L26 + $block := 29 + } + case 28 { + // label L24 // $t75 := 104 $t75 := 104 - // $t76 := ==($t74, $t75) - $t76 := $Eq($t74, $t75) - // if ($t76) goto L16 else goto L17 - switch $t76 - case 0 { $block := 19 } - default { $block := 20 } - } - case 19 { - // label L17 - // $t77 := 104 - $t77 := 104 - // abort($t77) - $Abort($t77) + // abort($t75) + $Abort($t75) } - case 20 { - // label L16 + case 29 { + // label L26 // return () $Free($locals, 96) leave @@ -669,7 +714,7 @@ object "test_A2_M_h1" { } } } -===> Test result of M::h1: Succeed(Stopped) (used_gas=166469): [] +===> Test result of M::h1: Succeed(Stopped) (used_gas=170443): [] // test of M::test_same_literals /* ======================================= @@ -711,21 +756,21 @@ object "test_A2_M_test_same_literals" { for {} true {} { switch $block case 2 { - // label L0 + // label L1 // Evm::abort_with($t1) A2_Evm_abort_with(message) - // goto L2 + // goto L0 $block := 3 } case 3 { - // label L2 + // label L0 // return () leave } case 4 { // $t2 := !($t0) $t2 := $LogicalNot(cond) - // if ($t2) goto L0 else goto L2 + // if ($t2) goto L1 else goto L0 switch $t2 case 0 { $block := 3 } default { $block := 2 } diff --git a/language/evm/move-to-yul/tests/U256Arith.exp b/language/evm/move-to-yul/tests/U256Arith.exp index b1bdfef100..1a2b2270f1 100644 --- a/language/evm/move-to-yul/tests/U256Arith.exp +++ b/language/evm/move-to-yul/tests/U256Arith.exp @@ -308,27 +308,27 @@ object "A2_U256Arith" { } function A2_U256Arith_shl() -> $result { - let x, $t1, $t2, $t3 - // $t1 := 2041694201525630780780247644590609268738 - $t1 := 2041694201525630780780247644590609268738 - // $t2 := 127 - $t2 := 127 - // $t3 := <<($t1, $t2) - $t3 := $ShlU256($t1, $t2) - // return $t3 - $result := $t3 + let $t0, $t1, $t2 + // $t0 := 2041694201525630780780247644590609268738 + $t0 := 2041694201525630780780247644590609268738 + // $t1 := 127 + $t1 := 127 + // $t2 := <<($t0, $t1) + $t2 := $ShlU256($t0, $t1) + // return $t2 + $result := $t2 } function A2_U256Arith_shr() -> $result { - let x, $t1, $t2, $t3 - // $t1 := 2041694201525630780780247644590609268738 - $t1 := 2041694201525630780780247644590609268738 - // $t2 := 127 - $t2 := 127 - // $t3 := >>($t1, $t2) - $t3 := $Shr($t1, $t2) - // return $t3 - $result := $t3 + let $t0, $t1, $t2 + // $t0 := 2041694201525630780780247644590609268738 + $t0 := 2041694201525630780780247644590609268738 + // $t1 := 127 + $t1 := 127 + // $t2 := >>($t0, $t1) + $t2 := $Shr($t0, $t1) + // return $t2 + $result := $t2 } function A2_U256Arith_sub() -> $result { diff --git a/language/evm/move-to-yul/tests/Vectors.exp b/language/evm/move-to-yul/tests/Vectors.exp index ed194e1cc6..6bca84ca77 100644 --- a/language/evm/move-to-yul/tests/Vectors.exp +++ b/language/evm/move-to-yul/tests/Vectors.exp @@ -38,13 +38,34 @@ object "A2_Vectors" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t5 := 101 $t5 := 101 // abort($t5) $Abort($t5) } - case 3 { - // label L0 + case 4 { + // $t0 := Vectors::one_elem_u64() + mstore($locals, A2_Vectors_one_elem_u64()) + // $t1 := borrow_local($t0) + $t1 := $MakePtr(false, $locals) + // $t2 := vector::length($t1) + $t2 := A1_vector_length$u64$($t1) + // $t3 := 1 + $t3 := 1 + // $t4 := ==($t2, $t3) + $t4 := $Eq($t2, $t3) + // if ($t4) goto L1 else goto L0 + switch $t4 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t6 := borrow_local($t0) $t6 := $MakePtr(false, $locals) // $t7 := 0 @@ -57,36 +78,25 @@ object "A2_Vectors" { $t10 := 42 // $t11 := ==($t9, $t10) $t11 := $Eq($t9, $t10) - // if ($t11) goto L2 else goto L3 + // if ($t11) goto L4 else goto L3 switch $t11 - case 0 { $block := 5 } + case 0 { $block := 7 } default { $block := 6 } } - case 4 { - // $t0 := Vectors::one_elem_u64() - mstore($locals, A2_Vectors_one_elem_u64()) - // $t1 := borrow_local($t0) - $t1 := $MakePtr(false, $locals) - // $t2 := vector::length($t1) - $t2 := A1_vector_length$u64$($t1) - // $t3 := 1 - $t3 := 1 - // $t4 := ==($t2, $t3) - $t4 := $Eq($t2, $t3) - // if ($t4) goto L0 else goto L1 - switch $t4 - case 0 { $block := 2 } - default { $block := 3 } + case 6 { + // label L4 + // goto L5 + $block := 8 } - case 5 { + case 7 { // label L3 // $t12 := 102 $t12 := 102 // abort($t12) $Abort($t12) } - case 6 { - // label L2 + case 8 { + // label L5 // return () $Free($locals, 32) leave @@ -94,6 +104,13 @@ object "A2_Vectors" { } } + function A1_vector_borrow$u64$(v_ref, i) -> e_ptr { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + let size := $LoadU64(v_ptr) + if $GtEq(i, size) { $AbortBuiltin() } + e_ptr := $IndexPtr(v_ptr, add(32, mul(i, 8))) + } function A1_vector_length$u64$(v_ref) -> len { let v_offs := $LoadU256(v_ref) let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) @@ -135,13 +152,6 @@ object "A2_Vectors" { vector := $Malloc(48) $MemoryStoreU64(add(vector, 8), 2) } - function A1_vector_borrow$u64$(v_ref, i) -> e_ptr { - let v_offs := $LoadU256(v_ref) - let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) - let size := $LoadU64(v_ptr) - if $GtEq(i, size) { $AbortBuiltin() } - e_ptr := $IndexPtr(v_ptr, add(32, mul(i, 8))) - } function abi_encode_tuple__(headStart ) -> tail { tail := add(headStart, 0) } @@ -383,17 +393,16 @@ object "test_A2_Vectors_test_borrow_fail" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t7 := 101 $t7 := 101 // abort($t7) $Abort($t7) } - case 3 { - // label L0 - // return () - $Free($locals, 32) - leave - } case 4 { // $t0 := Vectors::empty_vector() mstore($locals, A2_Vectors_empty_vector()) @@ -409,10 +418,16 @@ object "test_A2_Vectors_test_borrow_fail" { $t5 := 0 // $t6 := ==($t4, $t5) $t6 := $Eq($t4, $t5) - // if ($t6) goto L0 else goto L1 + // if ($t6) goto L1 else goto L0 switch $t6 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // return () + $Free($locals, 32) + leave } } } @@ -565,7 +580,7 @@ object "test_A2_Vectors_test_borrow_fail" { } } } -===> Test result of Vectors::test_borrow_fail: Revert(Reverted) (used_gas=468): [255, 255, 255, 255, 255, 255, 255, 255] +===> Test result of Vectors::test_borrow_fail: Revert(Reverted) (used_gas=470): [255, 255, 255, 255, 255, 255, 255, 255] // test of Vectors::test_borrow_mut /* ======================================= @@ -586,32 +601,16 @@ object "test_A2_Vectors_test_borrow_mut" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t24 := 101 $t24 := 101 // abort($t24) $Abort($t24) } - case 3 { - // label L0 - // $t25 := borrow_local($t2) - $t25 := $MakePtr(false, $locals) - // $t26 := 0 - $t26 := 0 - // $t27 := vector::borrow($t25, $t26) - $t27 := A1_vector_borrow$A2_Vectors_S$($t25, $t26) - // $t28 := borrow_field.y($t27) - $t28 := $IndexPtr($t27, 24) - // $t29 := read_ref($t28) - $t29 := $LoadU8($t28) - // $t30 := false - $t30 := false - // $t31 := ==($t29, $t30) - $t31 := $Eq($t29, $t30) - // if ($t31) goto L2 else goto L3 - switch $t31 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t2 := Vectors::one_elem_struct() mstore($locals, A2_Vectors_one_elem_struct()) @@ -671,20 +670,46 @@ object "test_A2_Vectors_test_borrow_mut" { $t22 := 90 // $t23 := ==($t21, $t22) $t23 := $Eq($t21, $t22) - // if ($t23) goto L0 else goto L1 + // if ($t23) goto L1 else goto L0 switch $t23 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t25 := borrow_local($t2) + $t25 := $MakePtr(false, $locals) + // $t26 := 0 + $t26 := 0 + // $t27 := vector::borrow($t25, $t26) + $t27 := A1_vector_borrow$A2_Vectors_S$($t25, $t26) + // $t28 := borrow_field.y($t27) + $t28 := $IndexPtr($t27, 24) + // $t29 := read_ref($t28) + $t29 := $LoadU8($t28) + // $t30 := false + $t30 := false + // $t31 := ==($t29, $t30) + $t31 := $Eq($t29, $t30) + // if ($t31) goto L4 else goto L3 + switch $t31 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t32 := 102 $t32 := 102 // abort($t32) $Abort($t32) } - case 6 { - // label L2 + case 8 { + // label L5 // $t33 := borrow_local($t2) $t33 := $MakePtr(false, $locals) // $t34 := 0 @@ -699,20 +724,25 @@ object "test_A2_Vectors_test_borrow_mut" { $t38 := 1028 // $t39 := ==($t37, $t38) $t39 := $Eq($t37, $t38) - // if ($t39) goto L4 else goto L5 + // if ($t39) goto L7 else goto L6 switch $t39 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t40 := 103 $t40 := 103 // abort($t40) $Abort($t40) } - case 8 { - // label L4 + case 11 { + // label L8 // $t41 := borrow_local($t2) $t41 := $MakePtr(false, $locals) // $t42 := 1 @@ -727,20 +757,25 @@ object "test_A2_Vectors_test_borrow_mut" { $t46 := 45 // $t47 := ==($t45, $t46) $t47 := $Eq($t45, $t46) - // if ($t47) goto L6 else goto L7 + // if ($t47) goto L10 else goto L9 switch $t47 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t48 := 104 $t48 := 104 // abort($t48) $Abort($t48) } - case 10 { - // label L6 + case 14 { + // label L11 // $t49 := borrow_local($t2) $t49 := $MakePtr(false, $locals) // $t50 := 1 @@ -755,20 +790,25 @@ object "test_A2_Vectors_test_borrow_mut" { $t54 := false // $t55 := ==($t53, $t54) $t55 := $Eq($t53, $t54) - // if ($t55) goto L8 else goto L9 + // if ($t55) goto L13 else goto L12 switch $t55 - case 0 { $block := 11 } - default { $block := 12 } + case 0 { $block := 16 } + default { $block := 15 } } - case 11 { - // label L9 + case 15 { + // label L13 + // goto L14 + $block := 17 + } + case 16 { + // label L12 // $t56 := 105 $t56 := 105 // abort($t56) $Abort($t56) } - case 12 { - // label L8 + case 17 { + // label L14 // $t57 := borrow_local($t2) $t57 := $MakePtr(false, $locals) // $t58 := 1 @@ -783,20 +823,25 @@ object "test_A2_Vectors_test_borrow_mut" { $t62 := 123 // $t63 := ==($t61, $t62) $t63 := $Eq($t61, $t62) - // if ($t63) goto L10 else goto L11 + // if ($t63) goto L16 else goto L15 switch $t63 - case 0 { $block := 13 } - default { $block := 14 } + case 0 { $block := 19 } + default { $block := 18 } } - case 13 { - // label L11 + case 18 { + // label L16 + // goto L17 + $block := 20 + } + case 19 { + // label L15 // $t64 := 106 $t64 := 106 // abort($t64) $Abort($t64) } - case 14 { - // label L10 + case 20 { + // label L17 // $t65 := borrow_local($t2) $t65 := $MakePtr(false, $locals) // $t66 := 1 @@ -835,20 +880,25 @@ object "test_A2_Vectors_test_borrow_mut" { $t79 := 10 // $t80 := ==($t78, $t79) $t80 := $Eq($t78, $t79) - // if ($t80) goto L12 else goto L13 + // if ($t80) goto L19 else goto L18 switch $t80 - case 0 { $block := 15 } - default { $block := 16 } + case 0 { $block := 22 } + default { $block := 21 } } - case 15 { - // label L13 + case 21 { + // label L19 + // goto L20 + $block := 23 + } + case 22 { + // label L18 // $t81 := 107 $t81 := 107 // abort($t81) $Abort($t81) } - case 16 { - // label L12 + case 23 { + // label L20 // $t82 := borrow_local($t2) $t82 := $MakePtr(false, $locals) // $t83 := 1 @@ -863,20 +913,25 @@ object "test_A2_Vectors_test_borrow_mut" { $t87 := true // $t88 := ==($t86, $t87) $t88 := $Eq($t86, $t87) - // if ($t88) goto L14 else goto L15 + // if ($t88) goto L22 else goto L21 switch $t88 - case 0 { $block := 17 } - default { $block := 18 } + case 0 { $block := 25 } + default { $block := 24 } } - case 17 { - // label L15 + case 24 { + // label L22 + // goto L23 + $block := 26 + } + case 25 { + // label L21 // $t89 := 108 $t89 := 108 // abort($t89) $Abort($t89) } - case 18 { - // label L14 + case 26 { + // label L23 // $t90 := borrow_local($t2) $t90 := $MakePtr(false, $locals) // $t91 := 1 @@ -891,20 +946,25 @@ object "test_A2_Vectors_test_borrow_mut" { $t95 := 456 // $t96 := ==($t94, $t95) $t96 := $Eq($t94, $t95) - // if ($t96) goto L16 else goto L17 + // if ($t96) goto L25 else goto L24 switch $t96 - case 0 { $block := 19 } - default { $block := 20 } + case 0 { $block := 28 } + default { $block := 27 } } - case 19 { - // label L17 + case 27 { + // label L25 + // goto L26 + $block := 29 + } + case 28 { + // label L24 // $t97 := 109 $t97 := 109 // abort($t97) $Abort($t97) } - case 20 { - // label L16 + case 29 { + // label L26 // return () $Free($locals, 32) leave @@ -1271,7 +1331,7 @@ object "test_A2_Vectors_test_borrow_mut" { } } } -===> Test result of Vectors::test_borrow_mut: Succeed(Stopped) (used_gas=10908): [] +===> Test result of Vectors::test_borrow_mut: Succeed(Stopped) (used_gas=14880): [] // test of Vectors::test_destroy_empty /* ======================================= @@ -1285,11 +1345,11 @@ object "test_A2_Vectors_test_destroy_empty" { A2_Vectors_test_destroy_empty() return (0, 0) function A2_Vectors_test_destroy_empty() { - let v, $t1 - // $t1 := vector::empty
() - $t1 := A1_vector_empty$address$() - // vector::destroy_empty
($t1) - A1_vector_destroy_empty$address$($t1) + let $t0 + // $t0 := vector::empty
() + $t0 := A1_vector_empty$address$() + // vector::destroy_empty
($t0) + A1_vector_destroy_empty$address$($t0) // return () } @@ -1355,11 +1415,11 @@ object "test_A2_Vectors_test_destroy_non_empty_fail" { A2_Vectors_test_destroy_non_empty_fail() return (0, 0) function A2_Vectors_test_destroy_non_empty_fail() { - let v, $t1 - // $t1 := Vectors::one_elem_struct() - $t1 := A2_Vectors_one_elem_struct() - // vector::destroy_empty($t1) - A1_vector_destroy_empty$A2_Vectors_S$($t1) + let $t0 + // $t0 := Vectors::one_elem_struct() + $t0 := A2_Vectors_one_elem_struct() + // vector::destroy_empty($t0) + A1_vector_destroy_empty$A2_Vectors_S$($t0) // return () } @@ -1667,17 +1727,16 @@ object "test_A2_Vectors_test_empty" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t5 := 101 $t5 := 101 // abort($t5) $Abort($t5) } - case 3 { - // label L0 - // return () - $Free($locals, 32) - leave - } case 4 { // $t0 := Vectors::empty_vector() mstore($locals, A2_Vectors_empty_vector()) @@ -1689,10 +1748,16 @@ object "test_A2_Vectors_test_empty" { $t3 := 0 // $t4 := ==($t2, $t3) $t4 := $Eq($t2, $t3) - // if ($t4) goto L0 else goto L1 + // if ($t4) goto L1 else goto L0 switch $t4 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // return () + $Free($locals, 32) + leave } } } @@ -1834,7 +1899,7 @@ object "test_A2_Vectors_test_empty" { } } } -===> Test result of Vectors::test_empty: Succeed(Stopped) (used_gas=522): [] +===> Test result of Vectors::test_empty: Succeed(Stopped) (used_gas=605): [] // test of Vectors::test_nested_vector_equality /* ======================================= @@ -1855,13 +1920,34 @@ object "test_A2_Vectors_test_nested_vector_equality" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t5 := 101 $t5 := 101 // abort($t5) $Abort($t5) } - case 3 { - // label L0 + case 4 { + // $t0 := vector::empty>() + mstore($locals, A1_vector_empty$vec$u8$$()) + // $t1 := vector::empty>() + mstore(add($locals, 32), A1_vector_empty$vec$u8$$()) + // $t2 := copy($t0) + $t2 := mload($locals) + // $t3 := copy($t1) + $t3 := mload(add($locals, 32)) + // $t4 := ==($t2, $t3) + $t4 := $Eq_$vec$vec$u8$$$($t2, $t3) + // if ($t4) goto L1 else goto L0 + switch $t4 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t6 := borrow_local($t0) $t6 := $MakePtr(false, $locals) // $t7 := [97, 98, 99] @@ -1886,36 +1972,25 @@ object "test_A2_Vectors_test_nested_vector_equality" { $t11 := mload(add($locals, 32)) // $t12 := ==($t10, $t11) $t12 := $Eq_$vec$vec$u8$$$($t10, $t11) - // if ($t12) goto L2 else goto L3 + // if ($t12) goto L4 else goto L3 switch $t12 - case 0 { $block := 5 } + case 0 { $block := 7 } default { $block := 6 } } - case 4 { - // $t0 := vector::empty>() - mstore($locals, A1_vector_empty$vec$u8$$()) - // $t1 := vector::empty>() - mstore(add($locals, 32), A1_vector_empty$vec$u8$$()) - // $t2 := copy($t0) - $t2 := mload($locals) - // $t3 := copy($t1) - $t3 := mload(add($locals, 32)) - // $t4 := ==($t2, $t3) - $t4 := $Eq_$vec$vec$u8$$$($t2, $t3) - // if ($t4) goto L0 else goto L1 - switch $t4 - case 0 { $block := 2 } - default { $block := 3 } + case 6 { + // label L4 + // goto L5 + $block := 8 } - case 5 { + case 7 { // label L3 // $t13 := 102 $t13 := 102 // abort($t13) $Abort($t13) } - case 6 { - // label L2 + case 8 { + // label L5 // $t14 := borrow_local($t0) $t14 := $MakePtr(false, $locals) // $t15 := [100, 101, 102] @@ -1940,20 +2015,25 @@ object "test_A2_Vectors_test_nested_vector_equality" { $t19 := mload(add($locals, 32)) // $t20 := ==($t18, $t19) $t20 := $Eq_$vec$vec$u8$$$($t18, $t19) - // if ($t20) goto L4 else goto L5 + // if ($t20) goto L7 else goto L6 switch $t20 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t21 := 103 $t21 := 103 // abort($t21) $Abort($t21) } - case 8 { - // label L4 + case 11 { + // label L8 // $t22 := borrow_local($t0) $t22 := $MakePtr(false, $locals) // $t23 := [103, 104, 105] @@ -1978,20 +2058,25 @@ object "test_A2_Vectors_test_nested_vector_equality" { $t27 := mload(add($locals, 32)) // $t28 := !=($t26, $t27) $t28 := $LogicalNot($Eq_$vec$vec$u8$$$($t26, $t27)) - // if ($t28) goto L6 else goto L7 + // if ($t28) goto L10 else goto L9 switch $t28 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t29 := 104 $t29 := 104 // abort($t29) $Abort($t29) } - case 10 { - // label L6 + case 14 { + // label L11 // return () $Free($locals, 64) leave @@ -2338,7 +2423,7 @@ object "test_A2_Vectors_test_nested_vector_equality" { } } } -===> Test result of Vectors::test_nested_vector_equality: Succeed(Stopped) (used_gas=10145): [] +===> Test result of Vectors::test_nested_vector_equality: Succeed(Stopped) (used_gas=11041): [] // test of Vectors::test_nested_vectors /* ======================================= @@ -2359,30 +2444,16 @@ object "test_A2_Vectors_test_nested_vectors" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t32 := 101 $t32 := 101 // abort($t32) $Abort($t32) } - case 3 { - // label L0 - // $t33 := borrow_local($t0) - $t33 := $MakePtr(false, add($locals, 96)) - // $t34 := 0 - $t34 := 0 - // $t35 := vector::borrow>($t33, $t34) - $t35 := A1_vector_borrow$vec$u64$$($t33, $t34) - // $t36 := vector::length($t35) - $t36 := A1_vector_length$u64$($t35) - // $t37 := 2 - $t37 := 2 - // $t38 := ==($t36, $t37) - $t38 := $Eq($t36, $t37) - // if ($t38) goto L2 else goto L3 - switch $t38 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t1 := vector::empty() mstore($locals, A1_vector_empty$u64$()) @@ -2472,20 +2543,44 @@ object "test_A2_Vectors_test_nested_vectors" { $t30 := 3 // $t31 := ==($t29, $t30) $t31 := $Eq($t29, $t30) - // if ($t31) goto L0 else goto L1 + // if ($t31) goto L1 else goto L0 switch $t31 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t33 := borrow_local($t0) + $t33 := $MakePtr(false, add($locals, 96)) + // $t34 := 0 + $t34 := 0 + // $t35 := vector::borrow>($t33, $t34) + $t35 := A1_vector_borrow$vec$u64$$($t33, $t34) + // $t36 := vector::length($t35) + $t36 := A1_vector_length$u64$($t35) + // $t37 := 2 + $t37 := 2 + // $t38 := ==($t36, $t37) + $t38 := $Eq($t36, $t37) + // if ($t38) goto L4 else goto L3 + switch $t38 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t39 := 102 $t39 := 102 // abort($t39) $Abort($t39) } - case 6 { - // label L2 + case 8 { + // label L5 // $t40 := borrow_local($t0) $t40 := $MakePtr(false, add($locals, 96)) // $t41 := 1 @@ -2498,20 +2593,25 @@ object "test_A2_Vectors_test_nested_vectors" { $t44 := 3 // $t45 := ==($t43, $t44) $t45 := $Eq($t43, $t44) - // if ($t45) goto L4 else goto L5 + // if ($t45) goto L7 else goto L6 switch $t45 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t46 := 103 $t46 := 103 // abort($t46) $Abort($t46) } - case 8 { - // label L4 + case 11 { + // label L8 // $t47 := borrow_local($t0) $t47 := $MakePtr(false, add($locals, 96)) // $t48 := 2 @@ -2524,20 +2624,25 @@ object "test_A2_Vectors_test_nested_vectors" { $t51 := 4 // $t52 := ==($t50, $t51) $t52 := $Eq($t50, $t51) - // if ($t52) goto L6 else goto L7 + // if ($t52) goto L10 else goto L9 switch $t52 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t53 := 104 $t53 := 104 // abort($t53) $Abort($t53) } - case 10 { - // label L6 + case 14 { + // label L11 // $t54 := borrow_local($t0) $t54 := $MakePtr(false, add($locals, 96)) // $t55 := 0 @@ -2554,20 +2659,25 @@ object "test_A2_Vectors_test_nested_vectors" { $t60 := 10 // $t61 := ==($t59, $t60) $t61 := $Eq($t59, $t60) - // if ($t61) goto L8 else goto L9 + // if ($t61) goto L13 else goto L12 switch $t61 - case 0 { $block := 11 } - default { $block := 12 } + case 0 { $block := 16 } + default { $block := 15 } } - case 11 { - // label L9 + case 15 { + // label L13 + // goto L14 + $block := 17 + } + case 16 { + // label L12 // $t62 := 105 $t62 := 105 // abort($t62) $Abort($t62) } - case 12 { - // label L8 + case 17 { + // label L14 // $t63 := borrow_local($t0) $t63 := $MakePtr(false, add($locals, 96)) // $t64 := 1 @@ -2584,20 +2694,25 @@ object "test_A2_Vectors_test_nested_vectors" { $t69 := 13 // $t70 := ==($t68, $t69) $t70 := $Eq($t68, $t69) - // if ($t70) goto L10 else goto L11 + // if ($t70) goto L16 else goto L15 switch $t70 - case 0 { $block := 13 } - default { $block := 14 } + case 0 { $block := 19 } + default { $block := 18 } } - case 13 { - // label L11 + case 18 { + // label L16 + // goto L17 + $block := 20 + } + case 19 { + // label L15 // $t71 := 105 $t71 := 105 // abort($t71) $Abort($t71) } - case 14 { - // label L10 + case 20 { + // label L17 // $t72 := borrow_local($t0) $t72 := $MakePtr(false, add($locals, 96)) // $t73 := 2 @@ -2614,20 +2729,25 @@ object "test_A2_Vectors_test_nested_vectors" { $t78 := 17 // $t79 := ==($t77, $t78) $t79 := $Eq($t77, $t78) - // if ($t79) goto L12 else goto L13 + // if ($t79) goto L19 else goto L18 switch $t79 - case 0 { $block := 15 } - default { $block := 16 } + case 0 { $block := 22 } + default { $block := 21 } } - case 15 { - // label L13 + case 21 { + // label L19 + // goto L20 + $block := 23 + } + case 22 { + // label L18 // $t80 := 105 $t80 := 105 // abort($t80) $Abort($t80) } - case 16 { - // label L12 + case 23 { + // label L20 // $t81 := borrow_local($t0) $t81 := $MakePtr(false, add($locals, 96)) // $t82 := 2 @@ -2644,20 +2764,25 @@ object "test_A2_Vectors_test_nested_vectors" { $t87 := 18 // $t88 := ==($t86, $t87) $t88 := $Eq($t86, $t87) - // if ($t88) goto L14 else goto L15 + // if ($t88) goto L22 else goto L21 switch $t88 - case 0 { $block := 17 } - default { $block := 18 } + case 0 { $block := 25 } + default { $block := 24 } } - case 17 { - // label L15 + case 24 { + // label L22 + // goto L23 + $block := 26 + } + case 25 { + // label L21 // $t89 := 105 $t89 := 105 // abort($t89) $Abort($t89) } - case 18 { - // label L14 + case 26 { + // label L23 // return () $Free($locals, 128) leave @@ -2960,7 +3085,7 @@ object "test_A2_Vectors_test_nested_vectors" { } } } -===> Test result of Vectors::test_nested_vectors: Succeed(Stopped) (used_gas=17759): [] +===> Test result of Vectors::test_nested_vectors: Succeed(Stopped) (used_gas=20935): [] // test of Vectors::test_one_elem_struct /* ======================================= @@ -2981,13 +3106,34 @@ object "test_A2_Vectors_test_one_elem_struct" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t5 := 101 $t5 := 101 // abort($t5) $Abort($t5) } - case 3 { - // label L0 + case 4 { + // $t0 := Vectors::one_elem_struct() + mstore($locals, A2_Vectors_one_elem_struct()) + // $t1 := borrow_local($t0) + $t1 := $MakePtr(false, $locals) + // $t2 := vector::length($t1) + $t2 := A1_vector_length$A2_Vectors_S$($t1) + // $t3 := 1 + $t3 := 1 + // $t4 := ==($t2, $t3) + $t4 := $Eq($t2, $t3) + // if ($t4) goto L1 else goto L0 + switch $t4 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t6 := borrow_local($t0) $t6 := $MakePtr(false, $locals) // $t7 := 0 @@ -3002,36 +3148,25 @@ object "test_A2_Vectors_test_one_elem_struct" { $t11 := 42 // $t12 := ==($t10, $t11) $t12 := $Eq($t10, $t11) - // if ($t12) goto L2 else goto L3 + // if ($t12) goto L4 else goto L3 switch $t12 - case 0 { $block := 5 } + case 0 { $block := 7 } default { $block := 6 } } - case 4 { - // $t0 := Vectors::one_elem_struct() - mstore($locals, A2_Vectors_one_elem_struct()) - // $t1 := borrow_local($t0) - $t1 := $MakePtr(false, $locals) - // $t2 := vector::length($t1) - $t2 := A1_vector_length$A2_Vectors_S$($t1) - // $t3 := 1 - $t3 := 1 - // $t4 := ==($t2, $t3) - $t4 := $Eq($t2, $t3) - // if ($t4) goto L0 else goto L1 - switch $t4 - case 0 { $block := 2 } - default { $block := 3 } + case 6 { + // label L4 + // goto L5 + $block := 8 } - case 5 { + case 7 { // label L3 // $t13 := 102 $t13 := 102 // abort($t13) $Abort($t13) } - case 6 { - // label L2 + case 8 { + // label L5 // $t14 := borrow_local($t0) $t14 := $MakePtr(false, $locals) // $t15 := 0 @@ -3046,20 +3181,25 @@ object "test_A2_Vectors_test_one_elem_struct" { $t19 := true // $t20 := ==($t18, $t19) $t20 := $Eq($t18, $t19) - // if ($t20) goto L4 else goto L5 + // if ($t20) goto L7 else goto L6 switch $t20 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t21 := 103 $t21 := 103 // abort($t21) $Abort($t21) } - case 8 { - // label L4 + case 11 { + // label L8 // $t22 := borrow_local($t0) $t22 := $MakePtr(false, $locals) // $t23 := 0 @@ -3074,20 +3214,25 @@ object "test_A2_Vectors_test_one_elem_struct" { $t27 := 789 // $t28 := ==($t26, $t27) $t28 := $Eq($t26, $t27) - // if ($t28) goto L6 else goto L7 + // if ($t28) goto L10 else goto L9 switch $t28 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t29 := 104 $t29 := 104 // abort($t29) $Abort($t29) } - case 10 { - // label L6 + case 14 { + // label L11 // return () $Free($locals, 32) leave @@ -3424,7 +3569,7 @@ object "test_A2_Vectors_test_one_elem_struct" { } } } -===> Test result of Vectors::test_one_elem_struct: Succeed(Stopped) (used_gas=3407): [] +===> Test result of Vectors::test_one_elem_struct: Succeed(Stopped) (used_gas=4291): [] // test of Vectors::test_one_elem_u64 /* ======================================= @@ -3445,13 +3590,34 @@ object "test_A2_Vectors_test_one_elem_u64" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t5 := 101 $t5 := 101 // abort($t5) $Abort($t5) } - case 3 { - // label L0 + case 4 { + // $t0 := Vectors::one_elem_u64() + mstore($locals, A2_Vectors_one_elem_u64()) + // $t1 := borrow_local($t0) + $t1 := $MakePtr(false, $locals) + // $t2 := vector::length($t1) + $t2 := A1_vector_length$u64$($t1) + // $t3 := 1 + $t3 := 1 + // $t4 := ==($t2, $t3) + $t4 := $Eq($t2, $t3) + // if ($t4) goto L1 else goto L0 + switch $t4 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t6 := borrow_local($t0) $t6 := $MakePtr(false, $locals) // $t7 := 0 @@ -3464,36 +3630,25 @@ object "test_A2_Vectors_test_one_elem_u64" { $t10 := 42 // $t11 := ==($t9, $t10) $t11 := $Eq($t9, $t10) - // if ($t11) goto L2 else goto L3 + // if ($t11) goto L4 else goto L3 switch $t11 - case 0 { $block := 5 } + case 0 { $block := 7 } default { $block := 6 } } - case 4 { - // $t0 := Vectors::one_elem_u64() - mstore($locals, A2_Vectors_one_elem_u64()) - // $t1 := borrow_local($t0) - $t1 := $MakePtr(false, $locals) - // $t2 := vector::length($t1) - $t2 := A1_vector_length$u64$($t1) - // $t3 := 1 - $t3 := 1 - // $t4 := ==($t2, $t3) - $t4 := $Eq($t2, $t3) - // if ($t4) goto L0 else goto L1 - switch $t4 - case 0 { $block := 2 } - default { $block := 3 } + case 6 { + // label L4 + // goto L5 + $block := 8 } - case 5 { + case 7 { // label L3 // $t12 := 102 $t12 := 102 // abort($t12) $Abort($t12) } - case 6 { - // label L2 + case 8 { + // label L5 // return () $Free($locals, 32) leave @@ -3501,6 +3656,13 @@ object "test_A2_Vectors_test_one_elem_u64" { } } + function A1_vector_borrow$u64$(v_ref, i) -> e_ptr { + let v_offs := $LoadU256(v_ref) + let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) + let size := $LoadU64(v_ptr) + if $GtEq(i, size) { $AbortBuiltin() } + e_ptr := $IndexPtr(v_ptr, add(32, mul(i, 8))) + } function A1_vector_length$u64$(v_ref) -> len { let v_offs := $LoadU256(v_ref) let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) @@ -3542,13 +3704,6 @@ object "test_A2_Vectors_test_one_elem_u64" { vector := $Malloc(48) $MemoryStoreU64(add(vector, 8), 2) } - function A1_vector_borrow$u64$(v_ref, i) -> e_ptr { - let v_offs := $LoadU256(v_ref) - let v_ptr := $MakePtr($IsStoragePtr(v_ref), v_offs) - let size := $LoadU64(v_ptr) - if $GtEq(i, size) { $AbortBuiltin() } - e_ptr := $IndexPtr(v_ptr, add(32, mul(i, 8))) - } function $Abort(code) { mstore(0, code) revert(24, 8) // TODO: store code as a string? @@ -3757,7 +3912,7 @@ object "test_A2_Vectors_test_one_elem_u64" { } } } -===> Test result of Vectors::test_one_elem_u64: Succeed(Stopped) (used_gas=1746): [] +===> Test result of Vectors::test_one_elem_u64: Succeed(Stopped) (used_gas=2012): [] // test of Vectors::test_pop_back /* ======================================= @@ -3778,30 +3933,16 @@ object "test_A2_Vectors_test_pop_back" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t9 := 101 $t9 := 101 // abort($t9) $Abort($t9) } - case 3 { - // label L0 - // $t10 := borrow_local($t2) - $t10 := $MakePtr(false, $locals) - // $t11 := 0 - $t11 := 0 - // $t12 := vector::borrow($t10, $t11) - $t12 := A1_vector_borrow$u64$($t10, $t11) - // $t13 := read_ref($t12) - $t13 := $LoadU64($t12) - // $t14 := 42 - $t14 := 42 - // $t15 := ==($t13, $t14) - $t15 := $Eq($t13, $t14) - // if ($t15) goto L2 else goto L3 - switch $t15 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t2 := Vectors::one_elem_u64() mstore($locals, A2_Vectors_one_elem_u64()) @@ -3819,20 +3960,44 @@ object "test_A2_Vectors_test_pop_back" { $t7 := 2 // $t8 := ==($t6, $t7) $t8 := $Eq($t6, $t7) - // if ($t8) goto L0 else goto L1 + // if ($t8) goto L1 else goto L0 switch $t8 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t10 := borrow_local($t2) + $t10 := $MakePtr(false, $locals) + // $t11 := 0 + $t11 := 0 + // $t12 := vector::borrow($t10, $t11) + $t12 := A1_vector_borrow$u64$($t10, $t11) + // $t13 := read_ref($t12) + $t13 := $LoadU64($t12) + // $t14 := 42 + $t14 := 42 + // $t15 := ==($t13, $t14) + $t15 := $Eq($t13, $t14) + // if ($t15) goto L4 else goto L3 + switch $t15 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t16 := 102 $t16 := 102 // abort($t16) $Abort($t16) } - case 6 { - // label L2 + case 8 { + // label L5 // $t17 := borrow_local($t2) $t17 := $MakePtr(false, $locals) // $t18 := 1 @@ -3845,20 +4010,25 @@ object "test_A2_Vectors_test_pop_back" { $t21 := 43 // $t22 := ==($t20, $t21) $t22 := $Eq($t20, $t21) - // if ($t22) goto L4 else goto L5 + // if ($t22) goto L7 else goto L6 switch $t22 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t23 := 103 $t23 := 103 // abort($t23) $Abort($t23) } - case 8 { - // label L4 + case 11 { + // label L8 // $t24 := borrow_local($t2) $t24 := $MakePtr(false, $locals) // $t25 := vector::pop_back($t24) @@ -3871,38 +4041,48 @@ object "test_A2_Vectors_test_pop_back" { $t28 := 1 // $t29 := ==($t27, $t28) $t29 := $Eq($t27, $t28) - // if ($t29) goto L6 else goto L7 + // if ($t29) goto L10 else goto L9 switch $t29 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t30 := 104 $t30 := 104 // abort($t30) $Abort($t30) } - case 10 { - // label L6 + case 14 { + // label L11 // $t31 := 43 $t31 := 43 // $t32 := ==($t25, $t31) $t32 := $Eq($t25, $t31) - // if ($t32) goto L8 else goto L9 + // if ($t32) goto L13 else goto L12 switch $t32 - case 0 { $block := 11 } - default { $block := 12 } + case 0 { $block := 16 } + default { $block := 15 } } - case 11 { - // label L9 + case 15 { + // label L13 + // goto L14 + $block := 17 + } + case 16 { + // label L12 // $t33 := 105 $t33 := 105 // abort($t33) $Abort($t33) } - case 12 { - // label L8 + case 17 { + // label L14 // $t34 := borrow_local($t2) $t34 := $MakePtr(false, $locals) // $t35 := vector::pop_back($t34) @@ -3915,38 +4095,48 @@ object "test_A2_Vectors_test_pop_back" { $t38 := 0 // $t39 := ==($t37, $t38) $t39 := $Eq($t37, $t38) - // if ($t39) goto L10 else goto L11 + // if ($t39) goto L16 else goto L15 switch $t39 - case 0 { $block := 13 } - default { $block := 14 } + case 0 { $block := 19 } + default { $block := 18 } } - case 13 { - // label L11 + case 18 { + // label L16 + // goto L17 + $block := 20 + } + case 19 { + // label L15 // $t40 := 106 $t40 := 106 // abort($t40) $Abort($t40) } - case 14 { - // label L10 + case 20 { + // label L17 // $t41 := 42 $t41 := 42 // $t42 := ==($t35, $t41) $t42 := $Eq($t35, $t41) - // if ($t42) goto L12 else goto L13 + // if ($t42) goto L19 else goto L18 switch $t42 - case 0 { $block := 15 } - default { $block := 16 } + case 0 { $block := 22 } + default { $block := 21 } } - case 15 { - // label L13 + case 21 { + // label L19 + // goto L20 + $block := 23 + } + case 22 { + // label L18 // $t43 := 107 $t43 := 107 // abort($t43) $Abort($t43) } - case 16 { - // label L12 + case 23 { + // label L20 // $t44 := move($t2) $t44 := mload($locals) // vector::destroy_empty($t44) @@ -4229,7 +4419,7 @@ object "test_A2_Vectors_test_pop_back" { } } } -===> Test result of Vectors::test_pop_back: Succeed(Stopped) (used_gas=6263): [] +===> Test result of Vectors::test_pop_back: Succeed(Stopped) (used_gas=8729): [] // test of Vectors::test_pop_back_empty_fail /* ======================================= @@ -4452,13 +4642,34 @@ object "test_A2_Vectors_test_push_back" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t5 := 101 $t5 := 101 // abort($t5) $Abort($t5) } - case 3 { - // label L0 + case 4 { + // $t0 := Vectors::one_elem_u64() + mstore($locals, A2_Vectors_one_elem_u64()) + // $t1 := borrow_local($t0) + $t1 := $MakePtr(false, $locals) + // $t2 := vector::length($t1) + $t2 := A1_vector_length$u64$($t1) + // $t3 := 1 + $t3 := 1 + // $t4 := ==($t2, $t3) + $t4 := $Eq($t2, $t3) + // if ($t4) goto L1 else goto L0 + switch $t4 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t6 := borrow_local($t0) $t6 := $MakePtr(false, $locals) // $t7 := 0 @@ -4471,36 +4682,25 @@ object "test_A2_Vectors_test_push_back" { $t10 := 42 // $t11 := ==($t9, $t10) $t11 := $Eq($t9, $t10) - // if ($t11) goto L2 else goto L3 + // if ($t11) goto L4 else goto L3 switch $t11 - case 0 { $block := 5 } + case 0 { $block := 7 } default { $block := 6 } } - case 4 { - // $t0 := Vectors::one_elem_u64() - mstore($locals, A2_Vectors_one_elem_u64()) - // $t1 := borrow_local($t0) - $t1 := $MakePtr(false, $locals) - // $t2 := vector::length($t1) - $t2 := A1_vector_length$u64$($t1) - // $t3 := 1 - $t3 := 1 - // $t4 := ==($t2, $t3) - $t4 := $Eq($t2, $t3) - // if ($t4) goto L0 else goto L1 - switch $t4 - case 0 { $block := 2 } - default { $block := 3 } + case 6 { + // label L4 + // goto L5 + $block := 8 } - case 5 { + case 7 { // label L3 // $t12 := 102 $t12 := 102 // abort($t12) $Abort($t12) } - case 6 { - // label L2 + case 8 { + // label L5 // $t13 := borrow_local($t0) $t13 := $MakePtr(false, $locals) // $t14 := 43 @@ -4515,20 +4715,25 @@ object "test_A2_Vectors_test_push_back" { $t17 := 2 // $t18 := ==($t16, $t17) $t18 := $Eq($t16, $t17) - // if ($t18) goto L4 else goto L5 + // if ($t18) goto L7 else goto L6 switch $t18 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t19 := 103 $t19 := 103 // abort($t19) $Abort($t19) } - case 8 { - // label L4 + case 11 { + // label L8 // $t20 := borrow_local($t0) $t20 := $MakePtr(false, $locals) // $t21 := 0 @@ -4541,20 +4746,25 @@ object "test_A2_Vectors_test_push_back" { $t24 := 42 // $t25 := ==($t23, $t24) $t25 := $Eq($t23, $t24) - // if ($t25) goto L6 else goto L7 + // if ($t25) goto L10 else goto L9 switch $t25 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t26 := 104 $t26 := 104 // abort($t26) $Abort($t26) } - case 10 { - // label L6 + case 14 { + // label L11 // $t27 := borrow_local($t0) $t27 := $MakePtr(false, $locals) // $t28 := 1 @@ -4567,20 +4777,25 @@ object "test_A2_Vectors_test_push_back" { $t31 := 43 // $t32 := ==($t30, $t31) $t32 := $Eq($t30, $t31) - // if ($t32) goto L8 else goto L9 + // if ($t32) goto L13 else goto L12 switch $t32 - case 0 { $block := 11 } - default { $block := 12 } + case 0 { $block := 16 } + default { $block := 15 } } - case 11 { - // label L9 + case 15 { + // label L13 + // goto L14 + $block := 17 + } + case 16 { + // label L12 // $t33 := 105 $t33 := 105 // abort($t33) $Abort($t33) } - case 12 { - // label L8 + case 17 { + // label L14 // $t34 := borrow_local($t0) $t34 := $MakePtr(false, $locals) // $t35 := 44 @@ -4595,20 +4810,25 @@ object "test_A2_Vectors_test_push_back" { $t38 := 3 // $t39 := ==($t37, $t38) $t39 := $Eq($t37, $t38) - // if ($t39) goto L10 else goto L11 + // if ($t39) goto L16 else goto L15 switch $t39 - case 0 { $block := 13 } - default { $block := 14 } + case 0 { $block := 19 } + default { $block := 18 } } - case 13 { - // label L11 + case 18 { + // label L16 + // goto L17 + $block := 20 + } + case 19 { + // label L15 // $t40 := 106 $t40 := 106 // abort($t40) $Abort($t40) } - case 14 { - // label L10 + case 20 { + // label L17 // $t41 := borrow_local($t0) $t41 := $MakePtr(false, $locals) // $t42 := 0 @@ -4621,20 +4841,25 @@ object "test_A2_Vectors_test_push_back" { $t45 := 42 // $t46 := ==($t44, $t45) $t46 := $Eq($t44, $t45) - // if ($t46) goto L12 else goto L13 + // if ($t46) goto L19 else goto L18 switch $t46 - case 0 { $block := 15 } - default { $block := 16 } + case 0 { $block := 22 } + default { $block := 21 } } - case 15 { - // label L13 + case 21 { + // label L19 + // goto L20 + $block := 23 + } + case 22 { + // label L18 // $t47 := 107 $t47 := 107 // abort($t47) $Abort($t47) } - case 16 { - // label L12 + case 23 { + // label L20 // $t48 := borrow_local($t0) $t48 := $MakePtr(false, $locals) // $t49 := 1 @@ -4647,20 +4872,25 @@ object "test_A2_Vectors_test_push_back" { $t52 := 43 // $t53 := ==($t51, $t52) $t53 := $Eq($t51, $t52) - // if ($t53) goto L14 else goto L15 + // if ($t53) goto L22 else goto L21 switch $t53 - case 0 { $block := 17 } - default { $block := 18 } + case 0 { $block := 25 } + default { $block := 24 } } - case 17 { - // label L15 + case 24 { + // label L22 + // goto L23 + $block := 26 + } + case 25 { + // label L21 // $t54 := 108 $t54 := 108 // abort($t54) $Abort($t54) } - case 18 { - // label L14 + case 26 { + // label L23 // $t55 := borrow_local($t0) $t55 := $MakePtr(false, $locals) // $t56 := 2 @@ -4673,20 +4903,25 @@ object "test_A2_Vectors_test_push_back" { $t59 := 44 // $t60 := ==($t58, $t59) $t60 := $Eq($t58, $t59) - // if ($t60) goto L16 else goto L17 + // if ($t60) goto L25 else goto L24 switch $t60 - case 0 { $block := 19 } - default { $block := 20 } + case 0 { $block := 28 } + default { $block := 27 } } - case 19 { - // label L17 + case 27 { + // label L25 + // goto L26 + $block := 29 + } + case 28 { + // label L24 // $t61 := 109 $t61 := 109 // abort($t61) $Abort($t61) } - case 20 { - // label L16 + case 29 { + // label L26 // $t62 := borrow_local($t0) $t62 := $MakePtr(false, $locals) // $t63 := 45 @@ -4701,20 +4936,25 @@ object "test_A2_Vectors_test_push_back" { $t66 := 4 // $t67 := ==($t65, $t66) $t67 := $Eq($t65, $t66) - // if ($t67) goto L18 else goto L19 + // if ($t67) goto L28 else goto L27 switch $t67 - case 0 { $block := 21 } - default { $block := 22 } + case 0 { $block := 31 } + default { $block := 30 } } - case 21 { - // label L19 + case 30 { + // label L28 + // goto L29 + $block := 32 + } + case 31 { + // label L27 // $t68 := 110 $t68 := 110 // abort($t68) $Abort($t68) } - case 22 { - // label L18 + case 32 { + // label L29 // $t69 := borrow_local($t0) $t69 := $MakePtr(false, $locals) // $t70 := 0 @@ -4727,20 +4967,25 @@ object "test_A2_Vectors_test_push_back" { $t73 := 42 // $t74 := ==($t72, $t73) $t74 := $Eq($t72, $t73) - // if ($t74) goto L20 else goto L21 + // if ($t74) goto L31 else goto L30 switch $t74 - case 0 { $block := 23 } - default { $block := 24 } + case 0 { $block := 34 } + default { $block := 33 } } - case 23 { - // label L21 + case 33 { + // label L31 + // goto L32 + $block := 35 + } + case 34 { + // label L30 // $t75 := 111 $t75 := 111 // abort($t75) $Abort($t75) } - case 24 { - // label L20 + case 35 { + // label L32 // $t76 := borrow_local($t0) $t76 := $MakePtr(false, $locals) // $t77 := 1 @@ -4753,20 +4998,25 @@ object "test_A2_Vectors_test_push_back" { $t80 := 43 // $t81 := ==($t79, $t80) $t81 := $Eq($t79, $t80) - // if ($t81) goto L22 else goto L23 + // if ($t81) goto L34 else goto L33 switch $t81 - case 0 { $block := 25 } - default { $block := 26 } + case 0 { $block := 37 } + default { $block := 36 } } - case 25 { - // label L23 + case 36 { + // label L34 + // goto L35 + $block := 38 + } + case 37 { + // label L33 // $t82 := 112 $t82 := 112 // abort($t82) $Abort($t82) } - case 26 { - // label L22 + case 38 { + // label L35 // $t83 := borrow_local($t0) $t83 := $MakePtr(false, $locals) // $t84 := 2 @@ -4779,20 +5029,25 @@ object "test_A2_Vectors_test_push_back" { $t87 := 44 // $t88 := ==($t86, $t87) $t88 := $Eq($t86, $t87) - // if ($t88) goto L24 else goto L25 + // if ($t88) goto L37 else goto L36 switch $t88 - case 0 { $block := 27 } - default { $block := 28 } + case 0 { $block := 40 } + default { $block := 39 } } - case 27 { - // label L25 + case 39 { + // label L37 + // goto L38 + $block := 41 + } + case 40 { + // label L36 // $t89 := 113 $t89 := 113 // abort($t89) $Abort($t89) } - case 28 { - // label L24 + case 41 { + // label L38 // $t90 := borrow_local($t0) $t90 := $MakePtr(false, $locals) // $t91 := 3 @@ -4805,20 +5060,25 @@ object "test_A2_Vectors_test_push_back" { $t94 := 45 // $t95 := ==($t93, $t94) $t95 := $Eq($t93, $t94) - // if ($t95) goto L26 else goto L27 + // if ($t95) goto L40 else goto L39 switch $t95 - case 0 { $block := 29 } - default { $block := 30 } + case 0 { $block := 43 } + default { $block := 42 } } - case 29 { - // label L27 + case 42 { + // label L40 + // goto L41 + $block := 44 + } + case 43 { + // label L39 // $t96 := 114 $t96 := 114 // abort($t96) $Abort($t96) } - case 30 { - // label L26 + case 44 { + // label L41 // return () $Free($locals, 32) leave @@ -5082,7 +5342,7 @@ object "test_A2_Vectors_test_push_back" { } } } -===> Test result of Vectors::test_push_back: Succeed(Stopped) (used_gas=14029): [] +===> Test result of Vectors::test_push_back: Succeed(Stopped) (used_gas=23283): [] // test of Vectors::test_swap /* ======================================= @@ -5103,30 +5363,16 @@ object "test_A2_Vectors_test_swap" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t11 := 101 $t11 := 101 // abort($t11) $Abort($t11) } - case 3 { - // label L0 - // $t12 := borrow_local($t0) - $t12 := $MakePtr(false, $locals) - // $t13 := 1 - $t13 := 1 - // $t14 := vector::borrow($t12, $t13) - $t14 := A1_vector_borrow$u64$($t12, $t13) - // $t15 := read_ref($t14) - $t15 := $LoadU64($t14) - // $t16 := 43 - $t16 := 43 - // $t17 := ==($t15, $t16) - $t17 := $Eq($t15, $t16) - // if ($t17) goto L2 else goto L3 - switch $t17 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t0 := Vectors::one_elem_u64() mstore($locals, A2_Vectors_one_elem_u64()) @@ -5154,20 +5400,44 @@ object "test_A2_Vectors_test_swap" { $t9 := 42 // $t10 := ==($t8, $t9) $t10 := $Eq($t8, $t9) - // if ($t10) goto L0 else goto L1 + // if ($t10) goto L1 else goto L0 switch $t10 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t12 := borrow_local($t0) + $t12 := $MakePtr(false, $locals) + // $t13 := 1 + $t13 := 1 + // $t14 := vector::borrow($t12, $t13) + $t14 := A1_vector_borrow$u64$($t12, $t13) + // $t15 := read_ref($t14) + $t15 := $LoadU64($t14) + // $t16 := 43 + $t16 := 43 + // $t17 := ==($t15, $t16) + $t17 := $Eq($t15, $t16) + // if ($t17) goto L4 else goto L3 + switch $t17 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t18 := 102 $t18 := 102 // abort($t18) $Abort($t18) } - case 6 { - // label L2 + case 8 { + // label L5 // $t19 := borrow_local($t0) $t19 := $MakePtr(false, $locals) // $t20 := 2 @@ -5180,20 +5450,25 @@ object "test_A2_Vectors_test_swap" { $t23 := 44 // $t24 := ==($t22, $t23) $t24 := $Eq($t22, $t23) - // if ($t24) goto L4 else goto L5 + // if ($t24) goto L7 else goto L6 switch $t24 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t25 := 103 $t25 := 103 // abort($t25) $Abort($t25) } - case 8 { - // label L4 + case 11 { + // label L8 // $t26 := borrow_local($t0) $t26 := $MakePtr(false, $locals) // $t27 := 0 @@ -5214,20 +5489,25 @@ object "test_A2_Vectors_test_swap" { $t33 := 44 // $t34 := ==($t32, $t33) $t34 := $Eq($t32, $t33) - // if ($t34) goto L6 else goto L7 + // if ($t34) goto L10 else goto L9 switch $t34 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t35 := 104 $t35 := 104 // abort($t35) $Abort($t35) } - case 10 { - // label L6 + case 14 { + // label L11 // $t36 := borrow_local($t0) $t36 := $MakePtr(false, $locals) // $t37 := 1 @@ -5240,20 +5520,25 @@ object "test_A2_Vectors_test_swap" { $t40 := 43 // $t41 := ==($t39, $t40) $t41 := $Eq($t39, $t40) - // if ($t41) goto L8 else goto L9 + // if ($t41) goto L13 else goto L12 switch $t41 - case 0 { $block := 11 } - default { $block := 12 } + case 0 { $block := 16 } + default { $block := 15 } } - case 11 { - // label L9 + case 15 { + // label L13 + // goto L14 + $block := 17 + } + case 16 { + // label L12 // $t42 := 105 $t42 := 105 // abort($t42) $Abort($t42) } - case 12 { - // label L8 + case 17 { + // label L14 // $t43 := borrow_local($t0) $t43 := $MakePtr(false, $locals) // $t44 := 2 @@ -5266,20 +5551,25 @@ object "test_A2_Vectors_test_swap" { $t47 := 42 // $t48 := ==($t46, $t47) $t48 := $Eq($t46, $t47) - // if ($t48) goto L10 else goto L11 + // if ($t48) goto L16 else goto L15 switch $t48 - case 0 { $block := 13 } - default { $block := 14 } + case 0 { $block := 19 } + default { $block := 18 } } - case 13 { - // label L11 + case 18 { + // label L16 + // goto L17 + $block := 20 + } + case 19 { + // label L15 // $t49 := 106 $t49 := 106 // abort($t49) $Abort($t49) } - case 14 { - // label L10 + case 20 { + // label L17 // return () $Free($locals, 32) leave @@ -5550,7 +5840,7 @@ object "test_A2_Vectors_test_swap" { } } } -===> Test result of Vectors::test_swap: Succeed(Stopped) (used_gas=7087): [] +===> Test result of Vectors::test_swap: Succeed(Stopped) (used_gas=8941): [] // test of Vectors::test_swap_fail /* ======================================= @@ -5860,28 +6150,15 @@ object "test_A2_Vectors_test_vector_equality" { switch $block case 2 { // label L1 - // $t12 := 101 - $t12 := 101 - // abort($t12) - $Abort($t12) + // goto L2 + $block := 5 } - case 3 { - // label L0 - // $t13 := copy($t0) - $t13 := mload($locals) - // $t14 := [10, 11, 12, 13] - $t14 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(4))) - $MemoryStoreU64($t14, 4) - $MemoryStoreU64(add($t14, 8), $ClosestGreaterPowerOfTwo(4)) - copy_literal_string_to_memory_512532313(add($t14, 32)) - // $t15 := !=($t13, $t14) - $t15 := $LogicalNot($Eq_$vec$u8$$($t13, $t14)) - // $t16 := !($t15) - $t16 := $LogicalNot($t15) - // if ($t16) goto L2 else goto L3 - switch $t16 - case 0 { $block := 5 } - default { $block := 6 } + case 3 { + // label L0 + // $t12 := 101 + $t12 := 101 + // abort($t12) + $Abort($t12) } case 4 { // $t0 := vector::empty() @@ -5919,20 +6196,43 @@ object "test_A2_Vectors_test_vector_equality" { copy_literal_string_to_memory_512532313(add($t10, 32)) // $t11 := ==($t9, $t10) $t11 := $Eq_$vec$u8$$($t9, $t10) - // if ($t11) goto L0 else goto L1 + // if ($t11) goto L1 else goto L0 switch $t11 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t13 := copy($t0) + $t13 := mload($locals) + // $t14 := [10, 11, 12, 13] + $t14 := $Malloc(add(32, $ClosestGreaterPowerOfTwo(4))) + $MemoryStoreU64($t14, 4) + $MemoryStoreU64(add($t14, 8), $ClosestGreaterPowerOfTwo(4)) + copy_literal_string_to_memory_512532313(add($t14, 32)) + // $t15 := !=($t13, $t14) + $t15 := $LogicalNot($Eq_$vec$u8$$($t13, $t14)) + // $t16 := !($t15) + $t16 := $LogicalNot($t15) + // if ($t16) goto L4 else goto L3 + switch $t16 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t17 := 102 $t17 := 102 // abort($t17) $Abort($t17) } - case 6 { - // label L2 + case 8 { + // label L5 // $t18 := copy($t0) $t18 := mload($locals) // $t19 := [10, 11, 12] @@ -5942,20 +6242,25 @@ object "test_A2_Vectors_test_vector_equality" { copy_literal_string_to_memory_2815201339(add($t19, 32)) // $t20 := !=($t18, $t19) $t20 := $LogicalNot($Eq_$vec$u8$$($t18, $t19)) - // if ($t20) goto L4 else goto L5 + // if ($t20) goto L7 else goto L6 switch $t20 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t21 := 103 $t21 := 103 // abort($t21) $Abort($t21) } - case 8 { - // label L4 + case 11 { + // label L8 // $t22 := copy($t0) $t22 := mload($locals) // $t23 := [10, 11, 12] @@ -5967,20 +6272,25 @@ object "test_A2_Vectors_test_vector_equality" { $t24 := $Eq_$vec$u8$$($t22, $t23) // $t25 := !($t24) $t25 := $LogicalNot($t24) - // if ($t25) goto L6 else goto L7 + // if ($t25) goto L10 else goto L9 switch $t25 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t26 := 104 $t26 := 104 // abort($t26) $Abort($t26) } - case 10 { - // label L6 + case 14 { + // label L11 // $t27 := borrow_local($t0) $t27 := $MakePtr(false, $locals) // $t28 := 14 @@ -5996,20 +6306,25 @@ object "test_A2_Vectors_test_vector_equality" { copy_literal_string_to_memory_337779769(add($t30, 32)) // $t31 := ==($t29, $t30) $t31 := $Eq_$vec$u8$$($t29, $t30) - // if ($t31) goto L8 else goto L9 + // if ($t31) goto L13 else goto L12 switch $t31 - case 0 { $block := 11 } - default { $block := 12 } + case 0 { $block := 16 } + default { $block := 15 } } - case 11 { - // label L9 + case 15 { + // label L13 + // goto L14 + $block := 17 + } + case 16 { + // label L12 // $t32 := 105 $t32 := 105 // abort($t32) $Abort($t32) } - case 12 { - // label L8 + case 17 { + // label L14 // return () $Free($locals, 32) leave @@ -6319,7 +6634,7 @@ object "test_A2_Vectors_test_vector_equality" { } } } -===> Test result of Vectors::test_vector_equality: Succeed(Stopped) (used_gas=7346): [] +===> Test result of Vectors::test_vector_equality: Succeed(Stopped) (used_gas=8658): [] // test of Vectors::test_vector_equality_struct /* ======================================= @@ -6340,13 +6655,34 @@ object "test_A2_Vectors_test_vector_equality_struct" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t7 := 101 $t7 := 101 // abort($t7) $Abort($t7) } - case 3 { - // label L0 + case 4 { + // $t2 := vector::empty() + mstore($locals, A1_vector_empty$A2_Vectors_R$()) + // $t3 := vector::empty() + mstore(add($locals, 32), A1_vector_empty$A2_Vectors_R$()) + // $t4 := copy($t2) + $t4 := mload($locals) + // $t5 := copy($t3) + $t5 := mload(add($locals, 32)) + // $t6 := ==($t4, $t5) + $t6 := $Eq_$vec$A2_Vectors_R$$($t4, $t5) + // if ($t6) goto L1 else goto L0 + switch $t6 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t8 := 42 $t8 := 42 // $t9 := true @@ -6380,36 +6716,25 @@ object "test_A2_Vectors_test_vector_equality_struct" { $t16 := mload(add($locals, 32)) // $t17 := !=($t15, $t16) $t17 := $LogicalNot($Eq_$vec$A2_Vectors_R$$($t15, $t16)) - // if ($t17) goto L2 else goto L3 + // if ($t17) goto L4 else goto L3 switch $t17 - case 0 { $block := 5 } + case 0 { $block := 7 } default { $block := 6 } } - case 4 { - // $t2 := vector::empty() - mstore($locals, A1_vector_empty$A2_Vectors_R$()) - // $t3 := vector::empty() - mstore(add($locals, 32), A1_vector_empty$A2_Vectors_R$()) - // $t4 := copy($t2) - $t4 := mload($locals) - // $t5 := copy($t3) - $t5 := mload(add($locals, 32)) - // $t6 := ==($t4, $t5) - $t6 := $Eq_$vec$A2_Vectors_R$$($t4, $t5) - // if ($t6) goto L0 else goto L1 - switch $t6 - case 0 { $block := 2 } - default { $block := 3 } + case 6 { + // label L4 + // goto L5 + $block := 8 } - case 5 { + case 7 { // label L3 // $t18 := 102 $t18 := 102 // abort($t18) $Abort($t18) } - case 6 { - // label L2 + case 8 { + // label L5 // $t19 := borrow_local($t3) $t19 := $MakePtr(false, add($locals, 32)) // vector::push_back($t19, $t13) @@ -6420,20 +6745,25 @@ object "test_A2_Vectors_test_vector_equality_struct" { $t21 := mload(add($locals, 32)) // $t22 := ==($t20, $t21) $t22 := $Eq_$vec$A2_Vectors_R$$($t20, $t21) - // if ($t22) goto L4 else goto L5 + // if ($t22) goto L7 else goto L6 switch $t22 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t23 := 103 $t23 := 103 // abort($t23) $Abort($t23) } - case 8 { - // label L4 + case 11 { + // label L8 // $t24 := 42 $t24 := 42 // $t25 := false @@ -6467,20 +6797,25 @@ object "test_A2_Vectors_test_vector_equality_struct" { $t32 := mload(add($locals, 32)) // $t33 := !=($t31, $t32) $t33 := $LogicalNot($Eq_$vec$A2_Vectors_R$$($t31, $t32)) - // if ($t33) goto L6 else goto L7 + // if ($t33) goto L10 else goto L9 switch $t33 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t34 := 104 $t34 := 104 // abort($t34) $Abort($t34) } - case 10 { - // label L6 + case 14 { + // label L11 // $t35 := borrow_local($t3) $t35 := $MakePtr(false, add($locals, 32)) // vector::push_back($t35, $t29) @@ -6491,20 +6826,25 @@ object "test_A2_Vectors_test_vector_equality_struct" { $t37 := mload(add($locals, 32)) // $t38 := !=($t36, $t37) $t38 := $LogicalNot($Eq_$vec$A2_Vectors_R$$($t36, $t37)) - // if ($t38) goto L8 else goto L9 + // if ($t38) goto L13 else goto L12 switch $t38 - case 0 { $block := 11 } - default { $block := 12 } + case 0 { $block := 16 } + default { $block := 15 } } - case 11 { - // label L9 + case 15 { + // label L13 + // goto L14 + $block := 17 + } + case 16 { + // label L12 // $t39 := 105 $t39 := 105 // abort($t39) $Abort($t39) } - case 12 { - // label L8 + case 17 { + // label L14 // return () $Free($locals, 64) leave @@ -6884,7 +7224,7 @@ object "test_A2_Vectors_test_vector_equality_struct" { } } } -===> Test result of Vectors::test_vector_equality_struct: Succeed(Stopped) (used_gas=9065): [] +===> Test result of Vectors::test_vector_equality_struct: Succeed(Stopped) (used_gas=10390): [] // test of Vectors::test_vectors_in_structs /* ======================================= @@ -6905,32 +7245,16 @@ object "test_A2_Vectors_test_vectors_in_structs" { switch $block case 2 { // label L1 + // goto L2 + $block := 5 + } + case 3 { + // label L0 // $t18 := 101 $t18 := 101 // abort($t18) $Abort($t18) } - case 3 { - // label L0 - // $t19 := borrow_local($t0) - $t19 := $MakePtr(false, r) - // $t20 := borrow_field.v($t19) - $t20 := $IndexPtr($t19, 32) - // $t21 := 0 - $t21 := 0 - // $t22 := vector::borrow($t20, $t21) - $t22 := A1_vector_borrow$u64$($t20, $t21) - // $t23 := read_ref($t22) - $t23 := $LoadU64($t22) - // $t24 := 10 - $t24 := 10 - // $t25 := ==($t23, $t24) - $t25 := $Eq($t23, $t24) - // if ($t25) goto L2 else goto L3 - switch $t25 - case 0 { $block := 5 } - default { $block := 6 } - } case 4 { // $t1 := vector::empty() mstore($locals, A1_vector_empty$u64$()) @@ -6985,20 +7309,46 @@ object "test_A2_Vectors_test_vectors_in_structs" { $t16 := 3 // $t17 := ==($t15, $t16) $t17 := $Eq($t15, $t16) - // if ($t17) goto L0 else goto L1 + // if ($t17) goto L1 else goto L0 switch $t17 - case 0 { $block := 2 } - default { $block := 3 } + case 0 { $block := 3 } + default { $block := 2 } } case 5 { + // label L2 + // $t19 := borrow_local($t0) + $t19 := $MakePtr(false, r) + // $t20 := borrow_field.v($t19) + $t20 := $IndexPtr($t19, 32) + // $t21 := 0 + $t21 := 0 + // $t22 := vector::borrow($t20, $t21) + $t22 := A1_vector_borrow$u64$($t20, $t21) + // $t23 := read_ref($t22) + $t23 := $LoadU64($t22) + // $t24 := 10 + $t24 := 10 + // $t25 := ==($t23, $t24) + $t25 := $Eq($t23, $t24) + // if ($t25) goto L4 else goto L3 + switch $t25 + case 0 { $block := 7 } + default { $block := 6 } + } + case 6 { + // label L4 + // goto L5 + $block := 8 + } + case 7 { // label L3 // $t26 := 102 $t26 := 102 // abort($t26) $Abort($t26) } - case 6 { - // label L2 + case 8 { + // label L5 // $t27 := borrow_local($t0) $t27 := $MakePtr(false, r) // $t28 := borrow_field.v($t27) @@ -7013,20 +7363,25 @@ object "test_A2_Vectors_test_vectors_in_structs" { $t32 := 11 // $t33 := ==($t31, $t32) $t33 := $Eq($t31, $t32) - // if ($t33) goto L4 else goto L5 + // if ($t33) goto L7 else goto L6 switch $t33 - case 0 { $block := 7 } - default { $block := 8 } + case 0 { $block := 10 } + default { $block := 9 } } - case 7 { - // label L5 + case 9 { + // label L7 + // goto L8 + $block := 11 + } + case 10 { + // label L6 // $t34 := 103 $t34 := 103 // abort($t34) $Abort($t34) } - case 8 { - // label L4 + case 11 { + // label L8 // $t35 := borrow_local($t0) $t35 := $MakePtr(false, r) // $t36 := borrow_field.v($t35) @@ -7041,20 +7396,25 @@ object "test_A2_Vectors_test_vectors_in_structs" { $t40 := 12 // $t41 := ==($t39, $t40) $t41 := $Eq($t39, $t40) - // if ($t41) goto L6 else goto L7 + // if ($t41) goto L10 else goto L9 switch $t41 - case 0 { $block := 9 } - default { $block := 10 } + case 0 { $block := 13 } + default { $block := 12 } } - case 9 { - // label L7 + case 12 { + // label L10 + // goto L11 + $block := 14 + } + case 13 { + // label L9 // $t42 := 104 $t42 := 104 // abort($t42) $Abort($t42) } - case 10 { - // label L6 + case 14 { + // label L11 // $t43 := 41 $t43 := 41 // $t44 := borrow_local($t0) @@ -7081,20 +7441,25 @@ object "test_A2_Vectors_test_vectors_in_structs" { $t53 := 41 // $t54 := ==($t52, $t53) $t54 := $Eq($t52, $t53) - // if ($t54) goto L8 else goto L9 + // if ($t54) goto L13 else goto L12 switch $t54 - case 0 { $block := 11 } - default { $block := 12 } + case 0 { $block := 16 } + default { $block := 15 } } - case 11 { - // label L9 + case 15 { + // label L13 + // goto L14 + $block := 17 + } + case 16 { + // label L12 // $t55 := 105 $t55 := 105 // abort($t55) $Abort($t55) } - case 12 { - // label L8 + case 17 { + // label L14 // $t56 := Vectors::one_elem_u64() $t56 := A2_Vectors_one_elem_u64() // $t57 := borrow_local($t0) @@ -7125,20 +7490,25 @@ object "test_A2_Vectors_test_vectors_in_structs" { $t62 := 1 // $t63 := ==($t61, $t62) $t63 := $Eq($t61, $t62) - // if ($t63) goto L10 else goto L11 + // if ($t63) goto L16 else goto L15 switch $t63 - case 0 { $block := 13 } - default { $block := 14 } + case 0 { $block := 19 } + default { $block := 18 } } - case 13 { - // label L11 + case 18 { + // label L16 + // goto L17 + $block := 20 + } + case 19 { + // label L15 // $t64 := 106 $t64 := 106 // abort($t64) $Abort($t64) } - case 14 { - // label L10 + case 20 { + // label L17 // $t65 := borrow_local($t0) $t65 := $MakePtr(false, r) // $t66 := borrow_field.v($t65) @@ -7153,20 +7523,25 @@ object "test_A2_Vectors_test_vectors_in_structs" { $t70 := 42 // $t71 := ==($t69, $t70) $t71 := $Eq($t69, $t70) - // if ($t71) goto L12 else goto L13 + // if ($t71) goto L19 else goto L18 switch $t71 - case 0 { $block := 15 } - default { $block := 16 } + case 0 { $block := 22 } + default { $block := 21 } } - case 15 { - // label L13 + case 21 { + // label L19 + // goto L20 + $block := 23 + } + case 22 { + // label L18 // $t72 := 107 $t72 := 107 // abort($t72) $Abort($t72) } - case 16 { - // label L12 + case 23 { + // label L20 // return () $Free($locals, 32) leave @@ -7457,4 +7832,4 @@ object "test_A2_Vectors_test_vectors_in_structs" { } } } -===> Test result of Vectors::test_vectors_in_structs: Succeed(Stopped) (used_gas=8586): [] +===> Test result of Vectors::test_vectors_in_structs: Succeed(Stopped) (used_gas=11062): [] diff --git a/language/evm/move-to-yul/tests/dispatcher_testsuite.rs b/language/evm/move-to-yul/tests/dispatcher_testsuite.rs index 26cba3b798..2e0e1c73c9 100644 --- a/language/evm/move-to-yul/tests/dispatcher_testsuite.rs +++ b/language/evm/move-to-yul/tests/dispatcher_testsuite.rs @@ -46,6 +46,7 @@ fn compile_yul_to_bytecode_bytes(filename: &str) -> Result> { let deps = vec![ path_from_crate_root("../stdlib/sources"), path_from_crate_root("../../move-stdlib/sources"), + path_from_crate_root("../../extensions/async/move-async-lib/sources"), ]; let mut named_address_map = move_stdlib_named_addresses(); named_address_map.insert( @@ -56,6 +57,10 @@ fn compile_yul_to_bytecode_bytes(filename: &str) -> Result> { "Evm".to_string(), NumericalAddress::parse_str("0x2").unwrap(), ); + named_address_map.insert( + "Async".to_string(), + NumericalAddress::parse_str("0x1").unwrap(), + ); let env = run_model_builder_with_options( vec![PackagePaths { name: None, diff --git a/language/evm/move-to-yul/tests/test-dispatcher/DispatcherArrayDecoding.exp b/language/evm/move-to-yul/tests/test-dispatcher/DispatcherArrayDecoding.exp index 935dbc898a..d53fac7861 100644 --- a/language/evm/move-to-yul/tests/test-dispatcher/DispatcherArrayDecoding.exp +++ b/language/evm/move-to-yul/tests/test-dispatcher/DispatcherArrayDecoding.exp @@ -278,7 +278,7 @@ object "A2_M" { // label L3 // $t11 := <($t1, $t8) $t11 := $Lt(i, $t8) - // if ($t11) goto L0 else goto L2 + // if ($t11) goto L1 else goto L0 switch $t11 case 0 { $block := 5 } default { $block := 4 } @@ -300,7 +300,19 @@ object "A2_M" { $block := 2 } case 4 { + // label L1 + // goto L2 + $block := 6 + } + case 5 { // label L0 + // return $t3 + $result := sum + $Free($locals, 32) + leave + } + case 6 { + // label L2 // $t12 := borrow_local($t0) $t12 := $MakePtr(false, $locals) // $t13 := vector::borrow>($t12, $t1) @@ -328,13 +340,6 @@ object "A2_M" { // goto L3 $block := 2 } - case 5 { - // label L2 - // return $t3 - $result := sum - $Free($locals, 32) - leave - } } } @@ -351,7 +356,7 @@ object "A2_M" { $t9 := 2 // $t10 := <($t1, $t9) $t10 := $Lt(i, $t9) - // if ($t10) goto L0 else goto L2 + // if ($t10) goto L1 else goto L0 switch $t10 case 0 { $block := 5 } default { $block := 4 } @@ -369,7 +374,19 @@ object "A2_M" { $block := 2 } case 4 { + // label L1 + // goto L2 + $block := 6 + } + case 5 { // label L0 + // return $t4 + $result := sum + $Free($locals, 32) + leave + } + case 6 { + // label L2 // $t11 := borrow_local($t0) $t11 := $MakePtr(false, $locals) // $t12 := vector::borrow>($t11, $t1) @@ -381,26 +398,34 @@ object "A2_M" { // $t2 := $t14 j := $t14 // goto L6 - $block := 6 + $block := 7 } - case 5 { - // label L2 - // return $t4 - $result := sum - $Free($locals, 32) - leave - } - case 6 { + case 7 { // label L6 // $t15 := <($t2, $t13) $t15 := $Lt(j, $t13) - // if ($t15) goto L3 else goto L5 + // if ($t15) goto L4 else goto L3 switch $t15 - case 0 { $block := 8 } - default { $block := 7 } + case 0 { $block := 9 } + default { $block := 8 } } - case 7 { + case 8 { + // label L4 + // goto L5 + $block := 10 + } + case 9 { // label L3 + // destroy($t12) + // $t19 := 1 + $t19 := 1 + // $t1 := +($t1, $t19) + i := $AddU64(i, $t19) + // goto L7 + $block := 2 + } + case 10 { + // label L5 // $t16 := vector::borrow($t12, $t2) $t16 := A1_vector_borrow$u128$($t12, j) // $t17 := read_ref($t16) @@ -412,17 +437,7 @@ object "A2_M" { // $t2 := +($t2, $t18) j := $AddU64(j, $t18) // goto L6 - $block := 6 - } - case 8 { - // label L5 - // destroy($t12) - // $t19 := 1 - $t19 := 1 - // $t1 := +($t1, $t19) - i := $AddU64(i, $t19) - // goto L7 - $block := 2 + $block := 7 } } } @@ -438,7 +453,7 @@ object "A2_M" { // label L3 // $t10 := <($t1, $t8) $t10 := $Lt(i, $t8) - // if ($t10) goto L0 else goto L2 + // if ($t10) goto L1 else goto L0 switch $t10 case 0 { $block := 5 } default { $block := 4 } @@ -458,7 +473,19 @@ object "A2_M" { $block := 2 } case 4 { + // label L1 + // goto L2 + $block := 6 + } + case 5 { // label L0 + // return $t3 + $result := sum + $Free($locals, 32) + leave + } + case 6 { + // label L2 // $t11 := borrow_local($t0) $t11 := $MakePtr(false, $locals) // $t12 := vector::borrow>($t11, $t1) @@ -486,13 +513,6 @@ object "A2_M" { // goto L3 $block := 2 } - case 5 { - // label L2 - // return $t3 - $result := sum - $Free($locals, 32) - leave - } } } @@ -638,7 +658,7 @@ object "A2_M" { $t8 := 2 // $t9 := <($t1, $t8) $t9 := $Lt(i, $t8) - // if ($t9) goto L0 else goto L2 + // if ($t9) goto L1 else goto L0 switch $t9 case 0 { $block := 5 } default { $block := 4 } @@ -654,7 +674,19 @@ object "A2_M" { $block := 2 } case 4 { + // label L1 + // goto L2 + $block := 6 + } + case 5 { // label L0 + // return $t4 + $result := sum + $Free($locals, 32) + leave + } + case 6 { + // label L2 // $t10 := borrow_local($t0) $t10 := $MakePtr(false, $locals) // $t11 := vector::borrow>($t10, $t1) @@ -666,26 +698,34 @@ object "A2_M" { // $t2 := $t13 j := $t13 // goto L6 - $block := 6 - } - case 5 { - // label L2 - // return $t4 - $result := sum - $Free($locals, 32) - leave + $block := 7 } - case 6 { + case 7 { // label L6 // $t14 := <($t2, $t12) $t14 := $Lt(j, $t12) - // if ($t14) goto L3 else goto L5 + // if ($t14) goto L4 else goto L3 switch $t14 - case 0 { $block := 8 } - default { $block := 7 } + case 0 { $block := 9 } + default { $block := 8 } } - case 7 { + case 8 { + // label L4 + // goto L5 + $block := 10 + } + case 9 { // label L3 + // destroy($t11) + // $t18 := 1 + $t18 := 1 + // $t1 := +($t1, $t18) + i := $AddU64(i, $t18) + // goto L7 + $block := 2 + } + case 10 { + // label L5 // $t15 := vector::borrow($t11, $t2) $t15 := A1_vector_borrow$A2_U256_U256$($t11, j) // $t16 := read_ref($t15) @@ -697,17 +737,7 @@ object "A2_M" { // $t2 := +($t2, $t17) j := $AddU64(j, $t17) // goto L6 - $block := 6 - } - case 8 { - // label L5 - // destroy($t11) - // $t18 := 1 - $t18 := 1 - // $t1 := +($t1, $t18) - i := $AddU64(i, $t18) - // goto L7 - $block := 2 + $block := 7 } } } @@ -725,7 +755,7 @@ object "A2_M" { $t9 := 2 // $t10 := <($t1, $t9) $t10 := $Lt(i, $t9) - // if ($t10) goto L0 else goto L2 + // if ($t10) goto L1 else goto L0 switch $t10 case 0 { $block := 5 } default { $block := 4 } @@ -743,7 +773,19 @@ object "A2_M" { $block := 2 } case 4 { + // label L1 + // goto L2 + $block := 6 + } + case 5 { // label L0 + // return $t4 + $result := sum + $Free($locals, 32) + leave + } + case 6 { + // label L2 // $t11 := borrow_local($t0) $t11 := $MakePtr(false, $locals) // $t12 := vector::borrow>($t11, $t1) @@ -755,26 +797,34 @@ object "A2_M" { // $t2 := $t14 j := $t14 // goto L6 - $block := 6 + $block := 7 } - case 5 { - // label L2 - // return $t4 - $result := sum - $Free($locals, 32) - leave - } - case 6 { + case 7 { // label L6 // $t15 := <($t2, $t13) $t15 := $Lt(j, $t13) - // if ($t15) goto L3 else goto L5 + // if ($t15) goto L4 else goto L3 switch $t15 - case 0 { $block := 8 } - default { $block := 7 } + case 0 { $block := 9 } + default { $block := 8 } } - case 7 { + case 8 { + // label L4 + // goto L5 + $block := 10 + } + case 9 { // label L3 + // destroy($t12) + // $t19 := 1 + $t19 := 1 + // $t1 := +($t1, $t19) + i := $AddU64(i, $t19) + // goto L7 + $block := 2 + } + case 10 { + // label L5 // $t16 := vector::borrow($t12, $t2) $t16 := A1_vector_borrow$u64$($t12, j) // $t17 := read_ref($t16) @@ -786,17 +836,7 @@ object "A2_M" { // $t2 := +($t2, $t18) j := $AddU64(j, $t18) // goto L6 - $block := 6 - } - case 8 { - // label L5 - // destroy($t12) - // $t19 := 1 - $t19 := 1 - // $t1 := +($t1, $t19) - i := $AddU64(i, $t19) - // goto L7 - $block := 2 + $block := 7 } } } @@ -814,7 +854,7 @@ object "A2_M" { $t9 := 2 // $t10 := <($t1, $t9) $t10 := $Lt(i, $t9) - // if ($t10) goto L0 else goto L2 + // if ($t10) goto L1 else goto L0 switch $t10 case 0 { $block := 5 } default { $block := 4 } @@ -832,7 +872,19 @@ object "A2_M" { $block := 2 } case 4 { + // label L1 + // goto L2 + $block := 6 + } + case 5 { // label L0 + // return $t4 + $result := sum + $Free($locals, 32) + leave + } + case 6 { + // label L2 // $t11 := borrow_local($t0) $t11 := $MakePtr(false, $locals) // $t12 := vector::borrow>($t11, $t1) @@ -844,26 +896,34 @@ object "A2_M" { // $t2 := $t14 j := $t14 // goto L6 - $block := 6 + $block := 7 } - case 5 { - // label L2 - // return $t4 - $result := sum - $Free($locals, 32) - leave - } - case 6 { + case 7 { // label L6 // $t15 := <($t2, $t13) $t15 := $Lt(j, $t13) - // if ($t15) goto L3 else goto L5 + // if ($t15) goto L4 else goto L3 switch $t15 - case 0 { $block := 8 } - default { $block := 7 } + case 0 { $block := 9 } + default { $block := 8 } } - case 7 { + case 8 { + // label L4 + // goto L5 + $block := 10 + } + case 9 { // label L3 + // destroy($t12) + // $t19 := 1 + $t19 := 1 + // $t1 := +($t1, $t19) + i := $AddU64(i, $t19) + // goto L7 + $block := 2 + } + case 10 { + // label L5 // $t16 := vector::borrow($t12, $t2) $t16 := A1_vector_borrow$u8$($t12, j) // $t17 := read_ref($t16) @@ -875,17 +935,7 @@ object "A2_M" { // $t2 := +($t2, $t18) j := $AddU64(j, $t18) // goto L6 - $block := 6 - } - case 8 { - // label L5 - // destroy($t12) - // $t19 := 1 - $t19 := 1 - // $t1 := +($t1, $t19) - i := $AddU64(i, $t19) - // goto L7 - $block := 2 + $block := 7 } } } @@ -901,7 +951,7 @@ object "A2_M" { // label L3 // $t10 := <($t1, $t8) $t10 := $Lt(i, $t8) - // if ($t10) goto L0 else goto L2 + // if ($t10) goto L1 else goto L0 switch $t10 case 0 { $block := 5 } default { $block := 4 } @@ -921,7 +971,19 @@ object "A2_M" { $block := 2 } case 4 { + // label L1 + // goto L2 + $block := 6 + } + case 5 { // label L0 + // return $t3 + $result := sum + $Free($locals, 32) + leave + } + case 6 { + // label L2 // $t11 := borrow_local($t0) $t11 := $MakePtr(false, $locals) // $t12 := vector::borrow>($t11, $t1) @@ -949,13 +1011,6 @@ object "A2_M" { // goto L3 $block := 2 } - case 5 { - // label L2 - // return $t3 - $result := sum - $Free($locals, 32) - leave - } } } @@ -970,7 +1025,7 @@ object "A2_M" { // label L3 // $t11 := <($t1, $t8) $t11 := $Lt(i, $t8) - // if ($t11) goto L0 else goto L2 + // if ($t11) goto L1 else goto L0 switch $t11 case 0 { $block := 5 } default { $block := 4 } @@ -992,7 +1047,19 @@ object "A2_M" { $block := 2 } case 4 { + // label L1 + // goto L2 + $block := 6 + } + case 5 { // label L0 + // return $t3 + $result := sum + $Free($locals, 32) + leave + } + case 6 { + // label L2 // $t12 := borrow_local($t0) $t12 := $MakePtr(false, $locals) // $t13 := vector::borrow>($t12, $t1) @@ -1020,13 +1087,6 @@ object "A2_M" { // goto L3 $block := 2 } - case 5 { - // label L2 - // return $t3 - $result := sum - $Free($locals, 32) - leave - } } } @@ -1041,7 +1101,7 @@ object "A2_M" { // label L3 // $t11 := <($t1, $t8) $t11 := $Lt(i, $t8) - // if ($t11) goto L0 else goto L2 + // if ($t11) goto L1 else goto L0 switch $t11 case 0 { $block := 5 } default { $block := 4 } @@ -1063,7 +1123,19 @@ object "A2_M" { $block := 2 } case 4 { + // label L1 + // goto L2 + $block := 6 + } + case 5 { // label L0 + // return $t3 + $result := sum + $Free($locals, 32) + leave + } + case 6 { + // label L2 // $t12 := borrow_local($t0) $t12 := $MakePtr(false, $locals) // $t13 := vector::borrow>($t12, $t1) @@ -1091,13 +1163,6 @@ object "A2_M" { // goto L3 $block := 2 } - case 5 { - // label L2 - // return $t3 - $result := sum - $Free($locals, 32) - leave - } } } @@ -1112,7 +1177,7 @@ object "A2_M" { // label L7 // $t10 := <($t1, $t7) $t10 := $Lt(i, $t7) - // if ($t10) goto L0 else goto L2 + // if ($t10) goto L1 else goto L0 switch $t10 case 0 { $block := 5 } default { $block := 4 } @@ -1134,7 +1199,19 @@ object "A2_M" { $block := 2 } case 4 { + // label L1 + // goto L2 + $block := 6 + } + case 5 { // label L0 + // return $t4 + $result := sum + $Free($locals, 32) + leave + } + case 6 { + // label L2 // $t11 := borrow_local($t0) $t11 := $MakePtr(false, $locals) // $t12 := vector::borrow>($t11, $t1) @@ -1144,28 +1221,36 @@ object "A2_M" { // $t2 := $t13 j := $t13 // goto L6 - $block := 6 + $block := 7 } - case 5 { - // label L2 - // return $t4 - $result := sum - $Free($locals, 32) - leave - } - case 6 { + case 7 { // label L6 // $t14 := vector::length($t12) $t14 := A1_vector_length$u128$($t12) // $t15 := <($t2, $t14) $t15 := $Lt(j, $t14) - // if ($t15) goto L3 else goto L5 + // if ($t15) goto L4 else goto L3 switch $t15 - case 0 { $block := 8 } - default { $block := 7 } + case 0 { $block := 9 } + default { $block := 8 } } - case 7 { + case 8 { + // label L4 + // goto L5 + $block := 10 + } + case 9 { // label L3 + // destroy($t12) + // $t19 := 1 + $t19 := 1 + // $t1 := +($t1, $t19) + i := $AddU64(i, $t19) + // goto L7 + $block := 2 + } + case 10 { + // label L5 // $t16 := vector::borrow($t12, $t2) $t16 := A1_vector_borrow$u128$($t12, j) // $t17 := read_ref($t16) @@ -1177,17 +1262,7 @@ object "A2_M" { // $t2 := +($t2, $t18) j := $AddU64(j, $t18) // goto L6 - $block := 6 - } - case 8 { - // label L5 - // destroy($t12) - // $t19 := 1 - $t19 := 1 - // $t1 := +($t1, $t19) - i := $AddU64(i, $t19) - // goto L7 - $block := 2 + $block := 7 } } } diff --git a/language/evm/move-to-yul/tests/test-dispatcher/DispatcherBytesDecoding.exp b/language/evm/move-to-yul/tests/test-dispatcher/DispatcherBytesDecoding.exp index 663ce183a0..37d2fe3220 100644 --- a/language/evm/move-to-yul/tests/test-dispatcher/DispatcherBytesDecoding.exp +++ b/language/evm/move-to-yul/tests/test-dispatcher/DispatcherBytesDecoding.exp @@ -107,7 +107,7 @@ object "A2_M" { // label L7 // $t16 := <($t1, $t12) $t16 := $Lt(i, $t12) - // if ($t16) goto L0 else goto L2 + // if ($t16) goto L1 else goto L0 switch $t16 case 0 { $block := 5 } default { $block := 4 } @@ -133,7 +133,20 @@ object "A2_M" { $block := 2 } case 4 { + // label L1 + // goto L2 + $block := 6 + } + case 5 { // label L0 + // return ($t7, $t6) + $result0 := sum_len + $result1 := sum + $Free($locals, 32) + leave + } + case 6 { + // label L2 // $t17 := borrow_local($t0) $t17 := $MakePtr(false, $locals) // $t18 := vector::borrow>>($t17, $t1) @@ -145,27 +158,34 @@ object "A2_M" { // $t2 := $t20 j := $t20 // goto L6 - $block := 6 + $block := 7 } - case 5 { - // label L2 - // return ($t7, $t6) - $result0 := sum_len - $result1 := sum - $Free($locals, 32) - leave - } - case 6 { + case 7 { // label L6 // $t21 := <($t2, $t19) $t21 := $Lt(j, $t19) - // if ($t21) goto L3 else goto L5 + // if ($t21) goto L4 else goto L3 switch $t21 - case 0 { $block := 8 } - default { $block := 7 } + case 0 { $block := 9 } + default { $block := 8 } } - case 7 { + case 8 { + // label L4 + // goto L5 + $block := 10 + } + case 9 { // label L3 + // destroy($t18) + // $t29 := 1 + $t29 := 1 + // $t1 := +($t1, $t29) + i := $AddU64(i, $t29) + // goto L7 + $block := 2 + } + case 10 { + // label L5 // $t22 := vector::borrow>($t18, $t2) $t22 := A1_vector_borrow$vec$u8$$($t18, j) // $t23 := vector::length($t22) @@ -187,17 +207,7 @@ object "A2_M" { // $t2 := +($t2, $t28) j := $AddU64(j, $t28) // goto L6 - $block := 6 - } - case 8 { - // label L5 - // destroy($t18) - // $t29 := 1 - $t29 := 1 - // $t1 := +($t1, $t29) - i := $AddU64(i, $t29) - // goto L7 - $block := 2 + $block := 7 } } } diff --git a/language/evm/move-to-yul/tests/test-dispatcher/ExternalCall.exp b/language/evm/move-to-yul/tests/test-dispatcher/ExternalCall.exp index 593070f0f4..37e207b622 100644 --- a/language/evm/move-to-yul/tests/test-dispatcher/ExternalCall.exp +++ b/language/evm/move-to-yul/tests/test-dispatcher/ExternalCall.exp @@ -111,7 +111,7 @@ object "A2_M" { for {} true {} { switch $block case 2 { - // label L0 + // label L1 // $t4 := move($t1) $t4 := v // $t5 := ExternalResult::unwrap($t4) @@ -121,7 +121,7 @@ object "A2_M" { leave } case 3 { - // label L2 + // label L0 // $t6 := U256::one() $t6 := A2_U256_one() // return $t6 @@ -135,7 +135,7 @@ object "A2_M" { $t2 := $MakePtr(false, v) // $t3 := ExternalResult::is_ok($t2) $t3 := A2_ExternalResult_is_ok$A2_U256_U256$($t2) - // if ($t3) goto L0 else goto L2 + // if ($t3) goto L1 else goto L0 switch $t3 case 0 { $block := 3 } default { $block := 2 } @@ -144,35 +144,35 @@ object "A2_M" { } function A2_M_call_unit(addr) { - let _u, v, $t3, $t4, $t5, $t6 + let v, $t2, $t3, $t4, $t5 let $block := 4 for {} true {} { switch $block case 2 { - // label L0 - // $t5 := move($t2) - $t5 := v - // $t6 := ExternalResult::unwrap($t5) - $t6 := A2_ExternalResult_unwrap$A2_Evm_Unit$($t5) - // destroy($t6) - $Free($t6, 1) - // goto L2 + // label L1 + // $t4 := move($t1) + $t4 := v + // $t5 := ExternalResult::unwrap($t4) + $t5 := A2_ExternalResult_unwrap$A2_Evm_Unit$($t4) + // destroy($t5) + $Free($t5, 1) + // goto L0 $block := 3 } case 3 { - // label L2 + // label L0 // return () leave } case 4 { - // $t2 := M::test_unit($t0) + // $t1 := M::test_unit($t0) v := A2_M_test_unit(addr) - // $t3 := borrow_local($t2) - $t3 := $MakePtr(false, v) - // $t4 := ExternalResult::is_ok($t3) - $t4 := A2_ExternalResult_is_ok$A2_Evm_Unit$($t3) - // if ($t4) goto L0 else goto L2 - switch $t4 + // $t2 := borrow_local($t1) + $t2 := $MakePtr(false, v) + // $t3 := ExternalResult::is_ok($t2) + $t3 := A2_ExternalResult_is_ok$A2_Evm_Unit$($t2) + // if ($t3) goto L1 else goto L0 + switch $t3 case 0 { $block := 3 } default { $block := 2 } } @@ -180,133 +180,133 @@ object "A2_M" { } function A2_M_test_is_approved_for_all() -> $result { - let account, contract_addr, operator, $t3, $t4, $t5, $t6 - // $t3 := 0x3 - $t3 := 0x3 - // $t4 := 0x4 - $t4 := 0x4 - // $t5 := 0x5 - $t5 := 0x5 - // $t6 := M::is_approved_for_all($t3, $t4, $t5) - $t6 := A2_M_is_approved_for_all($t3, $t4, $t5) - // return $t6 - $result := $t6 + let $t0, $t1, $t2, $t3 + // $t0 := 0x3 + $t0 := 0x3 + // $t1 := 0x4 + $t1 := 0x4 + // $t2 := 0x5 + $t2 := 0x5 + // $t3 := M::is_approved_for_all($t0, $t1, $t2) + $t3 := A2_M_is_approved_for_all($t0, $t1, $t2) + // return $t3 + $result := $t3 } function A2_M_test_multi_ret() -> $result0, $result1 { - let contract_addr, data, v, $t3, $t4, $t5, $t6, $t7 - // $t3 := 0 - $t3 := 0 - // $t4 := vector::empty() - $t4 := A1_vector_empty$A2_U256_U256$() - // $t5 := 0x3 - $t5 := 0x3 - // ($t6, $t7) := M::multi_ret($t5, $t3, $t4) - $t6, $t7 := A2_M_multi_ret($t5, $t3, $t4) - // return ($t6, $t7) - $result0 := $t6 - $result1 := $t7 + let data, v, $t2, $t3, $t4, $t5, $t6 + // $t2 := 0 + $t2 := 0 + // $t3 := vector::empty() + $t3 := A1_vector_empty$A2_U256_U256$() + // $t4 := 0x3 + $t4 := 0x3 + // ($t5, $t6) := M::multi_ret($t4, $t2, $t3) + $t5, $t6 := A2_M_multi_ret($t4, $t2, $t3) + // return ($t5, $t6) + $result0 := $t5 + $result1 := $t6 } function A2_M_test_no_para() { - let contract_addr, $t1 - // $t1 := 0x3 - $t1 := 0x3 - // M::no_para($t1) - A2_M_no_para($t1) + let $t0 + // $t0 := 0x3 + $t0 := 0x3 + // M::no_para($t0) + A2_M_no_para($t0) // return () } function A2_M_test_safe_transfer_from(x, y) { - let contract_addr, data, from_addr, to_addr, token_id, $t7, $t8, $t9, $t10, $t11 - // $t7 := (u256)($t0, $t1) - $t7 := $CastU256(x, y) - // $t8 := vector::empty() - $t8 := A1_vector_empty$u8$() - // $t9 := 0x3 - $t9 := 0x3 - // $t10 := 0x4 - $t10 := 0x4 - // $t11 := 0x5 - $t11 := 0x5 - // M::safe_transfer_form($t9, $t10, $t11, $t7, $t8) - A2_M_safe_transfer_form($t9, $t10, $t11, $t7, $t8) + let data, token_id, $t4, $t5, $t6, $t7, $t8 + // $t4 := (u256)($t0, $t1) + $t4 := $CastU256(x, y) + // $t5 := vector::empty() + $t5 := A1_vector_empty$u8$() + // $t6 := 0x3 + $t6 := 0x3 + // $t7 := 0x4 + $t7 := 0x4 + // $t8 := 0x5 + $t8 := 0x5 + // M::safe_transfer_form($t6, $t7, $t8, $t4, $t5) + A2_M_safe_transfer_form($t6, $t7, $t8, $t4, $t5) // return () } function A2_M_test_try() -> $result { - let contract_addr, v, value, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13, $t14 + let v, value, $t2, $t3, $t4, $t5, $t6, $t7, $t8, $t9, $t10, $t11, $t12, $t13 let $block := 4 for {} true {} { switch $block case 2 { - // label L0 - // $t7 := 0 - $t7 := 0 - // return $t7 - $result := $t7 + // label L1 + // $t6 := 0 + $t6 := 0 + // return $t6 + $result := $t6 leave } case 3 { - // label L2 - // $t8 := borrow_local($t2) - $t8 := $MakePtr(false, value) - // $t9 := ExternalResult::is_err_reason($t8) - $t9 := A2_ExternalResult_is_err_reason$A2_U256_U256$($t8) - // if ($t9) goto L3 else goto L5 - switch $t9 + // label L0 + // $t7 := borrow_local($t1) + $t7 := $MakePtr(false, value) + // $t8 := ExternalResult::is_err_reason($t7) + $t8 := A2_ExternalResult_is_err_reason$A2_U256_U256$($t7) + // if ($t8) goto L3 else goto L2 + switch $t8 case 0 { $block := 6 } default { $block := 5 } } case 4 { - // $t3 := 340282366920938463463374607431768211458 - $t3 := 340282366920938463463374607431768211458 - // $t4 := 0x3 - $t4 := 0x3 - // $t2 := M::test_try_call($t4, $t3) - value := A2_M_test_try_call($t4, $t3) - // $t5 := borrow_local($t2) - $t5 := $MakePtr(false, value) - // $t6 := ExternalResult::is_ok($t5) - $t6 := A2_ExternalResult_is_ok$A2_U256_U256$($t5) - // if ($t6) goto L0 else goto L2 - switch $t6 + // $t2 := 340282366920938463463374607431768211458 + $t2 := 340282366920938463463374607431768211458 + // $t3 := 0x3 + $t3 := 0x3 + // $t1 := M::test_try_call($t3, $t2) + value := A2_M_test_try_call($t3, $t2) + // $t4 := borrow_local($t1) + $t4 := $MakePtr(false, value) + // $t5 := ExternalResult::is_ok($t4) + $t5 := A2_ExternalResult_is_ok$A2_U256_U256$($t4) + // if ($t5) goto L1 else goto L0 + switch $t5 case 0 { $block := 3 } default { $block := 2 } } case 5 { // label L3 - // $t10 := 1 - $t10 := 1 - // return $t10 - $result := $t10 + // $t9 := 1 + $t9 := 1 + // return $t9 + $result := $t9 leave } case 6 { - // label L5 - // $t11 := borrow_local($t2) - $t11 := $MakePtr(false, value) - // $t12 := ExternalResult::is_panic($t11) - $t12 := A2_ExternalResult_is_panic$A2_U256_U256$($t11) - // if ($t12) goto L6 else goto L8 - switch $t12 + // label L2 + // $t10 := borrow_local($t1) + $t10 := $MakePtr(false, value) + // $t11 := ExternalResult::is_panic($t10) + $t11 := A2_ExternalResult_is_panic$A2_U256_U256$($t10) + // if ($t11) goto L5 else goto L4 + switch $t11 case 0 { $block := 8 } default { $block := 7 } } case 7 { - // label L6 - // $t13 := 2 - $t13 := 2 - // return $t13 - $result := $t13 + // label L5 + // $t12 := 2 + $t12 := 2 + // return $t12 + $result := $t12 leave } case 8 { - // label L8 - // $t14 := 3 - $t14 := 3 - // return $t14 - $result := $t14 + // label L4 + // $t13 := 3 + $t13 := 3 + // return $t13 + $result := $t13 leave } } @@ -934,13 +934,28 @@ object "A2_M" { switch $block case 2 { // label L1 - // $t5 := 1 - $t5 := 1 - // abort($t5) - $Abort($t5) + // goto L2 + $block := 5 } case 3 { // label L0 + // $t5 := 262145 + $t5 := 262145 + // abort($t5) + $Abort($t5) + } + case 4 { + // $t3 := borrow_local($t0) + $t3 := $MakePtr(false, t) + // $t4 := option::is_some<#0>($t3) + $t4 := A1_option_is_some$A2_Evm_Unit$($t3) + // if ($t4) goto L1 else goto L0 + switch $t4 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t6 := move($t0) $t6 := t // $t2 := unpack option::Option<#0>($t6) @@ -959,16 +974,6 @@ object "A2_M" { $Free($locals, 32) leave } - case 4 { - // $t3 := borrow_local($t0) - $t3 := $MakePtr(false, t) - // $t4 := option::is_some<#0>($t3) - $t4 := A1_option_is_some$A2_Evm_Unit$($t3) - // if ($t4) goto L0 else goto L1 - switch $t4 - case 0 { $block := 2 } - default { $block := 3 } - } } } @@ -996,42 +1001,53 @@ object "A2_M" { $StoreU64(v_ptr, sub(size, 1)) } function A1_option_destroy_none$A2_U256_U256$(t) { - let vec, $t2, $t3, $t4, $t5, $t6 + let $t1, $t2, $t3, $t4, $t5 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t4 := 0 - $t4 := 0 - // abort($t4) - $Abort($t4) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t5 := move($t0) - $t5 := t - // $t6 := unpack option::Option<#0>($t5) - $t6 := $MemoryLoadU256(add($t5, 0)) - $Free($t5, 32) - // vector::destroy_empty<#0>($t6) - A1_vector_destroy_empty$A2_U256_U256$($t6) - // return () - leave + // $t3 := 262144 + $t3 := 262144 + // abort($t3) + $Abort($t3) } case 4 { - // $t2 := borrow_local($t0) - $t2 := $MakePtr(false, t) - // $t3 := option::is_none<#0>($t2) - $t3 := A1_option_is_none$A2_U256_U256$($t2) - // if ($t3) goto L0 else goto L1 - switch $t3 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := borrow_local($t0) + $t1 := $MakePtr(false, t) + // $t2 := option::is_none<#0>($t1) + $t2 := A1_option_is_none$A2_U256_U256$($t1) + // if ($t2) goto L1 else goto L0 + switch $t2 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t4 := move($t0) + $t4 := t + // $t5 := unpack option::Option<#0>($t4) + $t5 := $MemoryLoadU256(add($t4, 0)) + $Free($t4, 32) + // vector::destroy_empty<#0>($t5) + A1_vector_destroy_empty$A2_U256_U256$($t5) + // return () + leave } } } + function A1_vector_destroy_empty$A2_U256_U256$(v) { + let size := $MemoryLoadU64(v) + if $LogicalNot(iszero(size)) { $AbortBuiltin() } + let capacity := $MemoryLoadU64(add(v, 8)) + $Free(v, add(32, mul(capacity, 32))) + } function A1_option_is_none$A2_U256_U256$(t) -> $result { let $t1, $t2 // $t1 := borrow_field>.vec($t0) @@ -1042,49 +1058,54 @@ object "A2_M" { $result := $t2 } - function A1_vector_destroy_empty$A2_U256_U256$(v) { - let size := $MemoryLoadU64(v) - if $LogicalNot(iszero(size)) { $AbortBuiltin() } - let capacity := $MemoryLoadU64(add(v, 8)) - $Free(v, add(32, mul(capacity, 32))) - } function A1_option_destroy_none$vec$u8$$(t) { - let vec, $t2, $t3, $t4, $t5, $t6 + let $t1, $t2, $t3, $t4, $t5 let $block := 4 for {} true {} { switch $block case 2 { // label L1 - // $t4 := 0 - $t4 := 0 - // abort($t4) - $Abort($t4) + // goto L2 + $block := 5 } case 3 { // label L0 - // $t5 := move($t0) - $t5 := t - // $t6 := unpack option::Option<#0>($t5) - $t6 := $MemoryLoadU256(add($t5, 0)) - $Free($t5, 32) - // vector::destroy_empty<#0>($t6) - A1_vector_destroy_empty$vec$u8$$($t6) - // return () - leave + // $t3 := 262144 + $t3 := 262144 + // abort($t3) + $Abort($t3) } case 4 { - // $t2 := borrow_local($t0) - $t2 := $MakePtr(false, t) - // $t3 := option::is_none<#0>($t2) - $t3 := A1_option_is_none$vec$u8$$($t2) - // if ($t3) goto L0 else goto L1 - switch $t3 - case 0 { $block := 2 } - default { $block := 3 } + // $t1 := borrow_local($t0) + $t1 := $MakePtr(false, t) + // $t2 := option::is_none<#0>($t1) + $t2 := A1_option_is_none$vec$u8$$($t1) + // if ($t2) goto L1 else goto L0 + switch $t2 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 + // $t4 := move($t0) + $t4 := t + // $t5 := unpack option::Option<#0>($t4) + $t5 := $MemoryLoadU256(add($t4, 0)) + $Free($t4, 32) + // vector::destroy_empty<#0>($t5) + A1_vector_destroy_empty$vec$u8$$($t5) + // return () + leave } } } + function A1_vector_destroy_empty$vec$u8$$(v) { + let size := $MemoryLoadU64(v) + if $LogicalNot(iszero(size)) { $AbortBuiltin() } + let capacity := $MemoryLoadU64(add(v, 8)) + $Free(v, add(32, mul(capacity, 32))) + } function A1_option_is_none$vec$u8$$(t) -> $result { let $t1, $t2 // $t1 := borrow_field>.vec($t0) @@ -1095,12 +1116,6 @@ object "A2_M" { $result := $t2 } - function A1_vector_destroy_empty$vec$u8$$(v) { - let size := $MemoryLoadU64(v) - if $LogicalNot(iszero(size)) { $AbortBuiltin() } - let capacity := $MemoryLoadU64(add(v, 8)) - $Free(v, add(32, mul(capacity, 32))) - } function A2_M_success(contract) -> $result { // storage for arguments and returned data let $t1 := mload(0) @@ -1175,13 +1190,28 @@ object "A2_M" { switch $block case 2 { // label L1 - // $t5 := 1 - $t5 := 1 - // abort($t5) - $Abort($t5) + // goto L2 + $block := 5 } case 3 { // label L0 + // $t5 := 262145 + $t5 := 262145 + // abort($t5) + $Abort($t5) + } + case 4 { + // $t3 := borrow_local($t0) + $t3 := $MakePtr(false, t) + // $t4 := option::is_some<#0>($t3) + $t4 := A1_option_is_some$A2_U256_U256$($t3) + // if ($t4) goto L1 else goto L0 + switch $t4 + case 0 { $block := 3 } + default { $block := 2 } + } + case 5 { + // label L2 // $t6 := move($t0) $t6 := t // $t2 := unpack option::Option<#0>($t6) @@ -1200,16 +1230,6 @@ object "A2_M" { $Free($locals, 32) leave } - case 4 { - // $t3 := borrow_local($t0) - $t3 := $MakePtr(false, t) - // $t4 := option::is_some<#0>($t3) - $t4 := A1_option_is_some$A2_U256_U256$($t3) - // if ($t4) goto L0 else goto L1 - switch $t4 - case 0 { $block := 2 } - default { $block := 3 } - } } } diff --git a/language/evm/move-to-yul/tests/testsuite.rs b/language/evm/move-to-yul/tests/testsuite.rs index 81966cb4a5..f782f09153 100644 --- a/language/evm/move-to-yul/tests/testsuite.rs +++ b/language/evm/move-to-yul/tests/testsuite.rs @@ -19,6 +19,7 @@ use move_to_yul::{generator::Generator, options::Options}; use primitive_types::{H160, U256}; use std::{ collections::BTreeMap, + fmt::Write, path::{Path, PathBuf}, }; @@ -30,6 +31,7 @@ fn test_runner(path: &Path) -> datatest_stable::Result<()> { let deps = vec![ path_from_crate_root("../stdlib/sources"), path_from_crate_root("../../move-stdlib/sources"), + path_from_crate_root("../../extensions/async/move-async-lib/sources"), ]; let mut named_address_map = move_stdlib_named_addresses(); named_address_map.insert( @@ -40,6 +42,10 @@ fn test_runner(path: &Path) -> datatest_stable::Result<()> { "Evm".to_string(), NumericalAddress::parse_str("0x2").unwrap(), ); + named_address_map.insert( + "Async".to_string(), + NumericalAddress::parse_str("0x1").unwrap(), + ); let env = run_model_builder_with_options_and_compilation_flags( vec![PackagePaths { name: None, @@ -52,7 +58,9 @@ fn test_runner(path: &Path) -> datatest_stable::Result<()> { named_address_map, }], ModelBuilderOptions::default(), - move_compiler::Flags::empty().set_sources_shadow_deps(true), + move_compiler::Flags::empty() + .set_sources_shadow_deps(true) + .set_flavor("async"), )?; for exp in std::iter::once(String::new()).chain(experiments.into_iter()) { let mut options = Options { @@ -109,16 +117,19 @@ fn run_tests( let mut res = String::new(); res.push_str("!! Unit tests\n\n"); for (fun, source) in test_cases { - res.push_str(&format!( - "// test of {}\n", + writeln!( + &mut res, + "// test of {}", env.get_function(*fun).get_full_name_str() - )); + ) + .unwrap(); res.push_str(source); - res.push_str(&format!( - "===> Test result of {}: {}\n\n", + writeln!( + &mut res, + "===> Test result of {}: {}\n", env.get_function(*fun).get_full_name_str(), execute_test(env, source)? - )); + )?; } Ok(res) } diff --git a/language/extensions/async/examples/account/sources/AccountStateMachine.move b/language/extensions/async/examples/account/sources/AccountStateMachine.move index 62ed5af4ab..0b8581496c 100644 --- a/language/extensions/async/examples/account/sources/AccountStateMachine.move +++ b/language/extensions/async/examples/account/sources/AccountStateMachine.move @@ -7,7 +7,7 @@ /// pending transactions over a certain age. module This::AccountStateMachine { - use Async::Actor::{self, epoch_time}; + use Async::Actor::{self, virtual_time}; use std::vector; const MAX: u64 = 43; @@ -48,7 +48,7 @@ module This::AccountStateMachine { // Do not initiate the transfer if there are not enough funds. assert!(this.value >= v, 1); let xfer_id = new_xfer_id(this); - vector::push_back(&mut this.pending, PendingTransfer{xfer_id, amount: v, initiated_at: epoch_time()}); + vector::push_back(&mut this.pending, PendingTransfer{xfer_id, amount: v, initiated_at: virtual_time()}); // Call into a special version of deposit which calls us back once done. send_xfer_deposit(dest, v, self(), xfer_id); } diff --git a/language/extensions/async/move-async-vm/Cargo.toml b/language/extensions/async/move-async-vm/Cargo.toml index 812745d9d4..998e73da46 100644 --- a/language/extensions/async/move-async-vm/Cargo.toml +++ b/language/extensions/async/move-async-vm/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Diem Association "] description = "Wrapper for the Move VM for the asynchronous execution flavor" repository = "https://github.com/diem/move" license = "Apache-2.0" -edition = "2018" +edition = "2021" publish = false [dependencies] @@ -14,15 +14,17 @@ better_any = "0.1.1" walkdir = "2.3.1" itertools = "0.10.0" smallvec = "1.6.1" -bcs = "0.1.2" sha3 = "0.9.1" move-command-line-common = { path = "../../../move-command-line-common" } move-core-types = { path = "../../../move-core/types" } move-compiler = { path = "../../../move-compiler" } move-vm-types = { path = "../../../move-vm/types" } move-vm-runtime = { path = "../../../move-vm/runtime", features = ["debugging"] } +move-vm-test-utils = { path = "../../../move-vm/test-utils" } move-binary-format = { path = "../../../move-binary-format" } +bcs.workspace = true + [dev-dependencies] datatest-stable = "0.1.1" move-prover-test-utils = { path = "../../../move-prover/test-utils" } diff --git a/language/extensions/async/move-async-vm/src/async_vm.rs b/language/extensions/async/move-async-vm/src/async_vm.rs index 6b6cce61fb..a09740767a 100644 --- a/language/extensions/async/move-async-vm/src/async_vm.rs +++ b/language/extensions/async/move-async-vm/src/async_vm.rs @@ -11,8 +11,7 @@ use std::{ use move_binary_format::errors::{Location, PartialVMError, PartialVMResult, VMError, VMResult}; use move_core_types::{ account_address::AccountAddress, - effects::{ChangeSet, Event}, - gas_schedule::GasAlgebra, + effects::{ChangeSet, Event, Op}, identifier::Identifier, language_storage::{ModuleId, StructTag, TypeTag}, resolver::MoveResolver, @@ -24,13 +23,16 @@ use move_vm_runtime::{ native_functions::NativeFunction, session::{SerializedReturnValues, Session}, }; -use move_vm_types::{ - gas_schedule::GasStatus, - values::{Reference, Value}, +use move_vm_test_utils::gas_schedule::{Gas, GasStatus}; +use move_vm_types::values::{Reference, Value}; + +use crate::{ + actor_metadata, + actor_metadata::ActorMetadata, + natives, + natives::{AsyncExtension, GasParameters as ActorGasParameters}, }; -use crate::{actor_metadata, actor_metadata::ActorMetadata, natives, natives::AsyncExtension}; - /// Represents an instance of an async VM. pub struct AsyncVM { move_vm: MoveVM, @@ -40,7 +42,12 @@ pub struct AsyncVM { impl AsyncVM { /// Creates a new VM, registering the given natives and actors. - pub fn new(async_lib_addr: AccountAddress, natives: I, actors: A) -> VMResult + pub fn new( + async_lib_addr: AccountAddress, + natives: I, + actors: A, + actor_gas_parameters: ActorGasParameters, + ) -> VMResult where I: IntoIterator, A: IntoIterator, @@ -62,9 +69,9 @@ impl AsyncVM { .collect(); Ok(AsyncVM { move_vm: MoveVM::new( - natives - .into_iter() - .chain(natives::actor_natives(async_lib_addr).into_iter()), + natives.into_iter().chain( + natives::actor_natives(async_lib_addr, actor_gas_parameters).into_iter(), + ), )?, actor_metadata, message_table, @@ -138,7 +145,7 @@ pub struct AsyncSuccess<'r> { pub change_set: ChangeSet, pub events: Vec, pub messages: Vec, - pub gas_used: u64, + pub gas_used: Gas, pub ext: NativeContextExtensions<'r>, } @@ -146,7 +153,7 @@ pub struct AsyncSuccess<'r> { #[derive(Debug, Clone)] pub struct AsyncError { pub error: VMError, - pub gas_used: u64, + pub gas_used: Gas, } /// Result type for operations of an AsyncSession. @@ -172,7 +179,7 @@ impl<'r, 'l, S: MoveResolver> AsyncSession<'r, 'l, S> { .actor_metadata .get(module_id) .ok_or_else(|| async_extension_error(format!("actor `{}` unknown", module_id)))?; - let state_type_tag = TypeTag::Struct(actor.state_tag.clone()); + let state_type_tag = TypeTag::Struct(Box::new(actor.state_tag.clone())); let state_type = self .vm_session .load_type(&state_type_tag) @@ -183,6 +190,7 @@ impl<'r, 'l, S: MoveResolver> AsyncSession<'r, 'l, S> { .vm_session .get_data_store() .load_resource(actor_addr, &state_type) + .map(|(gv, _)| gv) .map_err(partial_vm_error_to_async)?; if state.exists().map_err(partial_vm_error_to_async)? { return Err(async_extension_error(format!( @@ -193,7 +201,7 @@ impl<'r, 'l, S: MoveResolver> AsyncSession<'r, 'l, S> { } // Execute the initializer. - let gas_before = gas_status.remaining_gas().get(); + let gas_before = gas_status.remaining_gas(); let result = self .vm_session .execute_function_bypass_visibility( @@ -204,7 +212,7 @@ impl<'r, 'l, S: MoveResolver> AsyncSession<'r, 'l, S> { gas_status, ) .and_then(|ret| Ok((ret, self.vm_session.finish_with_extensions()?))); - let gas_used = gas_status.remaining_gas().get() - gas_before; + let gas_used = gas_before.checked_sub(gas_status.remaining_gas()).unwrap(); // Process the result, moving the return value of the initializer function into the // changeset. @@ -227,6 +235,7 @@ impl<'r, 'l, S: MoveResolver> AsyncSession<'r, 'l, S> { actor_addr, actor.state_tag.clone(), return_values.remove(0).0, + false, ) .map_err(partial_vm_error_to_async)?; let async_ext = native_extensions.remove::(); @@ -266,7 +275,7 @@ impl<'r, 'l, S: MoveResolver> AsyncSession<'r, 'l, S> { })?; // Load the resource representing the actor state and add to arguments. - let state_type_tag = TypeTag::Struct(actor.state_tag.clone()); + let state_type_tag = TypeTag::Struct(Box::new(actor.state_tag.clone())); let state_type = self .vm_session .load_type(&state_type_tag) @@ -276,6 +285,7 @@ impl<'r, 'l, S: MoveResolver> AsyncSession<'r, 'l, S> { .vm_session .get_data_store() .load_resource(actor_addr, &state_type) + .map(|(gv, _)| gv) .map_err(partial_vm_error_to_async)?; let actor_state = actor_state_global .borrow_global() @@ -289,13 +299,13 @@ impl<'r, 'l, S: MoveResolver> AsyncSession<'r, 'l, S> { ); // Execute the handler. - let gas_before = gas_status.remaining_gas().get(); + let gas_before = gas_status.remaining_gas(); let result = self .vm_session .execute_function_bypass_visibility(module_id, handler_id, vec![], args, gas_status) .and_then(|ret| Ok((ret, self.vm_session.finish_with_extensions()?))); - let gas_used = gas_status.remaining_gas().get() - gas_before; + let gas_used = gas_before.checked_sub(gas_status.remaining_gas()).unwrap(); // Process the result, moving the mutated value of the handlers first parameter // into the changeset. @@ -319,6 +329,7 @@ impl<'r, 'l, S: MoveResolver> AsyncSession<'r, 'l, S> { actor_addr, actor.state_tag.clone(), mutable_reference_outputs.remove(0).1, + true, ) .map_err(partial_vm_error_to_async)?; } @@ -367,9 +378,18 @@ fn publish_actor_state( actor_addr: AccountAddress, state_tag: StructTag, state: Vec, + is_modify: bool, ) -> PartialVMResult<()> { change_set - .publish_resource(actor_addr, state_tag, state) + .add_resource_op( + actor_addr, + state_tag, + if is_modify { + Op::Modify(state) + } else { + Op::New(state) + }, + ) .map_err(|err| partial_extension_error(format!("cannot publish actor state: {}", err))) } @@ -384,12 +404,15 @@ pub(crate) fn extension_error(msg: impl ToString) -> VMError { fn async_extension_error(msg: impl ToString) -> AsyncError { AsyncError { error: extension_error(msg), - gas_used: 0, + gas_used: 0.into(), } } fn vm_error_to_async(error: VMError) -> AsyncError { - AsyncError { error, gas_used: 0 } + AsyncError { + error, + gas_used: 0.into(), + } } fn partial_vm_error_to_async(error: PartialVMError) -> AsyncError { diff --git a/language/extensions/async/move-async-vm/src/natives.rs b/language/extensions/async/move-async-vm/src/natives.rs index 5b78f372f4..a9a9f4f967 100644 --- a/language/extensions/async/move-async-vm/src/natives.rs +++ b/language/extensions/async/move-async-vm/src/natives.rs @@ -5,26 +5,23 @@ use crate::async_vm::Message; use better_any::{Tid, TidAble}; use move_binary_format::errors::PartialVMResult; -use move_core_types::{account_address::AccountAddress, identifier::Identifier}; +use move_core_types::{ + account_address::AccountAddress, + gas_algebra::{InternalGas, InternalGasPerByte, NumBytes}, + identifier::Identifier, +}; use move_vm_runtime::{ native_functions, native_functions::{NativeContext, NativeFunction}, }; use move_vm_types::{ - gas_schedule::NativeCostIndex, loaded_data::runtime_types::Type, - natives::function::{native_gas, NativeResult}, + natives::function::NativeResult, pop_arg, values::{Value, Vector}, }; use smallvec::smallvec; -use std::collections::VecDeque; - -// TODO: make cost tables extensible; right now we forward to one of the predefined cost indices -// as an approximation. -const SELF_COST_INDEX: NativeCostIndex = NativeCostIndex::LENGTH; -const SEND_COST_INDEX: NativeCostIndex = NativeCostIndex::EMIT_EVENT; -const EPOCH_TIME_INDEX: NativeCostIndex = NativeCostIndex::LENGTH; +use std::{collections::VecDeque, sync::Arc}; /// Environment extension for the Move VM which we pass down to native functions, /// to implement message sending and retrieval of actor address. @@ -36,39 +33,116 @@ pub struct AsyncExtension { pub in_initializer: bool, } +#[derive(Clone, Debug)] +pub struct GasParameters { + pub self_: SelfGasParameters, + pub send: SendGasParameters, + pub virtual_time: VirtualTimeGasParameters, +} + +impl GasParameters { + pub fn zeros() -> Self { + Self { + self_: SelfGasParameters { + base_cost: 0.into(), + }, + send: SendGasParameters { + base_cost: 0.into(), + unit_cost: 0.into(), + }, + virtual_time: VirtualTimeGasParameters { + base_cost: 0.into(), + }, + } + } +} + pub fn actor_natives( async_addr: AccountAddress, + gas_params: GasParameters, ) -> Vec<(AccountAddress, Identifier, Identifier, NativeFunction)> { - const NATIVES: &[(&str, &str, NativeFunction)] = &[ - ("Actor", "self", native_self), - ("Actor", "virtual_time", native_virtual_time), - ("Runtime", "send__0", native_send), - ("Runtime", "send__1", native_send), - ("Runtime", "send__2", native_send), - ("Runtime", "send__3", native_send), - ("Runtime", "send__4", native_send), - ("Runtime", "send__5", native_send), - ("Runtime", "send__6", native_send), - ("Runtime", "send__7", native_send), - ("Runtime", "send__8", native_send), + let natives = [ + ("Actor", "self", make_native_self(gas_params.self_)), + ( + "Actor", + "virtual_time", + make_native_virtual_time(gas_params.virtual_time), + ), + ( + "Runtime", + "send__0", + make_native_send(gas_params.send.clone()), + ), + ( + "Runtime", + "send__1", + make_native_send(gas_params.send.clone()), + ), + ( + "Runtime", + "send__2", + make_native_send(gas_params.send.clone()), + ), + ( + "Runtime", + "send__3", + make_native_send(gas_params.send.clone()), + ), + ( + "Runtime", + "send__4", + make_native_send(gas_params.send.clone()), + ), + ( + "Runtime", + "send__5", + make_native_send(gas_params.send.clone()), + ), + ( + "Runtime", + "send__6", + make_native_send(gas_params.send.clone()), + ), + ( + "Runtime", + "send__7", + make_native_send(gas_params.send.clone()), + ), + ("Runtime", "send__8", make_native_send(gas_params.send)), ]; - native_functions::make_table(async_addr, NATIVES) + native_functions::make_table_from_iter(async_addr, natives) +} + +#[derive(Clone, Debug)] +pub struct SelfGasParameters { + base_cost: InternalGas, } fn native_self( + gas_params: &SelfGasParameters, context: &mut NativeContext, mut _ty_args: Vec, mut _args: VecDeque, ) -> PartialVMResult { - let cost = native_gas(context.cost_table(), SELF_COST_INDEX, 1); let ext = context.extensions().get::(); Ok(NativeResult::ok( - cost, + gas_params.base_cost, smallvec![Value::address(ext.current_actor)], )) } +fn make_native_self(gas_params: SelfGasParameters) -> NativeFunction { + Arc::new(move |context, ty_args, args| native_self(&gas_params, context, ty_args, args)) +} + +#[derive(Clone, Debug)] +pub struct SendGasParameters { + base_cost: InternalGas, + unit_cost: InternalGasPerByte, +} + fn native_send( + gas_params: &SendGasParameters, context: &mut NativeContext, mut _ty_args: Vec, mut args: VecDeque, @@ -82,19 +156,34 @@ fn native_send( let message_hash = pop_arg!(args, u64); let target = pop_arg!(args, AccountAddress); ext.sent.push((target, message_hash, bcs_args)); - let cost = native_gas(context.cost_table(), SEND_COST_INDEX, args.len()); + + let cost = gas_params.base_cost + gas_params.unit_cost * NumBytes::new(args.len() as u64); + Ok(NativeResult::ok(cost, smallvec![])) } +fn make_native_send(gas_params: SendGasParameters) -> NativeFunction { + Arc::new(move |context, ty_args, args| native_send(&gas_params, context, ty_args, args)) +} + +#[derive(Clone, Debug)] +pub struct VirtualTimeGasParameters { + base_cost: InternalGas, +} + fn native_virtual_time( + gas_params: &VirtualTimeGasParameters, context: &mut NativeContext, mut _ty_args: Vec, mut _args: VecDeque, ) -> PartialVMResult { - let cost = native_gas(context.cost_table(), EPOCH_TIME_INDEX, 1); let ext = context.extensions().get::(); Ok(NativeResult::ok( - cost, + gas_params.base_cost, smallvec![Value::u128(ext.virtual_time)], )) } + +fn make_native_virtual_time(gas_params: VirtualTimeGasParameters) -> NativeFunction { + Arc::new(move |context, ty_args, args| native_virtual_time(&gas_params, context, ty_args, args)) +} diff --git a/language/extensions/async/move-async-vm/tests/sources/AccountStateMachine.exp b/language/extensions/async/move-async-vm/tests/sources/AccountStateMachine.exp index da5160c13f..aa288bfed9 100644 --- a/language/extensions/async/move-async-vm/tests/sources/AccountStateMachine.exp +++ b/language/extensions/async/move-async-vm/tests/sources/AccountStateMachine.exp @@ -5,10 +5,10 @@ publishing vector publishing AccountStateMachine actor 0x4 created from 0x3::AccountStateMachine SUCCESS - commit 0x3::AccountStateMachine::AccountStateMachine[0x4] := [00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00] + commit 0x3::AccountStateMachine::AccountStateMachine[0x4] := New("[00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00]") actor 0x5 created from 0x3::AccountStateMachine SUCCESS - commit 0x3::AccountStateMachine::AccountStateMachine[0x5] := [00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00] + commit 0x3::AccountStateMachine::AccountStateMachine[0x5] := New("[00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00]") actor 0x4 handling 0x3::AccountStateMachine::start (hash=0x5438F379BC9E3BCB) SUCCESS sent 0x4 <- 0x4C40DD3C3521A146 argc=1 @@ -20,28 +20,28 @@ actor 0x5 handling 0x3::AccountStateMachine::start (hash=0x5438F379BC9E3BCB) SUCCESS actor 0x4 handling 0x3::AccountStateMachine::deposit (hash=0x4C40DD3C3521A146) SUCCESS - commit 0x3::AccountStateMachine::AccountStateMachine[0x4] := [64, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00] + commit 0x3::AccountStateMachine::AccountStateMachine[0x4] := Modify("[64, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00]") actor 0x5 handling 0x3::AccountStateMachine::deposit (hash=0x4C40DD3C3521A146) SUCCESS - commit 0x3::AccountStateMachine::AccountStateMachine[0x5] := [64, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00] + commit 0x3::AccountStateMachine::AccountStateMachine[0x5] := Modify("[64, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00]") actor 0x4 handling 0x3::AccountStateMachine::xfer (hash=0xF8ECAD16D8E182BB) SUCCESS sent 0x5 <- 0xB32E0FAF108F638 argc=3 - commit 0x3::AccountStateMachine::AccountStateMachine[0x4] := [64, 00, 00, 00, 00, 00, 00, 00, 01, 00, 00, 00, 00, 00, 00, 00, 01, 00, 00, 00, 00, 00, 00, 00, 00, 14, 00, 00, 00, 00, 00, 00, 00, A0, 69, 62, 02, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00] + commit 0x3::AccountStateMachine::AccountStateMachine[0x4] := Modify("[64, 00, 00, 00, 00, 00, 00, 00, 01, 00, 00, 00, 00, 00, 00, 00, 01, 00, 00, 00, 00, 00, 00, 00, 00, 14, 00, 00, 00, 00, 00, 00, 00, A0, 69, 62, 02, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00]") actor 0x4 handling 0x3::AccountStateMachine::cleanup (hash=0xDD840198DA7DE13E) SUCCESS - commit 0x3::AccountStateMachine::AccountStateMachine[0x4] := [64, 00, 00, 00, 00, 00, 00, 00, 01, 00, 00, 00, 00, 00, 00, 00, 01, 00, 00, 00, 00, 00, 00, 00, 00, 14, 00, 00, 00, 00, 00, 00, 00, A0, 69, 62, 02, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00] + commit 0x3::AccountStateMachine::AccountStateMachine[0x4] := Modify("[64, 00, 00, 00, 00, 00, 00, 00, 01, 00, 00, 00, 00, 00, 00, 00, 01, 00, 00, 00, 00, 00, 00, 00, 00, 14, 00, 00, 00, 00, 00, 00, 00, A0, 69, 62, 02, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00]") actor 0x5 handling 0x3::AccountStateMachine::cleanup (hash=0xDD840198DA7DE13E) SUCCESS - commit 0x3::AccountStateMachine::AccountStateMachine[0x5] := [64, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00] + commit 0x3::AccountStateMachine::AccountStateMachine[0x5] := Modify("[64, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00]") actor 0x5 handling 0x3::AccountStateMachine::xfer_deposit (hash=0xB32E0FAF108F638) SUCCESS sent 0x4 <- 0xB8229D65C5B58BBA argc=1 - commit 0x3::AccountStateMachine::AccountStateMachine[0x5] := [78, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00] + commit 0x3::AccountStateMachine::AccountStateMachine[0x5] := Modify("[78, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00]") actor 0x4 handling 0x3::AccountStateMachine::xfer_finish (hash=0xB8229D65C5B58BBA) SUCCESS sent 0x4 <- 0x22801C54EE790BE3 argc=0 - commit 0x3::AccountStateMachine::AccountStateMachine[0x4] := [50, 00, 00, 00, 00, 00, 00, 00, 01, 00, 00, 00, 00, 00, 00, 00, 00] + commit 0x3::AccountStateMachine::AccountStateMachine[0x4] := Modify("[50, 00, 00, 00, 00, 00, 00, 00, 01, 00, 00, 00, 00, 00, 00, 00, 00]") actor 0x4 handling 0x3::AccountStateMachine::end (hash=0x22801C54EE790BE3) SUCCESS sent 0x4 <- 0x3450A8717C6383FF argc=1 @@ -52,4 +52,4 @@ actor 0x4 handling 0x3::AccountStateMachine::verify (hash=0x3450A8717C6383FF) actor 0x5 handling 0x3::AccountStateMachine::verify (hash=0x3450A8717C6383FF) SUCCESS actor 0x5 handling 0x3::AccountStateMachine::verify (hash=0x3450A8717C6383FF) - FAIL VMError with status ABORTED with sub status 2 at location Module ModuleId { address: 00000000000000000000000000000003, name: Identifier("AccountStateMachine") } and message 0x00000000000000000000000000000003::AccountStateMachine::verify at offset 9 at code offset 9 in function definition 16 + FAIL VMError with status ABORTED with sub status 2 at location Module ModuleId { address: 00000000000000000000000000000003, name: Identifier("AccountStateMachine") } and message 0x00000000000000000000000000000003::AccountStateMachine::verify at offset 8 at code offset 8 in function definition 16 diff --git a/language/extensions/async/move-async-vm/tests/sources/Basic.exp b/language/extensions/async/move-async-vm/tests/sources/Basic.exp index f0b1741af0..fc83136899 100644 --- a/language/extensions/async/move-async-vm/tests/sources/Basic.exp +++ b/language/extensions/async/move-async-vm/tests/sources/Basic.exp @@ -3,30 +3,30 @@ publishing bcs publishing Basic actor 0x4 created from 0x3::Basic SUCCESS - commit 0x3::Basic::Basic[0x4] := [00, 00, 00, 00, 00, 00, 00, 00] + commit 0x3::Basic::Basic[0x4] := New("[00, 00, 00, 00, 00, 00, 00, 00]") actor 0x4 handling 0x3::Basic::start (hash=0xA9C2CD33311F2015) SUCCESS sent 0x4 <- 0x45F84510862E6905 argc=1 actor 0x4 handling 0x3::Basic::count_down (hash=0x45F84510862E6905) SUCCESS sent 0x4 <- 0x45F84510862E6905 argc=1 - commit 0x3::Basic::Basic[0x4] := [01, 00, 00, 00, 00, 00, 00, 00] + commit 0x3::Basic::Basic[0x4] := Modify("[01, 00, 00, 00, 00, 00, 00, 00]") actor 0x4 handling 0x3::Basic::count_down (hash=0x45F84510862E6905) SUCCESS sent 0x4 <- 0x45F84510862E6905 argc=1 - commit 0x3::Basic::Basic[0x4] := [02, 00, 00, 00, 00, 00, 00, 00] + commit 0x3::Basic::Basic[0x4] := Modify("[02, 00, 00, 00, 00, 00, 00, 00]") actor 0x4 handling 0x3::Basic::count_down (hash=0x45F84510862E6905) SUCCESS sent 0x4 <- 0x45F84510862E6905 argc=1 - commit 0x3::Basic::Basic[0x4] := [03, 00, 00, 00, 00, 00, 00, 00] + commit 0x3::Basic::Basic[0x4] := Modify("[03, 00, 00, 00, 00, 00, 00, 00]") actor 0x4 handling 0x3::Basic::count_down (hash=0x45F84510862E6905) SUCCESS sent 0x4 <- 0x45F84510862E6905 argc=1 - commit 0x3::Basic::Basic[0x4] := [04, 00, 00, 00, 00, 00, 00, 00] + commit 0x3::Basic::Basic[0x4] := Modify("[04, 00, 00, 00, 00, 00, 00, 00]") actor 0x4 handling 0x3::Basic::count_down (hash=0x45F84510862E6905) SUCCESS sent 0x4 <- 0x45F84510862E6905 argc=1 - commit 0x3::Basic::Basic[0x4] := [05, 00, 00, 00, 00, 00, 00, 00] + commit 0x3::Basic::Basic[0x4] := Modify("[05, 00, 00, 00, 00, 00, 00, 00]") actor 0x4 handling 0x3::Basic::count_down (hash=0x45F84510862E6905) SUCCESS - commit 0x3::Basic::Basic[0x4] := [05, 00, 00, 00, 00, 00, 00, 00] + commit 0x3::Basic::Basic[0x4] := Modify("[05, 00, 00, 00, 00, 00, 00, 00]") diff --git a/language/extensions/async/move-async-vm/tests/testsuite.rs b/language/extensions/async/move-async-vm/tests/testsuite.rs index f986693e25..a5fbc03a53 100644 --- a/language/extensions/async/move-async-vm/tests/testsuite.rs +++ b/language/extensions/async/move-async-vm/tests/testsuite.rs @@ -8,6 +8,7 @@ use move_async_vm::{ actor_metadata, actor_metadata::ActorMetadata, async_vm::{AsyncResult, AsyncSession, AsyncVM, Message}, + natives::GasParameters as ActorGasParameters, }; use move_binary_format::access::ModuleAccess; use move_command_line_common::testing::EXP_EXT; @@ -17,13 +18,13 @@ use move_compiler::{ }; use move_core_types::{ account_address::AccountAddress, - effects::ChangeSet, + effects::{ChangeSet, Op}, identifier::{IdentStr, Identifier}, language_storage::{ModuleId, StructTag}, resolver::{ModuleResolver, ResourceResolver}, }; use move_prover_test_utils::{baseline_test::verify_or_update_baseline, extract_test_directives}; -use move_vm_types::gas_schedule::GasStatus; +use move_vm_test_utils::gas_schedule::GasStatus; use std::{ cell::RefCell, collections::{BTreeMap, BTreeSet, VecDeque}, @@ -182,25 +183,34 @@ impl Harness { fn commit_changeset(&self, changeset: ChangeSet) { for (addr, change) in changeset.into_inner() { - for (struct_tag, val) in change.into_inner().1 { + for (struct_tag, op) in change.into_inner().1 { self.log(format!( - " commit 0x{}::{}::{}[0x{}] := {}", + " commit 0x{}::{}::{}[0x{}] := {:?}", struct_tag.address.short_str_lossless(), struct_tag.module, struct_tag.module, addr.short_str_lossless(), - val.as_ref() - .map(|b| format!("{:02X?}", b)) - .unwrap_or_else(|| "None".to_string()) + op.as_ref().map(|b| format!("{:02X?}", b)) )); - match val { - Some(v) => { + match op { + Op::New(v) => { + assert!(self + .resource_store + .borrow_mut() + .insert((addr, struct_tag), v) + .is_none()); + } + Op::Modify(v) => { self.resource_store .borrow_mut() - .insert((addr, struct_tag), v); + .insert((addr, struct_tag), v) + .unwrap(); } - None => { - self.resource_store.borrow_mut().remove(&(addr, struct_tag)); + Op::Delete => { + self.resource_store + .borrow_mut() + .remove(&(addr, struct_tag)) + .unwrap(); } } } @@ -237,8 +247,14 @@ impl Harness { resource_store: Default::default(), vm: AsyncVM::new( test_account(), - move_stdlib::natives::all_natives(test_account()), + move_stdlib::natives::all_natives( + test_account(), + // We may want to switch to a different gas schedule in the future, but for now, + // the all-zero one should be enough. + move_stdlib::natives::GasParameters::zeros(), + ), actor_metadata, + ActorGasParameters::zeros(), )?, actor_instances, }; diff --git a/language/extensions/move-table-extension/Cargo.toml b/language/extensions/move-table-extension/Cargo.toml index 36e01fd7ab..1dc6384986 100644 --- a/language/extensions/move-table-extension/Cargo.toml +++ b/language/extensions/move-table-extension/Cargo.toml @@ -5,14 +5,13 @@ authors = ["Diem Association "] description = "Wrapper for the Move VM which coordinates multiple extensions" repository = "https://github.com/diem/move" license = "Apache-2.0" -edition = "2018" +edition = "2021" publish = false [dependencies] anyhow = "1.0.52" better_any = "0.1.1" smallvec = "1.6.1" -bcs = "0.1.2" sha3 = "0.9.1" once_cell = "1.7.2" move-core-types = { path = "../../move-core/types" } @@ -20,6 +19,8 @@ move-vm-types = { path = "../../move-vm/types" } move-vm-runtime = { path = "../../move-vm/runtime", features = ["debugging"] } move-binary-format = { path = "../../move-binary-format" } +bcs.workspace = true + [dev-dependencies] move-stdlib = { path = "../../move-stdlib", features = ["testing"] } move-unit-test = { path = "../../tools/move-unit-test", features = ["table-extension"] } diff --git a/language/extensions/move-table-extension/Move.toml b/language/extensions/move-table-extension/Move.toml index 6c2aa20b6e..d44e94143a 100644 --- a/language/extensions/move-table-extension/Move.toml +++ b/language/extensions/move-table-extension/Move.toml @@ -3,12 +3,11 @@ name = "MoveTableExtension" version = "1.0.0" [addresses] -std = "_" -Extensions = "_" +extensions = "_" [dev-addresses] std = "0x1" -Extensions = "0x2" +extensions = "0x2" [dependencies] MoveStdlib = { local = "../../move-stdlib" } diff --git a/language/extensions/move-table-extension/README.md b/language/extensions/move-table-extension/README.md index 36280c0971..cda2f1bd87 100644 --- a/language/extensions/move-table-extension/README.md +++ b/language/extensions/move-table-extension/README.md @@ -15,7 +15,7 @@ use move_vm_runtime::native_functions::NativeContextExtensions; fn run() { let resource_resolver = unimplemented!(); // a resource resolver the adapter provides let txn_hash = unimplemented!(); // a unique hash for table creation for this transaction - let table_resolver = unimplemented!(); // a remote table resover the adapter provides + let table_resolver = unimplemented!(); // a remote table resolver the adapter provides let std_addr = unimplemented!(); // address where to deploy the std lib let extension_addr = unimplemented!(); // address where to deploy the table extension diff --git a/language/extensions/move-table-extension/sources/Table.move b/language/extensions/move-table-extension/sources/Table.move index fe8bc180f2..8241264370 100644 --- a/language/extensions/move-table-extension/sources/Table.move +++ b/language/extensions/move-table-extension/sources/Table.move @@ -1,5 +1,5 @@ /// Type of large-scale storage tables. -module Extensions::Table { +module extensions::table { use std::errors; // TODO: native code should not use reasons to signal logical type of error. Instead, @@ -11,14 +11,14 @@ module Extensions::Table { /// Type of tables struct Table has store { - handle: u128, + handle: address, length: u64, } /// Create a new Table. public fun new(): Table { Table{ - handle: new_table_handle(), + handle: new_table_handle(), length: 0, } } @@ -98,7 +98,7 @@ module Extensions::Table { // Primitives which take as an additional type parameter `Box`, so the implementation // can use this to determine serialization layout. - native fun new_table_handle(): u128; + native fun new_table_handle(): address; native fun add_box(table: &mut Table, key: K, val: Box); native fun borrow_box(table: &Table, key: K): &Box; native fun borrow_box_mut(table: &mut Table, key: K): &mut Box; diff --git a/language/extensions/move-table-extension/sources/Table.spec.move b/language/extensions/move-table-extension/sources/Table.spec.move index 645ba5a284..bfdd72f2cb 100644 --- a/language/extensions/move-table-extension/sources/Table.spec.move +++ b/language/extensions/move-table-extension/sources/Table.spec.move @@ -1,54 +1,31 @@ /// Specifications of the `Table` module. -spec Extensions::Table { +spec extensions::table { // Make most of the public API intrinsic. Those functions have custom specifications in the prover. spec Table { - pragma intrinsic; - } - - spec new { - pragma intrinsic; - } - - spec destroy_empty { - pragma intrinsic; - } - - spec add { - pragma intrinsic; - } - - spec borrow { - pragma intrinsic; - } - - spec borrow_mut { - pragma intrinsic; - } - - spec length { - pragma intrinsic; - } - - spec empty { - pragma intrinsic; - } - - spec remove { - pragma intrinsic; - } - - spec contains { - pragma intrinsic; + pragma intrinsic = map, + map_new = new, + map_destroy_empty = destroy_empty, + map_len = length, + map_is_empty = empty, + map_has_key = contains, + map_add_no_override = add, + map_del_must_exist = remove, + map_borrow = borrow, + map_borrow_mut = borrow_mut, + map_spec_get = spec_get, + map_spec_set = spec_set, + map_spec_del = spec_remove, + map_spec_len = spec_len, + map_spec_has_key = spec_contains; } // Specification functions for tables - spec native fun spec_table(): Table; spec native fun spec_len(t: Table): num; spec native fun spec_contains(t: Table, k: K): bool; - spec native fun spec_add(t: Table, k: K, v: V): Table; + spec native fun spec_set(t: Table, k: K, v: V): Table; spec native fun spec_remove(t: Table, k: K): Table; spec native fun spec_get(t: Table, k: K): V; } diff --git a/language/extensions/move-table-extension/src/lib.rs b/language/extensions/move-table-extension/src/lib.rs index 42c5c189ee..7a2b6fc5ac 100644 --- a/language/extensions/move-table-extension/src/lib.rs +++ b/language/extensions/move-table-extension/src/lib.rs @@ -11,27 +11,29 @@ use better_any::{Tid, TidAble}; use move_binary_format::errors::{PartialVMError, PartialVMResult}; use move_core_types::{ account_address::AccountAddress, - gas_schedule::{GasAlgebra, GasCarrier, InternalGasUnits}, + effects::Op, + gas_algebra::{InternalGas, InternalGasPerByte, NumBytes}, + language_storage::TypeTag, value::MoveTypeLayout, vm_status::StatusCode, }; use move_vm_runtime::{ native_functions, - native_functions::{NativeContext, NativeFunctionTable}, + native_functions::{NativeContext, NativeFunction, NativeFunctionTable}, }; use move_vm_types::{ loaded_data::runtime_types::Type, natives::function::NativeResult, pop_arg, - values::{GlobalValue, GlobalValueEffect, Reference, StructRef, Value}, + values::{GlobalValue, Reference, StructRef, Value}, }; use sha3::{Digest, Sha3_256}; use smallvec::smallvec; use std::{ cell::RefCell, collections::{btree_map::Entry, BTreeMap, BTreeSet, VecDeque}, - convert::TryInto, fmt::Display, + sync::Arc, }; // =========================================================================================== @@ -41,7 +43,7 @@ use std::{ /// hash over a transaction hash provided by the environment and a table creation counter /// local to the transaction. #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)] -pub struct TableHandle(pub u128); +pub struct TableHandle(pub AccountAddress); impl Display for TableHandle { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -49,17 +51,38 @@ impl Display for TableHandle { } } +#[derive(Clone, Debug)] +pub struct TableInfo { + pub key_type: TypeTag, + pub value_type: TypeTag, +} + +impl TableInfo { + pub fn new(key_type: TypeTag, value_type: TypeTag) -> Self { + Self { + key_type, + value_type, + } + } +} + +impl Display for TableInfo { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "Table<{}, {}>", self.key_type, self.value_type) + } +} + /// A table change set. #[derive(Default)] pub struct TableChangeSet { - pub new_tables: BTreeSet, + pub new_tables: BTreeMap, pub removed_tables: BTreeSet, pub changes: BTreeMap, } /// A change of a single table. pub struct TableChange { - pub entries: BTreeMap, Option>>, + pub entries: BTreeMap, Op>>, } /// A table resolver which needs to be provided by the environment. This allows to lookup @@ -70,24 +93,6 @@ pub trait TableResolver { handle: &TableHandle, key: &[u8], ) -> Result>, anyhow::Error>; - - fn operation_cost( - &self, - op: TableOperation, - key_size: usize, - val_size: usize, - ) -> InternalGasUnits; -} - -/// A table operation, for supporting cost calculation. -pub enum TableOperation { - NewHandle, - Destroy, - Insert, - Borrow, - Length, - Remove, - Contains, } /// The native table context extension. This needs to be attached to the NativeContextExtensions @@ -96,7 +101,7 @@ pub enum TableOperation { #[derive(Tid)] pub struct NativeTableContext<'a> { resolver: &'a dyn TableResolver, - txn_hash: u128, + txn_hash: [u8; 32], table_data: RefCell, } @@ -116,7 +121,7 @@ const _NOT_EMPTY: u64 = (102 << 8) + _ECATEGORY_INVALID_STATE as u64; /// of the overall context so we can mutate while still accessing the overall context. #[derive(Default)] struct TableData { - new_tables: BTreeSet, + new_tables: BTreeMap, removed_tables: BTreeSet, tables: BTreeMap, } @@ -138,7 +143,7 @@ const HANDLE_FIELD_INDEX: usize = 0; impl<'a> NativeTableContext<'a> { /// Create a new instance of a native table context. This must be passed in via an /// extension into VM session functions. - pub fn new(txn_hash: u128, resolver: &'a dyn TableResolver) -> Self { + pub fn new(txn_hash: [u8; 32], resolver: &'a dyn TableResolver) -> Self { Self { resolver, txn_hash, @@ -163,15 +168,23 @@ impl<'a> NativeTableContext<'a> { } = table; let mut entries = BTreeMap::new(); for (key, gv) in content { - match gv.into_effect()? { - GlobalValueEffect::Deleted => { - entries.insert(key, None); + let op = match gv.into_effect() { + Some(op) => op, + None => continue, + }; + + match op { + Op::New(val) => { + let bytes = serialize(&value_layout, &val)?; + entries.insert(key, Op::New(bytes)); + } + Op::Modify(val) => { + let bytes = serialize(&value_layout, &val)?; + entries.insert(key, Op::Modify(bytes)); } - GlobalValueEffect::Changed(new_val) => { - let new_bytes = serialize(&value_layout, &new_val)?; - entries.insert(key, Some(new_bytes)); + Op::Delete => { + entries.insert(key, Op::Delete); } - _ => {} } } if !entries.is_empty() { @@ -196,173 +209,179 @@ impl TableData { key_ty: &Type, value_ty: &Type, ) -> PartialVMResult<&mut Table> { - if let Entry::Vacant(e) = self.tables.entry(handle) { - let key_layout = get_type_layout(context, key_ty)?; - let value_layout = get_type_layout(context, value_ty)?; - let table = Table { - handle, - key_layout, - value_layout, - content: Default::default(), - }; - e.insert(table); - } - Ok(self.tables.get_mut(&handle).unwrap()) + Ok(match self.tables.entry(handle) { + Entry::Vacant(e) => { + let key_layout = get_type_layout(context, key_ty)?; + let value_layout = get_type_layout(context, value_ty)?; + let table = Table { + handle, + key_layout, + value_layout, + content: Default::default(), + }; + e.insert(table) + } + Entry::Occupied(e) => e.into_mut(), + }) } } impl Table { - /// Inserts a value into a table. - fn insert( + fn get_or_create_global_value( &mut self, context: &NativeTableContext, - key: &Value, - val: Value, - ) -> PartialVMResult<(usize, usize)> { - let (gv_opt, _, _) = self.global_value_if_exists(context, key)?; - if gv_opt.is_some() { - return Err(partial_abort_error( - "table entry already occupied", - ALREADY_EXISTS, - )); - } - let key_bytes = serialize(&self.key_layout, key)?; - let key_size = key_bytes.len(); - // Need to serialize for cost computation - let val_size = serialize(&self.value_layout, &val)?.len(); - self.content - .entry(key_bytes) - .or_insert_with(GlobalValue::none) - .move_to(val)?; - Ok((key_size, val_size)) - } - - /// Borrows a reference to a table (mutable or immutable). - fn borrow_global( - &mut self, - context: &NativeTableContext, - key: &Value, - ) -> PartialVMResult<(Value, usize, usize)> { - let (gv_opt, key_size, val_size) = self.global_value_if_exists(context, key)?; - let gv = gv_opt.ok_or_else(|| partial_abort_error("undefined table entry", NOT_FOUND))?; - let val = gv.borrow_global()?; - Ok((val, key_size, val_size)) - } - - /// Removes an entry from a table. - fn remove( - &mut self, - context: &NativeTableContext, - key: &Value, - ) -> PartialVMResult<(Value, usize, usize)> { - let (gv_opt, key_size, val_size) = self.global_value_if_exists(context, key)?; - let gv = gv_opt.ok_or_else(|| partial_abort_error("undefined table entry", NOT_FOUND))?; - let val = gv.move_from()?; - Ok((val, key_size, val_size)) + key: Vec, + ) -> PartialVMResult<(&mut GlobalValue, Option>)> { + Ok(match self.content.entry(key) { + Entry::Vacant(entry) => { + let (gv, loaded) = match context + .resolver + .resolve_table_entry(&self.handle, entry.key()) + .map_err(|err| { + partial_extension_error(format!("remote table resolver failure: {}", err)) + })? { + Some(val_bytes) => { + let val = deserialize(&self.value_layout, &val_bytes)?; + ( + GlobalValue::cached(val)?, + Some(NumBytes::new(val_bytes.len() as u64)), + ) + } + None => (GlobalValue::none(), None), + }; + (entry.insert(gv), Some(loaded)) + } + Entry::Occupied(entry) => (entry.into_mut(), None), + }) } +} - /// Checks whether a key is in the table. - fn contains( - &mut self, - context: &NativeTableContext, - key: &Value, - ) -> PartialVMResult<(Value, usize, usize)> { - let (gv_opt, key_size, val_size) = self.global_value_if_exists(context, key)?; - Ok((Value::bool(gv_opt.is_some()), key_size, val_size)) - } +// ========================================================================================= +// Native Function Implementations - /// Destroys a table. - fn destroy_empty(&mut self, _context: &NativeTableContext) -> PartialVMResult<(usize, usize)> { - Ok((0, 0)) - } +/// Returns all natives for tables. +pub fn table_natives(table_addr: AccountAddress, gas_params: GasParameters) -> NativeFunctionTable { + let natives: [(&str, &str, NativeFunction); 8] = [ + ( + "table", + "new_table_handle", + make_native_new_table_handle(gas_params.new_table_handle), + ), + ( + "table", + "add_box", + make_native_add_box(gas_params.common.clone(), gas_params.add_box), + ), + ( + "table", + "borrow_box", + make_native_borrow_box(gas_params.common.clone(), gas_params.borrow_box.clone()), + ), + ( + "table", + "borrow_box_mut", + make_native_borrow_box(gas_params.common.clone(), gas_params.borrow_box), + ), + ( + "table", + "remove_box", + make_native_remove_box(gas_params.common.clone(), gas_params.remove_box), + ), + ( + "table", + "contains_box", + make_native_contains_box(gas_params.common, gas_params.contains_box), + ), + ( + "table", + "destroy_empty_box", + make_native_destroy_empty_box(gas_params.destroy_empty_box), + ), + ( + "table", + "drop_unchecked_box", + make_native_drop_unchecked_box(gas_params.drop_unchecked_box), + ), + ]; + + native_functions::make_table_from_iter(table_addr, natives) +} - /// Gets the global value of an entry in the table. Attempts to retrieve a value from - /// the resolver if needed. Aborts if the value does not exists. Also returns the size - /// of the key and value (if a value needs to be fetched from remote) for cost computation. - fn global_value_if_exists( - &mut self, - context: &NativeTableContext, - key: &Value, - ) -> PartialVMResult<(Option<&mut GlobalValue>, usize, usize)> { - let key_bytes = serialize(&self.key_layout, key)?; - let key_size = key_bytes.len(); - let mut val_size = 0; - if !self.content.contains_key(&key_bytes) { - // Try to retrieve a value from the remote resolver. - let gv = match context - .resolver - .resolve_table_entry(&self.handle, &key_bytes) - .map_err(|err| { - partial_extension_error(format!("remote table resolver failure: {}", err)) - })? { - Some(val_bytes) => { - val_size = val_bytes.len(); - let val = deserialize(&self.value_layout, &val_bytes)?; - GlobalValue::cached(val)? - } - None => GlobalValue::none(), - }; - self.content.insert(key_bytes.clone(), gv); - } +#[derive(Debug, Clone)] +pub struct CommonGasParameters { + pub load_base: InternalGas, + pub load_per_byte: InternalGasPerByte, + pub load_failure: InternalGas, +} - let gv = self.content.get_mut(&key_bytes).unwrap(); - if gv.exists()? { - Ok((Some(gv), key_size, val_size)) - } else { - Ok((None, key_size, val_size)) - } +impl CommonGasParameters { + fn calculate_load_cost(&self, loaded: Option>) -> InternalGas { + self.load_base + + match loaded { + Some(Some(num_bytes)) => self.load_per_byte * num_bytes, + Some(None) => self.load_failure, + None => 0.into(), + } } } -// ========================================================================================= -// Native Function Implementations - -/// Returns all natives for tables. -pub fn table_natives(table_addr: AccountAddress) -> NativeFunctionTable { - native_functions::make_table( - table_addr, - &[ - ("Table", "new_table_handle", native_new_table_handle), - ("Table", "add_box", native_add_box), - ("Table", "borrow_box", native_borrow_box), - ("Table", "borrow_box_mut", native_borrow_box), - ("Table", "remove_box", native_remove_box), - ("Table", "contains_box", native_contains_box), - ("Table", "destroy_empty_box", native_destroy_empty_box), - ("Table", "drop_unchecked_box", native_drop_unchecked_box), - ], - ) +#[derive(Debug, Clone)] +pub struct NewTableHandleGasParameters { + pub base: InternalGas, } fn native_new_table_handle( + gas_params: &NewTableHandleGasParameters, context: &mut NativeContext, - mut _ty_args: Vec, + ty_args: Vec, args: VecDeque, ) -> PartialVMResult { + assert_eq!(ty_args.len(), 2); assert!(args.is_empty()); let table_context = context.extensions().get::(); let mut table_data = table_context.table_data.borrow_mut(); // Take the transaction hash provided by the environment, combine it with the # of tables - // produced so far, sha256 this and select 16 bytes from the result. Given the txn hash + // produced so far, sha256 this to produce a unique handle. Given the txn hash // is unique, this should create a unique and deterministic global id. let mut digest = Sha3_256::new(); - Digest::update(&mut digest, table_context.txn_hash.to_be_bytes()); - Digest::update(&mut digest, table_data.new_tables.len().to_be_bytes()); - let bytes: [u8; 16] = digest.finalize()[0..16].try_into().unwrap(); - let id = u128::from_be_bytes(bytes); - assert!(table_data.new_tables.insert(TableHandle(id))); + let table_len = table_data.new_tables.len() as u32; // cast usize to u32 to ensure same length + Digest::update(&mut digest, table_context.txn_hash); + Digest::update(&mut digest, table_len.to_be_bytes()); + let bytes = digest.finalize().to_vec(); + let handle = AccountAddress::from_bytes(&bytes[0..AccountAddress::LENGTH]) + .map_err(|_| partial_extension_error("Unable to create table handle"))?; + let key_type = context.type_to_type_tag(&ty_args[0])?; + let value_type = context.type_to_type_tag(&ty_args[1])?; + assert!(table_data + .new_tables + .insert(TableHandle(handle), TableInfo::new(key_type, value_type)) + .is_none()); Ok(NativeResult::ok( - table_context - .resolver - .operation_cost(TableOperation::NewHandle, 0, 0), - smallvec![Value::u128(id)], + gas_params.base, + smallvec![Value::address(handle)], )) } +pub fn make_native_new_table_handle(gas_params: NewTableHandleGasParameters) -> NativeFunction { + Arc::new( + move |context, ty_args, args| -> PartialVMResult { + native_new_table_handle(&gas_params, context, ty_args, args) + }, + ) +} + +#[derive(Debug, Clone)] +pub struct AddBoxGasParameters { + pub base: InternalGas, + pub per_byte_serialized: InternalGasPerByte, +} + fn native_add_box( + common_gas_params: &CommonGasParameters, + gas_params: &AddBoxGasParameters, context: &mut NativeContext, ty_args: Vec, mut args: VecDeque, @@ -377,19 +396,42 @@ fn native_add_box( let key = args.pop_back().unwrap(); let handle = get_table_handle(&pop_arg!(args, StructRef))?; + let mut cost = gas_params.base; + let table = table_data.get_or_create_table(context, handle, &ty_args[0], &ty_args[2])?; - let status = table.insert(table_context, &key, val); - let (key_size, val_size) = status?; - Ok(NativeResult::ok( - table_context - .resolver - .operation_cost(TableOperation::Insert, key_size, val_size), - smallvec![], - )) + let key_bytes = serialize(&table.key_layout, &key)?; + cost += gas_params.per_byte_serialized * NumBytes::new(key_bytes.len() as u64); + + let (gv, loaded) = table.get_or_create_global_value(table_context, key_bytes)?; + cost += common_gas_params.calculate_load_cost(loaded); + + match gv.move_to(val) { + Ok(_) => Ok(NativeResult::ok(cost, smallvec![])), + Err(_) => Ok(NativeResult::err(cost, ALREADY_EXISTS)), + } +} + +pub fn make_native_add_box( + common_gas_params: CommonGasParameters, + gas_params: AddBoxGasParameters, +) -> NativeFunction { + Arc::new( + move |context, ty_args, args| -> PartialVMResult { + native_add_box(&common_gas_params, &gas_params, context, ty_args, args) + }, + ) +} + +#[derive(Debug, Clone)] +pub struct BorrowBoxGasParameters { + pub base: InternalGas, + pub per_byte_serialized: InternalGasPerByte, } fn native_borrow_box( + common_gas_params: &CommonGasParameters, + gas_params: &BorrowBoxGasParameters, context: &mut NativeContext, ty_args: Vec, mut args: VecDeque, @@ -404,17 +446,41 @@ fn native_borrow_box( let handle = get_table_handle(&pop_arg!(args, StructRef))?; let table = table_data.get_or_create_table(context, handle, &ty_args[0], &ty_args[2])?; - let (val, key_size, val_size) = table.borrow_global(table_context, &key)?; - Ok(NativeResult::ok( - table_context - .resolver - .operation_cost(TableOperation::Borrow, key_size, val_size), - smallvec![val], - )) + let mut cost = gas_params.base; + + let key_bytes = serialize(&table.key_layout, &key)?; + cost += gas_params.per_byte_serialized * NumBytes::new(key_bytes.len() as u64); + + let (gv, loaded) = table.get_or_create_global_value(table_context, key_bytes)?; + cost += common_gas_params.calculate_load_cost(loaded); + + match gv.borrow_global() { + Ok(ref_val) => Ok(NativeResult::ok(cost, smallvec![ref_val])), + Err(_) => Ok(NativeResult::err(cost, NOT_FOUND)), + } +} + +pub fn make_native_borrow_box( + common_gas_params: CommonGasParameters, + gas_params: BorrowBoxGasParameters, +) -> NativeFunction { + Arc::new( + move |context, ty_args, args| -> PartialVMResult { + native_borrow_box(&common_gas_params, &gas_params, context, ty_args, args) + }, + ) +} + +#[derive(Debug, Clone)] +pub struct ContainsBoxGasParameters { + pub base: InternalGas, + pub per_byte_serialized: InternalGasPerByte, } fn native_contains_box( + common_gas_params: &CommonGasParameters, + gas_params: &ContainsBoxGasParameters, context: &mut NativeContext, ty_args: Vec, mut args: VecDeque, @@ -429,17 +495,40 @@ fn native_contains_box( let handle = get_table_handle(&pop_arg!(args, StructRef))?; let table = table_data.get_or_create_table(context, handle, &ty_args[0], &ty_args[2])?; - let (val, key_size, val_size) = table.contains(table_context, &key)?; - Ok(NativeResult::ok( - table_context - .resolver - .operation_cost(TableOperation::Contains, key_size, val_size), - smallvec![val], - )) + let mut cost = gas_params.base; + + let key_bytes = serialize(&table.key_layout, &key)?; + cost += gas_params.per_byte_serialized * NumBytes::new(key_bytes.len() as u64); + + let (gv, loaded) = table.get_or_create_global_value(table_context, key_bytes)?; + cost += common_gas_params.calculate_load_cost(loaded); + + let exists = Value::bool(gv.exists()?); + + Ok(NativeResult::ok(cost, smallvec![exists])) +} + +pub fn make_native_contains_box( + common_gas_params: CommonGasParameters, + gas_params: ContainsBoxGasParameters, +) -> NativeFunction { + Arc::new( + move |context, ty_args, args| -> PartialVMResult { + native_contains_box(&common_gas_params, &gas_params, context, ty_args, args) + }, + ) +} + +#[derive(Debug, Clone)] +pub struct RemoveGasParameters { + pub base: InternalGas, + pub per_byte_serialized: InternalGasPerByte, } fn native_remove_box( + common_gas_params: &CommonGasParameters, + gas_params: &RemoveGasParameters, context: &mut NativeContext, ty_args: Vec, mut args: VecDeque, @@ -452,18 +541,41 @@ fn native_remove_box( let key = args.pop_back().unwrap(); let handle = get_table_handle(&pop_arg!(args, StructRef))?; + let table = table_data.get_or_create_table(context, handle, &ty_args[0], &ty_args[2])?; - let (val, key_size, val_size) = table.remove(table_context, &key)?; - Ok(NativeResult::ok( - table_context - .resolver - .operation_cost(TableOperation::Remove, key_size, val_size), - smallvec![val], - )) + let mut cost = gas_params.base; + + let key_bytes = serialize(&table.key_layout, &key)?; + cost += gas_params.per_byte_serialized * NumBytes::new(key_bytes.len() as u64); + + let (gv, loaded) = table.get_or_create_global_value(table_context, key_bytes)?; + cost += common_gas_params.calculate_load_cost(loaded); + + match gv.move_from() { + Ok(val) => Ok(NativeResult::ok(cost, smallvec![val])), + Err(_) => Ok(NativeResult::err(cost, NOT_FOUND)), + } +} + +pub fn make_native_remove_box( + common_gas_params: CommonGasParameters, + gas_params: RemoveGasParameters, +) -> NativeFunction { + Arc::new( + move |context, ty_args, args| -> PartialVMResult { + native_remove_box(&common_gas_params, &gas_params, context, ty_args, args) + }, + ) +} + +#[derive(Debug, Clone)] +pub struct DestroyEmptyBoxGasParameters { + pub base: InternalGas, } fn native_destroy_empty_box( + gas_params: &DestroyEmptyBoxGasParameters, context: &mut NativeContext, ty_args: Vec, mut args: VecDeque, @@ -475,20 +587,29 @@ fn native_destroy_empty_box( let mut table_data = table_context.table_data.borrow_mut(); let handle = get_table_handle(&pop_arg!(args, StructRef))?; - let table = table_data.get_or_create_table(context, handle, &ty_args[0], &ty_args[2])?; - let (key_size, val_size) = table.destroy_empty(table_context)?; + // TODO: Can the following line be removed? + table_data.get_or_create_table(context, handle, &ty_args[0], &ty_args[2])?; assert!(table_data.removed_tables.insert(handle)); - Ok(NativeResult::ok( - table_context - .resolver - .operation_cost(TableOperation::Destroy, key_size, val_size), - smallvec![], - )) + Ok(NativeResult::ok(gas_params.base, smallvec![])) +} + +pub fn make_native_destroy_empty_box(gas_params: DestroyEmptyBoxGasParameters) -> NativeFunction { + Arc::new( + move |context, ty_args, args| -> PartialVMResult { + native_destroy_empty_box(&gas_params, context, ty_args, args) + }, + ) +} + +#[derive(Debug, Clone)] +pub struct DropUncheckedBoxGasParameters { + pub base: InternalGas, } fn native_drop_unchecked_box( + gas_params: &DropUncheckedBoxGasParameters, _context: &mut NativeContext, ty_args: Vec, args: VecDeque, @@ -496,17 +617,70 @@ fn native_drop_unchecked_box( assert_eq!(ty_args.len(), 3); assert_eq!(args.len(), 1); - Ok(NativeResult::ok(InternalGasUnits::new(0_u64), smallvec![])) + Ok(NativeResult::ok(gas_params.base, smallvec![])) +} + +pub fn make_native_drop_unchecked_box(gas_params: DropUncheckedBoxGasParameters) -> NativeFunction { + Arc::new( + move |context, ty_args, args| -> PartialVMResult { + native_drop_unchecked_box(&gas_params, context, ty_args, args) + }, + ) +} + +#[derive(Debug, Clone)] +pub struct GasParameters { + pub common: CommonGasParameters, + pub new_table_handle: NewTableHandleGasParameters, + pub add_box: AddBoxGasParameters, + pub borrow_box: BorrowBoxGasParameters, + pub contains_box: ContainsBoxGasParameters, + pub remove_box: RemoveGasParameters, + pub destroy_empty_box: DestroyEmptyBoxGasParameters, + pub drop_unchecked_box: DropUncheckedBoxGasParameters, +} + +impl GasParameters { + pub fn zeros() -> Self { + Self { + common: CommonGasParameters { + load_base: 0.into(), + load_per_byte: 0.into(), + load_failure: 0.into(), + }, + new_table_handle: NewTableHandleGasParameters { base: 0.into() }, + add_box: AddBoxGasParameters { + base: 0.into(), + per_byte_serialized: 0.into(), + }, + borrow_box: BorrowBoxGasParameters { + base: 0.into(), + per_byte_serialized: 0.into(), + }, + contains_box: ContainsBoxGasParameters { + base: 0.into(), + per_byte_serialized: 0.into(), + }, + remove_box: RemoveGasParameters { + base: 0.into(), + per_byte_serialized: 0.into(), + }, + destroy_empty_box: DestroyEmptyBoxGasParameters { base: 0.into() }, + drop_unchecked_box: DropUncheckedBoxGasParameters { base: 0.into() }, + } + } } // ========================================================================================= // Helpers fn get_table_handle(table: &StructRef) -> PartialVMResult { - let field_ref = table + let handle = table .borrow_field(HANDLE_FIELD_INDEX)? - .value_as::()?; - field_ref.read_ref()?.value_as::().map(TableHandle) + .value_as::()? + .read_ref()? + .value_as::()?; + Ok(TableHandle(handle)) } fn serialize(layout: &MoveTypeLayout, val: &Value) -> PartialVMResult> { @@ -523,12 +697,6 @@ fn partial_extension_error(msg: impl ToString) -> PartialVMError { PartialVMError::new(StatusCode::VM_EXTENSION_ERROR).with_message(msg.to_string()) } -fn partial_abort_error(msg: impl ToString, code: u64) -> PartialVMError { - PartialVMError::new(StatusCode::ABORTED) - .with_message(msg.to_string()) - .with_sub_status(code) -} - fn get_type_layout(context: &NativeContext, ty: &Type) -> PartialVMResult { context .type_to_type_layout(ty)? diff --git a/language/extensions/move-table-extension/tests/move_unit_tests.rs b/language/extensions/move-table-extension/tests/move_unit_tests.rs index df7b40ec61..9bc3c7205a 100644 --- a/language/extensions/move-table-extension/tests/move_unit_tests.rs +++ b/language/extensions/move-table-extension/tests/move_unit_tests.rs @@ -2,21 +2,24 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 -use move_cli::package::{cli, cli::UnitTestResult}; +use move_cli::base::test::{run_move_unit_tests, UnitTestResult}; use move_core_types::account_address::AccountAddress; -use move_table_extension::table_natives; +use move_table_extension::{table_natives, GasParameters}; use move_unit_test::UnitTestingConfig; use std::path::PathBuf; use tempfile::tempdir; fn run_tests_for_pkg(path_to_pkg: impl Into) { let pkg_path = path_in_crate(path_to_pkg); - let mut natives = - move_stdlib::natives::all_natives(AccountAddress::from_hex_literal("0x1").unwrap()); + let mut natives = move_stdlib::natives::all_natives( + AccountAddress::from_hex_literal("0x1").unwrap(), + move_stdlib::natives::GasParameters::zeros(), + ); natives.append(&mut table_natives( AccountAddress::from_hex_literal("0x2").unwrap(), + GasParameters::zeros(), )); - let res = cli::run_move_unit_tests( + let res = run_move_unit_tests( &pkg_path, move_package::BuildConfig { test_mode: true, @@ -25,7 +28,9 @@ fn run_tests_for_pkg(path_to_pkg: impl Into) { }, UnitTestingConfig::default_with_bound(Some(100_000)), natives, + None, /* compute_coverage */ false, + &mut std::io::stdout(), ) .unwrap(); if res != UnitTestResult::Success { diff --git a/language/extensions/move-table-extension/tests/TableTests.move b/language/extensions/move-table-extension/tests/table_tests.move similarity index 93% rename from language/extensions/move-table-extension/tests/TableTests.move rename to language/extensions/move-table-extension/tests/table_tests.move index feeff3d5cf..c61fda43f3 100644 --- a/language/extensions/move-table-extension/tests/TableTests.move +++ b/language/extensions/move-table-extension/tests/table_tests.move @@ -1,7 +1,7 @@ #[test_only] -module Extensions::TableTests { +module extensions::table_tests { use std::vector; - use Extensions::Table as T; + use extensions::table as T; struct S has key { t: T::Table @@ -41,7 +41,7 @@ module Extensions::TableTests { } #[test] - #[expected_failure(abort_code = 26113)] + #[expected_failure(abort_code = 26113, location = extensions::table)] fun test_destroy_fails() { let t = T::new(); T::add(&mut t, 1, 2); @@ -180,7 +180,7 @@ module Extensions::TableTests { } #[test(s = @0x42)] - #[expected_failure(abort_code = 25607)] + #[expected_failure(abort_code = 25607, location = extensions::table)] fun test_insert_fail(s: signer) { let t = T::new(); assert!(!T::contains(&t, 42), 100); @@ -193,7 +193,7 @@ module Extensions::TableTests { } #[test(s = @0x42)] - #[expected_failure(abort_code = 25863)] + #[expected_failure(abort_code = 25863, location = extensions::table)] fun test_borrow_fail(s: signer) { let t = T::new(); assert!(!T::contains(&t, 42), 100); @@ -205,7 +205,7 @@ module Extensions::TableTests { } #[test(s = @0x42)] - #[expected_failure(abort_code = 25863)] + #[expected_failure(abort_code = 25863, location = extensions::table)] fun test_remove_fail(s: signer) { let t = T::new(); let Balance { value } = T::remove(&mut t, 42); // should fail here since key 42 doesn't exist @@ -228,7 +228,7 @@ module Extensions::TableTests { } #[test] - #[expected_failure(abort_code = 25863)] + #[expected_failure(abort_code = 25863, location = extensions::table)] fun test_remove_removed() { let t = T::new(); T::add(&mut t, 42, 42); @@ -242,7 +242,7 @@ module Extensions::TableTests { } #[test] - #[expected_failure(abort_code = 25863)] + #[expected_failure(abort_code = 25863, location = extensions::table)] fun test_borrow_removed() { let t = T::new(); T::add(&mut t, 42, 42); diff --git a/language/move-analyzer/Cargo.toml b/language/move-analyzer/Cargo.toml index a454f24521..20b6f8ca0c 100644 --- a/language/move-analyzer/Cargo.toml +++ b/language/move-analyzer/Cargo.toml @@ -1,21 +1,23 @@ [package] name = "move-analyzer" -version = "0.0.0" +version = "1.0.0" authors = ["Diem Association "] description = "A language server for Move" -repository = "https://github.com/diem/diem" -homepage = "https://diem.com" +repository = "https://github.com/move-language/move" license = "Apache-2.0" publish = false -edition = "2018" +edition = "2021" [dependencies] anyhow = "1.0.52" codespan-reporting = "0.11.1" +derivative = "2.2.0" +dunce = "1.0.2" im = "15.1.0" lsp-server = "0.5.1" lsp-types = "0.90.1" petgraph = "0.5.1" +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.64" tempfile = "3.2.0" url = "2.2.2" @@ -26,3 +28,7 @@ move-compiler = { path = "../move-compiler" } move-ir-types = { path = "../move-ir/types" } move-package = { path = "../tools/move-package" } move-symbol-pool = { path = "../move-symbol-pool" } + +[features] +address20 = ["move-compiler/address20"] +address32 = ["move-compiler/address32"] diff --git a/language/move-analyzer/editors/code/.eslintrc.json b/language/move-analyzer/editors/code/.eslintrc.json index 084af02eea..a6a2d7351c 100644 --- a/language/move-analyzer/editors/code/.eslintrc.json +++ b/language/move-analyzer/editors/code/.eslintrc.json @@ -106,11 +106,11 @@ "function-call-argument-newline": ["warn", "consistent"], "function-paren-newline": ["warn", "consistent"], "key-spacing": "warn", - "linebreak-style": "warn", + "linebreak-style": "off", // We use different linebreak styles. ref https://eslint.org/docs/latest/rules/linebreak-style "max-len": [ "warn", { - "code": 100, + "code": 120, "ignoreUrls": true } ], @@ -139,7 +139,6 @@ // * All @typescript-eslint rules: https://github.com/typescript-eslint/typescript-eslint/tree/v4.31.1/packages/eslint-plugin/docs/rules // * The rules included in @typescript-eslint/recommended: https://github.com/typescript-eslint/typescript-eslint/blob/v4.31.1/packages/eslint-plugin/src/configs/recommended.ts // * The rules included in @typescript-eslint/recommended-requiring-type-checking: https://github.com/typescript-eslint/typescript-eslint/blob/v4.31.1/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts - "@typescript-eslint/array-type": ["warn", { "default": "generic" }], "@typescript-eslint/ban-tslint-comment": "warn", "@typescript-eslint/brace-style": "warn", "@typescript-eslint/comma-dangle": [ @@ -158,7 +157,7 @@ "@typescript-eslint/keyword-spacing": "warn", "@typescript-eslint/lines-between-class-members": "warn", "@typescript-eslint/member-delimiter-style": "warn", - "@typescript-eslint/naming-convention": "warn", + "@typescript-eslint/naming-convention": "off", "@typescript-eslint/no-base-to-string": "warn", "@typescript-eslint/no-confusing-non-null-assertion": "warn", "@typescript-eslint/no-duplicate-imports": "warn", @@ -206,10 +205,16 @@ ], "@typescript-eslint/strict-boolean-expressions": "warn", "@typescript-eslint/switch-exhaustiveness-check": "warn", - "@typescript-eslint/type-annotation-spacing": "warn", "@typescript-eslint/unified-signatures": "warn", // The following are eslint-plugin-tsdoc rules: - "tsdoc/syntax": "warn" + "tsdoc/syntax": "warn", + + "@typescript-eslint/no-unsafe-return": "off", + "@typescript-eslint/type-annotation-spacing": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-unsafe-assignment": "off", + "@typescript-eslint/restrict-template-expressions": "off", + "@typescript-eslint/array-type": "off" } } diff --git a/language/move-analyzer/editors/code/.gitignore b/language/move-analyzer/editors/code/.gitignore index 036b79d9db..8174e373d7 100644 --- a/language/move-analyzer/editors/code/.gitignore +++ b/language/move-analyzer/editors/code/.gitignore @@ -7,3 +7,5 @@ out .vscode-test # VS Code extension package (VSIX) archive *.vsix +# Yarn cache directory +yarn.lock diff --git a/language/move-analyzer/editors/code/.vscodeignore b/language/move-analyzer/editors/code/.vscodeignore index b622950d4c..ddd5d59296 100644 --- a/language/move-analyzer/editors/code/.vscodeignore +++ b/language/move-analyzer/editors/code/.vscodeignore @@ -4,7 +4,8 @@ # https://code.visualstudio.com/api/working-with-extensions/publishing-extension#.vscodeignore **/* -!out/src/* +!images/move.png +!out/src/**/* !node_modules/**/* !language-configuration.json !move.tmLanguage.json diff --git a/language/move-analyzer/editors/code/README.md b/language/move-analyzer/editors/code/README.md index cc4e44b4d7..a6891393e3 100644 --- a/language/move-analyzer/editors/code/README.md +++ b/language/move-analyzer/editors/code/README.md @@ -10,25 +10,30 @@ For information about Move visit [the Move repository](https://github.com/move-l ## How to Install -The move-analyzer Visual Studio Code extension works via two components: the extension itself, and +The move-analyzer Visual Studio Code extension works via two components: the extension itself and the `move-analyzer` language server. ### 1. Installing the `move-analyzer` language server -The `move-analyzer` language server is a Rust program that is part of -[the Move repository](https://github.com/move-language/move). It may be installed in one of two ways: +The `move-analyzer` language server is a Rust program that is part of the +[Move repository](https://github.com/move-language/move). It may be installed in one of two ways: -1. You may clone [the Move repository](https://github.com/move-language/move) yourself and build - `move-analyzer` from its source code. To do so, follow the instructions in the Move tutorial's +* Clone [the Move repository](https://github.com/move-language/move) yourself and build + `move-analyzer` from its source code, which is especially useful if you will work on core Move. + To do so, follow the instructions in the Move tutorial's [Step 0: Installation](https://github.com/move-language/move/tree/main/language/documentation/tutorial#step-0-installation). -2. You may use Rust's package manager `cargo` to install `move-analyzer` in your user's PATH. This - is recommended for people who do not work on Move core. +* Use Rust's package manager `cargo` to install `move-analyzer` in your user's PATH. This + is recommended for people who do not work on core Move. 1. If you don't already have a Rust toolchain installed, you should install [Rustup](https://rustup.rs/), which will install the latest stable Rust toolchain. 2. Invoke `cargo install --git https://github.com/move-language/move move-analyzer` to install the - `move-analyzer` language server in your Cargo binary directory. On macOS and Linux this is + `move-analyzer` language server in your Cargo binary directory. On macOS and Linux, this is usually `~/.cargo/bin`. You'll want to make sure this location is in your `PATH` environment - variable. + variable. If you plan to use the language server with Move language flavors different from core Move, + you should specify an additional option to `cargo install` command as different Move flavors + may enforce different max length of the Move address type: `--features "address20"` option for Move + flavors requiring 20-byte long addresses (e.g., Sui Move) and `--features "address32"` option + for Move flavors requiring 32-byte long addresses (e.g., Aptos Move). To confirm that you've installed the language server program successfully, execute `move-analyzer --version` on the command line. You should see the output `move-analyzer 1.0.0`. @@ -36,28 +41,28 @@ To confirm that you've installed the language server program successfully, execu ### 2. Installing the move-analyzer Visual Studio Code extension 1. Open a new window in any Visual Studio Code application version 1.55.2 or greater. -2. Open the command palette (`⇧⌘P` on macOS, or use the menu item "View > Command Palette...") and - type in `"Extensions: Install Extensions"`. This will open a panel named "Extensions" in the +2. Open the command palette (`⇧⌘P` on macOS, or use the menu item *View > Command Palette...*) and + type **Extensions: Install Extensions**. This will open a panel named *Extensions* in the sidebar of your Visual Studio Code window. -3. In the search bar labeled "Search Extensions in Marketplace," type in "move-analyzer". The - move-analyzer extension should appear in the list below the search bar. Click "Install". -4. Open any file that ends in `.move` (or, create a new file, click on "Select a language," and - choose the "Move" language). As you type, you should see that keywords and types appear in +3. In the search bar labeled *Search Extensions in Marketplace*, type **move-analyzer**. The + move-analyzer extension should appear in the list below the search bar. Click **Install**. +4. Open any file that ends in `.move`. Or to create a new file, click **Select a language**, and + choose the **Move** language. As you type, you should see that keywords and types appear in different colors. ### Troubleshooting -If you see an error message "language server executable 'move-analyzer' could not be found" in the +If you see an error message *language server executable 'move-analyzer' could not be found* in the bottom-right of your Visual Studio Code screen when opening a Move file, it means that the `move-analyzer` executable could not be found in your `PATH`. You may try the following: -1. Confirm that invoking `move-analyzer --version` in a command-line terminal prints out +1. Confirm that invoking `move-analyzer --version` in a command line terminal prints out `move-analyzer 1.0.0`. If it doesn't, then retry the instructions in [step 1](./Step1). If it - does successfully print this text out, try closing and re-opening the Visual Studio Code - application, as it may not have picked up the udpates to your `PATH`. + does successfully print this output, try closing and re-opening the Visual Studio Code + application, as it may not have picked up the update to your `PATH`. 2. If you installed the `move-analyzer` executable to a different location that is outside of your `PATH`, then you may have the extension look at this location by using the the Visual Studio Code - settings (`⌘,` on macOS, or use the menu item "Code > Preferences > Settings"). Search for the + settings (`⌘,` on macOS, or use the menu item *Code > Preferences > Settings*). Search for the `move-analyzer.server.path` setting, and set it to the location of the `move-analyzer` language server you installed. 3. If the above steps don't work, then report @@ -65,19 +70,20 @@ bottom-right of your Visual Studio Code screen when opening a Move file, it mean ## Features -Here are some of the features of the move-analyzer Visual Studio Code extension. Open a Move source -file (a file with a `.move` file extension), and: +Here are some of the features of the move-analyzer Visual Studio Code extension. To see them, open a +Move source file (a file with a `.move` file extension) and: - See Move keywords and types highlighted in appropriate colors. -- Comment and un-comment lines of code using the `⌘/` shortcut on macOS (or the menu command "Edit > - Toggle Line Comment"). +- Comment and un-comment lines of code using the `⌘/` shortcut on macOS (or the menu command *Edit > + Toggle Line Comment*). - Place your cursor on a delimiter, such as `<`, `(`, or `{`, and its corresponding delimiter -- `>`, `)`, or `}` -- will be highlighted. - As you type, Move keywords will appear as completion suggestions. - If the opened Move source file is located within a buildable project (a `Move.toml` file can be - found in one of its parent directories), the following advanced features will be available: + found in one of its parent directories), the following advanced features will also be available: - compiler diagnostics - go to definition - go to type definition - go to references - type on hover + - outline view showing symbol tree for Move source files diff --git a/language/move-analyzer/editors/code/images/move.png b/language/move-analyzer/editors/code/images/move.png new file mode 100644 index 0000000000..c6bfb341ae Binary files /dev/null and b/language/move-analyzer/editors/code/images/move.png differ diff --git a/language/move-analyzer/editors/code/package-lock.json b/language/move-analyzer/editors/code/package-lock.json index 7be9879524..b4126498af 100644 --- a/language/move-analyzer/editors/code/package-lock.json +++ b/language/move-analyzer/editors/code/package-lock.json @@ -1,7063 +1,7444 @@ { - "name": "move-analyzer", - "version": "0.0.7", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "move-analyzer", - "version": "0.0.7", - "license": "Apache-2.0", - "dependencies": { - "command-exists": "^1.2.9", - "vscode-languageclient": "6.1.4" - }, - "devDependencies": { - "@types/command-exists": "^1.2.0", - "@types/glob": "^7.1.4", - "@types/mocha": "^9.0.0", - "@types/node": "^14.17.22", - "@types/vscode": "^1.58.2", - "@typescript-eslint/eslint-plugin": "^4.33.0", - "@typescript-eslint/parser": "^4.33.0", - "@vscode/test-electron": "^1.6.1", - "eslint": "^7.32.0", - "eslint-plugin-tsdoc": "^0.2.14", - "glob": "^7.1.7", - "mocha": "^9.1.1", - "typescript": "^4.4.4", - "typescript-formatter": "^7.2.2", - "vsce": "^2.5.1", - "vscode-test": "^1.6.1" - }, - "engines": { - "vscode": "^1.58.2" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.15.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", - "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.14.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", - "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", - "dev": true - }, - "node_modules/@microsoft/tsdoc": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.13.2.tgz", - "integrity": "sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg==", - "dev": true - }, - "node_modules/@microsoft/tsdoc-config": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.15.2.tgz", - "integrity": "sha512-mK19b2wJHSdNf8znXSMYVShAHktVr/ib0Ck2FA3lsVBSEhSI/TfXT7DJQkAYgcztTuwazGcg58ZjYdk0hTCVrA==", - "dev": true, - "dependencies": { - "@microsoft/tsdoc": "0.13.2", - "ajv": "~6.12.6", - "jju": "~1.4.0", - "resolve": "~1.19.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/command-exists": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/command-exists/-/command-exists-1.2.0.tgz", - "integrity": "sha512-ugsxEJfsCuqMLSuCD4PIJkp5Uk2z6TCMRCgYVuhRo5cYQY3+1xXTQkSlPtkpGHuvWMjS2KTeVQXxkXRACMbM6A==", - "dev": true - }, - "node_modules/@types/glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==", - "dev": true, - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", - "dev": true - }, - "node_modules/@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", - "dev": true - }, - "node_modules/@types/mocha": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.0.0.tgz", - "integrity": "sha512-scN0hAWyLVAvLR9AyW7HoFF5sJZglyBsbPuHO4fv7JRvfmPBMfp1ozWqOf/e4wwPNxezBZXRfWzMb6iFLgEVRA==", - "dev": true - }, - "node_modules/@types/node": { - "version": "14.17.27", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.27.tgz", - "integrity": "sha512-94+Ahf9IcaDuJTle/2b+wzvjmutxXAEXU6O81JHblYXUg2BDG+dnBy7VxIPHKAyEEDHzCMQydTJuWvrE+Aanzw==", - "dev": true - }, - "node_modules/@types/vscode": { - "version": "1.61.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.61.0.tgz", - "integrity": "sha512-9k5Nwq45hkRwdfCFY+eKXeQQSbPoA114mF7U/4uJXRBJeGIO7MuJdhF1PnaDN+lllL9iKGQtd6FFXShBXMNaFg==", - "dev": true - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz", - "integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==", - "dev": true, - "dependencies": { - "@typescript-eslint/experimental-utils": "4.33.0", - "@typescript-eslint/scope-manager": "4.33.0", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^4.0.0", - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz", - "integrity": "sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.33.0", - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/typescript-estree": "4.33.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz", - "integrity": "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "4.33.0", - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/typescript-estree": "4.33.0", - "debug": "^4.3.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", - "integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/visitor-keys": "4.33.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", - "integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==", - "dev": true, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz", - "integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/visitor-keys": "4.33.0", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", - "integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.33.0", - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, - "node_modules/@vscode/test-electron": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-1.6.2.tgz", - "integrity": "sha512-W01ajJEMx6223Y7J5yaajGjVs1QfW3YGkkOJHVKfAMEqNB1ZHN9wCcViehv5ZwVSSJnjhu6lYEYgwBdHtCxqhQ==", - "dev": true, - "dependencies": { - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "rimraf": "^3.0.2", - "unzipper": "^0.10.11" - }, - "engines": { - "node": ">=8.9.3" - } - }, - "node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "node_modules/are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", - "dev": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/azure-devops-node-api": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.1.0.tgz", - "integrity": "sha512-6/2YZuf+lJzJLrjXNYEA5RXAkMCb8j/4VcHD0qJQRsgG/KsRMYo0HgDh0by1FGHyZkQWY5LmQyJqCwRVUB3Y7Q==", - "dev": true, - "dependencies": { - "tunnel": "0.0.6", - "typed-rest-client": "^1.8.4" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/big-integer": { - "version": "1.6.50", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.50.tgz", - "integrity": "sha512-+O2uoQWFRo8ysZNo/rjtri2jIwjr3XfeAgRjAUADRqGG+ZITvyn8J1kvXLTaKVr3hhGXk+f23tKfdzmklVM9vQ==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "dependencies": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", - "dev": true - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", - "dev": true, - "engines": { - "node": ">=0.2.0" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "dependencies": { - "traverse": ">=0.3.0 <0.4" - }, - "engines": { - "node": "*" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/chalk/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/chalk/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/chalk/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dev": true, - "dependencies": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - }, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" - } - }, - "node_modules/cheerio-select": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", - "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", - "dev": true, - "dependencies": { - "css-select": "^4.1.3", - "css-what": "^5.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0", - "domutils": "^2.7.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cheerio/node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - }, - "node_modules/chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/commandpost": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/commandpost/-/commandpost-1.4.0.tgz", - "integrity": "sha512-aE2Y4MTFJ870NuB/+2z1cXBhSBBzRydVVjzhFC4gtenEhpnj15yu0qptWGJsO9YGrcPZ3ezX8AWb1VA391MKpQ==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", - "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "dev": true, - "dependencies": { - "mimic-response": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, - "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true, - "bin": { - "detect-libc": "bin/detect-libc.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", - "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", - "dev": true, - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz", - "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==", - "dev": true, - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/editorconfig": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", - "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", - "dev": true, - "dependencies": { - "commander": "^2.19.0", - "lru-cache": "^4.1.5", - "semver": "^5.6.0", - "sigmund": "^1.0.1" - }, - "bin": { - "editorconfig": "bin/editorconfig" - } - }, - "node_modules/editorconfig/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/editorconfig/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/editorconfig/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-tsdoc": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.14.tgz", - "integrity": "sha512-fJ3fnZRsdIoBZgzkQjv8vAj6NeeOoFkTfgosj6mKsFjX70QV256sA/wq+y/R2+OL4L8E79VVaVWrPeZnKNe8Ng==", - "dev": true, - "dependencies": { - "@microsoft/tsdoc": "0.13.2", - "@microsoft/tsdoc-config": "0.15.2" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint/node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/eslint/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", - "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", - "dev": true - }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/fstream/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "node_modules/gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "dependencies": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "node_modules/gauge/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gauge/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gauge/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gauge/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", - "dev": true - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globals": { - "version": "13.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", - "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true - }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true, - "engines": { - "node": ">=4.x" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", - "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/jju": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", - "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=", - "dev": true - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/keytar": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.7.0.tgz", - "integrity": "sha512-YEY9HWqThQc5q5xbXbRwsZTh2PJ36OSYRjSv3NN2xf5s5dpLTjEZnC2YikR29OaVybf9nQ0dJ/80i40RS97t/A==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "node-addon-api": "^3.0.0", - "prebuild-install": "^6.0.0" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "dependencies": { - "uc.micro": "^1.0.1" - } - }, - "node_modules/listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", - "dev": true - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "bin": { - "markdown-it": "bin/markdown-it.js" - } - }, - "node_modules/markdown-it/node_modules/entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true - }, - "node_modules/mocha": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.3.tgz", - "integrity": "sha512-Xcpl9FqXOAYqI3j79pEtHBBnQgVXIhpULjGQa7DVb0Po+VzmSIK9kanAiWLHoRR/dbZ2qpdPshuXr8l1VaHCzw==", - "dev": true, - "dependencies": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.2", - "debug": "4.3.2", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.1.7", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "3.0.4", - "ms": "2.1.3", - "nanoid": "3.1.25", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "workerpool": "6.1.5", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/mocha/node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.1.25", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz", - "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "dev": true - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/node-abi": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", - "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", - "dev": true, - "dependencies": { - "semver": "^5.4.1" - } - }, - "node_modules/node-abi/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "dependencies": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "node_modules/nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.1.tgz", - "integrity": "sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", - "dev": true, - "dependencies": { - "semver": "^5.1.0" - } - }, - "node_modules/parse-semver/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "dependencies": { - "parse5": "^6.0.1" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/prebuild-install": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", - "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", - "dev": true, - "dependencies": { - "detect-libc": "^1.0.3", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^2.21.0", - "npmlog": "^4.0.1", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^3.0.3", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.2.tgz", - "integrity": "sha512-mSIdjzqznWgfd4pMii7sHtaYF8rx8861hBO80SraY5GT0XQibWZWJSid0avzHGkDIZLImux2S5mXO0Hfct2QCw==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "dev": true, - "dependencies": { - "mute-stream": "~0.0.4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", - "dev": true, - "dependencies": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, - "node_modules/signal-exit": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", - "dev": true - }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/simple-get": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", - "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", - "dev": true, - "dependencies": { - "decompress-response": "^4.2.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/slice-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/table": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.7.2.tgz", - "integrity": "sha512-UFZK67uvyNivLeQbVtkiUs8Uuuxv24aSL4/Vil2PJVtMgU8Lx0CYkP12uCGa3kjyQzOSgV1+z9Wkb82fCGsO0g==", - "dev": true, - "dependencies": { - "ajv": "^8.0.1", - "lodash.clonedeep": "^4.5.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "8.6.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.3.tgz", - "integrity": "sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dev": true, - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar-stream/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "dependencies": { - "rimraf": "^3.0.0" - }, - "engines": { - "node": ">=8.17.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true, - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-rest-client": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.6.tgz", - "integrity": "sha512-xcQpTEAJw2DP7GqVNECh4dD+riS+C1qndXLfBCJ3xk0kqprtGN491P5KlmrDbKdtuW8NEcP/5ChxiJI3S9WYTA==", - "dev": true, - "dependencies": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" - } - }, - "node_modules/typescript": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", - "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/typescript-formatter": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/typescript-formatter/-/typescript-formatter-7.2.2.tgz", - "integrity": "sha512-V7vfI9XArVhriOTYHPzMU2WUnm5IMdu9X/CPxs8mIMGxmTBFpDABlbkBka64PZJ9/xgQeRpK8KzzAG4MPzxBDQ==", - "dev": true, - "dependencies": { - "commandpost": "^1.0.0", - "editorconfig": "^0.15.0" - }, - "bin": { - "tsfmt": "bin/tsfmt" - }, - "engines": { - "node": ">= 4.2.0" - }, - "peerDependencies": { - "typescript": "^2.1.6 || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev" - } - }, - "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "node_modules/underscore": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", - "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==", - "dev": true - }, - "node_modules/unzipper": { - "version": "0.10.11", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", - "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", - "dev": true, - "dependencies": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", - "dev": true - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "node_modules/vsce": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-2.5.1.tgz", - "integrity": "sha512-vJ+xY93Wv3NhgeriMyIC2oMA+niifOI9XGIqEToIq/rFRoQnXlmO4PSyis/OxBl9hw8OKKC/VcI9CijfFufEkw==", - "dev": true, - "dependencies": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", - "glob": "^7.0.6", - "hosted-git-info": "^4.0.2", - "keytar": "^7.7.0", - "leven": "^3.1.0", - "markdown-it": "^10.0.0", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^5.1.0", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^4.0.1", - "xml2js": "^0.4.23", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "bin": { - "vsce": "vsce" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/vsce/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/vsce/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/vsce/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/vsce/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/vscode-jsonrpc": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", - "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==", - "engines": { - "node": ">=8.0.0 || >=10.0.0" - } - }, - "node_modules/vscode-languageclient": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.4.tgz", - "integrity": "sha512-EUOU+bJu6axmt0RFNo3nrglQLPXMfanbYViJee3Fbn2VuQoX0ZOI4uTYhSRvYLP2vfwTP/juV62P/mksCdTZMA==", - "dependencies": { - "semver": "^6.3.0", - "vscode-languageserver-protocol": "3.15.3" - }, - "engines": { - "vscode": "^1.41.0" - } - }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz", - "integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==", - "dependencies": { - "vscode-jsonrpc": "^5.0.1", - "vscode-languageserver-types": "3.15.1" - } - }, - "node_modules/vscode-languageserver-types": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz", - "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==" - }, - "node_modules/vscode-test": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.6.1.tgz", - "integrity": "sha512-086q88T2ca1k95mUzffvbzb7esqQNvJgiwY4h29ukPhFo8u+vXOOmelUoU5EQUHs3Of8+JuQ3oGdbVCqaxuTXA==", - "deprecated": "This package has been renamed to @vscode/test-electron, please update to the new name", - "dev": true, - "dependencies": { - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "rimraf": "^3.0.2", - "unzipper": "^0.10.11" - }, - "engines": { - "node": ">=8.9.3" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/workerpool": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", - "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", - "dev": true, - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.15.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", - "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", - "dev": true - }, - "@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - } - } - }, - "@eslint/eslintrc": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - } - } - }, - "@humanwhocodes/config-array": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/object-schema": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", - "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", - "dev": true - }, - "@microsoft/tsdoc": { - "version": "0.13.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.13.2.tgz", - "integrity": "sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg==", - "dev": true - }, - "@microsoft/tsdoc-config": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.15.2.tgz", - "integrity": "sha512-mK19b2wJHSdNf8znXSMYVShAHktVr/ib0Ck2FA3lsVBSEhSI/TfXT7DJQkAYgcztTuwazGcg58ZjYdk0hTCVrA==", - "dev": true, - "requires": { - "@microsoft/tsdoc": "0.13.2", - "ajv": "~6.12.6", - "jju": "~1.4.0", - "resolve": "~1.19.0" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@types/command-exists": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/command-exists/-/command-exists-1.2.0.tgz", - "integrity": "sha512-ugsxEJfsCuqMLSuCD4PIJkp5Uk2z6TCMRCgYVuhRo5cYQY3+1xXTQkSlPtkpGHuvWMjS2KTeVQXxkXRACMbM6A==", - "dev": true - }, - "@types/glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==", - "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", - "dev": true - }, - "@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", - "dev": true - }, - "@types/mocha": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.0.0.tgz", - "integrity": "sha512-scN0hAWyLVAvLR9AyW7HoFF5sJZglyBsbPuHO4fv7JRvfmPBMfp1ozWqOf/e4wwPNxezBZXRfWzMb6iFLgEVRA==", - "dev": true - }, - "@types/node": { - "version": "14.17.27", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.27.tgz", - "integrity": "sha512-94+Ahf9IcaDuJTle/2b+wzvjmutxXAEXU6O81JHblYXUg2BDG+dnBy7VxIPHKAyEEDHzCMQydTJuWvrE+Aanzw==", - "dev": true - }, - "@types/vscode": { - "version": "1.61.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.61.0.tgz", - "integrity": "sha512-9k5Nwq45hkRwdfCFY+eKXeQQSbPoA114mF7U/4uJXRBJeGIO7MuJdhF1PnaDN+lllL9iKGQtd6FFXShBXMNaFg==", - "dev": true - }, - "@typescript-eslint/eslint-plugin": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz", - "integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==", - "dev": true, - "requires": { - "@typescript-eslint/experimental-utils": "4.33.0", - "@typescript-eslint/scope-manager": "4.33.0", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@typescript-eslint/experimental-utils": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz", - "integrity": "sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.33.0", - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/typescript-estree": "4.33.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - } - }, - "@typescript-eslint/parser": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz", - "integrity": "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "4.33.0", - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/typescript-estree": "4.33.0", - "debug": "^4.3.1" - } - }, - "@typescript-eslint/scope-manager": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", - "integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/visitor-keys": "4.33.0" - } - }, - "@typescript-eslint/types": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", - "integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz", - "integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/visitor-keys": "4.33.0", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@typescript-eslint/visitor-keys": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", - "integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.33.0", - "eslint-visitor-keys": "^2.0.0" - } - }, - "@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, - "@vscode/test-electron": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-1.6.2.tgz", - "integrity": "sha512-W01ajJEMx6223Y7J5yaajGjVs1QfW3YGkkOJHVKfAMEqNB1ZHN9wCcViehv5ZwVSSJnjhu6lYEYgwBdHtCxqhQ==", - "dev": true, - "requires": { - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "rimraf": "^3.0.2", - "unzipper": "^0.10.11" - } - }, - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "azure-devops-node-api": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.1.0.tgz", - "integrity": "sha512-6/2YZuf+lJzJLrjXNYEA5RXAkMCb8j/4VcHD0qJQRsgG/KsRMYo0HgDh0by1FGHyZkQWY5LmQyJqCwRVUB3Y7Q==", - "dev": true, - "requires": { - "tunnel": "0.0.6", - "typed-rest-client": "^1.8.4" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true - }, - "big-integer": { - "version": "1.6.50", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.50.tgz", - "integrity": "sha512-+O2uoQWFRo8ysZNo/rjtri2jIwjr3XfeAgRjAUADRqGG+ZITvyn8J1kvXLTaKVr3hhGXk+f23tKfdzmklVM9vQ==", - "dev": true - }, - "binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "requires": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", - "dev": true - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true - }, - "buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", - "dev": true - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true - }, - "chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "requires": { - "traverse": ">=0.3.0 <0.4" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", - "dev": true, - "requires": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - } - } - }, - "cheerio-select": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", - "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", - "dev": true, - "requires": { - "css-select": "^4.1.3", - "css-what": "^5.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0", - "domutils": "^2.7.0" - } - }, - "chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "commandpost": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/commandpost/-/commandpost-1.4.0.tgz", - "integrity": "sha512-aE2Y4MTFJ870NuB/+2z1cXBhSBBzRydVVjzhFC4gtenEhpnj15yu0qptWGJsO9YGrcPZ3ezX8AWb1VA391MKpQ==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "css-select": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", - "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^5.0.0", - "domhandler": "^4.2.0", - "domutils": "^2.6.0", - "nth-check": "^2.0.0" - } - }, - "css-what": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", - "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", - "dev": true - }, - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - }, - "decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "dev": true, - "requires": { - "mimic-response": "^2.0.0" - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-serializer": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", - "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", - "dev": true - }, - "domhandler": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz", - "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==", - "dev": true, - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } - }, - "editorconfig": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", - "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", - "dev": true, - "requires": { - "commander": "^2.19.0", - "lru-cache": "^4.1.5", - "semver": "^5.6.0", - "sigmund": "^1.0.1" - }, - "dependencies": { - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - } - } - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - } - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", - "dev": true, - "requires": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "eslint-plugin-tsdoc": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.14.tgz", - "integrity": "sha512-fJ3fnZRsdIoBZgzkQjv8vAj6NeeOoFkTfgosj6mKsFjX70QV256sA/wq+y/R2+OL4L8E79VVaVWrPeZnKNe8Ng==", - "dev": true, - "requires": { - "@microsoft/tsdoc": "0.13.2", - "@microsoft/tsdoc-config": "0.15.2" - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - } - }, - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - }, - "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", - "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", - "dev": true - }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "dependencies": { - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", - "dev": true - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "globals": { - "version": "13.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", - "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" - } - }, - "graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true - }, - "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", - "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "jju": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", - "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "keytar": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.7.0.tgz", - "integrity": "sha512-YEY9HWqThQc5q5xbXbRwsZTh2PJ36OSYRjSv3NN2xf5s5dpLTjEZnC2YikR29OaVybf9nQ0dJ/80i40RS97t/A==", - "dev": true, - "requires": { - "node-addon-api": "^3.0.0", - "prebuild-install": "^6.0.0" - } - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "requires": { - "uc.micro": "^1.0.1" - } - }, - "listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", - "dev": true - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "dependencies": { - "entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - } - } - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true - }, - "mocha": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.3.tgz", - "integrity": "sha512-Xcpl9FqXOAYqI3j79pEtHBBnQgVXIhpULjGQa7DVb0Po+VzmSIK9kanAiWLHoRR/dbZ2qpdPshuXr8l1VaHCzw==", - "dev": true, - "requires": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.2", - "debug": "4.3.2", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.1.7", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "3.0.4", - "ms": "2.1.3", - "nanoid": "3.1.25", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "workerpool": "6.1.5", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "nanoid": { - "version": "3.1.25", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz", - "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", - "dev": true - }, - "napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node-abi": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", - "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", - "dev": true, - "requires": { - "semver": "^5.4.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "nth-check": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", - "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-inspect": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.1.tgz", - "integrity": "sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-semver": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", - "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", - "dev": true, - "requires": { - "semver": "^5.1.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "requires": { - "parse5": "^6.0.1" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true - }, - "prebuild-install": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", - "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", - "dev": true, - "requires": { - "detect-libc": "^1.0.3", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^2.21.0", - "npmlog": "^4.0.1", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^3.0.3", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "qs": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.2.tgz", - "integrity": "sha512-mSIdjzqznWgfd4pMii7sHtaYF8rx8861hBO80SraY5GT0XQibWZWJSid0avzHGkDIZLImux2S5mXO0Hfct2QCw==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - } - } - }, - "read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "dev": true, - "requires": { - "mute-stream": "~0.0.4" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", - "dev": true, - "requires": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, - "signal-exit": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", - "dev": true - }, - "simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "dev": true - }, - "simple-get": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", - "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", - "dev": true, - "requires": { - "decompress-response": "^4.2.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "table": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.7.2.tgz", - "integrity": "sha512-UFZK67uvyNivLeQbVtkiUs8Uuuxv24aSL4/Vil2PJVtMgU8Lx0CYkP12uCGa3kjyQzOSgV1+z9Wkb82fCGsO0g==", - "dev": true, - "requires": { - "ajv": "^8.0.1", - "lodash.clonedeep": "^4.5.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "ajv": { - "version": "8.6.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.3.tgz", - "integrity": "sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } - } - }, - "tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dev": true, - "requires": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, - "requires": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "typed-rest-client": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.6.tgz", - "integrity": "sha512-xcQpTEAJw2DP7GqVNECh4dD+riS+C1qndXLfBCJ3xk0kqprtGN491P5KlmrDbKdtuW8NEcP/5ChxiJI3S9WYTA==", - "dev": true, - "requires": { - "qs": "^6.9.1", - "tunnel": "0.0.6", - "underscore": "^1.12.1" - } - }, - "typescript": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", - "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", - "dev": true - }, - "typescript-formatter": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/typescript-formatter/-/typescript-formatter-7.2.2.tgz", - "integrity": "sha512-V7vfI9XArVhriOTYHPzMU2WUnm5IMdu9X/CPxs8mIMGxmTBFpDABlbkBka64PZJ9/xgQeRpK8KzzAG4MPzxBDQ==", - "dev": true, - "requires": { - "commandpost": "^1.0.0", - "editorconfig": "^0.15.0" - } - }, - "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "underscore": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", - "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==", - "dev": true - }, - "unzipper": { - "version": "0.10.11", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", - "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", - "dev": true, - "requires": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "vsce": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-2.5.1.tgz", - "integrity": "sha512-vJ+xY93Wv3NhgeriMyIC2oMA+niifOI9XGIqEToIq/rFRoQnXlmO4PSyis/OxBl9hw8OKKC/VcI9CijfFufEkw==", - "dev": true, - "requires": { - "azure-devops-node-api": "^11.0.1", - "chalk": "^2.4.2", - "cheerio": "^1.0.0-rc.9", - "commander": "^6.1.0", - "glob": "^7.0.6", - "hosted-git-info": "^4.0.2", - "keytar": "^7.7.0", - "leven": "^3.1.0", - "markdown-it": "^10.0.0", - "mime": "^1.3.4", - "minimatch": "^3.0.3", - "parse-semver": "^1.1.1", - "read": "^1.0.7", - "semver": "^5.1.0", - "tmp": "^0.2.1", - "typed-rest-client": "^1.8.4", - "url-join": "^4.0.1", - "xml2js": "^0.4.23", - "yauzl": "^2.3.1", - "yazl": "^2.2.2" - }, - "dependencies": { - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "vscode-jsonrpc": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", - "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==" - }, - "vscode-languageclient": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.4.tgz", - "integrity": "sha512-EUOU+bJu6axmt0RFNo3nrglQLPXMfanbYViJee3Fbn2VuQoX0ZOI4uTYhSRvYLP2vfwTP/juV62P/mksCdTZMA==", - "requires": { - "semver": "^6.3.0", - "vscode-languageserver-protocol": "3.15.3" - } - }, - "vscode-languageserver-protocol": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz", - "integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==", - "requires": { - "vscode-jsonrpc": "^5.0.1", - "vscode-languageserver-types": "3.15.1" - } - }, - "vscode-languageserver-types": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz", - "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==" - }, - "vscode-test": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.6.1.tgz", - "integrity": "sha512-086q88T2ca1k95mUzffvbzb7esqQNvJgiwY4h29ukPhFo8u+vXOOmelUoU5EQUHs3Of8+JuQ3oGdbVCqaxuTXA==", - "dev": true, - "requires": { - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "rimraf": "^3.0.2", - "unzipper": "^0.10.11" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "workerpool": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", - "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", - "dev": true, - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - } - }, - "xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - } - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "yazl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", - "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3" - } - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } + "name": "move-analyzer", + "version": "0.0.10", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "move-analyzer", + "version": "0.0.10", + "license": "Apache-2.0", + "dependencies": { + "command-exists": "^1.2.9", + "lru-cache": "^4.1.3", + "vscode-languageclient": "6.1.4" + }, + "devDependencies": { + "@types/command-exists": "^1.2.0", + "@types/fs-extra": "^9.0.13", + "@types/glob": "^7.1.4", + "@types/mocha": "^9.0.0", + "@types/node": "^14.17.22", + "@types/vscode": "^1.58.2", + "@typescript-eslint/eslint-plugin": "^4.33.0", + "@typescript-eslint/parser": "^4.33.0", + "@vscode/test-electron": "^2.0.0", + "copyfiles": "2.4.1", + "cross-env": "^7.0.3", + "eslint": "^7.32.0", + "eslint-plugin-tsdoc": "^0.2.14", + "fs-extra": "10.0.1", + "glob": "^7.1.7", + "mocha": "^9.1.1", + "typescript": "^4.4.4", + "typescript-formatter": "^7.2.2", + "vsce": "^2.5.1", + "vscode-test": "^1.6.1" + }, + "engines": { + "vscode": "^1.58.2" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "dev": true + }, + "node_modules/@microsoft/tsdoc": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.13.2.tgz", + "integrity": "sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg==", + "dev": true + }, + "node_modules/@microsoft/tsdoc-config": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.15.2.tgz", + "integrity": "sha512-mK19b2wJHSdNf8znXSMYVShAHktVr/ib0Ck2FA3lsVBSEhSI/TfXT7DJQkAYgcztTuwazGcg58ZjYdk0hTCVrA==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.13.2", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/command-exists": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/command-exists/-/command-exists-1.2.0.tgz", + "integrity": "sha512-ugsxEJfsCuqMLSuCD4PIJkp5Uk2z6TCMRCgYVuhRo5cYQY3+1xXTQkSlPtkpGHuvWMjS2KTeVQXxkXRACMbM6A==", + "dev": true + }, + "node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true + }, + "node_modules/@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true + }, + "node_modules/@types/mocha": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.0.0.tgz", + "integrity": "sha512-scN0hAWyLVAvLR9AyW7HoFF5sJZglyBsbPuHO4fv7JRvfmPBMfp1ozWqOf/e4wwPNxezBZXRfWzMb6iFLgEVRA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "14.17.27", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.27.tgz", + "integrity": "sha512-94+Ahf9IcaDuJTle/2b+wzvjmutxXAEXU6O81JHblYXUg2BDG+dnBy7VxIPHKAyEEDHzCMQydTJuWvrE+Aanzw==", + "dev": true + }, + "node_modules/@types/vscode": { + "version": "1.61.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.61.0.tgz", + "integrity": "sha512-9k5Nwq45hkRwdfCFY+eKXeQQSbPoA114mF7U/4uJXRBJeGIO7MuJdhF1PnaDN+lllL9iKGQtd6FFXShBXMNaFg==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz", + "integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==", + "dev": true, + "dependencies": { + "@typescript-eslint/experimental-utils": "4.33.0", + "@typescript-eslint/scope-manager": "4.33.0", + "debug": "^4.3.1", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.1.8", + "regexpp": "^3.1.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^4.0.0", + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/experimental-utils": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz", + "integrity": "sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.7", + "@typescript-eslint/scope-manager": "4.33.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/typescript-estree": "4.33.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz", + "integrity": "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "4.33.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/typescript-estree": "4.33.0", + "debug": "^4.3.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", + "integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", + "integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==", + "dev": true, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz", + "integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0", + "debug": "^4.3.1", + "globby": "^11.0.3", + "is-glob": "^4.0.1", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", + "integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "4.33.0", + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "node_modules/@vscode/test-electron": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.1.5.tgz", + "integrity": "sha512-O/ioqFpV+RvKbRykX2ItYPnbcZ4Hk5V0rY4uhQjQTLhGL9WZUvS7exzuYQCCI+ilSqJpctvxq2llTfGXf9UnnA==", + "dev": true, + "dependencies": { + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "rimraf": "^3.0.2", + "unzipper": "^0.10.11" + }, + "engines": { + "node": ">=8.9.3" + } + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/azure-devops-node-api": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.1.0.tgz", + "integrity": "sha512-6/2YZuf+lJzJLrjXNYEA5RXAkMCb8j/4VcHD0qJQRsgG/KsRMYo0HgDh0by1FGHyZkQWY5LmQyJqCwRVUB3Y7Q==", + "dev": true, + "dependencies": { + "tunnel": "0.0.6", + "typed-rest-client": "^1.8.4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/big-integer": { + "version": "1.6.50", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.50.tgz", + "integrity": "sha512-+O2uoQWFRo8ysZNo/rjtri2jIwjr3XfeAgRjAUADRqGG+ZITvyn8J1kvXLTaKVr3hhGXk+f23tKfdzmklVM9vQ==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "dev": true, + "dependencies": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", + "dev": true + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-indexof-polyfill": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", + "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", + "dev": true, + "engines": { + "node": ">=0.2.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", + "dev": true, + "dependencies": { + "traverse": ">=0.3.0 <0.4" + }, + "engines": { + "node": "*" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/chalk/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/chalk/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cheerio": { + "version": "1.0.0-rc.10", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", + "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", + "dev": true, + "dependencies": { + "cheerio-select": "^1.5.0", + "dom-serializer": "^1.3.2", + "domhandler": "^4.2.0", + "htmlparser2": "^6.1.0", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", + "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", + "dev": true, + "dependencies": { + "css-select": "^4.1.3", + "css-what": "^5.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0", + "domutils": "^2.7.0" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cheerio/node_modules/tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "dev": true + }, + "node_modules/chokidar": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/commandpost": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/commandpost/-/commandpost-1.4.0.tgz", + "integrity": "sha512-aE2Y4MTFJ870NuB/+2z1cXBhSBBzRydVVjzhFC4gtenEhpnj15yu0qptWGJsO9YGrcPZ3ezX8AWb1VA391MKpQ==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "node_modules/copyfiles": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-2.4.1.tgz", + "integrity": "sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==", + "dev": true, + "dependencies": { + "glob": "^7.0.5", + "minimatch": "^3.0.3", + "mkdirp": "^1.0.4", + "noms": "0.0.0", + "through2": "^2.0.1", + "untildify": "^4.0.0", + "yargs": "^16.1.0" + }, + "bin": { + "copyfiles": "copyfiles", + "copyup": "copyfiles" + } + }, + "node_modules/copyfiles/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", + "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^5.0.0", + "domhandler": "^4.2.0", + "domutils": "^2.6.0", + "nth-check": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", + "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "dev": true, + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "dev": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-serializer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz", + "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "dev": true, + "dependencies": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" + }, + "bin": { + "editorconfig": "bin/editorconfig" + } + }, + "node_modules/editorconfig/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-tsdoc": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.14.tgz", + "integrity": "sha512-fJ3fnZRsdIoBZgzkQjv8vAj6NeeOoFkTfgosj6mKsFjX70QV256sA/wq+y/R2+OL4L8E79VVaVWrPeZnKNe8Ng==", + "dev": true, + "dependencies": { + "@microsoft/tsdoc": "0.13.2", + "@microsoft/tsdoc-config": "0.15.2" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint/node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/eslint/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", + "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", + "dev": true + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "node_modules/fs-extra": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", + "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + }, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/fstream/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/gauge/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", + "dev": true + }, + "node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", + "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hosted-git-info": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", + "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keytar": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.7.0.tgz", + "integrity": "sha512-YEY9HWqThQc5q5xbXbRwsZTh2PJ36OSYRjSv3NN2xf5s5dpLTjEZnC2YikR29OaVybf9nQ0dJ/80i40RS97t/A==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^3.0.0", + "prebuild-install": "^6.0.0" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dev": true, + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/listenercount": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", + "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", + "dev": true + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/markdown-it": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", + "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "entities": "~2.0.0", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it/node_modules/entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", + "dev": true + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "node_modules/mocha": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.3.tgz", + "integrity": "sha512-Xcpl9FqXOAYqI3j79pEtHBBnQgVXIhpULjGQa7DVb0Po+VzmSIK9kanAiWLHoRR/dbZ2qpdPshuXr8l1VaHCzw==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.2", + "debug": "4.3.2", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.7", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.1.25", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.1.5", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.1.25", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz", + "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "dev": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/node-abi": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", + "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", + "dev": true, + "dependencies": { + "semver": "^5.4.1" + } + }, + "node_modules/node-abi/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true + }, + "node_modules/noms": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/noms/-/noms-0.0.0.tgz", + "integrity": "sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "~1.0.31" + } + }, + "node_modules/noms/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true + }, + "node_modules/noms/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/noms/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/nth-check": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", + "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.1.tgz", + "integrity": "sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-semver": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", + "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", + "dev": true, + "dependencies": { + "semver": "^5.1.0" + } + }, + "node_modules/parse-semver/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dev": true, + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prebuild-install": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", + "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", + "dev": true, + "dependencies": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.21.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.2.tgz", + "integrity": "sha512-mSIdjzqznWgfd4pMii7sHtaYF8rx8861hBO80SraY5GT0XQibWZWJSid0avzHGkDIZLImux2S5mXO0Hfct2QCw==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "dev": true, + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "node_modules/signal-exit": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", + "dev": true + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", + "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "dev": true, + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/table": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.2.tgz", + "integrity": "sha512-UFZK67uvyNivLeQbVtkiUs8Uuuxv24aSL4/Vil2PJVtMgU8Lx0CYkP12uCGa3kjyQzOSgV1+z9Wkb82fCGsO0g==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.6.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.3.tgz", + "integrity": "sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-rest-client": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.6.tgz", + "integrity": "sha512-xcQpTEAJw2DP7GqVNECh4dD+riS+C1qndXLfBCJ3xk0kqprtGN491P5KlmrDbKdtuW8NEcP/5ChxiJI3S9WYTA==", + "dev": true, + "dependencies": { + "qs": "^6.9.1", + "tunnel": "0.0.6", + "underscore": "^1.12.1" + } + }, + "node_modules/typescript": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", + "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/typescript-formatter": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/typescript-formatter/-/typescript-formatter-7.2.2.tgz", + "integrity": "sha512-V7vfI9XArVhriOTYHPzMU2WUnm5IMdu9X/CPxs8mIMGxmTBFpDABlbkBka64PZJ9/xgQeRpK8KzzAG4MPzxBDQ==", + "dev": true, + "dependencies": { + "commandpost": "^1.0.0", + "editorconfig": "^0.15.0" + }, + "bin": { + "tsfmt": "bin/tsfmt" + }, + "engines": { + "node": ">= 4.2.0" + }, + "peerDependencies": { + "typescript": "^2.1.6 || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "node_modules/underscore": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", + "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==", + "dev": true + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/unzipper": { + "version": "0.10.11", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", + "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", + "dev": true, + "dependencies": { + "big-integer": "^1.6.17", + "binary": "~0.3.0", + "bluebird": "~3.4.1", + "buffer-indexof-polyfill": "~1.0.0", + "duplexer2": "~0.1.4", + "fstream": "^1.0.12", + "graceful-fs": "^4.2.2", + "listenercount": "~1.0.1", + "readable-stream": "~2.3.6", + "setimmediate": "~1.0.4" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/vsce": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/vsce/-/vsce-2.5.1.tgz", + "integrity": "sha512-vJ+xY93Wv3NhgeriMyIC2oMA+niifOI9XGIqEToIq/rFRoQnXlmO4PSyis/OxBl9hw8OKKC/VcI9CijfFufEkw==", + "dev": true, + "dependencies": { + "azure-devops-node-api": "^11.0.1", + "chalk": "^2.4.2", + "cheerio": "^1.0.0-rc.9", + "commander": "^6.1.0", + "glob": "^7.0.6", + "hosted-git-info": "^4.0.2", + "keytar": "^7.7.0", + "leven": "^3.1.0", + "markdown-it": "^10.0.0", + "mime": "^1.3.4", + "minimatch": "^3.0.3", + "parse-semver": "^1.1.1", + "read": "^1.0.7", + "semver": "^5.1.0", + "tmp": "^0.2.1", + "typed-rest-client": "^1.8.4", + "url-join": "^4.0.1", + "xml2js": "^0.4.23", + "yauzl": "^2.3.1", + "yazl": "^2.2.2" + }, + "bin": { + "vsce": "vsce" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/vsce/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/vsce/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/vsce/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/vsce/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", + "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==", + "engines": { + "node": ">=8.0.0 || >=10.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.4.tgz", + "integrity": "sha512-EUOU+bJu6axmt0RFNo3nrglQLPXMfanbYViJee3Fbn2VuQoX0ZOI4uTYhSRvYLP2vfwTP/juV62P/mksCdTZMA==", + "dependencies": { + "semver": "^6.3.0", + "vscode-languageserver-protocol": "3.15.3" + }, + "engines": { + "vscode": "^1.41.0" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.15.3", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz", + "integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==", + "dependencies": { + "vscode-jsonrpc": "^5.0.1", + "vscode-languageserver-types": "3.15.1" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz", + "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==" + }, + "node_modules/vscode-test": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.6.1.tgz", + "integrity": "sha512-086q88T2ca1k95mUzffvbzb7esqQNvJgiwY4h29ukPhFo8u+vXOOmelUoU5EQUHs3Of8+JuQ3oGdbVCqaxuTXA==", + "deprecated": "This package has been renamed to @vscode/test-electron, please update to the new name", + "dev": true, + "dependencies": { + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "rimraf": "^3.0.2", + "unzipper": "^0.10.11" + }, + "engines": { + "node": ">=8.9.3" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workerpool": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", + "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dev": true, + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", + "dev": true + }, + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + } + } + }, + "@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + } + } + }, + "@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "dev": true + }, + "@microsoft/tsdoc": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.13.2.tgz", + "integrity": "sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg==", + "dev": true + }, + "@microsoft/tsdoc-config": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.15.2.tgz", + "integrity": "sha512-mK19b2wJHSdNf8znXSMYVShAHktVr/ib0Ck2FA3lsVBSEhSI/TfXT7DJQkAYgcztTuwazGcg58ZjYdk0hTCVrA==", + "dev": true, + "requires": { + "@microsoft/tsdoc": "0.13.2", + "ajv": "~6.12.6", + "jju": "~1.4.0", + "resolve": "~1.19.0" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, + "@types/command-exists": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/command-exists/-/command-exists-1.2.0.tgz", + "integrity": "sha512-ugsxEJfsCuqMLSuCD4PIJkp5Uk2z6TCMRCgYVuhRo5cYQY3+1xXTQkSlPtkpGHuvWMjS2KTeVQXxkXRACMbM6A==", + "dev": true + }, + "@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true + }, + "@types/mocha": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.0.0.tgz", + "integrity": "sha512-scN0hAWyLVAvLR9AyW7HoFF5sJZglyBsbPuHO4fv7JRvfmPBMfp1ozWqOf/e4wwPNxezBZXRfWzMb6iFLgEVRA==", + "dev": true + }, + "@types/node": { + "version": "14.17.27", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.27.tgz", + "integrity": "sha512-94+Ahf9IcaDuJTle/2b+wzvjmutxXAEXU6O81JHblYXUg2BDG+dnBy7VxIPHKAyEEDHzCMQydTJuWvrE+Aanzw==", + "dev": true + }, + "@types/vscode": { + "version": "1.61.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.61.0.tgz", + "integrity": "sha512-9k5Nwq45hkRwdfCFY+eKXeQQSbPoA114mF7U/4uJXRBJeGIO7MuJdhF1PnaDN+lllL9iKGQtd6FFXShBXMNaFg==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz", + "integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "4.33.0", + "@typescript-eslint/scope-manager": "4.33.0", + "debug": "^4.3.1", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.1.8", + "regexpp": "^3.1.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz", + "integrity": "sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.7", + "@typescript-eslint/scope-manager": "4.33.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/typescript-estree": "4.33.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + } + }, + "@typescript-eslint/parser": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz", + "integrity": "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "4.33.0", + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/typescript-estree": "4.33.0", + "debug": "^4.3.1" + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", + "integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0" + } + }, + "@typescript-eslint/types": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", + "integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz", + "integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.33.0", + "@typescript-eslint/visitor-keys": "4.33.0", + "debug": "^4.3.1", + "globby": "^11.0.3", + "is-glob": "^4.0.1", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", + "integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.33.0", + "eslint-visitor-keys": "^2.0.0" + } + }, + "@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "@vscode/test-electron": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.1.5.tgz", + "integrity": "sha512-O/ioqFpV+RvKbRykX2ItYPnbcZ4Hk5V0rY4uhQjQTLhGL9WZUvS7exzuYQCCI+ilSqJpctvxq2llTfGXf9UnnA==", + "dev": true, + "requires": { + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "rimraf": "^3.0.2", + "unzipper": "^0.10.11" + } + }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "azure-devops-node-api": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-11.1.0.tgz", + "integrity": "sha512-6/2YZuf+lJzJLrjXNYEA5RXAkMCb8j/4VcHD0qJQRsgG/KsRMYo0HgDh0by1FGHyZkQWY5LmQyJqCwRVUB3Y7Q==", + "dev": true, + "requires": { + "tunnel": "0.0.6", + "typed-rest-client": "^1.8.4" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, + "big-integer": { + "version": "1.6.50", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.50.tgz", + "integrity": "sha512-+O2uoQWFRo8ysZNo/rjtri2jIwjr3XfeAgRjAUADRqGG+ZITvyn8J1kvXLTaKVr3hhGXk+f23tKfdzmklVM9vQ==", + "dev": true + }, + "binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", + "dev": true, + "requires": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", + "dev": true + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "buffer-indexof-polyfill": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", + "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", + "dev": true + }, + "buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", + "dev": true + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", + "dev": true, + "requires": { + "traverse": ">=0.3.0 <0.4" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "cheerio": { + "version": "1.0.0-rc.10", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", + "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", + "dev": true, + "requires": { + "cheerio-select": "^1.5.0", + "dom-serializer": "^1.3.2", + "domhandler": "^4.2.0", + "htmlparser2": "^6.1.0", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "tslib": "^2.2.0" + }, + "dependencies": { + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "dev": true + } + } + }, + "cheerio-select": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", + "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", + "dev": true, + "requires": { + "css-select": "^4.1.3", + "css-what": "^5.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0", + "domutils": "^2.7.0" + } + }, + "chokidar": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "commandpost": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/commandpost/-/commandpost-1.4.0.tgz", + "integrity": "sha512-aE2Y4MTFJ870NuB/+2z1cXBhSBBzRydVVjzhFC4gtenEhpnj15yu0qptWGJsO9YGrcPZ3ezX8AWb1VA391MKpQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "copyfiles": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-2.4.1.tgz", + "integrity": "sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==", + "dev": true, + "requires": { + "glob": "^7.0.5", + "minimatch": "^3.0.3", + "mkdirp": "^1.0.4", + "noms": "0.0.0", + "through2": "^2.0.1", + "untildify": "^4.0.0", + "yargs": "^16.1.0" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.1" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "css-select": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", + "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^5.0.0", + "domhandler": "^4.2.0", + "domutils": "^2.6.0", + "nth-check": "^2.0.0" + } + }, + "css-what": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", + "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", + "dev": true + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true + }, + "decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "dev": true, + "requires": { + "mimic-response": "^2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "dev": true + }, + "diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-serializer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true + }, + "domhandler": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz", + "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==", + "dev": true, + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "dev": true, + "requires": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "dev": true, + "requires": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "eslint-plugin-tsdoc": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/eslint-plugin-tsdoc/-/eslint-plugin-tsdoc-0.2.14.tgz", + "integrity": "sha512-fJ3fnZRsdIoBZgzkQjv8vAj6NeeOoFkTfgosj6mKsFjX70QV256sA/wq+y/R2+OL4L8E79VVaVWrPeZnKNe8Ng==", + "dev": true, + "requires": { + "@microsoft/tsdoc": "0.13.2", + "@microsoft/tsdoc-config": "0.15.2" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + } + }, + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", + "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", + "dev": true + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "fs-extra": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", + "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", + "dev": true + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", + "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "hosted-git-info": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", + "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-core-module": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha1-o6vicYryQaKykE+EpiWXDzia4yo=", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "keytar": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.7.0.tgz", + "integrity": "sha512-YEY9HWqThQc5q5xbXbRwsZTh2PJ36OSYRjSv3NN2xf5s5dpLTjEZnC2YikR29OaVybf9nQ0dJ/80i40RS97t/A==", + "dev": true, + "requires": { + "node-addon-api": "^3.0.0", + "prebuild-install": "^6.0.0" + } + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, + "listenercount": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", + "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=", + "dev": true + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "markdown-it": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", + "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "entities": "~2.0.0", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "dependencies": { + "entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", + "dev": true + } + } + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "mocha": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.3.tgz", + "integrity": "sha512-Xcpl9FqXOAYqI3j79pEtHBBnQgVXIhpULjGQa7DVb0Po+VzmSIK9kanAiWLHoRR/dbZ2qpdPshuXr8l1VaHCzw==", + "dev": true, + "requires": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.2", + "debug": "4.3.2", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.7", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.1.25", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.1.5", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "nanoid": { + "version": "3.1.25", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz", + "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", + "dev": true + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node-abi": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", + "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", + "dev": true, + "requires": { + "semver": "^5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true + }, + "noms": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/noms/-/noms-0.0.0.tgz", + "integrity": "sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "~1.0.31" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "dev": true + } + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "nth-check": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", + "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "dev": true, + "requires": { + "boolbase": "^1.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-inspect": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.1.tgz", + "integrity": "sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-semver": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", + "integrity": "sha1-mkr9bfBj3Egm+T+6SpnPIj9mbLg=", + "dev": true, + "requires": { + "semver": "^5.1.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dev": true, + "requires": { + "parse5": "^6.0.1" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true + }, + "prebuild-install": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", + "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", + "dev": true, + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.21.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qs": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.2.tgz", + "integrity": "sha512-mSIdjzqznWgfd4pMii7sHtaYF8rx8861hBO80SraY5GT0XQibWZWJSid0avzHGkDIZLImux2S5mXO0Hfct2QCw==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + } + } + }, + "read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "dev": true, + "requires": { + "mute-stream": "~0.0.4" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "requires": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==", + "dev": true + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true + }, + "simple-get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", + "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "dev": true, + "requires": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.2.tgz", + "integrity": "sha512-UFZK67uvyNivLeQbVtkiUs8Uuuxv24aSL4/Vil2PJVtMgU8Lx0CYkP12uCGa3kjyQzOSgV1+z9Wkb82fCGsO0g==", + "dev": true, + "requires": { + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ajv": { + "version": "8.6.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.3.tgz", + "integrity": "sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", + "dev": true + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "typed-rest-client": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.6.tgz", + "integrity": "sha512-xcQpTEAJw2DP7GqVNECh4dD+riS+C1qndXLfBCJ3xk0kqprtGN491P5KlmrDbKdtuW8NEcP/5ChxiJI3S9WYTA==", + "dev": true, + "requires": { + "qs": "^6.9.1", + "tunnel": "0.0.6", + "underscore": "^1.12.1" + } + }, + "typescript": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", + "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", + "dev": true + }, + "typescript-formatter": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/typescript-formatter/-/typescript-formatter-7.2.2.tgz", + "integrity": "sha512-V7vfI9XArVhriOTYHPzMU2WUnm5IMdu9X/CPxs8mIMGxmTBFpDABlbkBka64PZJ9/xgQeRpK8KzzAG4MPzxBDQ==", + "dev": true, + "requires": { + "commandpost": "^1.0.0", + "editorconfig": "^0.15.0" + } + }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "underscore": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", + "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==", + "dev": true + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true + }, + "unzipper": { + "version": "0.10.11", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", + "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", + "dev": true, + "requires": { + "big-integer": "^1.6.17", + "binary": "~0.3.0", + "bluebird": "~3.4.1", + "buffer-indexof-polyfill": "~1.0.0", + "duplexer2": "~0.1.4", + "fstream": "^1.0.12", + "graceful-fs": "^4.2.2", + "listenercount": "~1.0.1", + "readable-stream": "~2.3.6", + "setimmediate": "~1.0.4" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "vsce": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/vsce/-/vsce-2.5.1.tgz", + "integrity": "sha512-vJ+xY93Wv3NhgeriMyIC2oMA+niifOI9XGIqEToIq/rFRoQnXlmO4PSyis/OxBl9hw8OKKC/VcI9CijfFufEkw==", + "dev": true, + "requires": { + "azure-devops-node-api": "^11.0.1", + "chalk": "^2.4.2", + "cheerio": "^1.0.0-rc.9", + "commander": "^6.1.0", + "glob": "^7.0.6", + "hosted-git-info": "^4.0.2", + "keytar": "^7.7.0", + "leven": "^3.1.0", + "markdown-it": "^10.0.0", + "mime": "^1.3.4", + "minimatch": "^3.0.3", + "parse-semver": "^1.1.1", + "read": "^1.0.7", + "semver": "^5.1.0", + "tmp": "^0.2.1", + "typed-rest-client": "^1.8.4", + "url-join": "^4.0.1", + "xml2js": "^0.4.23", + "yauzl": "^2.3.1", + "yazl": "^2.2.2" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "vscode-jsonrpc": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz", + "integrity": "sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==" + }, + "vscode-languageclient": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.1.4.tgz", + "integrity": "sha512-EUOU+bJu6axmt0RFNo3nrglQLPXMfanbYViJee3Fbn2VuQoX0ZOI4uTYhSRvYLP2vfwTP/juV62P/mksCdTZMA==", + "requires": { + "semver": "^6.3.0", + "vscode-languageserver-protocol": "3.15.3" + } + }, + "vscode-languageserver-protocol": { + "version": "3.15.3", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz", + "integrity": "sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==", + "requires": { + "vscode-jsonrpc": "^5.0.1", + "vscode-languageserver-types": "3.15.1" + } + }, + "vscode-languageserver-types": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz", + "integrity": "sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==" + }, + "vscode-test": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.6.1.tgz", + "integrity": "sha512-086q88T2ca1k95mUzffvbzb7esqQNvJgiwY4h29ukPhFo8u+vXOOmelUoU5EQUHs3Of8+JuQ3oGdbVCqaxuTXA==", + "dev": true, + "requires": { + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "rimraf": "^3.0.2", + "unzipper": "^0.10.11" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "workerpool": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", + "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dev": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true + }, + "yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "requires": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + } + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3" + } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } } diff --git a/language/move-analyzer/editors/code/package.json b/language/move-analyzer/editors/code/package.json index 7ee536c720..9e54615e57 100644 --- a/language/move-analyzer/editors/code/package.json +++ b/language/move-analyzer/editors/code/package.json @@ -3,8 +3,9 @@ "displayName": "move-analyzer", "description": "A language server and basic grammar for the Move programming language.", "publisher": "move", + "icon": "images/move.png", "license": "Apache-2.0", - "version": "0.0.7", + "version": "0.0.10", "preview": true, "homepage": "https://github.com/move-language/move", "repository": { @@ -25,7 +26,8 @@ ], "main": "./out/src/main.js", "activationEvents": [ - "onLanguage:move" + "onLanguage:move", + "workspaceContains:Move.toml" ], "contributes": { "commands": [ @@ -84,14 +86,16 @@ } }, "scripts": { - "compile": "tsc -p ./", + "compile": "tsc -p ./ && cd ../../ && cargo build", "watch": "tsc -watch -p ./", - "lint": "tsfmt --verify && eslint . --ext ts --max-warnings 0", - "fix": "tsfmt --replace && eslint . --ext ts --fix", - "pretest": "npm run compile && npm run lint", + "lint": "eslint . --ext ts --max-warnings 0", + "fix": "eslint . --ext ts --fix", + "copy-tests-files": "copyfiles \"tests/**/*.move\" \"tests/**/*.exp\" \"tests/**/*.toml\" \"tests/**/*.code-workspace\" out", + "pretest": "npm run compile && npm run lint && npm run copy-tests-files", "test": "node ./out/tests/runTests.js", + "dev": "npm run pretest && cross-env mode=dev node ./out/tests/runTests.js", "vscode:prepublish": "npm run pretest", - "package": "vsce package -o move-analyzer.vsix", + "package": "npm run pretest && vsce package -o move-analyzer.vsix", "publish": "npm run pretest && npm run test && vsce publish" }, "extensionDependencies": [ @@ -99,19 +103,24 @@ ], "dependencies": { "command-exists": "^1.2.9", - "vscode-languageclient": "6.1.4" + "vscode-languageclient": "6.1.4", + "lru-cache": "^4.1.3" }, "devDependencies": { "@types/command-exists": "^1.2.0", + "@types/fs-extra": "^9.0.13", "@types/glob": "^7.1.4", "@types/mocha": "^9.0.0", "@types/node": "^14.17.22", "@types/vscode": "^1.58.2", "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.33.0", - "@vscode/test-electron": "^1.6.1", + "@vscode/test-electron": "^2.0.0", + "copyfiles": "2.4.1", + "cross-env": "^7.0.3", "eslint": "^7.32.0", "eslint-plugin-tsdoc": "^0.2.14", + "fs-extra": "10.0.1", "glob": "^7.1.7", "mocha": "^9.1.1", "typescript": "^4.4.4", diff --git a/language/move-analyzer/editors/code/src/commands/index.ts b/language/move-analyzer/editors/code/src/commands/index.ts new file mode 100644 index 0000000000..71d5f7fdfb --- /dev/null +++ b/language/move-analyzer/editors/code/src/commands/index.ts @@ -0,0 +1 @@ +export * from './lsp_command'; diff --git a/language/move-analyzer/editors/code/src/commands/lsp_command.ts b/language/move-analyzer/editors/code/src/commands/lsp_command.ts new file mode 100644 index 0000000000..157551759a --- /dev/null +++ b/language/move-analyzer/editors/code/src/commands/lsp_command.ts @@ -0,0 +1,60 @@ +import type { + DocumentSymbolParams, + SymbolInformation, + DocumentSymbol, + CompletionParams, + CompletionList, + CompletionItem, +} from 'vscode-languageclient'; +import { DocumentSymbolRequest, HoverRequest, CompletionRequest } from 'vscode-languageclient'; +import type { Context } from '../context'; + +/** + * An LSP command textDocument/documentSymbol + */ +export async function textDocumentDocumentSymbol( + context: Readonly, + params: DocumentSymbolParams, +): Promise { + const client = context.getClient(); + if (client === undefined) { + return Promise.reject(new Error('No language client connected.')); + } + + // Send the request to the language client. + return client.sendRequest(DocumentSymbolRequest.type, params); +} + +/** + * An LSP command textDocument/completion + */ +export async function textDocumentCompletion( + context: Readonly, + params: CompletionParams, +): Promise { + const client = context.getClient(); + if (client === undefined) { + return Promise.reject(new Error('No language client connected.')); + } + + // Send the request to the language client. + return client.sendRequest(CompletionRequest.type, params); +} + + +/** + * An LSP command textDocument/hover + */ +export async function textDocumentHover( + context: Readonly, + params: DocumentSymbolParams, +) + : Promise { + const client = context.getClient(); + if (client === undefined) { + return Promise.reject(new Error('No language client connected.')); + } + + // Send the request to the language client. + return client.sendRequest(HoverRequest.method, params); +} diff --git a/language/move-analyzer/editors/code/src/configuration.ts b/language/move-analyzer/editors/code/src/configuration.ts index 8c37429975..595a791cf5 100644 --- a/language/move-analyzer/editors/code/src/configuration.ts +++ b/language/move-analyzer/editors/code/src/configuration.ts @@ -4,6 +4,7 @@ import * as os from 'os'; import * as vscode from 'vscode'; +import * as Path from 'path'; /** * User-defined configuration values, such as those specified in VS Code settings. @@ -26,16 +27,28 @@ export class Configuration { /** The path to the move-analyzer executable. */ get serverPath(): string { const defaultName = 'move-analyzer'; - const path = this.configuration.get('server.path', defaultName); - if (path.length === 0) { + let serverPath = this.configuration.get('server.path', defaultName); + if (serverPath.length === 0) { // The default value of the `server.path` setting is 'move-analyzer'. // A user may have over-written this default with an empty string value, ''. // An empty string cannot be an executable name, so instead use the default. return defaultName; } - if (path.startsWith('~/')) { - return os.homedir() + path.slice('~'.length); + + if (serverPath === defaultName) { + // If the program set by the user is through PATH, + // it will return directly if specified + return defaultName; + } + + if (serverPath.startsWith('~/')) { + serverPath = os.homedir() + serverPath.slice('~'.length); } - return path; + + if (process.platform === 'win32' && !serverPath.endsWith('.exe')) { + serverPath = serverPath + '.exe'; + } + + return Path.resolve(serverPath); } } diff --git a/language/move-analyzer/editors/code/src/context.ts b/language/move-analyzer/editors/code/src/context.ts index c962040772..2f894923b8 100644 --- a/language/move-analyzer/editors/code/src/context.ts +++ b/language/move-analyzer/editors/code/src/context.ts @@ -7,13 +7,19 @@ import * as vscode from 'vscode'; import * as lc from 'vscode-languageclient'; import { log } from './log'; import { sync as commandExistsSync } from 'command-exists'; +import { IndentAction } from 'vscode'; /** Information passed along to each VS Code command defined by this extension. */ export class Context { + private client: lc.LanguageClient | undefined; + private constructor( private readonly extensionContext: Readonly, readonly configuration: Readonly, - ) { } + client: lc.LanguageClient | undefined = undefined, + ) { + this.client = client; + } static create( extensionContext: Readonly, @@ -39,11 +45,44 @@ export class Context { */ registerCommand( name: Readonly, - command: (context: Readonly) => Promise, + command: (context: Readonly, ...args: Array) => any, ): void { - const disposable = vscode.commands.registerCommand(`move-analyzer.${name}`, async () => { - const com = await command(this); - return com; + const disposable = vscode.commands.registerCommand( + `move-analyzer.${name}`, + async (...args: Array) : Promise => { + const ret = await command(this, ...args); + return ret; + }, + ); + + this.extensionContext.subscriptions.push(disposable); + } + + /** + * Sets up additional language configuration that's impossible to do via a + * separate language-configuration.json file. See [1] for more information. + * + * This code originates from [2](vscode-rust). + * + * [1]: https://github.com/Microsoft/vscode/issues/11514#issuecomment-244707076 + * [2]: https://github.com/rust-lang/vscode-rust/blob/660b412701fe2ea62fad180c40ee4f8a60571c61/src/extension.ts#L287:L287 + */ + configureLanguage(): void { + const disposable = vscode.languages.setLanguageConfiguration('move', { + onEnterRules: [ + { + // Doc single-line comment + // e.g. ///| + beforeText: /^\s*\/{3}.*$/, + action: { indentAction: IndentAction.None, appendText: '/// ' }, + }, + { + // Parent doc single-line comment + // e.g. //!| + beforeText: /^\s*\/{2}!.*$/, + action: { indentAction: IndentAction.None, appendText: '//! ' }, + }, + ], }); this.extensionContext.subscriptions.push(disposable); } @@ -59,8 +98,11 @@ export class Context { * * To read more about the messages sent and responses received by this client, such as * "initialize," read [the Language Server Protocol specification](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#initialize). + * + * In order to synchronously wait for the client to be completely ready, + * we need to mark the function as asynchronous **/ - startClient(): void { + async startClient(): Promise { const executable: lc.Executable = { command: this.configuration.serverPath, }; @@ -92,5 +134,19 @@ export class Context { log.info('Starting client...'); const disposable = client.start(); this.extensionContext.subscriptions.push(disposable); + this.client = client; + + // Wait for the Move Language Server initialization to complete, + // especially the first symbol table parsing is completed + await this.client.onReady(); + } + + /** + * Returns the client that this extension interacts with. + * + * @returns lc.LanguageClient + */ + getClient(): lc.LanguageClient | undefined { + return this.client; } -} +} // Context diff --git a/language/move-analyzer/editors/code/src/main.ts b/language/move-analyzer/editors/code/src/main.ts index 169bc9b2d1..64981a2263 100644 --- a/language/move-analyzer/editors/code/src/main.ts +++ b/language/move-analyzer/editors/code/src/main.ts @@ -6,8 +6,11 @@ import { Configuration } from './configuration'; import { Context } from './context'; import { Extension } from './extension'; import { log } from './log'; + import * as childProcess from 'child_process'; import * as vscode from 'vscode'; +import * as commands from './commands'; + /** * An extension command that displays the version of the server that this extension @@ -40,8 +43,11 @@ async function serverVersion(context: Readonly): Promise { * * Activation events for this extension are listed in its `package.json` file, under the key * `"activationEvents"`. + * + * In order to achieve synchronous activation, mark the function as an asynchronous function, + * so that you can wait for the activation to complete by await */ -export function activate(extensionContext: Readonly): void { +export async function activate(extensionContext: Readonly): Promise { const extension = new Extension(); log.info(`${extension.identifier} version ${extension.version}`); @@ -62,6 +68,12 @@ export function activate(extensionContext: Readonly): v // Register handlers for VS Code commands that the user explicitly issues. context.registerCommand('serverVersion', serverVersion); + // Configure other language features. + context.configureLanguage(); + // All other utilities provided by this extension occur via the language server. - context.startClient(); + await context.startClient(); + context.registerCommand('textDocumentDocumentSymbol', commands.textDocumentDocumentSymbol); + context.registerCommand('textDocumentHover', commands.textDocumentHover); + context.registerCommand('textDocumentCompletion', commands.textDocumentCompletion); } diff --git a/language/move-analyzer/editors/code/tests/index.ts b/language/move-analyzer/editors/code/tests/index.ts index 8b7cd74b5a..1660a4dc49 100644 --- a/language/move-analyzer/editors/code/tests/index.ts +++ b/language/move-analyzer/editors/code/tests/index.ts @@ -14,13 +14,21 @@ import * as path from 'path'; /* eslint-disable */ // deno-lint-ignore require-await export async function run(): Promise { + // dev mode + const mode = process.env['mode'] || 'test'; + if (mode === 'dev') { + return new Promise((resolve) => { + setTimeout(resolve, 1000 * 60 * 15); // Development mode, set a timeout of 15 minutes + }); + } + /* eslint-disable */ const suite = new Mocha({ ui: 'tdd', color: true, // The default timeout of 2000 miliseconds can sometimes be too quick, since the extension // tests need to launch VS Code first. - timeout: 5000, + timeout: 10000, }); const testsRoot = path.resolve(__dirname, '..'); diff --git a/language/move-analyzer/editors/code/tests/lsp-demo/Move.toml b/language/move-analyzer/editors/code/tests/lsp-demo/Move.toml new file mode 100644 index 0000000000..47ddc67395 --- /dev/null +++ b/language/move-analyzer/editors/code/tests/lsp-demo/Move.toml @@ -0,0 +1,9 @@ +[package] +name = "Symbols" +version = "0.0.1" + +[dependencies] +MoveStdlib = { local = "../../../../../../move-stdlib/", addr_subst = { "std" = "0x1" } } + +[addresses] +Symbols = "0xCAFE" diff --git a/language/move-analyzer/editors/code/tests/lsp-demo/lsp-demo-win.code-workspace b/language/move-analyzer/editors/code/tests/lsp-demo/lsp-demo-win.code-workspace new file mode 100644 index 0000000000..4651fb61d0 --- /dev/null +++ b/language/move-analyzer/editors/code/tests/lsp-demo/lsp-demo-win.code-workspace @@ -0,0 +1,10 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": { + "move-analyzer.server.path": "../../../../../../target/debug/move-analyzer" + } +} diff --git a/language/move-analyzer/editors/code/tests/lsp-demo/lsp-demo.code-workspace b/language/move-analyzer/editors/code/tests/lsp-demo/lsp-demo.code-workspace new file mode 100644 index 0000000000..087aded48f --- /dev/null +++ b/language/move-analyzer/editors/code/tests/lsp-demo/lsp-demo.code-workspace @@ -0,0 +1,10 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": { + "move-analyzer.server.path": "../../../../target/debug/move-analyzer" + } +} diff --git a/language/move-analyzer/editors/code/tests/lsp-demo/sources/Completions.move b/language/move-analyzer/editors/code/tests/lsp-demo/sources/Completions.move new file mode 100644 index 0000000000..b0ff2df28f --- /dev/null +++ b/language/move-analyzer/editors/code/tests/lsp-demo/sources/Completions.move @@ -0,0 +1,13 @@ +module Symbols::Completions { + fun add(a: u64, b: u64): u64 { + a + b + } + + fun subtract(a: u64, b: u64): u64 { + a - b + } + + fun divide(a: u64, b: u64): u64 { + a / b + } +} diff --git a/language/move-analyzer/editors/code/tests/lsp-demo/sources/M1.move b/language/move-analyzer/editors/code/tests/lsp-demo/sources/M1.move new file mode 100644 index 0000000000..d1454454b6 --- /dev/null +++ b/language/move-analyzer/editors/code/tests/lsp-demo/sources/M1.move @@ -0,0 +1,18 @@ +module Symbols::M1 { + + const SOME_CONST: u64 = 42; + + struct SomeOtherStruct has drop { + some_field: u64, + } + + public fun some_other_struct(v: u64): SomeOtherStruct { + SomeOtherStruct { some_field: v } + } + + #[test] + #[expected_failure] + fun this_is_a_test() { + 1/0; + } +} diff --git a/language/move-analyzer/editors/code/tests/lsp-demo/sources/M2.move b/language/move-analyzer/editors/code/tests/lsp-demo/sources/M2.move new file mode 100644 index 0000000000..4d00f275e7 --- /dev/null +++ b/language/move-analyzer/editors/code/tests/lsp-demo/sources/M2.move @@ -0,0 +1,22 @@ +module Symbols::M2 { + + /// Constant containing the answer to the universe + const DOCUMENTED_CONSTANT: u64 = 42; + + /** + This is a multiline docstring + + This docstring has empty lines. + + It uses the ** format instead of /// + */ + fun other_doc_struct(): Symbols::M3::OtherDocStruct { + Symbols::M3::create_other_struct(DOCUMENTED_CONSTANT) + } + + use Symbols::M3::{Self, OtherDocStruct}; + + fun other_doc_struct_import(): OtherDocStruct { + M3::create_other_struct(7) + } +} diff --git a/language/move-analyzer/editors/code/tests/lsp-demo/sources/M3.move b/language/move-analyzer/editors/code/tests/lsp-demo/sources/M3.move new file mode 100644 index 0000000000..1fd363e82e --- /dev/null +++ b/language/move-analyzer/editors/code/tests/lsp-demo/sources/M3.move @@ -0,0 +1,12 @@ +module Symbols::M3 { + + /// Documented struct in another module + struct OtherDocStruct has drop { + some_field: u64, + } + + /// Documented initializer in another module + public fun create_other_struct(v: u64): OtherDocStruct { + OtherDocStruct { some_field: v } + } +} diff --git a/language/move-analyzer/editors/code/tests/lsp.test.ts b/language/move-analyzer/editors/code/tests/lsp.test.ts new file mode 100644 index 0000000000..c07e29730f --- /dev/null +++ b/language/move-analyzer/editors/code/tests/lsp.test.ts @@ -0,0 +1,218 @@ +import * as assert from 'assert'; +import * as Mocha from 'mocha'; +import * as path from 'path'; +import * as vscode from 'vscode'; +import * as lc from 'vscode-languageclient'; +import type { MarkupContent } from 'vscode-languageclient'; +import { CompletionItemKind } from 'vscode-languageclient'; + +const isFunctionInCompletionItems = (fnName: string, items: vscode.CompletionItem[]): boolean => { + return ( + items.find((item) => item.label === fnName && item.kind === CompletionItemKind.Function) !== + undefined + ); +}; + +const isKeywordInCompletionItems = (label: string, items: vscode.CompletionItem[]): boolean => { + return ( + items.find((item) => item.label === label && item.kind === CompletionItemKind.Keyword) !== + undefined + ); +}; + +const PRIMITIVE_TYPES = ['u8', 'u16', 'u32', 'u64', 'u128', 'u256', 'bool', 'vector']; + +Mocha.suite('LSP', () => { + Mocha.test('textDocument/documentSymbol', async () => { + const ext = vscode.extensions.getExtension('move.move-analyzer'); + assert.ok(ext); + + await ext.activate(); // Synchronous waiting for activation to complete + + // 1. get workdir + const workDir = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath ?? ''; + + // 2. open doc + const docs = await vscode.workspace.openTextDocument(path.join(workDir, 'sources/M1.move')); + await vscode.window.showTextDocument(docs); + + // 3. execute command + const params: lc.DocumentSymbolParams = { + textDocument: { + uri: docs.uri.toString(), + }, + }; + + const syms: Array | undefined = await + vscode.commands.executeCommand( + 'move-analyzer.textDocumentDocumentSymbol', params, + ); + + assert.ok(syms); + assert.deepStrictEqual(syms[0]?.kind, lc.SymbolKind.Module); + assert.deepStrictEqual(syms[0].name, 'M1'); + + assert.ok(syms[0].children); + assert.deepStrictEqual(syms[0]?.children[0]?.kind, lc.SymbolKind.Constant); + assert.deepStrictEqual(syms[0]?.children[0].name, 'SOME_CONST'); + assert.deepStrictEqual(syms[0]?.children[1]?.kind, lc.SymbolKind.Struct); + assert.deepStrictEqual(syms[0]?.children[1].name, 'SomeOtherStruct'); + assert.ok(syms[0].children[1].children); + assert.deepStrictEqual(syms[0]?.children[1]?.children[0]?.kind, lc.SymbolKind.Field); + assert.deepStrictEqual(syms[0]?.children[1]?.children[0]?.name, 'some_field'); + assert.deepStrictEqual(syms[0]?.children[1].name, 'SomeOtherStruct'); + assert.deepStrictEqual(syms[0]?.children[2]?.kind, lc.SymbolKind.Function); + assert.deepStrictEqual(syms[0]?.children[2].name, 'some_other_struct'); + assert.deepStrictEqual(syms[0]?.children[3]?.kind, lc.SymbolKind.Function); + assert.deepStrictEqual(syms[0]?.children[3].name, 'this_is_a_test'); + assert.deepStrictEqual(syms[0]?.children[3]?.detail, '["test", "expected_failure"]'); + }); + + Mocha.test('textDocument/hover for definition in the same module', async () => { + const ext = vscode.extensions.getExtension('move.move-analyzer'); + assert.ok(ext); + + await ext.activate(); // Synchronous waiting for activation to complete + + // 1. get workdir + const workDir = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath ?? ''; + + // 2. open doc + const docs = await vscode.workspace.openTextDocument( + path.join(workDir, 'sources/M2.move'), + ); + await vscode.window.showTextDocument(docs); + + // 3. execute command + const params: lc.HoverParams = { + textDocument: { + uri: docs.uri.toString(), + }, + position: { + line: 12, + character: 8, + }, + }; + + const hoverResult: lc.Hover | undefined = + await vscode.commands.executeCommand( + 'move-analyzer.textDocumentHover', + params, + ); + + assert.ok(hoverResult); + assert.deepStrictEqual((hoverResult.contents as MarkupContent).value, + // eslint-disable-next-line max-len + 'fun Symbols::M2::other_doc_struct(): Symbols::M3::OtherDocStruct\n\n\nThis is a multiline docstring\n\nThis docstring has empty lines.\n\nIt uses the ** format instead of ///\n\n'); + + }); + + Mocha.test('textDocument/hover for definition in an external module', async () => { + const ext = vscode.extensions.getExtension('move.move-analyzer'); + assert.ok(ext); + + await ext.activate(); // Synchronous waiting for activation to complete + + // 1. get workdir + const workDir = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath ?? ''; + + // 2. open doc + const docs = await vscode.workspace.openTextDocument( + path.join(workDir, 'sources/M2.move'), + ); + await vscode.window.showTextDocument(docs); + + // 3. execute command + const params: lc.HoverParams = { + textDocument: { + uri: docs.uri.toString(), + }, + position: { + line: 18, + character: 35, + }, + }; + + const hoverResult: lc.Hover | undefined = + await vscode.commands.executeCommand( + 'move-analyzer.textDocumentHover', + params, + ); + + + assert.ok(hoverResult); + assert.deepStrictEqual((hoverResult.contents as MarkupContent).value, + 'Symbols::M3::OtherDocStruct\n\nDocumented struct in another module\n'); + }); + + Mocha.test('textDocument/completion', async () => { + const ext = vscode.extensions.getExtension('move.move-analyzer'); + assert.ok(ext); + + await ext.activate(); // Synchronous waiting for activation to complete + + // 1. get workdir + const workDir = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath ?? ''; + + // 2. open doc + const docs = await vscode.workspace.openTextDocument( + path.join(workDir, 'sources/Completions.move'), + ); + await vscode.window.showTextDocument(docs); + + // 3. execute command + const params: lc.CompletionParams = { + textDocument: { + uri: docs.uri.toString(), + }, + position: { + line: 12, + character: 1, + }, + }; + + const items = await vscode.commands.executeCommand>( + 'move-analyzer.textDocumentCompletion', + params, + ); + + assert.ok(items); + + // Items should return all functions defined in the file + assert.strictEqual(isFunctionInCompletionItems('add', items), true); + assert.strictEqual(isFunctionInCompletionItems('subtract', items), true); + assert.strictEqual(isFunctionInCompletionItems('divide', items), true); + + // Items also include all primitive types because they are keywords + PRIMITIVE_TYPES.forEach((primitive) => { + assert.strictEqual(isKeywordInCompletionItems(primitive, items), true); + }); + + const colonParams: lc.CompletionParams = { + textDocument: { + uri: docs.uri.toString(), + }, + // The position of the character ":" + position: { + line: 9, + character: 15, + }, + }; + + const itemsOnColon = await vscode.commands.executeCommand>( + 'move-analyzer.textDocumentCompletion', + colonParams, + ); + + assert.ok(itemsOnColon); + + const keywordsOnColon = itemsOnColon.filter(i => i.kind === CompletionItemKind.Keyword); + // Primitive types are the only keywords returned after inserting the colon + assert.strictEqual(keywordsOnColon.length, PRIMITIVE_TYPES.length); + + // Final safety check + PRIMITIVE_TYPES.forEach((primitive) => { + assert.strictEqual(isKeywordInCompletionItems(primitive, keywordsOnColon), true); + }); + }); +}); diff --git a/language/move-analyzer/editors/code/tests/runTests.ts b/language/move-analyzer/editors/code/tests/runTests.ts index 5bb578e7a4..a8cd46f285 100644 --- a/language/move-analyzer/editors/code/tests/runTests.ts +++ b/language/move-analyzer/editors/code/tests/runTests.ts @@ -9,8 +9,16 @@ * https://code.visualstudio.com/api/working-with-extensions/testing-extension#the-test-script */ +import * as os from 'os'; import * as path from 'path'; -import { runTests } from '@vscode/test-electron'; +import * as cp from 'child_process'; +import * as fs from 'fs'; +import * as fse from 'fs-extra'; +import { + runTests, + downloadAndUnzipVSCode, + resolveCliArgsFromVSCodeExecutablePath, +} from '@vscode/test-electron'; /** * Launches a VS Code instance to run tests. @@ -18,7 +26,7 @@ import { runTests } from '@vscode/test-electron'; * This is essentially a TypeScript program that executes the "VS Code Tokenizer Tests" launch * target defined in this repository's `.vscode/launch.json`. */ -async function main(): Promise { +async function runVSCodeTest(vscodeVersion: string): Promise { try { // The `--extensionDevelopmentPath` argument passed to VS Code. This should point to the // directory that contains the extension manifest file, `package.json`. @@ -28,12 +36,45 @@ async function main(): Promise { // program that is considered to be the "test suite" for the extension. const extensionTestsPath = path.resolve(__dirname, 'index.js'); + // The workspace + let testWorkspacePath = path.resolve(__dirname, './lsp-demo/lsp-demo.code-workspace'); + if (process.platform === 'win32') { + testWorkspacePath = path.resolve(__dirname, './lsp-demo/lsp-demo-win.code-workspace'); + } + + // Install vscode and depends extension + const vscodeExecutablePath = await downloadAndUnzipVSCode(vscodeVersion); + const [cli, ...args] = resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath); + const newCli = cli ?? 'code'; + cp.spawnSync(newCli, [...args, '--install-extension', 'damirka.move-syntax', '--force'], { + encoding: 'utf-8', + stdio: 'inherit', + }); + + // Because the default vscode userDataDir is too long, + // v1.69.2 will report an error when running test. + // So generate a short + const userDataDir = path.join(os.tmpdir(), 'vscode-test', vscodeVersion); + if (!fs.existsSync(userDataDir)) { + fse.mkdirsSync(userDataDir); + } + // Download VS Code, unzip it, and run the "test suite" program. - await runTests({ extensionDevelopmentPath, extensionTestsPath }); + await runTests({ + vscodeExecutablePath: vscodeExecutablePath, + extensionDevelopmentPath, + extensionTestsPath, + launchArgs: [testWorkspacePath, '--user-data-dir', userDataDir], + }); } catch (_err: unknown) { console.error('Failed to run tests'); process.exit(1); } } +async function main(): Promise { + await runVSCodeTest('1.64.0'); // Test with vscode v1.64.0 + await runVSCodeTest('1.69.2'); // Test with vscode v1.69.2 +} + void main(); diff --git a/language/move-analyzer/editors/code/types/vscode-test-electron.d.ts b/language/move-analyzer/editors/code/types/vscode-test-electron.d.ts deleted file mode 100644 index e325fbf6ab..0000000000 --- a/language/move-analyzer/editors/code/types/vscode-test-electron.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -// FIXME: The vscode-test `runTests` function is implemented in TypeScript and has type annotations: -// https://github.com/microsoft/vscode-test/blob/v1.6.1/lib/runTest.ts#L86 -// But I don't know where, if anywhere, those types are published, so to appease the TypeScript -// compiler's type-checker, I declare the function type in this file. -declare module '@vscode/test-electron' { - export interface TestOptions { - extensionDevelopmentPath?: string; - extensionTestsPath?: string; - // N.B.: vscode-test's definition of `TestOptions` contains many more fields: - // https://github.com/microsoft/vscode-test/blob/v1.6.1/lib/runTest.ts#L9-L79 - } - - export function runTests(options: TestOptions): Thenable; -} diff --git a/language/move-analyzer/src/bin/move-analyzer.rs b/language/move-analyzer/src/bin/move-analyzer.rs index 4943a6e804..d99f6032f0 100644 --- a/language/move-analyzer/src/bin/move-analyzer.rs +++ b/language/move-analyzer/src/bin/move-analyzer.rs @@ -15,6 +15,7 @@ use std::{ collections::BTreeMap, path::Path, sync::{Arc, Mutex}, + thread, }; use move_analyzer::{ @@ -27,7 +28,7 @@ use move_symbol_pool::Symbol; use url::Url; #[derive(Parser)] -#[clap(author, version = "1.0.0", about)] +#[clap(author, version, about)] struct Options {} fn main() { @@ -48,11 +49,18 @@ fn main() { ); let (connection, io_threads) = Connection::stdio(); + let symbols = Arc::new(Mutex::new(symbols::Symbolicator::empty_symbols())); let mut context = Context { connection, files: VirtualFileSystem::default(), - symbols: Arc::new(Mutex::new(symbols::Symbolicator::empty_symbols())), + symbols: symbols.clone(), }; + + let (id, client_response) = context + .connection + .initialize_start() + .expect("could not start connection initialization"); + let capabilities = serde_json::to_value(lsp_types::ServerCapabilities { // The server receives notifications from the client as users open, close, // and modify documents. @@ -98,22 +106,56 @@ fn main() { symbols::DEFS_AND_REFS_SUPPORT, )), references_provider: Some(OneOf::Left(symbols::DEFS_AND_REFS_SUPPORT)), + document_symbol_provider: Some(OneOf::Left(true)), ..Default::default() }) .expect("could not serialize server capabilities"); - context - .connection - .initialize(capabilities) - .expect("could not initialize the connection"); - let (diag_sender, diag_receiver) = bounded::>>>(0); let mut symbolicator_runner = symbols::SymbolicatorRunner::idle(); if symbols::DEFS_AND_REFS_SUPPORT { - symbolicator_runner = - symbols::SymbolicatorRunner::new(context.symbols.clone(), diag_sender); + let initialize_params: lsp_types::InitializeParams = + serde_json::from_value(client_response) + .expect("could not deserialize client capabilities"); + + symbolicator_runner = symbols::SymbolicatorRunner::new(symbols.clone(), diag_sender); + + // If initialization information from the client contains a path to the directory being + // opened, try to initialize symbols before sending response to the client. Do not bother + // with diagnostics as they will be recomputed whenever the first source file is opened. The + // main reason for this is to enable unit tests that rely on the symbolication information + // to be available right after the client is initialized. + if let Some(uri) = initialize_params.root_uri { + if let Some(p) = symbols::SymbolicatorRunner::root_dir(&uri.to_file_path().unwrap()) { + // need to evaluate in a separate thread to allow for a larger stack size (needed on + // Windows) + thread::Builder::new() + .stack_size(symbols::STACK_SIZE_BYTES) + .spawn(move || { + if let Ok((Some(new_symbols), _)) = + symbols::Symbolicator::get_symbols(p.as_path()) + { + let mut old_symbols = symbols.lock().unwrap(); + (*old_symbols).merge(new_symbols); + } + }) + .unwrap() + .join() + .unwrap(); + } + } }; + context + .connection + .initialize_finish( + id, + serde_json::json!({ + "capabilities": capabilities, + }), + ) + .expect("could not finish connection initialization"); + loop { select! { recv(diag_receiver) -> message => { @@ -181,7 +223,9 @@ fn main() { fn on_request(context: &Context, request: &Request) { match request.method.as_str() { - lsp_types::request::Completion::METHOD => on_completion_request(context, request), + lsp_types::request::Completion::METHOD => { + on_completion_request(context, request, &context.symbols.lock().unwrap()) + } lsp_types::request::GotoDefinition::METHOD => { symbols::on_go_to_def_request(context, request, &context.symbols.lock().unwrap()); } @@ -194,6 +238,9 @@ fn on_request(context: &Context, request: &Request) { lsp_types::request::HoverRequest::METHOD => { symbols::on_hover_request(context, request, &context.symbols.lock().unwrap()); } + lsp_types::request::DocumentSymbolRequest::METHOD => { + symbols::on_document_symbol_request(context, request, &context.symbols.lock().unwrap()); + } _ => eprintln!("handle request '{}' from client", request.method), } } diff --git a/language/move-analyzer/src/completion.rs b/language/move-analyzer/src/completion.rs index 34c61b4340..787ee43f4a 100644 --- a/language/move-analyzer/src/completion.rs +++ b/language/move-analyzer/src/completion.rs @@ -2,15 +2,16 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 -use crate::context::Context; +use crate::{context::Context, symbols::Symbols}; use lsp_server::Request; use lsp_types::{CompletionItem, CompletionItemKind, CompletionParams, Position}; use move_command_line_common::files::FileHash; use move_compiler::parser::{ - keywords::{BUILTINS, CONTEXTUAL_KEYWORDS, KEYWORDS}, + keywords::{BUILTINS, CONTEXTUAL_KEYWORDS, KEYWORDS, PRIMITIVE_TYPES}, lexer::{Lexer, Tok}, }; -use std::collections::HashSet; +use move_symbol_pool::Symbol; +use std::{collections::HashSet, path::PathBuf}; /// Constructs an `lsp_types::CompletionItem` with the given `label` and `kind`. fn completion_item(label: &str, kind: CompletionItemKind) -> CompletionItem { @@ -31,6 +32,7 @@ fn keywords() -> Vec { KEYWORDS .iter() .chain(CONTEXTUAL_KEYWORDS.iter()) + .chain(PRIMITIVE_TYPES.iter()) .map(|label| { let kind = if label == &"copy" || label == &"move" { CompletionItemKind::Operator @@ -42,6 +44,14 @@ fn keywords() -> Vec { .collect() } +/// Return a list of completion items of Move's primitive types +fn primitive_types() -> Vec { + PRIMITIVE_TYPES + .iter() + .map(|label| completion_item(label, CompletionItemKind::Keyword)) + .collect() +} + /// Return a list of completion items corresponding to each one of Move's builtin functions. fn builtins() -> Vec { BUILTINS @@ -59,7 +69,7 @@ fn builtins() -> Vec { /// server did not initialize with a response indicating it's capable of providing completions. In /// the future, the server should be modified to return semantically valid completion items, not /// simple textual suggestions. -fn identifiers(buffer: &str) -> Vec { +fn identifiers(buffer: &str, symbols: &Symbols, path: &PathBuf) -> Vec { let mut lexer = Lexer::new(buffer, FileHash::new(buffer)); if lexer.advance().is_err() { return vec![]; @@ -83,13 +93,26 @@ fn identifiers(buffer: &str) -> Vec { } } + let mods_opt = symbols.file_mods().get(path); + // The completion item kind "text" indicates that the item is based on simple textual matching, // not any deeper semantic analysis. - let items = ids - .iter() - .map(|label| completion_item(label, CompletionItemKind::Text)) - .collect(); - items + ids.iter() + .map(|label| { + if let Some(mods) = mods_opt { + if mods + .iter() + .any(|m| m.functions().contains_key(&Symbol::from(*label))) + { + completion_item(label, CompletionItemKind::Function) + } else { + completion_item(label, CompletionItemKind::Text) + } + } else { + completion_item(label, CompletionItemKind::Text) + } + }) + .collect() } /// Returns the token corresponding to the "trigger character" that precedes the user's cursor, @@ -122,15 +145,23 @@ fn get_cursor_token(buffer: &str, position: &Position) -> Option { /// Sends the given connection a response to a completion request. /// /// The completions returned depend upon where the user's cursor is positioned. -pub fn on_completion_request(context: &Context, request: &Request) { +pub fn on_completion_request(context: &Context, request: &Request, symbols: &Symbols) { eprintln!("handling completion request"); let parameters = serde_json::from_value::(request.params.clone()) .expect("could not deserialize completion request"); - let path = parameters.text_document_position.text_document.uri.path(); - let buffer = context.files.get(path); + let path = parameters + .text_document_position + .text_document + .uri + .to_file_path() + .unwrap(); + let buffer = context.files.get(&path); if buffer.is_none() { - eprintln!("Could not read '{}' when handling completion request", path); + eprintln!( + "Could not read '{:?}' when handling completion request", + path + ); } // The completion items we provide depend upon where the user's cursor is positioned. @@ -140,9 +171,7 @@ pub fn on_completion_request(context: &Context, request: &Request) { let mut items = vec![]; match cursor { Some(Tok::Colon) => { - // If the user's cursor is positioned after a single `:`, do not provide any completion - // items at all -- this is a "mis-fire" of the "trigger character" `:`. - return; + items.extend_from_slice(&primitive_types()); } Some(Tok::Period) | Some(Tok::ColonColon) => { // `.` or `::` must be followed by identifiers, which are added to the completion items @@ -157,7 +186,7 @@ pub fn on_completion_request(context: &Context, request: &Request) { } if let Some(buffer) = &buffer { - let identifiers = identifiers(buffer); + let identifiers = identifiers(buffer, symbols, &path); items.extend_from_slice(&identifiers); } diff --git a/language/move-analyzer/src/symbols.rs b/language/move-analyzer/src/symbols.rs index c847c3758b..970549ef70 100644 --- a/language/move-analyzer/src/symbols.rs +++ b/language/move-analyzer/src/symbols.rs @@ -54,16 +54,19 @@ use crate::{ use anyhow::{anyhow, Result}; use codespan_reporting::files::SimpleFiles; use crossbeam::channel::Sender; +use derivative::*; use im::ordmap::OrdMap; use lsp_server::{Request, RequestId}; use lsp_types::{ - request::GotoTypeDefinitionParams, Diagnostic, GotoDefinitionParams, Hover, HoverContents, - HoverParams, LanguageString, Location, MarkedString, Position, Range, ReferenceParams, + request::GotoTypeDefinitionParams, Diagnostic, DocumentSymbol, DocumentSymbolParams, + GotoDefinitionParams, Hover, HoverContents, HoverParams, LanguageString, Location, + MarkedString, Position, Range, ReferenceParams, SymbolKind, }; + use std::{ cmp, collections::{BTreeMap, BTreeSet, HashMap}, - fmt, fs, + fmt, path::{Path, PathBuf}, sync::{Arc, Condvar, Mutex}, thread, @@ -90,6 +93,9 @@ use move_symbol_pool::Symbol; /// Enabling/disabling the language server reporting readiness to support go-to-def and /// go-to-references to the IDE. pub const DEFS_AND_REFS_SUPPORT: bool = true; +// Building Move code requires a larger stack size on Windows (16M has been chosen somewhat +// arbitrarily) +pub const STACK_SIZE_BYTES: usize = 16 * 1024 * 1024; #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)] /// Location of a definition's identifier @@ -121,7 +127,8 @@ pub enum IdentType { ModuleIdent_, /* defining module */ Symbol, /* name */ Vec, /* type args */ - Vec, /* args */ + Vec, /* arg names */ + Vec, /* arg types */ Type, /* ret */ Vec, /* acquires */ ), @@ -142,33 +149,50 @@ pub struct UseDef { def_loc: DefLoc, /// Location of the type definition type_def_loc: Option, + /// Doc string for the relevant identifier/function + doc_string: String, } /// Definition of a struct field -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)] struct FieldDef { name: Symbol, start: Position, } /// Definition of a struct -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)] struct StructDef { name_start: Position, field_defs: Vec, } +#[derive(Derivative, Debug, Clone, PartialEq, Eq)] +#[derivative(PartialOrd, Ord)] +pub struct FunctionDef { + name: Symbol, + start: Position, + attrs: Vec, + #[derivative(PartialOrd = "ignore")] + #[derivative(Ord = "ignore")] + ident_type: IdentType, +} + /// Module-level definitions -#[derive(Debug)] -struct ModuleDefs { +#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)] +pub struct ModuleDefs { /// File where this module is located fhash: FileHash, + /// Location where this module is located + start: Position, + /// Module name + name: ModuleIdent_, /// Struct definitions structs: BTreeMap, /// Const definitions constants: BTreeMap, /// Function definitions - functions: BTreeMap, + functions: BTreeMap, } /// Data used during symbolication @@ -179,6 +203,8 @@ pub struct Symbolicator { files: SimpleFiles, /// A mapping from file hashes to file IDs (used to obtain source file locations) file_id_mapping: HashMap, + // A mapping from file IDs to a split vector of the lines in each file (used to build docstrings) + file_id_to_lines: HashMap>, /// Contains type params where relevant (e.g. when processing function definition) type_params: BTreeMap, /// Current processed module (always set before module processing starts) @@ -187,9 +213,13 @@ pub struct Symbolicator { /// Maps a line number to a list of use-def pairs on a given line (use-def set is sorted by /// col_start) -#[derive(Debug)] +#[derive(Debug, Clone, Eq, PartialEq)] struct UseDefMap(BTreeMap>); +/// Maps a function name to its usage definition +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct FunctionIdentTypeMap(BTreeMap); + /// Result of the symbolication process pub struct Symbols { /// A map from def locations to all the references (uses) @@ -198,6 +228,8 @@ pub struct Symbols { file_use_defs: BTreeMap, /// A mapping from file hashes to file names file_name_mapping: BTreeMap, + /// A mapping from filePath to ModuleDefs + file_mods: BTreeMap>, } #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)] @@ -212,6 +244,12 @@ pub struct SymbolicatorRunner { mtx_cvar: Arc<(Mutex, Condvar)>, } +impl ModuleDefs { + pub fn functions(&self) -> &BTreeMap { + &self.functions + } +} + impl fmt::Display for IdentType { fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result { match self { @@ -225,9 +263,9 @@ impl fmt::Display for IdentType { // IDE independently on how compiler error messages are generated. write!(f, "{}", type_to_ide_string(t)) } - Self::FunctionType(mod_ident, name, type_args, args, ret, acquires) => { + Self::FunctionType(mod_ident, name, type_args, arg_names, arg_types, ret, acquires) => { let type_args_str = if !type_args.is_empty() { - let mut s = "<".to_string(); + let mut s = '<'.to_string(); s.push_str(&type_list_to_ide_string(type_args)); s.push('>'); s @@ -253,7 +291,7 @@ impl fmt::Display for IdentType { mod_ident.module.value(), name, type_args_str, - type_list_to_ide_string(args), + arg_list_to_ide_string(arg_names, arg_types), ret_str, acquires_str ) @@ -262,6 +300,15 @@ impl fmt::Display for IdentType { } } +fn arg_list_to_ide_string(names: &[Symbol], types: &[Type]) -> String { + names + .iter() + .zip(types.iter()) + .map(|(n, t)| format!("{}: {}", n, type_to_ide_string(t))) + .collect::>() + .join(", ") +} + fn type_to_ide_string(sp!(_, t): &Type) -> String { match t { Type_::Unit => "()".to_string(), @@ -309,8 +356,8 @@ fn addr_to_ide_string(addr: &Address) -> String { } } -fn type_list_to_ide_string(items: &[Type]) -> String { - items +fn type_list_to_ide_string(types: &[Type]) -> String { + types .iter() .map(type_to_ide_string) .collect::>() @@ -333,95 +380,98 @@ impl SymbolicatorRunner { let thread_mtx_cvar = mtx_cvar.clone(); let runner = SymbolicatorRunner { mtx_cvar }; - thread::spawn(move || { - let (mtx, cvar) = &*thread_mtx_cvar; - // Locations opened in the IDE (files or directories) for which manifest file is missing - let mut missing_manifests = BTreeSet::new(); - // infinite loop to wait for symbolication requests - eprintln!("starting symbolicator runner loop"); - loop { - let starting_path_opt = { - // hold the lock only as long as it takes to get the data, rather than through - // the whole symbolication process (hence a separate scope here) - let mut symbolicate = mtx.lock().unwrap(); - match symbolicate.clone() { - RunnerState::Quit => break, - RunnerState::Run(root_dir) => { - *symbolicate = RunnerState::Wait; - Some(root_dir) - } - RunnerState::Wait => { - // wait for next request - symbolicate = cvar.wait(symbolicate).unwrap(); - match symbolicate.clone() { - RunnerState::Quit => break, - RunnerState::Run(root_dir) => { - *symbolicate = RunnerState::Wait; - Some(root_dir) + thread::Builder::new() + .stack_size(STACK_SIZE_BYTES) + .spawn(move || { + let (mtx, cvar) = &*thread_mtx_cvar; + // Locations opened in the IDE (files or directories) for which manifest file is missing + let mut missing_manifests = BTreeSet::new(); + // infinite loop to wait for symbolication requests + eprintln!("starting symbolicator runner loop"); + loop { + let starting_path_opt = { + // hold the lock only as long as it takes to get the data, rather than through + // the whole symbolication process (hence a separate scope here) + let mut symbolicate = mtx.lock().unwrap(); + match symbolicate.clone() { + RunnerState::Quit => break, + RunnerState::Run(root_dir) => { + *symbolicate = RunnerState::Wait; + Some(root_dir) + } + RunnerState::Wait => { + // wait for next request + symbolicate = cvar.wait(symbolicate).unwrap(); + match symbolicate.clone() { + RunnerState::Quit => break, + RunnerState::Run(root_dir) => { + *symbolicate = RunnerState::Wait; + Some(root_dir) + } + RunnerState::Wait => None, } - RunnerState::Wait => None, } } - } - }; - if let Some(starting_path) = starting_path_opt { - let root_dir = Self::root_dir(&starting_path); - if root_dir.is_none() && !missing_manifests.contains(&starting_path) { - eprintln!("reporting missing manifest"); - - // report missing manifest file only once to avoid cluttering IDE's UI in - // cases when developer indeed intended to open a standalone file that was - // not meant to compile - missing_manifests.insert(starting_path); - if let Err(err) = sender.send(Err(anyhow!( - "Unable to find package manifest. Make sure that + }; + if let Some(starting_path) = starting_path_opt { + let root_dir = Self::root_dir(&starting_path); + if root_dir.is_none() && !missing_manifests.contains(&starting_path) { + eprintln!("reporting missing manifest"); + + // report missing manifest file only once to avoid cluttering IDE's UI in + // cases when developer indeed intended to open a standalone file that was + // not meant to compile + missing_manifests.insert(starting_path); + if let Err(err) = sender.send(Err(anyhow!( + "Unable to find package manifest. Make sure that the source files are located in a sub-directory of a package containing a Move.toml file. " - ))) { - eprintln!("could not pass missing manifest error: {:?}", err); - } - continue; - } - eprintln!("symbolication started"); - match Symbolicator::get_symbols(root_dir.unwrap().as_path()) { - Ok((symbols_opt, lsp_diagnostics)) => { - eprintln!("symbolication finished"); - if let Some(new_symbols) = symbols_opt { - // merge the new symbols with the old ones to support a - // (potentially) new project/package that symbolication information - // was built for - // - // TODO: we may consider "unloading" symbolication information when - // files/directories are being closed but as with other performance - // optimizations (e.g. incrementalizatino of the vfs), let's wait - // until we know we actually need it - let mut old_symbols = symbols.lock().unwrap(); - (*old_symbols).merge(new_symbols); - } - // set/reset (previous) diagnostics - if let Err(err) = sender.send(Ok(lsp_diagnostics)) { - eprintln!("could not pass diagnostics: {:?}", err); + ))) { + eprintln!("could not pass missing manifest error: {:?}", err); } + continue; } - Err(err) => { - eprintln!("symbolication failed: {:?}", err); - if let Err(err) = sender.send(Err(err)) { - eprintln!("could not pass compiler error: {:?}", err); + eprintln!("symbolication started"); + match Symbolicator::get_symbols(root_dir.unwrap().as_path()) { + Ok((symbols_opt, lsp_diagnostics)) => { + eprintln!("symbolication finished"); + if let Some(new_symbols) = symbols_opt { + // merge the new symbols with the old ones to support a + // (potentially) new project/package that symbolication information + // was built for + // + // TODO: we may consider "unloading" symbolication information when + // files/directories are being closed but as with other performance + // optimizations (e.g. incrementalizatino of the vfs), let's wait + // until we know we actually need it + let mut old_symbols = symbols.lock().unwrap(); + (*old_symbols).merge(new_symbols); + } + // set/reset (previous) diagnostics + if let Err(err) = sender.send(Ok(lsp_diagnostics)) { + eprintln!("could not pass diagnostics: {:?}", err); + } + } + Err(err) => { + eprintln!("symbolication failed: {:?}", err); + if let Err(err) = sender.send(Err(err)) { + eprintln!("could not pass compiler error: {:?}", err); + } } } } } - } - }); + }) + .unwrap(); runner } - pub fn run(&self, starting_path: &str) { - eprintln!("scheduling run for {}", starting_path); + pub fn run(&self, starting_path: PathBuf) { + eprintln!("scheduling run for {:?}", starting_path); let (mtx, cvar) = &*self.mtx_cvar; let mut symbolicate = mtx.lock().unwrap(); - *symbolicate = RunnerState::Run(PathBuf::from(starting_path)); + *symbolicate = RunnerState::Run(starting_path); cvar.notify_one(); eprintln!("scheduled run"); } @@ -433,8 +483,8 @@ impl SymbolicatorRunner { cvar.notify_one(); } - /// Finds manifest file in a subdirectory of a Move source file passed as argument - fn root_dir(starting_path: &Path) -> Option { + /// Finds manifest file in a (sub)directory of the starting path passed as argument + pub fn root_dir(starting_path: &Path) -> Option { let mut current_path_opt = Some(starting_path); while current_path_opt.is_some() { let current_path = current_path_opt.unwrap(); @@ -458,6 +508,7 @@ impl UseDef { use_name: &Symbol, use_type: IdentType, type_def_loc: Option, + doc_string: String, ) -> Self { let def_loc = DefLoc { fhash: def_fhash, @@ -480,6 +531,7 @@ impl UseDef { use_type, def_loc, type_def_loc, + doc_string, } } } @@ -524,8 +576,22 @@ impl UseDefMap { } } +impl FunctionIdentTypeMap { + fn new() -> Self { + Self(BTreeMap::new()) + } + + fn insert(&mut self, key: String, val: IdentType) { + self.0.entry(key).or_insert_with(|| val); + } + + pub fn contains_key(self, key: &String) -> bool { + self.0.contains_key(key) + } +} + impl Symbols { - fn merge(&mut self, other: Self) { + pub fn merge(&mut self, other: Self) { for (k, v) in other.references { self.references .entry(k) @@ -534,6 +600,11 @@ impl Symbols { } self.file_use_defs.extend(other.file_use_defs); self.file_name_mapping.extend(other.file_name_mapping); + self.file_mods.extend(other.file_mods); + } + + pub fn file_mods(&self) -> &BTreeMap> { + &self.file_mods } } @@ -553,24 +624,30 @@ impl Symbolicator { eprintln!("symbolicating {:?}", pkg_path); - let resolution_graph = build_config.resolution_graph_for_package(pkg_path)?; + // resolution graph diagnostics are only needed for CLI commands so ignore them by passing a + // vector as the writer + let resolution_graph = + build_config.resolution_graph_for_package(pkg_path, &mut Vec::new())?; // get source files to be able to correlate positions (in terms of byte offsets) with actual // file locations (in terms of line/column numbers) let source_files = &resolution_graph.file_sources(); let mut files = SimpleFiles::new(); let mut file_id_mapping = HashMap::new(); + let mut file_id_to_lines = HashMap::new(); let mut file_name_mapping = BTreeMap::new(); for (fhash, (fname, source)) in source_files { let id = files.add(*fname, source.clone()); file_id_mapping.insert(*fhash, id); file_name_mapping.insert(*fhash, *fname); + let lines: Vec = source.lines().map(String::from).collect(); + file_id_to_lines.insert(id, lines); } let build_plan = BuildPlan::create(resolution_graph)?; let mut typed_ast = None; let mut diagnostics = None; - build_plan.compile_with_driver(&mut std::io::sink(), |compiler| { + build_plan.compile_with_driver(&mut std::io::sink(), None, |compiler| { let (files, compilation_result) = compiler.run::()?; let (_, compiler) = match compilation_result { Ok(v) => v, @@ -629,38 +706,66 @@ impl Symbolicator { let mut mod_outer_defs = BTreeMap::new(); let mut mod_use_defs = BTreeMap::new(); + let mut file_mods = BTreeMap::new(); + for (pos, module_ident, module_def) in modules { - let (defs, symbols) = - Self::get_mod_outer_defs(&pos, module_def, &files, &file_id_mapping); + let (defs, symbols) = Self::get_mod_outer_defs( + &pos, + &sp(pos, *module_ident), + module_def, + &files, + &file_id_mapping, + ); + + let cloned_defs = defs.clone(); + let path = file_name_mapping.get(&cloned_defs.fhash.clone()).unwrap(); + file_mods + .entry( + dunce::canonicalize(path.as_str()) + .unwrap_or_else(|_| PathBuf::from(path.as_str())), + ) + .or_insert_with(BTreeSet::new) + .insert(cloned_defs); + mod_outer_defs.insert(*module_ident, defs); mod_use_defs.insert(*module_ident, symbols); } + eprintln!("get_symbols loaded file_mods length: {}", file_mods.len()); + let mut symbolicator = Symbolicator { mod_outer_defs, files, file_id_mapping, + file_id_to_lines, type_params: BTreeMap::new(), current_mod: None, }; let mut references = BTreeMap::new(); let mut file_use_defs = BTreeMap::new(); + let mut function_ident_type = FunctionIdentTypeMap::new(); + for (pos, module_ident, module_def) in modules { let mut use_defs = mod_use_defs.remove(module_ident).unwrap(); symbolicator.current_mod = Some(sp(pos, *module_ident)); - symbolicator.mod_symbols(module_def, &mut references, &mut use_defs); + symbolicator.mod_symbols( + module_def, + &mut references, + &mut use_defs, + &mut function_ident_type, + ); let fpath = match source_files.get(&pos.file_hash()) { Some((p, _)) => p, None => continue, }; + let fpath_buffer = dunce::canonicalize(fpath.as_str()) + .unwrap_or_else(|_| PathBuf::from(fpath.as_str())); + file_use_defs - .entry( - fs::canonicalize(fpath.as_str()) - .unwrap_or_else(|_| PathBuf::from(fpath.as_str())), - ) + .entry(fpath_buffer) .or_insert_with(UseDefMap::new) .extend(use_defs.elements()); } @@ -669,7 +774,11 @@ impl Symbolicator { references, file_use_defs, file_name_mapping, + file_mods, }; + + eprintln!("get_symbols load complete"); + Ok((Some(symbols), ide_diagnostics)) } @@ -679,6 +788,7 @@ impl Symbolicator { file_use_defs: BTreeMap::new(), references: BTreeMap::new(), file_name_mapping: BTreeMap::new(), + file_mods: BTreeMap::new(), } } @@ -687,6 +797,7 @@ impl Symbolicator { /// Get symbols for outer definitions in the module (functions, structs, and consts) fn get_mod_outer_defs( loc: &Loc, + mod_ident: &ModuleIdent, mod_def: &ModuleDefinition, files: &SimpleFiles, file_id_mapping: &HashMap, @@ -722,6 +833,7 @@ impl Symbolicator { continue; } }; + structs.insert( *name, StructDef { @@ -742,7 +854,7 @@ impl Symbolicator { constants.insert(*name, name_start); } - for (pos, name, _) in &mod_def.functions { + for (pos, name, fun) in &mod_def.functions { let name_start = match Self::get_start_loc(&pos, files, file_id_mapping) { Some(s) => s, None => { @@ -750,18 +862,80 @@ impl Symbolicator { continue; } }; - functions.insert(*name, name_start); + let ident_type = IdentType::FunctionType( + mod_ident.value, + *name, + fun.signature + .type_parameters + .iter() + .map(|t| sp(t.user_specified_name.loc, Type_::Param(t.clone()))) + .collect(), + fun.signature + .parameters + .iter() + .map(|(n, _)| n.value()) + .collect(), + fun.signature + .parameters + .iter() + .map(|(_, t)| t.clone()) + .collect(), + fun.signature.return_type.clone(), + fun.acquires + .iter() + .map(|(k, v)| Self::create_struct_type(*mod_ident, *k, *v, vec![])) + .collect(), + ); + functions.insert( + *name, + FunctionDef { + name: *name, + start: name_start, + attrs: fun + .attributes + .clone() + .iter() + .map(|(_loc, name, _attr)| name.to_string()) + .collect(), + ident_type, + }, + ); } + let use_def_map = UseDefMap::new(); + + let name = mod_ident.value; let fhash = loc.file_hash(); + let start = match Self::get_start_loc(loc, files, file_id_mapping) { + Some(s) => s, + None => { + debug_assert!(false); + return ( + ModuleDefs { + fhash, + start: Position { + line: 0, + character: 0, + }, + name, + structs, + constants, + functions, + }, + use_def_map, + ); + } + }; + let module_defs = ModuleDefs { + name, + start, fhash, structs, constants, functions, }; - let use_def_map = UseDefMap::new(); (module_defs, use_def_map) } @@ -771,51 +945,41 @@ impl Symbolicator { mod_def: &ModuleDefinition, references: &mut BTreeMap>, use_defs: &mut UseDefMap, + function_ident_type: &mut FunctionIdentTypeMap, ) { for (pos, name, fun) in &mod_def.functions { // enter self-definition for function name (unwrap safe - done when inserting def) let name_start = Self::get_start_loc(&pos, &self.files, &self.file_id_mapping).unwrap(); - let use_type = IdentType::FunctionType( - self.current_mod.unwrap().value, - *name, - fun.signature - .type_parameters - .iter() - .map(|t| sp(t.user_specified_name.loc, Type_::Param(t.clone()))) - .collect(), - fun.signature - .parameters - .iter() - .map(|(_, t)| t.clone()) - .collect(), - fun.signature.return_type.clone(), - fun.acquires - .iter() - .map(|(k, v)| { - Self::create_struct_type(self.current_mod.unwrap(), *k, *v, vec![]) - }) - .collect(), - ); - let ident_type_def = self.ident_type_def_loc(&use_type); - use_defs.insert( - name_start.line, - UseDef::new( - references, - pos.file_hash(), - name_start, - pos.file_hash(), - name_start, - name, - use_type, - ident_type_def, - ), + let doc_string = self.extract_doc_string(&name_start, &pos.file_hash()); + + let mod_ident = self.current_mod.unwrap(); + + let mod_def = self.mod_outer_defs.get(&mod_ident.value).unwrap(); + let fun_def = mod_def.functions.get(name).unwrap(); + let use_type = fun_def.ident_type.clone(); + + let fun_type_def = self.ident_type_def_loc(&use_type); + let use_def = UseDef::new( + references, + pos.file_hash(), + name_start, + pos.file_hash(), + name_start, + name, + use_type.clone(), + fun_type_def, + doc_string, ); + + use_defs.insert(name_start.line, use_def); self.fun_symbols(fun, references, use_defs); + function_ident_type.insert(name.to_string(), use_type); } for (pos, name, c) in &mod_def.constants { // enter self-definition for const name (unwrap safe - done when inserting def) let name_start = Self::get_start_loc(&pos, &self.files, &self.file_id_mapping).unwrap(); + let doc_string = self.extract_doc_string(&name_start, &pos.file_hash()); let ident_type = IdentType::RegularType(c.signature.clone()); let ident_type_def = self.ident_type_def_loc(&ident_type); use_defs.insert( @@ -829,6 +993,7 @@ impl Symbolicator { name, ident_type, ident_type_def, + doc_string, ), ); } @@ -836,6 +1001,7 @@ impl Symbolicator { for (pos, name, struct_def) in &mod_def.structs { // enter self-definition for struct name (unwrap safe - done when inserting def) let name_start = Self::get_start_loc(&pos, &self.files, &self.file_id_mapping).unwrap(); + let doc_string = self.extract_doc_string(&name_start, &pos.file_hash()); let ident_type = IdentType::RegularType(Self::create_struct_type( self.current_mod.unwrap(), StructName(sp(pos, *name)), @@ -854,6 +1020,7 @@ impl Symbolicator { name, ident_type, ident_type_def, + doc_string, ), ); @@ -881,6 +1048,7 @@ impl Symbolicator { let start = Self::get_start_loc(&fpos, &self.files, &self.file_id_mapping).unwrap(); let ident_type = IdentType::RegularType(t.clone()); let ident_type_def = self.ident_type_def_loc(&ident_type); + let doc_string = self.extract_doc_string(&start, &fpos.file_hash()); use_defs.insert( start.line, UseDef::new( @@ -892,6 +1060,7 @@ impl Symbolicator { fname, ident_type, ident_type_def, + doc_string, ), ); } @@ -966,6 +1135,74 @@ impl Symbolicator { get_loc(&pos.file_hash(), pos.start(), files, file_id_mapping) } + /// Extracts the docstring (/// or /** ... */) for a given definition by traversing up from the line definition + fn extract_doc_string(&self, name_start: &Position, file_hash: &FileHash) -> String { + let mut doc_string = String::new(); + let file_id = match self.file_id_mapping.get(file_hash) { + None => return doc_string, + Some(v) => v, + }; + + let file_lines = match self.file_id_to_lines.get(file_id) { + None => return doc_string, + Some(v) => v, + }; + + if name_start.line == 0 { + return doc_string; + } + + let mut iter = (name_start.line - 1) as usize; + let mut line_before = file_lines[iter].trim(); + + // Detect the two different types of docstrings + if line_before.starts_with("///") { + while let Some(stripped_line) = line_before.strip_prefix("///") { + doc_string = format!("{}\n{}", stripped_line.trim(), doc_string); + if iter == 0 { + break; + } + iter -= 1; + line_before = file_lines[iter].trim(); + } + } else if line_before.ends_with("*/") { + let mut doc_string_found = false; + line_before = file_lines[iter].strip_suffix("*/").unwrap_or("").trim(); + + // Loop condition is a safe guard. + while !doc_string_found { + // We found the start of the multi-line comment/docstring + if line_before.starts_with("/*") { + let is_doc = line_before.starts_with("/**") && !line_before.starts_with("/***"); + + // Invalid doc_string start prefix so return empty doc string. + if !is_doc { + return String::new(); + } + + line_before = line_before.strip_prefix("/**").unwrap_or("").trim(); + doc_string_found = true; + } + + doc_string = format!("{}\n{}", line_before, doc_string); + + if iter == 0 { + break; + } + + iter -= 1; + line_before = file_lines[iter].trim(); + } + + // No doc_string found - return String::new(); + if !doc_string_found { + return String::new(); + } + } + + doc_string + } + /// Get symbols for a sequence representing function body fn seq_item_symbols( &self, @@ -1144,9 +1381,7 @@ impl Symbolicator { use_defs, exp.ty.clone(), ), - E::ModuleCall(mod_call) => { - self.mod_call_symbols(mod_call, scope, references, use_defs, exp.ty.clone()) - } + E::ModuleCall(mod_call) => self.mod_call_symbols(mod_call, scope, references, use_defs), E::Builtin(builtin_fun, exp) => { use BuiltinFunction_ as BF; match &builtin_fun.value { @@ -1296,21 +1531,16 @@ impl Symbolicator { scope: &mut OrdMap, references: &mut BTreeMap>, use_defs: &mut UseDefMap, - ret_type: Type, ) { - // handle function name - let use_type = IdentType::FunctionType( - mod_call.module.value, - mod_call.name.value(), - mod_call.type_arguments.clone(), - mod_call.parameter_types.clone(), - ret_type, - mod_call - .acquires - .iter() - .map(|(k, v)| Self::create_struct_type(mod_call.module, *k, *v, vec![])) - .collect(), - ); + let mod_ident = mod_call.module; + let mod_def = self.mod_outer_defs.get(&mod_ident.value).unwrap(); + + let fun_def = match mod_def.functions.get(&mod_call.name.value()) { + Some(v) => v, + None => return, + }; + let use_type = fun_def.ident_type.clone(); + self.add_fun_use_def( &mod_call.module, &mod_call.name.value(), @@ -1394,6 +1624,8 @@ impl Symbolicator { Type_::Param(tp.clone()), )); let ident_type_def = self.ident_type_def_loc(&ident_type); + + let doc_string = self.extract_doc_string(&start, &fhash); use_defs.insert( start.line, UseDef::new( @@ -1405,6 +1637,7 @@ impl Symbolicator { &tname, ident_type, ident_type_def, + doc_string, ), ); let exists = tp_scope.insert(tname, DefLoc { fhash, start }); @@ -1464,18 +1697,22 @@ impl Symbolicator { |use_name, name_start, mod_defs| match mod_defs.constants.get(use_name) { Some(def_start) => { let ident_type = IdentType::RegularType(use_type.clone()); + let def_fhash = self.mod_outer_defs.get(&module_ident).unwrap().fhash; + let doc_string = self.extract_doc_string(def_start, &def_fhash); let ident_type_def = self.ident_type_def_loc(&ident_type); + use_defs.insert( name_start.line, UseDef::new( references, use_pos.file_hash(), name_start, - self.mod_outer_defs.get(&module_ident).unwrap().fhash, + def_fhash, *def_start, use_name, ident_type, ident_type_def, + doc_string, ), ); } @@ -1499,18 +1736,21 @@ impl Symbolicator { use_name, use_pos, |use_name, name_start, mod_defs| match mod_defs.functions.get(use_name) { - Some(def_start) => { + Some(func_def) => { + let def_fhash = self.mod_outer_defs.get(&module_ident.value).unwrap().fhash; + let doc_string = self.extract_doc_string(&func_def.start, &def_fhash); use_defs.insert( name_start.line, UseDef::new( references, use_pos.file_hash(), name_start, - self.mod_outer_defs.get(&module_ident.value).unwrap().fhash, - *def_start, + def_fhash, + func_def.start, use_name, use_type.clone(), self.ident_type_def_loc(&use_type), + doc_string, ), ); } @@ -1536,18 +1776,22 @@ impl Symbolicator { |use_name, name_start, mod_defs| match mod_defs.structs.get(use_name) { Some(def) => { let ident_type = IdentType::RegularType(use_type.clone()); + let ident_type_def = self.ident_type_def_loc(&ident_type); + let def_fhash = self.mod_outer_defs.get(module_ident).unwrap().fhash; + let doc_string = self.extract_doc_string(&def.name_start, &def_fhash); use_defs.insert( name_start.line, UseDef::new( references, use_pos.file_hash(), name_start, - self.mod_outer_defs.get(module_ident).unwrap().fhash, + def_fhash, def.name_start, use_name, ident_type, ident_type_def, + doc_string, ), ); } @@ -1577,17 +1821,21 @@ impl Symbolicator { if fdef.name == *use_name { let ident_type = IdentType::RegularType(use_type.clone()); let ident_type_def = self.ident_type_def_loc(&ident_type); + + let def_fhash = self.mod_outer_defs.get(module_ident).unwrap().fhash; + let doc_string = self.extract_doc_string(&fdef.start, &def_fhash); use_defs.insert( name_start.line, UseDef::new( references, use_pos.file_hash(), name_start, - self.mod_outer_defs.get(module_ident).unwrap().fhash, + def_fhash, fdef.start, use_name, ident_type, ident_type_def, + doc_string, ), ); } @@ -1615,6 +1863,8 @@ impl Symbolicator { Some(def_loc) => { let ident_type = IdentType::RegularType(id_type.clone()); let ident_type_def = self.ident_type_def_loc(&ident_type); + let doc_string = + self.extract_doc_string(&def_loc.start, &def_loc.fhash); use_defs.insert( name_start.line, UseDef::new( @@ -1626,6 +1876,7 @@ impl Symbolicator { &use_name, ident_type, ident_type_def, + doc_string, ), ); } @@ -1674,6 +1925,8 @@ impl Symbolicator { // in rust) a variable can be re-defined in the same scope replacing the previous // definition + let doc_string = self.extract_doc_string(&name_start, &pos.file_hash()); + // enter self-definition for def name let ident_type = IdentType::RegularType(use_type); let ident_type_def = self.ident_type_def_loc(&ident_type); @@ -1688,6 +1941,7 @@ impl Symbolicator { name, ident_type, ident_type_def, + doc_string, ), ); } @@ -1717,6 +1971,7 @@ impl Symbolicator { }; if let Some(def_loc) = scope.get(use_name) { + let doc_string = self.extract_doc_string(&def_loc.start, &def_loc.fhash); let ident_type = IdentType::RegularType(use_type); let ident_type_def = self.ident_type_def_loc(&ident_type); use_defs.insert( @@ -1730,6 +1985,7 @@ impl Symbolicator { use_name, ident_type, ident_type_def, + doc_string, ), ); } else { @@ -1753,7 +2009,7 @@ impl Symbolicator { fn ident_type_def_loc(&self, ident_type: &IdentType) -> Option { match ident_type { IdentType::RegularType(t) => self.type_def_loc(t), - IdentType::FunctionType(_, _, _, _, ret, _) => self.type_def_loc(ret), + IdentType::FunctionType(_, _, _, _, _, ret, _) => self.type_def_loc(ret), } } @@ -1788,7 +2044,8 @@ pub fn on_go_to_def_request(context: &Context, request: &Request, symbols: &Symb .text_document_position_params .text_document .uri - .path(); + .to_file_path() + .unwrap(); let loc = parameters.text_document_position_params.position; let line = loc.line; let col = loc.character; @@ -1796,7 +2053,7 @@ pub fn on_go_to_def_request(context: &Context, request: &Request, symbols: &Symb on_use_request( context, symbols, - fpath, + &fpath, line, col, request.id.clone(), @@ -1827,7 +2084,8 @@ pub fn on_go_to_type_def_request(context: &Context, request: &Request, symbols: .text_document_position_params .text_document .uri - .path(); + .to_file_path() + .unwrap(); let loc = parameters.text_document_position_params.position; let line = loc.line; let col = loc.character; @@ -1835,7 +2093,7 @@ pub fn on_go_to_type_def_request(context: &Context, request: &Request, symbols: on_use_request( context, symbols, - fpath, + &fpath, line, col, request.id.clone(), @@ -1862,7 +2120,12 @@ pub fn on_references_request(context: &Context, request: &Request, symbols: &Sym let parameters = serde_json::from_value::(request.params.clone()) .expect("could not deserialize references request"); - let fpath = parameters.text_document_position.text_document.uri.path(); + let fpath = parameters + .text_document_position + .text_document + .uri + .to_file_path() + .unwrap(); let loc = parameters.text_document_position.position; let line = loc.line; let col = loc.character; @@ -1871,7 +2134,7 @@ pub fn on_references_request(context: &Context, request: &Request, symbols: &Sym on_use_request( context, symbols, - fpath, + &fpath, line, col, request.id.clone(), @@ -1917,7 +2180,8 @@ pub fn on_hover_request(context: &Context, request: &Request, symbols: &Symbols) .text_document_position_params .text_document .uri - .path(); + .to_file_path() + .unwrap(); let loc = parameters.text_document_position_params.position; let line = loc.line; let col = loc.character; @@ -1925,14 +2189,18 @@ pub fn on_hover_request(context: &Context, request: &Request, symbols: &Symbols) on_use_request( context, symbols, - fpath, + &fpath, line, col, request.id.clone(), |u| { let lang_string = LanguageString { language: "".to_string(), - value: format!("{}", u.use_type), + value: if !u.doc_string.is_empty() { + format!("{}\n\n{}", u.use_type, u.doc_string) + } else { + format!("{}", u.use_type) + }, }; let contents = HoverContents::Scalar(MarkedString::LanguageString(lang_string)); let range = None; @@ -1945,7 +2213,7 @@ pub fn on_hover_request(context: &Context, request: &Request, symbols: &Symbols) pub fn on_use_request( context: &Context, symbols: &Symbols, - use_fpath: &str, + use_fpath: &PathBuf, use_line: u32, use_col: u32, id: RequestId, @@ -1954,7 +2222,7 @@ pub fn on_use_request( let mut result = None; let mut use_def_found = false; - if let Some(mod_symbols) = symbols.file_use_defs.get(&PathBuf::from(use_fpath)) { + if let Some(mod_symbols) = symbols.file_use_defs.get(use_fpath) { if let Some(uses) = mod_symbols.get(use_line) { for u in uses { if use_col >= u.col_start && use_col <= u.col_end { @@ -1981,8 +2249,147 @@ pub fn on_use_request( } } +/// Handles document symbol request of the language server +#[allow(deprecated)] +pub fn on_document_symbol_request(context: &Context, request: &Request, symbols: &Symbols) { + let parameters = serde_json::from_value::(request.params.clone()) + .expect("could not deserialize document symbol request"); + + let fpath = parameters.text_document.uri.to_file_path().unwrap(); + eprintln!("on_document_symbol_request: {:?}", fpath); + + let empty_mods: BTreeSet = BTreeSet::new(); + let mods = symbols.file_mods.get(&fpath).unwrap_or(&empty_mods); + + let mut defs: Vec = vec![]; + for mod_def in mods { + let name = mod_def.name.module.clone().to_string(); + let detail = Some(mod_def.name.clone().to_string()); + let kind = SymbolKind::Module; + let range = Range { + start: mod_def.start, + end: mod_def.start, + }; + + let mut children = vec![]; + + // handle constants + let cloned_const_def = mod_def.constants.clone(); + for (sym, const_def_pos) in cloned_const_def { + let const_range = Range { + start: const_def_pos, + end: const_def_pos, + }; + + children.push(DocumentSymbol { + name: sym.clone().to_string(), + detail: None, + kind: SymbolKind::Constant, + range: const_range, + selection_range: const_range, + children: None, + tags: Some(vec![]), + deprecated: Some(false), + }); + } + + // handle structs + let cloned_struct_def = mod_def.structs.clone(); + for (sym, struct_def) in cloned_struct_def { + let struct_range = Range { + start: struct_def.name_start, + end: struct_def.name_start, + }; + + let mut fields: Vec = vec![]; + handle_struct_fields(struct_def, &mut fields); + + children.push(DocumentSymbol { + name: sym.clone().to_string(), + detail: None, + kind: SymbolKind::Struct, + range: struct_range, + selection_range: struct_range, + children: Some(fields), + tags: Some(vec![]), + deprecated: Some(false), + }); + } + + // handle functions + let cloned_func_def = mod_def.functions.clone(); + for (sym, func_def) in cloned_func_def { + let func_range = Range { + start: func_def.start, + end: func_def.start, + }; + + let mut detail = None; + if !func_def.attrs.is_empty() { + detail = Some(format!("{:?}", func_def.attrs)); + } + + children.push(DocumentSymbol { + name: sym.clone().to_string(), + detail, + kind: SymbolKind::Function, + range: func_range, + selection_range: func_range, + children: None, + tags: Some(vec![]), + deprecated: Some(false), + }); + } + + defs.push(DocumentSymbol { + name, + detail, + kind, + range, + selection_range: range, + children: Some(children), + tags: Some(vec![]), + deprecated: Some(false), + }); + } + + // unwrap will succeed based on the logic above which the compiler is unable to figure out + let response = lsp_server::Response::new_ok(request.id.clone(), defs); + if let Err(err) = context + .connection + .sender + .send(lsp_server::Message::Response(response)) + { + eprintln!("could not send use response: {:?}", err); + } +} + +/// Helper function to handle struct fields +#[allow(deprecated)] +fn handle_struct_fields(struct_def: StructDef, fields: &mut Vec) { + let clonded_fileds = struct_def.field_defs; + + for field_def in clonded_fileds { + let field_range = Range { + start: field_def.start, + end: field_def.start, + }; + + fields.push(DocumentSymbol { + name: field_def.name.clone().to_string(), + detail: None, + kind: SymbolKind::Field, + range: field_range, + selection_range: field_range, + children: None, + tags: Some(vec![]), + deprecated: Some(false), + }); + } +} + #[cfg(test)] -fn assert_use_def( +fn assert_use_def_with_doc_string( mod_symbols: &UseDefMap, file_name_mapping: &BTreeMap, use_idx: usize, @@ -1993,6 +2400,7 @@ fn assert_use_def( def_file: &str, type_str: &str, type_def: Option<(u32, u32, &str)>, + doc_string: &str, ) { let uses = mod_symbols.get(use_line).unwrap(); let use_def = uses.iter().nth(use_idx).unwrap(); @@ -2005,6 +2413,8 @@ fn assert_use_def( .as_str() .ends_with(def_file)); assert!(type_str == format!("{}", use_def.use_type)); + + assert!(doc_string == use_def.doc_string); match use_def.type_def_loc { Some(type_def_loc) => { let tdef_line = type_def.unwrap().0; @@ -2022,6 +2432,258 @@ fn assert_use_def( } } +#[cfg(test)] +fn assert_use_def( + mod_symbols: &UseDefMap, + file_name_mapping: &BTreeMap, + use_idx: usize, + use_line: u32, + use_col: u32, + def_line: u32, + def_col: u32, + def_file: &str, + type_str: &str, + type_def: Option<(u32, u32, &str)>, +) { + assert_use_def_with_doc_string( + mod_symbols, + file_name_mapping, + use_idx, + use_line, + use_col, + def_line, + def_col, + def_file, + type_str, + type_def, + "", + ) +} + +#[test] +/// Tests if symbolication + doc_string information for documented Move constructs is constructed correctly. +fn docstring_test() { + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + + path.push("tests/symbols"); + + let (symbols_opt, _) = Symbolicator::get_symbols(path.as_path()).unwrap(); + let symbols = symbols_opt.unwrap(); + + let mut fpath = path.clone(); + fpath.push("sources/M6.move"); + let cpath = dunce::canonicalize(&fpath).unwrap(); + + let mod_symbols = symbols.file_use_defs.get(&cpath).unwrap(); + + // struct def name + assert_use_def_with_doc_string( + mod_symbols, + &symbols.file_name_mapping, + 0, + 4, + 11, + 4, + 11, + "M6.move", + "Symbols::M6::DocumentedStruct", + Some((4, 11, "M6.move")), + "This is a documented struct\nWith a multi-line docstring\n", + ); + + // const def name + assert_use_def_with_doc_string( + mod_symbols, + &symbols.file_name_mapping, + 0, + 10, + 10, + 10, + 10, + "M6.move", + "u64", + None, + "Constant containing the answer to the universe\n", + ); + + // function def name + assert_use_def_with_doc_string( + mod_symbols, + &symbols.file_name_mapping, + 0, + 14, + 8, + 14, + 8, + "M6.move", + "fun Symbols::M6::unpack(s: Symbols::M6::DocumentedStruct): u64", + None, + "A documented function that unpacks a DocumentedStruct\n", + ); + // param var (unpack function) + assert_use_def_with_doc_string( + mod_symbols, + &symbols.file_name_mapping, + 1, + 14, + 15, + 14, + 15, + "M6.move", + "Symbols::M6::DocumentedStruct", + Some((4, 11, "M6.move")), + "A documented function that unpacks a DocumentedStruct\n", + ); + // struct name in param type (unpack function) + assert_use_def_with_doc_string( + mod_symbols, + &symbols.file_name_mapping, + 2, + 14, + 18, + 4, + 11, + "M6.move", + "Symbols::M6::DocumentedStruct", + Some((4, 11, "M6.move")), + "This is a documented struct\nWith a multi-line docstring\n", + ); + // struct name in unpack (unpack function) + assert_use_def_with_doc_string( + mod_symbols, + &symbols.file_name_mapping, + 0, + 15, + 12, + 4, + 11, + "M6.move", + "Symbols::M6::DocumentedStruct", + Some((4, 11, "M6.move")), + "This is a documented struct\nWith a multi-line docstring\n", + ); + // field name in unpack (unpack function) + assert_use_def_with_doc_string( + mod_symbols, + &symbols.file_name_mapping, + 1, + 15, + 31, + 6, + 8, + "M6.move", + "u64", + None, + "A documented field\n", + ); + // moved var in unpack assignment (unpack function) + assert_use_def_with_doc_string( + mod_symbols, + &symbols.file_name_mapping, + 3, + 15, + 59, + 14, + 15, + "M6.move", + "Symbols::M6::DocumentedStruct", + Some((4, 11, "M6.move")), + "A documented function that unpacks a DocumentedStruct\n", + ); + + // docstring construction for multi-line /** .. */ based strings + assert_use_def_with_doc_string( + mod_symbols, + &symbols.file_name_mapping, + 0, + 26, + 8, + 26, + 8, + "M6.move", + "fun Symbols::M6::other_doc_struct(): Symbols::M7::OtherDocStruct", + Some((3, 11, "M7.move")), + "\nThis is a multiline docstring\n\nThis docstring has empty lines.\n\nIt uses the ** format instead of ///\n\n", + ); + + // docstring construction for single-line /** .. */ based strings + assert_use_def_with_doc_string( + mod_symbols, + &symbols.file_name_mapping, + 0, + 31, + 8, + 31, + 8, + "M6.move", + "fun Symbols::M6::acq(addr: address): u64 acquires Symbols::M6::DocumentedStruct", + None, + "Asterix based single-line docstring\n", + ); + + /* Test doc_string construction for struct/function imported from another module */ + + // other module struct name (other_doc_struct function) + assert_use_def_with_doc_string( + mod_symbols, + &symbols.file_name_mapping, + 1, + 26, + 41, + 3, + 11, + "M7.move", + "Symbols::M7::OtherDocStruct", + Some((3, 11, "M7.move")), + "Documented struct in another module\n", + ); + + // function name in a call (other_doc_struct function) + assert_use_def_with_doc_string( + mod_symbols, + &symbols.file_name_mapping, + 0, + 27, + 21, + 9, + 15, + "M7.move", + "fun Symbols::M7::create_other_struct(v: u64): Symbols::M7::OtherDocStruct", + Some((3, 11, "M7.move")), + "Documented initializer in another module\n", + ); + + // const in param (other_doc_struct function) + assert_use_def_with_doc_string( + mod_symbols, + &symbols.file_name_mapping, + 1, + 27, + 41, + 10, + 10, + "M6.move", + "u64", + None, + "Constant containing the answer to the universe\n", + ); + + // // other documented struct name imported (other_doc_struct_import function) + assert_use_def_with_doc_string( + mod_symbols, + &symbols.file_name_mapping, + 1, + 38, + 35, + 3, + 11, + "M7.move", + "Symbols::M7::OtherDocStruct", + Some((3, 11, "M7.move")), + "Documented struct in another module\n", + ); +} + #[test] /// Tests if symbolication information for specific Move constructs has been constructed correctly. fn symbols_test() { @@ -2034,7 +2696,7 @@ fn symbols_test() { let mut fpath = path.clone(); fpath.push("sources/M1.move"); - let cpath = fs::canonicalize(&fpath).unwrap(); + let cpath = dunce::canonicalize(&fpath).unwrap(); let mod_symbols = symbols.file_use_defs.get(&cpath).unwrap(); @@ -2074,7 +2736,7 @@ fn symbols_test() { 9, 8, "M1.move", - "fun Symbols::M1::unpack(Symbols::M1::SomeStruct): u64", + "fun Symbols::M1::unpack(s: Symbols::M1::SomeStruct): u64", None, ); // param var (unpack function) @@ -2243,7 +2905,7 @@ fn symbols_test() { 6, 15, "M2.move", - "fun Symbols::M2::some_other_struct(u64): Symbols::M2::SomeOtherStruct", + "fun Symbols::M2::some_other_struct(v: u64): Symbols::M2::SomeOtherStruct", Some((2, 11, "M2.move")), ); // const in param (other_mod_struct function) @@ -2282,7 +2944,7 @@ fn symbols_test() { 34, 8, "M1.move", - "fun Symbols::M1::acq(address): u64 acquires Symbols::M1::SomeStruct", + "fun Symbols::M1::acq(addr: address): u64 acquires Symbols::M1::SomeStruct", None, ); // struct name in acquires (acq function) @@ -2464,7 +3126,7 @@ fn symbols_test() { 61, 8, "M1.move", - "fun Symbols::M1::ret(bool, u64): u64", + "fun Symbols::M1::ret(p1: bool, p2: u64): u64", None, ); // returned value (ret function) @@ -2717,7 +3379,7 @@ fn symbols_test() { let mut fpath = path.clone(); fpath.push("sources/M3.move"); - let cpath = fs::canonicalize(&fpath).unwrap(); + let cpath = dunce::canonicalize(&fpath).unwrap(); let mod_symbols = symbols.file_use_defs.get(&cpath).unwrap(); @@ -2867,7 +3529,7 @@ fn symbols_test() { let mut fpath = path.clone(); fpath.push("sources/M4.move"); - let cpath = fs::canonicalize(&fpath).unwrap(); + let cpath = dunce::canonicalize(&fpath).unwrap(); let mod_symbols = symbols.file_use_defs.get(&cpath).unwrap(); diff --git a/language/move-analyzer/src/vfs.rs b/language/move-analyzer/src/vfs.rs index 33c96c6b1e..0773375729 100644 --- a/language/move-analyzer/src/vfs.rs +++ b/language/move-analyzer/src/vfs.rs @@ -10,24 +10,24 @@ //! basically just a mapping from file identifier (this could be the file's path were it to be //! saved) to its textual contents. +use crate::symbols; use lsp_server::Notification; use lsp_types::{ notification::Notification as _, DidChangeTextDocumentParams, DidCloseTextDocumentParams, DidOpenTextDocumentParams, DidSaveTextDocumentParams, }; - -use crate::symbols; +use std::path::PathBuf; /// A mapping from identifiers (file names, potentially, but not necessarily) to their contents. #[derive(Debug, Default)] pub struct VirtualFileSystem { - files: std::collections::HashMap, + files: std::collections::HashMap, } impl VirtualFileSystem { /// Returns a reference to the buffer corresponding to the given identifier, or `None` if it /// is not present in the system. - pub fn get(&self, identifier: &str) -> Option<&str> { + pub fn get(&self, identifier: &PathBuf) -> Option<&str> { self.files.get(identifier).map(|s| s.as_str()) } @@ -37,13 +37,12 @@ impl VirtualFileSystem { /// from the client, instead of completely replacing them each time. The rust-analyzer has a /// 'vfs' module that is capable of doing just that, but it is not published on crates.io. If /// we could help get it published, we could use it here. - pub fn update(&mut self, identifier: &str, content: &str) { - self.files - .insert(identifier.to_string(), content.to_string()); + pub fn update(&mut self, identifier: PathBuf, content: &str) { + self.files.insert(identifier, content.to_string()); } /// Removes the buffer and its identifier from the system. - pub fn remove(&mut self, identifier: &str) { + pub fn remove(&mut self, identifier: &PathBuf) { self.files.remove(identifier); } } @@ -61,17 +60,17 @@ pub fn on_text_document_sync_notification( serde_json::from_value::(notification.params.clone()) .expect("could not deserialize notification"); files.update( - parameters.text_document.uri.path(), + parameters.text_document.uri.to_file_path().unwrap(), ¶meters.text_document.text, ); - symbolicator_runner.run(parameters.text_document.uri.path()); + symbolicator_runner.run(parameters.text_document.uri.to_file_path().unwrap()); } lsp_types::notification::DidChangeTextDocument::METHOD => { let parameters = serde_json::from_value::(notification.params.clone()) .expect("could not deserialize notification"); files.update( - parameters.text_document.uri.path(), + parameters.text_document.uri.to_file_path().unwrap(), ¶meters.content_changes.last().unwrap().text, ); } @@ -80,16 +79,16 @@ pub fn on_text_document_sync_notification( serde_json::from_value::(notification.params.clone()) .expect("could not deserialize notification"); files.update( - parameters.text_document.uri.path(), + parameters.text_document.uri.to_file_path().unwrap(), ¶meters.text.unwrap(), ); - symbolicator_runner.run(parameters.text_document.uri.path()); + symbolicator_runner.run(parameters.text_document.uri.to_file_path().unwrap()); } lsp_types::notification::DidCloseTextDocument::METHOD => { let parameters = serde_json::from_value::(notification.params.clone()) .expect("could not deserialize notification"); - files.remove(parameters.text_document.uri.path()); + files.remove(¶meters.text_document.uri.to_file_path().unwrap()); } _ => eprintln!("invalid notification '{}'", notification.method), } diff --git a/language/move-analyzer/tests/symbols/sources/M6.move b/language/move-analyzer/tests/symbols/sources/M6.move new file mode 100644 index 0000000000..aa3427fa8c --- /dev/null +++ b/language/move-analyzer/tests/symbols/sources/M6.move @@ -0,0 +1,42 @@ +module Symbols::M6 { + + /// This is a documented struct + /// With a multi-line docstring + struct DocumentedStruct has key, drop, store { + /// A documented field + documented_field: u64, + } + + /// Constant containing the answer to the universe + const DOCUMENTED_CONSTANT: u64 = 42; + + + /// A documented function that unpacks a DocumentedStruct + fun unpack(s: DocumentedStruct): u64 { + let DocumentedStruct { documented_field: value } = s; + value + } + + /** + This is a multiline docstring + + This docstring has empty lines. + + It uses the ** format instead of /// + */ + fun other_doc_struct(): Symbols::M7::OtherDocStruct { + Symbols::M7::create_other_struct(DOCUMENTED_CONSTANT) + } + + /** Asterix based single-line docstring */ + fun acq(addr: address): u64 acquires DocumentedStruct { + let val = borrow_global(addr); + val.documented_field + } + + use Symbols::M7::{Self, OtherDocStruct}; + + fun other_doc_struct_import(): OtherDocStruct { + M7::create_other_struct(7) + } +} diff --git a/language/move-analyzer/tests/symbols/sources/M7.move b/language/move-analyzer/tests/symbols/sources/M7.move new file mode 100644 index 0000000000..b4165da101 --- /dev/null +++ b/language/move-analyzer/tests/symbols/sources/M7.move @@ -0,0 +1,13 @@ +module Symbols::M7 { + + /// Documented struct in another module + struct OtherDocStruct has drop { + /// Documented field in another module + some_field: u64, + } + + /// Documented initializer in another module + public fun create_other_struct(v: u64): OtherDocStruct { + OtherDocStruct { some_field: v } + } +} diff --git a/language/move-binary-format/Cargo.toml b/language/move-binary-format/Cargo.toml index 0ae756af37..36b4253144 100644 --- a/language/move-binary-format/Cargo.toml +++ b/language/move-binary-format/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/diem/diem" homepage = "https://diem.com" license = "Apache-2.0" publish = ["crates-io"] -edition = "2018" +edition = "2021" [dependencies] anyhow = "1.0.52" @@ -16,15 +16,16 @@ proptest = { version = "1.0.0", optional = true } proptest-derive = { version = "0.3.0", optional = true } ref-cast = "1.0.6" variant_count = "1.1.0" -move-core-types = { path = "../move-core/types", version = "0.0.4" } +move-core-types = { path = "../move-core/types" } serde = { version = "1.0.124", default-features = false } +arbitrary = { version = "1.1.7", optional = true, features = ["derive"] } [dev-dependencies] proptest = "1.0.0" proptest-derive = "0.3.0" -move-core-types = { path = "../move-core/types", features = ["fuzzing"] } +move-core-types = { path = "../move-core/types", features = ["fuzzing" ] } serde_json = "1.0.64" [features] default = [] -fuzzing = ["proptest", "proptest-derive", "move-core-types/fuzzing"] +fuzzing = ["proptest", "proptest-derive", "arbitrary", "move-core-types/fuzzing"] diff --git a/language/move-binary-format/serializer-tests/Cargo.toml b/language/move-binary-format/serializer-tests/Cargo.toml index a7a85baba6..1cd9077992 100644 --- a/language/move-binary-format/serializer-tests/Cargo.toml +++ b/language/move-binary-format/serializer-tests/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/diem/diem" homepage = "https://diem.com" license = "Apache-2.0" publish = false -edition = "2018" +edition = "2021" [dev-dependencies] proptest = "1.0.0" diff --git a/language/move-binary-format/src/binary_views.rs b/language/move-binary-format/src/binary_views.rs index 260233e25d..43a002dc6f 100644 --- a/language/move-binary-format/src/binary_views.rs +++ b/language/move-binary-format/src/binary_views.rs @@ -257,7 +257,7 @@ impl<'a> BinaryIndexedView<'a> { use SignatureToken::*; match ty { - Bool | U8 | U64 | U128 | Address => Ok(AbilitySet::PRIMITIVES), + Bool | U8 | U16 | U32 | U64 | U128 | U256 | Address => Ok(AbilitySet::PRIMITIVES), Reference(_) | MutableReference(_) => Ok(AbilitySet::REFERENCES), Signer => Ok(AbilitySet::SIGNER), @@ -336,8 +336,6 @@ pub struct FunctionView<'a> { impl<'a> FunctionView<'a> { // Creates a `FunctionView` for a module function. - // Creates a `FunctionView` for a module function. - // Requires control flow verifier (control_flow.rs) pub fn function( module: &'a CompiledModule, index: FunctionDefinitionIndex, diff --git a/language/move-binary-format/src/check_bounds.rs b/language/move-binary-format/src/check_bounds.rs index dccc77a14a..c60fa080c5 100644 --- a/language/move-binary-format/src/check_bounds.rs +++ b/language/move-binary-format/src/check_bounds.rs @@ -11,14 +11,13 @@ use crate::{ file_format::{ AbilitySet, Bytecode, CodeOffset, CodeUnit, CompiledModule, CompiledScript, Constant, FieldHandle, FieldInstantiation, FunctionDefinition, FunctionDefinitionIndex, - FunctionHandle, FunctionInstantiation, ModuleHandle, Signature, SignatureToken, + FunctionHandle, FunctionInstantiation, LocalIndex, ModuleHandle, Signature, SignatureToken, StructDefInstantiation, StructDefinition, StructFieldInformation, StructHandle, TableIndex, }, internals::ModuleIndex, IndexKind, }; use move_core_types::vm_status::StatusCode; -use std::u8; enum BoundsCheckingContext { Module, @@ -61,6 +60,7 @@ impl<'a> BoundsChecker<'a> { .signatures() .get(script.parameters.into_index()) .unwrap(), + CompiledScript::MAIN_INDEX.into_index(), ) } @@ -324,24 +324,29 @@ impl<'a> BoundsChecker<'a> { None => return Ok(()), }; - debug_assert!(function_def.function.into_index() < self.view.function_handles().len()); + if function_def.function.into_index() >= self.view.function_handles().len() { + return Err(verification_error( + StatusCode::INDEX_OUT_OF_BOUNDS, + IndexKind::FunctionDefinition, + function_def_idx as TableIndex, + )); + } let function_handle = &self.view.function_handles()[function_def.function.into_index()]; - - debug_assert!(function_handle.parameters.into_index() < self.view.signatures().len()); - let parameters = &self.view.signatures()[function_handle.parameters.into_index()]; - - // check if the number of parameters + locals is less than u8::MAX - let locals_count = self.get_locals(code_unit)?.len() + parameters.len(); - - if locals_count > (u8::MAX as usize) + 1 { + if function_handle.parameters.into_index() >= self.view.signatures().len() { return Err(verification_error( - StatusCode::TOO_MANY_LOCALS, + StatusCode::INDEX_OUT_OF_BOUNDS, IndexKind::FunctionDefinition, function_def_idx as TableIndex, )); } + let parameters = &self.view.signatures()[function_handle.parameters.into_index()]; - self.check_code(code_unit, &function_handle.type_parameters, parameters) + self.check_code( + code_unit, + &function_handle.type_parameters, + parameters, + function_def_idx, + ) } fn check_code( @@ -349,11 +354,21 @@ impl<'a> BoundsChecker<'a> { code_unit: &CodeUnit, type_parameters: &[AbilitySet], parameters: &Signature, + index: usize, ) -> PartialVMResult<()> { check_bounds_impl(self.view.signatures(), code_unit.locals)?; let locals = self.get_locals(code_unit)?; - let locals_count = locals.len() + parameters.len(); + // Use saturating add for stability + let locals_count = locals.len().saturating_add(parameters.len()); + + if locals_count > LocalIndex::MAX as usize { + return Err(verification_error( + StatusCode::TOO_MANY_LOCALS, + IndexKind::FunctionDefinition, + index as TableIndex, + )); + } // if there are locals check that the type parameters in local signature are in bounds. let type_param_count = type_parameters.len(); @@ -513,10 +528,11 @@ impl<'a> BoundsChecker<'a> { // List out the other options explicitly so there's a compile error if a new // bytecode gets added. - FreezeRef | Pop | Ret | LdU8(_) | LdU64(_) | LdU128(_) | CastU8 | CastU64 - | CastU128 | LdTrue | LdFalse | ReadRef | WriteRef | Add | Sub | Mul | Mod - | Div | BitOr | BitAnd | Xor | Shl | Shr | Or | And | Not | Eq | Neq | Lt | Gt - | Le | Ge | Abort | Nop => (), + FreezeRef | Pop | Ret | LdU8(_) | LdU16(_) | LdU32(_) | LdU64(_) | LdU256(_) + | LdU128(_) | CastU8 | CastU16 | CastU32 | CastU64 | CastU128 | CastU256 + | LdTrue | LdFalse | ReadRef | WriteRef | Add | Sub | Mul | Mod | Div | BitOr + | BitAnd | Xor | Shl | Shr | Or | And | Not | Eq | Neq | Lt | Gt | Le | Ge + | Abort | Nop => (), } } Ok(()) @@ -527,8 +543,8 @@ impl<'a> BoundsChecker<'a> { for ty in ty.preorder_traversal() { match ty { - Bool | U8 | U64 | U128 | Address | Signer | TypeParameter(_) | Reference(_) - | MutableReference(_) | Vector(_) => (), + Bool | U8 | U16 | U32 | U64 | U128 | U256 | Address | Signer | TypeParameter(_) + | Reference(_) | MutableReference(_) | Vector(_) => (), Struct(idx) => { check_bounds_impl(self.view.struct_handles(), *idx)?; if let Some(sh) = self.view.struct_handles().get(idx.into_index()) { @@ -585,8 +601,11 @@ impl<'a> BoundsChecker<'a> { Bool | U8 + | U16 + | U32 | U64 | U128 + | U256 | Address | Signer | Struct(_) diff --git a/language/move-binary-format/src/compatibility.rs b/language/move-binary-format/src/compatibility.rs index 258727dc2f..6ddab6d181 100644 --- a/language/move-binary-format/src/compatibility.rs +++ b/language/move-binary-format/src/compatibility.rs @@ -2,42 +2,83 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 +use std::collections::BTreeSet; + use crate::{ + errors::{PartialVMError, PartialVMResult}, file_format::{AbilitySet, StructTypeParameter, Visibility}, file_format_common::VERSION_5, normalized::Module, }; -use std::collections::BTreeSet; +use move_core_types::vm_status::StatusCode; -/// The result of a linking and layout compatibility check. Here is what the different combinations +/// The result of a linking and layout compatibility check. Here is what the different combinations. NOTE that if `check_struct_layout` is false, type safety over a series of upgrades cannot be guaranteed. /// mean: -/// `{ struct: true, struct_layout: true }`: fully backward compatible -/// `{ struct_and_function_linking: true, struct_layout: false }`: Dependent modules that reference functions or types in this module may not link. However, fixing, recompiling, and redeploying all dependent modules will work--no data migration needed. -/// `{ type_and_function_linking: true, struct_layout: false }`: Attempting to read structs published by this module will now fail at runtime. However, dependent modules will continue to link. Requires data migration, but no changes to dependent modules. -/// `{ type_and_function_linking: false, struct_layout: false }`: Everything is broken. Need both a data migration and changes to dependent modules. +/// `{ check_struct_and_pub_function_linking: true, check_struct_layout: true, check_friend_linking: true }`: fully backward compatible +/// `{ check_struct_and_pub_function_linking: true, check_struct_layout: true, check_friend_linking: false }`: Backward compatible, exclude the friend module declare and friend functions +/// `{ check_struct_and_pub_function_linking: false, check_struct_layout: true, check_friend_linking: false }`: Dependent modules that reference functions or types in this module may not link. However, fixing, recompiling, and redeploying all dependent modules will work--no data migration needed. +/// `{ check_struct_and_pub_function_linking: true, check_struct_layout: false, check_friend_linking: true }`: Attempting to read structs published by this module will now fail at runtime. However, dependent modules will continue to link. Requires data migration, but no changes to dependent modules. +/// `{ check_struct_and_pub_function_linking: false, check_struct_layout: false, check_friend_linking: false }`: Everything is broken. Need both a data migration and changes to dependent modules. #[derive(PartialEq, Eq, Debug, Clone, Copy)] pub struct Compatibility { - /// If false, dependent modules that reference functions or structs in this module may not link - pub struct_and_function_linking: bool, - /// If false, attempting to read structs previously published by this module will fail at runtime - pub struct_layout: bool, + /// if false, do not ensure the dependent modules that reference public functions or structs in this module can link + check_struct_and_pub_function_linking: bool, + /// if false, do not ensure the struct layout capability + check_struct_layout: bool, + /// if false, treat `friend` as `private` when `check_struct_and_function_linking`. + check_friend_linking: bool, +} + +impl Default for Compatibility { + fn default() -> Self { + Self { + check_struct_and_pub_function_linking: true, + check_struct_layout: true, + check_friend_linking: true, + } + } } impl Compatibility { - /// Return true if the two module s compared in the compatiblity check are both linking and - /// layout compatible. - pub fn is_fully_compatible(&self) -> bool { - self.struct_and_function_linking && self.struct_layout + pub fn full_check() -> Self { + Self::default() + } + + pub fn no_check() -> Self { + Self { + check_struct_and_pub_function_linking: false, + check_struct_layout: false, + check_friend_linking: false, + } } - /// Return compatibility assessment for `new_module` relative to old module `old_module`. - pub fn check(old_module: &Module, new_module: &Module) -> Compatibility { - let mut struct_and_function_linking = true; + pub fn new( + check_struct_and_pub_function_linking: bool, + check_struct_layout: bool, + check_friend_linking: bool, + ) -> Self { + Self { + check_struct_and_pub_function_linking, + check_struct_layout, + check_friend_linking, + } + } + + pub fn need_check_compat(&self) -> bool { + self.check_struct_and_pub_function_linking + || self.check_friend_linking + || self.check_struct_layout + } + + /// Check compatibility for `new_module` relative to old module `old_module`. + pub fn check(&self, old_module: &Module, new_module: &Module) -> PartialVMResult<()> { + let mut struct_and_pub_function_linking = true; let mut struct_layout = true; + let mut friend_linking = true; // module's name and address are unchanged if old_module.address != new_module.address || old_module.name != new_module.name { - struct_and_function_linking = false; + struct_and_pub_function_linking = false; } // old module's structs are a subset of the new module's structs @@ -46,18 +87,11 @@ impl Compatibility { Some(new_struct) => new_struct, None => { // Struct not present in new . Existing modules that depend on this struct will fail to link with the new version of the module. - struct_and_function_linking = false; - // Note: we intentionally do *not* label this a layout compatibility violation. - // Existing modules can still successfully read previously published values of - // this struct `Parent::T`. That is, code like the function `foo` in - // ``` - // struct S { t: Parent::T } - // public fun foo(a: addr): S { move_from(addr) } - // ``` - // in module `Child` will continue to run without error. But values of type - // `Parent::T` in `Child` are now "orphaned" in the sense that `Parent` no - // longer exposes any API for reading/writing them. - continue; + // Also, struct layout cannot be guaranteed transitively, because after + // removing the struct, it could be re-added later with a different layout. + struct_and_pub_function_linking = false; + struct_layout = false; + break; } }; @@ -67,22 +101,15 @@ impl Compatibility { &new_struct.type_parameters, ) { - struct_and_function_linking = false; + struct_and_pub_function_linking = false; } if new_struct.fields != old_struct.fields { // Fields changed. Code in this module will fail at runtime if it tries to // read a previously published struct value // TODO: this is a stricter definition than required. We could in principle - // choose to label the following as compatible - // (1) changing the name (but not position or type) of a field. The VM does - // not care about the name of a field (it's purely informational), but - // clients presumably do. - // (2) changing the type of a field to a different, but layout and kind - // compatible type. E.g. `struct S { b: bool }` to `struct S { b: B }` - // where - // B is struct B { some_name: bool }. TODO: does this affect clients? I - // think not--the serialization of the same data with these two types - // will be the same. + // choose that changing the name (but not position or type) of a field is + // compatible. The VM does not care about the name of a field + // (it's purely informational), but clients presumably do. struct_layout = false } } @@ -105,7 +132,11 @@ impl Compatibility { let new_func = match new_module.exposed_functions.get(name) { Some(new_func) => new_func, None => { - struct_and_function_linking = false; + if matches!(old_func.visibility, Visibility::Friend) { + friend_linking = false; + } else { + struct_and_pub_function_linking = false; + } continue; } }; @@ -140,7 +171,11 @@ impl Compatibility { &new_func.type_parameters, ) { - struct_and_function_linking = false; + if matches!(old_func.visibility, Visibility::Friend) { + friend_linking = false; + } else { + struct_and_pub_function_linking = false; + } } } @@ -149,19 +184,29 @@ impl Compatibility { // - additions to the list are allowed // - removals are not allowed // - // NOTE: we may also relax this checking a bit in the future: we may allow the removal of - // a module removed from the friend list if the module does not call any friend function - // in this module. let old_friend_module_ids: BTreeSet<_> = old_module.friends.iter().cloned().collect(); let new_friend_module_ids: BTreeSet<_> = new_module.friends.iter().cloned().collect(); if !old_friend_module_ids.is_subset(&new_friend_module_ids) { - struct_and_function_linking = false; + friend_linking = false; } - Compatibility { - struct_and_function_linking, - struct_layout, + if self.check_struct_and_pub_function_linking && !struct_and_pub_function_linking { + return Err(PartialVMError::new( + StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE, + )); + } + if self.check_struct_layout && !struct_layout { + return Err(PartialVMError::new( + StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE, + )); } + if self.check_friend_linking && !friend_linking { + return Err(PartialVMError::new( + StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE, + )); + } + + Ok(()) } } diff --git a/language/move-binary-format/src/constant.rs b/language/move-binary-format/src/constant.rs index 08f4ed8297..a6df17d72a 100644 --- a/language/move-binary-format/src/constant.rs +++ b/language/move-binary-format/src/constant.rs @@ -12,8 +12,11 @@ fn sig_to_ty(sig: &SignatureToken) -> Option { SignatureToken::Address => Some(MoveTypeLayout::Address), SignatureToken::Bool => Some(MoveTypeLayout::Bool), SignatureToken::U8 => Some(MoveTypeLayout::U8), + SignatureToken::U16 => Some(MoveTypeLayout::U16), + SignatureToken::U32 => Some(MoveTypeLayout::U32), SignatureToken::U64 => Some(MoveTypeLayout::U64), SignatureToken::U128 => Some(MoveTypeLayout::U128), + SignatureToken::U256 => Some(MoveTypeLayout::U256), SignatureToken::Vector(v) => Some(MoveTypeLayout::Vector(Box::new(sig_to_ty(v.as_ref())?))), SignatureToken::Reference(_) | SignatureToken::MutableReference(_) @@ -28,8 +31,11 @@ fn ty_to_sig(ty: &MoveTypeLayout) -> Option { MoveTypeLayout::Address => Some(SignatureToken::Address), MoveTypeLayout::Signer => Some(SignatureToken::Signer), MoveTypeLayout::U8 => Some(SignatureToken::U8), + MoveTypeLayout::U16 => Some(SignatureToken::U16), + MoveTypeLayout::U32 => Some(SignatureToken::U32), MoveTypeLayout::U64 => Some(SignatureToken::U64), MoveTypeLayout::U128 => Some(SignatureToken::U128), + MoveTypeLayout::U256 => Some(SignatureToken::U256), MoveTypeLayout::Vector(v) => Some(SignatureToken::Vector(Box::new(ty_to_sig(v.as_ref())?))), MoveTypeLayout::Struct(_) => None, MoveTypeLayout::Bool => Some(SignatureToken::Bool), diff --git a/language/move-binary-format/src/control_flow_graph.rs b/language/move-binary-format/src/control_flow_graph.rs index 9026bcf0c9..63ac1e0a29 100644 --- a/language/move-binary-format/src/control_flow_graph.rs +++ b/language/move-binary-format/src/control_flow_graph.rs @@ -4,7 +4,7 @@ //! This module defines the control-flow graph uses for bytecode verification. use crate::file_format::{Bytecode, CodeOffset}; -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::{btree_map::Entry, BTreeMap, BTreeSet}; // BTree/Hash agnostic type wrappers type Map = BTreeMap; @@ -45,6 +45,9 @@ pub trait ControlFlowGraph { /// Checks if the the edge from cur->next is a back edge /// returns false if the edge is not in the cfg fn is_back_edge(&self, cur: BlockId, next: BlockId) -> bool; + + /// Return the number of back edges in the cfg + fn num_back_edges(&self) -> usize; } struct BasicBlock { @@ -77,12 +80,7 @@ impl BasicBlock { const ENTRY_BLOCK_ID: BlockId = 0; impl VMControlFlowGraph { - // Requires checks from the control flow verifier (control_flow.rs) pub fn new(code: &[Bytecode]) -> Self { - fn is_back_edge(cur_block: BlockId, target_block: BlockId) -> bool { - target_block <= cur_block - } - let code_len = code.len() as CodeOffset; // First go through and collect block ids, i.e., offsets that begin basic blocks. // Need to do this first in order to handle backwards edges. @@ -112,56 +110,103 @@ impl VMControlFlowGraph { let blocks = blocks; assert_eq!(entry, code_len); - // Determine traversal order - // build a DAG subgraph (remove the loop back edges) - let dag: Map> = blocks - .iter() - .map(|(id, block)| { - let id = *id; - let non_loop_continue_successors = block - .successors - .iter() - // remove the loop back edges - // this simple check for back edges relies on guarantees from the control flow - // verifier (control_flow.rs) - .filter(|successor| !is_back_edge(id, **successor)) - .copied() - .collect(); - (id, non_loop_continue_successors) - }) - .collect(); - // assert it is a dag - debug_assert!(dag.iter().all(|(id, successors)| successors - .iter() - .all(|successor| !is_back_edge(*id, *successor)))); + // # Loop analysis + // + // This section identifies loops in the control-flow graph, picks a back edge and loop head + // (the basic block the back edge returns to), and decides the order that blocks are + // traversed during abstract interpretation (reverse post-order). + // + // The implementation is based on the algorithm for finding widening points in Section 4.1, + // "Depth-first numbering" of Bourdoncle [1993], "Efficient chaotic iteration strategies + // with widenings." + // + // NB. The comments below refer to a block's sub-graph -- the reflexive transitive closure + // of its successor edges, modulo cycles. + + #[derive(Copy, Clone)] + enum Exploration { + InProgress, + Done, + } + + let mut exploration: Map = Map::new(); + let mut stack = vec![ENTRY_BLOCK_ID]; + + // For every loop in the CFG that is reachable from the entry block, there is an entry in + // `loop_heads` mapping to all the back edges pointing to it, and vice versa. + // + // Entry in `loop_heads` implies loop in the CFG is justified by the comments in the loop + // below. Loop in the CFG implies entry in `loop_heads` is justified by considering the + // point at which the first node in that loop, `F` is added to the `exploration` map: + // + // - By definition `F` is part of a loop, meaning there is a block `L` such that: + // + // F - ... -> L -> F + // + // - `F` will not transition to `Done` until all the nodes reachable from it (including `L`) + // have been visited. + // - Because `F` is the first node seen in the loop, all the other nodes in the loop + // (including `L`) will be visited while `F` is `InProgress`. + // - Therefore, we will process the `L -> F` edge while `F` is `InProgress`. + // - Therefore, we will record a back edge to it. + let mut loop_heads: Map> = Map::new(); - // build the post-order traversal + // Blocks appear in `post_order` after all the blocks in their (non-reflexive) sub-graph. let mut post_order = Vec::with_capacity(blocks.len()); - let mut finished = Set::new(); - let mut stack = vec![(ENTRY_BLOCK_ID, /* is_first_visit */ true)]; - while let Some((cur, is_first_visit)) = stack.pop() { - if is_first_visit { - stack.push((cur, false)); - stack.extend( - dag[&cur] - .iter() - .filter(|successor| !finished.contains(*successor)) - .map(|successor| (*successor, /* is_first_visit */ true)), - ); - } else { - debug_assert!(dag[&cur] - .iter() - .all(|successor| finished.contains(successor))); - if finished.insert(cur) { - post_order.push(cur) + + while let Some(block) = stack.pop() { + match exploration.entry(block) { + Entry::Vacant(entry) => { + // Record the fact that exploration of this block and its sub-graph has started. + entry.insert(Exploration::InProgress); + + // Push the block back on the stack to finish processing it, and mark it as done + // once its sub-graph has been traversed. + stack.push(block); + + for succ in &blocks[&block].successors { + match exploration.get(succ) { + // This successor has never been visited before, add it to the stack to + // be explored before `block` gets marked `Done`. + None => stack.push(*succ), + + // This block's sub-graph was being explored, meaning it is a (reflexive + // transitive) predecessor of `block` as well as being a successor, + // implying a loop has been detected -- greedily choose the successor + // block as the loop head. + Some(Exploration::InProgress) => { + loop_heads.entry(*succ).or_default().insert(block); + } + + // Cross-edge detected, this block and its entire sub-graph (modulo + // cycles) has already been explored via a different path, and is + // already present in `post_order`. + Some(Exploration::Done) => { /* skip */ } + }; + } } + + Entry::Occupied(mut entry) => match entry.get() { + // Already traversed the sub-graph reachable from this block, so skip it. + Exploration::Done => continue, + + // Finish up the traversal by adding this block to the post-order traversal + // after its sub-graph (modulo cycles). + Exploration::InProgress => { + post_order.push(block); + entry.insert(Exploration::Done); + } + }, } } - // traversal order is the reverse post-order + let traversal_order = { + // This reverse post order is akin to a topological sort (ignoring cycles) and is + // different from a pre-order in the presence of diamond patterns in the graph. post_order.reverse(); post_order }; + // build a mapping from a block id to the next block id in the traversal order let traversal_successors = traversal_order .windows(2) @@ -171,18 +216,6 @@ impl VMControlFlowGraph { }) .collect(); - // Gather loop head information - let mut loop_heads: Map> = Map::new(); - for (id, block) in &blocks { - for successor in &block.successors { - // this simple check for back edges relies on guarantees from the control flow - // verifier (control_flow.rs) - if is_back_edge(*id, *successor) { - loop_heads.entry(*successor).or_default().insert(*id); - } - } - } - VMControlFlowGraph { blocks, traversal_successors, @@ -295,4 +328,10 @@ impl ControlFlowGraph for VMControlFlowGraph { .get(&next) .map_or(false, |back_edges| back_edges.contains(&cur)) } + + fn num_back_edges(&self) -> usize { + self.loop_heads + .iter() + .fold(0, |acc, (_, edges)| acc + edges.len()) + } } diff --git a/language/move-binary-format/src/deserializer.rs b/language/move-binary-format/src/deserializer.rs index 3f68235c8d..33ca060009 100644 --- a/language/move-binary-format/src/deserializer.rs +++ b/language/move-binary-format/src/deserializer.rs @@ -4,7 +4,7 @@ use crate::{check_bounds::BoundsChecker, errors::*, file_format::*, file_format_common::*}; use move_core_types::{ - account_address::AccountAddress, identifier::Identifier, metadata::Metadata, + account_address::AccountAddress, identifier::Identifier, metadata::Metadata, state::VMState, vm_status::StatusCode, }; use std::{collections::HashSet, convert::TryInto, io::Read}; @@ -12,7 +12,15 @@ use std::{collections::HashSet, convert::TryInto, io::Read}; impl CompiledScript { /// Deserializes a &[u8] slice into a `CompiledScript` instance. pub fn deserialize(binary: &[u8]) -> BinaryLoaderResult { - let script = CompiledScript::deserialize_no_check_bounds(binary)?; + Self::deserialize_with_max_version(binary, VERSION_MAX) + } + + /// Deserializes a &[u8] slice into a `CompiledScript` instance. + pub fn deserialize_with_max_version( + binary: &[u8], + max_binary_format_version: u32, + ) -> BinaryLoaderResult { + let script = deserialize_compiled_script(binary, max_binary_format_version)?; BoundsChecker::verify_script(&script)?; Ok(script) } @@ -20,21 +28,42 @@ impl CompiledScript { // exposed as a public function to enable testing the deserializer #[doc(hidden)] pub fn deserialize_no_check_bounds(binary: &[u8]) -> BinaryLoaderResult { - deserialize_compiled_script(binary) + deserialize_compiled_script(binary, VERSION_MAX) } } impl CompiledModule { /// Deserialize a &[u8] slice into a `CompiledModule` instance. pub fn deserialize(binary: &[u8]) -> BinaryLoaderResult { - let module = CompiledModule::deserialize_no_check_bounds(binary)?; - BoundsChecker::verify_module(&module)?; - Ok(module) + Self::deserialize_with_max_version(binary, VERSION_MAX) + } + + /// Deserialize a &[u8] slice into a `CompiledModule` instance, up to the specified version. + pub fn deserialize_with_max_version( + binary: &[u8], + max_binary_format_version: u32, + ) -> BinaryLoaderResult { + let prev_state = move_core_types::state::set_state(VMState::DESERIALIZER); + let result = std::panic::catch_unwind(|| { + let module = deserialize_compiled_module(binary, max_binary_format_version)?; + BoundsChecker::verify_module(&module)?; + + Ok(module) + }) + .unwrap_or_else(|_| { + Err(PartialVMError::new( + StatusCode::VERIFIER_INVARIANT_VIOLATION, + )) + }); + move_core_types::state::set_state(prev_state); + + result } // exposed as a public function to enable testing the deserializer + #[doc(hidden)] pub fn deserialize_no_check_bounds(binary: &[u8]) -> BinaryLoaderResult { - deserialize_compiled_module(binary) + deserialize_compiled_module(binary, VERSION_MAX) } } @@ -57,6 +86,22 @@ impl Table { } } +fn read_u16_internal(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + let mut u16_bytes = [0; 2]; + cursor + .read_exact(&mut u16_bytes) + .map_err(|_| PartialVMError::new(StatusCode::BAD_U16))?; + Ok(u16::from_le_bytes(u16_bytes)) +} + +fn read_u32_internal(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + let mut u32_bytes = [0; 4]; + cursor + .read_exact(&mut u32_bytes) + .map_err(|_| PartialVMError::new(StatusCode::BAD_U32))?; + Ok(u32::from_le_bytes(u32_bytes)) +} + fn read_u64_internal(cursor: &mut VersionedCursor) -> BinaryLoaderResult { let mut u64_bytes = [0; 8]; cursor @@ -73,6 +118,16 @@ fn read_u128_internal(cursor: &mut VersionedCursor) -> BinaryLoaderResult Ok(u128::from_le_bytes(u128_bytes)) } +fn read_u256_internal( + cursor: &mut VersionedCursor, +) -> BinaryLoaderResult { + let mut u256_bytes = [0; 32]; + cursor + .read_exact(&mut u256_bytes) + .map_err(|_| PartialVMError::new(StatusCode::BAD_U256))?; + Ok(move_core_types::u256::U256::from_le_bytes(&u256_bytes)) +} + // // Helpers to read all uleb128 encoded integers. // @@ -256,9 +311,12 @@ fn load_local_index(cursor: &mut VersionedCursor) -> BinaryLoaderResult { } /// Module internal function that manages deserialization of transactions. -fn deserialize_compiled_script(binary: &[u8]) -> BinaryLoaderResult { +fn deserialize_compiled_script( + binary: &[u8], + max_binary_format_version: u32, +) -> BinaryLoaderResult { let binary_len = binary.len(); - let mut cursor = VersionedCursor::new(binary)?; + let mut cursor = VersionedCursor::new(binary, max_binary_format_version)?; let table_count = load_table_count(&mut cursor)?; let mut tables: Vec = Vec::new(); read_tables(&mut cursor, table_count, &mut tables)?; @@ -287,9 +345,12 @@ fn deserialize_compiled_script(binary: &[u8]) -> BinaryLoaderResult BinaryLoaderResult { +fn deserialize_compiled_module( + binary: &[u8], + max_binary_format_version: u32, +) -> BinaryLoaderResult { let binary_len = binary.len(); - let mut cursor = VersionedCursor::new(binary)?; + let mut cursor = VersionedCursor::new(binary, max_binary_format_version)?; let table_count = load_table_count(&mut cursor)?; let mut tables: Vec
= Vec::new(); read_tables(&mut cursor, table_count, &mut tables)?; @@ -971,11 +1032,26 @@ fn load_signature_token(cursor: &mut VersionedCursor) -> BinaryLoaderResult { + return Err( + PartialVMError::new(StatusCode::MALFORMED).with_message(format!( + "u16, u32, u256 integers not supported in bytecode version {}", + cursor.version() + )), + ); + } + _ => (), + }; + Ok(match S::from_u8(byte)? { S::BOOL => T::Saturated(SignatureToken::Bool), S::U8 => T::Saturated(SignatureToken::U8), + S::U16 => T::Saturated(SignatureToken::U16), + S::U32 => T::Saturated(SignatureToken::U32), S::U64 => T::Saturated(SignatureToken::U64), S::U128 => T::Saturated(SignatureToken::U128), + S::U256 => T::Saturated(SignatureToken::U256), S::ADDRESS => T::Saturated(SignatureToken::Address), S::SIGNER => T::Saturated(SignatureToken::Signer), S::VECTOR => T::Vector, @@ -988,6 +1064,10 @@ fn load_signature_token(cursor: &mut VersionedCursor) -> BinaryLoaderResult { let sh_idx = load_struct_handle_index(cursor)?; let arity = load_type_parameter_count(cursor)?; + if arity == 0 { + return Err(PartialVMError::new(StatusCode::MALFORMED) + .with_message("Struct inst with arity 0".to_string())); + } T::StructInst { sh_idx, arity, @@ -1378,6 +1458,26 @@ fn load_code(cursor: &mut VersionedCursor, code: &mut Vec) -> BinaryLo } _ => {} }; + + match opcode { + Opcodes::LD_U16 + | Opcodes::LD_U32 + | Opcodes::LD_U256 + | Opcodes::CAST_U16 + | Opcodes::CAST_U32 + | Opcodes::CAST_U256 + if (cursor.version() < VERSION_6) => + { + return Err( + PartialVMError::new(StatusCode::MALFORMED).with_message(format!( + "Loading or casting u16, u32, u256 integers not supported in bytecode version {}", + cursor.version() + )), + ); + } + _ => (), + }; + // conversion let bytecode = match opcode { Opcodes::POP => Bytecode::Pop, @@ -1479,6 +1579,21 @@ fn load_code(cursor: &mut VersionedCursor, code: &mut Vec) -> BinaryLo Bytecode::VecUnpack(load_signature_index(cursor)?, read_u64_internal(cursor)?) } Opcodes::VEC_SWAP => Bytecode::VecSwap(load_signature_index(cursor)?), + Opcodes::LD_U16 => { + let value = read_u16_internal(cursor)?; + Bytecode::LdU16(value) + } + Opcodes::LD_U32 => { + let value = read_u32_internal(cursor)?; + Bytecode::LdU32(value) + } + Opcodes::LD_U256 => { + let value = read_u256_internal(cursor)?; + Bytecode::LdU256(value) + } + Opcodes::CAST_U16 => Bytecode::CastU16, + Opcodes::CAST_U32 => Bytecode::CastU32, + Opcodes::CAST_U256 => Bytecode::CastU256, }; code.push(bytecode); } @@ -1523,6 +1638,9 @@ impl SerializedType { 0xA => Ok(SerializedType::VECTOR), 0xB => Ok(SerializedType::STRUCT_INST), 0xC => Ok(SerializedType::SIGNER), + 0xD => Ok(SerializedType::U16), + 0xE => Ok(SerializedType::U32), + 0xF => Ok(SerializedType::U256), _ => Err(PartialVMError::new(StatusCode::UNKNOWN_SERIALIZED_TYPE)), } } @@ -1650,6 +1768,12 @@ impl Opcodes { 0x45 => Ok(Opcodes::VEC_POP_BACK), 0x46 => Ok(Opcodes::VEC_UNPACK), 0x47 => Ok(Opcodes::VEC_SWAP), + 0x48 => Ok(Opcodes::LD_U16), + 0x49 => Ok(Opcodes::LD_U32), + 0x4A => Ok(Opcodes::LD_U256), + 0x4B => Ok(Opcodes::CAST_U16), + 0x4C => Ok(Opcodes::CAST_U32), + 0x4D => Ok(Opcodes::CAST_U256), _ => Err(PartialVMError::new(StatusCode::UNKNOWN_OPCODE)), } } diff --git a/language/move-binary-format/src/errors.rs b/language/move-binary-format/src/errors.rs index 9f56314968..5d4ad1a7f6 100644 --- a/language/move-binary-format/src/errors.rs +++ b/language/move-binary-format/src/errors.rs @@ -41,8 +41,11 @@ impl ExecutionState { } } -#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] -pub struct VMError { +#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)] +pub struct VMError(Box); + +#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)] +struct VMError_ { major_status: StatusCode, sub_status: Option, message: Option, @@ -54,13 +57,13 @@ pub struct VMError { impl VMError { pub fn into_vm_status(self) -> VMStatus { - let VMError { + let VMError_ { major_status, sub_status, location, mut offsets, .. - } = self; + } = *self.0; match (major_status, sub_status, location) { (StatusCode::EXECUTED, sub_status, _) => { debug_assert!(sub_status.is_none()); @@ -82,10 +85,17 @@ impl VMError { VMStatus::Error(StatusCode::ABORTED) } - // TODO Errors for OUT_OF_GAS do not always have index set (major_status, sub_status, location) if major_status.status_type() == StatusType::Execution => { + let abort_location = match &location { + Location::Script => vm_status::AbortLocation::Script, + Location::Module(id) => vm_status::AbortLocation::Module(id.clone()), + Location::Undefined => { + return VMStatus::Error(major_status); + } + }; + // Errors for OUT_OF_GAS do not always have index set: if it does not, it should already return above. debug_assert!( offsets.len() == 1, "Unexpected offsets. major_status: {:?}\ @@ -97,13 +107,6 @@ impl VMError { location, offsets ); - let abort_location = match location { - Location::Script => vm_status::AbortLocation::Script, - Location::Module(id) => vm_status::AbortLocation::Module(id), - Location::Undefined => { - return VMStatus::Error(major_status); - } - }; let (function, code_offset) = match offsets.pop() { None => { return VMStatus::Error(major_status); @@ -123,39 +126,39 @@ impl VMError { } pub fn major_status(&self) -> StatusCode { - self.major_status + self.0.major_status } pub fn sub_status(&self) -> Option { - self.sub_status + self.0.sub_status } pub fn message(&self) -> Option<&String> { - self.message.as_ref() + self.0.message.as_ref() } pub fn exec_state(&self) -> Option<&ExecutionState> { - self.exec_state.as_ref() + self.0.exec_state.as_ref() } pub fn remove_exec_state(&mut self) { - self.exec_state = None; + self.0.exec_state = None; } pub fn location(&self) -> &Location { - &self.location + &self.0.location } pub fn indices(&self) -> &Vec<(IndexKind, TableIndex)> { - &self.indices + &self.0.indices } pub fn offsets(&self) -> &Vec<(FunctionDefinitionIndex, CodeOffset)> { - &self.offsets + &self.0.offsets } pub fn status_type(&self) -> StatusType { - self.major_status.status_type() + self.0.major_status.status_type() } pub fn all_data( @@ -169,7 +172,7 @@ impl VMError { Vec<(IndexKind, TableIndex)>, Vec<(FunctionDefinitionIndex, CodeOffset)>, ) { - let VMError { + let VMError_ { major_status, sub_status, message, @@ -177,7 +180,7 @@ impl VMError { location, indices, offsets, - } = self; + } = *self.0; ( major_status, sub_status, @@ -190,7 +193,7 @@ impl VMError { } pub fn to_partial(self) -> PartialVMError { - let VMError { + let VMError_ { major_status, sub_status, message, @@ -198,22 +201,54 @@ impl VMError { indices, offsets, .. - } = self; - PartialVMError { + } = *self.0; + PartialVMError(Box::new(PartialVMError_ { major_status, sub_status, message, exec_state, indices, offsets, - } + })) + } +} + +impl fmt::Debug for VMError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } +} + +impl fmt::Debug for VMError_ { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { + major_status, + sub_status, + message, + exec_state, + location, + indices, + offsets, + } = self; + f.debug_struct("VMError") + .field("major_status", major_status) + .field("sub_status", sub_status) + .field("message", message) + .field("exec_state", exec_state) + .field("location", location) + .field("indices", indices) + .field("offsets", offsets) + .finish() } } impl std::error::Error for VMError {} -#[derive(Debug, Clone)] -pub struct PartialVMError { +#[derive(Clone)] +pub struct PartialVMError(Box); + +#[derive(Clone)] +struct PartialVMError_ { major_status: StatusCode, sub_status: Option, message: Option, @@ -233,14 +268,14 @@ impl PartialVMError { Vec<(IndexKind, TableIndex)>, Vec<(FunctionDefinitionIndex, CodeOffset)>, ) { - let PartialVMError { + let PartialVMError_ { major_status, sub_status, message, exec_state, indices, offsets, - } = self; + } = *self.0; ( major_status, sub_status, @@ -252,15 +287,15 @@ impl PartialVMError { } pub fn finish(self, location: Location) -> VMError { - let PartialVMError { + let PartialVMError_ { major_status, sub_status, message, exec_state, indices, offsets, - } = self; - VMError { + } = *self.0; + VMError(Box::new(VMError_ { major_status, sub_status, message, @@ -268,96 +303,82 @@ impl PartialVMError { location, indices, offsets, - } + })) } pub fn new(major_status: StatusCode) -> Self { - Self { + Self(Box::new(PartialVMError_ { major_status, sub_status: None, message: None, exec_state: None, indices: vec![], offsets: vec![], - } + })) } pub fn major_status(&self) -> StatusCode { - self.major_status + self.0.major_status } - pub fn with_sub_status(self, sub_status: u64) -> Self { - debug_assert!(self.sub_status.is_none()); - Self { - sub_status: Some(sub_status), - ..self - } + pub fn with_sub_status(mut self, sub_status: u64) -> Self { + debug_assert!(self.0.sub_status.is_none()); + self.0.sub_status = Some(sub_status); + self } - pub fn with_message(self, message: String) -> Self { - debug_assert!(self.message.is_none()); - Self { - message: Some(message), - ..self - } + pub fn with_message(mut self, message: String) -> Self { + debug_assert!(self.0.message.is_none()); + self.0.message = Some(message); + self } - pub fn with_exec_state(self, exec_state: ExecutionState) -> Self { - debug_assert!(self.exec_state.is_none()); - Self { - exec_state: Some(exec_state), - ..self - } + pub fn with_exec_state(mut self, exec_state: ExecutionState) -> Self { + debug_assert!(self.0.exec_state.is_none()); + self.0.exec_state = Some(exec_state); + self } - pub fn at_index(self, kind: IndexKind, index: TableIndex) -> Self { - let mut indices = self.indices; - indices.push((kind, index)); - Self { indices, ..self } + pub fn at_index(mut self, kind: IndexKind, index: TableIndex) -> Self { + self.0.indices.push((kind, index)); + self } - pub fn at_indices(self, additional_indices: Vec<(IndexKind, TableIndex)>) -> Self { - let mut indices = self.indices; - indices.extend(additional_indices); - Self { indices, ..self } + pub fn at_indices(mut self, additional_indices: Vec<(IndexKind, TableIndex)>) -> Self { + self.0.indices.extend(additional_indices); + self } - pub fn at_code_offset(self, function: FunctionDefinitionIndex, offset: CodeOffset) -> Self { - let mut offsets = self.offsets; - offsets.push((function, offset)); - Self { offsets, ..self } + pub fn at_code_offset(mut self, function: FunctionDefinitionIndex, offset: CodeOffset) -> Self { + self.0.offsets.push((function, offset)); + self } pub fn at_code_offsets( - self, + mut self, additional_offsets: Vec<(FunctionDefinitionIndex, CodeOffset)>, ) -> Self { - let mut offsets = self.offsets; - offsets.extend(additional_offsets); - Self { offsets, ..self } + self.0.offsets.extend(additional_offsets); + self } /// Append the message `message` to the message field of the VM status, and insert a seperator /// if the original message is non-empty. pub fn append_message_with_separator( - self, + mut self, separator: char, additional_message: String, ) -> Self { - let message = match self.message { - Some(mut msg) => { + match self.0.message.as_mut() { + Some(msg) => { if !msg.is_empty() { msg.push(separator); } msg.push_str(&additional_message); - msg } - None => additional_message, + None => self.0.message = Some(additional_message), }; - Self { - message: Some(message), - ..self - } + self } } @@ -373,20 +394,20 @@ impl fmt::Display for Location { impl fmt::Display for PartialVMError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut status = format!("PartialVMError with status {:#?}", self.major_status); + let mut status = format!("PartialVMError with status {:#?}", self.0.major_status); - if let Some(sub_status) = self.sub_status { + if let Some(sub_status) = self.0.sub_status { status = format!("{} with sub status {}", status, sub_status); } - if let Some(msg) = &self.message { + if let Some(msg) = &self.0.message { status = format!("{} and message {}", status, msg); } - for (kind, index) in &self.indices { + for (kind, index) in &self.0.indices { status = format!("{} at index {} for {}", status, index, kind); } - for (fdef, code_offset) in &self.offsets { + for (fdef, code_offset) in &self.0.offsets { status = format!( "{} at code offset {} in function definition {}", status, code_offset, fdef @@ -399,22 +420,22 @@ impl fmt::Display for PartialVMError { impl fmt::Display for VMError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut status = format!("VMError with status {:#?}", self.major_status); + let mut status = format!("VMError with status {:#?}", self.0.major_status); - if let Some(sub_status) = self.sub_status { + if let Some(sub_status) = self.0.sub_status { status = format!("{} with sub status {}", status, sub_status); } - status = format!("{} at location {}", status, self.location); + status = format!("{} at location {}", status, self.0.location); - if let Some(msg) = &self.message { + if let Some(msg) = &self.0.message { status = format!("{} and message {}", status, msg); } - for (kind, index) in &self.indices { + for (kind, index) in &self.0.indices { status = format!("{} at index {} for {}", status, index, kind); } - for (fdef, code_offset) in &self.offsets { + for (fdef, code_offset) in &self.0.offsets { status = format!( "{} at code offset {} in function definition {}", status, code_offset, fdef @@ -477,6 +498,33 @@ pub fn verification_error(status: StatusCode, kind: IndexKind, idx: TableIndex) PartialVMError::new(status).at_index(kind, idx) } +impl fmt::Debug for PartialVMError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } +} + +impl fmt::Debug for PartialVMError_ { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { + major_status, + sub_status, + message, + exec_state, + indices, + offsets, + } = self; + f.debug_struct("PartialVMError") + .field("major_status", major_status) + .field("sub_status", sub_status) + .field("message", message) + .field("exec_state", exec_state) + .field("indices", indices) + .field("offsets", offsets) + .finish() + } +} + impl std::error::Error for PartialVMError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None diff --git a/language/move-binary-format/src/file_format.rs b/language/move-binary-format/src/file_format.rs index e6a92f591f..0be6b85fb8 100644 --- a/language/move-binary-format/src/file_format.rs +++ b/language/move-binary-format/src/file_format.rs @@ -43,8 +43,6 @@ use move_core_types::{ }; #[cfg(any(test, feature = "fuzzing"))] use proptest::{collection::vec, prelude::*, strategy::BoxedStrategy}; -#[cfg(any(test, feature = "fuzzing"))] -use proptest_derive::Arbitrary; use ref_cast::RefCast; use serde::{Deserialize, Serialize}; use std::ops::BitOr; @@ -60,8 +58,9 @@ macro_rules! define_index { doc: $comment: literal, } => { #[derive(Clone, Copy, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] - #[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] + #[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] + #[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] #[doc=$comment] pub struct $name(pub TableIndex); @@ -216,8 +215,9 @@ pub const NO_TYPE_ARGUMENTS: SignatureIndex = SignatureIndex(0); /// Type definitions (fields) are private to the module. Outside the module a /// Type is an opaque handle. #[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct ModuleHandle { /// Index into the `AddressIdentifierIndex`. Identifies module-holding account's address. pub address: AddressIdentifierIndex, @@ -239,8 +239,9 @@ pub struct ModuleHandle { /// At link time ability/constraint checking is performed and an error is reported if there is a /// mismatch with the definition. #[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct StructHandle { /// The module that defines the type. pub module: ModuleHandleIndex, @@ -262,8 +263,9 @@ impl StructHandle { /// A type parameter used in the declaration of a struct. #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct StructTypeParameter { /// The type parameter constraints. pub constraints: AbilitySet, @@ -279,8 +281,9 @@ pub struct StructTypeParameter { /// ensure the function reference is valid and it is also used by the verifier to type check /// function calls. #[derive(Clone, Debug, Eq, Hash, PartialEq)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(params = "usize"))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct FunctionHandle { /// The module that defines the function. pub module: ModuleHandleIndex, @@ -296,8 +299,9 @@ pub struct FunctionHandle { /// A field access info (owner type and offset) #[derive(Clone, Debug, Eq, Hash, PartialEq)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct FieldHandle { pub owner: StructDefinitionIndex, pub field: MemberCount, @@ -308,8 +312,9 @@ pub struct FieldHandle { /// `StructFieldInformation` indicates whether a struct is native or has user-specified fields #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub enum StructFieldInformation { Native, Declared(Vec), @@ -325,8 +330,9 @@ pub enum StructFieldInformation { /// A complete or partial instantiation of a generic struct #[derive(Clone, Debug, Eq, Hash, PartialEq)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct StructDefInstantiation { pub def: StructDefinitionIndex, pub type_parameters: SignatureIndex, @@ -334,8 +340,9 @@ pub struct StructDefInstantiation { /// A complete or partial instantiation of a function #[derive(Clone, Debug, Eq, Hash, PartialEq)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct FunctionInstantiation { pub handle: FunctionHandleIndex, pub type_parameters: SignatureIndex, @@ -346,10 +353,11 @@ pub struct FunctionInstantiation { /// A `FieldInstantiation` points to a generic `FieldHandle` and the instantiation /// of the owner type. /// E.g. for `S.f` where `f` is a field of any type, `instantiation` -/// would be `[u8, boo]` +/// would be `[u8, bool]` #[derive(Clone, Debug, Eq, Hash, PartialEq)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct FieldInstantiation { pub handle: FieldHandleIndex, pub type_parameters: SignatureIndex, @@ -358,8 +366,9 @@ pub struct FieldInstantiation { /// A `StructDefinition` is a type definition. It either indicates it is native or defines all the /// user-specified fields declared on the type. #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct StructDefinition { /// The `StructHandle` for this `StructDefinition`. This has the name and the abilities /// for the type. @@ -390,8 +399,9 @@ impl StructDefinition { /// A `FieldDefinition` is the definition of a field: its name and the field type. #[derive(Clone, Debug, Eq, PartialEq)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct FieldDefinition { /// The name of the field. pub name: IdentifierIndex, @@ -402,8 +412,9 @@ pub struct FieldDefinition { /// `Visibility` restricts the accessibility of the associated entity. /// - For function visibility, it restricts who may call into the associated function. #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] #[repr(u8)] pub enum Visibility { /// Accessible within its defining module only. @@ -443,8 +454,9 @@ impl std::convert::TryFrom for Visibility { /// A `FunctionDefinition` is the implementation of a function. It defines /// the *prototype* of the function and the function body. #[derive(Clone, Debug, Default, Eq, PartialEq)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(params = "usize"))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct FunctionDefinition { /// The prototype of the function (module, name, signature). pub function: FunctionHandleIndex, @@ -495,16 +507,18 @@ impl FunctionDefinition { /// A type definition. `SignatureToken` allows the definition of the set of known types and their /// composition. #[derive(Clone, Debug, Eq, Hash, PartialEq)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct TypeSignature(pub SignatureToken); // TODO: remove at some point or move it in the front end (language/move-ir-compiler) /// A `FunctionSignature` in internally used to create a unique representation of the overall /// signature as need. Consider deprecated... #[derive(Clone, Debug, Eq, Hash, PartialEq)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(params = "usize"))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct FunctionSignature { /// The list of return types. #[cfg_attr( @@ -527,8 +541,9 @@ pub struct FunctionSignature { /// Locals include the arguments to the function from position `0` to argument `count - 1`. /// The remaining elements are the type of each local. #[derive(Clone, Debug, Default, Eq, Hash, PartialEq, Ord, PartialOrd)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(params = "usize"))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct Signature( #[cfg_attr( any(test, feature = "fuzzing"), @@ -558,7 +573,8 @@ pub type TypeParameterIndex = u16; /// An `Ability` classifies what operations are permitted for a given type #[repr(u8)] #[derive(Debug, Clone, Eq, Copy, Hash, Ord, PartialEq, PartialOrd)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub enum Ability { /// Allows values of types with this ability to be copied, via CopyLoc or ReadRef Copy = 0x1, @@ -609,6 +625,7 @@ impl Ability { /// A set of `Ability`s #[derive(Clone, Eq, Copy, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize)] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct AbilitySet(u8); impl AbilitySet { @@ -634,6 +651,10 @@ impl AbilitySet { | (Ability::Key as u8), ); + pub fn singleton(ability: Ability) -> Self { + Self(ability as u8) + } + pub fn has_ability(self, ability: Ability) -> bool { let a = ability as u8; (a & self.0) == a @@ -816,6 +837,7 @@ impl Arbitrary for AbilitySet { /// A SignatureToken can express more types than the VM can handle safely, and correctness is /// enforced by the verifier. #[derive(Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub enum SignatureToken { /// Boolean, `true` or `false`. Bool, @@ -840,6 +862,12 @@ pub enum SignatureToken { MutableReference(Box), /// Type parameter. TypeParameter(TypeParameterIndex), + /// Unsigned integers, 16 bits length. + U16, + /// Unsigned integers, 32 bits length. + U32, + /// Unsigned integers, 256 bits length. + U256, } /// An iterator to help traverse the `SignatureToken` in a non-recursive fashion to avoid @@ -867,7 +895,8 @@ impl<'a> Iterator for SignatureTokenPreorderTraversalIter<'a> { self.stack.extend(inner_toks.iter().rev()) } - Signer | Bool | Address | U8 | U64 | U128 | Struct(_) | TypeParameter(_) => (), + Signer | Bool | Address | U8 | U16 | U32 | U64 | U128 | U256 | Struct(_) + | TypeParameter(_) => (), } Some(tok) } @@ -899,7 +928,8 @@ impl<'a> Iterator for SignatureTokenPreorderTraversalIterWithDepth<'a> { .stack .extend(inner_toks.iter().map(|tok| (tok, depth + 1)).rev()), - Signer | Bool | Address | U8 | U64 | U128 | Struct(_) | TypeParameter(_) => (), + Signer | Bool | Address | U8 | U16 | U32 | U64 | U128 | U256 | Struct(_) + | TypeParameter(_) => (), } Some((tok, depth)) } @@ -920,8 +950,11 @@ impl Arbitrary for SignatureToken { let leaf = prop_oneof![ Just(Bool), Just(U8), + Just(U16), + Just(U32), Just(U64), Just(U128), + Just(U256), Just(Address), any::().prop_map(Struct), any::().prop_map(TypeParameter), @@ -947,8 +980,11 @@ impl std::fmt::Debug for SignatureToken { match self { SignatureToken::Bool => write!(f, "Bool"), SignatureToken::U8 => write!(f, "U8"), + SignatureToken::U16 => write!(f, "U16"), + SignatureToken::U32 => write!(f, "U32"), SignatureToken::U64 => write!(f, "U64"), SignatureToken::U128 => write!(f, "U128"), + SignatureToken::U256 => write!(f, "U256"), SignatureToken::Address => write!(f, "Address"), SignatureToken::Signer => write!(f, "Signer"), SignatureToken::Vector(boxed) => write!(f, "Vector({:?})", boxed), @@ -976,8 +1012,11 @@ impl SignatureToken { MutableReference(_) => SignatureTokenKind::MutableReference, Bool | U8 + | U16 + | U32 | U64 | U128 + | U256 | Address | Signer | Struct(_) @@ -993,7 +1032,7 @@ impl SignatureToken { pub fn is_integer(&self) -> bool { use SignatureToken::*; match self { - U8 | U64 | U128 => true, + U8 | U16 | U32 | U64 | U128 | U256 => true, Bool | Address | Signer @@ -1033,7 +1072,7 @@ impl SignatureToken { use SignatureToken::*; match self { - Bool | U8 | U64 | U128 | Address => true, + Bool | U8 | U16 | U32 | U64 | U128 | U256 | Address => true, Vector(inner) => inner.is_valid_for_constant(), Signer | Struct(_) @@ -1076,6 +1115,7 @@ impl SignatureToken { /// A `Constant` is a serialized value along with its type. That type will be deserialized by the /// loader/evauluator #[derive(Clone, Debug, Eq, PartialEq, Hash)] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct Constant { pub type_: SignatureToken, pub data: Vec, @@ -1083,8 +1123,9 @@ pub struct Constant { /// A `CodeUnit` is the body of a function. It has the function header and the instruction stream. #[derive(Clone, Debug, Default, Eq, PartialEq)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(params = "usize"))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct CodeUnit { /// List of locals type. All locals are typed. pub locals: SignatureIndex, @@ -1102,8 +1143,9 @@ pub struct CodeUnit { /// Bytecodes operate on a stack machine and each bytecode has side effect on the stack and the /// instruction stream. #[derive(Clone, Hash, Eq, VariantCount, PartialEq)] -#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] +#[cfg_attr(any(test, feature = "fuzzing"), derive(proptest_derive::Arbitrary))] #[cfg_attr(any(test, feature = "fuzzing"), proptest(no_params))] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub enum Bytecode { /// Pop and discard the value at the top of the stack. /// The value on the stack must be an copyable type. @@ -1168,7 +1210,7 @@ pub enum Bytecode { /// /// Stack transition: /// - /// ```..., integer_value -> ..., u8_value``` + /// ```..., integer_value -> ..., u64_value``` CastU64, /// Convert the value at the top of the stack into u128. /// @@ -1557,10 +1599,44 @@ pub enum Bytecode { /// /// ```..., vector_reference, u64_value(1), u64_value(2) -> ...``` VecSwap(SignatureIndex), + /// Push a U16 constant onto the stack. + /// + /// Stack transition: + /// + /// ```... -> ..., u16_value``` + LdU16(u16), + /// Push a U32 constant onto the stack. + /// + /// Stack transition: + /// + /// ```... -> ..., u32_value``` + LdU32(u32), + /// Push a U256 constant onto the stack. + /// + /// Stack transition: + /// + /// ```... -> ..., u256_value``` + LdU256(move_core_types::u256::U256), + /// Convert the value at the top of the stack into u16. + /// + /// Stack transition: + /// + /// ```..., integer_value -> ..., u16_value``` + CastU16, + /// Convert the value at the top of the stack into u32. + /// + /// Stack transition: + /// + /// ```..., integer_value -> ..., u32_value``` + CastU32, + /// Convert the value at the top of the stack into u256. + /// + /// Stack transition: + /// + /// ```..., integer_value -> ..., u256_value``` + CastU256, } -pub const NUMBER_OF_NATIVE_FUNCTIONS: usize = 18; - impl ::std::fmt::Debug for Bytecode { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { match self { @@ -1570,11 +1646,17 @@ impl ::std::fmt::Debug for Bytecode { Bytecode::BrFalse(a) => write!(f, "BrFalse({})", a), Bytecode::Branch(a) => write!(f, "Branch({})", a), Bytecode::LdU8(a) => write!(f, "LdU8({})", a), + Bytecode::LdU16(a) => write!(f, "LdU16({})", a), + Bytecode::LdU32(a) => write!(f, "LdU32({})", a), Bytecode::LdU64(a) => write!(f, "LdU64({})", a), Bytecode::LdU128(a) => write!(f, "LdU128({})", a), + Bytecode::LdU256(a) => write!(f, "LdU256({})", a), Bytecode::CastU8 => write!(f, "CastU8"), + Bytecode::CastU16 => write!(f, "CastU16"), + Bytecode::CastU32 => write!(f, "CastU32"), Bytecode::CastU64 => write!(f, "CastU64"), Bytecode::CastU128 => write!(f, "CastU128"), + Bytecode::CastU256 => write!(f, "CastU256"), Bytecode::LdConst(a) => write!(f, "LdConst({})", a), Bytecode::LdTrue => write!(f, "LdTrue"), Bytecode::LdFalse => write!(f, "LdFalse"), @@ -1670,11 +1752,11 @@ impl Bytecode { /// Return the successor offsets of this bytecode instruction. pub fn get_successors(pc: CodeOffset, code: &[Bytecode]) -> Vec { assert!( - // The program counter could be added to at most twice and must remain - // within the bounds of the code. - pc <= u16::max_value() - 2 && (pc as usize) < code.len(), + // The program counter must remain within the bounds of the code + pc < u16::MAX && (pc as usize) < code.len(), "Program counter out of bounds" ); + let bytecode = &code[pc as usize]; let mut v = vec![]; @@ -1749,6 +1831,7 @@ impl CompiledScript { /// /// A module is published as a single entry and it is retrieved as a single blob. #[derive(Clone, Debug, Default, Eq, PartialEq)] +#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))] pub struct CompiledModule { /// Version number found during deserialization pub version: u32, diff --git a/language/move-binary-format/src/file_format_common.rs b/language/move-binary-format/src/file_format_common.rs index 82d7979bf0..392090b574 100644 --- a/language/move-binary-format/src/file_format_common.rs +++ b/language/move-binary-format/src/file_format_common.rs @@ -24,10 +24,10 @@ use std::{ pub enum BinaryConstants {} impl BinaryConstants { /// The blob that must start a binary. - pub const DIEM_MAGIC_SIZE: usize = 4; - pub const DIEM_MAGIC: [u8; BinaryConstants::DIEM_MAGIC_SIZE] = [0xA1, 0x1C, 0xEB, 0x0B]; + pub const MOVE_MAGIC_SIZE: usize = 4; + pub const MOVE_MAGIC: [u8; BinaryConstants::MOVE_MAGIC_SIZE] = [0xA1, 0x1C, 0xEB, 0x0B]; /// The `DIEM_MAGIC` size, 4 byte for major version and 1 byte for table count. - pub const HEADER_SIZE: usize = BinaryConstants::DIEM_MAGIC_SIZE + 5; + pub const HEADER_SIZE: usize = BinaryConstants::MOVE_MAGIC_SIZE + 5; /// A (Table Type, Start Offset, Byte Count) size, which is 1 byte for the type and /// 4 bytes for the offset/count. pub const TABLE_HEADER_SIZE: u8 = size_of::() as u8 * 2 + 1; @@ -121,6 +121,9 @@ pub enum SerializedType { VECTOR = 0xA, STRUCT_INST = 0xB, SIGNER = 0xC, + U16 = 0xD, + U32 = 0xE, + U256 = 0xF, } #[rustfmt::skip] @@ -209,6 +212,12 @@ pub enum Opcodes { VEC_POP_BACK = 0x45, VEC_UNPACK = 0x46, VEC_SWAP = 0x47, + LD_U16 = 0x48, + LD_U32 = 0x49, + LD_U256 = 0x4A, + CAST_U16 = 0x4B, + CAST_U32 = 0x4C, + CAST_U256 = 0x4D, } /// Upper limit on the binary size @@ -320,6 +329,14 @@ pub(crate) fn write_u128(binary: &mut BinaryData, value: u128) -> Result<()> { binary.extend(&value.to_le_bytes()) } +/// Write a `u256` in Little Endian format. +pub(crate) fn write_u256( + binary: &mut BinaryData, + value: move_core_types::u256::U256, +) -> Result<()> { + binary.extend(&value.to_le_bytes()) +} + pub fn read_u8(cursor: &mut Cursor<&[u8]>) -> Result { let mut buf = [0; 1]; cursor.read_exact(&mut buf)?; @@ -384,8 +401,12 @@ pub const VERSION_4: u32 = 4; /// + metadata pub const VERSION_5: u32 = 5; +/// Version 6: changes compared with version 5 +/// + u16, u32, u256 integers and corresponding Ld, Cast bytecodes +pub const VERSION_6: u32 = 6; + // Mark which version is the latest version -pub const VERSION_MAX: u32 = VERSION_5; +pub const VERSION_MAX: u32 = VERSION_6; // Mark which oldest version is supported. // TODO(#145): finish v4 compatibility; as of now, only metadata is implemented @@ -406,11 +427,11 @@ pub(crate) mod versioned_data { } impl<'a> VersionedBinary<'a> { - fn new(binary: &'a [u8]) -> BinaryLoaderResult<(Self, Cursor<&'a [u8]>)> { + fn new(binary: &'a [u8], max_version: u32) -> BinaryLoaderResult<(Self, Cursor<&'a [u8]>)> { let mut cursor = Cursor::<&'a [u8]>::new(binary); - let mut magic = [0u8; BinaryConstants::DIEM_MAGIC_SIZE]; + let mut magic = [0u8; BinaryConstants::MOVE_MAGIC_SIZE]; if let Ok(count) = cursor.read(&mut magic) { - if count != BinaryConstants::DIEM_MAGIC_SIZE || magic != BinaryConstants::DIEM_MAGIC + if count != BinaryConstants::MOVE_MAGIC_SIZE || magic != BinaryConstants::MOVE_MAGIC { return Err(PartialVMError::new(StatusCode::BAD_MAGIC)); } @@ -425,7 +446,7 @@ pub(crate) mod versioned_data { .with_message("Bad binary header".to_string())); } }; - if version == 0 || version > VERSION_MAX { + if version == 0 || version > u32::min(max_version, VERSION_MAX) { return Err(PartialVMError::new(StatusCode::UNKNOWN_VERSION)); } Ok((Self { version, binary }, cursor)) @@ -451,8 +472,8 @@ pub(crate) mod versioned_data { impl<'a> VersionedCursor<'a> { /// Verifies the correctness of the "static" part of the binary's header. /// If valid, returns a cursor to the binary - pub fn new(binary: &'a [u8]) -> BinaryLoaderResult { - let (binary, cursor) = VersionedBinary::new(binary)?; + pub fn new(binary: &'a [u8], max_version: u32) -> BinaryLoaderResult { + let (binary, cursor) = VersionedBinary::new(binary, max_version)?; Ok(VersionedCursor { version: binary.version, cursor, @@ -598,6 +619,12 @@ pub fn instruction_key(instruction: &Bytecode) -> u8 { VecPopBack(_) => Opcodes::VEC_POP_BACK, VecUnpack(..) => Opcodes::VEC_UNPACK, VecSwap(_) => Opcodes::VEC_SWAP, + LdU16(_) => Opcodes::LD_U16, + LdU32(_) => Opcodes::LD_U32, + LdU256(_) => Opcodes::LD_U256, + CastU16 => Opcodes::CAST_U16, + CastU32 => Opcodes::CAST_U32, + CastU256 => Opcodes::CAST_U256, }; opcode as u8 } diff --git a/language/move-binary-format/src/lib.rs b/language/move-binary-format/src/lib.rs index b5fab63af3..ebcd6b1b24 100644 --- a/language/move-binary-format/src/lib.rs +++ b/language/move-binary-format/src/lib.rs @@ -136,3 +136,59 @@ impl fmt::Display for SignatureTokenKind { f.write_str(desc) } } + +/// A macro which should be preferred in critical runtime paths for unwrapping an option +/// if a `PartialVMError` is expected. In debug mode, this will panic. Otherwise +/// we return an Err. +#[macro_export] +macro_rules! safe_unwrap { + ($e:expr) => {{ + match $e { + Some(x) => x, + None => { + let err = PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR) + .with_message(format!("{}:{} (none)", file!(), line!())); + if cfg!(debug_assertions) { + panic!("{:?}", err); + } else { + return Err(err); + } + } + } + }}; +} + +/// Similar as above but for Result +#[macro_export] +macro_rules! safe_unwrap_err { + ($e:expr) => {{ + match $e { + Ok(x) => x, + Err(e) => { + let err = PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR) + .with_message(format!("{}:{} {:#}", file!(), line!(), e)); + if cfg!(debug_assertions) { + panic!("{:?}", err); + } else { + return Err(err); + } + } + } + }}; +} + +/// Similar as above, but asserts a boolean expression to be true. +#[macro_export] +macro_rules! safe_assert { + ($e:expr) => {{ + if !$e { + let err = PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR) + .with_message(format!("{}:{} (assert)", file!(), line!())); + if cfg!(debug_assertions) { + panic!("{:?}", err) + } else { + return Err(err); + } + } + }}; +} diff --git a/language/move-binary-format/src/normalized.rs b/language/move-binary-format/src/normalized.rs index 0323cc8c34..183ae569c0 100644 --- a/language/move-binary-format/src/normalized.rs +++ b/language/move-binary-format/src/normalized.rs @@ -53,6 +53,13 @@ pub enum Type { TypeParameter(TypeParameterIndex), Reference(Box), MutableReference(Box), + // NOTE: Added in bytecode version v6, do not reorder! + #[serde(rename = "u16")] + U16, + #[serde(rename = "u32")] + U32, + #[serde(rename = "u256")] + U256, } /// Normalized version of a `FieldDefinition`. The `name` is included even though it is @@ -161,8 +168,11 @@ impl Type { } Bool => Type::Bool, U8 => Type::U8, + U16 => Type::U16, + U32 => Type::U32, U64 => Type::U64, U128 => Type::U128, + U256 => Type::U256, Address => Type::Address, Signer => Type::Signer, Vector(t) => Type::Vector(Box::new(Type::new(m, t))), @@ -179,8 +189,11 @@ impl Type { TypeParameter(_) => false, Bool => true, U8 => true, + U16 => true, + U32 => true, U64 => true, U128 => true, + U256 => true, Address => true, Signer => true, Struct { type_arguments, .. } => type_arguments.iter().all(|t| t.is_closed()), @@ -195,8 +208,11 @@ impl Type { Reference(_) | MutableReference(_) => return None, Bool => TypeTag::Bool, U8 => TypeTag::U8, + U16 => TypeTag::U16, + U32 => TypeTag::U32, U64 => TypeTag::U64, U128 => TypeTag::U128, + U256 => TypeTag::U256, Address => TypeTag::Address, Signer => TypeTag::Signer, Vector(t) => TypeTag::Vector(Box::new( @@ -208,7 +224,7 @@ impl Type { module, name, type_arguments, - } => TypeTag::Struct(StructTag { + } => TypeTag::Struct(Box::new(StructTag { address, module, name, @@ -220,7 +236,7 @@ impl Type { ) }) .collect(), - }), + })), TypeParameter(_) => unreachable!(), } } else { @@ -230,7 +246,7 @@ impl Type { pub fn into_struct_tag(self) -> Option { match self.into_type_tag()? { - TypeTag::Struct(s) => Some(s), + TypeTag::Struct(s) => Some(*s), _ => None, } } @@ -238,7 +254,7 @@ impl Type { pub fn subst(&self, type_args: &[Type]) -> Self { use Type::*; match self { - Bool | U8 | U64 | U128 | Address | Signer => self.clone(), + Bool | U8 | U16 | U32 | U64 | U128 | U256 | Address | Signer => self.clone(), Reference(ty) => Reference(Box::new(ty.subst(type_args))), MutableReference(ty) => MutableReference(Box::new(ty.subst(type_args))), Vector(t) => Vector(Box::new(t.subst(type_args))), @@ -280,7 +296,10 @@ impl Struct { pub fn new(m: &CompiledModule, def: &StructDefinition) -> (Identifier, Self) { let handle = m.struct_handle_at(def.struct_handle); let fields = match &def.field_information { - StructFieldInformation::Native => panic!("Can't extract for native struct"), + StructFieldInformation::Native => { + // Pretend for compatibility checking no fields + vec![] + } StructFieldInformation::Declared(fields) => { fields.iter().map(|f| Field::new(m, f)).collect() } @@ -341,8 +360,11 @@ impl From for Type { match ty { TypeTag::Bool => Bool, TypeTag::U8 => U8, + TypeTag::U16 => U16, + TypeTag::U32 => U32, TypeTag::U64 => U64, TypeTag::U128 => U128, + TypeTag::U256 => U256, TypeTag::Address => Address, TypeTag::Signer => Signer, TypeTag::Vector(ty) => Vector(Box::new(Type::from(*ty))), @@ -384,8 +406,11 @@ impl std::fmt::Display for Type { } Type::Vector(ty) => write!(f, "vector<{}>", ty), Type::U8 => write!(f, "u8"), + Type::U16 => write!(f, "u16"), + Type::U32 => write!(f, "u32"), Type::U64 => write!(f, "u64"), Type::U128 => write!(f, "u128"), + Type::U256 => write!(f, "u256"), Type::Address => write!(f, "address"), Type::Signer => write!(f, "signer"), Type::Bool => write!(f, "bool"), diff --git a/language/move-binary-format/src/proptest_types/functions.rs b/language/move-binary-format/src/proptest_types/functions.rs index 26d402b62c..30c9a28af8 100644 --- a/language/move-binary-format/src/proptest_types/functions.rs +++ b/language/move-binary-format/src/proptest_types/functions.rs @@ -18,6 +18,7 @@ use crate::{ TableSize, }, }; +use move_core_types::u256::U256; use proptest::{ collection::{vec, SizeRange}, prelude::*, @@ -782,6 +783,9 @@ impl BytecodeGen { Bytecode::ImmBorrowLoc(idx.index(locals_signature.len()) as LocalIndex) } BytecodeGen::VecPack((idx, num)) => { + if num > u16::MAX as u64 { + return None; + } let sigs_len = state.signatures.signatures.len(); if sigs_len == 0 { return None; @@ -854,6 +858,9 @@ impl BytecodeGen { Bytecode::VecPopBack(SignatureIndex(sig_idx as TableIndex)) } BytecodeGen::VecUnpack((idx, num)) => { + if num > u16::MAX as u64 { + return None; + } let sigs_len = state.signatures.signatures.len(); if sigs_len == 0 { return None; @@ -887,7 +894,8 @@ impl BytecodeGen { fn check_signature_token(token: &SignatureToken) -> bool { use SignatureToken::*; match token { - U8 | U64 | U128 | Bool | Address | Signer | Struct(_) | TypeParameter(_) => true, + U8 | U16 | U32 | U64 | U128 | U256 | Bool | Address | Signer | Struct(_) + | TypeParameter(_) => true, Vector(element_token) => BytecodeGen::check_signature_token(element_token), StructInstantiation(_, type_arguments) => type_arguments .iter() @@ -905,11 +913,14 @@ impl BytecodeGen { fn simple_bytecode_strategy() -> impl Strategy { prop_oneof![ - // The numbers are relative weights, somewhat arbitrarily picked. - 9 => Self::just_bytecode_strategy(), - 1 => any::().prop_map(Bytecode::LdU64), - 1 => any::().prop_map(Bytecode::LdU8), - 1 => any::().prop_map(Bytecode::LdU128), + // The numbers are relative weights, somewhat arbitrarily picked. + 9 => Self::just_bytecode_strategy(), + 1 => any::().prop_map(Bytecode::LdU64), + 1 => any::().prop_map(Bytecode::LdU8), + 1 => any::().prop_map(Bytecode::LdU128), + 1 => any::().prop_map(Bytecode::LdU16), + 1 => any::().prop_map(Bytecode::LdU32), + 1 => any::().prop_map(Bytecode::LdU256), ] } @@ -919,7 +930,7 @@ impl BytecodeGen { static JUST_BYTECODES: &[Bytecode] = &[ FreezeRef, Pop, Ret, LdTrue, LdFalse, ReadRef, WriteRef, Add, Sub, Mul, Mod, Div, BitOr, BitAnd, Xor, Or, And, Eq, Neq, Lt, Gt, Le, Ge, Abort, CastU8, CastU64, CastU128, - Not, Nop, Shl, Shr, + CastU16, CastU32, CastU256, Not, Nop, Shl, Shr, ]; select(JUST_BYTECODES) } diff --git a/language/move-binary-format/src/proptest_types/signature.rs b/language/move-binary-format/src/proptest_types/signature.rs index d769a706f1..5b94c12925 100644 --- a/language/move-binary-format/src/proptest_types/signature.rs +++ b/language/move-binary-format/src/proptest_types/signature.rs @@ -84,8 +84,11 @@ pub enum SignatureTokenGen { // Atomic signature tokens. Bool, U8, + U16, + U32, U64, U128, + U256, Address, Signer, TypeParameter(PropIndex), @@ -124,7 +127,8 @@ impl SignatureTokenGen { pub fn owned_non_struct_strategy() -> impl Strategy { use SignatureTokenGen::*; - static OWNED_NON_STRUCTS: &[SignatureTokenGen] = &[Bool, U8, U64, U128, Address, Signer]; + static OWNED_NON_STRUCTS: &[SignatureTokenGen] = + &[Bool, U8, U16, U32, U64, U128, U256, Address, Signer]; select(OWNED_NON_STRUCTS) } @@ -158,8 +162,11 @@ impl SignatureTokenGen { match self { Bool => SignatureToken::Bool, U8 => SignatureToken::U8, + U16 => SignatureToken::U16, + U32 => SignatureToken::U32, U64 => SignatureToken::U64, U128 => SignatureToken::U128, + U256 => SignatureToken::U256, Address => SignatureToken::Address, Signer => SignatureToken::Signer, Struct(idx) => { diff --git a/language/move-binary-format/src/proptest_types/types.rs b/language/move-binary-format/src/proptest_types/types.rs index 716ba66ea9..8879daa9e6 100644 --- a/language/move-binary-format/src/proptest_types/types.rs +++ b/language/move-binary-format/src/proptest_types/types.rs @@ -61,7 +61,7 @@ impl StDefnMaterializeState { use SignatureToken::*; match ty { - Bool | U8 | U64 | U128 | Address => AbilitySet::PRIMITIVES, + Bool | U8 | U16 | U32 | U64 | U128 | U256 | Address => AbilitySet::PRIMITIVES, Reference(_) | MutableReference(_) => AbilitySet::REFERENCES, Signer => AbilitySet::SIGNER, diff --git a/language/move-binary-format/src/serializer.rs b/language/move-binary-format/src/serializer.rs index 2c33e91212..3a63bf5717 100644 --- a/language/move-binary-format/src/serializer.rs +++ b/language/move-binary-format/src/serializer.rs @@ -16,7 +16,7 @@ //! serialization errors. use crate::{file_format::*, file_format_common::*}; -use anyhow::{bail, Result}; +use anyhow::{anyhow, bail, Result}; use move_core_types::{ account_address::AccountAddress, identifier::Identifier, metadata::Metadata, }; @@ -320,7 +320,7 @@ fn serialize_table_index( } fn serialize_magic(binary: &mut BinaryData) -> Result<()> { - for byte in &BinaryConstants::DIEM_MAGIC { + for byte in &BinaryConstants::MOVE_MAGIC { binary.push(*byte)?; } Ok(()) @@ -641,8 +641,11 @@ fn serialize_signature_token_single_node_impl( match token { SignatureToken::Bool => binary.push(SerializedType::BOOL as u8)?, SignatureToken::U8 => binary.push(SerializedType::U8 as u8)?, + SignatureToken::U16 => binary.push(SerializedType::U16 as u8)?, + SignatureToken::U32 => binary.push(SerializedType::U32 as u8)?, SignatureToken::U64 => binary.push(SerializedType::U64 as u8)?, SignatureToken::U128 => binary.push(SerializedType::U128 as u8)?, + SignatureToken::U256 => binary.push(SerializedType::U256 as u8)?, SignatureToken::Address => binary.push(SerializedType::ADDRESS as u8)?, SignatureToken::Signer => binary.push(SerializedType::SIGNER as u8)?, SignatureToken::Vector(_) => { @@ -720,13 +723,34 @@ fn serialize_ability_sets(binary: &mut BinaryData, sets: &[AbilitySet]) -> Resul /// - `CodeUnit.max_stack_size` as a ULEB128 /// - `CodeUnit.locals` as a ULEB128 (index into the `LocalSignaturePool`) /// - `CodeUnit.code` as variable size byte stream for the bytecode -fn serialize_code_unit(binary: &mut BinaryData, code: &CodeUnit) -> Result<()> { +fn serialize_code_unit(major_version: u32, binary: &mut BinaryData, code: &CodeUnit) -> Result<()> { serialize_signature_index(binary, &code.locals)?; - serialize_code(binary, &code.code) + serialize_code(major_version, binary, &code.code) } /// Serializes a single `Bytecode` instruction. -fn serialize_instruction_inner(binary: &mut BinaryData, opcode: &Bytecode) -> Result<()> { +fn serialize_instruction_inner( + major_version: u32, + binary: &mut BinaryData, + opcode: &Bytecode, +) -> Result<()> { + match opcode { + Bytecode::LdU16(_) + | Bytecode::LdU32(_) + | Bytecode::LdU256(_) + | Bytecode::CastU16 + | Bytecode::CastU32 + | Bytecode::CastU256 + if (major_version < VERSION_6) => + { + return Err(anyhow!( + "Loading or casting u16, u32, u256 integers not supported in bytecode version {}", + major_version + )); + } + _ => (), + }; + let res = match opcode { Bytecode::FreezeRef => binary.push(Opcodes::FREEZE_REF as u8), Bytecode::Pop => binary.push(Opcodes::POP as u8), @@ -921,16 +945,31 @@ fn serialize_instruction_inner(binary: &mut BinaryData, opcode: &Bytecode) -> Re binary.push(Opcodes::VEC_SWAP as u8)?; serialize_signature_index(binary, sig_idx) } + Bytecode::LdU16(value) => { + binary.push(Opcodes::LD_U16 as u8)?; + write_u16(binary, *value) + } + Bytecode::LdU32(value) => { + binary.push(Opcodes::LD_U32 as u8)?; + write_u32(binary, *value) + } + Bytecode::LdU256(value) => { + binary.push(Opcodes::LD_U256 as u8)?; + write_u256(binary, *value) + } + Bytecode::CastU16 => binary.push(Opcodes::CAST_U16 as u8), + Bytecode::CastU32 => binary.push(Opcodes::CAST_U32 as u8), + Bytecode::CastU256 => binary.push(Opcodes::CAST_U256 as u8), }; res?; Ok(()) } /// Serializes a `Bytecode` stream. Serialization of the function body. -fn serialize_code(binary: &mut BinaryData, code: &[Bytecode]) -> Result<()> { +fn serialize_code(major_version: u32, binary: &mut BinaryData, code: &[Bytecode]) -> Result<()> { serialize_bytecode_count(binary, code.len())?; for opcode in code { - serialize_instruction_inner(binary, opcode)?; + serialize_instruction_inner(major_version, binary, opcode)?; } Ok(()) } @@ -1202,6 +1241,10 @@ impl CommonSerializer { } Ok(()) } + + pub fn major_version(&self) -> u32 { + self.major_version + } } impl ModuleSerializer { @@ -1392,7 +1435,7 @@ impl ModuleSerializer { serialize_acquires(binary, &function_definition.acquires_global_resources)?; if let Some(code) = &function_definition.code { - serialize_code_unit(binary, code)?; + serialize_code_unit(self.common.major_version(), binary, code)?; } Ok(()) } @@ -1425,7 +1468,7 @@ impl ScriptSerializer { fn serialize_main(&mut self, binary: &mut BinaryData, script: &CompiledScript) -> Result<()> { serialize_ability_sets(binary, &script.type_parameters)?; serialize_signature_index(binary, &script.parameters)?; - serialize_code_unit(binary, &script.code)?; + serialize_code_unit(self.common.major_version(), binary, &script.code)?; Ok(()) } } diff --git a/language/move-binary-format/src/unit_tests/binary_tests.rs b/language/move-binary-format/src/unit_tests/binary_tests.rs index 64353191f4..1d7f325378 100644 --- a/language/move-binary-format/src/unit_tests/binary_tests.rs +++ b/language/move-binary-format/src/unit_tests/binary_tests.rs @@ -2,7 +2,7 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 -use crate::file_format_common::*; +use crate::{file_format::Bytecode, file_format_common::*}; use proptest::prelude::*; #[test] @@ -14,6 +14,18 @@ fn binary_len() { assert_eq!(binary_data.len(), 100); } +#[test] +fn test_max_number_of_bytecode() { + let mut nops = vec![]; + for _ in 0..u16::MAX - 1 { + nops.push(Bytecode::Nop); + } + nops.push(Bytecode::Branch(0)); + + let result = Bytecode::get_successors(u16::MAX - 1, &nops); + assert_eq!(result, vec![0]); +} + proptest! { #[test] fn vec_to_binary(vec in any::>()) { diff --git a/language/move-binary-format/src/unit_tests/compatibility_tests.rs b/language/move-binary-format/src/unit_tests/compatibility_tests.rs index d6855421e5..9e5e0c78f2 100644 --- a/language/move-binary-format/src/unit_tests/compatibility_tests.rs +++ b/language/move-binary-format/src/unit_tests/compatibility_tests.rs @@ -68,23 +68,12 @@ fn mk_module(vis: u8) -> normalized::Module { normalized::Module::new(&m) } -const NON_COMPATIBLE: Compatibility = Compatibility { - struct_and_function_linking: false, - struct_layout: true, -}; - -const COMPATIBLE: Compatibility = Compatibility { - struct_and_function_linking: true, - struct_layout: true, -}; - #[test] fn deprecated_unchanged_script_visibility() { let script_module = mk_module(Visibility::DEPRECATED_SCRIPT); - assert_eq!( - Compatibility::check(&script_module, &script_module,), - COMPATIBLE - ); + assert!(Compatibility::full_check() + .check(&script_module, &script_module) + .is_ok(),); } #[test] @@ -92,22 +81,19 @@ fn deprecated_remove_script_visibility() { let script_module = mk_module(Visibility::DEPRECATED_SCRIPT); // script -> private, not allowed let private_module = mk_module(Visibility::Private as u8); - assert_eq!( - Compatibility::check(&script_module, &private_module), - NON_COMPATIBLE - ); + assert!(Compatibility::full_check() + .check(&script_module, &private_module) + .is_err()); // script -> public, not allowed let public_module = mk_module(Visibility::Public as u8); - assert_eq!( - Compatibility::check(&script_module, &public_module), - NON_COMPATIBLE - ); + assert!(Compatibility::full_check() + .check(&script_module, &public_module) + .is_err()); // script -> friend, not allowed let friend_module = mk_module(Visibility::Friend as u8); - assert_eq!( - Compatibility::check(&script_module, &friend_module), - NON_COMPATIBLE - ); + assert!(Compatibility::full_check() + .check(&script_module, &friend_module) + .is_err()); } #[test] @@ -115,20 +101,17 @@ fn deprecated_add_script_visibility() { let script_module = mk_module(Visibility::DEPRECATED_SCRIPT); // private -> script, allowed let private_module = mk_module(Visibility::Private as u8); - assert_eq!( - Compatibility::check(&private_module, &script_module,), - COMPATIBLE - ); + assert!(Compatibility::full_check() + .check(&private_module, &script_module) + .is_ok()); // public -> script, not allowed let public_module = mk_module(Visibility::Public as u8); - assert_eq!( - Compatibility::check(&public_module, &script_module), - NON_COMPATIBLE - ); + assert!(Compatibility::full_check() + .check(&public_module, &script_module) + .is_err()); // friend -> script, not allowed let friend_module = mk_module(Visibility::Friend as u8); - assert_eq!( - Compatibility::check(&friend_module, &script_module), - NON_COMPATIBLE - ); + assert!(Compatibility::full_check() + .check(&friend_module, &script_module) + .is_err()); } diff --git a/language/move-binary-format/src/unit_tests/control_flow_graph_tests.rs b/language/move-binary-format/src/unit_tests/control_flow_graph_tests.rs new file mode 100644 index 0000000000..064aa151bf --- /dev/null +++ b/language/move-binary-format/src/unit_tests/control_flow_graph_tests.rs @@ -0,0 +1,74 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + control_flow_graph::{BlockId, ControlFlowGraph, VMControlFlowGraph}, + file_format::Bytecode, +}; + +#[test] +fn traversal_no_loops() { + let cfg = { + use Bytecode::*; + VMControlFlowGraph::new(&[ + /* L0 */ LdTrue, + /* */ BrTrue(3), + /* L2 */ Branch(3), + /* L3 */ Ret, + ]) + }; + + cfg.display(); + assert_eq!(cfg.num_blocks(), 3); + assert_eq!(traversal(&cfg), vec![0, 2, 3]); +} + +#[test] +fn traversal_loops() { + let cfg = { + use Bytecode::*; + VMControlFlowGraph::new(&[ + /* L0: Outer head */ LdTrue, + /* Outer break */ BrTrue(6), + /* L2: Inner head */ LdTrue, + /* Inner break */ BrTrue(5), + /* L4: Inner continue */ Branch(2), + /* Outer continue */ Branch(0), + /* L6: */ Ret, + ]) + }; + + cfg.display(); + assert_eq!(cfg.num_blocks(), 5); + assert_eq!(traversal(&cfg), vec![0, 2, 4, 5, 6]); +} + +#[test] +fn traversal_non_loop_back_branch() { + let cfg = { + use Bytecode::*; + VMControlFlowGraph::new(&[ + /* L0 */ Branch(2), + /* L1 */ Ret, + /* L2 */ Branch(1), + ]) + }; + + cfg.display(); + assert_eq!(cfg.num_blocks(), 3); + assert_eq!(traversal(&cfg), vec![0, 2, 1]); +} + +/// Return a vector containing the `BlockId`s from `cfg` in the order suggested by successively +/// calling `ControlFlowGraph::next_block` starting from the entry block. +fn traversal(cfg: &dyn ControlFlowGraph) -> Vec { + let mut order = Vec::with_capacity(cfg.num_blocks() as usize); + let mut next = Some(cfg.entry_block_id()); + + while let Some(block) = next { + order.push(block); + next = cfg.next_block(block); + } + + order +} diff --git a/language/move-binary-format/src/unit_tests/deserializer_tests.rs b/language/move-binary-format/src/unit_tests/deserializer_tests.rs index 2d266b23ae..756e6d3815 100644 --- a/language/move-binary-format/src/unit_tests/deserializer_tests.rs +++ b/language/move-binary-format/src/unit_tests/deserializer_tests.rs @@ -10,8 +10,8 @@ use move_core_types::vm_status::StatusCode; fn malformed_simple_versioned_test(version: u32) { // bad uleb (more than allowed for table count) - let mut binary = BinaryConstants::DIEM_MAGIC.to_vec(); - binary.extend(&version.to_le_bytes()); // version + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version binary.push(150); // table count (high bit 1) binary.push(150); // table count (high bit 1) binary.push(1); @@ -22,8 +22,8 @@ fn malformed_simple_versioned_test(version: u32) { ); // bad uleb (too big) - let mut binary = BinaryConstants::DIEM_MAGIC.to_vec(); - binary.extend(&version.to_le_bytes()); // version + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version binary.push(150); // table count (high bit 1) binary.push(150); // table count again (high bit 1) binary.push(150); // table count again (high bit 1) @@ -43,8 +43,8 @@ fn malformed_simple_versioned_test(version: u32) { ); // no tables - let mut binary = BinaryConstants::DIEM_MAGIC.to_vec(); - binary.extend(&version.to_le_bytes()); // version + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version binary.push(0); // table count let res = CompiledModule::deserialize(&binary); assert_eq!( @@ -53,8 +53,8 @@ fn malformed_simple_versioned_test(version: u32) { ); // missing tables - let mut binary = BinaryConstants::DIEM_MAGIC.to_vec(); - binary.extend(&version.to_le_bytes()); // version + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version binary.push(10); // table count let res = CompiledModule::deserialize(&binary); assert_eq!( @@ -63,8 +63,8 @@ fn malformed_simple_versioned_test(version: u32) { ); // missing table content - let mut binary = BinaryConstants::DIEM_MAGIC.to_vec(); - binary.extend(&version.to_le_bytes()); // version + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version binary.push(1); // table count binary.push(1); // table type binary.push(0); // table offset @@ -76,8 +76,8 @@ fn malformed_simple_versioned_test(version: u32) { ); // bad table header (bad offset) - let mut binary = BinaryConstants::DIEM_MAGIC.to_vec(); - binary.extend(&version.to_le_bytes()); // version + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version binary.push(1); // table count binary.push(1); // table type binary.push(100); // bad table offset @@ -89,8 +89,8 @@ fn malformed_simple_versioned_test(version: u32) { ); // bad table header (bad offset) - let mut binary = BinaryConstants::DIEM_MAGIC.to_vec(); - binary.extend(&version.to_le_bytes()); // version + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version binary.push(2); // table count binary.push(1); // table type binary.push(0); // table offset @@ -106,8 +106,8 @@ fn malformed_simple_versioned_test(version: u32) { ); // incomplete table - let mut binary = BinaryConstants::DIEM_MAGIC.to_vec(); - binary.extend(&version.to_le_bytes()); // version + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version binary.push(1); // table count binary.push(1); // table type binary.push(0); // table offset @@ -120,8 +120,8 @@ fn malformed_simple_versioned_test(version: u32) { ); // unknown table - let mut binary = BinaryConstants::DIEM_MAGIC.to_vec(); - binary.extend(&version.to_le_bytes()); // version + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version binary.push(1); // table count binary.push(100); // table type binary.push(0); // table offset @@ -134,8 +134,8 @@ fn malformed_simple_versioned_test(version: u32) { ); // duplicate table - let mut binary = BinaryConstants::DIEM_MAGIC.to_vec(); - binary.extend(&version.to_le_bytes()); // version + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version binary.push(3); // table count binary.push(1); // table type binary.push(0); // table offset @@ -155,8 +155,8 @@ fn malformed_simple_versioned_test(version: u32) { ); // bad table in script - let mut binary = BinaryConstants::DIEM_MAGIC.to_vec(); - binary.extend(&version.to_le_bytes()); // version + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend(version.to_le_bytes()); // version binary.push(1); // table count binary.push(0xD); // table type - FieldHandle not good for script binary.push(0); // table offset @@ -198,7 +198,7 @@ fn malformed_simple() { ); // only magic - let binary = BinaryConstants::DIEM_MAGIC.to_vec(); + let binary = BinaryConstants::MOVE_MAGIC.to_vec(); let res = CompiledScript::deserialize(&binary); assert_eq!( res.expect_err("Expected malformed binary").major_status(), @@ -206,8 +206,8 @@ fn malformed_simple() { ); // bad version - let mut binary = BinaryConstants::DIEM_MAGIC.to_vec(); - binary.extend(&(VERSION_MAX.checked_add(1).unwrap()).to_le_bytes()); // version + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend((VERSION_MAX.checked_add(1).unwrap()).to_le_bytes()); // version binary.push(10); // table count binary.push(0); // rest of binary let res = CompiledScript::deserialize(&binary); @@ -222,6 +222,21 @@ fn malformed_simple() { } } +#[test] +fn max_version_lower_than_hardcoded() { + let mut binary = BinaryConstants::MOVE_MAGIC.to_vec(); + binary.extend((VERSION_MAX).to_le_bytes()); // version + binary.push(10); // table count + binary.push(0); // rest of binary + + let res = + CompiledScript::deserialize_with_max_version(&binary, VERSION_MAX.checked_sub(1).unwrap()); + assert_eq!( + res.expect_err("Expected unknown version").major_status(), + StatusCode::UNKNOWN_VERSION + ); +} + // Ensure that we can deserialize a script from disk static EMPTY_SCRIPT: &[u8] = include_bytes!("empty_script.mv"); diff --git a/language/move-binary-format/src/unit_tests/mod.rs b/language/move-binary-format/src/unit_tests/mod.rs index 04fca3168f..e811762a11 100644 --- a/language/move-binary-format/src/unit_tests/mod.rs +++ b/language/move-binary-format/src/unit_tests/mod.rs @@ -4,6 +4,7 @@ mod binary_tests; mod compatibility_tests; +mod control_flow_graph_tests; mod deserializer_tests; mod number_tests; mod signature_token_tests; diff --git a/language/move-binary-format/src/unit_tests/signature_token_tests.rs b/language/move-binary-format/src/unit_tests/signature_token_tests.rs index 900319c2cc..c2e2d82130 100644 --- a/language/move-binary-format/src/unit_tests/signature_token_tests.rs +++ b/language/move-binary-format/src/unit_tests/signature_token_tests.rs @@ -5,7 +5,7 @@ use crate::{ deserializer::load_signature_token_test_entry, file_format::{SignatureToken, StructHandleIndex}, - file_format_common::{BinaryData, SIGNATURE_TOKEN_DEPTH_MAX}, + file_format_common::{BinaryData, SerializedType, SIGNATURE_TOKEN_DEPTH_MAX}, serializer::{serialize_signature_token, serialize_signature_token_unchecked}, }; use std::io::Cursor; @@ -44,3 +44,46 @@ fn serialize_nested_types_too_deep() { load_signature_token_test_entry(cursor).expect_err("deserialization should fail"); } } + +#[test] +fn deserialize_struct_inst_arity_0() { + let cursor = Cursor::new( + [ + SerializedType::STRUCT_INST as u8, + 0x0, /* struct handle idx */ + 0x0, /* arity */ + SerializedType::BOOL as u8, + ] + .as_slice(), + ); + load_signature_token_test_entry(cursor).expect_err("deserialization should fail"); +} + +#[test] +fn deserialize_struct_inst_arity_1() { + let cursor = Cursor::new( + [ + SerializedType::STRUCT_INST as u8, + 0x0, /* struct handle idx */ + 0x1, /* arity */ + SerializedType::BOOL as u8, + ] + .as_slice(), + ); + load_signature_token_test_entry(cursor).expect("deserialization should succeed"); +} + +#[test] +fn deserialize_struct_inst_arity_2() { + let cursor = Cursor::new( + [ + SerializedType::STRUCT_INST as u8, + 0x0, /* struct handle idx */ + 0x2, /* arity */ + SerializedType::BOOL as u8, + SerializedType::BOOL as u8, + ] + .as_slice(), + ); + load_signature_token_test_entry(cursor).expect("deserialization should succeed"); +} diff --git a/language/move-borrow-graph/Cargo.toml b/language/move-borrow-graph/Cargo.toml index 5e2285b2ef..891b9be448 100644 --- a/language/move-borrow-graph/Cargo.toml +++ b/language/move-borrow-graph/Cargo.toml @@ -3,5 +3,5 @@ name = "move-borrow-graph" version = "0.0.1" authors = ["Diem Association "] publish = false -edition = "2018" +edition = "2021" license = "Apache-2.0" diff --git a/language/move-borrow-graph/src/graph.rs b/language/move-borrow-graph/src/graph.rs index 0aa742ad65..517baa1463 100644 --- a/language/move-borrow-graph/src/graph.rs +++ b/language/move-borrow-graph/src/graph.rs @@ -12,7 +12,7 @@ use std::collections::{BTreeMap, BTreeSet}; // Definitions //************************************************************************************************** -#[derive(Clone, Debug, Default, PartialEq)] +#[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct BorrowGraph(BTreeMap>); //************************************************************************************************** @@ -26,6 +26,14 @@ impl BorrowGraph { Self(BTreeMap::new()) } + /// Returns the graph size, that is the number of nodes + number of edges + pub fn graph_size(&self) -> usize { + self.0 + .values() + .map(|r| 1 + r.borrowed_by.0.values().map(|e| e.len()).sum::()) + .sum() + } + /// checks if the given reference is mutable or not pub fn is_mutable(&self, id: RefID) -> bool { self.0.get(&id).unwrap().mutable @@ -325,14 +333,16 @@ impl BorrowGraph { /// If it is not in the map, the id remains the same pub fn remap_refs(&mut self, id_map: &BTreeMap) { debug_assert!(self.check_invariant()); - for info in self.0.values_mut() { - info.remap_refs(id_map); - } - for (old, new) in id_map { - if let Some(info) = self.0.remove(old) { - self.0.insert(*new, info); - } - } + let _before = self.0.len(); + self.0 = std::mem::take(&mut self.0) + .into_iter() + .map(|(id, mut info)| { + info.remap_refs(id_map); + (id_map.get(&id).copied().unwrap_or(id), info) + }) + .collect(); + let _after = self.0.len(); + debug_assert!(_before == _after); debug_assert!(self.check_invariant()); } diff --git a/language/move-borrow-graph/src/references.rs b/language/move-borrow-graph/src/references.rs index a420d56032..c04e390c37 100644 --- a/language/move-borrow-graph/src/references.rs +++ b/language/move-borrow-graph/src/references.rs @@ -162,11 +162,13 @@ impl BorrowEdges { /// Utility for remapping the reference ids according the `id_map` provided /// If it is not in the map, the id remains the same pub(crate) fn remap_refs(&mut self, id_map: &BTreeMap) { - for (old, new) in id_map { - if let Some(edges) = self.0.remove(old) { - self.0.insert(*new, edges); - } - } + let _before = self.0.len(); + self.0 = std::mem::take(&mut self.0) + .into_iter() + .map(|(id, edges)| (id_map.get(&id).copied().unwrap_or(id), edges)) + .collect(); + let _after = self.0.len(); + debug_assert!(_before == _after) } } @@ -229,7 +231,7 @@ impl Debug for BorrowEdge { // Iteration //********************************************************************************************** -impl<'a, Loc: Copy, Lbl: Clone + Ord> IntoIterator for BorrowEdgeSet { +impl IntoIterator for BorrowEdgeSet { type Item = BorrowEdge; type IntoIter = std::collections::btree_set::IntoIter>; diff --git a/language/move-borrow-graph/src/shared.rs b/language/move-borrow-graph/src/shared.rs index c6ee221085..b3baca041b 100644 --- a/language/move-borrow-graph/src/shared.rs +++ b/language/move-borrow-graph/src/shared.rs @@ -4,9 +4,11 @@ use std::collections::{BTreeMap, BTreeSet}; pub fn remap_set(set: &mut BTreeSet, id_map: &BTreeMap) { - for (old, new) in id_map { - if set.remove(old) { - set.insert(*new); - } - } + let _before = set.len(); + *set = std::mem::take(set) + .into_iter() + .map(|x| id_map.get(&x).copied().unwrap_or(x)) + .collect(); + let _after = set.len(); + debug_assert!(_before == _after); } diff --git a/language/move-bytecode-verifier/Cargo.toml b/language/move-bytecode-verifier/Cargo.toml index c85640fbeb..2b1bab73d0 100644 --- a/language/move-bytecode-verifier/Cargo.toml +++ b/language/move-bytecode-verifier/Cargo.toml @@ -7,17 +7,19 @@ repository = "https://github.com/diem/diem" homepage = "https://diem.com" license = "Apache-2.0" publish = false -edition = "2018" +edition = "2021" [dependencies] anyhow = "1.0.52" petgraph = "0.5.1" +fail = "0.4.0" move-borrow-graph = { path = "../move-borrow-graph" } move-binary-format = { path = "../move-binary-format" } move-core-types = { path = "../move-core/types" } [dev-dependencies] +hex-literal = "0.3.4" invalid-mutations = { path = "invalid-mutations" } [features] diff --git a/language/move-bytecode-verifier/README.md b/language/move-bytecode-verifier/README.md index f6e3fdeaea..4b3b4ee4c9 100644 --- a/language/move-bytecode-verifier/README.md +++ b/language/move-bytecode-verifier/README.md @@ -29,7 +29,7 @@ Resources represent the assets of the blockchain. As such, there are certain res * `CopyLoc` and `StLoc` require that the type of local is not of resource kind. * `WriteRef`, `Eq`, and `Neq` require that the type of the reference is not of resource kind. -* At the end of a function (when `Ret` is reached), no local whose type is of resource kind must be empty, i.e., the value must have been moved out of the local. +* At the end of a function (when `Ret` is reached), any local whose type is of resource kind must be empty, i.e., the value must have been moved out of the local. As mentioned above, this last rule around `Ret` implies that the resource *must* have been either: diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/Cargo.toml b/language/move-bytecode-verifier/bytecode-verifier-tests/Cargo.toml index 7ba9a30293..902cb2340d 100644 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/Cargo.toml +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/Cargo.toml @@ -7,16 +7,18 @@ repository = "https://github.com/diem/diem" homepage = "https://diem.com" license = "Apache-2.0" publish = false -edition = "2018" +edition = "2021" [dev-dependencies] petgraph = "0.5.1" proptest = "1.0.0" - +fail = { version = "0.4.0", features = ['failpoints']} +hex = "0.4.3" move-bytecode-verifier = { path = "../" } invalid-mutations = { path = "../invalid-mutations" } move-core-types = { path = "../../move-core/types" } -move-binary-format = { path = "../../move-binary-format", features = ["fuzzing"] } +move-binary-format = { path = "../../move-binary-format", features = ["fuzzing" ] } [features] fuzzing = ["move-binary-format/fuzzing"] +address32 = ["move-core-types/address32"] diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/METER_TESTING.md b/language/move-bytecode-verifier/bytecode-verifier-tests/METER_TESTING.md new file mode 100644 index 0000000000..cd5ae0f421 --- /dev/null +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/METER_TESTING.md @@ -0,0 +1,5 @@ +This testsuite can be run in a specific way to print the time until a 'complex' program is detected or accepted. Call as in: + +``` +cargo test --release --features=address32 -- --nocapture 1>/dev/null +``` diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/binary_samples.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/binary_samples.rs new file mode 100644 index 0000000000..9da0b1c989 --- /dev/null +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/binary_samples.rs @@ -0,0 +1,83 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +//! Tests in here are based on binary representation of modules taken from production. Those tests +//! may fail over time if the representation becomes out of date, then they can be removed. +//! Right now the serve to calibrate the metering working as expected. Those tests represent +//! cases which we want to continue to succeed. + +use crate::unit_tests::production_config; +use move_binary_format::{errors::VMResult, CompiledModule}; +use move_bytecode_verifier::verifier; + +#[allow(unused)] +fn run_binary_test(name: &str, bytes: &str) -> VMResult<()> { + let bytes = hex::decode(bytes).expect("invalid hex string"); + let m = CompiledModule::deserialize(&bytes).expect("invalid module"); + verifier::verify_module_with_config_for_test(name, &production_config(), &m) +} + +#[cfg(feature = "address32")] +#[test] +fn sample_price_oracle() { + let code = + "a11ceb0b050000000c01001602162003368a0104c0011405d401a80607fc07f90308f50b6006d50c9b3210f03e770ae73f170cfe3f951e0d935e060000010101020103010401050006020702080209020a000b0800000c0800080d070004170402030100010318070009190700071c0700000e000100000f0201010000100201010000110302000012030200001304020000140506000015050600080f080900071d0a0100081e080900071f0a0b0007200a010006210c01000122020f01000123020c01000424110b020300042511120203000a261314000527020f0100022803180004290219020304092a1a1b00032b1a0f00042c1c02020302020e0e0e0f0e10101110130e1016111615101810020608020201030001060c02060c0304030103010203010908060303080603010301030106080201080601060806010101020502060800080508040802010900010804020804080502060b0302090009010900010609010208050301080202080406080102080403ae010a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a02080508000708000a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050a0208050105010b030209000901010a0201080503070b0302090009010900090193010508000708000a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a020a02080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805080508050805010708000b03030101010301030103010b01030101010301030103010c70726963655f6f7261636c6504636f696e067369676e657206737472696e67057461626c6509747970655f696e666f046d617468036936340570726963651070726963655f6964656e74696669657204707974681250726963654964656e7469666965724d61700e54657374507269636553746f72650550726963650c666f726d61745f7072696365096765745f7072696365126765745f70726963655f666f725f746573740a696e697469616c697a6512696e697469616c697a655f746573746e6574127365745f7468726573686f6c645f73656373107369676e65645f7536345f6d696e75730f7369676e65645f7536345f706c757304696e666f055461626c6506537472696e670f50726963654964656e7469666965720e7468726573686f6c645f736563730b70726963655f7461626c6503493634196765745f6d61676e69747564655f69665f706f736974697665086765745f6578706f0f6765745f69735f6e65676174697665196765745f6d61676e69747564655f69665f6e6567617469766506706f775f31300673796d626f6c08646563696d616c7308636f6e7461696e7306626f72726f77176765745f70726963655f6e6f5f6f6c6465725f7468616e09747970655f6e616d650a616464726573735f6f66036e65770d66726f6d5f627974655f76656304757466380675707365727414812adfd8ba2f589c0fe48c5170fa287cd36050dd487d17e2f4a765101f70ed00000000000000000000000000000000000000000000000000000000000000017e783b349d3e89cf5931af376ebeadbfab855b3fa239b7ada8f5a92fbea6b3870308700000000000000003086d0000000000000003086e0000000000000003081000000000000000052014812adfd8ba2f589c0fe48c5170fa287cd36050dd487d17e2f4a765101f70ed0a0221202b9ab1e972a281585084148ba1389800799bd4be63b957507db1349314e474450a020504414156450a022120bd640cddb72063e2ede34c6a0baf6699759b9837fcb06aa0e2fbcecb9b65fde70a02040341434d0a0221202a01deaec9e51a579277b34b122399984d0bbf57e2458a7e42fecd2829867a0d0a0204034144410a022120fa17ceaf30d19ba51112fdcc750cc83454776f47fb0112e4af07f15f4bb1ebc00a020504414c474f0a0221206d0af467543fc7daedf7abed96423877560c8d03725f3e5c87516774982a679c0a020403414e430a02212015add95022ae13563a11992e727c91bdb6b55bc183d9d747436c80a483d8c8640a0204034150450a02212003ae4db29ed4ae33d323568895aa00337e658e348b37509f5372ae51f0af00d50a0204034150540a022120b881c6dad5dd3dc9a83222f8032fb439859288119afc742d43adc305cef151cc0a0204034153520a022120681e0eb7acf9a2a3384927684d932560fb6f67c6beb21baa0f110e993b2653860a02060541544c41530a0221208ff1200345393bb25be4f4eeb2d97234e91f7e6213f3745a694b1436e700f2710a02040341544d0a022120b00b60f88b03a6a625a8d1c048c3f66653edf217439983d037e7222c4e6128190a02050441544f4d0a0221204cbd623d7aa47003fff1cd75c3f96cb24a660014b697d91cfb7adcd204b952020a020504415553540a02212093da3352f9f1d105fdfe4971cfa80e9dd777bfc5d0f683ebb6e1294b92137bb70a020504415641580a022120b7e3904c08ddd9c0c10c6d207d390fd19e87eb6aab96304f571ed94caebdefa00a0204034158530a0221209d23a47f843f5c9284832ae6e76e4aa067dc6072a58f151d39a65a4cc792ef9f0a0204034241520a0221203dd2b63686a450ec7290df3a1e0b583c0481f651351edfa7636f39aed55cf8a30a0204034243480a0221207f981f906d7cfe93f618804f1de89e0199ead306edc022d3230b3e8305f391b00a020504424554480a0221202f95862b045670cd22bee3114c39763a4a08beeb663b145d283c31d7d1101c4f0a020403424e420a0221201ce9069708fb49e2f1b062fa4f1be0bb151475ca506939d6d8c14386d49f43dc0a02040342525a0a022120e62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b430a0204034254430a022120097d687437374051c75160d648800f021086bc8edf469f11284491fda81923150a0204034254540a0221205bc91f13e412c07599167bae86f07543f076a638962b8d6017ec19dab4a828140a020504425553440a0221202dd14c7c38aa7066c7a508aac299ebcde5165b07d5d9f2d94dfbfe41f0bc5f2e0a0204034339380a0221202356af9529a1064d41e32d617e2ce1dca5733afa901daba9e2b68dee5d53ecf90a02050443414b450a02212015ecddd26d49e1a8f1de9376ebebc03916ede873447c1255d2d5891b92ce57170a02060543424554480a022120bd4dbcbfd90e6bc6c583e07ffcb5cb6d09a0c7b1221805211ace08c8378596270a0204034348520a022120e799f456b358a2534aa1b45141d454ac04b444ed23b1440b778549bb758f2b5c0a02040343485a0a0221209c479b12a2b2c1051715d4d462dd7a6abbb6dccabf3af31a53f6130a1cd88efc0a020504434954590a0221208517b35589b5f1f6ad626da2379ff592d5101b63aa661d75b7a883fdbda023f00a020504434f50450a0221204e53c6ef1f2f9952facdcf64551edb6d2a550985484ccce6a0477cae4c1bca3e0a020403434f570a0221208f218655050a1476b780185e89f19d2b1e1f49e9bd629efad6ac547a946bf6ab0a020504435553440a022120b0948a5e5313200c632b51bb5ca32f6de0d36e9950a942d19751e833f70dabfd0a0204034441490a022120dcef50dd0a4cd2dcc17e45df1676dcb336a11a61c69df7a0299b0150c672d25c0a020504444f47450a022120ca3eed9b267293f6595901c734c7525ce8ef49adafe8284606ceb307afa2ca5b0a020403444f540a022120ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace0a0204034554480a022120c80657b7f6f3eac27218d09d5a4e54e47b25768d9f5e10ac15fe2cf9008814000a020504464944410a0221202fb245b9a84554a0f15aa123cbb5f64cd263b59e9a87d80148cbffab50c69f300a020504464c4f570a0221205c6c0d2386e3352356c3ab84434fafb5ea067ac2678a38a338c4a69ddc4bdb0c0a02040346544d0a0221206c75e52531ec5fd3ef253f6062956a8508a2f03fa0a209fb7fbc51efd9d35f880a0204034654540a022120301377b122716cee1a498e7930a1836c0b1db84667cc78bbbcbad6c330ea6afb0a02040347414c0a0221200781209c28fda797616212b7f94d77af3a01f3e94a5d421760aef020cf2bcb510a02050447414c410a022120baa284eaf23edf975b371ba2818772f93dbae72836bbdea28b07d40f3cf8b4850a020403474d540a0221206034b1f68b9363dff2cf9d53b1a88fb4d0929c65f34d532db53738853efc00ad0a020504474f46580a02212095609d32c98a467a72ac419f2e64bb2b8dbd5b00b74f3a0fd72f42343af1743d0a0205044858524f0a0221207a5bc1d2b56ad029048cd63964b3ad2776eadf812edc1a43a31406cb54bff5920a020403494e4a0a022120a4702f0f5818258783a1e47f453cb20b0fbec32ca67260e1d19dfcdd6a4d0ebb0a020605494e5445520a02212081a21b01c15b8d01f6cdfed65e00987cc4c901858c821b2089344987de3102e90a0204034a45540a022120ee42016c303126bd9263724e00f83a8114e84518c6e8ffc9738c001cc301daff0a0204034a53540a022120abe4f2b264560a397f38eec024369356e5c1ea4f7aab94729369f144b3d977790a0204034a55560a022120d1d95644ffc11ca502f21e067a7814144c56b37018515ced4335a886a827a3050a0206054c415a494f0a0221206e3f3fa8253588df9326580180233eb791e03b443a3ba7a1d892e73874e19a540a0204034c54430a022120e6ccd3f878cf338e6732bf59f60943e8ca2c28402fc4d9c258503b2edbe74a310a0205044c554e410a0221204456d442a152fd1f972b18459263ef467d3c29fb9d667e30c463b086691fbc790a0205044c554e430a0221205de33a9112c2b700b8d30b8a3402c103578ccfa2765696471cc672bd5cf6ac520a0206054d415449430a0221201888f463c27997174f97d2a36af29bf4648b61a5f69e67c45505a80f826bb7850a0205044d424f580a02212027d108eb764c912f49d3453a21dd95516619b1c45d0b607ee58a137ac8a6f32d0a0205044d45414e0a022120dfaeafde7f8ad3cb9ddbcc85ed7ae7e53910e7ab377fd75921920f97c80a8edc0a0204034d45520a0221200b46c1c04e9c914037cc4e0561a7e6787f6db0b89b7b65281f0f6fea1ce45a740a0204034d49520a0221205b70af49d639eefe11f20df47a0c0760123291bb5bc55053faf797d1ff9059830a0205044d4e474f0a022120c2289a6a43d2ce91c6f55caec370f4acc38a2ed477f58813334c6d03749ff2a40a0205044d534f4c0a022120c415de8d2eba7db216527dff4b60e8f3a5311c740dadb233e13e12547e2267500a0205044e4541520a02212005934526b94a9fbe4c4ce0c3792213032f086ee4bf58f2168a7085361af9bdc10a0203024f470a022120c572690504b42b57a3f7aed6bd4aae08cbeeebdadcf130646a692fe73ec1e0090a0204034f4e450a02212037505261e557e251290b8c8899453064e8d760ed5c65a779726f2490980da74c0a0205044f5243410a0221200afa3199e0899270a74ddcf5cc960d3c6c4414b4ca71024af1a62786dd24f52a0a020504504f52540a02212088e2d5cbd2474766abffb2a67a58755a2cc19beb3b309e1ded1e357253aa36230a020605504f52544f0a0221203d253019d38099c0fe918291bd08c9b887f4306a44d7d472c8031529141f275a0a0204035053470a022120fd0690232b0fae5efdc402c1b9aac74176383ff7daf87d021554bda24a38e0ec0a020504524143410a02212091568baa8beb53db23eb3fb7f22c6e8bd303d103919e19733f2bb642d3e7987a0a0204035241590a0221206ed3c7c4427ae2f91707495fc5a891b30795d93dbb3931782ddd77a5d8cb6db70a0204035342520a0221201021a42d623ab4fe0bf8c47fd21cc10636e39e07f91e9b2478551e137d512aaa0a02070653434e534f4c0a022120f8d030e4ef460b91ad23eabbbb27aec463e3c30ecc8d5c4b71e92f54a36ccdbd0a020504534c4e440a0221209fb0bd29fe51481b61df41e650346cc374b13c2bab2e3610364cd834a592025a0a020403534e590a022120ef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d0a020403534f4c0a02212023245bb74254e65a98cc3ff4a37443d79f527e44e449750ad304538b006f21bc0a02040353524d0a022120a1a6465f4c2ebf244c31d80bc95c27345a3424e428c2def33eced9e90d3f701b0a0206055354534f4c0a0221204457960559b812558bb0f8cb7912f8bcb843eb801a3133ef45be998630ff8c050a020403544c4d0a022120433faaa801ecdb6618e3897177a118b273a8e18cc3ff545aadfc207d58d028f70a020504545553440a022120eaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a0a020504555344430a0221202b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b0a020504555344540a022120ef94acc2fb09eb976c6eb3000bab898cab891d5b800702cd1dc88e61d7c3c5e60a020504555354430a0221207507a4629ad0143550666bce2e7cae0b961a0f624f821feaab642fe1be632f5c0a0204035641490a022120b216f7ca372b318985903866e0b6dc44a14564828c49f36d0d363805aa76335c0a02040357494e0a022120b82449fd728133488d2d41131cffe763f9c1693b73c544d9ef6aaa371060dd250a020403574f4f0a022120831624f51c7bd4499fe5e0f16dfa2fd22584ae4bdc496bbbbe9ba831b2d9bce90a0204035856530a02212026852e2d0696e25e6adaad2d7ca3a1f2f15aab68d317ace14d41b4128a7e780f0a0204035a42430a022120d6b3bc030a8bbb7dd9de46fb564c34bb7f860dead8985eb16a49cdc62f8ab3a50a02212073dc009953c83c944690037ea477df627657f45c14f16ad3a61089c5a3f9f4f20a02212008f781a893bc9340140c5f89c8a96f438bcfae4d1474cc0f688e3a52892c73180a0221204204a764d9e0ca8db0fd43b62728265bf82671ce8a8b4bfedba13672be12de620a022120cb1743d0e3e3eace7e84b8230dc082829813e3ab04e91b503c08e9a441c0ea8b0a02212044a93dddd8effa54ea51076c4e851b6cbbfd938e82eb90197de38fe8876bb66e0a022120c11efd88a9b2c96bc84bccd6ce4aa05bebad7aa760dbe5f2f00ef90c4abd50cc0a02212061226d39beea19d334f17c2febce27e12646d84675924ebb02b9cdaea68727e30a022120d7566a3ba7f7286ed54f4ae7e983f4420ae0b1e0f3892e11f9c4ab107bbad7b90a02212030029479598797290e3638a1712c29bde2367d0eca794f778b25b5a472f192de0a022120fc309467defa4b198c6b5bd59c08db4b9dfb27ddbcc32f31560f217b4ff8fc2b0a022120ecf553770d9b10965f8fb64771e93f5690a182edc32be4a3236e0caaa6e0581a0a022120457064c555edae5b6b89267e992be4c58be5375f0e9ca9749391c7094f7d90330a022120f9c0172ba10dfa4d19088d94f5bf61d3b54d5bd7483a322a982e1373ee8ea31b0a022120eb3b5720301b36fa074260e6e27e2cfff3a7c6bbb47564eb218a9a7f2a8c01930a02212006c532524fabd49cc142815502d785e4f34ec3bd035480efb770568d423f46c60a022120c098773aa18ebb7e84d5ee7ea7d97105ab2015a329f670012398cd2c8f5cc6ca0a0221200d10b9ccdc9af1d65cd4bafabf4e34db01c0ce83abba190230eaf26d7592cd210a022120970541e943e11d1bf1d4d763bc8e70995f613dc682f727045a866312312a63760a02212013ac8c71e4e1c61dece57bea76163d393bf75cd0db8e52981e1564fa592698cb0a022120b59d65c2e10af17c0d6f7d10be8d64c0c13dd15d957c4c39763b4cc55e5919370a02212087a67534df591d2dd5ec577ab3c75668a8e3d35e92e27bf29d9e2e52df8de4120a02212031775e1d6897129e8a84eeba975778fb50015b88039e9bc140bbd839694ac0ae0a02212036032e522b810babd8e3148e9f0d588af9e95e93b97ffb58566b837fdbd31f7f0a022120ca80ba6dc32e08d06f1aa886011eed1d77c77be9eb761cc10d72b7d0a2fd57a60a0221206660d7629213995af8aa169ad6a1cf1a725765d3741b7e7a27825f884a701b960a022120aa67a6594d0e1578faa3bba80bec5b31e461b945e4fbab59eeab38ece09335fb0a0221209b7bfd7654cbb80099d5edc0a29159afc9e9b4636c811cf8c3b95bd11dd8e3dd0a0221200184a60a47ab7c23fcb828d727b05748ef52433fb5ae96f775cc98c9049d8c2c0a0221206354d685c247f1efc36f967617beffa2ebd5a95d8ffe17de4498505c923067b80a02212021adabf73ad61903c1872fa220f84d3b1b9990cec2047f8317e2a67efcd1764e0a022120c999fe8a75bf9528931deb832e2934dd1ac138757d7f2c1398675b6f521d556f0a02212087fd5a8d0bf026239f98b53311d2cec2ee171e853f545e1ad742e092a97ef8600a02212051ae9b785e6aeb288955720faef15f63ee3ae21af38114ade8b3fc3d3831b5ad0a0221202d9315a88f3019f8efa88dfe9c0f0843712da0bac814461e27733f6b83eb51b30a0221202245aec1db780b8dc9f710173256996164f0a65f25a975453e4202a54371d2ea0a022120077e345652cb98edba89815a63a0ede724eba12d7a10c8498e0e762d581aca6b0a022120997e0bf451cb36b4aea096e6b5c254d700922211dd933d9d17c467f0d6f343210a022120677dbbf4f68b5cb996a40dfae338b87d5efb2e12a9b2686d1ca16d69b3d7f2040a0221206de025a4cf28124f8ea6cb8085f860096dbc36d9c40002e221fc449337e065b20a022120d2c2c1f2bba8e0964f9589e060c2ee97f5e19057267ac3284caef3bd50bd2cb50a02212070bf2974182b6ebf4eac64977170074315e7a07d7b58a963758060924ee9a1920a0221209f2acb902ee5c3a8e41c643164a498ed3089c99df3477189babd3682801340750a02212052800482aa2666c0d2621f8f0a8c19ee6e5e5039a65524e268315501b3355fbb0a0221202f317bea04ce89adb8acc85a1a68d20d6e89976d5e86306570a0bb3107e4916a0a022120b5366e5ded52c3db5d81635a624a39d81eb8c639427fc79c539e5c91e17c84940a0221207f57ca775216655022daa88e41c380529211cde01a1517735dbcf30e4a02bdaa0a02212027e867f0f4f61076456d1a73b14c7edc1cf5cef4f4d6193a33424288f11bd0f40a0221209b245faf19d2f3306b58821ef60b194d7b67eb5250635059d8eaae4a36337b280a02212085dafbfa99c733fdd33649551666958ca8f82fd0d849746e093b770caab249d20a0221206b86b78584e182c61729267d73593f48b6a929f3218234769281513cbe5e87ee0a0204035041490a0221201e761bb4e6b1e4d7899b618d389516ddbdfbdb858018b71c45cb6ade57c96f620a0221207730809b4a4656325b7fbc8157fd803c3da170727c541afc4db37773246258b10a022120cb9372930932694b8a74dd5599c0f9e236575f434faf05141d95803a91f044ed0a022120341d9502b1e6bc445036fd76f57bc824c09254a754289878b52a40eb067d2a0b0a022120f9917668f24038a383e51c0b019f5d9645d6785c6bf9a0d48483edf82ba5caec0a022120dd51a67a1b4d0702abf5b5385631b7d3e586993eadacf2e0d900c0a81edcffdd0a022120b5d2cee0b86bb0571db898ae7b9f288c5e272fa486d41a5bf375b52a0249d94c0a022120fe650f0367d4a7ef9815a593ea15d36593f0643aaaf0149bb04be67ab851decd0a02212078ec25615d53d2486db101e829f77615c4408cbbd543088714b9f267da44591a0a022120b718e659619a031b41c6ea9122f146859a82d4a7edc17c55b1e5188e8b4c1d1c0a020504535445500a02212013f7925c9186b8cca50dde4bbf2d4fa9705052cceb6f2fc79df827e2b37d6f3b0a0221200adbf6463e27f60f171bcc498703a4282d1954ec3a85e1f6698b48ecde18c00e0a0221201bd1c59cd425aebf8a931c1b2a902b9a11e7d18dc68021e4a35a5cf24220a6c70a02212041f3625971ca2ed2263e78573fe5ce23e13d2558ed3f2e47ab0f84fb9e7ae7220a0221201fc18861232290221461220bd4e2acd1dcdfbc89c84092c93c18bdc7756c15880a022120026d1f1cf9f1c0ee92eb55696d3bd2393075b611c4f468ae5b967175edc4c25c0a022120eca4f9c5ce7cbef8a349fa9f6c12b23ac45b9ad91c4d1808c6a2dda841f95a020a022120834d3f05278b6f5c963670f437a2267c160914707328f888418902106bcd13d70a022120bf517e0f7ccfc307f0b2fa93b99a737641933989af6af769c928725989c21e660a0221206ff709bf1f0fdb46d991ae6839163df1e050d143429d737fc650b6b2143478080a02212064abe8a459058c60d55427f62be3dc4942c0ba93d1eb5cb85117b70b8e4651ad126170746f733a3a6d657461646174615f763063036d000000000000001a4552525f4e4f545f454e4f5547485f5045524d495353494f4e53006e00000000000000134552525f544f4b454e5f4e4f545f464f554e44007000000000000000174552525f414c52454144595f494e495449414c495a454400000202160b0302080408051a030102011b0b03020804030000000007440a0011080c020e0211090c080b00110a0c050600000000000000000c0a090c090b0a0b0907030911070c090c0a0e05110b0c070a07031a051e0e05110c0c0305210e0511090c030b030c060b0a0b090b060b0711070c090c0a0b0a0b090b01340911060c090c0a0b090335053c0b080b0a33110d1a0c0405420b080b0a33110d180c040b04020101000200010d26070429010304050638000238010c0338020c0007042b000c010a0110000a03380303160b01010702270a0110000b033804140c020b020b0110011411120c040e040b001100020200000101151438050c0007042b010c010a0110020a003806030e0b01010702270b0110020b0038071402030104010017a4060a00111407042103090b00010701270a00111429002003120b00010700273808063c0000000000000012000c6b0a000b6b2d000b0011142a000c6c070511160c020a6c0f00070611170b023809070711160c040a6c0f00070811170b043809070911160c060a6c0f00070a11170b063809070b11160c080a6c0f00070c11170b083809070d11160c0a0a6c0f00070e11170b0a3809070f11160c0c0a6c0f00071011170b0c3809071111160c0e0a6c0f00071211170b0e3809071311160c100a6c0f00071411170b103809071511160c120a6c0f00071611170b123809071711160c140a6c0f00071811170b143809071911160c160a6c0f00071a11170b163809071b11160c180a6c0f00071c11170b183809071d11160c1a0a6c0f00071e11170b1a3809071f11160c1c0a6c0f00072011170b1c3809072111160c1e0a6c0f00072211170b1e3809072311160c200a6c0f00072411170b203809072511160c220a6c0f00072611170b223809072711160c240a6c0f00072811170b243809072911160c260a6c0f00072a11170b263809072b11160c280a6c0f00072c11170b283809072d11160c2a0a6c0f00072e11170b2a3809072f11160c2c0a6c0f00073011170b2c3809073111160c2e0a6c0f00073211170b2e3809073311160c300a6c0f00073411170b303809073511160c320a6c0f00073611170b323809073711160c340a6c0f00073811170b343809073911160c360a6c0f00073a11170b363809073b11160c380a6c0f00073c11170b383809073d11160c3a0a6c0f00073e11170b3a3809073f11160c3c0a6c0f00074011170b3c3809074111160c3e0a6c0f00074211170b3e3809074311160c400a6c0f00074411170b403809074511160c420a6c0f00074611170b423809074711160c440a6c0f00074811170b443809074911160c460a6c0f00074a11170b463809074b11160c480a6c0f00074c11170b483809074d11160c4a0a6c0f00074e11170b4a3809074f11160c4c0a6c0f00075011170b4c3809075111160c4e0a6c0f00075211170b4e3809075311160c500a6c0f00075411170b503809075511160c520a6c0f00075611170b523809075711160c540a6c0f00075811170b543809075911160c560a6c0f00075a11170b563809075b11160c580a6c0f00075c11170b583809075d11160c5a0a6c0f00075e11170b5a3809075f11160c5c0a6c0f00076011170b5c3809076111160c5e0a6c0f00076211170b5e3809076311160c600a6c0f00076411170b603809076511160c620a6c0f00076611170b623809076711160c640a6c0f00076811170b643809076911160c660a6c0f00076a11170b663809076b11160c680a6c0f00076c11170b683809076d11160c6a0a6c0f00076e11170b6a3809076f11160c6e0a6c0f00077011170b6e3809077111160c700a6c0f00077211170b703809077311160c720a6c0f00077411170b723809077511160c740a6c0f00077611170b743809077711160c760a6c0f00077811170b763809077911160c780a6c0f00077a11170b783809077b11160c7a0a6c0f00077c11170b7a3809077d11160c7c0a6c0f00077e11170b7c3809077f11160c7e0a6c0f0007800111170b7e380907810111160c80010a6c0f0007820111170b8001380907830111160c82010a6c0f0007840111170b8201380907850111160c84010a6c0f0007860111170b8401380907870111160c86010a6c0f0007880111170b8601380907890111160c88010a6c0f00078a0111170b88013809078b0111160c8a010a6c0f00078c0111170b8a013809078d0111160c8c010a6c0f00078e0111170b8c013809078f0111160c8e010a6c0f0007900111170b8e01380907910111160c90010a6c0f0007920111170b9001380907930111160c92010a6c0f0007940111170b9201380907950111160c94010a6c0f0007960111170b9401380907970111160c96010a6c0f0007980111170b9601380907990111160c98010a6c0f00079a0111170b98013809079b0111160c9a010a6c0f00079c0111170b9a013809079d0111160c9c010a6c0f00079e0111170b9c013809079f0111160c9e010a6c0f0007a00111170b9e01380907a10111160ca0010a6c0f0007a20111170ba001380907a30111160ca2010a6c0f0007a40111170ba201380907a50111160ca4010a6c0f0007a60111170ba401380907a70111160ca6010a6c0f0007a80111170ba601380907a90111160ca8010a6c0f0007aa0111170ba801380907ab0111160caa010a6c0f0007ac0111170baa01380907ad0111160cac010a6c0f0007ae0111170bac01380907af0111160cae010b6c0f0007b00111170bae0138090204010401001da7050a0011140c010a01070421030b0b00010701270a00111429002003140b0001070027380806504600000000000012000c020b000b022d000b012a000c0307b10111160c4c0a030f00070611170b4c380907b20111160c6d0a030f00070a11170b6d380907b30111160c780a030f00070c11170b78380907b40111160c83010a030f00070e11170b8301380907b50111160c8e010a030f00071011170b8e01380907b60111160c520a030f00071211170b52380907b70111160c5d0a030f00071611170b5d380907b80111160c650a030f00071a11170b65380907b90111160c660a030f00071e11170b66380907ba0111160c670a030f00072411170b67380907bb0111160c680a030f00072611170b68380907bc0111160c690a030f00072811170b69380907bd0111160c6a0a030f00072a11170b6a380907be0111160c6b0a030f00072c11170b6b380907bf0111160c6c0a030f00072e11170b6c380907c00111160c6e0a030f00073011170b6e380907c10111160c6f0a030f00073211170b6f380907c20111160c700a030f00073811170b70380907c30111160c710a030f00073e11170b71380907c40111160c720a030f00074011170b72380907c50111160c730a030f00074211170b73380907c60111160c740a030f00074411170b74380907c70111160c750a030f00074611170b75380907c80111160c760a030f00074811170b76380907c90111160c770a030f00074a11170b77380907ca0111160c790a030f00074c11170b79380907cb0111160c7a0a030f00074e11170b7a380907cc0111160c7b0a030f00075011170b7b380907cd0111160c7c0a030f00075211170b7c380907ce0111160c7d0a030f00075411170b7d380907cf0111160c7e0a030f00075611170b7e380907d00111160c7f0a030f00075811170b7f380907d10111160c80010a030f00075a11170b8001380907d20111160c81010a030f00075c11170b8101380907d30111160c82010a030f00075e11170b8201380907d40111160c84010a030f00076211170b8401380907d50111160c85010a030f00076411170b8501380907d60111160c86010a030f00076a11170b8601380907d70111160c87010a030f00076c11170b8701380907d80111160c88010a030f00076e11170b8801380907d90111160c89010a030f00077011170b8901380907da0111160c8a010a030f00077211170b8a01380907db0111160c8b010a030f00077411170b8b01380907dc0111160c8c010a030f00077611170b8c01380907dd0111160c8d010a030f00077811170b8d01380907de0111160c8f010a030f00077a11170b8f01380907df0111160c90010a030f00077c11170b9001380907e00111160c91010a030f00077e11170b9101380907e10111160c92010a030f0007820111170b9201380907e20111160c93010a030f0007840111170b9301380907e30111160c4d0a030f0007e40111170b4d380907e50111160c4e0a030f0007860111170b4e380907e60111160c4f0a030f00078c0111170b4f380907e70111160c500a030f00078e0111170b50380907e80111160c510a030f0007900111170b51380907e90111160c530a030f0007920111170b53380907ea0111160c540a030f0007940111170b54380907eb0111160c550a030f0007960111170b55380907ec0111160c560a030f0007980111170b56380907ed0111160c570a030f00079a0111170b57380907ee0111160c580a030f0007ef0111170b58380907f00111160c590a030f00079c0111170b59380907f10111160c5a0a030f00079e0111170b5a380907f20111160c5b0a030f0007a00111170b5b380907f30111160c5c0a030f0007a20111170b5c380907f40111160c5e0a030f0007a40111170b5e380907f50111160c5f0a030f0007a60111170b5f380907f60111160c600a030f0007a80111170b60380907f70111160c610a030f0007aa0111170b61380907f80111160c620a030f0007ac0111170b62380907f90111160c630a030f0007ae0111170b63380907fa0111160c640b030f0007b00111170b6438090205010401001e120a00111407042103090b00010701270b0011142a000c020b010b020f011502060000001f5d0a010a031f0305051c0a020a0026030a05110b020b0017090c070c0405170b000b0217080c070c040b040b070c060c05055a0a01031f05230a03200c080525090c080b080328052f0b000b0216080c0e0c0d05560b01200b031f0335053c0b000b0216090c0c0c0b05520a000a0226034105480b000b0217090c0a0c09054e0b020b0017080c0a0c090b090b0a0c0c0c0b0b0b0b0c0c0e0c0d0b0d0b0e0c060c050b050b060207000000205e0a010a031f03050508080c0705140a0120030c05100a03200c040512090c040b040c070b070317051e0b000b02160b010c060c05055b0b01032105250b03200c080527090c080b08032a05410a000a0224032f05360b000b0217080c0a0c09053c0b020b0017090c0a0c090b090b0a0c0e0c0d05570a020a00240346054d0b020b0017080c0c0c0b05530b000b0217090c0c0c0b0b0b0b0c0c0e0c0d0b0d0b0e0c060c050b050b060200000001010000"; + let res = run_binary_test("sample_price_oracle", code); + assert!(res.is_ok(), "{:?}", res) +} + +#[cfg(feature = "address32")] +#[test] +fn sample_aptosd_swap() { + let code = "a11ceb0b050000000c0100160216300346ee0104b4022205d602960407ec06de0708ca0e40068a0f8b01109510f9010a8e12520ce012e80e0dc821160000010101020103010401050106010700080009000a000b0700000c0700000d0800000e0700000f07000a28040207000400042b0401060102380800083a0000063c070100000010000100001102010000120101000013030100001401010000150101000016020100001701040000180506000019010700001a020100001b020100001c010100001d000100001e020100001f02010000200001000021000100092f01090009300105000a310b0c02070604320e01010607330205000934010f0009350104000936010f000a37110f020704033900010100033b02010100093d0104000a3e1617020704063f180f01000640191a01000a411b1c02070409421d010005431f040005441f0400094501200009460104000947010f0009480901000a490125020704014a022601060a4b1128020704140a150d1a0a1b121c1315141e0a1f052005210a151e290a2a0d2a142a1e2b0a1b1303060c05030001060c02060c0301030105050303030303010a050c03030303030505070b0502050803070b0502050803070802070803070b0601080401020205080303070b050209000901090009010107090101080402070b060109000900010108070b05020508030501070b06010800030107080207080302060b05020900090109000108070108080108002d0b0901050b0901050b0901050c0b0901050b0901050b0901050b0901050b090105030303030303070b06010801070b06010801070b06010801070b0601080103070803070803070803070803070b0502050803070b0502050803070b0502050803070b0502050803070b090105070b090105070b090105070b09010503030b0901050b0901050b0901050b090105070802070802070802070802070802030301060b050209000901010b0901090001060b0901090001070b0901090001090002070b0502090009010900030709010b090109000b09010900020503010801020303010c04010103030a03030303030505070b0502050803070b0502050803070803070b0901050b090105070803070b0502050803070b0901050b0901050a050a0b0502050803060c030c0b060108040c0b060108000c0b060108010c010b050209000901010b060109000c0b0901050c070b0502050803050b090105070b06010801060803070b0502050803070b0901050b090105070802060c030609010b090109000b090109000d6170746f737061645f73776170076163636f756e740a6170746f735f636f696e04636f696e056576656e74066d6174683634066f7074696f6e067369676e65720d6170746f737061645f636f696e06636f6e6669670e6974657261626c655f7461626c65104269644170746f735061644576656e7417446973747269627574654170746f737061644576656e74114c61756e636850616452656769737472790f546f6b656e446973747269627574650e57686974654c6973744576656e740c61646457686974654c6973740c6173736572745f61646d696e136173736572745f6e6f5f656d657267656e63790b6269644170746f735061640d64697374726962757465416c6c0e64697374726962757465417470701064697374726962757465536561736f6e0f67657453776170546f74616c4269640c67657457686974654c6973740d67657457686974654c697374730a696e697469616c697a650f6c61756e6368506164536561736f6e09726566756e64416c6c0b726566756e644170746f730b7265736574536561736f6e0f77686974654c697374536561736f6e0d77697468647261774170746f731077697468647261774170746f73506164036361700362696408696e766573746f72106469737472696275746564546f6b656e06726566756e6409696e766573746f72730d4974657261626c655461626c6508746f74616c426964126269646170746f737061645f6576656e74730b4576656e7448616e646c6519646973747269627574656170746f737061645f6576656e74731077686974656c6973745f6576656e74730b64697374726962757465640c676574537761705374617465126765745265736f757263654164647265737317626f72726f775f6d75745f776974685f64656661756c740a656d69745f6576656e740a616464726573735f6f660b6973456d657267656e63791467657453776170436f6e6669674861726443617011697342797061737357686974654c69737408636f6e7461696e73094170746f73436f696e087472616e736665720c4170746f73506164436f696e087265676973746572064f7074696f6e1a67657453776170436f6e666967417074546f417074745261746508686561645f6b65790769735f736f6d6507657874726163740f626f72726f775f697465725f6d75740a6d696e7441747070546f036d696e036d6178116765745265736f757263655369676e65721467657453776170436f6e666967536f66744361701967657453776170436f6e666967456e61626c65526566756e640c736574537761705374617465036e6577106e65775f6576656e745f68616e646c650b626f72726f775f6974657241376d8231e6aedc29a19459e804b3770a250c3f367ac8d0f91e10842e8c906d0000000000000000000000000000000000000000000000000000000000000001030800e87648170000000308950100000000000003089a0100000000000003089b010000000000000308930100000000000003089801000000000000030896010000000000000308970100000000000003089901000000000000020104020105020101020103020102052041376d8231e6aedc29a19459e804b3770a250c3f367ac8d0f91e10842e8c906d126170746f733a3a6d657461646174615f7630e4010893010000000000000f4552525f5045524d495353494f4e530095010000000000000d4552525f454d455247454e4359009601000000000000104552525f534541534f4e5f454e444544009701000000000000144552525f534541534f4e5f4e4f545f5245534554009801000000000000114552525f534541534f4e5f414354495645009901000000000000104552525f534541534f4e5f5354415445009a01000000000000134552525f484152444341505f52454143484544009b01000000000000144552525f4e4f545f494e5f57484954454c4953540b6572726f7220636f64657300020322032303240501020522032303250326032405020205270b050205080329032a0b060108002c0b060108012d0b06010804030206220323032e03250326032405040206220323032e032503260324050001000102083c0b0011011112070d21030807082711132a020c0c0a0c0f000c0b0b0c0f010c0e0b0b0c0a0a010c090b010c080b0a0b090600000000000000000600000000000000000600000000000000000600000000000000000600000000000000000b08120338000c0d0b020a0d0f02150b0e0a0d1002140a0d1003140a0d1004140a0d1005140a0d1005140b0d10061412043801020100000001080b001116070e210307070427020200000001061117200305070127020301000102106111021112070c2103090b000107082711180c0611132a020c0811190c040a080f000a0011160c030c020b022e0b0338020c070b040b071e03250b00010b08010703270a081007140b062503310b00010b08010702270a081007140a01160a080f07150a080f080c050a0011130a0138030a0038040b080f000a00111607000600000000000000000600000000000000000600000000000000000600000000000000000b001116120338000c090b010a090f03150b050a091002140a091003140b091006141200380502040000010215a00311180c13111d0c2b11132a020c260b261007140c2c0b2c0a13250310055c11132a020c270a270f000c180b270f090c0f0a182e38060c010d010c1c0a1c2e3807032405550a180b1c380838090c22010c140a141003140a140f0a150a14100a140a2b180a140f04150a141006140a1410041411220a0f0a141002140a141003140a141004140a141005140b141006141201380a0d220c1c051f0b1c010b18010b0f01059f030b130c0a11132a020c2a0a2a0f000c1b0b2a0f090c120a1b2e38060c040d040c1f0a1f2e3807037205c3010a1b0b1f380838090c23010c170a171002140c0d0a171003140c0b0b0d0b0b11230a0a11230c090a0906000000000000000024038c0105b4010a090a170f0a150a090a2b180a170f04150b0a0b09170c0a0a171006140a1710041411220a120a171002140a171003140a171004140a171005140b171006141201380a05b6010b17010a0a0600000000000000002503bb0105c0010b1b010b120105c3010d230c1f056d0a0a0600000000000000002403c80105b30211132a020c280a280f000c190b280f090c100a192e38060c000d000c1d0a1d2e380703dc0105b3020a190b1d380838090c24010c150a151003140a15100a141706000000000000000011240a0a11230c200a200600000000000000002403f40105a4020a15100a140a20160a150f0a150a200a2b180c210a151004140a21160a150f04150b0a0b20170c0a0a151006140b2111220a100a151002140a151003140a151004140a151005140b151006141201380a05a6020b15010a0a0600000000000000002503ab0205b0020b19010b100105b3020d240c1d05d7010b0a0600000000000000002503b90206a1860100000000002711132a020c290a290f000c1a0b290f090c110a1a2e38060c020d020c1e0a1e2e380703cd020599030a1a0b1e380838090c25010c160a161003140c0c0a16100a140c0e0a0c0a0e2603e8020b1a010b16010b1101061127000000000000270b0c0b0e1706000000000000000011240a160f05150a161005140600000000000000002403f70205940311250c030e030a161006140a16100514110d0a110a161002140a161003140a161004140a161005140b161006141201380a0596030b16010d250c1e05c8020b1e010b1a010b1101020500000102211a11260c0211132a021007140c0311270c010b01030c05110b030b02230c000513090c000b0003160518110c05191104020601000102010f0b00110111021112070c210309070827070911281105070a1128020701000102010511132b02100714020801000102222511132a020f000c090b090c080a000c070b000c060b080b070600000000000000000600000000000000000600000000000000000600000000000000000600000000000000000b06120338000c0a0a0a1002140a0a1003140a0a100a140a0a1004140b0a100514020901000102232611132a020f000c03400500000000000000000c060a032e38060c000d000c040a042e3807031105200a030b04380838090c05010c020d060b0210061444050d050c04050c0b04010b03010b06020a01000024220b00110111250c0a0e0a0c02380b0c0111250c040e04380c0c0511250c060e06380d0c0711250c080e08380e0c090b020b010600000000000000000b070b090b0512022d02070b1128020b010000010b0b0011011112070d210308070827070c1128020c00000102274a11132a020c0a0a0a0f000c070b0a0f090c050a072e38060c000d000c0811250c010e010c0b0a082e3807031805410a070b0838080c030c020b022e0b03380f0c09010c060a0b0a061006140a06100314110d0a050a061002140a061003140a061004140a061005140b061006141201380a0d090c0805130b0b010b08010b07010b0501020d00000001050b000b010b023803020e010000010b0b0011011112070a210308070627070b1128020f010000010b0b0011011112070b210308070727070d1128021001000020090b00110111250c030e030b010b023803021101000020090b00110111250c030e030b010b02381002020002040300030103030304030502010202020303020000"; + let res = run_binary_test("sample_aptosd_swap", code); + assert!(res.is_ok(), "{:?}", res) +} + +#[cfg(feature = "address32")] +#[test] +fn sample_router() { + let code = "a11ceb0b050000000a01000e020e0603148f0104a3012805cb018f0207da03f90208d30640069307a00110b3082b0cde08db110000010101020003000400050006010a0401000100070000000008010202000000090102020000020b050600050c060700050d050200030e0207020000040f02070200000410020a0200000111020c01000612000d000113020f01000414020a0200000115100f0100031611120200000117130201000418020d0200000519140d00041a1500020000041b020a020000041c020d020000051d140d00031e111202000006080609070907080808090b0b0e0c080d0b0e080f0b100812080f0e0809090e130914091209160802040403060c030300030404043501010101010103030404040404040404040b000109000b000109000b000109000b000109000b000109000b000109000b000109010b000109010b0001090103030303030303030404030301010404010404040503030303030301060c0105010102090009010209010900010301090001020104010901010b0001090002060c0308060c070b00010900070b00010901030301030302030302050b000109000305040106060c010303030432010103030404040404040404040b000109000b000109000b000109000b000109000b000109000b000109000b000109010b000109010b000109010303030303030404030301010404010404040505030303030303030306726f7574657204636f696e067369676e657203616d6d0b636c6f625f6d61726b657403666565047574696c0873696d706c69667918737761705f636f696e5f666f725f65786163745f636f696e18737761705f65786163745f636f696e5f666f725f636f696e04436f696e0a616464726573735f6f660a6665655f65786973747316696e697469616c697a655f6665655f64656661756c740b706f6f6c5f6578697374730d6d61726b65745f657869737473086c6f745f73697a6508646563696d616c7303657870047a65726f0c6e5f6269645f6c6576656c730877697468647261771d636f696e5f737761705f636f696e5f666f725f65786163745f636f696e076465706f7369740b626573745f6269645f61750c73756274726163745f66656516706c6163655f6f726465725f666f725f726f757465720c6e5f61736b5f6c6576656c730b626573745f61736b5f6175076164645f6665651d636f696e5f737761705f65786163745f636f696e5f666f725f636f696e49661cd59c0b89440313af587bc99c3d38614d9a52479eb3f7c7c766d580c30b00000000000000000000000000000000000000000000000000000000000000010308c9000000000000000308ca000000000000000308c800000000000000030804000000000000000308070000000000000003086500000000000000030866000000000000000308030000000000000003080200000000000000030864000000000000000308ffffffffffffffff0308050000000000000003080100000000000000030868000000000000000308670000000000000003080600000000000000126170746f733a3a6d657461646174615f7630170104000000000000000c45544553545f4641494c4544000001000003190a000c030a010c040a01320000000000000000000000000000000022030905120b000a01190c020b010c000b020c0105040b030a001a0b040b001a020101040004ec030a0011030c310a311104200308050a0a0011053800030d0510080c03051238010c030b030c2d38020c2a38030c290a2d0b291f031d05fb0138040c27320a000000000000000000000000000000380535110a0c0e0600000000000000000c320600000000000000000c3438060c1a0a340a0223032f05340a320a01230c060536090c060b06033905eb01380706000000000000000021033e055f0a000a010a321738080c140b000d140d1a0a010a32170a020a34170906000000000000000006000000000000000038090c210c1d0a310b14380a0b320b21160c320b340b1d160c3405eb01380b0c130a310a130811110c120a020a3417350a0e180a121a340c090b090a272303750596010a000a010a321738080c180b000d180d1a0a010a32170a020a34170906000000000000000006000000000000000038090c230c1f0a310b18380a0b320b23160c320b340b1f160c3405eb010a0e0a1211000c250c2b0a000a010a321738080c190a000d190d1a0a010a32170a020a3417080b2b340b253438090c240c200a310b19380a0b320b24160c320b340b20160c340a340a022303c20105c7010a320a01230c0805c901090c080b0803cc0105ea010a020a3417350a0e180b121a340c0a0a000907060b13340b0a3200000000000000000000000000000000380c0c2e0c0d0b320b0d34160c320b340b2e34160c34052a0b320b012503f1010707270b340b022103f7010708270b310b1a380d05eb030a2d0a2a1f03800205b203380e0c28320a000000000000000000000000000000380f35110a0c0f0600000000000000000c330600000000000000000c3538060c1b0a350a02230392020597020a330a01230c04059902090c040b04039c0205a20338100600000000000000002103a10205a402080c0505aa020a020a35170a28230c050b0503ad0205ce020a000a010a331738080c150b000d150d1b0a010a33170a020a35170906000000000000000006000000000000000038090c220c1e0a310b15380a0b330b22160c330b350b1e160c3505a20338110c110a310a110811150c100b100a0f11000c260c2c0a000a010a331738080c160a000d160d1b0a010a33170a020a3517080b2c340b263438090c360c370a310b16380a0b330b36160c330b350b37160c350a350a02230381030586030a330a01230c07058803090c070b07038b0305a1030a000807060b11340a020a3517320000000000000000000000000000000038120c2f0c0b0b330b2f34160c330b350b0b34160c35058d020b330b012503a8030707270b350b022103ae030708270b310b1b380d05eb030b2d03b50305cd030a000a0138080c1738060c1c0b000d170d1c0b010b0209060000000000000000060000000000000000380901010a310b17380a0b310b1c380d05eb030b2a03d00305e7030b00080705070a0a02320000000000000000000000000000000038120c300c0c0b0c340b022103e0030707270b30340b012503eb030708270b0001070c27020201040016d1030a0011030c2b0a2b1104200308050a0a0011053800030d0510080c03051238010c030b030c2738020c2438030c230a270a231f031d05b70138040c21320a000000000000000000000000000000380535110a0c0a0600000000000000000c2d0600000000000000000c2f38060c160a2d0a0123032f05a70138070600000000000000002103340537080c04053d0a010a2d170a21230c040b040340055f0a000a010a2d1738080c100b000d100d160a010a2d170600000000000000000906000000000000000006000000000000000038130c1c0c190a2b0b10380a0b2d0b1c160c2d0b2f0b19160c2f05a701380b0c0f0a2b0a0f0811110c0e0b0e0a0a11000c1f0c250a000a010a2d1738080c140a000d140d160a010a2d17060000000000000000080b25340b1f3438130c310c330a2b0b14380a0b2d0b31160c2d0b2f0b33160c2f0a2d0a012303900105a6010a000907060b0f340a010a2d173200000000000000000000000000000000380c0c280c080b2d0b0834160c2d0b2f0b2834160c2f052a0b2d0b012103ad010707270b2f0b022603b3010708270b2b0b16380d05d0030a270b241f03bc01059403380e0c22320a000000000000000000000000000000380f35110a0c0b0600000000000000000c2e0600000000000000000c3038060c180a2e0a012303ce0105840338100600000000000000002103d30105f2010a000a010a2e1738080c150b000d150d180a010a2e170600000000000000000906000000000000000006000000000000000038130c1d0c1a0a2b0b15380a0b2e0b1d160c2e0b300b1a160c3005840338110c0d0a2b0a0d0811150c0c0a010a2e17350a0b180a0c1a340c050b050a222303880205a7020a000a010a2e1738080c110b000d110d180a010a2e170600000000000000000906000000000000000006000000000000000038130c1e0c1b0a2b0b11380a0b2e0b1e160c2e0b300b1b160c300584030a0b0a0c11000c200c260a000a010a2e1738080c120a000d120d180a010a2e17060000000000000000080b26340b203438130c320c340a2b0b12380a0b2e0b32160c2e0b300b34160c300a2e0a012303d1020583030a010a2e17350a0b180b0c1a340c060a000807060b0d340a06320000000000000000000000000000000038120c2a0c070a07340b062503ee020b0001061111000000000000270a2a340a010a2e172503f9020b0001062222000000000000270b2e0b2a34160c2e0b300b0734160c3005c9010b2e0b0121038a030707270b300b02260390030708270b2b0b18380d05d0030b2703970305b2030a000a0138080c1338060c170a000d130d170b010b0209060000000000000000060000000000000000381301010b0011030c2c0a2c0b17380d0b2c0b13380a05d0030b2303b50305cc030b000907050600000000000000000a013200000000000000000000000000000000380c0c290c090b09340b012103c5030707270b29340b022603d0030708270b0001070c270200"; + let res = run_binary_test("sample_router", code); + assert!(res.is_ok(), "{:?}", res) +} + +#[cfg(feature = "address32")] +#[test] +fn sample_pool() { + let code = "a11ceb0b050000000c010020022079039901c90204e2036605c804fd0507c50aa80c08ed166006cd17c101108e19bb020ac91bd4020c9d1eb3250dd043340000010101020103010401050106010701080109010a020b000c000d000e000f0010070000110600001206000013060000140600001508000000040000160800001708000018060000190600001a0600001b0600071d07000b2707000b3a0700053c040106010344040100010245080009470402030100010b480400084e0402030100010b6c07000e7807000e7b07000e7e07000e80010700001c000100001e020100001f030100002002010000210201000022020100002300010000240201000025040100002605010000280607000029080100002a090100002b0a0100002c0b01000658050d0008590f07020300045a101000085b1213020300045c101000035d15160100035e17010100035f1810010005601a0101060b611e1c000b621f06000b632010000b64212200096524010203000a66250101000867122a0203000a682c2d01000a672e2f01000967312a0203000b69320100096a3301020300036b340101000d6d393a000c6d393a0009593b070203000b6e1c3c000b6f3d10000b703d10000b713d0d0003723e16010007733f1d000d74393a000c74393a000975013302030408654401020300087501460203040176054701060b7706100008790f490203000e7a4b4a000e7c4c4d000f7d4e0101040e7f3951000e81010e5300100e1011121114141514161417191c231d1c17261728120e1e111f2b202b12302123232324141735173617371f1c201c27232c1417403023103031303111310e17453211320e32303345333733263319333533363328334035303511384d384a3851350e385303060c04030006060c040a050a080d0a080d0a0306060c04020303030b060c020a050a080d0a080d0a03030303030201060c01080e010103060c05080d02060c0407060c03030303030302060c05040b11010812070805070806070808010502050a0402060b150209000901090001030204080602070b15020900090109000107090101081202060c03010b1101090002070b110109000b1101090001060b1101090001080202070b100109000900070708050303070806070808080f0a080f01080f01080d0405080d080d030305080d080d0205080f03060c080f0301081402080f081403070b1302090009010900090102070a09000a0900010803030708050708060708080108041a06040604030b1101081205080d070a0405020307080503030303030307080803080f0a080f0b1302080f0814040302070a04010901010402060a090006090002010302070a0900030109000208000a0402070b130209000901090002060c0814010b13020900090102050b1101090001080c01080b0108092c03030303030816050405080d040302030a080f0303030503080d03070b1001080a020b11010812030307080503030303030303070806070b150204080603060816030503080f0a080f0503030303030602030303030302060b13020900090109000108160106081602070b1101090003010a0201080a2b03030303030816050405080d040302030a080f0303030503080d03070b1001080a020b110108120307080503030303030303070806070b150204080603060816030503080f0a080f08070805030303070806070808080f0a080f0d01050b1101081206080d060507080507040303070808080f0a080f0b1302080f081403070b15020900090109000901010801010b150209000901010b10010900080800030403060a040608060708080a0817010609010108170d05030305080d020303020a080f0304030405080d0a040a081701081802060c09000206080607080817030303020303030303020303030303020303030303030301081902060a0407080801081a04506f6f6c076163636f756e740a6170746f735f636f696e04636f696e056572726f72056576656e74067369676e657206737472696e67057461626c65117461626c655f776974685f6c656e67746806766563746f7205746f6b656e104578706f6e656e7469616c43757276650b4c696e6561724375727665054d6f64656c04566965770c436f6c6c656374696f6e49640f437265617465506f6f6c4576656e74144465706f736974436f696e506f6f6c4576656e74154465706f736974546f6b656e506f6f6c4576656e740d45646974506f6f6c4576656e740a4576656e7453746f726508506f6f6c4775696405506f6f6c730f52656d6f7665506f6f6c4576656e7409537761704576656e74155769746864726177436f696e506f6f6c4576656e74165769746864726177546f6b656e506f6f6c4576656e740b4465706f736974436f696e06537472696e670c4465706f736974546f6b656e0845646974506f6f6c0a52656d6f7665506f6f6c1753776170436f696e466f7253706563696669634e4654730f537761704e465473466f72436f696e0c5769746864726177436f696e0d5769746864726177546f6b656e066372656174650b696e69745f6d6f64756c650b546f6b656e4461746149640a69735f6572633131353515766965775f636f6c6c656374696f6e5f706f6f6c7309766965775f706f6f6c0f766965775f70726963655f63616c630f766965775f757365725f706f6f6c7312636f6c6c656374696f6e5f63726561746f720f636f6c6c656374696f6e5f6e616d650763726561746f7207706f6f6c5f69640a73706f745f70726963650563757276650564656c7461116c705f6665655f6d756c7469706c69657204747970650673656e646572136465706f7369745f636f696e5f616d6f756e7405636f696e7309746f6b656e5f69647307546f6b656e49640b6372656174655f706f6f6c0b4576656e7448616e646c650b72656d6f76655f706f6f6c126465706f7369745f746f6b656e5f706f6f6c116465706f7369745f636f696e5f706f6f6c1377697468647261775f746f6b656e5f706f6f6c1277697468647261775f636f696e5f706f6f6c09656469745f706f6f6c047377617004436f696e094170746f73436f696e06746f6b656e730f5461626c65576974684c656e67746805546f6b656e0c7472616e73616374696f6e7317746f74616c5f7472616e73616374696f6e5f76616c75650f6c705f6665655f6561726e696e677305636f756e7405706f6f6c73055461626c650a757365725f706f6f6c7310636f6c6c656374696f6e5f706f6f6c730b636f696e5f616d6f756e740c70726f746f636f6c5f6665650e70726f746f636f6c5f70617965650b726f79616c74795f6665650d726f79616c74795f7061796565066c705f6665651477697468647261775f636f696e5f616d6f756e740a616464726573735f6f6608636f6e7461696e7310696e76616c69645f617267756d656e740a626f72726f775f6d7574117065726d697373696f6e5f64656e696564087769746864726177056d657267650576616c75650a656d69745f6576656e74136372656174655f746f6b656e5f69645f726177146372656174655f746f6b656e5f646174615f69640a62616c616e63655f6f660e77697468647261775f746f6b656e0361646406617070656e640672656d6f766508696e6465785f6f660d6465706f7369745f746f6b656e0d64657374726f795f656d707479076465706f73697407526f79616c74790a676574427579496e666f0b6765745f726f79616c7479176765745f726f79616c74795f64656e6f6d696e61746f72156765745f726f79616c74795f6e756d657261746f72116765745f726f79616c74795f7061796565076578747261637404757466380b67657453656c6c496e666f036e6577106e65775f6576656e745f68616e646c65156765745f746f6b656e646174615f6d6178696d756d08506f6f6c5669657706626f72726f7709706f6f6c5f7669657713436f6c6c656374696f6e506f6f6c735669657715636f6c6c656374696f6e5f706f6f6c735f7669657704766965770d507269636543616c63566965770f70726963655f63616c635f766965770d55736572506f6f6c73566965770f757365725f706f6f6c735f76696577ecb44cec6276ddc5860a13b976262c786e06af8f7306923cabec17808dabf0940000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000303086600000000000000030869000000000000000308680000000000000003086e000000000000000308670000000000000003086a0000000000000003086b0000000000000003086c000000000000000308650000000000000003086d000000000000000520ecb44cec6276ddc5860a13b976262c786e06af8f7306923cabec17808dabf09403086400000000000000052000000000000000000000000000000000000000000000000000000000000000000a0204036275790a02050473656c6c126170746f733a3a6d657461646174615f7630a6020a6500000000000000074552525f4e554d006600000000000000134552525f444946465f434f4c4c454354494f4e006700000000000000124552525f4e4f545f45584953545f504f4f4c006800000000000000154552525f494e56414c49445f504f4f4c5f54595045006900000000000000154552525f494e56414c49445f504f4f4c5f41524753006a000000000000001c4552525f4e4f545f4558495453545f544f4b454e5f494e5f504f4f4c006b00000000000000124552525f4e4f545f484156455f544f4b454e006c00000000000000144552525f4e4f545f504f4f4c5f43524541544f52006d00000000000000184552525f504f4f4c5f4e4f545f454e4f5547485f434f494e006e00000000000000114552525f49535f313135355f544f4b454e000002022d052e080d0102092f0530042d052e080d3103320233033403350202020a360530042d052e080d37033803310332023303340303020a360530042d052e080d390a080f3803310332023303340304020730042d052e080d31033202330334030502083b0b100108013d0b100108093e0b100108033f0b10010802400b1001080c410b1001080b420b10010804430b1001080a06020e2f053103380b11010812460b1302080f08142d052e080d3202330334033502390a080f49034a044b030702014c040802034d0b15020408064f0b1502050a04500b150208000a0409020c2f0530042d052e080d3103320233033403350249034a044b030a0210360530042d052e080d310332023303390a080f510352035305540355055603380335080d0b020a360530042d052e080d5703380331033202330334030c020a360530042d052e080d390a080f380331033202330334030001000205080c61070a2a080c06070a2a050c040a0610000a00110f3800040d05160b00010b06010b040107041111270a0610010a013801041c05250b00010b06010b040107041111270b060f010a0138020c050a051002140a00110f210432053b0b00010b05010b040107071113270a000a0238030c030a050f030b0338040b040f040b00110f0b010a051005140a051006140b020a05100338050a051007140a051008140a051009140b05100a1412023806020101000205081bd801070a2a080c0a070a2a050c060a0a10000a00110f3800040d05160b00010b0a010b060107041111270a0a10010a013801041c05250b00010b0a010b060107041111270b0a0f010a0138020c09401c00000000000000000c0c0a091002140a00110f210434053d0b00010b09010b060107071113270e02410d0c080600000000000000000c070a070a082304b60105470e020a07420d0a09100521044f05580b00010b09010b060107001111270e030a07421d0a09100621046005690b00010b09010b060107001111270e020a07420d140e030a07421d140e040a07421d140e050a0742101411180c0b0e020a07420d140e030a07421d140e040a07421d141119110a20048c010595010b00010b09010b060107031111270d0c0a0b441c0a00110f0a0b111a0601000000000000002604a00105a9010b00010b09010b060107061111270a090f0b0a0b0a000b0b060100000000000000111b38070b07060100000000000000160c0705420a090f0c0a0c38080b060f0d0b00110f0b010a091005140a091006140b0c0a09100338050a091007140a091008140a091009140b09100a1412033809020201000205082759070a2a080c08070a2a050c060a0810000a00110f3800040d05160b00010b08010b060107041111270a0810010a013801041c05250b00010b08010b060107041111270b080f010a0138020c070a071002140b00110f21043205390b07010b060107071113270a020a070f08150a040a070f09150a030a070f07150a050a070f0a150b060f0e0b010a071005140b071006140b030b020b040b051204380a0203010002050829dc01070a2a080c17070a2a050c100a1710000a00110f3800040d05160b00010b17010b100107041111270a170f000a00110f380b0c1f0a1710010a0138010422052d0b1f010b00010b17010b100107041111270a170f010a01380c13060c150c1c0c1d010c1e0c160c0f0c0e0c0b0c0a0c1b0c090c180c0d0a0d0a00110f21044605510b1f010b00010b17010b100107071113270a1f0e010c062e0b06380d0c12010b1f0b12380e010b170f0f0a0a0a0b1200380f0c0c0a0c0e010c072e0b07380d0c13046d05760b00010b10010b0c0107051111270b0c0b13380e010600000000000000000c110e02410d0c14401c00000000000000000c1a0a110a142304a5010586010e020a11420d140e030a11421d140e040a11421d140e050a1142101411180c190d1a0a19441c0a000d1b0b19381011220b11060100000000000000160c110581010b1b38110e0938050c080a00110f0b0938120a100f100a0d0a010a0a0a0b0b1a0600000000000000000600000000000000003100060000000000000000060000000000000000120c38130a100f110b0d0a010a0a0a0b0b080600000000000000000600000000000000003100060000000000000000060000000000000000120b38140b100f120b00110f0b010b0a0b0b0b180b0e0b0f0b160b1e0b1d0b1c0b15120938150204010002050838d502070a2a080f010c2a070a2a050c210a2a0a010c102e0b103801040f05180b00010b2a010b210107041111270e02410d0c270b2a0a0138020c290a2910081431012104380a291007140a291009140a270a29100a14070b11250c0a0c090c080c070c060c1d055a0a29100814310221043f05480b00010b29010b210107021111270a291007140a291009140a270a29100a14070b11260c0a0c090c080c070c060c1d0b1d0b060b070b080b090b0a0c240c2b0c1f0c250c26310021046905720b00010b29010b21010701111127070c0600000000000000000600000000000000000c2f0c2d0c2e0b260a290f07150b250a290f0915401c00000000000000000c310a000a1f38030c1e0600000000000000000c220a220a272304f401058d010e020a22420d140e030a22421d140e040a22421d140e050a2242101411180c300a29100c0e3038160c2304a60105af010b00010b29010b210107051111270a290f0c0b233817010d310a30441c0a29100b0a30381804bd0105c6010b00010b29010b210107051111270a000a290f0b0a30381011220b3011280c0b0e0b0c2c0a2c11290c200a2c112a0c280b2c112b0c2e0a200600000000000000002204ef010a1f0a271a0b28180b201a0c2d0b2f0a2d160c2f0a2e0d1e0a2d381938120b22060100000000000000160c220588010a291013140a1f35160a290f13150a29101414060100000000000000160a290f1415070a0d1e0a2b381938120a290f030b1e38040b210f150c1c0b00110f0c0c0b010c0d0a291005140c0e0a291006140c0f0a291007140c110a291008140c120a291009140c130b310c140b1f0a2b160b2d160c150b2b0c160b2f0c170b2e0c180b240c19070d112d0c1a0b29100338050c1b0b1c0b0c0b0d0b0e0b0f0b110b120b130b140b150b16070a0b170b180b190b1b0b1a120a381a02050100020508418c03070a2a080f010c29070a2a050c200a290a010c102e0b103801040f05180b00010b29010b200107041111270e02410d0c250b290a0138020c280a2810081431012104380a281007140a281009140a250a28100a14070b112e0c0a0c090c080c070c060c1d055a0a28100814310221043f05480b00010b28010b200107021111270a281007140a281009140a250a28100a14070b112f0c0a0c090c080c070c060c1d0b1d0b060b070b080b090b0a0c220c2a0c270c230c24310021046905720b00010b28010b20010701111127070c0600000000000000000600000000000000000c2e0c2c0c2d401c00000000000000000c300a280f030a270a2a1738190c1e0600000000000000000c210a210a2523049a020588010e020a21420d0a281005210490010599010b00010b28010b200107001111270e030a21421d0a2810062104a10105aa010b00010b28010b200107001111270e020a21420d140e030a21421d140e040a21421d140e050a2142101411180c2f0e020a21420d140e030a21421d140e040a21421d141119110a2004cd0105d6010b00010b28010b200107031111270d300a2f441c0a00110f0a2f111a0601000000000000002604e10105ea010b00010b28010b200107061111270a280f0b0a2f0a000a2f060100000000000000111b38070b2f11280c0b0e0b0c2b0a2b11290c1f0a2b112a0c260b2b112b0c2d0a1f060000000000000000220495020a270a251a0b26180b1f1a0c2c0b2e0a2c160c2e0a2d0d1e0a2c381938120b21060100000000000000160c210583010a280f0c0a303808070a0a280f030a2a381938120b240a280f07150b230a280f09150a00110f0b1e38120a281013140a270a2a170b2e1735160a280f13150a28101414060100000000000000160a280f14150b200f150c1c0b00110f0c0c0b010c0d0a281005140c0e0a281006140c0f0a281007140c110a281008140c120a281009140c130b300c140b270a2a170a2c170c150b2a0c160b2c0c170b2d0c180b220c19070e112d0c1a0b28100338050c1b0b1c0b0c0b0d0b0e0b0f0b110b120b130b140b150b16070a0b170b180b190b1b0b1a120a381a020601000205082770070a2a080c05070a2a050c030a0510000a00110f3800040d05160b00010b05010b030107041111270a0510010a013801041c05250b00010b05010b030107041111270b050f010a0138020c040a041002140a00110f210432053b0b00010b04010b030107071113270a04100338050a02260442054b0b00010b04010b030107091111270a00110f0a040f030a02381938120b030f110b00110f0b010a041005140a041006140b020a04100338050a041007140a041008140a041009140b04100a14120b38140207010002050842a901070a2a080c0b070a2a050c060a0b10000a00110f3800040d05160b00010b0b010b060107041111270a0b10010a013801041c05250b00010b0b010b060107041111270b0b0f010a0138020c0a401c00000000000000000c0d0a0a1002140a00110f210434053d0b00010b0a010b060107071113270e02410d0c090600000000000000000c070a070a0923048b0105470e020a07420d140e030a07421d140e040a07421d140e050a0742101411180c0c0a0a100c0e0c38160c08046005690b00010b0a010b060107051111270a0a0f0c0b083817010d0d0a0c441c0a0a100b0a0c381804770580010b00010b0a010b060107051111270a000a0a0f0b0b0c381011220b07060100000000000000160c0705420b060f100b00110f0b010a0a1005140a0a1006140b0d0a0a100338050a0a1007140a0a1008140a0a1009140b0a100a14120c38130208010003050708439f02070a2a080c14070a2a070f160c11070a2a050c10381b0c170e02410d0c130a13060000000000000000240414051f0b00010b14010b11010b100107081111270e02060000000000000000420d0c0f0e03060000000000000000421d0c0e0a14100f0a0f140a0e141200381c20043a0a140f0f0a0f140a0e141200402b0000000000000000381d0a140f0f0a0f140a0e141200380f0a1114442b401c00000000000000000c160600000000000000000c120a120a132304b001054e0a0f0e020a12420d21045b0a0e0e030a12421d210c0b055d090c0b0b0b0460056f0b00010b14010b11010b10010b0f010b0e0107001111270e020a12420d140e030a12421d140e040a12421d141119110a20048001058f010b00010b14010b11010b10010b0f010b0e0107031111270e020a12420d140e030a12421d140e040a12421d140e050a1242101411180c150d160a15441c0d170a150a000b15060100000000000000111b38070b12060100000000000000160c1205490a100f0d0a00110f0a11140a0f140a0e140a160a060a070a010a080a09120338090a000a0638030c0d0a100f040a00110f0a11140a0f140a0e140a060b060a070a010a080a09120238060a140f010a11140a00110f0a070b0d0b170a0f140a0e140a010a080a090a0a0b1606000000000000000032000000000000000000000000000000000600000000000000001206381e0a140f000a00110f0c0c2e0b0c38002004ff010a140f000a00110f402b0000000000000000381f0b140f000a00110f380b0a1114442b0b100f170b00110f0a11140b0f140b0e140b070b010b080b090b0a120138200a11143201000000000000000000000000000000160b11150209000000011e0a0038213822382312082d080a00320000000000000000000000000000000012072d070a000a0038240a0038250a0038260a0038270a0038280a0038290a00382a0b00382b12052d05020a00000001060601000000000000000b0011342120020b010401084876070a2a080c090a010a0212000c030a09100f0a03381c040d05130b00010b0901063f05000000000000270a09100f0b03382c0c07404a00000000000000000c0a0a07412b0c060600000000000000000c040a040a0623046b05240a070a04422b140c050a0910010a053801042f05370b00010b09010b0701063f05000000000000270a0910010b05382d0c080d0a0a081002140a081007140a08100338050a081005140a081006140a081008140a081009140a08100a140a081018140a08100c140a081014140a081013140b081019141136444a0b04060100000000000000160c04051f0b09010b000b010b020b07140b0a1137382e020c010401084f40070a2a080c030a0310010a013801040905100b00010b030107041111270b0310010b01382d0c020b000a021002140a021007140a02100338050a021005140a021006140a021008140a021009140a02100a140a021018140a02100c140a021014140a021013140b021019141136382f020d0104005087010b010600000000000000002104380a020601000000000000002104150b030b040b050b06070b11250c090c080c070c180c170c16052b0b0206020000000000000021041a051f0b000107021111270b030b040b050b06070b11260c090c080c070c180c170c160b160b170b180b070b080b090c150c140c130c120c110c10056b0a020601000000000000002104490b030b040b050b06070b112e0c0f0c0e0c0d0c0c0c0b0c0a055f0b0206020000000000000021044e05530b000107021111270b030b040b050b06070b112f0c0f0c0e0c0d0c0c0c0b0c0a0b0a0b0b0b0c0b0d0b0e0b0f0c150c140c130c120c110c100b100b110b120b130b140b150c1a0c1d0c190c1b0c1c310021047a057e0b0001064705000000000000270b000b1c0b1b0b190b1d0b1a11393830020e01040108521b070a2a080c030a0310000a0138000409050f0b00010b0301063f05000000000000270b0310000a0138310c020b000b010b0214113a383202080108000600060205030604060506010606060706080603060a050205060802050405050501060c060b0507070005000609060d00"; + let res = run_binary_test("sample_pool", code); + assert!(res.is_ok(), "{:?}", res) +} + +#[cfg(feature = "address32")] +#[test] +fn sample_farming() { + let code = "a11ceb0b050000000e01001e021e2603447c04c00158059802c80107e003bb04089b08a00106bb09e101109c0b780a940c3e0bd20c040cd60cd10d0da71a080eaf1a060000010101020103010401050106000700080209020a0309030a0409040a000b0800000c0e0200010001000d0c0200010001011106000513070002230401000107240000000e000100000f0201020000032104050001220607000525090a000e26010c0200000c26010c0200000a26010c0200000427001200022812140100022915160100022a17010100082b150101000d2c1a010200000b2c1a01020000092c1a010200000d2d1b010200000b2d1b01020000092d1b01020000062e011400050b050d050e050f05100511060b060d060e060f06100611070b070d070e070f0710071109130a130b1309180a180b1809190a190b190c130c180d0b0e0b0f0b0d0d0e0d0f0d0d0e0d100e0e0e100f0e0f10100b110b120b01060c0009060c0303030303030303020c080302060c0501080301060803010c2001010101010101010101030303030308040b050108060b050109000b050109010708000b0102090009010b0102090009010b020209000901070b020209000901050c0a0b0102090009010503030303010a0201080402090009010101020901090002080609000209000806020806090102090108060105010900010302060c03010b0501090002050b0501090001090101080603060c030305060c03030303010b010209000901076661726d696e67076163636f756e7404636f696e107265736f757263655f6163636f756e74067369676e657206737472696e670974696d657374616d700d6661756365745f746f6b656e73076c656e64696e6706726f7574657204737761700a4d6f64756c65446174610c506f736974696f6e496e666f0f506f736974696f6e496e666f4465780b696e69745f6d6f64756c65166c657665726167655f7969656c645f6661726d696e670a7369676e65725f636170105369676e65724361706162696c697479086465785f6e616d6506537472696e670b7369676e65725f616464720a637265617465645f617406737461747573086c657665726167650e737570706c79416d6f756e745f780e737570706c79416d6f756e745f790e737570706c79416d6f756e745f7a0e626f72726f77416d6f756e745f780e626f72726f77416d6f756e745f790e626f72726f77416d6f756e745f7a10706f736974696f6e496e666f5f70616e10706f736974696f6e496e666f5f6c697110706f736974696f6e496e666f5f6175781d72657472696576655f7265736f757263655f6163636f756e745f6361701d6372656174655f7369676e65725f776974685f6361706162696c69747904436f696e03455a4d04757466380f69735f706169725f637265617465640a616464726573735f6f660762616c616e6365087769746864726177076465706f73697406626f72726f7710737761705f65786163745f696e7075740d6164645f6c69717569646974790b6e6f775f7365636f6e64734d63574ba8d90a5926e2866d8291e57683108a47b96d884232a871fe4feddf4100000000000000000000000000000000000000000000000000000000000000015e40a5bf7ab741784d3a99d96d8e2ddc6706ee06e5f509a3314a74c9e53746f5b30dd6a14dd7626ac8a37bc964914f07e3dc38d629637f1087f9f7186f1e0909c4911c40cf758ec21c0ebf0e547933ef6bb0f53ad581c08d2ecc7ad11364be1b030804000000000000000520f67b2452fd82768002ec6c28568713b9359a596585dc1a4bf85fce6b0e3754020308020000000000000003080300000000000000030801000000000000000308ffffffffffffffff0410e80300000000000000000000000000000308000000000000000005204d63574ba8d90a5926e2866d8291e57683108a47b96d884232a871fe4feddf41052000000000000000000000000000000000000000000000000000000000000000000a020c0b50616e63616b65537761700a020b0a4c6971756964537761700a020d0c4155582045786368616e6765126170746f733a3a6d657461646174615f763064030100000000000000164552524f525f4e4f545f435245415445445f50414952000200000000000000184552524f525f494e53554646494349454e545f4153534554000300000000000000174552524f525f494e56414c49445f504152414d5f4445580000020110080301020b1208041405150316011703180319031a031b031c031d030202031e0a0b0102090009011f0a0b010209000901200a0b010209000901020b010b00000000030c0b00070111020c020e0211030c010e010b0212002d000201010402000208ee04070a1104010a010600000000000000002103080536070a11040c183800030e0511080c09051338010c090b0903190b00010704273802031c051f080c0b052138030c0b0b0b03270b00010704273804032a052d080c0c052f38050c0c0b0c03350b0001070427059f010a0106010000000000000021033b0569070b11040c18380603410544080c0d054638070c0d0b0d034c0b00010704273808034f0552080c0e055438090c0e0b0e035a0b0001070427380a035d0560080c0f0562380b0c0f0b0f03680b0001070427059f010a0106020000000000000021036e059b01070c11040c18380c03740577080c100579380d0c100b10037f0b0001070427380e038201058501080c11058701380f0c110b11038d010b00010704273810039001059301080c1205950138110c120b12039f010b00010704270b000107032707082a000c1c0b1c100011030c220e2211080c210a030600000000000000002403ae0105c1010a00110838120c160b160a032403ba010b00010702270a000a0338130c1a07080b1a38140a040600000000000000002403c60105d9010a00110838150c170b170a042403d2010b00010702270a000a0438160c1b07080b1b38170a050600000000000000002403de0105f1010a00110838180c150b150a052403ea010b00010702270a000a0538190c1907080b19381a0a060600000000000000002403f60105f9010e220a06381b0a070600000000000000002403fe010581020e220a07381c0a0806000000000000000024038502070838120c26070838150c280a030a06160602000000000000001a0600000000000000002403940205bd020a010600000000000000002103990205a2020e220a030a06160602000000000000001a060000000000000000381d05bd020a010601000000000000002103a70205b0020e220a030a06160602000000000000001a060000000000000000381e05bd020a010602000000000000002103b50205bd020e220a030a06160602000000000000001a060000000000000000381f0a040a07160602000000000000001a0600000000000000002403c60205ef020a010600000000000000002103cb0205d4020e220a040a07160602000000000000001a060000000000000000382005ef020a010601000000000000002103d90205e2020e220a040a07160602000000000000001a060000000000000000382105ef020a010602000000000000002103e70205ef020e220a040a07160602000000000000001a06000000000000000038220a050a08160602000000000000001a0600000000000000002403f80205b9030a010600000000000000002103fd02058e030e220a050a08160602000000000000001a06000000000000000038230e220a050a08160602000000000000001a060000000000000000382405b9030a010601000000000000002103930305a4030e220a050a08160602000000000000001a06000000000000000038250e220a050a08160602000000000000001a060000000000000000382605b9030a010602000000000000002103a90305b9030e220a050a08160602000000000000001a06000000000000000038270e220a050a08160602000000000000001a0600000000000000003828070838120c25070838150c270a030b25160b26170c130a040b27160b28170c140a130600000000000000002403d00305d5030a14060000000000000000240c0a05d703090c0a0b0a03da0305eb040a010600000000000000002103df0305e6030e220b130b14060000000000000000060000000000000000382905fd030a010601000000000000002103eb0305f2030e220b130b14060000000000000000060000000000000000382a05fd030a010602000000000000002103f70305fd030e220b130b14060000000000000000060000000000000000382b0b0011080c240a213b002003850405ba040b180b241113080b020b030b040b050b060b070b0839010c1d401c000000000000000001401c0000000000000000401c0000000000000000401c000000000000000039000c1f0a0106000000000000000021039e0405a3040d1f36000b1d441c05b6040a010601000000000000002103a80405ad040d1f36010b1d441c05b6040b010602000000000000002103b20405b6040d1f36020b1d441c0e220b1f3f0005ea040b213c000c200b180b241113080b020b030b040b050b060b070b0839010c1e0a010600000000000000002103cf0405d4040b2036000b1e441c05ea040a010601000000000000002103d90405de040b2036010b1e441c05ea040b010602000000000000002103e30405e8040b2036020b1e441c05ea040b200105ed040b0001020000020002010202010b020b030b00"; + let res = run_binary_test("sample_farming", code); + assert!(res.is_ok(), "{:?}", res) +} + +#[cfg(feature = "address32")] +#[test] +fn sample_whitelist() { + let code = "a11ceb0b050000000c01000602060c03123a044c0805545707ab01660891024006d102988b0210e98d02d7010ac08f02090cc98f02a2470debd6020200000101010200030800020a04020301000100040001000005020100000603040000070201000008000100010b0203000204070102030002060a04020300020c010c02030402080d0e020300060607060806090602060c050001060c01050101020507080002050203070b010209000901090009010305070b010205020708000106080002060b0102090009010900010b01020502010b01020900090102070b01020900090109000109010977686974656c697374067369676e6572057461626c650957686974656c69737403616464086164645f6d616e7908636f6e7461696e730a696e697469616c697a650672656d6f766507656e7472696573055461626c650a616464726573735f6f66036e65774419523fdfa01e96fc7c18b67d900be8c863459e25383a5c661b9523631811c1000000000000000000000000000000000000000000000000000000000000000103082003000000000000030822030000000000000308210300000000000005204419523fdfa01e96fc7c18b67d900be8c863459e25383a5c661b9523631811c1052000000000000000000000000000000000000000000000000000000000000000000520000000000000000000000000000000000000000000000000000000000000000105200000000000000000000000000000000000000000000000000000000000000002052000000000000000000000000000000000000000000000000000000000000000030520000000000000000000000000000000000000000000000000000000000000000405200000000000000000000000000000000000000000000000000000000000000005052000000000000000000000000000000000000000000000000000000000000000060520000000000000000000000000000000000000000000000000000000000000000705200000000000000000000000000000000000000000000000000000000000000008052000000000000000000000000000000000000000000000000000000000000000090520000000000000000000000000000000000000000000000000000000000000001005200000000000000000000000000000000000000000000000000000000000000011052000000000000000000000000000000000000000000000000000000000000000120520000000000000000000000000000000000000000000000000000000000000001305200000000000000000000000000000000000000000000000000000000000000014052000000000000000000000000000000000000000000000000000000000000000150520000000000000000000000000000000000000000000000000000000000000001605200000000000000000000000000000000000000000000000000000000000000017052000000000000000000000000000000000000000000000000000000000000000180520000000000000000000000000000000000000000000000000000000000000001905200000000000000000000000000000000000000000000000000000000000000020052000000000000000000000000000000000000000000000000000000000000000210520000000000000000000000000000000000000000000000000000000000000002205200000000000000000000000000000000000000000000000000000000000000023052000000000000000000000000000000000000000000000000000000000000000240520000000000000000000000000000000000000000000000000000000000000002505200000000000000000000000000000000000000000000000000000000000000026052000000000000000000000000000000000000000000000000000000000000000270520000000000000000000000000000000000000000000000000000000000000002805200000000000000000000000000000000000000000000000000000000000000029052000000000000000000000000000000000000000000000000000000000000000300520000000000000000000000000000000000000000000000000000000000000003105200000000000000000000000000000000000000000000000000000000000000032052000000000000000000000000000000000000000000000000000000000000000330520000000000000000000000000000000000000000000000000000000000000003405200000000000000000000000000000000000000000000000000000000000000035052000000000000000000000000000000000000000000000000000000000000000360520000000000000000000000000000000000000000000000000000000000000003705200000000000000000000000000000000000000000000000000000000000000038052000000000000000000000000000000000000000000000000000000000000000390520000000000000000000000000000000000000000000000000000000000000004005200000000000000000000000000000000000000000000000000000000000000041052000000000000000000000000000000000000000000000000000000000000000420520000000000000000000000000000000000000000000000000000000000000004305200000000000000000000000000000000000000000000000000000000000000044052000000000000000000000000000000000000000000000000000000000000000450520000000000000000000000000000000000000000000000000000000000000004605200000000000000000000000000000000000000000000000000000000000000047052000000000000000000000000000000000000000000000000000000000000000480520000000000000000000000000000000000000000000000000000000000000004905200000000000000000000000000000000000000000000000000000000000000050052000000000000000000000000000000000000000000000000000000000000000510520000000000000000000000000000000000000000000000000000000000000005205200000000000000000000000000000000000000000000000000000000000000053052000000000000000000000000000000000000000000000000000000000000000540520000000000000000000000000000000000000000000000000000000000000005505200000000000000000000000000000000000000000000000000000000000000056052000000000000000000000000000000000000000000000000000000000000000570520000000000000000000000000000000000000000000000000000000000000005805200000000000000000000000000000000000000000000000000000000000000059052000000000000000000000000000000000000000000000000000000000000000600520000000000000000000000000000000000000000000000000000000000000006105200000000000000000000000000000000000000000000000000000000000000062052000000000000000000000000000000000000000000000000000000000000000630520000000000000000000000000000000000000000000000000000000000000006405200000000000000000000000000000000000000000000000000000000000000065052000000000000000000000000000000000000000000000000000000000000000660520000000000000000000000000000000000000000000000000000000000000006705200000000000000000000000000000000000000000000000000000000000000068052000000000000000000000000000000000000000000000000000000000000000690520000000000000000000000000000000000000000000000000000000000000007005200000000000000000000000000000000000000000000000000000000000000071052000000000000000000000000000000000000000000000000000000000000000720520000000000000000000000000000000000000000000000000000000000000007305200000000000000000000000000000000000000000000000000000000000000074052000000000000000000000000000000000000000000000000000000000000000750520000000000000000000000000000000000000000000000000000000000000007605200000000000000000000000000000000000000000000000000000000000000077052000000000000000000000000000000000000000000000000000000000000000780520000000000000000000000000000000000000000000000000000000000000007905200000000000000000000000000000000000000000000000000000000000000080052000000000000000000000000000000000000000000000000000000000000000810520000000000000000000000000000000000000000000000000000000000000008205200000000000000000000000000000000000000000000000000000000000000083052000000000000000000000000000000000000000000000000000000000000000840520000000000000000000000000000000000000000000000000000000000000008505200000000000000000000000000000000000000000000000000000000000000086052000000000000000000000000000000000000000000000000000000000000000870520000000000000000000000000000000000000000000000000000000000000008805200000000000000000000000000000000000000000000000000000000000000089052000000000000000000000000000000000000000000000000000000000000000900520000000000000000000000000000000000000000000000000000000000000009105200000000000000000000000000000000000000000000000000000000000000092052000000000000000000000000000000000000000000000000000000000000000930520000000000000000000000000000000000000000000000000000000000000009405200000000000000000000000000000000000000000000000000000000000000095052000000000000000000000000000000000000000000000000000000000000000960520000000000000000000000000000000000000000000000000000000000000009705200000000000000000000000000000000000000000000000000000000000000098052000000000000000000000000000000000000000000000000000000000000000990520000000000000000000000000000000000000000000000000000000000000010005200000000000000000000000000000000000000000000000000000000000000101052000000000000000000000000000000000000000000000000000000000000001020520000000000000000000000000000000000000000000000000000000000000010305200000000000000000000000000000000000000000000000000000000000000104052000000000000000000000000000000000000000000000000000000000000001050520000000000000000000000000000000000000000000000000000000000000010605200000000000000000000000000000000000000000000000000000000000000107052000000000000000000000000000000000000000000000000000000000000001080520000000000000000000000000000000000000000000000000000000000000010905200000000000000000000000000000000000000000000000000000000000000110052000000000000000000000000000000000000000000000000000000000000001110520000000000000000000000000000000000000000000000000000000000000011205200000000000000000000000000000000000000000000000000000000000000113052000000000000000000000000000000000000000000000000000000000000001140520000000000000000000000000000000000000000000000000000000000000011505200000000000000000000000000000000000000000000000000000000000000116052000000000000000000000000000000000000000000000000000000000000001170520000000000000000000000000000000000000000000000000000000000000011805200000000000000000000000000000000000000000000000000000000000000119052000000000000000000000000000000000000000000000000000000000000001200520000000000000000000000000000000000000000000000000000000000000012105200000000000000000000000000000000000000000000000000000000000000122052000000000000000000000000000000000000000000000000000000000000001230520000000000000000000000000000000000000000000000000000000000000012405200000000000000000000000000000000000000000000000000000000000000125052000000000000000000000000000000000000000000000000000000000000001260520000000000000000000000000000000000000000000000000000000000000012705200000000000000000000000000000000000000000000000000000000000000128052000000000000000000000000000000000000000000000000000000000000001290520000000000000000000000000000000000000000000000000000000000000013005200000000000000000000000000000000000000000000000000000000000000131052000000000000000000000000000000000000000000000000000000000000001320520000000000000000000000000000000000000000000000000000000000000013305200000000000000000000000000000000000000000000000000000000000000134052000000000000000000000000000000000000000000000000000000000000001350520000000000000000000000000000000000000000000000000000000000000013605200000000000000000000000000000000000000000000000000000000000000137052000000000000000000000000000000000000000000000000000000000000001380520000000000000000000000000000000000000000000000000000000000000013905200000000000000000000000000000000000000000000000000000000000000140052000000000000000000000000000000000000000000000000000000000000001410520000000000000000000000000000000000000000000000000000000000000014205200000000000000000000000000000000000000000000000000000000000000143052000000000000000000000000000000000000000000000000000000000000001440520000000000000000000000000000000000000000000000000000000000000014505200000000000000000000000000000000000000000000000000000000000000146052000000000000000000000000000000000000000000000000000000000000001470520000000000000000000000000000000000000000000000000000000000000014805200000000000000000000000000000000000000000000000000000000000000149052000000000000000000000000000000000000000000000000000000000000001500520000000000000000000000000000000000000000000000000000000000000015105200000000000000000000000000000000000000000000000000000000000000152052000000000000000000000000000000000000000000000000000000000000001530520000000000000000000000000000000000000000000000000000000000000015405200000000000000000000000000000000000000000000000000000000000000155052000000000000000000000000000000000000000000000000000000000000001560520000000000000000000000000000000000000000000000000000000000000015705200000000000000000000000000000000000000000000000000000000000000158052000000000000000000000000000000000000000000000000000000000000001590520000000000000000000000000000000000000000000000000000000000000016005200000000000000000000000000000000000000000000000000000000000000161052000000000000000000000000000000000000000000000000000000000000001620520000000000000000000000000000000000000000000000000000000000000016305200000000000000000000000000000000000000000000000000000000000000164052000000000000000000000000000000000000000000000000000000000000001650520000000000000000000000000000000000000000000000000000000000000016605200000000000000000000000000000000000000000000000000000000000000167052000000000000000000000000000000000000000000000000000000000000001680520000000000000000000000000000000000000000000000000000000000000016905200000000000000000000000000000000000000000000000000000000000000170052000000000000000000000000000000000000000000000000000000000000001710520000000000000000000000000000000000000000000000000000000000000017205200000000000000000000000000000000000000000000000000000000000000173052000000000000000000000000000000000000000000000000000000000000001740520000000000000000000000000000000000000000000000000000000000000017505200000000000000000000000000000000000000000000000000000000000000176052000000000000000000000000000000000000000000000000000000000000001770520000000000000000000000000000000000000000000000000000000000000017805200000000000000000000000000000000000000000000000000000000000000179052000000000000000000000000000000000000000000000000000000000000001800520000000000000000000000000000000000000000000000000000000000000018105200000000000000000000000000000000000000000000000000000000000000182052000000000000000000000000000000000000000000000000000000000000001830520000000000000000000000000000000000000000000000000000000000000018405200000000000000000000000000000000000000000000000000000000000000185052000000000000000000000000000000000000000000000000000000000000001860520000000000000000000000000000000000000000000000000000000000000018705200000000000000000000000000000000000000000000000000000000000000188052000000000000000000000000000000000000000000000000000000000000001890520000000000000000000000000000000000000000000000000000000000000019005200000000000000000000000000000000000000000000000000000000000000191052000000000000000000000000000000000000000000000000000000000000001920520000000000000000000000000000000000000000000000000000000000000019305200000000000000000000000000000000000000000000000000000000000000194052000000000000000000000000000000000000000000000000000000000000001950520000000000000000000000000000000000000000000000000000000000000019605200000000000000000000000000000000000000000000000000000000000000197052000000000000000000000000000000000000000000000000000000000000001980520000000000000000000000000000000000000000000000000000000000000019905200000000000000000000000000000000000000000000000000000000000000200052000000000000000000000000000000000000000000000000000000000000002010520000000000000000000000000000000000000000000000000000000000000020205200000000000000000000000000000000000000000000000000000000000000203052000000000000000000000000000000000000000000000000000000000000002040520000000000000000000000000000000000000000000000000000000000000020505200000000000000000000000000000000000000000000000000000000000000206052000000000000000000000000000000000000000000000000000000000000002070520000000000000000000000000000000000000000000000000000000000000020805200000000000000000000000000000000000000000000000000000000000000209052000000000000000000000000000000000000000000000000000000000000002100520000000000000000000000000000000000000000000000000000000000000021105200000000000000000000000000000000000000000000000000000000000000212052000000000000000000000000000000000000000000000000000000000000002130520000000000000000000000000000000000000000000000000000000000000021405200000000000000000000000000000000000000000000000000000000000000215052000000000000000000000000000000000000000000000000000000000000002160520000000000000000000000000000000000000000000000000000000000000021705200000000000000000000000000000000000000000000000000000000000000218052000000000000000000000000000000000000000000000000000000000000002190520000000000000000000000000000000000000000000000000000000000000022005200000000000000000000000000000000000000000000000000000000000000221052000000000000000000000000000000000000000000000000000000000000002220520000000000000000000000000000000000000000000000000000000000000022305200000000000000000000000000000000000000000000000000000000000000224052000000000000000000000000000000000000000000000000000000000000002250520000000000000000000000000000000000000000000000000000000000000022605200000000000000000000000000000000000000000000000000000000000000227052000000000000000000000000000000000000000000000000000000000000002280520000000000000000000000000000000000000000000000000000000000000022905200000000000000000000000000000000000000000000000000000000000000230052000000000000000000000000000000000000000000000000000000000000002310520000000000000000000000000000000000000000000000000000000000000023205200000000000000000000000000000000000000000000000000000000000000233052000000000000000000000000000000000000000000000000000000000000002340520000000000000000000000000000000000000000000000000000000000000023505200000000000000000000000000000000000000000000000000000000000000236052000000000000000000000000000000000000000000000000000000000000002370520000000000000000000000000000000000000000000000000000000000000023805200000000000000000000000000000000000000000000000000000000000000239052000000000000000000000000000000000000000000000000000000000000002400520000000000000000000000000000000000000000000000000000000000000024105200000000000000000000000000000000000000000000000000000000000000242052000000000000000000000000000000000000000000000000000000000000002430520000000000000000000000000000000000000000000000000000000000000024405200000000000000000000000000000000000000000000000000000000000000245052000000000000000000000000000000000000000000000000000000000000002460520000000000000000000000000000000000000000000000000000000000000024705200000000000000000000000000000000000000000000000000000000000000248052000000000000000000000000000000000000000000000000000000000000002490520000000000000000000000000000000000000000000000000000000000000025005200000000000000000000000000000000000000000000000000000000000000251052000000000000000000000000000000000000000000000000000000000000002520520000000000000000000000000000000000000000000000000000000000000025305200000000000000000000000000000000000000000000000000000000000000254052000000000000000000000000000000000000000000000000000000000000002550520000000000000000000000000000000000000000000000000000000000000025605200000000000000000000000000000000000000000000000000000000000000257052000000000000000000000000000000000000000000000000000000000000002580520000000000000000000000000000000000000000000000000000000000000025905200000000000000000000000000000000000000000000000000000000000000260052000000000000000000000000000000000000000000000000000000000000002610520000000000000000000000000000000000000000000000000000000000000026205200000000000000000000000000000000000000000000000000000000000000263052000000000000000000000000000000000000000000000000000000000000002640520000000000000000000000000000000000000000000000000000000000000026505200000000000000000000000000000000000000000000000000000000000000266052000000000000000000000000000000000000000000000000000000000000002670520000000000000000000000000000000000000000000000000000000000000026805200000000000000000000000000000000000000000000000000000000000000269052000000000000000000000000000000000000000000000000000000000000002700520000000000000000000000000000000000000000000000000000000000000027105200000000000000000000000000000000000000000000000000000000000000272052000000000000000000000000000000000000000000000000000000000000002730520000000000000000000000000000000000000000000000000000000000000027405200000000000000000000000000000000000000000000000000000000000000275052000000000000000000000000000000000000000000000000000000000000002760520000000000000000000000000000000000000000000000000000000000000027705200000000000000000000000000000000000000000000000000000000000000278052000000000000000000000000000000000000000000000000000000000000002790520000000000000000000000000000000000000000000000000000000000000028005200000000000000000000000000000000000000000000000000000000000000281052000000000000000000000000000000000000000000000000000000000000002820520000000000000000000000000000000000000000000000000000000000000028305200000000000000000000000000000000000000000000000000000000000000284052000000000000000000000000000000000000000000000000000000000000002850520000000000000000000000000000000000000000000000000000000000000028605200000000000000000000000000000000000000000000000000000000000000287052000000000000000000000000000000000000000000000000000000000000002880520000000000000000000000000000000000000000000000000000000000000028905200000000000000000000000000000000000000000000000000000000000000290052000000000000000000000000000000000000000000000000000000000000002910520000000000000000000000000000000000000000000000000000000000000029205200000000000000000000000000000000000000000000000000000000000000293052000000000000000000000000000000000000000000000000000000000000002940520000000000000000000000000000000000000000000000000000000000000029505200000000000000000000000000000000000000000000000000000000000000296052000000000000000000000000000000000000000000000000000000000000002970520000000000000000000000000000000000000000000000000000000000000029805200000000000000000000000000000000000000000000000000000000000000299052000000000000000000000000000000000000000000000000000000000000003000520000000000000000000000000000000000000000000000000000000000000030105200000000000000000000000000000000000000000000000000000000000000302052000000000000000000000000000000000000000000000000000000000000003030520000000000000000000000000000000000000000000000000000000000000030405200000000000000000000000000000000000000000000000000000000000000305052000000000000000000000000000000000000000000000000000000000000003060520000000000000000000000000000000000000000000000000000000000000030705200000000000000000000000000000000000000000000000000000000000000308052000000000000000000000000000000000000000000000000000000000000003090520000000000000000000000000000000000000000000000000000000000000031005200000000000000000000000000000000000000000000000000000000000000311052000000000000000000000000000000000000000000000000000000000000003120520000000000000000000000000000000000000000000000000000000000000031305200000000000000000000000000000000000000000000000000000000000000314052000000000000000000000000000000000000000000000000000000000000003150520000000000000000000000000000000000000000000000000000000000000031605200000000000000000000000000000000000000000000000000000000000000317052000000000000000000000000000000000000000000000000000000000000003180520000000000000000000000000000000000000000000000000000000000000031905200000000000000000000000000000000000000000000000000000000000000320052000000000000000000000000000000000000000000000000000000000000003210520000000000000000000000000000000000000000000000000000000000000032205200000000000000000000000000000000000000000000000000000000000000323052000000000000000000000000000000000000000000000000000000000000003240520000000000000000000000000000000000000000000000000000000000000032505200000000000000000000000000000000000000000000000000000000000000326052000000000000000000000000000000000000000000000000000000000000003270520000000000000000000000000000000000000000000000000000000000000032805200000000000000000000000000000000000000000000000000000000000000329052000000000000000000000000000000000000000000000000000000000000003300520000000000000000000000000000000000000000000000000000000000000033105200000000000000000000000000000000000000000000000000000000000000332052000000000000000000000000000000000000000000000000000000000000003330520000000000000000000000000000000000000000000000000000000000000033405200000000000000000000000000000000000000000000000000000000000000335052000000000000000000000000000000000000000000000000000000000000003360520000000000000000000000000000000000000000000000000000000000000033705200000000000000000000000000000000000000000000000000000000000000338052000000000000000000000000000000000000000000000000000000000000003390520000000000000000000000000000000000000000000000000000000000000034005200000000000000000000000000000000000000000000000000000000000000341052000000000000000000000000000000000000000000000000000000000000003420520000000000000000000000000000000000000000000000000000000000000034305200000000000000000000000000000000000000000000000000000000000000344052000000000000000000000000000000000000000000000000000000000000003450520000000000000000000000000000000000000000000000000000000000000034605200000000000000000000000000000000000000000000000000000000000000347052000000000000000000000000000000000000000000000000000000000000003480520000000000000000000000000000000000000000000000000000000000000034905200000000000000000000000000000000000000000000000000000000000000350052000000000000000000000000000000000000000000000000000000000000003510520000000000000000000000000000000000000000000000000000000000000035205200000000000000000000000000000000000000000000000000000000000000353052000000000000000000000000000000000000000000000000000000000000003540520000000000000000000000000000000000000000000000000000000000000035505200000000000000000000000000000000000000000000000000000000000000356052000000000000000000000000000000000000000000000000000000000000003570520000000000000000000000000000000000000000000000000000000000000035805200000000000000000000000000000000000000000000000000000000000000359052000000000000000000000000000000000000000000000000000000000000003600520000000000000000000000000000000000000000000000000000000000000036105200000000000000000000000000000000000000000000000000000000000000362052000000000000000000000000000000000000000000000000000000000000003630520000000000000000000000000000000000000000000000000000000000000036405200000000000000000000000000000000000000000000000000000000000000365052000000000000000000000000000000000000000000000000000000000000003660520000000000000000000000000000000000000000000000000000000000000036705200000000000000000000000000000000000000000000000000000000000000368052000000000000000000000000000000000000000000000000000000000000003690520000000000000000000000000000000000000000000000000000000000000037005200000000000000000000000000000000000000000000000000000000000000371052000000000000000000000000000000000000000000000000000000000000003720520000000000000000000000000000000000000000000000000000000000000037305200000000000000000000000000000000000000000000000000000000000000374052000000000000000000000000000000000000000000000000000000000000003750520000000000000000000000000000000000000000000000000000000000000037605200000000000000000000000000000000000000000000000000000000000000377052000000000000000000000000000000000000000000000000000000000000003780520000000000000000000000000000000000000000000000000000000000000037905200000000000000000000000000000000000000000000000000000000000000380052000000000000000000000000000000000000000000000000000000000000003810520000000000000000000000000000000000000000000000000000000000000038205200000000000000000000000000000000000000000000000000000000000000383052000000000000000000000000000000000000000000000000000000000000003840520000000000000000000000000000000000000000000000000000000000000038505200000000000000000000000000000000000000000000000000000000000000386052000000000000000000000000000000000000000000000000000000000000003870520000000000000000000000000000000000000000000000000000000000000038805200000000000000000000000000000000000000000000000000000000000000389052000000000000000000000000000000000000000000000000000000000000003900520000000000000000000000000000000000000000000000000000000000000039105200000000000000000000000000000000000000000000000000000000000000392052000000000000000000000000000000000000000000000000000000000000003930520000000000000000000000000000000000000000000000000000000000000039405200000000000000000000000000000000000000000000000000000000000000395052000000000000000000000000000000000000000000000000000000000000003960520000000000000000000000000000000000000000000000000000000000000039705200000000000000000000000000000000000000000000000000000000000000398052000000000000000000000000000000000000000000000000000000000000003990520000000000000000000000000000000000000000000000000000000000000040005200000000000000000000000000000000000000000000000000000000000000401052000000000000000000000000000000000000000000000000000000000000004020520000000000000000000000000000000000000000000000000000000000000040305200000000000000000000000000000000000000000000000000000000000000404052000000000000000000000000000000000000000000000000000000000000004050520000000000000000000000000000000000000000000000000000000000000040605200000000000000000000000000000000000000000000000000000000000000407052000000000000000000000000000000000000000000000000000000000000004080520000000000000000000000000000000000000000000000000000000000000040905200000000000000000000000000000000000000000000000000000000000000410052000000000000000000000000000000000000000000000000000000000000004110520000000000000000000000000000000000000000000000000000000000000041205200000000000000000000000000000000000000000000000000000000000000413052000000000000000000000000000000000000000000000000000000000000004140520000000000000000000000000000000000000000000000000000000000000041505200000000000000000000000000000000000000000000000000000000000000416052000000000000000000000000000000000000000000000000000000000000004170520000000000000000000000000000000000000000000000000000000000000041805200000000000000000000000000000000000000000000000000000000000000419052000000000000000000000000000000000000000000000000000000000000004200520000000000000000000000000000000000000000000000000000000000000042105200000000000000000000000000000000000000000000000000000000000000422052000000000000000000000000000000000000000000000000000000000000004230520000000000000000000000000000000000000000000000000000000000000042405200000000000000000000000000000000000000000000000000000000000000425052000000000000000000000000000000000000000000000000000000000000004260520000000000000000000000000000000000000000000000000000000000000042705200000000000000000000000000000000000000000000000000000000000000428052000000000000000000000000000000000000000000000000000000000000004290520000000000000000000000000000000000000000000000000000000000000043005200000000000000000000000000000000000000000000000000000000000000431052000000000000000000000000000000000000000000000000000000000000004320520000000000000000000000000000000000000000000000000000000000000043305200000000000000000000000000000000000000000000000000000000000000434052000000000000000000000000000000000000000000000000000000000000004350520000000000000000000000000000000000000000000000000000000000000043605200000000000000000000000000000000000000000000000000000000000000437052000000000000000000000000000000000000000000000000000000000000004380520000000000000000000000000000000000000000000000000000000000000043905200000000000000000000000000000000000000000000000000000000000000440052000000000000000000000000000000000000000000000000000000000000004410520000000000000000000000000000000000000000000000000000000000000044205200000000000000000000000000000000000000000000000000000000000000443052000000000000000000000000000000000000000000000000000000000000004440520000000000000000000000000000000000000000000000000000000000000044505200000000000000000000000000000000000000000000000000000000000000446052000000000000000000000000000000000000000000000000000000000000004470520000000000000000000000000000000000000000000000000000000000000044805200000000000000000000000000000000000000000000000000000000000000449052000000000000000000000000000000000000000000000000000000000000004500520000000000000000000000000000000000000000000000000000000000000045105200000000000000000000000000000000000000000000000000000000000000452052000000000000000000000000000000000000000000000000000000000000004530520000000000000000000000000000000000000000000000000000000000000045405200000000000000000000000000000000000000000000000000000000000000455052000000000000000000000000000000000000000000000000000000000000004560520000000000000000000000000000000000000000000000000000000000000045705200000000000000000000000000000000000000000000000000000000000000458052000000000000000000000000000000000000000000000000000000000000004590520000000000000000000000000000000000000000000000000000000000000046005200000000000000000000000000000000000000000000000000000000000000461052000000000000000000000000000000000000000000000000000000000000004620520000000000000000000000000000000000000000000000000000000000000046305200000000000000000000000000000000000000000000000000000000000000464052000000000000000000000000000000000000000000000000000000000000004650520000000000000000000000000000000000000000000000000000000000000046605200000000000000000000000000000000000000000000000000000000000000467052000000000000000000000000000000000000000000000000000000000000004680520000000000000000000000000000000000000000000000000000000000000046905200000000000000000000000000000000000000000000000000000000000000470052000000000000000000000000000000000000000000000000000000000000004710520000000000000000000000000000000000000000000000000000000000000047205200000000000000000000000000000000000000000000000000000000000000473052000000000000000000000000000000000000000000000000000000000000004740520000000000000000000000000000000000000000000000000000000000000047505200000000000000000000000000000000000000000000000000000000000000476052000000000000000000000000000000000000000000000000000000000000004770520000000000000000000000000000000000000000000000000000000000000047805200000000000000000000000000000000000000000000000000000000000000479052000000000000000000000000000000000000000000000000000000000000004800520000000000000000000000000000000000000000000000000000000000000048105200000000000000000000000000000000000000000000000000000000000000482052000000000000000000000000000000000000000000000000000000000000004830520000000000000000000000000000000000000000000000000000000000000048405200000000000000000000000000000000000000000000000000000000000000485052000000000000000000000000000000000000000000000000000000000000004860520000000000000000000000000000000000000000000000000000000000000048705200000000000000000000000000000000000000000000000000000000000000488052000000000000000000000000000000000000000000000000000000000000004890520000000000000000000000000000000000000000000000000000000000000049005200000000000000000000000000000000000000000000000000000000000000491052000000000000000000000000000000000000000000000000000000000000004920520000000000000000000000000000000000000000000000000000000000000049305200000000000000000000000000000000000000000000000000000000000000494052000000000000000000000000000000000000000000000000000000000000004950520000000000000000000000000000000000000000000000000000000000000049605200000000000000000000000000000000000000000000000000000000000000497052000000000000000000000000000000000000000000000000000000000000004980520000000000000000000000000000000000000000000000000000000000000049905200000000000000000000000000000000000000000000000000000000000000500052000000000000000000000000000000000000000000000000000000000000005010520000000000000000000000000000000000000000000000000000000000000050205200000000000000000000000000000000000000000000000000000000000000503052000000000000000000000000000000000000000000000000000000000000005040520000000000000000000000000000000000000000000000000000000000000050505200000000000000000000000000000000000000000000000000000000000000506052000000000000000000000000000000000000000000000000000000000000005070520000000000000000000000000000000000000000000000000000000000000050805200000000000000000000000000000000000000000000000000000000000000509052000000000000000000000000000000000000000000000000000000000000005100520000000000000000000000000000000000000000000000000000000000000051105200000000000000000000000000000000000000000000000000000000000000512052000000000000000000000000000000000000000000000000000000000000005130520000000000000000000000000000000000000000000000000000000000000051405200000000000000000000000000000000000000000000000000000000000000515052000000000000000000000000000000000000000000000000000000000000005160520000000000000000000000000000000000000000000000000000000000000051705200000000000000000000000000000000000000000000000000000000000000518052000000000000000000000000000000000000000000000000000000000000005190520000000000000000000000000000000000000000000000000000000000000052005200000000000000000000000000000000000000000000000000000000000000521052000000000000000000000000000000000000000000000000000000000000005220520000000000000000000000000000000000000000000000000000000000000052305200000000000000000000000000000000000000000000000000000000000000524052000000000000000000000000000000000000000000000000000000000000005250520000000000000000000000000000000000000000000000000000000000000052605200000000000000000000000000000000000000000000000000000000000000527052000000000000000000000000000000000000000000000000000000000000005280520000000000000000000000000000000000000000000000000000000000000052905200000000000000000000000000000000000000000000000000000000000000530052000000000000000000000000000000000000000000000000000000000000005310520000000000000000000000000000000000000000000000000000000000000053205200000000000000000000000000000000000000000000000000000000000000533052000000000000000000000000000000000000000000000000000000000000005340520000000000000000000000000000000000000000000000000000000000000053505200000000000000000000000000000000000000000000000000000000000000536052000000000000000000000000000000000000000000000000000000000000005370520000000000000000000000000000000000000000000000000000000000000053805200000000000000000000000000000000000000000000000000000000000000539052000000000000000000000000000000000000000000000000000000000000005400520000000000000000000000000000000000000000000000000000000000000054105200000000000000000000000000000000000000000000000000000000000000542052000000000000000000000000000000000000000000000000000000000000005430520000000000000000000000000000000000000000000000000000000000000054405200000000000000000000000000000000000000000000000000000000000000545052000000000000000000000000000000000000000000000000000000000000005460520000000000000000000000000000000000000000000000000000000000000054705200000000000000000000000000000000000000000000000000000000000000548052000000000000000000000000000000000000000000000000000000000000005490520000000000000000000000000000000000000000000000000000000000000055005200000000000000000000000000000000000000000000000000000000000000551052000000000000000000000000000000000000000000000000000000000000005520520000000000000000000000000000000000000000000000000000000000000055305200000000000000000000000000000000000000000000000000000000000000554052000000000000000000000000000000000000000000000000000000000000005550520000000000000000000000000000000000000000000000000000000000000055605200000000000000000000000000000000000000000000000000000000000000557052000000000000000000000000000000000000000000000000000000000000005580520000000000000000000000000000000000000000000000000000000000000055905200000000000000000000000000000000000000000000000000000000000000560052000000000000000000000000000000000000000000000000000000000000005610520000000000000000000000000000000000000000000000000000000000000056205200000000000000000000000000000000000000000000000000000000000000563052000000000000000000000000000000000000000000000000000000000000005640520000000000000000000000000000000000000000000000000000000000000056505200000000000000000000000000000000000000000000000000000000000000566052000000000000000000000000000000000000000000000000000000000000005670520000000000000000000000000000000000000000000000000000000000000056805200000000000000000000000000000000000000000000000000000000000000569052000000000000000000000000000000000000000000000000000000000000005700520000000000000000000000000000000000000000000000000000000000000057105200000000000000000000000000000000000000000000000000000000000000572052000000000000000000000000000000000000000000000000000000000000005730520000000000000000000000000000000000000000000000000000000000000057405200000000000000000000000000000000000000000000000000000000000000575052000000000000000000000000000000000000000000000000000000000000005760520000000000000000000000000000000000000000000000000000000000000057705200000000000000000000000000000000000000000000000000000000000000578052000000000000000000000000000000000000000000000000000000000000005790520000000000000000000000000000000000000000000000000000000000000058005200000000000000000000000000000000000000000000000000000000000000581052000000000000000000000000000000000000000000000000000000000000005820520000000000000000000000000000000000000000000000000000000000000058305200000000000000000000000000000000000000000000000000000000000000584052000000000000000000000000000000000000000000000000000000000000005850520000000000000000000000000000000000000000000000000000000000000058605200000000000000000000000000000000000000000000000000000000000000587052000000000000000000000000000000000000000000000000000000000000005880520000000000000000000000000000000000000000000000000000000000000058905200000000000000000000000000000000000000000000000000000000000000590052000000000000000000000000000000000000000000000000000000000000005910520000000000000000000000000000000000000000000000000000000000000059205200000000000000000000000000000000000000000000000000000000000000593052000000000000000000000000000000000000000000000000000000000000005940520000000000000000000000000000000000000000000000000000000000000059505200000000000000000000000000000000000000000000000000000000000000596052000000000000000000000000000000000000000000000000000000000000005970520000000000000000000000000000000000000000000000000000000000000059805200000000000000000000000000000000000000000000000000000000000000599052000000000000000000000000000000000000000000000000000000000000006000520000000000000000000000000000000000000000000000000000000000000060105200000000000000000000000000000000000000000000000000000000000000602052000000000000000000000000000000000000000000000000000000000000006030520000000000000000000000000000000000000000000000000000000000000060405200000000000000000000000000000000000000000000000000000000000000605052000000000000000000000000000000000000000000000000000000000000006060520000000000000000000000000000000000000000000000000000000000000060705200000000000000000000000000000000000000000000000000000000000000608052000000000000000000000000000000000000000000000000000000000000006090520000000000000000000000000000000000000000000000000000000000000061005200000000000000000000000000000000000000000000000000000000000000611052000000000000000000000000000000000000000000000000000000000000006120520000000000000000000000000000000000000000000000000000000000000061305200000000000000000000000000000000000000000000000000000000000000614052000000000000000000000000000000000000000000000000000000000000006150520000000000000000000000000000000000000000000000000000000000000061605200000000000000000000000000000000000000000000000000000000000000617052000000000000000000000000000000000000000000000000000000000000006180520000000000000000000000000000000000000000000000000000000000000061905200000000000000000000000000000000000000000000000000000000000000620052000000000000000000000000000000000000000000000000000000000000006210520000000000000000000000000000000000000000000000000000000000000062205200000000000000000000000000000000000000000000000000000000000000623052000000000000000000000000000000000000000000000000000000000000006240520000000000000000000000000000000000000000000000000000000000000062505200000000000000000000000000000000000000000000000000000000000000626052000000000000000000000000000000000000000000000000000000000000006270520000000000000000000000000000000000000000000000000000000000000062805200000000000000000000000000000000000000000000000000000000000000629052000000000000000000000000000000000000000000000000000000000000006300520000000000000000000000000000000000000000000000000000000000000063105200000000000000000000000000000000000000000000000000000000000000632052000000000000000000000000000000000000000000000000000000000000006330520000000000000000000000000000000000000000000000000000000000000063405200000000000000000000000000000000000000000000000000000000000000635052000000000000000000000000000000000000000000000000000000000000006360520000000000000000000000000000000000000000000000000000000000000063705200000000000000000000000000000000000000000000000000000000000000638052000000000000000000000000000000000000000000000000000000000000006390520000000000000000000000000000000000000000000000000000000000000064005200000000000000000000000000000000000000000000000000000000000000641052000000000000000000000000000000000000000000000000000000000000006420520000000000000000000000000000000000000000000000000000000000000064305200000000000000000000000000000000000000000000000000000000000000644052000000000000000000000000000000000000000000000000000000000000006450520000000000000000000000000000000000000000000000000000000000000064605200000000000000000000000000000000000000000000000000000000000000647052000000000000000000000000000000000000000000000000000000000000006480520000000000000000000000000000000000000000000000000000000000000064905200000000000000000000000000000000000000000000000000000000000000650052000000000000000000000000000000000000000000000000000000000000006510520000000000000000000000000000000000000000000000000000000000000065205200000000000000000000000000000000000000000000000000000000000000653052000000000000000000000000000000000000000000000000000000000000006540520000000000000000000000000000000000000000000000000000000000000065505200000000000000000000000000000000000000000000000000000000000000656052000000000000000000000000000000000000000000000000000000000000006570520000000000000000000000000000000000000000000000000000000000000065805200000000000000000000000000000000000000000000000000000000000000659052000000000000000000000000000000000000000000000000000000000000006600520000000000000000000000000000000000000000000000000000000000000066105200000000000000000000000000000000000000000000000000000000000000662052000000000000000000000000000000000000000000000000000000000000006630520000000000000000000000000000000000000000000000000000000000000066405200000000000000000000000000000000000000000000000000000000000000665052000000000000000000000000000000000000000000000000000000000000006660520000000000000000000000000000000000000000000000000000000000000066705200000000000000000000000000000000000000000000000000000000000000668052000000000000000000000000000000000000000000000000000000000000006690520000000000000000000000000000000000000000000000000000000000000067005200000000000000000000000000000000000000000000000000000000000000671052000000000000000000000000000000000000000000000000000000000000006720520000000000000000000000000000000000000000000000000000000000000067305200000000000000000000000000000000000000000000000000000000000000674052000000000000000000000000000000000000000000000000000000000000006750520000000000000000000000000000000000000000000000000000000000000067605200000000000000000000000000000000000000000000000000000000000000677052000000000000000000000000000000000000000000000000000000000000006780520000000000000000000000000000000000000000000000000000000000000067905200000000000000000000000000000000000000000000000000000000000000680052000000000000000000000000000000000000000000000000000000000000006810520000000000000000000000000000000000000000000000000000000000000068205200000000000000000000000000000000000000000000000000000000000000683052000000000000000000000000000000000000000000000000000000000000006840520000000000000000000000000000000000000000000000000000000000000068505200000000000000000000000000000000000000000000000000000000000000686052000000000000000000000000000000000000000000000000000000000000006870520000000000000000000000000000000000000000000000000000000000000068805200000000000000000000000000000000000000000000000000000000000000689052000000000000000000000000000000000000000000000000000000000000006900520000000000000000000000000000000000000000000000000000000000000069105200000000000000000000000000000000000000000000000000000000000000692052000000000000000000000000000000000000000000000000000000000000006930520000000000000000000000000000000000000000000000000000000000000069405200000000000000000000000000000000000000000000000000000000000000695052000000000000000000000000000000000000000000000000000000000000006960520000000000000000000000000000000000000000000000000000000000000069705200000000000000000000000000000000000000000000000000000000000000698052000000000000000000000000000000000000000000000000000000000000006990520000000000000000000000000000000000000000000000000000000000000070005200000000000000000000000000000000000000000000000000000000000000701052000000000000000000000000000000000000000000000000000000000000007020520000000000000000000000000000000000000000000000000000000000000070305200000000000000000000000000000000000000000000000000000000000000704052000000000000000000000000000000000000000000000000000000000000007050520000000000000000000000000000000000000000000000000000000000000070605200000000000000000000000000000000000000000000000000000000000000707052000000000000000000000000000000000000000000000000000000000000007080520000000000000000000000000000000000000000000000000000000000000070905200000000000000000000000000000000000000000000000000000000000000710052000000000000000000000000000000000000000000000000000000000000007110520000000000000000000000000000000000000000000000000000000000000071205200000000000000000000000000000000000000000000000000000000000000713052000000000000000000000000000000000000000000000000000000000000007140520000000000000000000000000000000000000000000000000000000000000071505200000000000000000000000000000000000000000000000000000000000000716052000000000000000000000000000000000000000000000000000000000000007170520000000000000000000000000000000000000000000000000000000000000071805200000000000000000000000000000000000000000000000000000000000000719052000000000000000000000000000000000000000000000000000000000000007200520000000000000000000000000000000000000000000000000000000000000072105200000000000000000000000000000000000000000000000000000000000000722052000000000000000000000000000000000000000000000000000000000000007230520000000000000000000000000000000000000000000000000000000000000072405200000000000000000000000000000000000000000000000000000000000000725052000000000000000000000000000000000000000000000000000000000000007260520000000000000000000000000000000000000000000000000000000000000072705200000000000000000000000000000000000000000000000000000000000000728052000000000000000000000000000000000000000000000000000000000000007290520000000000000000000000000000000000000000000000000000000000000073005200000000000000000000000000000000000000000000000000000000000000731052000000000000000000000000000000000000000000000000000000000000007320520000000000000000000000000000000000000000000000000000000000000073305200000000000000000000000000000000000000000000000000000000000000734052000000000000000000000000000000000000000000000000000000000000007350520000000000000000000000000000000000000000000000000000000000000073605200000000000000000000000000000000000000000000000000000000000000737052000000000000000000000000000000000000000000000000000000000000007380520000000000000000000000000000000000000000000000000000000000000073905200000000000000000000000000000000000000000000000000000000000000740052000000000000000000000000000000000000000000000000000000000000007410520000000000000000000000000000000000000000000000000000000000000074205200000000000000000000000000000000000000000000000000000000000000743052000000000000000000000000000000000000000000000000000000000000007440520000000000000000000000000000000000000000000000000000000000000074505200000000000000000000000000000000000000000000000000000000000000746052000000000000000000000000000000000000000000000000000000000000007470520000000000000000000000000000000000000000000000000000000000000074805200000000000000000000000000000000000000000000000000000000000000749052000000000000000000000000000000000000000000000000000000000000007500520000000000000000000000000000000000000000000000000000000000000075105200000000000000000000000000000000000000000000000000000000000000752052000000000000000000000000000000000000000000000000000000000000007530520000000000000000000000000000000000000000000000000000000000000075405200000000000000000000000000000000000000000000000000000000000000755052000000000000000000000000000000000000000000000000000000000000007560520000000000000000000000000000000000000000000000000000000000000075705200000000000000000000000000000000000000000000000000000000000000758052000000000000000000000000000000000000000000000000000000000000007590520000000000000000000000000000000000000000000000000000000000000076005200000000000000000000000000000000000000000000000000000000000000761052000000000000000000000000000000000000000000000000000000000000007620520000000000000000000000000000000000000000000000000000000000000076305200000000000000000000000000000000000000000000000000000000000000764052000000000000000000000000000000000000000000000000000000000000007650520000000000000000000000000000000000000000000000000000000000000076605200000000000000000000000000000000000000000000000000000000000000767052000000000000000000000000000000000000000000000000000000000000007680520000000000000000000000000000000000000000000000000000000000000076905200000000000000000000000000000000000000000000000000000000000000770052000000000000000000000000000000000000000000000000000000000000007710520000000000000000000000000000000000000000000000000000000000000077205200000000000000000000000000000000000000000000000000000000000000773052000000000000000000000000000000000000000000000000000000000000007740520000000000000000000000000000000000000000000000000000000000000077505200000000000000000000000000000000000000000000000000000000000000776052000000000000000000000000000000000000000000000000000000000000007770520000000000000000000000000000000000000000000000000000000000000077805200000000000000000000000000000000000000000000000000000000000000779052000000000000000000000000000000000000000000000000000000000000007800520000000000000000000000000000000000000000000000000000000000000078105200000000000000000000000000000000000000000000000000000000000000782052000000000000000000000000000000000000000000000000000000000000007830520000000000000000000000000000000000000000000000000000000000000078405200000000000000000000000000000000000000000000000000000000000000785052000000000000000000000000000000000000000000000000000000000000007860520000000000000000000000000000000000000000000000000000000000000078705200000000000000000000000000000000000000000000000000000000000000788052000000000000000000000000000000000000000000000000000000000000007890520000000000000000000000000000000000000000000000000000000000000079005200000000000000000000000000000000000000000000000000000000000000791052000000000000000000000000000000000000000000000000000000000000007920520000000000000000000000000000000000000000000000000000000000000079305200000000000000000000000000000000000000000000000000000000000000794052000000000000000000000000000000000000000000000000000000000000007950520000000000000000000000000000000000000000000000000000000000000079605200000000000000000000000000000000000000000000000000000000000000797052000000000000000000000000000000000000000000000000000000000000007980520000000000000000000000000000000000000000000000000000000000000079905200000000000000000000000000000000000000000000000000000000000000800052000000000000000000000000000000000000000000000000000000000000008010520000000000000000000000000000000000000000000000000000000000000080205200000000000000000000000000000000000000000000000000000000000000803052000000000000000000000000000000000000000000000000000000000000008040520000000000000000000000000000000000000000000000000000000000000080505200000000000000000000000000000000000000000000000000000000000000806052000000000000000000000000000000000000000000000000000000000000008070520000000000000000000000000000000000000000000000000000000000000080805200000000000000000000000000000000000000000000000000000000000000809052000000000000000000000000000000000000000000000000000000000000008100520000000000000000000000000000000000000000000000000000000000000081105200000000000000000000000000000000000000000000000000000000000000812052000000000000000000000000000000000000000000000000000000000000008130520000000000000000000000000000000000000000000000000000000000000081405200000000000000000000000000000000000000000000000000000000000000815052000000000000000000000000000000000000000000000000000000000000008160520000000000000000000000000000000000000000000000000000000000000081705200000000000000000000000000000000000000000000000000000000000000818052000000000000000000000000000000000000000000000000000000000000008190520000000000000000000000000000000000000000000000000000000000000082005200000000000000000000000000000000000000000000000000000000000000821052000000000000000000000000000000000000000000000000000000000000008220520000000000000000000000000000000000000000000000000000000000000082305200000000000000000000000000000000000000000000000000000000000000824052000000000000000000000000000000000000000000000000000000000000008250520000000000000000000000000000000000000000000000000000000000000082605200000000000000000000000000000000000000000000000000000000000000827052000000000000000000000000000000000000000000000000000000000000008280520000000000000000000000000000000000000000000000000000000000000082905200000000000000000000000000000000000000000000000000000000000000830052000000000000000000000000000000000000000000000000000000000000008310520000000000000000000000000000000000000000000000000000000000000083205200000000000000000000000000000000000000000000000000000000000000833052000000000000000000000000000000000000000000000000000000000000008340520000000000000000000000000000000000000000000000000000000000000083505200000000000000000000000000000000000000000000000000000000000000836052000000000000000000000000000000000000000000000000000000000000008370520000000000000000000000000000000000000000000000000000000000000083805200000000000000000000000000000000000000000000000000000000000000839052000000000000000000000000000000000000000000000000000000000000008400520000000000000000000000000000000000000000000000000000000000000084105200000000000000000000000000000000000000000000000000000000000000842052000000000000000000000000000000000000000000000000000000000000008430520000000000000000000000000000000000000000000000000000000000000084405200000000000000000000000000000000000000000000000000000000000000845052000000000000000000000000000000000000000000000000000000000000008460520000000000000000000000000000000000000000000000000000000000000084705200000000000000000000000000000000000000000000000000000000000000848052000000000000000000000000000000000000000000000000000000000000008490520000000000000000000000000000000000000000000000000000000000000085005200000000000000000000000000000000000000000000000000000000000000851052000000000000000000000000000000000000000000000000000000000000008520520000000000000000000000000000000000000000000000000000000000000085305200000000000000000000000000000000000000000000000000000000000000854052000000000000000000000000000000000000000000000000000000000000008550520000000000000000000000000000000000000000000000000000000000000085605200000000000000000000000000000000000000000000000000000000000000857052000000000000000000000000000000000000000000000000000000000000008580520000000000000000000000000000000000000000000000000000000000000085905200000000000000000000000000000000000000000000000000000000000000860052000000000000000000000000000000000000000000000000000000000000008610520000000000000000000000000000000000000000000000000000000000000086205200000000000000000000000000000000000000000000000000000000000000863052000000000000000000000000000000000000000000000000000000000000008640520000000000000000000000000000000000000000000000000000000000000086505200000000000000000000000000000000000000000000000000000000000000866052000000000000000000000000000000000000000000000000000000000000008670520000000000000000000000000000000000000000000000000000000000000086805200000000000000000000000000000000000000000000000000000000000000869052000000000000000000000000000000000000000000000000000000000000008700520000000000000000000000000000000000000000000000000000000000000087105200000000000000000000000000000000000000000000000000000000000000872052000000000000000000000000000000000000000000000000000000000000008730520000000000000000000000000000000000000000000000000000000000000087405200000000000000000000000000000000000000000000000000000000000000875052000000000000000000000000000000000000000000000000000000000000008760520000000000000000000000000000000000000000000000000000000000000087705200000000000000000000000000000000000000000000000000000000000000878052000000000000000000000000000000000000000000000000000000000000008790520000000000000000000000000000000000000000000000000000000000000088005200000000000000000000000000000000000000000000000000000000000000881052000000000000000000000000000000000000000000000000000000000000008820520000000000000000000000000000000000000000000000000000000000000088305200000000000000000000000000000000000000000000000000000000000000884052000000000000000000000000000000000000000000000000000000000000008850520000000000000000000000000000000000000000000000000000000000000088605200000000000000000000000000000000000000000000000000000000000000887052000000000000000000000000000000000000000000000000000000000000008880520000000000000000000000000000000000000000000000000000000000000088905200000000000000000000000000000000000000000000000000000000000000890052000000000000000000000000000000000000000000000000000000000000008910520000000000000000000000000000000000000000000000000000000000000089205200000000000000000000000000000000000000000000000000000000000000893052000000000000000000000000000000000000000000000000000000000000008940520000000000000000000000000000000000000000000000000000000000000089505200000000000000000000000000000000000000000000000000000000000000896052000000000000000000000000000000000000000000000000000000000000008970520000000000000000000000000000000000000000000000000000000000000089805200000000000000000000000000000000000000000000000000000000000000899052000000000000000000000000000000000000000000000000000000000000009000520000000000000000000000000000000000000000000000000000000000000090105200000000000000000000000000000000000000000000000000000000000000902052000000000000000000000000000000000000000000000000000000000000009030520000000000000000000000000000000000000000000000000000000000000090405200000000000000000000000000000000000000000000000000000000000000905052000000000000000000000000000000000000000000000000000000000000009060520000000000000000000000000000000000000000000000000000000000000090705200000000000000000000000000000000000000000000000000000000000000908052000000000000000000000000000000000000000000000000000000000000009090520000000000000000000000000000000000000000000000000000000000000091005200000000000000000000000000000000000000000000000000000000000000911052000000000000000000000000000000000000000000000000000000000000009120520000000000000000000000000000000000000000000000000000000000000091305200000000000000000000000000000000000000000000000000000000000000914052000000000000000000000000000000000000000000000000000000000000009150520000000000000000000000000000000000000000000000000000000000000091605200000000000000000000000000000000000000000000000000000000000000917052000000000000000000000000000000000000000000000000000000000000009180520000000000000000000000000000000000000000000000000000000000000091905200000000000000000000000000000000000000000000000000000000000000920052000000000000000000000000000000000000000000000000000000000000009210520000000000000000000000000000000000000000000000000000000000000092205200000000000000000000000000000000000000000000000000000000000000923052000000000000000000000000000000000000000000000000000000000000009240520000000000000000000000000000000000000000000000000000000000000092505200000000000000000000000000000000000000000000000000000000000000926052000000000000000000000000000000000000000000000000000000000000009270520000000000000000000000000000000000000000000000000000000000000092805200000000000000000000000000000000000000000000000000000000000000929052000000000000000000000000000000000000000000000000000000000000009300520000000000000000000000000000000000000000000000000000000000000093105200000000000000000000000000000000000000000000000000000000000000932052000000000000000000000000000000000000000000000000000000000000009330520000000000000000000000000000000000000000000000000000000000000093405200000000000000000000000000000000000000000000000000000000000000935052000000000000000000000000000000000000000000000000000000000000009360520000000000000000000000000000000000000000000000000000000000000093705200000000000000000000000000000000000000000000000000000000000000938052000000000000000000000000000000000000000000000000000000000000009390520000000000000000000000000000000000000000000000000000000000000094005200000000000000000000000000000000000000000000000000000000000000941052000000000000000000000000000000000000000000000000000000000000009420520000000000000000000000000000000000000000000000000000000000000094305200000000000000000000000000000000000000000000000000000000000000944052000000000000000000000000000000000000000000000000000000000000009450520000000000000000000000000000000000000000000000000000000000000094605200000000000000000000000000000000000000000000000000000000000000947052000000000000000000000000000000000000000000000000000000000000009480520000000000000000000000000000000000000000000000000000000000000094905200000000000000000000000000000000000000000000000000000000000000950052000000000000000000000000000000000000000000000000000000000000009510520000000000000000000000000000000000000000000000000000000000000095205200000000000000000000000000000000000000000000000000000000000000953052000000000000000000000000000000000000000000000000000000000000009540520000000000000000000000000000000000000000000000000000000000000095505200000000000000000000000000000000000000000000000000000000000000956052000000000000000000000000000000000000000000000000000000000000009570520000000000000000000000000000000000000000000000000000000000000095805200000000000000000000000000000000000000000000000000000000000000959052000000000000000000000000000000000000000000000000000000000000009600520000000000000000000000000000000000000000000000000000000000000096105200000000000000000000000000000000000000000000000000000000000000962052000000000000000000000000000000000000000000000000000000000000009630520000000000000000000000000000000000000000000000000000000000000096405200000000000000000000000000000000000000000000000000000000000000965052000000000000000000000000000000000000000000000000000000000000009660520000000000000000000000000000000000000000000000000000000000000096705200000000000000000000000000000000000000000000000000000000000000968052000000000000000000000000000000000000000000000000000000000000009690520000000000000000000000000000000000000000000000000000000000000097005200000000000000000000000000000000000000000000000000000000000000971052000000000000000000000000000000000000000000000000000000000000009720520000000000000000000000000000000000000000000000000000000000000097305200000000000000000000000000000000000000000000000000000000000000974052000000000000000000000000000000000000000000000000000000000000009750520000000000000000000000000000000000000000000000000000000000000097605200000000000000000000000000000000000000000000000000000000000000977052000000000000000000000000000000000000000000000000000000000000009780520000000000000000000000000000000000000000000000000000000000000097905200000000000000000000000000000000000000000000000000000000000000980052000000000000000000000000000000000000000000000000000000000000009810520000000000000000000000000000000000000000000000000000000000000098205200000000000000000000000000000000000000000000000000000000000000983052000000000000000000000000000000000000000000000000000000000000009840520000000000000000000000000000000000000000000000000000000000000098505200000000000000000000000000000000000000000000000000000000000000986052000000000000000000000000000000000000000000000000000000000000009870520000000000000000000000000000000000000000000000000000000000000098805200000000000000000000000000000000000000000000000000000000000000989052000000000000000000000000000000000000000000000000000000000000009900520000000000000000000000000000000000000000000000000000000000000099105200000000000000000000000000000000000000000000000000000000000000992052000000000000000000000000000000000000000000000000000000000000009930520000000000000000000000000000000000000000000000000000000000000099405200000000000000000000000000000000000000000000000000000000000000995052000000000000000000000000000000000000000000000000000000000000009960520000000000000000000000000000000000000000000000000000000000000099705200000000000000000000000000000000000000000000000000000000000000998052000000000000000000000000000000000000000000000000000000000000009990520e57eb8d10b6eed36a88a464538f8fcedbba7b1a71d6ed52124f77b835807d0fd05201c53ca351e7f26f963ced56cf18f9ebee56535170171b72a0addb4e1613776850520636b8e5a599cfe0833dbe141dbc093d65e0a497451ac21415fbf03698587c7b905204ea21cad94a85adb252b0a76b9826c67d7c697ca386d201752e38f19ed92a223126170746f733a3a6d657461646174615f7630c201032003000000000000134552525f414c52454144595f50524553454e542c4164647265737320697320616c72656164792070726573656e7420696e207468652077686974656c6973742e2103000000000000134552525f4e4f5f535543485f41444452455353214e6f2073756368206164647265737320696e207468652077686974656c6973742e2203000000000000134552525f4e4f545f494e495449414c495a45441d57686974656c697374206973206e6f7420696e697469616c697a65642e000201090b010205020001040100051d0b0011050c020b02070321030907012707032900030e0701270a01110220031407002707032a000c030b030f000b013101380002010104010008b01f0b0011050c010b01070321030907012707032a000c030b030f000c020a020704310138000a020705310138000a020706310138000a020707310138000a020708310138000a020709310138000a02070a310138000a02070b310138000a02070c310138000a02070d310138000a02070e310138000a02070f310138000a020710310138000a020711310138000a020712310138000a020713310138000a020714310138000a020715310138000a020716310138000a020717310138000a020718310138000a020719310138000a02071a310138000a02071b310138000a02071c310138000a02071d310138000a02071e310138000a02071f310138000a020720310138000a020721310138000a020722310138000a020723310138000a020724310138000a020725310138000a020726310138000a020727310138000a020728310138000a020729310138000a02072a310138000a02072b310138000a02072c310138000a02072d310138000a02072e310138000a02072f310138000a020730310138000a020731310138000a020732310138000a020733310138000a020734310138000a020735310138000a020736310138000a020737310138000a020738310138000a020739310138000a02073a310138000a02073b310138000a02073c310138000a02073d310138000a02073e310138000a02073f310138000a020740310138000a020741310138000a020742310138000a020743310138000a020744310138000a020745310138000a020746310138000a020747310138000a020748310138000a020749310138000a02074a310138000a02074b310138000a02074c310138000a02074d310138000a02074e310138000a02074f310138000a020750310138000a020751310138000a020752310138000a020753310138000a020754310138000a020755310138000a020756310138000a020757310138000a020758310138000a020759310138000a02075a310138000a02075b310138000a02075c310138000a02075d310138000a02075e310138000a02075f310138000a020760310138000a020761310138000a020762310138000a020763310138000a020764310138000a020765310138000a020766310138000a020767310138000a020768310138000a020769310138000a02076a310138000a02076b310138000a02076c310138000a02076d310138000a02076e310138000a02076f310138000a020770310138000a020771310138000a020772310138000a020773310138000a020774310138000a020775310138000a020776310138000a020777310138000a020778310138000a020779310138000a02077a310138000a02077b310138000a02077c310138000a02077d310138000a02077e310138000a02077f310138000a02078001310138000a02078101310138000a02078201310138000a02078301310138000a02078401310138000a02078501310138000a02078601310138000a02078701310138000a02078801310138000a02078901310138000a02078a01310138000a02078b01310138000a02078c01310138000a02078d01310138000a02078e01310138000a02078f01310138000a02079001310138000a02079101310138000a02079201310138000a02079301310138000a02079401310138000a02079501310138000a02079601310138000a02079701310138000a02079801310138000a02079901310138000a02079a01310138000a02079b01310138000a02079c01310138000a02079d01310138000a02079e01310138000a02079f01310138000a0207a001310138000a0207a101310138000a0207a201310138000a0207a301310138000a0207a401310138000a0207a501310138000a0207a601310138000a0207a701310138000a0207a801310138000a0207a901310138000a0207aa01310138000a0207ab01310138000a0207ac01310138000a0207ad01310138000a0207ae01310138000a0207af01310138000a0207b001310138000a0207b101310138000a0207b201310138000a0207b301310138000a0207b401310138000a0207b501310138000a0207b601310138000a0207b701310138000a0207b801310138000a0207b901310138000a0207ba01310138000a0207bb01310138000a0207bc01310138000a0207bd01310138000a0207be01310138000a0207bf01310138000a0207c001310138000a0207c101310138000a0207c201310138000a0207c301310138000a0207c401310138000a0207c501310138000a0207c601310138000a0207c701310138000a0207c801310138000a0207c901310138000a0207ca01310138000a0207cb01310138000a0207cc01310138000a0207cd01310138000a0207ce01310138000a0207cf01310138000a0207d001310138000a0207d101310138000a0207d201310138000a0207d301310138000a0207d401310138000a0207d501310138000a0207d601310138000a0207d701310138000a0207d801310138000a0207d901310138000a0207da01310138000a0207db01310138000a0207dc01310138000a0207dd01310138000a0207de01310138000a0207df01310138000a0207e001310138000a0207e101310138000a0207e201310138000a0207e301310138000a0207e401310138000a0207e501310138000a0207e601310138000a0207e701310138000a0207e801310138000a0207e901310138000a0207ea01310138000a0207eb01310138000a0207ec01310138000a0207ed01310138000a0207ee01310138000a0207ef01310138000a0207f001310138000a0207f101310138000a0207f201310138000a0207f301310138000a0207f401310138000a0207f501310138000a0207f601310138000a0207f701310138000a0207f801310138000a0207f901310138000a0207fa01310138000a0207fb01310138000a0207fc01310138000a0207fd01310138000a0207fe01310138000a0207ff01310138000a02078002310138000a02078102310138000a02078202310138000a02078302310138000a02078402310138000a02078502310138000a02078602310138000a02078702310138000a02078802310138000a02078902310138000a02078a02310138000a02078b02310138000a02078c02310138000a02078d02310138000a02078e02310138000a02078f02310138000a02079002310138000a02079102310138000a02079202310138000a02079302310138000a02079402310138000a02079502310138000a02079602310138000a02079702310138000a02079802310138000a02079902310138000a02079a02310138000a02079b02310138000a02079c02310138000a02079d02310138000a02079e02310138000a02079f02310138000a0207a002310138000a0207a102310138000a0207a202310138000a0207a302310138000a0207a402310138000a0207a502310138000a0207a602310138000a0207a702310138000a0207a802310138000a0207a902310138000a0207aa02310138000a0207ab02310138000a0207ac02310138000a0207ad02310138000a0207ae02310138000a0207af02310138000a0207b002310138000a0207b102310138000a0207b202310138000a0207b302310138000a0207b402310138000a0207b502310138000a0207b602310138000a0207b702310138000a0207b802310138000a0207b902310138000a0207ba02310138000a0207bb02310138000a0207bc02310138000a0207bd02310138000a0207be02310138000a0207bf02310138000a0207c002310138000a0207c102310138000a0207c202310138000a0207c302310138000a0207c402310138000a0207c502310138000a0207c602310138000a0207c702310138000a0207c802310138000a0207c902310138000a0207ca02310138000a0207cb02310138000a0207cc02310138000a0207cd02310138000a0207ce02310138000a0207cf02310138000a0207d002310138000a0207d102310138000a0207d202310138000a0207d302310138000a0207d402310138000a0207d502310138000a0207d602310138000a0207d702310138000a0207d802310138000a0207d902310138000a0207da02310138000a0207db02310138000a0207dc02310138000a0207dd02310138000a0207de02310138000a0207df02310138000a0207e002310138000a0207e102310138000a0207e202310138000a0207e302310138000a0207e402310138000a0207e502310138000a0207e602310138000a0207e702310138000a0207e802310138000a0207e902310138000a0207ea02310138000a0207eb02310138000a0207ec02310138000a0207ed02310138000a0207ee02310138000a0207ef02310138000a0207f002310138000a0207f102310138000a0207f202310138000a0207f302310138000a0207f402310138000a0207f502310138000a0207f602310138000a0207f702310138000a0207f802310138000a0207f902310138000a0207fa02310138000a0207fb02310138000a0207fc02310138000a0207fd02310138000a0207fe02310138000a0207ff02310138000a02078003310138000a02078103310138000a02078203310138000a02078303310138000a02078403310138000a02078503310138000a02078603310138000a02078703310138000a02078803310138000a02078903310138000a02078a03310138000a02078b03310138000a02078c03310138000a02078d03310138000a02078e03310138000a02078f03310138000a02079003310138000a02079103310138000a02079203310138000a02079303310138000a02079403310138000a02079503310138000a02079603310138000a02079703310138000a02079803310138000a02079903310138000a02079a03310138000a02079b03310138000a02079c03310138000a02079d03310138000a02079e03310138000a02079f03310138000a0207a003310138000a0207a103310138000a0207a203310138000a0207a303310138000a0207a403310138000a0207a503310138000a0207a603310138000a0207a703310138000a0207a803310138000a0207a903310138000a0207aa03310138000a0207ab03310138000a0207ac03310138000a0207ad03310138000a0207ae03310138000a0207af03310138000a0207b003310138000a0207b103310138000a0207b203310138000a0207b303310138000a0207b403310138000a0207b503310138000a0207b603310138000a0207b703310138000a0207b803310138000a0207b903310138000a0207ba03310138000a0207bb03310138000a0207bc03310138000a0207bd03310138000a0207be03310138000a0207bf03310138000a0207c003310138000a0207c103310138000a0207c203310138000a0207c303310138000a0207c403310138000a0207c503310138000a0207c603310138000a0207c703310138000a0207c803310138000a0207c903310138000a0207ca03310138000a0207cb03310138000a0207cc03310138000a0207cd03310138000a0207ce03310138000a0207cf03310138000a0207d003310138000a0207d103310138000a0207d203310138000a0207d303310138000a0207d403310138000a0207d503310138000a0207d603310138000a0207d703310138000a0207d803310138000a0207d903310138000a0207da03310138000a0207db03310138000a0207dc03310138000a0207dd03310138000a0207de03310138000a0207df03310138000a0207e003310138000a0207e103310138000a0207e203310138000a0207e303310138000a0207e403310138000a0207e503310138000a0207e603310138000a0207e703310138000a0207e803310138000a0207e903310138000a0207ea03310138000a0207eb03310138000a0207ec03310138000a0207ed03310138000a0207ee03310138000a0207ef03310138000a0207f003310138000a0207f103310138000a0207f203310138000a0207f303310138000a0207f403310138000a0207f503310138000a0207f603310138000a0207f703310138000a0207f803310138000a0207f903310138000a0207fa03310138000a0207fb03310138000a0207fc03310138000a0207fd03310138000a0207fe03310138000a0207ff03310138000a02078004310138000a02078104310138000a02078204310138000a02078304310138000a02078404310138000a02078504310138000a02078604310138000a02078704310138000a02078804310138000a02078904310138000a02078a04310138000a02078b04310138000a02078c04310138000a02078d04310138000a02078e04310138000a02078f04310138000a02079004310138000a02079104310138000a02079204310138000a02079304310138000a02079404310138000a02079504310138000a02079604310138000a02079704310138000a02079804310138000a02079904310138000a02079a04310138000a02079b04310138000a02079c04310138000a02079d04310138000a02079e04310138000a02079f04310138000a0207a004310138000a0207a104310138000a0207a204310138000a0207a304310138000a0207a404310138000a0207a504310138000a0207a604310138000a0207a704310138000a0207a804310138000a0207a904310138000a0207aa04310138000a0207ab04310138000a0207ac04310138000a0207ad04310138000a0207ae04310138000a0207af04310138000a0207b004310138000a0207b104310138000a0207b204310138000a0207b304310138000a0207b404310138000a0207b504310138000a0207b604310138000a0207b704310138000a0207b804310138000a0207b904310138000a0207ba04310138000a0207bb04310138000a0207bc04310138000a0207bd04310138000a0207be04310138000a0207bf04310138000a0207c004310138000a0207c104310138000a0207c204310138000a0207c304310138000a0207c404310138000a0207c504310138000a0207c604310138000a0207c704310138000a0207c804310138000a0207c904310138000a0207ca04310138000a0207cb04310138000a0207cc04310138000a0207cd04310138000a0207ce04310138000a0207cf04310138000a0207d004310138000a0207d104310138000a0207d204310138000a0207d304310138000a0207d404310138000a0207d504310138000a0207d604310138000a0207d704310138000a0207d804310138000a0207d904310138000a0207da04310138000a0207db04310138000a0207dc04310138000a0207dd04310138000a0207de04310138000a0207df04310138000a0207e004310138000a0207e104310138000a0207e204310138000a0207e304310138000a0207e404310138000a0207e504310138000a0207e604310138000a0207e704310138000a0207e804310138000a0207e904310138000a0207ea04310138000a0207eb04310138000a0207ec04310138000a0207ed04310138000a0207ee04310138000a0207ef04310138000a0207f004310138000a0207f104310138000a0207f204310138000a0207f304310138000a0207f404310138000a0207f504310138000a0207f604310138000a0207f704310138000a0207f804310138000a0207f904310138000a0207fa04310138000a0207fb04310138000a0207fc04310138000a0207fd04310138000a0207fe04310138000a0207ff04310138000a02078005310138000a02078105310138000a02078205310138000a02078305310138000a02078405310138000a02078505310138000a02078605310138000a02078705310138000a02078805310138000a02078905310138000a02078a05310138000a02078b05310138000a02078c05310138000a02078d05310138000a02078e05310138000a02078f05310138000a02079005310138000a02079105310138000a02079205310138000a02079305310138000a02079405310138000a02079505310138000a02079605310138000a02079705310138000a02079805310138000a02079905310138000a02079a05310138000a02079b05310138000a02079c05310138000a02079d05310138000a02079e05310138000a02079f05310138000a0207a005310138000a0207a105310138000a0207a205310138000a0207a305310138000a0207a405310138000a0207a505310138000a0207a605310138000a0207a705310138000a0207a805310138000a0207a905310138000a0207aa05310138000a0207ab05310138000a0207ac05310138000a0207ad05310138000a0207ae05310138000a0207af05310138000a0207b005310138000a0207b105310138000a0207b205310138000a0207b305310138000a0207b405310138000a0207b505310138000a0207b605310138000a0207b705310138000a0207b805310138000a0207b905310138000a0207ba05310138000a0207bb05310138000a0207bc05310138000a0207bd05310138000a0207be05310138000a0207bf05310138000a0207c005310138000a0207c105310138000a0207c205310138000a0207c305310138000a0207c405310138000a0207c505310138000a0207c605310138000a0207c705310138000a0207c805310138000a0207c905310138000a0207ca05310138000a0207cb05310138000a0207cc05310138000a0207cd05310138000a0207ce05310138000a0207cf05310138000a0207d005310138000a0207d105310138000a0207d205310138000a0207d305310138000a0207d405310138000a0207d505310138000a0207d605310138000a0207d705310138000a0207d805310138000a0207d905310138000a0207da05310138000a0207db05310138000a0207dc05310138000a0207dd05310138000a0207de05310138000a0207df05310138000a0207e005310138000a0207e105310138000a0207e205310138000a0207e305310138000a0207e405310138000a0207e505310138000a0207e605310138000a0207e705310138000a0207e805310138000a0207e905310138000a0207ea05310138000a0207eb05310138000a0207ec05310138000a0207ed05310138000a0207ee05310138000a0207ef05310138000a0207f005310138000a0207f105310138000a0207f205310138000a0207f305310138000a0207f405310138000a0207f505310138000a0207f605310138000a0207f705310138000a0207f805310138000a0207f905310138000a0207fa05310138000a0207fb05310138000a0207fc05310138000a0207fd05310138000a0207fe05310138000a0207ff05310138000a02078006310138000a02078106310138000a02078206310138000a02078306310138000a02078406310138000a02078506310138000a02078606310138000a02078706310138000a02078806310138000a02078906310138000a02078a06310138000a02078b06310138000a02078c06310138000a02078d06310138000a02078e06310138000a02078f06310138000a02079006310138000a02079106310138000a02079206310138000a02079306310138000a02079406310138000a02079506310138000a02079606310138000a02079706310138000a02079806310138000a02079906310138000a02079a06310138000a02079b06310138000a02079c06310138000a02079d06310138000a02079e06310138000a02079f06310138000a0207a006310138000a0207a106310138000a0207a206310138000a0207a306310138000a0207a406310138000a0207a506310138000a0207a606310138000a0207a706310138000a0207a806310138000a0207a906310138000a0207aa06310138000a0207ab06310138000a0207ac06310138000a0207ad06310138000a0207ae06310138000a0207af06310138000a0207b006310138000a0207b106310138000a0207b206310138000a0207b306310138000a0207b406310138000a0207b506310138000a0207b606310138000a0207b706310138000a0207b806310138000a0207b906310138000a0207ba06310138000a0207bb06310138000a0207bc06310138000a0207bd06310138000a0207be06310138000a0207bf06310138000a0207c006310138000a0207c106310138000a0207c206310138000a0207c306310138000a0207c406310138000a0207c506310138000a0207c606310138000a0207c706310138000a0207c806310138000a0207c906310138000a0207ca06310138000a0207cb06310138000a0207cc06310138000a0207cd06310138000a0207ce06310138000a0207cf06310138000a0207d006310138000a0207d106310138000a0207d206310138000a0207d306310138000a0207d406310138000a0207d506310138000a0207d606310138000a0207d706310138000a0207d806310138000a0207d906310138000a0207da06310138000a0207db06310138000a0207dc06310138000a0207dd06310138000a0207de06310138000a0207df06310138000a0207e006310138000a0207e106310138000a0207e206310138000a0207e306310138000a0207e406310138000a0207e506310138000a0207e606310138000a0207e706310138000a0207e806310138000a0207e906310138000a0207ea06310138000a0207eb06310138000a0207ec06310138000a0207ed06310138000a0207ee06310138000a0207ef06310138000a0207f006310138000a0207f106310138000a0207f206310138000a0207f306310138000a0207f406310138000a0207f506310138000a0207f606310138000a0207f706310138000a0207f806310138000a0207f906310138000a0207fa06310138000a0207fb06310138000a0207fc06310138000a0207fd06310138000a0207fe06310138000a0207ff06310138000a02078007310138000a02078107310138000a02078207310138000a02078307310138000a02078407310138000a02078507310138000a02078607310138000a02078707310138000a02078807310138000a02078907310138000a02078a07310138000a02078b07310138000a02078c07310138000a02078d07310138000a02078e07310138000a02078f07310138000a02079007310138000a02079107310138000a02079207310138000a02079307310138000a02079407310138000a02079507310138000a02079607310138000a02079707310138000a02079807310138000a02079907310138000a02079a07310138000a02079b07310138000a02079c07310138000a02079d07310138000a02079e07310138000a02079f07310138000a0207a007310138000a0207a107310138000a0207a207310138000a0207a307310138000a0207a407310138000a0207a507310138000a0207a607310138000a0207a707310138000a0207a807310138000a0207a907310138000a0207aa07310138000a0207ab07310138000a0207ac07310138000a0207ad07310138000a0207ae07310138000a0207af07310138000a0207b007310138000a0207b107310138000a0207b207310138000a0207b307310138000a0207b407310138000a0207b507310138000a0207b607310138000a0207b707310138000a0207b807310138000a0207b907310138000a0207ba07310138000a0207bb07310138000a0207bc07310138000a0207bd07310138000a0207be07310138000a0207bf07310138000a0207c007310138000a0207c107310138000a0207c207310138000a0207c307310138000a0207c407310138000a0207c507310138000a0207c607310138000a0207c707310138000a0207c807310138000a0207c907310138000a0207ca07310138000a0207cb07310138000a0207cc07310138000a0207cd07310138000a0207ce07310138000a0207cf07310138000a0207d007310138000a0207d107310138000a0207d207310138000a0207d307310138000a0207d407310138000a0207d507310138000a0207d607310138000a0207d707310138000a0207d807310138000a0207d907310138000a0207da07310138000a0207db07310138000a0207dc07310138000a0207dd07310138000a0207de07310138000a0207df07310138000a0207e007310138000a0207e107310138000a0207e207310138000a0207e307310138000a0207e407310138000a0207e507310138000a0207e607310138000a0207e707310138000a0207e807310138000a0207e907310138000a0207ea07310138000b0207eb0731013800020201000100090807032b000c010b0110000b00380102030100000b1f38020c010d0107ec07310138000d0107ed07310138000d0107ee07310138000d0107ef07310138000d01071a310138000d01071b310138000b000b0112002d00020401040100051c0b0011050c020b02070321030907012707032900030e0701270a011102031307022707032a000c030b030f000b0138030102000000"; + let res = run_binary_test("sample_whitelist", code); + assert!(res.is_ok(), "{:?}", res) +} + +#[cfg(feature = "address32")] +#[test] +fn sample_coin_store() { + let code = "a11ceb0b050000000e01001e021e0c032acb0604f5065405c907a41207ed19e80908d523800206d5252c108126420ac326090bcc26040cd026fd86010dcdad01020ecfad01040000010101020103020402050306030704080509050a0607060b070c070d000e08010001011104010001000f00010200000010010201000012030101000013040103000000001404010300000000150401030000000016040103000000001704010300000000180401030000000019040103000000001a040103000000001b040103000000001c040103000000001d040103000000001e040103000000001f0401030000000020040103000000002104010300000000220401030000000023040103000000002404010300000000250401030000000026040103000000002704010300000000280401030000000029040103000000002a040103000000002b040103000000002c040103000000002d040103000000002e040103000000002f0401030000000030040103000000003104010300000000320401030000000033050103000000003405010300000000350501030000000036050103000000003705010300000000380501030000000039050103000000003a050103000000003b050103000000003c050103000000003d050103000000003e050103000000003f0501030000000040050103000000004105010300000000420501030000000043050103000000004405010300000000450501030000000046050103000000004705010300000000480501030000000049050103000000004a050103000000004b050103000000004c050103000000004d050103000000004e050103000000004f050103000000005005010300000000510601010000520701010000530801010000540901020000005509010200000056000102000000570a010200000058070102000000590a01020000005a0b01020000005b0001020000005c0c0103000000005d0c01020000005e0c01020000005f0701010000600701010000610201010000620701010000630d01010000640e010100006502030100006601030100006702030100016810020100016911010100096a0114020000046b0100020000016c16030100016d01030100090b1819020000040b1a1b020000016e030101000c6f011d0200000b70031e020000066b0100030000000771221e030000000872010202000008730102020000087424000200000e6a01140200000d0b261e020000037508400002760202000165070301000477014200057801430200000a790100020000060b1a1b03000000011226010100017a48030100580f590f5a135a155b135c0f5d175e135e1559175d0f5f155f136017611361156215600f6320632164216513661366156515671568136815691562136420671369136c0f6e136f135c17702070215817710f720f020303000103010b010109000d030403040404010101010404040d0304030404010101010404040402060c0b0101090002060c0301060c0b030403040404010104040403060c030304060c0303010a060c03040403030404010102050303060c050301090001060b0101090002070b010109000b01010900230b010109000b010109010403040b010109000403040404040b010109010403030304040b010109000b010109000b01010901070b00010900040404040b010109000b010109000b0101090104040b0101090104040209000901020404020901090002070b0101090003010901040b01010900040b0101090104040b010109000b010109010b010109000b01010901040b01010900030b0101090103020b010109000b01010901250303030403040b010109000403040404040b0101090103030304040b010109000b010109010b01010900070b000109000404040b010109000b0101090003040404030b0101090104030403030303010b0101090122040303040b010109000403040404040b0101090103030304040b010109000b010109000b01010901070b000109000404040b0101090003040b010109000404030b0101090104040309000901090203090109000902020b010109000323040404040b010109000403040404040b0101090103030304040b010109000b010109000b01010901070b000109000404050b01010900040b010109000b01010901040b0101090004040b0101090104040805070b01010900070b01010901030301040423040404040b010109000403040404040b0101090103030304040b010109000b010109010b01010900070b00010900040405040b0101090004040b010109000404040b01010901040402050b01010900240403040403040404040403030304040b010109000b010109010b01010900070b000109000b0101090104040504040b010109010b010109000b01010900040b01010900040b010109010b0101090104040b01010900200303030403030404030404040403030304040b010109000b010109010b01010900070b000109000b010109010404030b01010900040303040b010109001d040303030404030404040403030304040b010109000b010109010b01010900070b000109000b01010901040403040b0101090003040b010109001e040404030404030404040403030304040b010109000b010109010b01010900070b000109000b010109010404050b01010900040b010109000b01010901040b010109001e040404030404030404040403030304040b010109000b010109010b01010900070b000109000b0101090104040504040b0101090004040b010109002603030304030403040404040403030304040b010109010b01010900070b00010900040405030b010109000b0101090104040b01010900040b01010900030b01010901040b01010901040304200303030b010109000b010109010403030403040404040403030304040b010109010b01010900070b000109000404030b010109000b01010901040303041d0303030403030304030404040403030304040b01010900070b0001090004040303040303030421030303040404030404030404040403030304040b010109010b01010900070b000109000404050b01010900030b010109000b01010901040303041f0303030404040304030404040403030304040b010109010b01010900070b0001090004040503040403040304230403030403040404040403030304040b010109000b01010901070b0001090004040503040b01010901040b010109000b01010900040b01010900030b01010901040b0101090104041d0b010109000b01010901040303030403040404040403030304040b010109000b01010901070b00010900040403040b010109000b0101090103041e04040403030404030404040403030304040b010109000b01010901070b000109000404050b0101090003040b010109000b0101090103041c040404030304030404040403030304040b010109000b01010901070b00010900040405030404030404240404040403040404040403030304040b010109000b010109000b01010901070b000109000404050b01010901040b01010901040b010109010b010109000b01010900040b01010900040b010109010b0101090104041f04040b010109000b0101090104030403040404040403030304040b010109000b010109000b01010901070b000109000404050b01010901040b010109010b010109000b0101090104200404030303040304030404040403030304040b010109000b01010900070b000109000404050b01010901030b010109010b01010900040303041d040404030304030404040403030304040b010109000b01010900070b000109000404050b0101090103040b010109010b0101090003041e040404040404030404040403030304040b010109000b010109010b01010900070b000109000404050b01010901040b01010900040b010109010404240404040403040404040403030304040b010109000b010109000b01010901070b00010900040405040b010109000b0101090104040b01010900040b01010900040b01010901040b0101090104041f04040b010109000b0101090104030403040404040403030304040b010109000b010109000b01010901070b0001090004040504040b010109000b0101090104041f0404030303040304030404040403030304040b010109000b01010900070b00010900040405040304040303041c040404030304030404040403030304040b010109000b01010900070b000109000404050403040403041f04040404040404030404040403030304040b010109000b010109000b01010901070b000109000404050b01010900040b010109000b01010901040404010b0001090001050d05030403070b000109000b01010901040b01010900040303030b01010900040302010101011a0504040404070b00010900070b000109010404030303030b01010901040404040b010109000b010109000b010109000b010109000b010109010b010109010b010109010b010109010f03030305040404030b010109010b01010901040b0101090003030b010109000e04040305040404030b010109000b01010901040b010109010b010109010b010109000f030303030305040404030b010109010403030301070b01010900030b0101090003070b000109000a636f696e5f73746f726504636f696e056572726f72067369676e65720f416e696d6553776170506f6f6c563116416e696d6553776170506f6f6c56314c6962726172790e6c69717569646974795f706f6f6c06726f7574657203616d6d09546f6b656e537761700f546f6b656e53776170436f6e66696704737761700a616d6d5f726f7574657208616d6d5f737761700b4d79436f696e53746f726512616e696d65737761705f73746172737761700762616c616e636504436f696e076465706f736974066c3073307431066c3073317430066c3173307431066c3173307432066c3173307433066c3173307434066c3173307435066c3173317430066c3173317432066c3173317433066c3173317434066c3173317435066c3173327430066c3173327431066c3173327433066c3173327434066c3173327435066c3173337430066c3173337431066c3173337432066c3173337434066c3173337435066c3173347430066c3173347431066c3173347432066c3173347433066c3173347435066c3173357430066c3173357431066c3173357432066c3173357433066c3173357434066c3273307431066c3273307432066c3273307433066c3273307434066c3273307435066c3273317430066c3273317432066c3273317433066c3273317434066c3273317435066c3273327430066c3273327431066c3273327433066c3273327434066c3273327435066c3273337430066c3273337431066c3273337432066c3273337434066c3273337435066c3273347430066c3273347431066c3273347432066c3273347433066c3273347435066c3273357430066c3273357431066c3273357432066c3273357433066c3273357434036e65770d6e65775f66726f6d5f6d61696e0d6e65775f66726f6d5f7a65726f047330743104733174301073696d706c655f616e696d65737761701373696d706c655f616e696d65737761705f76320f73696d706c655f73746172737761701273696d706c655f73746172737761705f76321273696d706c655f73746172737761705f76331273746172737761705f616e696d657377617012737761705f61625f6c69717569647377617008737761705f61757810737761705f70616e63616b6573776170127472616e736665725f66726f6d5f6d61696e197472616e736665725f66726f6d5f6d61696e5f736372697074107472616e736665725f746f5f6d61696e177472616e736665725f746f5f6d61696e5f736372697074117472616e736665725f746f5f6f74686572187472616e736665725f746f5f6f746865725f7363726970740877697468647261770c77697468647261775f616c6c0c77697468647261775f616e790576616c7565056d657267650c6765745f7265736572766573116765745f72657365727665735f73697a650765787472616374047a65726f0c64657374726f795f7a65726f0e746f6b656e5f726573657276657321737761705f65786163745f785f746f5f795f6469726563745f65787465726e616c18737761705f65786163745f636f696e5f666f725f636f696e04785f617504795f61751c737761705f65786163745f636f696e5f666f725f636f696e5f6d75740a616464726573735f6f66117065726d697373696f6e5f64656e6965640e6765745f61646d696e5f6461746107636f6d70617265116765745f706f756e646167655f726174650b657874726163745f616c6cd1b58e44ea11ffd326a280c453b080fd8af294298815a00e65b6e2bffc48d6ac000000000000000000000000000000000000000000000000000000000000000116fe2df00ea7dde4a63409201f7f4e536bde7bb7335526a35d05111e68aa322c190d44266241744264b964a37b8f09863167a12d3e70cda39376cfb4e3561e12bd35135844473187163ca197ca93b2ab014370587bb0ed3befff9e902d6bb541c755e4c8d7a6ab6d56f9289d97c43c1c94bde75ec09147c90d35cd1be61c8fb9c7efb4076dbe143cbcd98cfaaa929ecfc8f299203dfff63b95ccb6bfe19850faec42a352cc65eca17a9fa85d0fc602295897ed6b8b8af6a6c79ef490eb8f9eba0308915f0100000000000520d1b58e44ea11ffd326a280c453b080fd8af294298815a00e65b6e2bffc48d6ac126170746f733a3a6d657461646174615f76302e01915f010000000000234552524f525f5448455f4f55545055545f4c4553535f5448414e5f4d494e5f5245435600000201010b01010900000f001700010400010206ffffffffffffffff270101000100010507013c0037003800020201000100010607013c0036000b0038010203010400010206ffffffffffffffff2704010400010206ffffffffffffffff2705010400010206ffffffffffffffff2706010400010206ffffffffffffffff2707010400010206ffffffffffffffff2708010400010206ffffffffffffffff2709010400010206ffffffffffffffff270a010400010206ffffffffffffffff270b010400010206ffffffffffffffff270c010400010206ffffffffffffffff270d010400010206ffffffffffffffff270e010400010206ffffffffffffffff270f010400010206ffffffffffffffff2710010400010206ffffffffffffffff2711010400010206ffffffffffffffff2712010400010206ffffffffffffffff2713010400010206ffffffffffffffff2714010400010206ffffffffffffffff2715010400010206ffffffffffffffff2716010400010206ffffffffffffffff2717010400010206ffffffffffffffff2718010400010206ffffffffffffffff2719010400010206ffffffffffffffff271a010400010206ffffffffffffffff271b010400010206ffffffffffffffff271c010400010206ffffffffffffffff271d010400010206ffffffffffffffff271e010400010206ffffffffffffffff271f010400010206ffffffffffffffff2720010400010206ffffffffffffffff2721010400010206ffffffffffffffff2722010400010206ffffffffffffffff27230104010012f1010b05040638020c2c0c26050d38030c2b0c2e0b2b0c260b2e0c2c0b260b2c0c180c1738040c10350b10350c1f0c1e0a0432000000000000000000000000000000002104660a180a0c180a0a1a0a1f160c110a170a1f180a111a0c0f0a1e0a18180a0c180a0a1a0b111a0c110a0f0a11180a0b180a091a0c2f0a0f0a11180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2f23045e054d0a270c2f0a0f0a11180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c2705480b2f0b0f170a0b180a091a0c040a040b0b180c150b170b09180a15160c240b150b18180b241a320b000000000000000000000000000000170c130a130b0c180c160b1f0b0a180a16160c250b160b1e180b251a320b000000000000000000000000000000170c1a0a1a0a04170b0317010b04340c1407013c000c230a23370038000c1b0a2336000b1438050c200b0804ab010b200b133806320000000000000000000000000000000038070c190c120c2d0c2805b401380632000000000000000000000000000000000b200b1338080c120c190c280c2d0d280b1238010d2d0b1938090b2d0c220a2336000b283801380a0c290b0704cd010b220600000000000000000b290b1a34380b0c0d0c0e05d5010b290b1a340b22060000000000000000380c0c0e0c0d0b0e0b0d0c210c2a0a2336000b2138010b1b0b02160c1c0b23370038000c1d0a1d0a1c2404ea0105ee010b1c0b1d17270b2a380d0224010401001cef010b05040638020c2c0c26050d38030c2b0c2f0b2b0c260b2f0c2c0b260b2c0c190c180b060418380e0c0f0c0e0c0d0522380f0c300c290c2d0b290b2d0b300c0f0c0e0c0d0b0d0b0e0b0f010c11350b11350c1f0c1e0a04320000000000000000000000000000000021047a0a190a0c180a0a1a0a1f160c120a180a1f180a121a0c100a1e0a19180a0c180a0a1a0b121a0c120a100a12180a0b180a091a0c310a100a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c2a0a2a0a3123047205610a2a0c310a100a12180a0b180a091a0a2a1a0b2a1632020000000000000000000000000000001a0c2a055c0b310b10170a0b180a091a0c040a040b0b180c160b180b09180a16160c240b160b19180b241a320b000000000000000000000000000000170c140a140b0c180c170b1f0b0a180a17160c250b170b1e180b251a320b000000000000000000000000000000170a04170b0317010b04340c1507013c000c230a23370038000c1b0a2336000b1538050c200b0804bd010b200b143806320000000000000000000000000000000038070c1a0c130c2e0c2705c601380632000000000000000000000000000000000b200b1438080c130c1a0c270c2e0d270b1338010d2e0b1a38090b2e0c210a2336000b273801380a0c280b2138100c220a2336000b2238010b1b0b02160c1c0b23370038000c1d0a1d0a1c2404e80105ec010b1c0b1d17270b2838110225010401001fe8010b05040638020c2a0c24050d38030c290c2d0b290c240b2d0c2a0b240b2a0c170c160b06041738120c0f0c0e051e38130c260c2b0b260c0e0b2b0c0f0b0e350b0f350c1d0c1c0a0432000000000000000000000000000000002104720a170a0c180a0a1a0a1d160c100a160a1d180a101a0c0d0a1c0a17180a0c180a0a1a0b101a0c100a0d0a10180a0b180a091a0c2e0a0d0a10180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2e23046a05590a270c2e0a0d0a10180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c2705540b2e0b0d170a0b180a091a0c040a040b0b180c140b160b09180a14160c220b140b17180b221a320b000000000000000000000000000000170c120a120b0c180c150b1d0b0a180a15160c230b150b1c180b231a320b000000000000000000000000000000170a04170b0317010b04340c1307013c000c210a21370038000c190a2136000b1338050c1e0b0804b5010b1e0b123806320000000000000000000000000000000038070c180c110c2c0c2805be01380632000000000000000000000000000000000b1e0b1238080c110c180c280c2c0d280b1138010d2c0b1838090b2c0c200a2136000b283801380a0c250b2006000000000000000038140c1f0a2136000b1f38010b190b02160c1a0b21370038000c1b0a1b0a1a2404e10105e5010b1a0b1b17270b25381102260104010023f8010b05040638020c2c0c26050d38030c2b0c2e0b2b0c260b2e0c2c0b260b2c0c170c160b06041a3815353816350c0e0c0d05203817353818350c0e0c0d0b0d0b0e0c1d0c1c0a0432000000000000000000000000000000002104720a170a0c180a0a1a0a1d160c100a160a1d180a101a0c0f0a1c0a17180a0c180a0a1a0b101a0c100a0f0a10180a0b180a091a0c2f0a0f0a10180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c290a290a2f23046a05590a290c2f0a0f0a10180a0b180a091a0a291a0b291632020000000000000000000000000000001a0c2905540b2f0b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c220b140b17180b221a320b000000000000000000000000000000170c120a120b0c180c150b1d0b0a180a15160c230b150b1c180b231a320b000000000000000000000000000000170a04170b0317010b04340c1307010c240a243c000c210a21370038000c190a2136000b1338050c1e0b0804b7010b1e0a123806320000000000000000000000000000000038070c180c110c2d0c2a05c001380632000000000000000000000000000000000b1e0a1238080c110c180c2a0c2d0d2a0b1138010d2d0b1838090b2d0c200a2136000b2a3801380a0c270b240d200d270b12340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381901010b270c250b200c280b250c1f0a2136000b1f38010b190b02160c1a0b21370038000c1b0a1b0a1a2404f10105f5010b1a0b1b17270b28380d02270104010025e8010b05040638020c2b0c25050d38030c2a0c2e0b2a0c250b2e0c2b0b250b2b0c170c160b060417381a0c0e0c0d051e381b0c270c2c0b270b2c0c0e0c0d0b0d0b0e0c1d0c1c0a0432000000000000000000000000000000002104700a170a0c180a0a1a0a1d160c100a160a1d180a101a0c0f0a1c0a17180a0c180a0a1a0b101a0c100a0f0a10180a0b180a091a0c2f0a0f0a10180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c280a280a2f23046805570a280c2f0a0f0a10180a0b180a091a0a281a0b281632020000000000000000000000000000001a0c2805520b2f0b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c220b140b17180b221a320b000000000000000000000000000000170c120a120b0c180c150b1d0b0a180a15160c230b150b1c180b231a320b000000000000000000000000000000170a04170b0317010b04340c1307010c240a243c000c210a21370038000c190a2136000b1338050c1e0b0804b5010b1e0b123806320000000000000000000000000000000038070c180c110c2d0c2905be01380632000000000000000000000000000000000b1e0b1238080c110c180c290c2d0d290b1138010d2d0b1838090b2d0c1f0a2136000b293801380a0c260b240b1f381c0c200a2136000b2038010b190b02160c1a0b21370038000c1b0a1b0a1a2404e10105e5010b1a0b1b17270b26381102280104010027f20138040c0e350b0e350c150c140b06040d38020c2b0c24051438030c290c2e0b290c240b2e0c2b0b240b2b0c1b0c1a0a0432000000000000000000000000000000002104660a150a0c180a0a1a0a1b160c0f0a140a1b180a0f1a0c0d0a1a0a15180a0c180a0a1a0b0f1a0c0f0a0d0a0f180a0b180a091a0c2f0a0d0a0f180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2f23045e054d0a250c2f0a0d0a0f180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c2505480b2f0b0d170a0b180a091a0c040a040b0b180c120b140b09180a12160c210b120b15180b211a320b000000000000000000000000000000170c100a100b0c180c130b1b0b0a180a13160c220b130b1a180b221a320b000000000000000000000000000000170c160a160a04170b0317010b04340c1107010c230a233c000c1f0a1f370038000c170a1f36000b1138050c1c0b0804ac010b1c06000000000000000038060b1034380c0c200c3005b40138060b10340b1c060000000000000000380b0c300c200b300b200c1d0c270b0704c4010b1d0b160b27320000000000000000000000000000000038080c280c2d0c2a0c2c05cd010b2732000000000000000000000000000000000b1d0b1638070c2d0c280c2c0c2a0d2a0b2838010d2c0b2d38090b2a0c1e0b2c0c260a1f36000b1e38010b170b02160c180b1f370038000c190a190a182404e80105ec010b180b1917270b233c0136010b26380902290104010028d90138040c11350b11350c190c180b06040e380e0c0f0c0e0c0d0518380f0c2a0c260c290b260b290b2a0c0f0c0e0c0d0b0d0b0e0b0f010c12350b12350c1e0c1d0a0432000000000000000000000000000000002104700a190a0c180a0a1a0a1e160c130a180a1e180a131a0c100a1d0a19180a0c180a0a1a0b131a0c130a100a13180a0b180a091a0c2b0a100a13180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c280a280a2b23046805570a280c2b0a100a13180a0b180a091a0a281a0b281632020000000000000000000000000000001a0c2805520b2b0b10170a0b180a091a0c040a040b0b180c160b180b09180a16160c240b160b19180b241a320b000000000000000000000000000000170c140a140b0c180c170b1e0b0a180a17160c250b170b1d180b251a320b000000000000000000000000000000170a04170b0317010b04340c1507013c000c220a22370038000c1a0a2236000b1538050c1f0b0804b2010b1f06000000000000000038060b1434380c0c230c2c05ba0138060b14340b1f060000000000000000380b0c2c0c230b2c0b230c200c270b2038100c210a2236000b2138010b1a0b02160c1b0b22370038000c1c0a1c0a1b2404d20105d6010b1b0b1c17270b273811022a0104010029d20138040c0f350b0f350c170c160b06040d38120c100c0e051438130c240c270b240c0e0b270c100b0e350b10350c1c0c1b0a0432000000000000000000000000000000002104680a170a0c180a0a1a0a1c160c110a160a1c180a111a0c0d0a1b0a17180a0c180a0a1a0b111a0c110a0d0a11180a0b180a091a0c280a0d0a11180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a28230460054f0a250c280a0d0a11180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c25054a0b280b0d170a0b180a091a0c040a040b0b180c140b160b09180a14160c220b140b17180b221a320b000000000000000000000000000000170c120a120b0c180c150b1c0b0a180a15160c230b150b1b180b231a320b000000000000000000000000000000170a04170b0317010b04340c1307013c000c200a20370038000c180a2036000b1338050c1d0b0804aa010b1d06000000000000000038060b1234380c0c210c2905b20138060b12340b1d060000000000000000380b0c290c210b290b210c1e0c260b1e06000000000000000038140c1f0a2036000b1f38010b180b02160c190b20370038000c1a0a1a0a192404cb0105cf010b190b1a17270b263811022b010401002ae20138040c10350b10350c170c160b0604103815353816350c0e0c0d05163817353818350c0e0c0d0b0d0b0e0c1c0c1b0a0432000000000000000000000000000000002104680a170a0c180a0a1a0a1c160c110a160a1c180a111a0c0f0a1b0a17180a0c180a0a1a0b111a0c110a0f0a11180a0b180a091a0c290a0f0a11180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c260a260a29230460054f0a260c290a0f0a11180a0b180a091a0a261a0b261632020000000000000000000000000000001a0c26054a0b290b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c220b140b17180b221a320b000000000000000000000000000000170c120a120b0c180c150b1c0b0a180a15160c230b150b1b180b231a320b000000000000000000000000000000170a04170b0317010b04340c1307010c240a243c000c200a20370038000c180a2036000b1338050c1d0b0804ac010b1d06000000000000000038060a1234380c0c210c2a05b40138060a12340b1d060000000000000000380b0c2a0c210b2a0b210c1e0c270b240d1e0d270b12340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381901010b270c250b1e0c280b250c1f0a2036000b1f38010b180b02160c190b20370038000c1a0a1a0a192404db0105df010b190b1a17270b28380d022c010401002bd20138040c10350b10350c170c160b06040d381a0c0e0c0d0514381b0c250c280b250b280c0e0c0d0b0d0b0e0c1c0c1b0a0432000000000000000000000000000000002104660a170a0c180a0a1a0a1c160c110a160a1c180a111a0c0f0a1b0a17180a0c180a0a1a0b111a0c110a0f0a11180a0b180a091a0c290a0f0a11180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c260a260a2923045e054d0a260c290a0f0a11180a0b180a091a0a261a0b261632020000000000000000000000000000001a0c2605480b290b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c220b140b17180b221a320b000000000000000000000000000000170c120a120b0c180c150b1c0b0a180a15160c230b150b1b180b231a320b000000000000000000000000000000170a04170b0317010b04340c1307010c240a243c000c200a20370038000c180a2036000b1338050c1d0b0804aa010b1d06000000000000000038060b1234380c0c210c2a05b20138060b12340b1d060000000000000000380b0c2a0c210b2a0b210c1e0c270b240b1e381c0c1f0a2036000b1f38010b180b02160c190b20370038000c1a0a1a0a192404cb0105cf010b190b1a17270b273811022d010401002cec010b050407380e0c0f0c0e0c0d0511380f0c310c240c2c0b240b2c0b310c0f0c0e0c0d0b0d0b0e0b0f010c11350b11350c170c160b06042138020c2e0c27052838030c2a0c300b2a0c270b300c2e0b270b2e0c1d0c1c0a04320000000000000000000000000000000021047a0a170a0c180a0a1a0a1d160c120a160a1d180a121a0c100a1c0a17180a0c180a0a1a0b121a0c120a100a12180a0b180a091a0c320a100a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c280a280a3223047205610a280c320a100a12180a0b180a091a0a281a0b281632020000000000000000000000000000001a0c28055c0b320b10170a0b180a091a0c040a040b0b180c140b160b09180a14160c210b140b17180b211a0b0c180c150b1d0b0a180a15160c220b150b1c180b221a0c180a180a04170b0317010b04340c1307010c230a233c000c200a20370038000c190a2036000b133805381d0c1e380a0c250b0704be010b1e0b180b25320000000000000000000000000000000038080c290c2f0c2b0c2d05c7010b2532000000000000000000000000000000000b1e0b1838070c2f0c290c2d0c2b0d2b0b2938010d2d0b2f38090b2b0c1f0b2d0c260a2036000b1f38010b190b02160c1a0b20370038000c1b0a1b0a1a2404e20105e6010b1a0b1b17270b233c0136010b263809022e010401002dd5010b050407380e0c0f0c0e0c0d0511380f0c2b0c260c2a0b260b2a0b2b0c0f0c0e0c0d0b0d0b0e0b0f010c13350b13350c1a0c1938040c14350b14350c200c1f0a0432000000000000000000000000000000002104700a1a0a0c180a0a1a0a20160c150a190a20180a151a0c120a1f0a1a180a0c180a0a1a0b151a0c150a120a15180a0b180a091a0c2c0a120a15180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c290a290a2c23046805570a290c2c0a120a15180a0b180a091a0a291a0b291632020000000000000000000000000000001a0c2905520b2c0b12170a0b180a091a0c040a040b0b180c170b190b09180a17160c240b170b1a180b241a0b0c180c180b200b0a180a18160c250b180b1f180b251a0c1b0a1b0a04170b0317010b04340c1607013c000c230a23370038000c1c0a2336000b163805381d0c21380a0c270b0704b1010b210600000000000000000b270b1b34380b0c100c1105b9010b270b1b340b21060000000000000000380c0c110c100b110b100c220c280a2336000b2238010b1c0b02160c1d0b23370038000c1e0a1e0a1d2404ce0105d2010b1d0b1e17270b28380d022f010401002ec6010b050407380e0c0f0c0e0c0d0511380f0c280c230c260b230b260b280c0f0c0e0c0d0b0d0b0e0b0f010c12350b12350c190c180b06042138120c130c11052838130c240c270b240c110b270c130b11350b13350c1e0c1d0a04320000000000000000000000000000000021047c0a190a0c180a0a1a0a1e160c140a180a1e180a141a0c100a1d0a19180a0c180a0a1a0b141a0c140a100a14180a0b180a091a0c290a100a14180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2923047405630a250c290a100a14180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c25055e0b290b10170a0b180a091a0c040a040b0b180c160b180b09180a16160c210b160b19180b211a0b0c180c170b1e0b0a180a17160c220b170b1d180b221a0a04170b0317010b04340c1507013c000c200a20370038000c1a0a2036000b153805381d06000000000000000038140c1f0a2036000b1f38010b1a0b02160c1b0b20370038000c1c0a1c0a1b2404c10105c5010b1b0b1c17270230010401002fde010b050407380e0c0f0c0e0c0d0511380f0c2c0c270c2b0b270b2b0b2c0c0f0c0e0c0d0b0d0b0e0b0f010c13350b13350c1a0c190b0604243815353816350c110c10052a3817353818350c110c100b100b110c1f0c1e0a04320000000000000000000000000000000021047c0a1a0a0c180a0a1a0a1f160c140a190a1f180a141a0c120a1e0a1a180a0c180a0a1a0b141a0c140a120a14180a0b180a091a0c2d0a120a14180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c2a0a2a0a2d23047405630a2a0c2d0a120a14180a0b180a091a0a2a1a0b2a1632020000000000000000000000000000001a0c2a055e0b2d0b12170a0b180a091a0c040a040b0b180c170b190b09180a17160c230b170b1a180b231a0c150a150b0c180c180b1f0b0a180a18160c240b180b1e180b241a0a04170b0317010b04340c1607010c250a253c000c220a22370038000c1b0a2236000b163805381d0c20380a0c280b250d200d280b15340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381901010b280c260b200c290b260c210a2236000b2138010b1b0b02160c1c0b22370038000c1d0a1d0a1c2404d70105db010b1c0b1d17270b29380d02310104010030c8010b050407380e0c0f0c0e0c0d0511380f0c2a0c250c280b250b280b2a0c0f0c0e0c0d0b0d0b0e0b0f010c13350b13350c190c180b060421381a0c110c100528381b0c260c290b260b290c110c100b100b110c1e0c1d0a04320000000000000000000000000000000021047a0a190a0c180a0a1a0a1e160c140a180a1e180a141a0c120a1d0a19180a0c180a0a1a0b141a0c140a120a14180a0b180a091a0c2b0a120a14180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2b23047205610a270c2b0a120a14180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c27055c0b2b0b12170a0b180a091a0c040a040b0b180c160b180b09180a16160c220b160b19180b221a0b0c180c170b1e0b0a180a17160c230b170b1d180b231a0a04170b0317010b04340c1507010c240a243c000c210a21370038000c1a0a2136000b153805381d0c1f0b240b1f381c0c200a2136000b2038010b1a0b02160c1b0b21370038000c1c0a1c0a1b2404c30105c7010b1b0b1c172702320104010031e5010b05040638120c0f0c0e050d38130c220c2a0b220c0e0b2a0c0f0b0e350b0f350c150c140b06041938020c2c0c23052038030c280c2e0b280c230b2e0c2c0b230b2c0c1b0c1a0a0432000000000000000000000000000000002104720a150a0c180a0a1a0a1b160c100a140a1b180a101a0c0d0a1a0a15180a0c180a0a1a0b101a0c100a0d0a10180a0b180a091a0c2f0a0d0a10180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2f23046a05590a250c2f0a0d0a10180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c2505540b2f0b0d170a0b180a091a0c040a040b0b180c120b140b09180a12160c1f0b120b15180b1f1a0b0c180c130b1b0b0a180a13160c200b130b1a180b201a0c160a160a04170b0317010b04340c1107010c210a213c000c1e0a1e370038000c170a1e36000b113805060000000000000000381e0c1d380a0c260b0704b7010b1d0b160b26320000000000000000000000000000000038080c270c2d0c290c2b05c0010b2632000000000000000000000000000000000b1d0b1638070c2d0c270c2b0c290d290b2738010d2b0b2d38090b290c1c0b2b0c240a1e36000b1c38010b170b02160c180b1e370038000c190a190a182404db0105df010b180b1917270b213c0136010b24380902330104010032ce010b05040638120c110c10050d38130c240c280b240c100b280c110b10350b11350c180c1738040c12350b12350c1e0c1d0a0432000000000000000000000000000000002104680a180a0c180a0a1a0a1e160c130a170a1e180a131a0c0f0a1d0a18180a0c180a0a1a0b131a0c130a0f0a13180a0b180a091a0c290a0f0a13180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a29230460054f0a250c290a0f0a13180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c25054a0b290b0f170a0b180a091a0c040a040b0b180c150b170b09180a15160c220b150b18180b221a0b0c180c160b1e0b0a180a16160c230b160b1d180b231a0c190a190a04170b0317010b04340c1407013c000c210a21370038000c1a0a2136000b143805060000000000000000381e0c20380a0c260b0704aa010b200600000000000000000b260b1934380b0c0d0c0e05b2010b260b19340b20060000000000000000380c0c0e0c0d0b0e0b0d0c1f0c270a2136000b1f38010b1a0b02160c1b0b21370038000c1c0a1c0a1b2404c70105cb010b1b0b1c17270b27380d0234010401002ec6010b05040638120c120c11050d38130c230c260b230c110b260c120b11350b12350c190c180b06041a380e0c0f0c0e0c0d0524380f0c280c240c270b240b270b280c0f0c0e0c0d0b0d0b0e0b0f010c13350b13350c1e0c1d0a04320000000000000000000000000000000021047c0a190a0c180a0a1a0a1e160c140a180a1e180a141a0c100a1d0a19180a0c180a0a1a0b141a0c140a100a14180a0b180a091a0c290a100a14180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2923047405630a250c290a100a14180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c25055e0b290b10170a0b180a091a0c040a040b0b180c160b180b09180a16160c210b160b19180b211a0b0c180c170b1e0b0a180a17160c220b170b1d180b221a0a04170b0317010b04340c1507013c000c200a20370038000c1a0a2036000b153805060000000000000000381e38100c1f0a2036000b1f38010b1a0b02160c1b0b20370038000c1c0a1c0a1b2404c10105c5010b1b0b1c172702350104010033d7010b05040638120c110c10050d38130c250c290b250c100b290c110b10350b11350c180c170b06041c3815353816350c0e0c0d05223817353818350c0e0c0d0b0d0b0e0c1d0c1c0a0432000000000000000000000000000000002104740a180a0c180a0a1a0a1d160c120a170a1d180a121a0c0f0a1c0a18180a0c180a0a1a0b121a0c120a0f0a12180a0b180a091a0c2a0a0f0a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c260a260a2a23046c055b0a260c2a0a0f0a12180a0b180a091a0a261a0b261632020000000000000000000000000000001a0c2605560b2a0b0f170a0b180a091a0c040a040b0b180c150b170b09180a15160c210b150b18180b211a0c130a130b0c180c160b1d0b0a180a16160c220b160b1c180b221a0a04170b0317010b04340c1407010c230a233c000c200a20370038000c190a2036000b143805060000000000000000381e0c1f380a0c270b230d1f0d270b13340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381901010b270c240b1f0c280b240c1e0a2036000b1e38010b190b02160c1a0b20370038000c1b0a1b0a1a2404d00105d4010b1a0b1b17270b28380d02360104010034c1010b05040638120c110c10050d38130c230c260b230c100b260c110b10350b11350c170c160b060419381a0c0e0c0d0520381b0c240c270b240b270c0e0c0d0b0d0b0e0c1c0c1b0a0432000000000000000000000000000000002104720a170a0c180a0a1a0a1c160c120a160a1c180a121a0c0f0a1b0a17180a0c180a0a1a0b121a0c120a0f0a12180a0b180a091a0c280a0f0a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2823046a05590a250c280a0f0a12180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c2505540b280b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c200b140b17180b201a0b0c180c150b1c0b0a180a15160c210b150b1b180b211a0a04170b0317010b04340c1307010c220a223c000c1f0a1f370038000c180a1f36000b133805060000000000000000381e0c1e0b220b1e381c0c1d0a1f36000b1d38010b180b02160c190b1f370038000c1a0a1a0a192404bc0105c0010b190b1a172702370104010035f9010b0504093815353816350c0e0c0d050f3817353818350c0e0c0d0b0d0b0e0c150c140b06041938020c2c0c24052038030c2a0c2f0b2a0c240b2f0c2c0b240b2c0c1b0c1a0a0432000000000000000000000000000000002104720a150a0c180a0a1a0a1b160c100a140a1b180a101a0c0f0a1a0a15180a0c180a0a1a0b101a0c100a0f0a10180a0b180a091a0c300a0f0a10180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c260a260a3023046a05590a260c300a0f0a10180a0b180a091a0a261a0b261632020000000000000000000000000000001a0c2605540b300b0f170a0b180a091a0c040a040b0b180c120b140b09180a12160c200b120b15180b201a320b000000000000000000000000000000170b0c180c130b1b0b0a180a13160c210b130b1a180b211a320b000000000000000000000000000000170c160a160a04170b0317010b04340c1107010c220a223c000c1f0a1f370038000c170a1f36000a1138050c1c38060c270a220d1c0d270b11340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381f01010b270c230b1c0c280b230c1e0b0704cb010b1e0b160b28320000000000000000000000000000000038080c290c2e0c2b0c2d05d4010b2832000000000000000000000000000000000b1e0b1638070c2e0c290c2d0c2b0d2b0b2938010d2d0b2e38090b2b0c1d0b2d0c250a1f36000b1d38010b170b02160c180b1f370038000c190a190a182404ef0105f3010b180b1917270b223c0136010b25380902380104010036e4010b0504093815353816350c0e0c0d050f3817353818350c0e0c0d0b0d0b0e0c180c1738040c12350b12350c1e0c1d0a0432000000000000000000000000000000002104680a180a0c180a0a1a0a1e160c130a170a1e180a131a0c110a1d0a18180a0c180a0a1a0b131a0c130a110a13180a0b180a091a0c2b0a110a13180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2b230460054f0a270c2b0a110a13180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c27054a0b2b0b11170a0b180a091a0c040a040b0b180c150b170b09180a15160c230b150b18180b231a320b000000000000000000000000000000170b0c180c160b1e0b0a180a16160c240b160b1d180b241a320b000000000000000000000000000000170c190a190a04170b0317010b04340c1407010c250a253c000c220a22370038000c1a0a2236000a1438050c1f38060c280b250d1f0d280b14340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381f01010b280c260b1f0c290b260c210b0704c0010b210600000000000000000b290b1934380b0c0f0c1005c8010b290b19340b21060000000000000000380c0c100c0f0b100b0f0c200c2a0a2236000b2038010b1a0b02160c1b0b22370038000c1c0a1c0a1b2404dd0105e1010b1b0b1c17270b2a380d02390104010037e0010b0504093815353816350c0e0c0d050f3817353818350c0e0c0d0b0d0b0e0c190c180b06041a380e0c110c100c0f0524380f0c2b0c260c2a0b260b2a0b2b0c110c100c0f0b0f0b100b11010c13350b13350c1e0c1d0a04320000000000000000000000000000000021047c0a190a0c180a0a1a0a1e160c140a180a1e180a141a0c120a1d0a19180a0c180a0a1a0b141a0c140a120a14180a0b180a091a0c2c0a120a14180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c290a290a2c23047405630a290c2c0a120a14180a0b180a091a0a291a0b291632020000000000000000000000000000001a0c29055e0b2c0b12170a0b180a091a0c040a040b0b180c160b180b09180a16160c220b160b19180b221a320b000000000000000000000000000000170b0c180c170b1e0b0a180a17160c230b170b1d180b231a320b000000000000000000000000000000170a04170b0317010b04340c1507010c240a243c000c210a21370038000c1a0a2136000a1538050c1f38060c270b240d1f0d270b15340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381f01010b270c250b1f0c280b2538100c200a2136000b2038010b1a0b02160c1b0b21370038000c1c0a1c0a1b2404d90105dd010b1b0b1c17270b283811023a0104010038d9010b0504093815353816350c0e0c0d050f3817353818350c0e0c0d0b0d0b0e0c170c160b06041938120c110c10052038130c240c280b240c100b280c110b10350b11350c1c0c1b0a0432000000000000000000000000000000002104740a170a0c180a0a1a0a1c160c120a160a1c180a121a0c0f0a1b0a17180a0c180a0a1a0b121a0c120a0f0a12180a0b180a091a0c290a0f0a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2923046c055b0a250c290a0f0a12180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c2505560b290b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c200b140b17180b201a320b000000000000000000000000000000170b0c180c150b1c0b0a180a15160c210b150b1b180b211a320b000000000000000000000000000000170a04170b0317010b04340c1307010c220a223c000c1f0a1f370038000c180a1f36000a1338050c1d38060c260b220d1d0d260b13340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381f01010b260c230b1d0c270b2306000000000000000038140c1e0a1f36000b1e38010b180b02160c190b1f370038000c1a0a1a0a192404d20105d6010b190b1a17270b273811023b0104010039d9010b0504093815353816350c0e0c0d050f3817353818350c0e0c0d0b0d0b0e0c170c160b060419381a0c100c0f0520381b0c250c290b250b290c100c0f0b0f0b100c1c0c1b0a0432000000000000000000000000000000002104720a170a0c180a0a1a0a1c160c120a160a1c180a121a0c110a1b0a17180a0c180a0a1a0b121a0c120a110a12180a0b180a091a0c2a0a110a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2a23046a05590a270c2a0a110a12180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c2705540b2a0b11170a0b180a091a0c040a040b0b180c140b160b09180a14160c210b140b17180b211a320b000000000000000000000000000000170b0c180c150b1c0b0a180a15160c220b150b1b180b221a320b000000000000000000000000000000170a04170b0317010b04340c1307010c230a233c000c200a20370038000c180a2036000a1338050c1d38060c280a230d1d0d280b13340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381f01010b280c240b1d0c260b240c1e0b230b1e381c0c1f0a2036000b1f38010b180b02160c190b20370038000c1a0a1a0a192404d20105d6010b190b1a17270b263811023c010401003ae5010b050406381a0c0e0c0d050d381b0c230c2b0b230b2b0c0e0c0d0b0d0b0e0c150c140b06041738020c2d0c26051e38030c290c2f0b290c260b2f0c2d0b260b2d0c1b0c1a0a0432000000000000000000000000000000002104700a150a0c180a0a1a0a1b160c100a140a1b180a101a0c0f0a1a0a15180a0c180a0a1a0b101a0c100a0f0a10180a0b180a091a0c300a0f0a10180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a3023046805570a270c300a0f0a10180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c2705520b300b0f170a0b180a091a0c040a040b0b180c120b140b09180a12160c200b120b15180b201a0b0c180c130b1b0b0a180a13160c210b130b1a180b211a0c160a160a04170b0317010b04340c1107010c220a223c000c1f0a1f370038000c170a1f36000b1138050c1c0a220b1c38200c1e380a0c240b0704b7010b1e0b160b24320000000000000000000000000000000038080c280c2e0c2a0c2c05c0010b2432000000000000000000000000000000000b1e0b1638070c2e0c280c2c0c2a0d2a0b2838010d2c0b2e38090b2a0c1d0b2c0c250a1f36000b1d38010b170b02160c180b1f370038000c190a190a182404db0105df010b180b1917270b223c0136010b253809023d010401003bd0010b050406381a0c0e0c0d050d381b0c260c2a0b260b2a0c0e0c0d0b0d0b0e0c180c1738040c12350b12350c1e0c1d0a0432000000000000000000000000000000002104660a180a0c180a0a1a0a1e160c130a170a1e180a131a0c110a1d0a18180a0c180a0a1a0b131a0c130a110a13180a0b180a091a0c2b0a110a13180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2b23045e054d0a270c2b0a110a13180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c2705480b2b0b11170a0b180a091a0c040a040b0b180c150b170b09180a15160c230b150b18180b231a0b0c180c160b1e0b0a180a16160c240b160b1d180b241a0c190a190a04170b0317010b04340c1407010c250a253c000c220a22370038000c1a0a2236000b1438050c1f0b250b1f38200c21380a0c280b0704ac010b210600000000000000000b280b1934380b0c0f0c1005b4010b280b19340b21060000000000000000380c0c100c0f0b100b0f0c200c290a2236000b2038010b1a0b02160c1b0b22370038000c1c0a1c0a1b2404c90105cd010b1b0b1c17270b29380d023e010401003cc8010b050406381a0c0e0c0d050d381b0c250c280b250b280c0e0c0d0b0d0b0e0c190c180b060418380e0c110c100c0f0522380f0c2a0c260c290b260b290b2a0c110c100c0f0b0f0b100b11010c13350b13350c1e0c1d0a04320000000000000000000000000000000021047a0a190a0c180a0a1a0a1e160c140a180a1e180a141a0c120a1d0a19180a0c180a0a1a0b141a0c140a120a14180a0b180a091a0c2b0a120a14180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c270a270a2b23047205610a270c2b0a120a14180a0b180a091a0a271a0b271632020000000000000000000000000000001a0c27055c0b2b0b12170a0b180a091a0c040a040b0b180c160b180b09180a16160c220b160b19180b221a0b0c180c170b1e0b0a180a17160c230b170b1d180b231a0a04170b0317010b04340c1507010c240a243c000c210a21370038000c1a0a2136000b1538050c1f0b240b1f382038100c200a2136000b2038010b1a0b02160c1b0b21370038000c1c0a1c0a1b2404c30105c7010b1b0b1c1727023f010401003dc1010b050406381a0c0e0c0d050d381b0c230c260b230b260c0e0c0d0b0d0b0e0c170c160b06041738120c110c10051e38130c240c270b240c100b270c110b10350b11350c1c0c1b0a0432000000000000000000000000000000002104720a170a0c180a0a1a0a1c160c120a160a1c180a121a0c0f0a1b0a17180a0c180a0a1a0b121a0c120a0f0a12180a0b180a091a0c280a0f0a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c250a250a2823046a05590a250c280a0f0a12180a0b180a091a0a251a0b251632020000000000000000000000000000001a0c2505540b280b0f170a0b180a091a0c040a040b0b180c140b160b09180a14160c200b140b17180b201a0b0c180c150b1c0b0a180a15160c210b150b1b180b211a0a04170b0317010b04340c1307010c220a223c000c1f0a1f370038000c180a1f36000b1338050c1d0b220b1d382006000000000000000038140c1e0a1f36000b1e38010b180b02160c190b1f370038000c1a0a1a0a192404bc0105c0010b190b1a17270240010401003ed7010b050406381a0c0e0c0d050d381b0c260c2a0b260b2a0c0e0c0d0b0d0b0e0c180c170b06041a3815353816350c100c0f05203817353818350c100c0f0b0f0b100c1d0c1c0a0432000000000000000000000000000000002104720a180a0c180a0a1a0a1d160c120a170a1d180a121a0c110a1c0a18180a0c180a0a1a0b121a0c120a110a12180a0b180a091a0c2b0a110a12180a0b180a091a32020000000000000000000000000000001a3201000000000000000000000000000000160c290a290a2b23046a05590a290c2b0a110a12180a0b180a091a0a291a0b291632020000000000000000000000000000001a0c2905540b2b0b11170a0b180a091a0c040a040b0b180c150b170b09180a15160c220b150b18180b221a0c130a130b0c180c160b1d0b0a180a16160c230b160b1c180b231a0a04170b0317010b04340c1407010c240a243c000c210a21370038000c190a2136000b1438050c1e0a240b1e38200c20380a0c270b240d200d270b13340600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381901010b270c250b200c280b250c1f0a2136000b1f38010b190b02160c1a0b21370038000c1b0a1b0a1a2404d00105d4010b1a0b1b17270b28380d02410300003f070b0139000c020b000b023f0002420104003f140a00116a0701210406050b0b0001060000000000000000116b270a000b01382139000c020b000b023f0002430104003f120a00116a0701210406050b0b0001060000000000000000116b27380a39000c010b000b013f000244010400010206ffffffffffffffff2745010400010206ffffffffffffffff27460104000102060000000000000000274701040100415b0b00116a0c030a030701210408050b060000000000000000116b270a033c000c070a0736000b0138050c0a0e0a38000c04116d0101010c0e38040c0d0c0c0b04350610270000000000000b0e1735180c050a050b0d35180c0b0b0c353210270000000000000000000000000000180b05160c090b0b0b091a340c060a060b0226043c05400b07010700273822044a0b0a06000000000000000038060b06380c0c080c0f055138060b060b0a060000000000000000380b0c0f0c080b0736000b0f38010b033c0136010b0838090248010400010206000000000000000027490104000102060000000000000000274a010401004493010b00116a0c040a040701210408050b060000000000000000116b270b03044f38020c140c1238230c0d0c0f0a01350a0d0b0f1735180c050b120b0d35180a05160c0b0b050b14180b0b1a0c070a070b023524042e05300700270a043c000c090a0936000b0138050b073806320000000000000000000000000000000038070c1c0c180c1a0c160d160b1838010d1a0b1c38090b0936000b1638010b043c0136010b1a380905920138020c130c1538230c0e0c100a01350a0e0b101735180c060b130b0e35180a06160c0c0b060b15180b0c1a0c080a080b023524047005720700270a043c010c0a0a0a36010b0138240c11380a32000000000000000000000000000000000b110b0838070c1d0c190c1b0c170d170b1938010d1b0b1d38090b0a36010b1b38090b043c0036000b173801024b010400010206ffffffffffffffff274c0104010045650b00116a0c0d0a0d0701210408050b060000000000000000116b270b08041138120c0b0c0a051838130c160c170b160c0a0b170c0b0b0a350b0b350c100c0f0b030b07180c0e0b0f0b06180a0e160c140b0e0b10180b141a340c0c0a0c0a0526043405380b050b0c17270a0d3c0036000b0438050c150b0904480b1506000000000000000038060b0c38250c130c18054f38060b0c0b1506000000000000000038260c180c130b180b130c1238110e1238270c110a110a0524045b055f0b050b1117270b0d3c0136010b123809024d0104010046650b00116a0c0d0a0d0701210408050b060000000000000000116b270b0804143815353816350c0b0c0a051a3817353818350c0b0c0a0b0a0b0b0c100c0f0b030b07180c0e0b0f0b06180a0e160c140b0e0b10180b141a340c0c0a0c0a0526043405380b050b0c17270a0d3c0036000a0438050c1238060c160a0d0d120d160b040600000000000000000932000000000000000000000000000000003200000000000000000000000000000000381f01010b160c150b120c170b150c130e1338270c110a110a05240459055d0b050b1117270b0d3c0136010b1338090b173811024e0104010047590b00116a0c0f0a0f0701210408050b060000000000000000116b270b080412380e0c0c0c0b0c0a051c380f0c180c160c170b160b170b180c0c0c0b0c0a0b0a0b0b0b0c010c0d350b0d350c120c110b030b07180c100b110b06180a10160c150b100b12180b151a340c0e0a0e0a0526043c05400b050b0e17270a0f3c0036000b043805381d0c140e1438270c130a130a0524044f05530b050b1317270b0f3c0136010b143809024f03000100030a0b000b0138210c0207013c0036000b02380102500004010026170a00116a0c020a020701210408050d0b0001060000000000000000116b270b000b0138210c030b023c0036000b033801025103000100260c07010c010a013c0036000b0038050c020b010b02382802520004010026150b00116a0c020a020701210408050b060000000000000000116b270a023c0036000b0138050c030b020b033828025303000100030a07013c0036000b0138050c020b000b02382802540004010026150b00116a0c030a030701210408050b060000000000000000116b270b033c0036000b0238050c040b010b043828025503000100010607013c0036000b003805025603000100010507013c0036003829025703000100491707013c000c030a03370038000c020a000b022404110b0336000b0038050c0105150b03360038290c010b01020000000f001700"; + let res = run_binary_test("sample_coin_store", code); + assert!(res.is_ok(), "{:?}", res) +} + +#[cfg(feature = "address32")] +#[test] +fn sample_liquidity_pool() { + let code = "a11ceb0b050000000e0100240224ab0103cf01b6030485056405e905eb0507d40bde0d08b2196006921ab80110ca1bd8070aa223ef010b9125160ca725c9120df0372a0e9a38280000010101020103010401050106000700080009000a000b000c000d000e000f021002110012080300010001000100130003000100010001001406030001000100010015060300010001000100160803000100010001001706030001000100010018060300010001000100190800001a0603000100010001001b0603000100010001001c0603000100010001001d06030001000100010220040100010d210003000100010001033804010601024f05010001025105010001015b0600105e0700027305010001057407001185010700001e00010100001f01010300000000220203030000000023040503000000002401060300000000250107030000000026010403000000002701040300000000280107030000000029010403000000002a010403000000002b080100002c010903000000002d010903000000002e030203000000002f0a0b01000030050103000000003108010300000000320c010300000000330c010300000000340d010300000000350e030300000000360d0103000000085f010901000f6011120010611314000862010901001063151200106407120010651612000766010902000002671c0701000768011501000e691e0700026a1f200100022221010100036b230101060a6c010100046d0828000c6e0827000b2b0801000a2b0801000e6f0415000e7015070002712a010100022e2b2001000e722e070007750101010008760101010001773334000778013503000000022b36370100027938010100027a011401000e7b140700027c012001000b7d010701000b7e0107000931080103000000017f083a01060b80010128000b81010701000b82010701000983014101030000000684010107001186010444001187014415000e88010b150017101a101e1a01181f1b201b1f101f1d2210221d1618231b2422051808182c102c1d2d1b242c0f300030141824312f102f1d30303218331b341b17303510351d3710371d38303a183b393b2c3b223b3b3b313b3c3b3d3b3e2439243e243d3f18243b243c0603030404040400010b0c010b0d03090009010902020b0c0109000b0c010901020303030b0c0109000b0c0109010b010309000901090203040403010301060c010105030303030302040402060c0303070b04030900090109020303040b0c010900030b0c0109010307020208120812081204081201090004040304030108120206081206081201020104020812081201060b0403090009010902030900090109020b0103070b000309000901090204070b04030900090109020b0c01090003030b0c01090103030209000901010b0d0309000901090201060b0c0109000109010304040402070b0c01090003010b0c010900020b0c010900060b10010900010b050309000901090202070b0e01090009000601070b040309000901090203030b0c0109000b0c01090104030404060b040309000901090203060b0403090009010902030301081101050e0303070b0003090009010902030b0c010b0d0309000901090204070b04030900090109020303030303030302070b0c0109000b0c0109000203060b0f010900010b030309000901090206040404040404030303030b01070b0003090009010902070b04030900090109020303040303030403010902010b02030900090109020b0b00030900090109020b10010b0d030900090109020b13010b0d030900090109020b0f010b0d03090009010902081408140b04030900090109020c060807030301060811010c020814081405060c081408140201030b100109000b130109000b0f010900010b13010900010b0803090009010902010b0e010900010b0903090009010902010b0603090009010902010b0b03090009010902010b0a0309000901090202070b0003090009010902070b040309000901090208030303030b0c010900030b0c0109010303050b0c0109000b0c010901100103030303070b0e010b0903090009010902070b0003090009010902070b04030900090109020304030b0c0109000304030b0c01090108010103070b0003090009010902030404040108150e6c69717569646974795f706f6f6c076163636f756e7404636f696e056576656e74067369676e657206737472696e670974696d657374616d700b636f696e5f68656c706572066375727665730b64616f5f73746f7261676509656d657267656e63790d676c6f62616c5f636f6e6669670a6c705f6163636f756e74076c705f636f696e046d6174680c737461626c655f6375727665047532353607757136347836340b4576656e747353746f726509466c6173686c6f616e0e466c6173686c6f616e4576656e74134c697175696469747941646465644576656e740d4c6971756964697479506f6f6c154c697175696469747952656d6f7665644576656e74124f7261636c65557064617465644576656e7415506f6f6c4163636f756e744361706162696c69747910506f6f6c437265617465644576656e7409537761704576656e741155706461746544414f4665654576656e740e5570646174654665654576656e741c6173736572745f6c705f76616c75655f69735f696e63726561736564146173736572745f706f6f6c5f756e6c6f636b656404436f696e024c50046275726e09666c6173686c6f616e156765745f63756d756c61746976655f7072696365730b6765745f64616f5f666565136765745f64616f5f666565735f636f6e666967136765745f646563696d616c735f7363616c6573076765745f6665650f6765745f666565735f636f6e666967116765745f72657365727665735f73697a650a696e697469616c697a650e69735f706f6f6c5f6578697374730e69735f706f6f6c5f6c6f636b6564046d696e741e6e65775f72657365727665735f61667465725f666565735f7363616c65640d7061795f666c6173686c6f616e0872656769737465720b7365745f64616f5f666565077365745f6665651073706c69745f6665655f746f5f64616f04737761700d7570646174655f6f7261636c6513706f6f6c5f637265617465645f68616e646c650b4576656e7448616e646c65166c69717569646974795f61646465645f68616e646c65186c69717569646974795f72656d6f7665645f68616e646c650b737761705f68616e646c6510666c6173686c6f616e5f68616e646c65156f7261636c655f757064617465645f68616e646c65117570646174655f6665655f68616e646c65157570646174655f64616f5f6665655f68616e646c6506785f6c6f616e06795f6c6f616e04785f696e05785f6f757404795f696e05795f6f75740b61646465645f785f76616c0b61646465645f795f76616c126c705f746f6b656e735f72656365697665640e636f696e5f785f726573657276650e636f696e5f795f72657365727665146c6173745f626c6f636b5f74696d657374616d70176c6173745f70726963655f785f63756d756c6174697665176c6173745f70726963655f795f63756d756c61746976650b6c705f6d696e745f6361700e4d696e744361706162696c6974790b6c705f6275726e5f6361700e4275726e4361706162696c69747907785f7363616c6507795f7363616c65066c6f636b6564036665650764616f5f6665650e72657475726e65645f785f76616c0e72657475726e65645f795f76616c106c705f746f6b656e735f6275726e65640a7369676e65725f636170105369676e65724361706162696c6974790763726561746f72076e65775f66656504553235360969735f737461626c65086c705f76616c756507636f6d706172650f69735f756e636f7272656c617465640966726f6d5f753132380866726f6d5f753634036d756c0969735f736f727465640576616c756506737570706c790c6d756c5f6469765f7531323807657874726163740a656d69745f6576656e74136173736572745f6e6f5f656d657267656e63790a616464726573735f6f661372657472696576655f7369676e65725f6361700b6d756c5f746f5f753132380473717274056d65726765076d756c5f64697610467265657a654361706162696c69747906537472696e670e6173736572745f69735f636f696e126173736572745f76616c69645f63757276651d6372656174655f7369676e65725f776974685f6361706162696c6974791b67656e65726174655f6c705f6e616d655f616e645f73796d626f6c1264657374726f795f667265657a655f63617008646563696d616c7306706f775f3130047a65726f0f6765745f64656661756c745f666565136765745f64656661756c745f64616f5f666565106e65775f6576656e745f68616e646c650d6765745f6665655f61646d696e146173736572745f76616c69645f64616f5f666565106173736572745f76616c69645f666565076465706f7369740b6e6f775f7365636f6e64730755513634783634086672616374696f6e07746f5f753132380c6f766572666c6f775f61646449bcc662ad23bb4f134aad8c8117c03f238bf3f03f324afe91ce231a559e8a6b00000000000000000000000000000000000000000000000000000000000000014e9fce03284c0ce0b86c88dd5a46f050cad2f4f33c4cdd29d98f501868558c81030864000000000000000308680000000000000003086e0000000000000003086a000000000000000308690000000000000003087000000000000000030866000000000000000308670000000000000003086d0000000000000003086b000000000000000308650000000000000003086f0000000000000003086c00000000000000030810270000000000000308e803000000000000052049bcc662ad23bb4f134aad8c8117c03f238bf3f03f324afe91ce231a559e8a6b126170746f733a3a6d657461646174615f7630c3070d6400000000000000174552525f57524f4e475f504149525f4f52444552494e47335768656e20636f696e73207573656420746f20637265617465207061697220686176652077726f6e67206f72646572696e672e6500000000000000184552525f504f4f4c5f4558495354535f464f525f50414952245768656e207061697220616c726561647920657869737473206f6e206163636f756e742e6600000000000000204552525f4e4f545f454e4f5547485f494e495449414c5f4c4951554944495459215768656e206e6f7420656e6f756768206c6971756964697479206d696e7465642e6700000000000000184552525f4e4f545f454e4f5547485f4c4951554944495459215768656e206e6f7420656e6f756768206c6971756964697479206d696e7465642e6800000000000000114552525f454d5054595f434f494e5f494e335768656e20626f7468205820616e6420592070726f766964656420666f7220737761702061726520657175616c207a65726f2e6900000000000000124552525f494e434f52524543545f535741504b5768656e20696e636f727265637420494e732f4f55547320617267756d656e74732070617373656420647572696e67207377617020616e64206d61746820646f65736e277420776f726b2e6a00000000000000194552525f494e434f52524543545f4255524e5f56414c5545531d496e636f7272656374206c7020636f696e206275726e2076616c7565736b00000000000000174552525f504f4f4c5f444f45535f4e4f545f4558495354225768656e20706f6f6c20646f65736e27742065786973747320666f7220706169722e6c000000000000000f4552525f554e524541434841424c451353686f756c64206e65766572206f636375722e6d00000000000000284552525f4e4f545f454e4f5547485f5045524d495353494f4e535f544f5f494e495449414c495a45525768656e2060696e697469616c697a65282960207472616e73616374696f6e206973207369676e6564207769746820616e79206163636f756e74206f74686572207468616e20406c6971756964737761702e6e00000000000000134552525f454d5054595f434f494e5f4c4f414e385768656e20626f7468205820616e6420592070726f766964656420666f7220666c6173686c6f616e2061726520657175616c207a65726f2e6f00000000000000124552525f504f4f4c5f49535f4c4f434b4544145768656e20706f6f6c206973206c6f636b65642e70000000000000000d4552525f4e4f545f41444d494e165768656e2075736572206973206e6f742061646d696e000208370b0e010b0803090009010902390b0e010b03030900090109023a0b0e010b05030900090109023b0b0e010b09030900090109023c0b0e010b02030900090109023d0b0e010b06030900090109023e0b0e010b0b030900090109023f0b0e010b0a0309000901090201020240034103020204420343034403450303020346034703480304020c490b0c0109004a0b0c0109014b034c044d044e0b0f010b0d03090009010902500b10010b0d03090009010902520353035401550356030502035703580359030602024c044d040702015a08110802015c0509020442034303440345030a02015d030b02015d0304180018051801180318021808180a180b1809180618000000000f3c38000303051a0b020a000b030a0111180c0a0b040b000b050b0111180c080e080e0a11190c060b063102210319070427053b3801031d05390b020b03180c0b0b0b111b070d070d18111c111d0c0c0b04111b0b05111b111d0c090e090e0c11190c070b07310221033b070427070c27020100000104170c070f3d000c000b003700140921030b070b2702020100020004195938020304070027070f3b00030907092738030e0038040c02070f3c000c0538050c040a05370138060c070a05370238070c0a0a02350a07350a0411210c080a02350a0a350b0411210c0b0a0806000000000000000024032d05320a0b060000000000000000240c010534090c010b01033a0b05010703270a0536010a0838080c060a0536020a0b38090c090a050b070b0a380a0b000b053703380b070f3c010c030b0336040b080b0b0b023902380c0b060b0902030100020004243e112538020305070027070f3b00030a07092738030a000600000000000000002403100513080c0205170a01060000000000000000240c020b02031b070227070f3c000c030a03370138060c040a03370238070c050a0336010a0038080c060a0336020a0138090c07080a033600150b030b040b05380a0b060b070b000b013903020401000104251e112538020305070027070f3b00030a0709273803070f3d000c030a033705140c010a033706140c020b033707140c000b010b020b00020501000104171038020304070027070f3b000309070927070f3d000c000b003708140206010001040103380d0700020701000104171338020304070027070f3b000309070927070f3d000c000a003709140b00370a14020801000104171038020304070027070f3b000309070927070f3d000c000b00370b140209010001040103380e070d020a010001042619112538020305070027070f3b00030a0709273803070f3d000c000a00370138060c010b00370238070c020b010b02020b01040027150a001126070f2103090b00010708270a0011270c010a000b0112072d070a0011280b001129020c010000010738020304070027070f3b00020d01000104171038020304070027070f3b000309070927070f3d000c000b00370014020e01000200042976112538020305070027070f3b00030a070927380338050c07070f3c000c080a08370138060c0c0a08370238070c0f0e0038060c0b0e0138070c0e0a07320000000000000000000000000000000021032305350a0b0a0e112a112b0c050a05070e2403300b08010706270b05070e170c03054f0a0b350a070a0c3511210c0a0a0e350b070a0f3511210c0d0a0a0a0d230348054b0b0a0c02054d0b0d0c020b020c030b030c090a090600000000000000002403590b08010707270a0836010b00380f0a0836020b0138100a090a08370c38110c060b080b0c0b0f380a070f3c010c040b04360d0b0b0b0e0b09390438120b06020f0000002d3b38010303050c0b00070d112a0b020a04112a170c06051a38000310070c270b000b020a04070d112e17350c050b050c060b060c093801031f05280b01070d112a0b030b04112a170c0805363800032c070c270b010b030b04070d112e17350c070b070c080b080c0a0b090b0a021001000200042f6e112538020305070027070f3b00030a0709270b023a030c0b0c070e0038060c060e0138070c0a0a06060000000000000000240319051c080c0305200a0a060000000000000000240c030b030324070127070f3c000c050a05370138060c090a05370238070c0d0b090a07160c090b0d0a0b160c0d0a0536010b00380f0a0536020b0138100a05370138060a05370238070a060a0a0a05370b1438130c0c0c080a053709140a05370a140b09350b0d350b080b0c38140a050a060a0a3815090b05360015070f3c010c040b04360e0b060b070b0a0b0b390538160211010001073263112538173818380203090b00010700273819070f3b002003120b0001070a27070f2b070c090b09100f11310c08381a0c060c050e080b050b06310608381b0c040c030c020b03381c0600000000000000000c0a0600000000000000000c0b381d032e0534381e11360c0a381f11360c0b38203821060000000000000000320000000000000000000000000000000032000000000000000000000000000000000b040b020b0a0b0b093822113939000c070e080b073f000e0838230e0838240e0838250e0838260e0838270e0838280e0838290e08382a0e08382b39010c010d01360f0b0011263906382c0e080b013f01021201040200043f27380203060b0001070027070f3b00030d0b000107092738030b001126113c2103150705270a01113d070f3c000c030a010b03360815070f3c010c020b0236100b013907382d021301040200043f27380203060b0001070027070f3b00030d0b000107092738030b001126113c2103150705270a01113e070f3c000c030a010b03360b15070f3c010c020b0236110b013908382e0214000000403b0a00370b140c0a0a003708140c040a0a0a0418070019060000000000000000220311051a0b0a0b041807001a060100000000000000160c0305200b0a0b041807001a0c030b030c050b010a05070d112e0c060b020b05070d112e0c080a0036010b0638080c070b0036020b0838090c09070f0b070b09382f02150100020004427b112538020305070027070f3b00030a07092738030e0038060c0c0e0238070c100a0c0600000000000000002403160519080c04051d0a10060000000000000000240c040b040321070127070f3c000c0b0a0b370138060c0e0a0b370238070c120a0b36010b00380f0a0b36020b0238100a0b36010a0138080c0f0a0b36020a0338090c130a0b370138060a0b370238070a0c0a100a0b370b1438130c110c0d0a0b3709140a0b370a140a0e350a12350b0d350b113538140a0b0a0c0a1038150b0b0b0e0b12380a070f3c010c0a0b0a36120c090b0c0c050b100c060b010c070b030c080b090b050b070b060b08390938300b0f0b1302160000010043540a003707140c0711400c050a050b0717350c0a0a0a320000000000000000000000000000000024031005150a01060000000000000000220c030517090c030b03031a051f0a02060000000000000000220c040521090c040b040324054f0a020a01114111420a0a180c080b010b02114111420b0a180c090a003705140b0811430a003605150a003706140b0911430a00360615070f3c010c060b0636130a003705140a00370614390a38310b050b003607150204090400040104060002040304040402040b04070408040a04050001000407000000000700060003000500180118021803180418051806180718081809180a180b180c180d180e181018111812181318141800"; + let res = run_binary_test("sample_liquidity_pool", code); + assert!(res.is_ok(), "{:?}", res) +} diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/catch_unwind.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/catch_unwind.rs new file mode 100644 index 0000000000..b248c8584f --- /dev/null +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/catch_unwind.rs @@ -0,0 +1,29 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 +use fail::FailScenario; +use move_binary_format::file_format::empty_module; +use move_bytecode_verifier::VerifierConfig; +use move_core_types::{ + state::{self, VMState}, + vm_status::StatusCode, +}; +use std::panic::{self, PanicInfo}; + +// TODO: this tests must run in its own process since otherwise any crashing test here +// secondary-crashes in the panic handler. +#[ignore] +#[test] +fn test_unwind() { + let scenario = FailScenario::setup(); + fail::cfg("verifier-failpoint-panic", "panic").unwrap(); + + panic::set_hook(Box::new(move |_: &PanicInfo<'_>| { + assert_eq!(state::get_state(), VMState::VERIFIER); + })); + + let m = empty_module(); + let res = move_bytecode_verifier::verify_module_with_config(&VerifierConfig::unbounded(), &m) + .unwrap_err(); + assert_eq!(res.major_status(), StatusCode::VERIFIER_INVARIANT_VIOLATION); + scenario.teardown(); +} diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/code_unit_tests.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/code_unit_tests.rs index e8091afb85..cc172e3fa0 100644 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/code_unit_tests.rs +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/code_unit_tests.rs @@ -4,13 +4,13 @@ use crate::support::dummy_procedure_module; use move_binary_format::file_format::Bytecode; -use move_bytecode_verifier::CodeUnitVerifier; +use move_bytecode_verifier::{CodeUnitVerifier, VerifierConfig}; use move_core_types::vm_status::StatusCode; #[test] fn invalid_fallthrough_br_true() { let module = dummy_procedure_module(vec![Bytecode::LdFalse, Bytecode::BrTrue(1)]); - let result = CodeUnitVerifier::verify_module(&module); + let result = CodeUnitVerifier::verify_module(&Default::default(), &module); assert_eq!( result.unwrap_err().major_status(), StatusCode::INVALID_FALL_THROUGH @@ -20,7 +20,7 @@ fn invalid_fallthrough_br_true() { #[test] fn invalid_fallthrough_br_false() { let module = dummy_procedure_module(vec![Bytecode::LdTrue, Bytecode::BrFalse(1)]); - let result = CodeUnitVerifier::verify_module(&module); + let result = CodeUnitVerifier::verify_module(&Default::default(), &module); assert_eq!( result.unwrap_err().major_status(), StatusCode::INVALID_FALL_THROUGH @@ -31,7 +31,7 @@ fn invalid_fallthrough_br_false() { #[test] fn invalid_fallthrough_non_branch() { let module = dummy_procedure_module(vec![Bytecode::LdTrue, Bytecode::Pop]); - let result = CodeUnitVerifier::verify_module(&module); + let result = CodeUnitVerifier::verify_module(&Default::default(), &module); assert_eq!( result.unwrap_err().major_status(), StatusCode::INVALID_FALL_THROUGH @@ -41,20 +41,54 @@ fn invalid_fallthrough_non_branch() { #[test] fn valid_fallthrough_branch() { let module = dummy_procedure_module(vec![Bytecode::Branch(0)]); - let result = CodeUnitVerifier::verify_module(&module); + let result = CodeUnitVerifier::verify_module(&Default::default(), &module); assert!(result.is_ok()); } #[test] fn valid_fallthrough_ret() { let module = dummy_procedure_module(vec![Bytecode::Ret]); - let result = CodeUnitVerifier::verify_module(&module); + let result = CodeUnitVerifier::verify_module(&Default::default(), &module); assert!(result.is_ok()); } #[test] fn valid_fallthrough_abort() { let module = dummy_procedure_module(vec![Bytecode::LdU64(7), Bytecode::Abort]); - let result = CodeUnitVerifier::verify_module(&module); + let result = CodeUnitVerifier::verify_module(&Default::default(), &module); assert!(result.is_ok()); } + +#[test] +fn test_max_number_of_bytecode() { + let mut nops = vec![]; + for _ in 0..u16::MAX - 1 { + nops.push(Bytecode::Nop); + } + nops.push(Bytecode::Ret); + let module = dummy_procedure_module(nops); + + let result = CodeUnitVerifier::verify_module(&VerifierConfig::unbounded(), &module); + assert!(result.is_ok()); +} + +#[test] +fn test_max_basic_blocks() { + let mut code = (0..17) + .map(|idx| Bytecode::Branch(idx + 1)) + .collect::>(); + code.push(Bytecode::Ret); + let module = dummy_procedure_module(code); + + let result = CodeUnitVerifier::verify_module( + &VerifierConfig { + max_basic_blocks: Some(16), + ..Default::default() + }, + &module, + ); + assert_eq!( + result.unwrap_err().major_status(), + StatusCode::TOO_MANY_BASIC_BLOCKS + ); +} diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/constants_tests.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/constants_tests.rs index 1fbc46b841..f74e2653a1 100644 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/constants_tests.rs +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/constants_tests.rs @@ -14,6 +14,7 @@ proptest! { } #[test] +#[cfg(not(feature = "address32"))] fn valid_primitives() { let mut module = empty_module(); module.constant_pool = vec![ @@ -25,6 +26,14 @@ fn valid_primitives() { type_: SignatureToken::U8, data: vec![0], }, + Constant { + type_: SignatureToken::U16, + data: vec![0, 0], + }, + Constant { + type_: SignatureToken::U32, + data: vec![0, 0, 0, 0], + }, Constant { type_: SignatureToken::U64, data: vec![0, 0, 0, 0, 0, 0, 0, 0], @@ -33,6 +42,13 @@ fn valid_primitives() { type_: SignatureToken::U128, data: vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], }, + Constant { + type_: SignatureToken::U256, + data: vec![ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + ], + }, Constant { type_: SignatureToken::Address, data: vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -42,10 +58,14 @@ fn valid_primitives() { } #[test] +#[cfg(not(feature = "address32"))] fn invalid_primitives() { malformed(SignatureToken::U8, vec![0, 0]); + malformed(SignatureToken::U16, vec![0, 0, 0, 0]); + malformed(SignatureToken::U32, vec![0, 0, 0]); malformed(SignatureToken::U64, vec![0]); malformed(SignatureToken::U128, vec![0]); + malformed(SignatureToken::U256, vec![0, 0]); let data = vec![ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -54,6 +74,7 @@ fn invalid_primitives() { } #[test] +#[cfg(not(feature = "address32"))] fn valid_vectors() { let double_vec = |item: Vec| -> Vec { let mut items = vec![2]; @@ -103,6 +124,14 @@ fn valid_vectors() { type_: tvec(SignatureToken::U8), data: large_vec(vec![0]), }, + Constant { + type_: tvec(SignatureToken::U16), + data: large_vec(vec![0, 0]), + }, + Constant { + type_: tvec(SignatureToken::U32), + data: large_vec(vec![0, 0, 0, 0]), + }, Constant { type_: tvec(SignatureToken::U64), data: large_vec(vec![0, 0, 0, 0, 0, 0, 0, 0]), @@ -111,6 +140,13 @@ fn valid_vectors() { type_: tvec(SignatureToken::U128), data: large_vec(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), }, + Constant { + type_: tvec(SignatureToken::U256), + data: large_vec(vec![ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + ]), + }, Constant { type_: tvec(SignatureToken::Address), data: large_vec(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), @@ -124,6 +160,14 @@ fn valid_vectors() { type_: tvec(tvec(SignatureToken::U8)), data: double_vec(large_vec(vec![0])), }, + Constant { + type_: tvec(tvec(SignatureToken::U16)), + data: double_vec(large_vec(vec![0, 0])), + }, + Constant { + type_: tvec(tvec(SignatureToken::U32)), + data: double_vec(large_vec(vec![0, 0, 0, 0])), + }, Constant { type_: tvec(tvec(SignatureToken::U64)), data: double_vec(large_vec(vec![0, 0, 0, 0, 0, 0, 0, 0])), @@ -134,6 +178,13 @@ fn valid_vectors() { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ])), }, + Constant { + type_: tvec(tvec(SignatureToken::U256)), + data: double_vec(large_vec(vec![ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + ])), + }, Constant { type_: tvec(tvec(SignatureToken::Address)), data: double_vec(large_vec(vec![ @@ -145,6 +196,7 @@ fn valid_vectors() { } #[test] +#[cfg(not(feature = "address32"))] fn invalid_vectors() { let double_vec = |item: Vec| -> Vec { let mut items = vec![2]; @@ -158,6 +210,8 @@ fn invalid_vectors() { items }; // wrong inner + malformed(tvec(SignatureToken::U16), vec![1, 0]); + malformed(tvec(SignatureToken::U32), vec![1, 0]); malformed(tvec(SignatureToken::U64), vec![1, 0]); malformed( tvec(SignatureToken::Address), @@ -194,6 +248,7 @@ fn tvec(s: SignatureToken) -> SignatureToken { SignatureToken::Vector(Box::new(s)) } +#[allow(unused)] fn malformed(type_: SignatureToken, data: Vec) { error(type_, data, StatusCode::MALFORMED_CONSTANT_DATA) } diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/control_flow_tests.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/control_flow_tests.rs index ddf7796f3d..447ef51d94 100644 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/control_flow_tests.rs +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/control_flow_tests.rs @@ -8,23 +8,30 @@ use move_binary_format::{ errors::PartialVMResult, file_format::{Bytecode, CompiledModule, FunctionDefinitionIndex, TableIndex}, }; -use move_bytecode_verifier::control_flow; +use move_bytecode_verifier::{control_flow, meter::DummyMeter, VerifierConfig}; use move_core_types::vm_status::StatusCode; -fn verify_module(module: &CompiledModule) -> PartialVMResult<()> { +fn verify_module(verifier_config: &VerifierConfig, module: &CompiledModule) -> PartialVMResult<()> { for (idx, function_definition) in module .function_defs() .iter() .enumerate() .filter(|(_, def)| !def.is_native()) { - control_flow::verify( - Some(FunctionDefinitionIndex(idx as TableIndex)), - function_definition - .code - .as_ref() - .expect("unexpected native function"), - )? + let current_function = FunctionDefinitionIndex(idx as TableIndex); + let code = function_definition + .code + .as_ref() + .expect("unexpected native function"); + + control_flow::verify_function( + verifier_config, + module, + current_function, + function_definition, + code, + &mut DummyMeter, + )?; } Ok(()) } @@ -33,10 +40,32 @@ fn verify_module(module: &CompiledModule) -> PartialVMResult<()> { // Simple cases - Copied from code unit verifier //************************************************************************************************** +#[test] +fn empty_bytecode() { + let module = dummy_procedure_module(vec![]); + let result = verify_module(&Default::default(), &module); + assert_eq!( + result.unwrap_err().major_status(), + StatusCode::EMPTY_CODE_UNIT, + ); +} + +#[test] +fn empty_bytecode_v5() { + let mut module = dummy_procedure_module(vec![]); + module.version = 5; + + let result = verify_module(&Default::default(), &module); + assert_eq!( + result.unwrap_err().major_status(), + StatusCode::EMPTY_CODE_UNIT, + ); +} + #[test] fn invalid_fallthrough_br_true() { let module = dummy_procedure_module(vec![Bytecode::LdFalse, Bytecode::BrTrue(1)]); - let result = verify_module(&module); + let result = verify_module(&Default::default(), &module); assert_eq!( result.unwrap_err().major_status(), StatusCode::INVALID_FALL_THROUGH @@ -46,7 +75,7 @@ fn invalid_fallthrough_br_true() { #[test] fn invalid_fallthrough_br_false() { let module = dummy_procedure_module(vec![Bytecode::LdTrue, Bytecode::BrFalse(1)]); - let result = verify_module(&module); + let result = verify_module(&Default::default(), &module); assert_eq!( result.unwrap_err().major_status(), StatusCode::INVALID_FALL_THROUGH @@ -57,7 +86,7 @@ fn invalid_fallthrough_br_false() { #[test] fn invalid_fallthrough_non_branch() { let module = dummy_procedure_module(vec![Bytecode::LdTrue, Bytecode::Pop]); - let result = verify_module(&module); + let result = verify_module(&Default::default(), &module); assert_eq!( result.unwrap_err().major_status(), StatusCode::INVALID_FALL_THROUGH @@ -67,20 +96,144 @@ fn invalid_fallthrough_non_branch() { #[test] fn valid_fallthrough_branch() { let module = dummy_procedure_module(vec![Bytecode::Branch(0)]); - let result = verify_module(&module); + let result = verify_module(&Default::default(), &module); assert!(result.is_ok()); } #[test] fn valid_fallthrough_ret() { let module = dummy_procedure_module(vec![Bytecode::Ret]); - let result = verify_module(&module); + let result = verify_module(&Default::default(), &module); assert!(result.is_ok()); } #[test] fn valid_fallthrough_abort() { let module = dummy_procedure_module(vec![Bytecode::LdU64(7), Bytecode::Abort]); - let result = verify_module(&module); + let result = verify_module(&Default::default(), &module); + assert!(result.is_ok()); +} + +#[test] +fn nested_loops_max_depth() { + let module = dummy_procedure_module(vec![ + Bytecode::LdFalse, + Bytecode::LdFalse, + Bytecode::BrFalse(1), + Bytecode::BrFalse(0), + Bytecode::Ret, + ]); + let result = verify_module( + &VerifierConfig { + max_loop_depth: Some(2), + ..VerifierConfig::default() + }, + &module, + ); + assert!(result.is_ok()); +} + +#[test] +fn nested_loops_exceed_max_depth() { + let module = dummy_procedure_module(vec![ + Bytecode::LdFalse, + Bytecode::LdFalse, + Bytecode::LdFalse, + Bytecode::BrFalse(2), + Bytecode::BrFalse(1), + Bytecode::BrFalse(0), + Bytecode::Ret, + ]); + let result = verify_module( + &VerifierConfig { + max_loop_depth: Some(2), + ..VerifierConfig::default() + }, + &module, + ); + assert_eq!( + result.unwrap_err().major_status(), + StatusCode::LOOP_MAX_DEPTH_REACHED + ); +} + +#[test] +fn non_loop_backward_jump() { + let module = dummy_procedure_module(vec![ + Bytecode::Branch(2), + Bytecode::Ret, + Bytecode::Branch(1), + ]); + let result = verify_module(&Default::default(), &module); assert!(result.is_ok()); } + +#[test] +fn non_loop_backward_jump_v5() { + let mut module = dummy_procedure_module(vec![ + Bytecode::Branch(2), + Bytecode::Ret, + Bytecode::Branch(1), + ]); + + module.version = 5; + let result = verify_module(&Default::default(), &module); + assert_eq!( + result.unwrap_err().major_status(), + StatusCode::INVALID_LOOP_SPLIT, + ); +} + +#[test] +fn irreducible_control_flow_graph() { + let module = dummy_procedure_module(vec![ + Bytecode::LdTrue, + Bytecode::BrTrue(3), + Bytecode::Nop, + Bytecode::LdFalse, + Bytecode::BrFalse(2), + Bytecode::Ret, + ]); + let result = verify_module(&Default::default(), &module); + assert_eq!( + result.unwrap_err().major_status(), + StatusCode::INVALID_LOOP_SPLIT, + ); +} + +#[test] +fn nested_loop_break() { + let module = dummy_procedure_module(vec![ + Bytecode::LdFalse, + Bytecode::LdFalse, + Bytecode::LdFalse, + Bytecode::Branch(7), + Bytecode::BrFalse(2), + Bytecode::BrFalse(1), + Bytecode::BrFalse(0), + Bytecode::Ret, + ]); + let result = verify_module(&Default::default(), &module); + assert!(result.is_ok()); +} + +#[test] +fn nested_loop_break_v5() { + let mut module = dummy_procedure_module(vec![ + Bytecode::LdFalse, + Bytecode::LdFalse, + Bytecode::LdFalse, + Bytecode::Branch(7), + Bytecode::BrFalse(2), + Bytecode::BrFalse(1), + Bytecode::BrFalse(0), + Bytecode::Ret, + ]); + + module.version = 5; + let result = verify_module(&Default::default(), &module); + assert_eq!( + result.unwrap_err().major_status(), + StatusCode::INVALID_LOOP_BREAK, + ); +} diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/large_type_test.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/large_type_test.rs new file mode 100644 index 0000000000..c8499625e8 --- /dev/null +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/large_type_test.rs @@ -0,0 +1,155 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::unit_tests::production_config; +use move_binary_format::file_format::{ + empty_module, Bytecode, CodeUnit, FunctionDefinition, FunctionHandle, FunctionHandleIndex, + IdentifierIndex, ModuleHandleIndex, Signature, SignatureIndex, SignatureToken, + Visibility::Public, +}; +use move_core_types::{identifier::Identifier, vm_status::StatusCode}; + +const NUM_LOCALS: u8 = 64; +const NUM_CALLS: u16 = 77; +const NUM_FUNCTIONS: u16 = 177; + +fn get_nested_vec_type(len: usize) -> SignatureToken { + let mut ret = SignatureToken::Bool; + for _ in 0..len { + ret = SignatureToken::Vector(Box::new(ret)); + } + ret +} + +#[test] +fn test_large_types() { + // See also: github.com/aptos-labs/aptos-core/security/advisories/GHSA-37qw-jfpw-8899 + let mut m = empty_module(); + + m.signatures.push(Signature( + std::iter::repeat(SignatureToken::Reference(Box::new(get_nested_vec_type(64)))) + .take(NUM_LOCALS as usize) + .collect(), + )); + + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(0), + parameters: SignatureIndex(0), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(0), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![Bytecode::Call(FunctionHandleIndex(0)), Bytecode::Ret], + }), + }); + + // returns_vecs + m.identifiers.push(Identifier::new("returns_vecs").unwrap()); + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(1), + parameters: SignatureIndex(0), + return_: SignatureIndex(1), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(1), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![Bytecode::Call(FunctionHandleIndex(1)), Bytecode::Ret], + }), + }); + + // takes_and_returns_vecs + m.identifiers + .push(Identifier::new("takes_and_returns_vecs").unwrap()); + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(2), + parameters: SignatureIndex(1), + return_: SignatureIndex(1), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(2), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![Bytecode::Call(FunctionHandleIndex(1)), Bytecode::Ret], + }), + }); + + // takes_vecs + m.identifiers.push(Identifier::new("takes_vecs").unwrap()); + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(3), + parameters: SignatureIndex(1), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(3), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![Bytecode::Ret], + }), + }); + + // other fcts + for i in 0..NUM_FUNCTIONS { + m.identifiers + .push(Identifier::new(format!("f{}", i)).unwrap()); + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(i + 4), + parameters: SignatureIndex(0), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(i + 4), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![], + }), + }); + + let code = &mut m.function_defs[i as usize + 4].code.as_mut().unwrap().code; + code.clear(); + code.push(Bytecode::Call(FunctionHandleIndex(1))); + for _ in 0..NUM_CALLS { + code.push(Bytecode::Call(FunctionHandleIndex(2))); + } + code.push(Bytecode::Call(FunctionHandleIndex(3))); + code.push(Bytecode::Ret); + } + + let result = move_bytecode_verifier::verify_module_with_config_for_test( + "test_large_types", + &production_config(), + &m, + ); + assert_eq!( + result.unwrap_err().major_status(), + StatusCode::CONSTRAINT_NOT_SATISFIED, + ); +} diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/limit_tests.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/limit_tests.rs new file mode 100644 index 0000000000..8833331542 --- /dev/null +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/limit_tests.rs @@ -0,0 +1,674 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use move_binary_format::file_format::*; +use move_bytecode_verifier::{ + limits::LimitsVerifier, verify_module_with_config_for_test, VerifierConfig, +}; +use move_core_types::{ + account_address::AccountAddress, identifier::Identifier, vm_status::StatusCode, +}; + +#[test] +fn test_function_handle_type_instantiation() { + let mut m = basic_test_module(); + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex::new(0), + name: IdentifierIndex::new(0), + parameters: SignatureIndex(0), + return_: SignatureIndex(0), + type_parameters: std::iter::repeat(AbilitySet::ALL).take(10).collect(), + }); + + assert_eq!( + LimitsVerifier::verify_module( + &VerifierConfig { + max_generic_instantiation_length: Some(9), + ..Default::default() + }, + &m + ) + .unwrap_err() + .major_status(), + StatusCode::TOO_MANY_TYPE_PARAMETERS + ); + + let mut s = basic_test_script(); + s.function_handles.push(FunctionHandle { + module: ModuleHandleIndex::new(0), + name: IdentifierIndex::new(0), + parameters: SignatureIndex(0), + return_: SignatureIndex(0), + type_parameters: std::iter::repeat(AbilitySet::ALL).take(10).collect(), + }); + + assert_eq!( + LimitsVerifier::verify_script( + &VerifierConfig { + max_generic_instantiation_length: Some(9), + ..Default::default() + }, + &s + ) + .unwrap_err() + .major_status(), + StatusCode::TOO_MANY_TYPE_PARAMETERS + ); +} + +#[test] +fn test_struct_handle_type_instantiation() { + let mut m = basic_test_module(); + m.struct_handles.push(StructHandle { + module: ModuleHandleIndex::new(0), + name: IdentifierIndex::new(0), + abilities: AbilitySet::ALL, + type_parameters: std::iter::repeat(StructTypeParameter { + constraints: AbilitySet::ALL, + is_phantom: false, + }) + .take(10) + .collect(), + }); + + assert_eq!( + LimitsVerifier::verify_module( + &VerifierConfig { + max_generic_instantiation_length: Some(9), + ..Default::default() + }, + &m + ) + .unwrap_err() + .major_status(), + StatusCode::TOO_MANY_TYPE_PARAMETERS + ); + + let mut s = basic_test_script(); + s.struct_handles.push(StructHandle { + module: ModuleHandleIndex::new(0), + name: IdentifierIndex::new(0), + abilities: AbilitySet::ALL, + type_parameters: std::iter::repeat(StructTypeParameter { + constraints: AbilitySet::ALL, + is_phantom: false, + }) + .take(10) + .collect(), + }); + + assert_eq!( + LimitsVerifier::verify_script( + &VerifierConfig { + max_generic_instantiation_length: Some(9), + ..Default::default() + }, + &s + ) + .unwrap_err() + .major_status(), + StatusCode::TOO_MANY_TYPE_PARAMETERS + ); +} + +#[test] +fn test_function_handle_parameters() { + let mut m = basic_test_module(); + m.signatures.push(Signature( + std::iter::repeat(SignatureToken::Bool).take(10).collect(), + )); + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex::new(0), + name: IdentifierIndex::new(0), + parameters: SignatureIndex(1), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + + assert_eq!( + LimitsVerifier::verify_module( + &VerifierConfig { + max_function_parameters: Some(9), + ..Default::default() + }, + &m + ) + .unwrap_err() + .major_status(), + StatusCode::TOO_MANY_PARAMETERS + ); + + let mut s = basic_test_script(); + s.signatures.push(Signature( + std::iter::repeat(SignatureToken::Bool).take(10).collect(), + )); + s.function_handles.push(FunctionHandle { + module: ModuleHandleIndex::new(0), + name: IdentifierIndex::new(0), + parameters: SignatureIndex(1), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + + assert_eq!( + LimitsVerifier::verify_script( + &VerifierConfig { + max_function_parameters: Some(9), + ..Default::default() + }, + &s + ) + .unwrap_err() + .major_status(), + StatusCode::TOO_MANY_PARAMETERS + ); +} + +#[test] +fn big_vec_unpacks() { + const N_TYPE_PARAMS: usize = 16; + let mut st = SignatureToken::Vector(Box::new(SignatureToken::U8)); + let type_params = vec![st; N_TYPE_PARAMS]; + st = SignatureToken::StructInstantiation(StructHandleIndex(0), type_params); + const N_VEC_PUSH: u16 = 1000; + let mut code = vec![]; + // 1. CopyLoc: ... -> ... st + // 2. VecPack: ... st -> ... Vec + // 3. VecUnpack: ... Vec -> ... st, st, st, ... st + for _ in 0..N_VEC_PUSH { + code.push(Bytecode::CopyLoc(0)); + code.push(Bytecode::VecPack(SignatureIndex(1), 1)); + code.push(Bytecode::VecUnpack(SignatureIndex(1), 1 << 15)); + } + // 1. VecPack: ... st, st, st, ... st -> ... Vec + // 2. Pop: ... Vec -> ... + for _ in 0..N_VEC_PUSH { + code.push(Bytecode::VecPack(SignatureIndex(1), 1 << 15)); + code.push(Bytecode::Pop); + } + code.push(Bytecode::Ret); + let type_param_constraints = StructTypeParameter { + constraints: AbilitySet::EMPTY, + is_phantom: false, + }; + let module = CompiledModule { + version: 5, + self_module_handle_idx: ModuleHandleIndex(0), + module_handles: vec![ModuleHandle { + address: AddressIdentifierIndex(0), + name: IdentifierIndex(0), + }], + struct_handles: vec![StructHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(1), + abilities: AbilitySet::ALL, + type_parameters: vec![type_param_constraints; N_TYPE_PARAMS], + }], + function_handles: vec![FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(0), + parameters: SignatureIndex(1), + return_: SignatureIndex(0), + type_parameters: vec![], + }], + field_handles: vec![], + friend_decls: vec![], + struct_def_instantiations: vec![], + function_instantiations: vec![], + field_instantiations: vec![], + signatures: vec![Signature(vec![]), Signature(vec![st])], + identifiers: vec![ + Identifier::new("f").unwrap(), + Identifier::new("generic_struct").unwrap(), + ], + address_identifiers: vec![AccountAddress::ONE], + constant_pool: vec![], + metadata: vec![], + struct_defs: vec![StructDefinition { + struct_handle: StructHandleIndex(0), + field_information: StructFieldInformation::Native, + }], + function_defs: vec![FunctionDefinition { + function: FunctionHandleIndex(0), + visibility: Visibility::Public, + is_entry: true, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code, + }), + }], + }; + + // save module and verify that it can ser/de + let mut mvbytes = vec![]; + module.serialize(&mut mvbytes).unwrap(); + let module = CompiledModule::deserialize(&mvbytes).unwrap(); + + let res = verify_module_with_config_for_test( + "big_vec_unpacks", + &VerifierConfig { + max_loop_depth: Some(5), + max_generic_instantiation_length: Some(32), + max_function_parameters: Some(128), + max_basic_blocks: Some(1024), + max_push_size: Some(10000), + ..Default::default() + }, + &module, + ); + assert_eq!( + res.unwrap_err().major_status(), + StatusCode::VALUE_STACK_PUSH_OVERFLOW + ); +} + +const MAX_STRUCTS: usize = 200; +const MAX_FIELDS: usize = 30; +const MAX_FUNCTIONS: usize = 1000; + +#[test] +fn max_struct_test() { + let config = VerifierConfig { + max_struct_definitions: Some(MAX_STRUCTS), + max_fields_in_struct: Some(MAX_FIELDS), + max_function_definitions: Some(MAX_FUNCTIONS), + ..Default::default() + }; + let mut module = leaf_module("M"); + multi_struct(&mut module, 0); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + multi_struct(&mut module, 1); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS / 2); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS * 2); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!( + res.unwrap_err().major_status(), + StatusCode::MAX_STRUCT_DEFINITIONS_REACHED, + ); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS + 1); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!( + res.unwrap_err().major_status(), + StatusCode::MAX_STRUCT_DEFINITIONS_REACHED, + ); +} + +#[test] +fn max_fields_test() { + let config = VerifierConfig { + max_struct_definitions: Some(MAX_STRUCTS), + max_fields_in_struct: Some(MAX_FIELDS), + max_function_definitions: Some(MAX_FUNCTIONS), + ..Default::default() + }; + let mut module = leaf_module("M"); + multi_struct(&mut module, 1); + multi_fields(&mut module, MAX_FIELDS / 2); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, 10); + multi_fields(&mut module, MAX_FIELDS - 1); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, 50); + multi_fields(&mut module, MAX_FIELDS); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, 100); + multi_fields(&mut module, MAX_FIELDS + 1); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!( + res.unwrap_err().major_status(), + StatusCode::MAX_FIELD_DEFINITIONS_REACHED, + ); + let mut module = leaf_module("M"); + multi_struct(&mut module, 2); + multi_fields(&mut module, MAX_FIELDS * 2); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!( + res.unwrap_err().major_status(), + StatusCode::MAX_FIELD_DEFINITIONS_REACHED, + ); + let mut module = leaf_module("M"); + multi_struct(&mut module, 50); + multi_fields_except_one(&mut module, 0, 2, MAX_FIELDS + 1); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!( + res.unwrap_err().major_status(), + StatusCode::MAX_FIELD_DEFINITIONS_REACHED, + ); + let mut module = leaf_module("M"); + multi_struct(&mut module, 20); + multi_fields_except_one(&mut module, 19, MAX_FIELDS, MAX_FIELDS + 1); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!( + res.unwrap_err().major_status(), + StatusCode::MAX_FIELD_DEFINITIONS_REACHED, + ); + let mut module = leaf_module("M"); + multi_struct(&mut module, 100); + multi_fields_except_one(&mut module, 50, 1, MAX_FIELDS * 2); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!( + res.unwrap_err().major_status(), + StatusCode::MAX_FIELD_DEFINITIONS_REACHED, + ); +} + +#[test] +fn max_functions_test() { + let config = VerifierConfig { + max_struct_definitions: Some(MAX_STRUCTS), + max_fields_in_struct: Some(MAX_FIELDS), + max_function_definitions: Some(MAX_FUNCTIONS), + ..Default::default() + }; + let mut module = leaf_module("M"); + multi_struct(&mut module, 1); + multi_functions(&mut module, 1); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, 10); + multi_functions(&mut module, MAX_FUNCTIONS / 2); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, 5); + multi_functions(&mut module, MAX_FUNCTIONS); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, 5); + multi_functions(&mut module, MAX_FUNCTIONS - 1); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, 5); + multi_functions(&mut module, MAX_FUNCTIONS + 1); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!( + res.unwrap_err().major_status(), + StatusCode::MAX_FUNCTION_DEFINITIONS_REACHED, + ); + let mut module = leaf_module("M"); + multi_functions(&mut module, MAX_FUNCTIONS * 2); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!( + res.unwrap_err().major_status(), + StatusCode::MAX_FUNCTION_DEFINITIONS_REACHED, + ); +} + +#[test] +fn max_mixed_config_test() { + let config = VerifierConfig { + max_struct_definitions: Some(MAX_STRUCTS), + max_fields_in_struct: Some(MAX_FIELDS), + max_function_definitions: Some(MAX_FUNCTIONS), + ..Default::default() + }; + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS); + multi_fields(&mut module, MAX_FIELDS); + multi_functions(&mut module, MAX_FUNCTIONS); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + + let config = VerifierConfig { + max_function_definitions: None, + max_struct_definitions: None, + max_fields_in_struct: None, + ..Default::default() + }; + let mut module = leaf_module("M"); + multi_struct(&mut module, 1); + multi_fields(&mut module, 1); + multi_functions(&mut module, 1); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS); + multi_fields(&mut module, MAX_FIELDS); + multi_functions(&mut module, MAX_FUNCTIONS); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS * 2); + multi_fields(&mut module, MAX_FIELDS * 2); + multi_functions(&mut module, MAX_FUNCTIONS * 2); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS + 1); + multi_fields(&mut module, MAX_FIELDS + 1); + multi_functions(&mut module, MAX_FUNCTIONS + 1); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + + let config = VerifierConfig { + max_struct_definitions: Some(MAX_STRUCTS), + max_fields_in_struct: Some(MAX_FIELDS), + ..Default::default() + }; + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS); + multi_fields(&mut module, MAX_FIELDS); + multi_functions(&mut module, MAX_FUNCTIONS); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS); + multi_fields(&mut module, MAX_FIELDS); + multi_functions(&mut module, MAX_FUNCTIONS + 10); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS); + multi_fields(&mut module, MAX_FIELDS); + multi_functions(&mut module, MAX_FUNCTIONS * 3); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS * 2); + multi_fields(&mut module, MAX_FIELDS); + multi_functions(&mut module, MAX_FUNCTIONS + 1); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!( + res.unwrap_err().major_status(), + StatusCode::MAX_STRUCT_DEFINITIONS_REACHED, + ); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS); + multi_fields(&mut module, MAX_FIELDS * 2); + multi_functions(&mut module, MAX_FUNCTIONS * 3); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!( + res.unwrap_err().major_status(), + StatusCode::MAX_FIELD_DEFINITIONS_REACHED, + ); + + let config = VerifierConfig { + max_struct_definitions: Some(MAX_STRUCTS), + max_function_definitions: Some(MAX_FUNCTIONS), + ..Default::default() + }; + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS); + multi_fields(&mut module, MAX_FIELDS); + multi_functions(&mut module, MAX_FUNCTIONS); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS); + multi_fields(&mut module, MAX_FIELDS + 1); + multi_functions(&mut module, MAX_FUNCTIONS); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS); + multi_fields(&mut module, MAX_FIELDS * 3); + multi_functions(&mut module, MAX_FUNCTIONS); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS * 2); + multi_fields(&mut module, MAX_FIELDS * 3); + multi_functions(&mut module, MAX_FUNCTIONS); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!( + res.unwrap_err().major_status(), + StatusCode::MAX_STRUCT_DEFINITIONS_REACHED, + ); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS); + multi_fields(&mut module, MAX_FIELDS * 2); + multi_functions(&mut module, MAX_FUNCTIONS * 2); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!( + res.unwrap_err().major_status(), + StatusCode::MAX_FUNCTION_DEFINITIONS_REACHED, + ); + + let config = VerifierConfig { + max_fields_in_struct: Some(MAX_FIELDS), + max_function_definitions: Some(MAX_FUNCTIONS), + ..Default::default() + }; + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS); + multi_fields(&mut module, MAX_FIELDS); + multi_functions(&mut module, MAX_FUNCTIONS); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS * 3); + multi_fields(&mut module, MAX_FIELDS); + multi_functions(&mut module, MAX_FUNCTIONS); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS + 1); + multi_fields(&mut module, MAX_FIELDS); + multi_functions(&mut module, MAX_FUNCTIONS); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!(res, Ok(())); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS + 1); + multi_fields(&mut module, MAX_FIELDS * 3); + multi_functions(&mut module, MAX_FUNCTIONS); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!( + res.unwrap_err().major_status(), + StatusCode::MAX_FIELD_DEFINITIONS_REACHED, + ); + let mut module = leaf_module("M"); + multi_struct(&mut module, MAX_STRUCTS * 2); + multi_fields(&mut module, MAX_FIELDS); + multi_functions(&mut module, MAX_FUNCTIONS * 2); + let res = LimitsVerifier::verify_module(&config, &module); + assert_eq!( + res.unwrap_err().major_status(), + StatusCode::MAX_FUNCTION_DEFINITIONS_REACHED, + ); +} + +fn multi_struct(module: &mut CompiledModule, count: usize) { + for i in 0..count { + module + .identifiers + .push(Identifier::new(format!("A_{}", i)).unwrap()); + module.struct_handles.push(StructHandle { + module: module.self_module_handle_idx, + name: IdentifierIndex((module.identifiers.len() - 1) as u16), + abilities: AbilitySet::EMPTY, + type_parameters: vec![], + }); + module.struct_defs.push(StructDefinition { + struct_handle: StructHandleIndex((module.struct_handles.len() - 1) as u16), + field_information: StructFieldInformation::Declared(vec![]), + }); + } +} + +fn multi_fields(module: &mut CompiledModule, count: usize) { + for def in &mut module.struct_defs { + let mut fields = vec![]; + for i in 0..count { + module + .identifiers + .push(Identifier::new(format!("f_{}", i)).unwrap()); + fields.push(FieldDefinition { + name: Default::default(), + signature: TypeSignature(SignatureToken::U8), + }); + } + def.field_information = StructFieldInformation::Declared(fields); + } +} + +fn multi_fields_except_one(module: &mut CompiledModule, idx: usize, count: usize, one: usize) { + for (struct_idx, def) in module.struct_defs.iter_mut().enumerate() { + let mut fields = vec![]; + let count = if struct_idx == idx { one } else { count }; + for i in 0..count { + module + .identifiers + .push(Identifier::new(format!("f_{}", i)).unwrap()); + fields.push(FieldDefinition { + name: Default::default(), + signature: TypeSignature(SignatureToken::U8), + }); + } + def.field_information = StructFieldInformation::Declared(fields); + } +} + +fn multi_functions(module: &mut CompiledModule, count: usize) { + module.signatures.push(Signature(vec![])); + for i in 0..count { + module + .identifiers + .push(Identifier::new(format!("func_{}", i)).unwrap()); + module.function_handles.push(FunctionHandle { + module: module.self_module_handle_idx, + name: IdentifierIndex((module.identifiers.len() - 1) as u16), + parameters: SignatureIndex((module.signatures.len() - 1) as u16), + return_: SignatureIndex((module.signatures.len() - 1) as u16), + type_parameters: vec![], + }); + module.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex((module.function_handles.len() - 1) as u16), + visibility: Visibility::Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex((module.signatures.len() - 1) as u16), + code: vec![Bytecode::Ret], + }), + }); + } +} + +fn leaf_module(name: &str) -> CompiledModule { + let mut module = empty_module(); + module.identifiers[0] = Identifier::new(name).unwrap(); + module.address_identifiers[0] = AccountAddress::ONE; + module +} diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/locals.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/locals.rs new file mode 100644 index 0000000000..efca303080 --- /dev/null +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/locals.rs @@ -0,0 +1,120 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::unit_tests::production_config; +use move_binary_format::file_format::{ + empty_module, Bytecode, CodeUnit, FunctionDefinition, FunctionHandle, FunctionHandleIndex, + IdentifierIndex, ModuleHandleIndex, Signature, SignatureIndex, SignatureToken, + Visibility::Public, +}; +use move_core_types::{identifier::Identifier, vm_status::StatusCode}; + +#[test] +fn test_locals() { + // See also: github.com/aptos-labs/aptos-core/security/advisories/GHSA-jjqw-f9pc-525j + let mut m = empty_module(); + + const MAX_BASIC_BLOCKS: u16 = 1024; + const MAX_LOCALS: u8 = 255; + const NUM_FUNCTIONS: u16 = 16; + + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(0), + parameters: SignatureIndex(0), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(0), + visibility: Public, + is_entry: true, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![Bytecode::Ret], + }), + }); + + // signature of locals in f1..f + m.signatures.push(Signature( + std::iter::repeat(SignatureToken::U8) + .take(MAX_LOCALS as usize) + .collect(), + )); + + m.identifiers.push(Identifier::new("pwn").unwrap()); + + // create returns_bool_and_u64 + m.signatures + .push(Signature(vec![SignatureToken::Bool, SignatureToken::U8])); + m.identifiers + .push(Identifier::new("returns_bool_and_u64").unwrap()); + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(1), + parameters: SignatureIndex(0), + return_: SignatureIndex(2), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(1), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![Bytecode::LdTrue, Bytecode::LdU8(0), Bytecode::Ret], + }), + }); + + // create other functions + for i in 1..(NUM_FUNCTIONS + 1) { + m.identifiers + .push(Identifier::new(format!("f{}", i)).unwrap()); + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(i + 1), // the +1 accounts for returns_bool_and_u64 + parameters: SignatureIndex(0), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(i + 1), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(1), + code: vec![], + }), + }); + + let code = &mut m.function_defs[i as usize + 1].code.as_mut().unwrap().code; + + for _ in 0..(MAX_BASIC_BLOCKS / 2 - MAX_LOCALS as u16 - 3) { + code.push(Bytecode::LdTrue); + code.push(Bytecode::BrTrue((code.len() + 2) as u16)); + code.push(Bytecode::Ret); + code.push(Bytecode::LdTrue); + code.push(Bytecode::BrTrue(0)); + } + for i in 0..MAX_LOCALS { + code.push(Bytecode::Call(FunctionHandleIndex(1))); // calls returns_bool_and_u64 + code.push(Bytecode::StLoc(i as u8)); // i'th local is now available for the first time + code.push(Bytecode::BrTrue(0)); + } + code.push(Bytecode::Ret); + } + + let result = move_bytecode_verifier::verify_module_with_config_for_test( + "test_locals", + &production_config(), + &m, + ); + assert_eq!( + result.unwrap_err().major_status(), + StatusCode::CONSTRAINT_NOT_SATISFIED + ); +} diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/loop_summary_tests.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/loop_summary_tests.rs new file mode 100644 index 0000000000..819b941270 --- /dev/null +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/loop_summary_tests.rs @@ -0,0 +1,391 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use move_binary_format::{control_flow_graph::VMControlFlowGraph, file_format::Bytecode}; +use move_bytecode_verifier::loop_summary::{LoopPartition, LoopSummary}; + +macro_rules! assert_node { + ( $summary:ident, $node:expr ; $block:expr, $preds:expr, $descs:expr, $backs:expr ) => { + let (s, n) = (&$summary, $node); + assert_eq!(s.block(n), $block, "Block"); + + let descs = $descs; + for d in descs { + assert!(s.is_descendant(n, *d), "{:?} -> {:?}", n, d) + } + + assert_eq!(s.pred_edges(n), $preds, "Predecessor Edges"); + assert_eq!(s.back_edges(n), $backs, "Back Edges"); + }; +} + +#[test] +fn linear_summary() { + let summary = { + use Bytecode::*; + LoopSummary::new(&VMControlFlowGraph::new(&[ + /* B0, L0 */ Nop, + /* */ Branch(2), + /* B2, L1 */ Nop, + /* */ Branch(4), + /* B4, L2 */ Ret, + ])) + }; + + let n: Vec<_> = summary.preorder().collect(); + + assert_eq!(n.len(), 3); + + assert_node!( + summary, n[0]; + /* block */ 0, + /* preds */ &[], + /* descs */ &[n[1], n[2]], + /* backs */ &[] + ); + + assert_node!( + summary, n[1]; + /* block */ 2, + /* preds */ &[n[0]], + /* descs */ &[n[2]], + /* backs */ &[] + ); + + assert_node!( + summary, n[2]; + /* block */ 4, + /* preds */ &[n[1]], + /* descs */ &[], + /* backs */ &[] + ); +} + +#[test] +fn non_loop_back_branch_summary() { + let summary = { + use Bytecode::*; + LoopSummary::new(&VMControlFlowGraph::new(&[ + /* B0, L0 */ Nop, + /* */ Branch(3), + /* B2, L2 */ Ret, + /* B3, L1 */ Branch(2), + ])) + }; + + let n: Vec<_> = summary.preorder().collect(); + + assert_eq!(n.len(), 3); + + assert_node!( + summary, n[0]; + /* block */ 0, + /* preds */ &[], + /* descs */ &[n[1], n[2]], + /* backs */ &[] + ); + + assert_node!( + summary, n[1]; + /* block */ 3, + /* preds */ &[n[0]], + /* descs */ &[n[2]], + /* backs */ &[] + ); + + assert_node!( + summary, n[2]; + /* block */ 2, + /* preds */ &[n[1]], + /* descs */ &[], + /* backs */ &[] + ); +} + +#[test] +fn branching_summary() { + let summary = { + use Bytecode::*; + LoopSummary::new(&VMControlFlowGraph::new(&[ + /* B0, L0 */ LdTrue, + /* */ BrTrue(3), + /* B2, L2 */ Nop, + /* B3, L1 */ Ret, + ])) + }; + + let n: Vec<_> = summary.preorder().collect(); + + assert_eq!(n.len(), 3); + + assert_node!( + summary, n[0]; + /* block */ 0, + /* preds */ &[], + /* descs */ &[n[1], n[2]], + /* backs */ &[] + ); + + assert_node!( + summary, n[1]; + /* block */ 3, + /* preds */ &[n[0], n[2]], + /* descs */ &[], + /* backs */ &[] + ); + + assert_node!( + summary, n[2]; + /* block */ 2, + /* preds */ &[n[0]], + /* descs */ &[], + /* backs */ &[] + ); + + // Although L2 -> L1 is an edge in the CFG, it's not an edge in the DFST, so L2 is said to have + // no descendants. + assert!(!summary.is_descendant(n[2], n[1])); +} + +#[test] +fn looping_summary() { + let summary = { + use Bytecode::*; + LoopSummary::new(&VMControlFlowGraph::new(&[ + /* B0, L0 */ LdTrue, + /* */ BrTrue(4), + /* B2, L2 */ Nop, + /* */ Branch(0), + /* B4, L1 */ Ret, + ])) + }; + + let n: Vec<_> = summary.preorder().collect(); + + assert_eq!(n.len(), 3); + + assert_node!( + summary, n[0]; + /* block */ 0, + /* preds */ &[], + /* descs */ &[n[1], n[2]], + /* backs */ &[n[2]] + ); + + assert_node!( + summary, n[1]; + /* block */ 4, + /* preds */ &[n[0]], + /* descs */ &[], + /* backs */ &[] + ); + + assert_node!( + summary, n[2]; + /* block */ 2, + /* preds */ &[n[0]], + /* descs */ &[], + /* backs */ &[] + ); +} + +#[test] +fn branches_in_loops_summary() { + let summary = { + use Bytecode::*; + LoopSummary::new(&VMControlFlowGraph::new(&[ + /* B0, L0 */ LdTrue, + /* */ BrTrue(3), + /* B2, L3 */ Nop, + /* B3, L1 */ LdFalse, + /* */ BrFalse(0), + /* B5, L2 */ Ret, + ])) + }; + + let n: Vec<_> = summary.preorder().collect(); + + assert_eq!(n.len(), 4); + + assert_node!( + summary, n[0]; + /* block */ 0, + /* preds */ &[], + /* descs */ &[n[1], n[2], n[3]], + /* backs */ &[n[1]] + ); + + assert_node!( + summary, n[1]; + /* block */ 3, + /* preds */ &[n[0], n[3]], + /* descs */ &[n[2]], + /* backs */ &[] + ); + + assert_node!( + summary, n[2]; + /* block */ 5, + /* preds */ &[n[1]], + /* descs */ &[], + /* backs */ &[] + ); + + assert_node!( + summary, n[3]; + /* block */ 2, + /* preds */ &[n[0]], + /* descs */ &[], + /* backs */ &[] + ); +} + +#[test] +fn loops_in_branches_summary() { + let summary = { + use Bytecode::*; + LoopSummary::new(&VMControlFlowGraph::new(&[ + /* B0, L0 */ LdTrue, + /* */ BrTrue(8), + /* B2, L5 */ Nop, + /* B3, L6 */ LdFalse, + /* */ BrFalse(3), + /* B5, L7 */ LdTrue, + /* */ BrTrue(2), + /* B7, L8 */ Branch(13), + /* B8, L1 */ Nop, + /* B9, L2 */ LdTrue, + /* */ BrTrue(8), + /* B11, L3 */ LdFalse, + /* */ BrFalse(9), + /* B13, L4 */ Ret, + ])) + }; + + let n: Vec<_> = summary.preorder().collect(); + + assert_eq!(n.len(), 9); + + assert_node!( + summary, n[0]; + /* block */ 0, + /* preds */ &[], + /* descs */ &[n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8]], + /* backs */ &[] + ); + + assert_node!( + summary, n[1]; + /* block */ 8, + /* preds */ &[n[0]], + /* descs */ &[n[2], n[3], n[4]], + /* backs */ &[n[2]] + ); + + assert_node!( + summary, n[2]; + /* block */ 9, + /* preds */ &[n[1]], + /* descs */ &[n[3], n[4]], + /* backs */ &[n[3]] + ); + + assert_node!( + summary, n[3]; + /* block */ 11, + /* preds */ &[n[2]], + /* descs */ &[n[4]], + /* backs */ &[] + ); + + assert_node!( + summary, n[4]; + /* block */ 13, + /* preds */ &[n[3], n[8]], + /* descs */ &[], + /* backs */ &[] + ); + + assert_node!( + summary, n[5]; + /* block */ 2, + /* preds */ &[n[0]], + /* descs */ &[n[6], n[7], n[8]], + /* backs */ &[n[7]] + ); + + assert_node!( + summary, n[6]; + /* block */ 3, + /* preds */ &[n[5]], + /* descs */ &[n[7], n[8]], + /* backs */ &[n[6]] + ); + + assert_node!( + summary, n[7]; + /* block */ 5, + /* preds */ &[n[6]], + /* descs */ &[n[8]], + /* backs */ &[] + ); + + assert_node!( + summary, n[8]; + /* block */ 7, + /* preds */ &[n[7]], + /* descs */ &[], + /* backs */ &[] + ); +} + +#[test] +fn loop_collapsing() { + let summary = { + use Bytecode::*; + LoopSummary::new(&VMControlFlowGraph::new(&[ + /* B0, L0 */ LdTrue, + /* */ BrTrue(4), + /* B2, L2 */ Nop, + /* */ Branch(0), + /* B4, L1 */ Ret, + ])) + }; + + let mut partition = LoopPartition::new(&summary); + let n: Vec<_> = summary.preorder().collect(); + + for id in &n { + assert_eq!(*id, partition.containing_loop(*id), "Self-parent {:?}", id); + } + + assert_eq!(partition.collapse_loop(n[0], &[n[2]].into()), 1); + assert_eq!(partition.containing_loop(n[0]), n[0]); + assert_eq!(partition.containing_loop(n[1]), n[1]); + assert_eq!(partition.containing_loop(n[2]), n[0]); +} + +#[test] +fn nested_loop_collapsing() { + let summary = { + use Bytecode::*; + LoopSummary::new(&VMControlFlowGraph::new(&[ + /* B0, L0 */ Nop, + /* B1, L1 */ LdTrue, + /* */ BrTrue(1), + /* B3, L2 */ LdFalse, + /* */ BrFalse(0), + /* B5, L3 */ LdTrue, + /* */ BrTrue(0), + /* B7, L4 */ Ret, + ])) + }; + + let mut partition = LoopPartition::new(&summary); + let n: Vec<_> = summary.preorder().collect(); + + // Self-loop is a special case -- its depth should still be bumped. + assert_eq!(partition.collapse_loop(n[1], &[].into()), 1); + assert_eq!(partition.collapse_loop(n[0], &[n[1], n[2]].into()), 2); + assert_eq!(partition.collapse_loop(n[0], &[n[0], n[3]].into()), 3); +} diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/many_back_edges.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/many_back_edges.rs new file mode 100644 index 0000000000..cb9a7ac47f --- /dev/null +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/many_back_edges.rs @@ -0,0 +1,96 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::unit_tests::production_config; +use move_binary_format::file_format::{ + empty_module, Bytecode, CodeUnit, FunctionDefinition, FunctionHandle, FunctionHandleIndex, + IdentifierIndex, ModuleHandleIndex, Signature, SignatureIndex, SignatureToken, + Visibility::Public, +}; +use move_core_types::{identifier::Identifier, vm_status::StatusCode}; + +const MAX_BASIC_BLOCKS: u16 = 1024; +const MAX_LOCALS: u8 = 255; + +const NUM_FUNCTIONS: u16 = 16; + +#[test] +fn many_backedges() { + let mut m = empty_module(); + + // signature of locals in f1..f + m.signatures.push(Signature( + std::iter::repeat(SignatureToken::U8) + .take(MAX_LOCALS as usize) + .collect(), + )); + + // create returns_bool_and_u64 + m.signatures + .push(Signature(vec![SignatureToken::Bool, SignatureToken::U8])); + m.identifiers + .push(Identifier::new("returns_bool_and_u64").unwrap()); + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(1), + parameters: SignatureIndex(0), + return_: SignatureIndex(2), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(0), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![Bytecode::LdTrue, Bytecode::LdU8(0), Bytecode::Ret], + }), + }); + + // create other functions + for i in 1..(NUM_FUNCTIONS + 1) { + m.identifiers + .push(Identifier::new(format!("f{}", i)).unwrap()); + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(i + 1), // the +1 accounts for returns_bool_and_u64 + parameters: SignatureIndex(0), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(i), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(1), + code: vec![], + }), + }); + + let code = &mut m.function_defs[i as usize].code.as_mut().unwrap().code; + + for _ in 0..(MAX_BASIC_BLOCKS - MAX_LOCALS as u16 - 2) { + code.push(Bytecode::LdTrue); + code.push(Bytecode::BrTrue(0)); + } + for i in 0..MAX_LOCALS { + code.push(Bytecode::Call(FunctionHandleIndex(0))); // calls returns_bool_and_u64 + code.push(Bytecode::StLoc(i as u8)); // i'th local is now available for the first time + code.push(Bytecode::BrTrue(0)); + } + code.push(Bytecode::Ret); + } + + let result = move_bytecode_verifier::verify_module_with_config_for_test( + "many_backedges", + &production_config(), + &m, + ); + assert_eq!( + result.unwrap_err().major_status(), + StatusCode::CONSTRAINT_NOT_SATISFIED + ); +} diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/mod.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/mod.rs index 57d1e9b847..325cdddcba 100644 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/mod.rs +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/mod.rs @@ -2,15 +2,52 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 +use move_bytecode_verifier::VerifierConfig; + pub mod ability_field_requirements_tests; +pub mod binary_samples; pub mod bounds_tests; +pub mod catch_unwind; pub mod code_unit_tests; pub mod constants_tests; pub mod control_flow_tests; pub mod dependencies_tests; pub mod duplication_tests; pub mod generic_ops_tests; +pub mod large_type_test; +pub mod limit_tests; +pub mod locals; +pub mod loop_summary_tests; +pub mod many_back_edges; pub mod multi_pass_tests; pub mod negative_stack_size_tests; +pub mod reference_safety_tests; pub mod signature_tests; pub mod struct_defs_tests; +pub mod vec_pack_tests; + +/// Configuration used in production. +pub(crate) fn production_config() -> VerifierConfig { + VerifierConfig { + max_loop_depth: Some(5), + max_generic_instantiation_length: Some(32), + max_function_parameters: Some(128), + max_basic_blocks: Some(1024), + max_basic_blocks_in_script: Some(1024), + max_value_stack_size: 1024, + max_type_nodes: Some(256), + max_push_size: Some(10000), + max_dependency_depth: Some(100), + max_struct_definitions: Some(200), + max_fields_in_struct: Some(30), + max_function_definitions: Some(1000), + + // Do not use back edge constraints as they are superseded by metering + max_back_edges_per_function: None, + max_back_edges_per_module: None, + + // Same as the default. + max_per_fun_meter_units: Some(1000 * 8000), + max_per_mod_meter_units: Some(1000 * 8000), + } +} diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/negative_stack_size_tests.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/negative_stack_size_tests.rs index ceacdcea50..c239747e3d 100644 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/negative_stack_size_tests.rs +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/negative_stack_size_tests.rs @@ -10,7 +10,7 @@ use move_core_types::vm_status::StatusCode; #[test] fn one_pop_no_push() { let module = dummy_procedure_module(vec![Bytecode::Pop, Bytecode::Ret]); - let result = CodeUnitVerifier::verify_module(&module); + let result = CodeUnitVerifier::verify_module(&Default::default(), &module); assert_eq!( result.unwrap_err().major_status(), StatusCode::NEGATIVE_STACK_SIZE_WITHIN_BLOCK @@ -21,7 +21,7 @@ fn one_pop_no_push() { fn one_pop_one_push() { // Height: 0 + (-1 + 1) = 0 would have passed original usage verifier let module = dummy_procedure_module(vec![Bytecode::ReadRef, Bytecode::Ret]); - let result = CodeUnitVerifier::verify_module(&module); + let result = CodeUnitVerifier::verify_module(&Default::default(), &module); assert_eq!( result.unwrap_err().major_status(), StatusCode::NEGATIVE_STACK_SIZE_WITHIN_BLOCK @@ -32,7 +32,7 @@ fn one_pop_one_push() { fn two_pop_one_push() { // Height: 0 + 1 + (-2 + 1) = 0 would have passed original usage verifier let module = dummy_procedure_module(vec![Bytecode::LdU64(0), Bytecode::Add, Bytecode::Ret]); - let result = CodeUnitVerifier::verify_module(&module); + let result = CodeUnitVerifier::verify_module(&Default::default(), &module); assert_eq!( result.unwrap_err().major_status(), StatusCode::NEGATIVE_STACK_SIZE_WITHIN_BLOCK @@ -42,7 +42,7 @@ fn two_pop_one_push() { #[test] fn two_pop_no_push() { let module = dummy_procedure_module(vec![Bytecode::WriteRef, Bytecode::Ret]); - let result = CodeUnitVerifier::verify_module(&module); + let result = CodeUnitVerifier::verify_module(&Default::default(), &module); assert_eq!( result.unwrap_err().major_status(), StatusCode::NEGATIVE_STACK_SIZE_WITHIN_BLOCK diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/reference_safety_tests.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/reference_safety_tests.rs new file mode 100644 index 0000000000..e063280d8f --- /dev/null +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/reference_safety_tests.rs @@ -0,0 +1,422 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::unit_tests::production_config; +use move_binary_format::file_format::{ + empty_module, Bytecode, CodeUnit, FunctionDefinition, FunctionHandle, FunctionHandleIndex, + IdentifierIndex, ModuleHandleIndex, Signature, SignatureIndex, SignatureToken, + Visibility::Public, +}; +use move_core_types::{identifier::Identifier, vm_status::StatusCode}; + +#[test] +fn test_bicliques() { + // See also: github.com/aptos-labs/aptos-core/security/advisories/GHSA-xm6p-ffcq-5p2v + const NUM_LOCALS: u8 = 128; + const NUM_CALLS: u16 = 76; + const NUM_FUNCTIONS: u16 = 1; + + let mut m = empty_module(); + + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(0), + parameters: SignatureIndex(0), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(0), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![Bytecode::Call(FunctionHandleIndex(0)), Bytecode::Ret], + }), + }); + + // create take_and_return_references + m.signatures.push(Signature( + std::iter::repeat(SignatureToken::Reference(Box::new(SignatureToken::U64))) + .take(NUM_LOCALS as usize) + .collect(), + )); + m.identifiers + .push(Identifier::new("take_and_return_references").unwrap()); + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(1), + parameters: SignatureIndex(1), + return_: SignatureIndex(1), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(1), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![], + }), + }); + let code = &mut m.function_defs[1].code.as_mut().unwrap().code; + for i in 0..NUM_LOCALS { + code.push(Bytecode::MoveLoc(i)); + } + code.push(Bytecode::Ret); + + // create swallow_references + m.identifiers + .push(Identifier::new("swallow_references").unwrap()); + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(2), + parameters: SignatureIndex(1), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(2), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![Bytecode::Ret], + }), + }); + + // create other functions + for i in 1..(NUM_FUNCTIONS + 1) { + m.identifiers + .push(Identifier::new(format!("f{}", i)).unwrap()); + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(i + 2), + parameters: SignatureIndex(1), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(i + 2), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![], + }), + }); + let code = &mut m.function_defs[i as usize + 2].code.as_mut().unwrap().code; + for j in 0..NUM_LOCALS { + code.push(Bytecode::CopyLoc(j)); + } + for _ in 0..NUM_CALLS { + code.push(Bytecode::Call(FunctionHandleIndex(1))); + } + code.push(Bytecode::Call(FunctionHandleIndex(2))); + code.push(Bytecode::Ret); + } + + let result = move_bytecode_verifier::verify_module_with_config_for_test( + "test_bicliques", + &production_config(), + &m, + ); + assert_eq!( + result.unwrap_err().major_status(), + StatusCode::CONSTRAINT_NOT_SATISFIED + ); +} + +#[test] +fn test_merge_state_large_graph() { + // See also: github.com/aptos-labs/aptos-core/security/advisories/GHSA-g8v8-fw4c-8h82 + const N: u8 = 127; + const NUM_NOP_BLOCKS: u16 = 950; + const NUM_FUNCTIONS: u16 = 18; + + let mut m = empty_module(); + + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(0), + parameters: SignatureIndex(0), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(0), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![Bytecode::Call(FunctionHandleIndex(0)), Bytecode::Ret], + }), + }); + + m.signatures.push(Signature( + std::iter::repeat(SignatureToken::Reference(Box::new(SignatureToken::U8))) + .take(N as usize) + .collect(), + )); + + m.identifiers.push(Identifier::new("return_refs").unwrap()); + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(1), + parameters: SignatureIndex(0), + return_: SignatureIndex(1), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(1), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![Bytecode::Call(FunctionHandleIndex(1)), Bytecode::Ret], + }), + }); + + m.identifiers + .push(Identifier::new("take_and_return_refs").unwrap()); + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(2), + parameters: SignatureIndex(1), + return_: SignatureIndex(1), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(2), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![Bytecode::Call(FunctionHandleIndex(1)), Bytecode::Ret], + }), + }); + + for i in 0..NUM_FUNCTIONS { + m.identifiers + .push(Identifier::new(format!("f{}", i)).unwrap()); + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(i + 3), + parameters: SignatureIndex(1), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(i + 3), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(1), + code: vec![], + }), + }); + let code = &mut m.function_defs[i as usize + 3].code.as_mut().unwrap().code; + for j in 0..N { + code.push(Bytecode::CopyLoc(j)); + } + code.push(Bytecode::Call(FunctionHandleIndex(2))); + for j in 0..N { + code.push(Bytecode::StLoc(N + j)); + } + for _ in 0..NUM_NOP_BLOCKS { + code.push(Bytecode::LdTrue); + code.push(Bytecode::BrTrue(0)); + } + + code.push(Bytecode::Ret); + } + + let res = move_bytecode_verifier::verify_module_with_config_for_test( + "test_merge_state_large_graph", + &production_config(), + &m, + ); + assert_eq!( + res.unwrap_err().major_status(), + StatusCode::CONSTRAINT_NOT_SATISFIED + ); +} + +#[test] +fn test_merge_state() { + // See also: github.com/aptos-labs/aptos-core/security/advisories/GHSA-g8v8-fw4c-8h82 + const NUM_NOP_BLOCKS: u16 = 965; + const NUM_LOCALS: u8 = 32; + const NUM_FUNCTIONS: u16 = 21; + + let mut m = empty_module(); + + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(0), + parameters: SignatureIndex(0), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(0), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![Bytecode::Call(FunctionHandleIndex(0)), Bytecode::Ret], + }), + }); + + m.signatures + .push(Signature(vec![SignatureToken::Reference(Box::new( + SignatureToken::U8, + ))])); + m.signatures.push(Signature( + std::iter::repeat(SignatureToken::Reference(Box::new(SignatureToken::U8))) + .take(NUM_LOCALS as usize - 1) + .collect(), + )); + + for i in 0..NUM_FUNCTIONS { + m.identifiers + .push(Identifier::new(format!("f{}", i)).unwrap()); + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(i + 1), + parameters: SignatureIndex(1), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(i + 1), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(2), + code: vec![], + }), + }); + let code = &mut m.function_defs[i as usize + 1].code.as_mut().unwrap().code; + // create reference id + code.push(Bytecode::CopyLoc(0)); + code.push(Bytecode::StLoc(1)); + // create a path of length NUM_LOCALS - 1 in the borrow graph + for j in 0..(NUM_LOCALS - 2) { + // create Ref(new_id) and factor in empty-path edge id -> new_id + code.push(Bytecode::CopyLoc(1)); + // can't leave those references on stack since basic blocks need to be stack-neutral + code.push(Bytecode::StLoc(j + 2)); + } + for _ in 0..NUM_NOP_BLOCKS { + code.push(Bytecode::LdTrue); + // create back edge to first block + code.push(Bytecode::BrTrue(0)); + } + + code.push(Bytecode::Ret); + } + + let res = move_bytecode_verifier::verify_module_with_config_for_test( + "test_merge_state", + &production_config(), + &m, + ); + assert_eq!( + res.unwrap_err().major_status(), + StatusCode::CONSTRAINT_NOT_SATISFIED + ); +} + +#[test] +fn test_copyloc_pop() { + // See also: github.com/aptos-labs/aptos-core/security/advisories/GHSA-2qvr-c9qp-wch7 + const NUM_COPYLOCS: u16 = 1880; + const NUM_CHILDREN: u16 = 1020; + const NUM_FUNCTIONS: u16 = 2; + + let mut m = empty_module(); + + // parameters of f0, f1, ... + m.signatures + .push(Signature(vec![SignatureToken::Reference(Box::new( + SignatureToken::Vector(Box::new(SignatureToken::U8)), + ))])); + // locals of f0, f1, ... + m.signatures.push(Signature(vec![ + SignatureToken::Reference(Box::new(SignatureToken::Vector(Box::new( + SignatureToken::U8, + )))), + SignatureToken::U8, // ignore this, it's just here because I don't want to fix indices and the TypeParameter after removing the collision + ])); + // for VecImmBorrow + m.signatures.push(Signature( + std::iter::repeat(SignatureToken::U8).take(1).collect(), + )); + m.signatures + .push(Signature(vec![SignatureToken::TypeParameter(0)])); + + for i in 0..NUM_FUNCTIONS { + m.identifiers + .push(Identifier::new(format!("f{}", i)).unwrap()); + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(i), + parameters: SignatureIndex(1), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(i), + visibility: Public, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(2), + code: vec![], + }), + }); + let code = &mut m.function_defs[i as usize].code.as_mut().unwrap().code; + + // create reference id + code.push(Bytecode::CopyLoc(0)); + code.push(Bytecode::StLoc(1)); + // create NUM_CHLIDREN children of id + for _ in 0..NUM_CHILDREN { + code.push(Bytecode::CopyLoc(1)); + code.push(Bytecode::LdU64(0)); + code.push(Bytecode::VecImmBorrow(SignatureIndex(3))); + } + // then do a whole lot of copylocs on that reference + for _ in 0..NUM_COPYLOCS { + code.push(Bytecode::CopyLoc(1)); + code.push(Bytecode::Pop); + } + for _ in 0..NUM_CHILDREN { + code.push(Bytecode::Pop); + } + + code.push(Bytecode::Ret); + } + + let result = move_bytecode_verifier::verify_module_with_config_for_test( + "test_copyloc_pop", + &production_config(), + &m, + ); + assert_eq!( + result.unwrap_err().major_status(), + StatusCode::CONSTRAINT_NOT_SATISFIED + ); +} diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/signature_tests.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/signature_tests.rs index b077852144..30729e5a17 100644 --- a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/signature_tests.rs +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/signature_tests.rs @@ -2,10 +2,15 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 +use crate::unit_tests::production_config; use invalid_mutations::signature::{FieldRefMutation, SignatureRefMutation}; -use move_binary_format::file_format::{Bytecode::*, CompiledModule, SignatureToken::*, *}; -use move_bytecode_verifier::{verify_module, SignatureChecker}; -use move_core_types::{account_address::AccountAddress, identifier::Identifier}; +use move_binary_format::file_format::{ + Bytecode::*, CompiledModule, SignatureToken::*, Visibility::Public, *, +}; +use move_bytecode_verifier::{verify_module, verify_module_with_config_for_test, SignatureChecker}; +use move_core_types::{ + account_address::AccountAddress, identifier::Identifier, vm_status::StatusCode, +}; use proptest::{collection::vec, prelude::*, sample::Index as PropIndex}; #[test] @@ -121,3 +126,95 @@ fn no_verify_locals_good() { }; assert!(verify_module(&compiled_module_good).is_ok()); } + +#[test] +fn big_signature_test() { + const N_TYPE_PARAMS: usize = 5; + const INSTANTIATION_DEPTH: usize = 3; + const VECTOR_DEPTH: usize = 250; + let mut st = SignatureToken::U8; + for _ in 0..VECTOR_DEPTH { + st = SignatureToken::Vector(Box::new(st)); + } + for _ in 0..INSTANTIATION_DEPTH { + let type_params = vec![st; N_TYPE_PARAMS]; + st = SignatureToken::StructInstantiation(StructHandleIndex(0), type_params); + } + + const N_READPOP: u16 = 7500; + + let mut code = vec![]; + // 1. ImmBorrowLoc: ... ref + // 2. ReadRef: ... value + // 3. Pop: ... + for _ in 0..N_READPOP { + code.push(Bytecode::ImmBorrowLoc(0)); + code.push(Bytecode::ReadRef); + code.push(Bytecode::Pop); + } + code.push(Bytecode::Ret); + + let type_param_constraints = StructTypeParameter { + constraints: AbilitySet::EMPTY, + is_phantom: false, + }; + + let module = CompiledModule { + version: 5, + self_module_handle_idx: ModuleHandleIndex(0), + module_handles: vec![ModuleHandle { + address: AddressIdentifierIndex(0), + name: IdentifierIndex(0), + }], + struct_handles: vec![StructHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(1), + abilities: AbilitySet::ALL, + type_parameters: vec![type_param_constraints; N_TYPE_PARAMS], + }], + function_handles: vec![FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(0), + parameters: SignatureIndex(1), + return_: SignatureIndex(0), + type_parameters: vec![], + }], + field_handles: vec![], + friend_decls: vec![], + struct_def_instantiations: vec![], + function_instantiations: vec![], + field_instantiations: vec![], + signatures: vec![Signature(vec![]), Signature(vec![st])], + identifiers: vec![ + Identifier::new("f").unwrap(), + Identifier::new("generic_struct").unwrap(), + ], + address_identifiers: vec![AccountAddress::ONE], + constant_pool: vec![], + metadata: vec![], + struct_defs: vec![StructDefinition { + struct_handle: StructHandleIndex(0), + field_information: StructFieldInformation::Native, + }], + function_defs: vec![FunctionDefinition { + function: FunctionHandleIndex(0), + visibility: Public, + is_entry: true, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code, + }), + }], + }; + + // save module and verify that it can ser/de + let mut mvbytes = vec![]; + module.serialize(&mut mvbytes).unwrap(); + let module = CompiledModule::deserialize(&mvbytes).unwrap(); + + let res = + verify_module_with_config_for_test("big_signature_test", &production_config(), &module) + .unwrap_err(); + assert_eq!(res.major_status(), StatusCode::TOO_MANY_TYPE_NODES); +} diff --git a/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/vec_pack_tests.rs b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/vec_pack_tests.rs new file mode 100644 index 0000000000..8a1b5b27f9 --- /dev/null +++ b/language/move-bytecode-verifier/bytecode-verifier-tests/src/unit_tests/vec_pack_tests.rs @@ -0,0 +1,69 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use crate::unit_tests::production_config; +use move_binary_format::file_format::{ + empty_module, Bytecode, CodeUnit, FunctionDefinition, FunctionHandle, FunctionHandleIndex, + IdentifierIndex, ModuleHandleIndex, Signature, SignatureIndex, SignatureToken, Visibility, +}; +use move_core_types::{identifier::Identifier, vm_status::StatusCode}; + +fn vec_sig(len: usize) -> SignatureToken { + if len > 0 { + SignatureToken::Vector(Box::new(vec_sig(len - 1))) + } else { + SignatureToken::U8 + } +} + +#[test] +fn test_vec_pack() { + let mut m = empty_module(); + + let sig = SignatureIndex(m.signatures.len() as u16); + m.signatures.push(Signature(vec![vec_sig(255)])); + + m.function_defs.push(FunctionDefinition { + function: FunctionHandleIndex(0), + visibility: Visibility::Private, + is_entry: false, + acquires_global_resources: vec![], + code: Some(CodeUnit { + locals: SignatureIndex(0), + code: vec![], + }), + }); + + m.function_handles.push(FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(m.identifiers.len() as u16), + parameters: SignatureIndex(0), + return_: SignatureIndex(0), + type_parameters: vec![], + }); + m.identifiers + .push(Identifier::new("foo".to_string()).unwrap()); + + const COUNT: usize = 3000; + + m.function_defs[0].code.as_mut().unwrap().code = + std::iter::once(&[Bytecode::VecPack(sig, 0)][..]) + .chain( + std::iter::repeat( + &[Bytecode::VecUnpack(sig, 1024), Bytecode::VecPack(sig, 1024)][..], + ) + .take(COUNT), + ) + .chain(std::iter::once(&[Bytecode::Pop, Bytecode::Ret][..])) + .flatten() + .cloned() + .collect(); + + let res = move_bytecode_verifier::verify_module_with_config_for_test( + "test_vec_pack", + &production_config(), + &m, + ) + .unwrap_err(); + assert_eq!(res.major_status(), StatusCode::VALUE_STACK_PUSH_OVERFLOW); +} diff --git a/language/move-bytecode-verifier/fuzz/.gitignore b/language/move-bytecode-verifier/fuzz/.gitignore new file mode 100644 index 0000000000..a0925114d6 --- /dev/null +++ b/language/move-bytecode-verifier/fuzz/.gitignore @@ -0,0 +1,3 @@ +target +corpus +artifacts diff --git a/language/move-bytecode-verifier/fuzz/Cargo.toml b/language/move-bytecode-verifier/fuzz/Cargo.toml new file mode 100644 index 0000000000..90c2a406bd --- /dev/null +++ b/language/move-bytecode-verifier/fuzz/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "bytecode-verifier-libfuzzer" +version = "0.0.0" +authors = ["Diem Association "] +license = "Apache-2.0" +publish = false +edition = "2018" + +[package.metadata] +cargo-fuzz = true + +[dependencies] +libfuzzer-sys = "0.4" +arbitrary = "1.1.7" +move-bytecode-verifier = { path = "../" } +move-core-types = { path = "../../move-core/types", features = ["fuzzing"] } +move-binary-format = { path = "../../move-binary-format", features = ["fuzzing"] } + +# Prevent this from interfering with workspaces +#[workspace] +#members = ["."] + +[[bin]] +name = "code_unit" +path = "fuzz_targets/code_unit.rs" +test = false +doc = false + +[[bin]] +name = "compiled_module" +path = "fuzz_targets/compiled_module.rs" +test = false +doc = false + +[[bin]] +name = "mixed" +path = "fuzz_targets/mixed.rs" +test = false +doc = false diff --git a/language/move-bytecode-verifier/fuzz/README.md b/language/move-bytecode-verifier/fuzz/README.md new file mode 100644 index 0000000000..633a4797a4 --- /dev/null +++ b/language/move-bytecode-verifier/fuzz/README.md @@ -0,0 +1,4 @@ +See the [Rust fuzzing book](https://rust-fuzz.github.io/book/) +for how to use the fuzz targets in this directory. Notice that +`cargo +nightly fuzz run ` need to be executed in the parent +directory; nightly is required. diff --git a/language/move-bytecode-verifier/fuzz/fuzz_targets/code_unit.rs b/language/move-bytecode-verifier/fuzz/fuzz_targets/code_unit.rs new file mode 100644 index 0000000000..32d4cb8ac5 --- /dev/null +++ b/language/move-bytecode-verifier/fuzz/fuzz_targets/code_unit.rs @@ -0,0 +1,83 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +#![no_main] +use move_binary_format::file_format::{ + empty_module, AbilitySet, CodeUnit, Constant, FieldDefinition, FunctionDefinition, + FunctionHandle, FunctionHandleIndex, IdentifierIndex, ModuleHandleIndex, Signature, + SignatureIndex, + SignatureToken::{Address, Bool, U128, U64}, + StructDefinition, StructFieldInformation, StructHandle, StructHandleIndex, TypeSignature, + Visibility, +}; +use move_core_types::{account_address::AccountAddress, identifier::Identifier}; +use std::str::FromStr; + +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|code_unit: CodeUnit| { + let mut module = empty_module(); + module.version = 5; + + module.struct_handles.push(StructHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(1), + abilities: AbilitySet::ALL, + type_parameters: vec![], + }); + + let fun_handle = FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(2), + parameters: SignatureIndex(0), + return_: SignatureIndex(1), + type_parameters: vec![], + }; + + module.function_handles.push(fun_handle); + + module.signatures.pop(); + module.signatures.push(Signature(vec![ + Address, U64, Address, Address, U128, Address, U64, U64, U64, + ])); + module.signatures.push(Signature(vec![])); + module + .signatures + .push(Signature(vec![Address, Bool, Address])); + + module.identifiers.extend( + vec![ + Identifier::from_str("zf_hello_world").unwrap(), + Identifier::from_str("awldFnU18mlDKQfh6qNfBGx8X").unwrap(), + Identifier::from_str("aQPwJNHyAHpvJ").unwrap(), + Identifier::from_str("aT7ZphKTrKcYCwCebJySrmrKlckmnL5").unwrap(), + Identifier::from_str("arYpsFa2fvrpPJ").unwrap(), + ] + .into_iter(), + ); + module.address_identifiers.push(AccountAddress::random()); + + module.constant_pool.push(Constant { + type_: Address, + data: AccountAddress::ZERO.into_bytes().to_vec(), + }); + + module.struct_defs.push(StructDefinition { + struct_handle: StructHandleIndex(0), + field_information: StructFieldInformation::Declared(vec![FieldDefinition { + name: IdentifierIndex::new(3), + signature: TypeSignature(Address), + }]), + }); + + let fun_def = FunctionDefinition { + code: Some(code_unit), + function: FunctionHandleIndex(0), + visibility: Visibility::Public, + is_entry: false, + acquires_global_resources: vec![], + }; + + module.function_defs.push(fun_def); + let _ = move_bytecode_verifier::verify_module(&module); +}); diff --git a/language/move-bytecode-verifier/fuzz/fuzz_targets/compiled_module.rs b/language/move-bytecode-verifier/fuzz/fuzz_targets/compiled_module.rs new file mode 100644 index 0000000000..ba077a820d --- /dev/null +++ b/language/move-bytecode-verifier/fuzz/fuzz_targets/compiled_module.rs @@ -0,0 +1,10 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +#![no_main] +use libfuzzer_sys::fuzz_target; +use move_binary_format::file_format::CompiledModule; + +fuzz_target!(|module: CompiledModule| { + let _ = move_bytecode_verifier::verify_module(&module); +}); diff --git a/language/move-bytecode-verifier/fuzz/fuzz_targets/mixed.rs b/language/move-bytecode-verifier/fuzz/fuzz_targets/mixed.rs new file mode 100644 index 0000000000..35df4a5f2f --- /dev/null +++ b/language/move-bytecode-verifier/fuzz/fuzz_targets/mixed.rs @@ -0,0 +1,97 @@ +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +#![no_main] +use move_binary_format::file_format::{ + empty_module, AbilitySet, Bytecode, CodeUnit, Constant, FieldDefinition, FunctionDefinition, + FunctionHandle, FunctionHandleIndex, IdentifierIndex, ModuleHandleIndex, Signature, + SignatureIndex, SignatureToken, + SignatureToken::{Address, Bool}, + StructDefinition, StructFieldInformation, StructHandle, StructHandleIndex, TypeSignature, + Visibility, +}; +use move_core_types::{account_address::AccountAddress, identifier::Identifier}; +use std::str::FromStr; + +use arbitrary::Arbitrary; +use libfuzzer_sys::fuzz_target; + +#[derive(Arbitrary, Debug)] +struct Mixed { + code: Vec, + abilities: AbilitySet, + param_types: Vec, + return_type: Option, +} + +fuzz_target!(|mix: Mixed| { + let mut module = empty_module(); + module.version = 5; + + module.struct_handles.push(StructHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(1), + abilities: mix.abilities, + type_parameters: vec![], + }); + + let fun_handle = FunctionHandle { + module: ModuleHandleIndex(0), + name: IdentifierIndex(2), + parameters: SignatureIndex(0), + return_: SignatureIndex(1), + type_parameters: vec![], + }; + + module.function_handles.push(fun_handle); + + module.signatures.pop(); + module.signatures.push(Signature(mix.param_types)); + module.signatures.push(Signature( + mix.return_type.map(|s| vec![s]).unwrap_or_default(), + )); + module + .signatures + .push(Signature(vec![Address, Bool, Address])); + + module.identifiers.extend( + vec![ + Identifier::from_str("zf_hello_world").unwrap(), + Identifier::from_str("awldFnU18mlDKQfh6qNfBGx8X").unwrap(), + Identifier::from_str("aQPwJNHyAHpvJ").unwrap(), + Identifier::from_str("aT7ZphKTrKcYCwCebJySrmrKlckmnL5").unwrap(), + Identifier::from_str("arYpsFa2fvrpPJ").unwrap(), + ] + .into_iter(), + ); + module.address_identifiers.push(AccountAddress::random()); + + module.constant_pool.push(Constant { + type_: Address, + data: AccountAddress::ZERO.into_bytes().to_vec(), + }); + + module.struct_defs.push(StructDefinition { + struct_handle: StructHandleIndex(0), + field_information: StructFieldInformation::Declared(vec![FieldDefinition { + name: IdentifierIndex::new(3), + signature: TypeSignature(Address), + }]), + }); + + let code_unit = CodeUnit { + code: mix.code, + locals: SignatureIndex(0), + }; + + let fun_def = FunctionDefinition { + code: Some(code_unit), + function: FunctionHandleIndex(0), + visibility: Visibility::Public, + is_entry: false, + acquires_global_resources: vec![], + }; + + module.function_defs.push(fun_def); + let _ = move_bytecode_verifier::verify_module(&module); +}); diff --git a/language/move-bytecode-verifier/invalid-mutations/Cargo.toml b/language/move-bytecode-verifier/invalid-mutations/Cargo.toml index 5f6fc2617c..ed46af714c 100644 --- a/language/move-bytecode-verifier/invalid-mutations/Cargo.toml +++ b/language/move-bytecode-verifier/invalid-mutations/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "invalid-mutations" version = "0.1.0" -edition = "2018" +edition = "2021" authors = ["Diem Association "] description = "Diem invalid mutations" repository = "https://github.com/diem/diem" diff --git a/language/move-bytecode-verifier/invalid-mutations/src/bounds.rs b/language/move-bytecode-verifier/invalid-mutations/src/bounds.rs index e3d0d9d2af..b4d31c2011 100644 --- a/language/move-bytecode-verifier/invalid-mutations/src/bounds.rs +++ b/language/move-bytecode-verifier/invalid-mutations/src/bounds.rs @@ -358,6 +358,7 @@ fn struct_handle(token: &SignatureToken) -> Option { Struct(sh_idx) => Some(*sh_idx), StructInstantiation(sh_idx, _) => Some(*sh_idx), Reference(token) | MutableReference(token) => struct_handle(token), - Bool | U8 | U64 | U128 | Address | Signer | Vector(_) | TypeParameter(_) => None, + Bool | U8 | U16 | U32 | U64 | U128 | U256 | Address | Signer | Vector(_) + | TypeParameter(_) => None, } } diff --git a/language/move-bytecode-verifier/invalid-mutations/src/bounds/code_unit.rs b/language/move-bytecode-verifier/invalid-mutations/src/bounds/code_unit.rs index 6396835a23..18085317dc 100644 --- a/language/move-bytecode-verifier/invalid-mutations/src/bounds/code_unit.rs +++ b/language/move-bytecode-verifier/invalid-mutations/src/bounds/code_unit.rs @@ -478,8 +478,9 @@ impl<'a> ApplyCodeUnitBoundsContext<'a> { // List out the other options explicitly so there's a compile error if a new // bytecode gets added. - FreezeRef | Pop | Ret | LdU8(_) | LdU64(_) | LdU128(_) | CastU8 | CastU64 - | CastU128 | LdTrue | LdFalse | ReadRef | WriteRef | Add | Sub | Mul | Mod + FreezeRef | Pop | Ret | LdU8(_) | LdU16(_) | LdU32(_) | LdU64(_) + | LdU128(_) | LdU256(_) | CastU8 | CastU16 | CastU32 | CastU64 | CastU128 + | CastU256 | LdTrue | LdFalse | ReadRef | WriteRef | Add | Sub | Mul | Mod | Div | BitOr | BitAnd | Xor | Shl | Shr | Or | And | Not | Eq | Neq | Lt | Gt | Le | Ge | Abort | Nop => { panic!("Bytecode has no internal index: {:?}", code[bytecode_idx]) @@ -538,8 +539,9 @@ fn is_interesting(bytecode: &Bytecode) -> bool { // List out the other options explicitly so there's a compile error if a new // bytecode gets added. - FreezeRef | Pop | Ret | LdU8(_) | LdU64(_) | LdU128(_) | CastU8 | CastU64 | CastU128 - | LdTrue | LdFalse | ReadRef | WriteRef | Add | Sub | Mul | Mod | Div | BitOr | BitAnd - | Xor | Shl | Shr | Or | And | Not | Eq | Neq | Lt | Gt | Le | Ge | Abort | Nop => false, + FreezeRef | Pop | Ret | LdU8(_) | LdU16(_) | LdU32(_) | LdU64(_) | LdU128(_) + | LdU256(_) | CastU8 | CastU16 | CastU32 | CastU64 | CastU128 | CastU256 | LdTrue + | LdFalse | ReadRef | WriteRef | Add | Sub | Mul | Mod | Div | BitOr | BitAnd | Xor + | Shl | Shr | Or | And | Not | Eq | Neq | Lt | Gt | Le | Ge | Abort | Nop => false, } } diff --git a/language/move-bytecode-verifier/src/absint.rs b/language/move-bytecode-verifier/src/absint.rs index acb4077ced..9945d6f3d7 100644 --- a/language/move-bytecode-verifier/src/absint.rs +++ b/language/move-bytecode-verifier/src/absint.rs @@ -2,9 +2,11 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 +use crate::meter::Meter; use move_binary_format::{ binary_views::FunctionView, control_flow_graph::{BlockId, ControlFlowGraph}, + errors::PartialVMResult, file_format::{Bytecode, CodeOffset}, }; use std::collections::BTreeMap; @@ -12,7 +14,7 @@ use std::collections::BTreeMap; /// Trait for finite-height abstract domains. Infinite height domains would require a more complex /// trait with widening and a partial order. pub trait AbstractDomain: Clone + Sized { - fn join(&mut self, other: &Self) -> JoinResult; + fn join(&mut self, other: &Self, meter: &mut impl Meter) -> PartialVMResult; } #[derive(Debug)] @@ -21,36 +23,22 @@ pub enum JoinResult { Unchanged, } -#[derive(Clone)] -pub enum BlockPostcondition { - /// Block not yet analyzed - Unprocessed, - /// Analyzing block was successful - /// TODO might carry post state at some point - Success, - /// Analyzing block resulted in an error - Error(AnalysisError), -} - #[allow(dead_code)] #[derive(Clone)] -pub struct BlockInvariant { +pub struct BlockInvariant { /// Precondition of the block - pub pre: State, - /// Postcondition of the block - pub post: BlockPostcondition, + pre: State, } /// A map from block id's to the pre/post of each block after a fixed point is reached. #[allow(dead_code)] -pub type InvariantMap = - BTreeMap>; +pub type InvariantMap = BTreeMap>; /// Take a pre-state + instruction and mutate it to produce a post-state /// Auxiliary data can be stored in self. pub trait TransferFunctions { type State: AbstractDomain; - type AnalysisError; + type Error; /// Execute local@instr found at index local@index in the current basic block from pre-state /// local@pre. @@ -68,7 +56,8 @@ pub trait TransferFunctions { instr: &Bytecode, index: CodeOffset, last_index: CodeOffset, - ) -> Result<(), Self::AnalysisError>; + meter: &mut impl Meter, + ) -> PartialVMResult<()>; } pub trait AbstractInterpreter: TransferFunctions { @@ -77,17 +66,12 @@ pub trait AbstractInterpreter: TransferFunctions { &mut self, initial_state: Self::State, function_view: &FunctionView, - ) -> InvariantMap { - let mut inv_map: InvariantMap = InvariantMap::new(); + meter: &mut impl Meter, + ) -> PartialVMResult<()> { + let mut inv_map = InvariantMap::new(); let entry_block_id = function_view.cfg().entry_block_id(); let mut next_block = Some(entry_block_id); - inv_map.insert( - entry_block_id, - BlockInvariant { - pre: initial_state, - post: BlockPostcondition::Unprocessed, - }, - ); + inv_map.insert(entry_block_id, BlockInvariant { pre: initial_state }); while let Some(block_id) = next_block { let block_invariant = match inv_map.get_mut(&block_id) { @@ -101,17 +85,9 @@ pub trait AbstractInterpreter: TransferFunctions { }; let pre_state = &block_invariant.pre; - let post_state = match self.execute_block(block_id, pre_state, function_view) { - Err(e) => { - block_invariant.post = BlockPostcondition::Error(e); - next_block = function_view.cfg().next_block(block_id); - continue; - } - Ok(s) => { - block_invariant.post = BlockPostcondition::Success; - s - } - }; + // Note: this will stop analysis after the first error occurs, to avoid the risk of + // subsequent crashes + let post_state = self.execute_block(block_id, pre_state, function_view, meter)?; let mut next_block_candidate = function_view.cfg().next_block(block_id); // propagate postcondition of this block to successor blocks @@ -120,8 +96,8 @@ pub trait AbstractInterpreter: TransferFunctions { Some(next_block_invariant) => { let join_result = { let old_pre = &mut next_block_invariant.pre; - old_pre.join(&post_state) - }; + old_pre.join(&post_state, meter) + }?; match join_result { JoinResult::Unchanged => { // Pre is the same after join. Reanalyzing this block would produce @@ -136,8 +112,6 @@ pub trait AbstractInterpreter: TransferFunctions { { next_block_candidate = Some(*successor_block_id); } - // Pre has changed, the post condition is now unknown for the block - next_block_invariant.post = BlockPostcondition::Unprocessed } } } @@ -148,7 +122,6 @@ pub trait AbstractInterpreter: TransferFunctions { *successor_block_id, BlockInvariant { pre: post_state.clone(), - post: BlockPostcondition::Success, }, ); } @@ -156,7 +129,7 @@ pub trait AbstractInterpreter: TransferFunctions { } next_block = next_block_candidate; } - inv_map + Ok(()) } fn execute_block( @@ -164,12 +137,13 @@ pub trait AbstractInterpreter: TransferFunctions { block_id: BlockId, pre_state: &Self::State, function_view: &FunctionView, - ) -> Result { + meter: &mut impl Meter, + ) -> PartialVMResult { let mut state_acc = pre_state.clone(); let block_end = function_view.cfg().block_end(block_id); for offset in function_view.cfg().instr_indexes(block_id) { let instr = &function_view.code().code[offset as usize]; - self.execute(&mut state_acc, instr, offset, block_end)? + self.execute(&mut state_acc, instr, offset, block_end, meter)? } Ok(state_acc) } diff --git a/language/move-bytecode-verifier/src/acquires_list_verifier.rs b/language/move-bytecode-verifier/src/acquires_list_verifier.rs index de034ff742..9bad9e5731 100644 --- a/language/move-bytecode-verifier/src/acquires_list_verifier.rs +++ b/language/move-bytecode-verifier/src/acquires_list_verifier.rs @@ -11,6 +11,9 @@ //! - No missing resources (any resource acquired must be present) //! - No additional resources (no extraneous resources not actually acquired) +use std::collections::{BTreeSet, HashMap}; + +use crate::meter::Meter; use move_binary_format::{ access::ModuleAccess, errors::{PartialVMError, PartialVMResult}, @@ -18,9 +21,9 @@ use move_binary_format::{ Bytecode, CodeOffset, CompiledModule, FunctionDefinition, FunctionDefinitionIndex, FunctionHandle, FunctionHandleIndex, StructDefinitionIndex, }, + safe_unwrap, }; use move_core_types::vm_status::StatusCode; -use std::collections::{BTreeSet, HashMap}; pub(crate) struct AcquiresVerifier<'a> { module: &'a CompiledModule, @@ -35,8 +38,9 @@ impl<'a> AcquiresVerifier<'a> { module: &'a CompiledModule, index: FunctionDefinitionIndex, function_definition: &'a FunctionDefinition, + _meter: &mut impl Meter, // currently unused ) -> PartialVMResult<()> { - let annotated_acquires = function_definition + let annotated_acquires: BTreeSet<_> = function_definition .acquires_global_resources .iter() .cloned() @@ -53,10 +57,7 @@ impl<'a> AcquiresVerifier<'a> { handle_to_def, }; - for (offset, instruction) in function_definition - .code - .as_ref() - .unwrap() + for (offset, instruction) in safe_unwrap!(function_definition.code.as_ref()) .code .iter() .enumerate() @@ -71,7 +72,7 @@ impl<'a> AcquiresVerifier<'a> { )); } - let struct_def = module.struct_defs().get(annotation.0 as usize).unwrap(); + let struct_def = safe_unwrap!(module.struct_defs().get(annotation.0 as usize)); let struct_handle = module.struct_handle_at(struct_def.struct_handle); if !struct_handle.abilities.has_key() { return Err(PartialVMError::new(StatusCode::INVALID_ACQUIRES_ANNOTATION)); @@ -101,7 +102,76 @@ impl<'a> AcquiresVerifier<'a> { let si = self.module.struct_instantiation_at(*idx); self.struct_acquire(si.def, offset) } - _ => Ok(()), + + Bytecode::Pop + | Bytecode::BrTrue(_) + | Bytecode::BrFalse(_) + | Bytecode::Abort + | Bytecode::Branch(_) + | Bytecode::Nop + | Bytecode::Ret + | Bytecode::StLoc(_) + | Bytecode::MoveLoc(_) + | Bytecode::CopyLoc(_) + | Bytecode::ImmBorrowLoc(_) + | Bytecode::MutBorrowLoc(_) + | Bytecode::FreezeRef + | Bytecode::MutBorrowField(_) + | Bytecode::MutBorrowFieldGeneric(_) + | Bytecode::ImmBorrowField(_) + | Bytecode::ImmBorrowFieldGeneric(_) + | Bytecode::LdU8(_) + | Bytecode::LdU16(_) + | Bytecode::LdU32(_) + | Bytecode::LdU64(_) + | Bytecode::LdU128(_) + | Bytecode::LdU256(_) + | Bytecode::LdConst(_) + | Bytecode::LdTrue + | Bytecode::LdFalse + | Bytecode::Pack(_) + | Bytecode::PackGeneric(_) + | Bytecode::Unpack(_) + | Bytecode::UnpackGeneric(_) + | Bytecode::ReadRef + | Bytecode::WriteRef + | Bytecode::CastU8 + | Bytecode::CastU16 + | Bytecode::CastU32 + | Bytecode::CastU64 + | Bytecode::CastU128 + | Bytecode::CastU256 + | Bytecode::Add + | Bytecode::Sub + | Bytecode::Mul + | Bytecode::Mod + | Bytecode::Div + | Bytecode::BitOr + | Bytecode::BitAnd + | Bytecode::Xor + | Bytecode::Shl + | Bytecode::Shr + | Bytecode::Or + | Bytecode::And + | Bytecode::Not + | Bytecode::Eq + | Bytecode::Neq + | Bytecode::Lt + | Bytecode::Gt + | Bytecode::Le + | Bytecode::Ge + | Bytecode::Exists(_) + | Bytecode::ExistsGeneric(_) + | Bytecode::MoveTo(_) + | Bytecode::MoveToGeneric(_) + | Bytecode::VecPack(..) + | Bytecode::VecLen(_) + | Bytecode::VecImmBorrow(_) + | Bytecode::VecMutBorrow(_) + | Bytecode::VecPushBack(_) + | Bytecode::VecPopBack(_) + | Bytecode::VecUnpack(..) + | Bytecode::VecSwap(_) => Ok(()), } } diff --git a/language/move-bytecode-verifier/src/code_unit_verifier.rs b/language/move-bytecode-verifier/src/code_unit_verifier.rs index 13b96b20e5..265d86f3c2 100644 --- a/language/move-bytecode-verifier/src/code_unit_verifier.rs +++ b/language/move-bytecode-verifier/src/code_unit_verifier.rs @@ -6,93 +6,189 @@ //! The overall verification is split between stack_usage_verifier.rs and //! abstract_interpreter.rs. CodeUnitVerifier simply orchestrates calls into these two files. use crate::{ - acquires_list_verifier::AcquiresVerifier, control_flow, locals_safety, reference_safety, - stack_usage_verifier::StackUsageVerifier, type_safety, + acquires_list_verifier::AcquiresVerifier, + control_flow, locals_safety, + meter::{BoundMeter, Meter, Scope}, + reference_safety, + stack_usage_verifier::StackUsageVerifier, + type_safety, + verifier::VerifierConfig, }; use move_binary_format::{ access::ModuleAccess, binary_views::{BinaryIndexedView, FunctionView}, - errors::{Location, PartialVMResult, VMResult}, + control_flow_graph::ControlFlowGraph, + errors::{Location, PartialVMError, PartialVMResult, VMResult}, file_format::{ CompiledModule, CompiledScript, FunctionDefinition, FunctionDefinitionIndex, IdentifierIndex, TableIndex, }, IndexKind, }; +use move_core_types::vm_status::StatusCode; use std::collections::HashMap; pub struct CodeUnitVerifier<'a> { resolver: BinaryIndexedView<'a>, function_view: FunctionView<'a>, - name_def_map: HashMap, + name_def_map: &'a HashMap, } impl<'a> CodeUnitVerifier<'a> { - pub fn verify_module(module: &'a CompiledModule) -> VMResult<()> { - Self::verify_module_impl(module).map_err(|e| e.finish(Location::Module(module.self_id()))) + pub fn verify_module( + verifier_config: &VerifierConfig, + module: &'a CompiledModule, + ) -> VMResult<()> { + Self::verify_module_impl(verifier_config, module) + .map_err(|e| e.finish(Location::Module(module.self_id()))) } - fn verify_module_impl(module: &'a CompiledModule) -> PartialVMResult<()> { + fn verify_module_impl( + verifier_config: &VerifierConfig, + module: &CompiledModule, + ) -> PartialVMResult<()> { + let mut meter = BoundMeter::new(verifier_config); + let mut name_def_map = HashMap::new(); + for (idx, func_def) in module.function_defs().iter().enumerate() { + let fh = module.function_handle_at(func_def.function); + name_def_map.insert(fh.name, FunctionDefinitionIndex(idx as u16)); + } + let mut total_back_edges = 0; for (idx, function_definition) in module.function_defs().iter().enumerate() { let index = FunctionDefinitionIndex(idx as TableIndex); - Self::verify_function(index, function_definition, module) - .map_err(|err| err.at_index(IndexKind::FunctionDefinition, index.0))? + let num_back_edges = Self::verify_function( + verifier_config, + index, + function_definition, + module, + &name_def_map, + &mut meter, + ) + .map_err(|err| err.at_index(IndexKind::FunctionDefinition, index.0))?; + total_back_edges += num_back_edges; + } + if let Some(limit) = verifier_config.max_back_edges_per_module { + if total_back_edges > limit { + return Err(PartialVMError::new(StatusCode::TOO_MANY_BACK_EDGES)); + } } Ok(()) } - pub fn verify_script(module: &'a CompiledScript) -> VMResult<()> { - Self::verify_script_impl(module).map_err(|e| e.finish(Location::Script)) + pub fn verify_script( + verifier_config: &VerifierConfig, + module: &'a CompiledScript, + ) -> VMResult<()> { + Self::verify_script_impl(verifier_config, module).map_err(|e| e.finish(Location::Script)) } - fn verify_script_impl(script: &'a CompiledScript) -> PartialVMResult<()> { + fn verify_script_impl( + verifier_config: &VerifierConfig, + script: &'a CompiledScript, + ) -> PartialVMResult<()> { + let mut meter = BoundMeter::new(verifier_config); // create `FunctionView` and `BinaryIndexedView` - control_flow::verify(None, &script.code)?; - let function_view = FunctionView::script(script); + let function_view = control_flow::verify_script(verifier_config, script)?; let resolver = BinaryIndexedView::Script(script); + let name_def_map = HashMap::new(); + + if let Some(limit) = verifier_config.max_basic_blocks_in_script { + if function_view.cfg().blocks().len() > limit { + return Err(PartialVMError::new(StatusCode::TOO_MANY_BASIC_BLOCKS)); + } + } + + if let Some(limit) = verifier_config.max_back_edges_per_function { + if function_view.cfg().num_back_edges() > limit { + return Err(PartialVMError::new(StatusCode::TOO_MANY_BACK_EDGES)); + } + } + //verify + meter.enter_scope("script", Scope::Function); let code_unit_verifier = CodeUnitVerifier { resolver, function_view, - name_def_map: HashMap::new(), + name_def_map: &name_def_map, }; - code_unit_verifier.verify_common() + code_unit_verifier.verify_common(verifier_config, &mut meter) } fn verify_function( + verifier_config: &VerifierConfig, index: FunctionDefinitionIndex, - function_definition: &'a FunctionDefinition, - module: &'a CompiledModule, - ) -> PartialVMResult<()> { + function_definition: &FunctionDefinition, + module: &CompiledModule, + name_def_map: &HashMap, + meter: &mut impl Meter, + ) -> PartialVMResult { + meter.enter_scope( + module + .identifier_at(module.function_handle_at(function_definition.function).name) + .as_str(), + Scope::Function, + ); // nothing to verify for native function let code = match &function_definition.code { Some(code) => code, - None => return Ok(()), + None => return Ok(0), }; + // create `FunctionView` and `BinaryIndexedView` - let function_handle = module.function_handle_at(function_definition.function); - control_flow::verify(Some(index), code)?; - let function_view = FunctionView::function(module, index, code, function_handle); - let resolver = BinaryIndexedView::Module(module); - let mut name_def_map = HashMap::new(); - for (idx, func_def) in module.function_defs().iter().enumerate() { - let fh = module.function_handle_at(func_def.function); - name_def_map.insert(fh.name, FunctionDefinitionIndex(idx as u16)); + let function_view = control_flow::verify_function( + verifier_config, + module, + index, + function_definition, + code, + meter, + )?; + + if let Some(limit) = verifier_config.max_basic_blocks { + if function_view.cfg().blocks().len() > limit { + return Err( + PartialVMError::new(StatusCode::TOO_MANY_BASIC_BLOCKS).at_code_offset(index, 0) + ); + } } + + let num_back_edges = function_view.cfg().num_back_edges(); + if let Some(limit) = verifier_config.max_back_edges_per_function { + if num_back_edges > limit { + return Err( + PartialVMError::new(StatusCode::TOO_MANY_BACK_EDGES).at_code_offset(index, 0) + ); + } + } + + let resolver = BinaryIndexedView::Module(module); // verify let code_unit_verifier = CodeUnitVerifier { resolver, function_view, name_def_map, }; - code_unit_verifier.verify_common()?; - AcquiresVerifier::verify(module, index, function_definition) + code_unit_verifier.verify_common(verifier_config, meter)?; + AcquiresVerifier::verify(module, index, function_definition, meter)?; + + meter.transfer(Scope::Function, Scope::Module, 1.0)?; + + Ok(num_back_edges) } - fn verify_common(&self) -> PartialVMResult<()> { - StackUsageVerifier::verify(&self.resolver, &self.function_view)?; - type_safety::verify(&self.resolver, &self.function_view)?; - locals_safety::verify(&self.resolver, &self.function_view)?; - reference_safety::verify(&self.resolver, &self.function_view, &self.name_def_map) + fn verify_common( + &self, + verifier_config: &VerifierConfig, + meter: &mut impl Meter, + ) -> PartialVMResult<()> { + StackUsageVerifier::verify(verifier_config, &self.resolver, &self.function_view, meter)?; + type_safety::verify(&self.resolver, &self.function_view, meter)?; + locals_safety::verify(&self.resolver, &self.function_view, meter)?; + reference_safety::verify( + &self.resolver, + &self.function_view, + self.name_def_map, + meter, + ) } } diff --git a/language/move-bytecode-verifier/src/control_flow.rs b/language/move-bytecode-verifier/src/control_flow.rs index c2ed834801..6012684be1 100644 --- a/language/move-bytecode-verifier/src/control_flow.rs +++ b/language/move-bytecode-verifier/src/control_flow.rs @@ -2,240 +2,181 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 -//! This module implements a checker for verifies control flow. The following properties are -//! ensured: -//! - All forward jumps do not enter into the middle of a loop -//! - All "breaks" (forward, loop-exiting jumps) go to the "end" of the loop -//! - All "continues" (back jumps in a loop) are only to the current loop +//! This module implements control flow checks. +//! +//! For bytecode versions 6 and up, the following properties are ensured: +//! - The CFG is not empty and the last block ends in an unconditional jump, so it's not possible to +//! fall off the end of a function. +//! - The CFG is reducible (and optionally max loop depth is bounded), to limit the potential for +//! pathologically long abstract interpretation runtimes (through poor choice of loop heads and +//! back edges). +//! +//! For bytecode versions 5 and below, delegates to `control_flow_v5`. +use crate::{ + control_flow_v5, + loop_summary::{LoopPartition, LoopSummary}, + meter::Meter, + verifier::VerifierConfig, +}; use move_binary_format::{ + access::{ModuleAccess, ScriptAccess}, + binary_views::FunctionView, errors::{PartialVMError, PartialVMResult}, - file_format::{Bytecode, CodeOffset, CodeUnit, FunctionDefinitionIndex}, + file_format::{ + CodeOffset, CodeUnit, CompiledScript, FunctionDefinition, FunctionDefinitionIndex, + }, + CompiledModule, }; use move_core_types::vm_status::StatusCode; -use std::{collections::HashSet, convert::TryInto}; +use std::collections::BTreeSet; + +/// Perform control flow verification on the compiled function, returning its `FunctionView` if +/// verification was successful. +pub fn verify_function<'a>( + verifier_config: &'a VerifierConfig, + module: &'a CompiledModule, + index: FunctionDefinitionIndex, + function_definition: &'a FunctionDefinition, + code: &'a CodeUnit, + _meter: &mut impl Meter, // TODO: metering +) -> PartialVMResult> { + let function_handle = module.function_handle_at(function_definition.function); + + if module.version() <= 5 { + control_flow_v5::verify(verifier_config, Some(index), code)?; + Ok(FunctionView::function(module, index, code, function_handle)) + } else { + verify_fallthrough(Some(index), code)?; + let function_view = FunctionView::function(module, index, code, function_handle); + verify_reducibility(verifier_config, &function_view)?; + Ok(function_view) + } +} + +/// Perform control flow verification on the compiled script, returning its `FunctionView` if +/// verification was successful. +pub fn verify_script<'a>( + verifier_config: &'a VerifierConfig, + script: &'a CompiledScript, +) -> PartialVMResult> { + if script.version() <= 5 { + control_flow_v5::verify(verifier_config, None, &script.code)?; + Ok(FunctionView::script(script)) + } else { + verify_fallthrough(None, &script.code)?; + let function_view = FunctionView::script(script); + verify_reducibility(verifier_config, &function_view)?; + Ok(function_view) + } +} -pub fn verify( +/// Check to make sure that the bytecode vector is non-empty and ends with a branching instruction. +fn verify_fallthrough( current_function_opt: Option, code: &CodeUnit, ) -> PartialVMResult<()> { let current_function = current_function_opt.unwrap_or(FunctionDefinitionIndex(0)); - // check fall through - // Check to make sure that the bytecode vector ends with a branching instruction. match code.code.last() { - None => return Err(PartialVMError::new(StatusCode::EMPTY_CODE_UNIT)), + None => Err(PartialVMError::new(StatusCode::EMPTY_CODE_UNIT)), Some(last) if !last.is_unconditional_branch() => { - return Err(PartialVMError::new(StatusCode::INVALID_FALL_THROUGH) + Err(PartialVMError::new(StatusCode::INVALID_FALL_THROUGH) .at_code_offset(current_function, (code.code.len() - 1) as CodeOffset)) } - Some(_) => (), + Some(_) => Ok(()), } - - // check jumps - let context = &ControlFlowVerifier { - current_function, - code: &code.code, - }; - let labels = instruction_labels(context); - check_jumps(context, labels) -} - -#[derive(Clone, Copy)] -enum Label { - Loop { last_continue: u16 }, - Code, -} - -struct ControlFlowVerifier<'a> { - current_function: FunctionDefinitionIndex, - code: &'a Vec, } -impl<'a> ControlFlowVerifier<'a> { - fn code(&self) -> impl Iterator { - self.code - .iter() - .enumerate() - .map(|(idx, instr)| (idx.try_into().unwrap(), instr)) - } - - fn labeled_code<'b: 'a>( - &self, - labels: &'b [Label], - ) -> impl Iterator { - self.code() - .zip(labels) - .map(|((i, instr), lbl)| (i, instr, lbl)) - } - - fn error(&self, status: StatusCode, offset: CodeOffset) -> PartialVMError { - PartialVMError::new(status).at_code_offset(self.current_function, offset) - } -} - -fn instruction_labels(context: &ControlFlowVerifier) -> Vec