diff --git a/.github/workflows/build-m1-wheel.yml b/.github/workflows/build-m1-wheel.yml index 5831afae7..a7a3c0a4e 100644 --- a/.github/workflows/build-m1-wheel.yml +++ b/.github/workflows/build-m1-wheel.yml @@ -111,22 +111,32 @@ jobs: name: wheels path: ./target/wheels - - name: Test for secrets access - id: check_secrets - shell: bash - run: | - unset HAS_AWS_SECRET - - if [ -n "$AWS_SECRET" ]; then HAS_AWS_SECRET='true' ; fi - echo HAS_AWS_SECRET=${HAS_AWS_SECRET} >>$GITHUB_OUTPUT - env: - AWS_SECRET: "${{ secrets.CHIA_AWS_ACCOUNT_ID }}" + upload: + name: Upload to PyPI + runs-on: ubuntu-latest + needs: build_wheels + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Set Env uses: Chia-Network/actions/setjobenv@main env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Install python + uses: Chia-Network/actions/setup-python@main + with: + python-version: "3.10" + + - name: Download artifacts + uses: actions/download-artifact@v3 + with: + name: wheels + path: ./target/wheels/ + - name: publish (PyPi) if: env.RELEASE == 'true' uses: pypa/gh-action-pypi-publish@release/v1 @@ -142,6 +152,17 @@ jobs: packages-dir: target/wheels/ skip-existing: true + - name: Test for secrets access + id: check_secrets + shell: bash + run: | + unset HAS_AWS_SECRET + + if [ -n "$AWS_SECRET" ]; then HAS_AWS_SECRET='true' ; fi + echo HAS_AWS_SECRET=${HAS_AWS_SECRET} >>$GITHUB_OUTPUT + env: + AWS_SECRET: "${{ secrets.CHIA_AWS_ACCOUNT_ID }}" + - name: Configure AWS credentials if: steps.check_secrets.outputs.HAS_AWS_SECRET uses: aws-actions/configure-aws-credentials@v2 @@ -151,8 +172,10 @@ jobs: - name: Publish Dev if: steps.check_secrets.outputs.HAS_AWS_SECRET && github.ref == 'refs/heads/dev' + shell: bash + working-directory: ./target/wheels run: | - FILES=$(find ${{ github.workspace }}/target/wheels -type f -name '*.whl') + FILES=$(find . -type f -name '*.whl') while IFS= read -r file; do filename=$(basename $file) aws --no-progress s3 cp "$file" "s3://download.chia.net/simple-dev/clvm-tools-rs/$filename" diff --git a/.github/workflows/build-riscv.yml b/.github/workflows/build-riscv.yml new file mode 100644 index 000000000..7fef28d9d --- /dev/null +++ b/.github/workflows/build-riscv.yml @@ -0,0 +1,81 @@ +name: QEMU Build and test riscv64 crate + +on: + push: + branches: + - main + - dev + tags: + - '**' + pull_request: + branches: + - '**' + +jobs: + build_crate: + name: Build riscv64 crate and run tests + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ ubuntu-latest ] + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + fetch-depth: 1 + + - name: Set up QEMU on x86_64 + id: qemu + uses: docker/setup-qemu-action@v2 + with: + platforms: riscv64 + + - name: Build and Test + run: | + docker run --rm --platform linux/riscv64 \ + -v ${{ github.workspace }}:/ws --workdir=/ws \ + chianetwork/ubuntu-22.04-risc-builder:latest \ + bash -exc '\ + cargo test --release + ' + + build_wheels: + name: QEMU riscv64 wheel + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ ubuntu-latest ] + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + with: + fetch-depth: 1 + + - name: Set up QEMU on x86_64 + id: qemu + uses: docker/setup-qemu-action@v2 + with: + platforms: riscv64 + + - name: Build + run: | + docker run --rm --platform linux/riscv64 \ + -v ${{ github.workspace }}:/ws --workdir=/ws \ + chianetwork/ubuntu-22.04-risc-builder:latest \ + bash -exc '\ + pyenv global 3.10 + python -m venv venv && \ + source ./venv/bin/activate && \ + pip install --upgrade pip && \ + pip install --extra-index-url https://pypi.chia.net/simple/ maturin==1.2.3 && \ + maturin build -i python --release --strip \ + ' + + - name: Upload artifacts + uses: actions/upload-artifact@v3 + with: + name: packages + path: ./target/wheels/ + diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 409609482..883fcd604 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -97,7 +97,7 @@ jobs: . ./activate maturin build -i python --release --strip # Find and install the newly built wheel - python support/wheelname.py + pip install --no-index --find-links target/wheels/ clvm_tools_rs - name: Install clvm_tools_rs wheel if: ${{ !startsWith(matrix.os, 'windows') }} @@ -140,6 +140,30 @@ jobs: python -c 'import clvm_tools_rs; print(clvm_tools_rs.__file__)' echo "CLVM_TOOLS_RS_VERSION=$(python -c 'import clvm_tools_rs; print(clvm_tools_rs.get_version())')" >> "$GITHUB_ENV" + # Test cldb output both run from python and via its command line tool. + - name: "Run step run tests" + run: | + . ./activate + cargo build + # This finds and installs a compatible wheel from the target directory on linux. + # We do it here as a hedge against changes in the python environment that might + # have happened due to pulling in the trunk versions of other packages that + # depend on clvm_tools_rs. + pip install --no-index --find-links target/wheels/ clvm_tools_rs + pip install clvm_rs + pip install clvm_tools + cd resources/tests && python test_clvm_step.py && python mandelbrot-cldb.py && python test_compile_from_string.py + + - name: "Test step run with mandelbrot, setting print only" + run: | + . ./activate + python ./resources/tests/lib/steprun.py ./resources/tests/mandelbrot/mandelbrot.clvm.hex resources/tests/mandelbrot/mand_args.txt ./resources/tests/mandelbrot/mandelbrot.sym > mand_output.txt + # git diff invoked this way returns 0 (as /bin/true) if there is no difference or 1 if there is. + git diff --no-index -s --quiet -- mand_output.txt ./resources/tests/mandelbrot/mand_test.txt + # Remove file in a compatible way using git as a general tool + git add mand_output.txt + git rm --force mand_output.txt + - name: Verify recompilation of old sources match with new compiler if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.8') @@ -147,7 +171,7 @@ jobs: set -x . ./activate # Build cmd line tools - PYO3_PYTHON=`which python` cargo build --no-default-features --release + PYO3_PYTHON=`which python` cargo build --release # Grab chia-blockchain rm -rf chia-blockchain @@ -157,7 +181,7 @@ jobs: cp support/install_deps.sh support/verify_compiler_version.sh chia-blockchain (cd chia-blockchain && python -m venv venv && . venv/bin/activate && pip install --upgrade pip && \ python -m pip install maturin==1.1.0 && \ - cd .. && python support/wheelname.py && \ + cd .. && pip install --no-index --find-links target/wheels/ clvm_tools_rs && \ cd chia-blockchain && \ # deps for manage_clvm.py pip install click typing_extensions chia_rs clvm && \ @@ -169,7 +193,7 @@ jobs: run: | python -m pip install pytest # This script installs the wheel built during this workflow. - python support/wheelname.py + pip install --no-index --find-links wheel/target/wheels/ clvm_tools_rs # TODO: bring in the other tests in resources/tests/cmdline/tests besides cmds_test.py (cd resources/tests/cmdline/tests && py.test cmds_test.py ) @@ -182,13 +206,13 @@ jobs: # Ensure we're using the sources we have. This is a hedge against # changes made by any other step doing operations on pip. # This script installs the wheel built during this workflow. - python support/wheelname.py + pip install --no-index --find-links wheel/target/wheels/ clvm_tools_rs (cd resources/tests && python check-recompiles.py) - name: Verify recompilation follows date and modification rules if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.8') run: | - python support/wheelname.py + pip install --no-index --find-links wheel/target/wheels/ clvm_tools_rs python resources/tests/test-clvm-recompile-behavior.py - name: Install pytest @@ -210,7 +234,7 @@ jobs: - name: Run tests if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.8') - run: cargo test --no-default-features + run: cargo test - name: Exhaustive assign tests if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.8') @@ -223,36 +247,59 @@ jobs: rustup component add llvm-tools-preview python ./resources/coverage/run_coverage.py --require-percent 60 + - name: Build alpine wheel via docker + if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.8') + run: | + cd resources/alpine && docker build -t clvm-tools-rs-alpine . + docker run -v ${GITHUB_WORKSPACE}:/root/clvm_tools_rs -t clvm-tools-rs-alpine sh /root/build-alpine.sh + - name: Upload artifacts uses: actions/upload-artifact@v3 with: name: wheels path: ./target/wheels/ - - name: Test for secrets access - id: check_secrets - shell: bash - run: | - unset HAS_AWS_SECRET - - if [ -n "$AWS_SECRET" ]; then HAS_AWS_SECRET='true' ; fi - echo HAS_AWS_SECRET=${HAS_AWS_SECRET} >>$GITHUB_OUTPUT - env: - AWS_SECRET: "${{ secrets.CHIA_AWS_ACCOUNT_ID }}" + upload: + name: Upload to PyPI + runs-on: ubuntu-latest + needs: build_wheels + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 - name: Set Env uses: Chia-Network/actions/setjobenv@main env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: publish (PyPi) + - name: Install python + uses: Chia-Network/actions/setup-python@main + with: + python-version: "3.10" + + - name: Download artifacts + uses: actions/download-artifact@v3 + with: + name: wheels + path: ./target/wheels/ + + - name: Check for incompatible wheels and bail if found + run: | + set -e + # Check for a wheel with -linux_x86_64 platform tag, which will + # fail uploading to pypi. + find target -name \*-linux_x86_64.whl -exec /bin/false '{}' '+' + + - name: Publish distribution to PyPI if: env.RELEASE == 'true' uses: pypa/gh-action-pypi-publish@release/v1 with: packages-dir: target/wheels/ skip-existing: true - - name: publish (Test PyPi) + - name: Publish distribution to Test PyPI if: env.PRE_RELEASE == 'true' uses: pypa/gh-action-pypi-publish@release/v1 with: @@ -260,6 +307,17 @@ jobs: packages-dir: target/wheels/ skip-existing: true + - name: Test for secrets access + id: check_secrets + shell: bash + run: | + unset HAS_AWS_SECRET + + if [ -n "$AWS_SECRET" ]; then HAS_AWS_SECRET='true' ; fi + echo HAS_AWS_SECRET=${HAS_AWS_SECRET} >>$GITHUB_OUTPUT + env: + AWS_SECRET: "${{ secrets.CHIA_AWS_ACCOUNT_ID }}" + - name: Configure AWS credentials if: steps.check_secrets.outputs.HAS_AWS_SECRET uses: aws-actions/configure-aws-credentials@v2 @@ -278,12 +336,6 @@ jobs: aws --no-progress s3 cp "$file" "s3://download.chia.net/simple-dev/clvm-tools-rs/$filename" done <<< "$FILES" - - name: Build alpine wheel via docker - if: startsWith(matrix.os, 'ubuntu') && startsWith(matrix.python, '3.8') - run: | - cd resources/alpine && docker build -t clvm-tools-rs-alpine . - docker run -v ${GITHUB_WORKSPACE}:/root/clvm_tools_rs -t clvm-tools-rs-alpine sh /root/build-alpine.sh - fmt: runs-on: ubuntu-20.04 name: cargo fmt @@ -340,6 +392,7 @@ jobs: toolchain: stable - name: Run for coverage run: | + set -e sudo apt-get update sudo apt-get install lcov -y rustup component add llvm-tools-preview @@ -354,9 +407,13 @@ jobs: pip install ./clvm_tools pip install maturin pytest maturin develop --release + echo 'PYTEST' (cd resources/tests/cmdline/tests && pytest) + echo 'PYTEST COMPLETE' grcov . --binary-path target -s . --branch --ignore-not-existing --ignore='*/.cargo/*' --ignore='*/tests/*' -o rust_cov.info + echo 'GRCOV RAN' python -c 'with open("rust_cov.info") as f: lines = [l for l in f if not (l.startswith("DA:") and int(l.split(",")[1].strip()) >= 2**63)]; open("lcov.info", "w").writelines(lines)' + echo 'COVERAGE STEP DONE' - name: Upload to Coveralls uses: coverallsapp/github-action@v2 if: always() diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 000000000..b7a0ea90d --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,24 @@ +# Managed by repo-content-updater +# Dependency Review Action +# +# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging. +# +# Source repository: https://github.com/actions/dependency-review-action +# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement +name: '🚨 Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: 'Checkout Repository' + uses: actions/checkout@v4 + + - name: 'Dependency Review' + uses: actions/dependency-review-action@v4 + with: + deny-licenses: AGPL-1.0-only, AGPL-1.0-or-later, AGPL-1.0-or-later, AGPL-3.0-or-later, GPL-1.0-only, GPL-1.0-or-later, GPL-2.0-only, GPL-2.0-or-later, GPL-3.0-only, GPL-3.0-or-later diff --git a/.github/workflows/extensive-tests.yml b/.github/workflows/extensive-tests.yml new file mode 100644 index 000000000..4d34d8770 --- /dev/null +++ b/.github/workflows/extensive-tests.yml @@ -0,0 +1,122 @@ +# Taken from clvm_rs' version. +name: Extensive tests + +on: + push: + branches: + - main + - dev + tags: + - '**' + pull_request: + branches: + - '**' + +jobs: + extensive_tests: + name: Extensive tests + runs-on: ubuntu-latest + strategy: + fail-fast: false + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up rusts + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + components: rustfmt, clippy + + - name: Set up rust (stable) + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + components: rustfmt, clippy + + - uses: actions/setup-python@v4 + name: Install Python 3.11 + with: + python-version: 3.11 + + - name: Update pip + run: | + python -m pip install --upgrade pip + + - name: Set up rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + + - name: Install dependencies + run: | + python -m pip install maturin==1.1.0 + + - name: Build Linux in manylinux2010 with maturin on Python ${{ matrix.python }} + run: | + podman run --rm=true \ + -v ${{ github.workspace }}:/ws:rw --workdir=/ws \ + ghcr.io/chia-network/build-images/centos-pypa-rust-x86_64 \ + bash -exc '\ + yum -y install libc6 openssl-devel && \ + source $HOME/.cargo/env && \ + rustup target add x86_64-unknown-linux-musl && \ + rm -rf venv && \ + PY_VERSION=${{ matrix.python }} + PY_VERSION=${PY_VERSION/.} && \ + echo "Python version with dot removed is $PY_VERSION" && \ + if [ "$PY_VERSION" = "37" ]; \ + then export SCND_VERSION="${PY_VERSION}m"; \ + else export SCND_VERSION="$PY_VERSION"; fi && \ + echo "Exporting path /opt/python/cp$PY_VERSION-cp$SCND_VERSION/bin" && \ + export PATH=/opt/python/cp$PY_VERSION-cp$SCND_VERSION/bin/:$PATH && \ + /opt/python/cp38-cp38/bin/python -m venv venv && \ + if [ ! -f "activate" ]; then ln -s venv/bin/activate; fi && \ + . ./activate && \ + pip install --upgrade pip + ' + docker run --rm -v $(pwd):/io ghcr.io/pyo3/maturin:v1.1.0 build --release --strip --manylinux 2014 + # Refresh in case any ownerships changed. + mv target target.docker && cp -r target.docker target + # Ensure an empty .cargo-lock file exists. + touch target/release/.cargo-lock + + - name: Install clvm_tools_rs wheel + if: ${{ !startsWith(matrix.os, 'windows') }} + run: | + . ./activate + ls target/wheels/ + # this mess puts the name of the `.whl` file into `$WHEEL_PATH` + # remove the dot, use the `glob` lib to grab the file from the directory + export WHEEL_PATH=$(echo ${{ matrix.python }} | python -c 'DOTLESS=input().replace(".", ""); import glob; print(" ".join(filter(lambda x: "musl" not in x, glob.glob("target/wheels/clvm_tools_rs-*-cp*-*.whl"))))' ) + echo ${WHEEL_PATH} + pip install ${WHEEL_PATH} + + - name: Install other wheels + run: | + . ./activate + python -m pip install pytest + python -m pip install blspy + + - name: install clvm & clvm_tools + run: | + . ./activate + git clone https://github.com/Chia-Network/clvm.git --branch=main --single-branch + python -m pip install ./clvm + + echo "installing clvm_rs via pip" + pip install clvm_rs + + echo "installing clvm_tools for clvm tests" + # clvm tools is required to run the tests is clvm + python -m pip install clvm_tools + + - name: Run game referee test + run: | + . ./activate + cp support/test-game-referee.sh . + sh test-game-referee.sh resources/tests/game-referee-in-cl23 + sh test-game-referee.sh resources/tests/game-referee-in-cl21 + sh test-game-referee.sh resources/tests/game-referee-after-cl21 diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 691fdff94..46a2d9fe6 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -78,7 +78,7 @@ jobs: SECRET: "${{ secrets.NPM_TOKEN }}" - name: Publish wasm - if: env.FULL_RELEASE == 'true' && steps.check_secrets.HAS_SECRET + if: env.FULL_RELEASE == 'true' && steps.check_secrets.outputs.HAS_SECRET env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} working-directory: ${{ github.workspace }}/wasm/pkg diff --git a/.gitignore b/.gitignore index 77e2b42a7..a343936cb 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,9 @@ wasm/tests/node_modules resources/tests/bridgeref/*.sym resources/tests/bridgeref/*.clvm.hex resources/tests/gameref21/*.sym -resources/tests/gameref21/*.clvm.hex \ No newline at end of file +resources/tests/gameref21/*.clvm.hex +resources/tests/gameref21/*.clvm.hex +resources/tests/game-referee/*.sym +resources/tests/game-referee/*.clvm.hex +__pycache__ +.pytest_cache diff --git a/CHANGELOG.md b/CHANGELOG.md index e50a9fa5b..4d01a998d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,3 +30,25 @@ Skipped - &rest arguments. - new bls and sec256 operators. +## 0.1.36 + +- modern lambda added +- updated some internal data strucutres and call interfaces to support env variable renaming at during closure generation / lambda capture, or any step during transformation. + +## 0.1.37 + +- First npm publish with a Program-like object reminiscent of + chia.types.blockchain_format.program.Program + +## 0.1.38 + +- Uncurry fix, typescript type improvements for npm personality. + +## 0.1.39 + +- Support conversion from Uint8Array to IProgram in wasm. + +## 0.1.40 + +- New language sigil ```*standard-cl-23*``` is here which is the same language as that introduced by ```*strict-cl-21*``` but has much better optimization. +- Syntactic tree lists using #(...) syntax in cl21 and cl23 (matt-o-how). diff --git a/Cargo.lock b/Cargo.lock index 7e77bed2f..f775f4173 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,20 +4,32 @@ version = 3 [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" + [[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -54,9 +66,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "bitvec" @@ -102,6 +114,18 @@ dependencies = [ "subtle", ] +[[package]] +name = "blst" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c94087b935a822949d3291a9989ad2b2051ea141eda0fd4e478a75f6aa3e604b" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + [[package]] name = "bumpalo" version = "3.13.0" @@ -125,12 +149,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.81" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c6b2562119bf28c3439f7f02db99faf0aa1a8cdfe5772a2ee155d32227239f0" -dependencies = [ - "libc", -] +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cfg-if" @@ -138,14 +159,66 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chia-bls" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba003303bda3019f2fe94e5478555a96addff1d6a1ea84bfe207b3f075cd8420" +dependencies = [ + "anyhow", + "arbitrary", + "blst", + "chia-traits", + "hex", + "hkdf", + "sha2 0.10.8", + "thiserror", + "tiny-bip39", +] + +[[package]] +name = "chia-traits" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe532ed59df94db00cc1fb85edc3c4dd7287d0590eefb356d960671b93081334" +dependencies = [ + "chia_streamable_macro", + "hex", + "sha2 0.10.8", + "thiserror", +] + +[[package]] +name = "chia_streamable_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "342cdb29dd8c1214d60fac24100ab1567756270710e93336db910a531fe8a264" +dependencies = [ + "proc-macro-crate", + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.28", +] + +[[package]] +name = "clvm-traits" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b527f38a1a9ef23aafd982a89be3881fa5f0a0ba0a642fa94244c72a74b8c8" +dependencies = [ + "num-bigint", + "thiserror", +] + [[package]] name = "clvm_tools_rs" -version = "0.1.35" +version = "0.1.40" dependencies = [ "binascii", "bls12_381", "bytestream", "clvmr", + "ctor", "derivative", "do-notation", "encoding8", @@ -155,6 +228,7 @@ dependencies = [ "indoc 1.0.9", "js-sys", "lazy_static", + "lfsr", "linked-hash-map", "log", "num", @@ -164,6 +238,7 @@ dependencies = [ "pyo3-build-config 0.15.2", "rand", "rand_chacha", + "regex", "serde", "serde_json", "sha2 0.9.9", @@ -176,13 +251,12 @@ dependencies = [ [[package]] name = "clvmr" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cd344b6dc76235f446025fe9ebe54aa6131e2e59acb49e16be48a3bb3492491" +checksum = "dede49a536ac5ad83753cf241f674d0c7b251a2a58ae681577457be9c5ea7bc3" dependencies = [ - "bls12_381", - "getrandom", - "group", + "chia-bls", + "clvm-traits", "hex", "k256", "lazy_static", @@ -190,7 +264,7 @@ dependencies = [ "num-integer", "num-traits", "p256", - "sha2 0.9.9", + "sha2 0.10.8", ] [[package]] @@ -240,6 +314,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "ctor" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" +dependencies = [ + "quote 1.0.32", + "syn 2.0.28", +] + [[package]] name = "der" version = "0.7.7" @@ -257,8 +341,8 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.66", + "quote 1.0.32", "syn 1.0.109", ] @@ -303,6 +387,12 @@ dependencies = [ "spki", ] +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + [[package]] name = "elliptic-curve" version = "0.13.5" @@ -343,31 +433,26 @@ dependencies = [ ] [[package]] -name = "errno" -version = "0.3.2" +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", -] +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "errno" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "cc", "libc", + "windows-sys", ] [[package]] name = "fastrand" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "ff" @@ -410,6 +495,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "group" version = "0.13.0" @@ -421,6 +512,18 @@ dependencies = [ "subtle", ] +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -430,12 +533,27 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + [[package]] name = "hmac" version = "0.12.1" @@ -452,13 +570,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] -name = "indoc" -version = "0.3.6" +name = "indexmap" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ - "indoc-impl", - "proc-macro-hack", + "equivalent", + "hashbrown", ] [[package]] @@ -468,17 +586,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" [[package]] -name = "indoc-impl" -version = "0.3.6" +name = "indoc" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0" -dependencies = [ - "proc-macro-hack", - "proc-macro2", - "quote", - "syn 1.0.109", - "unindent", -] +checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" [[package]] name = "instant" @@ -489,6 +600,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "itertools" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.9" @@ -514,7 +634,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "once_cell", - "sha2 0.10.7", + "sha2 0.10.8", "signature", ] @@ -524,11 +644,66 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lfsr" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1408c5559fc91f522a78aa46b85647f5bcbeee9e64e4b7d8e7b0d259d0047c57" +dependencies = [ + "lfsr-base", + "lfsr-instances", + "lfsr-macro-generate", + "lfsr-macro-lookup", +] + +[[package]] +name = "lfsr-base" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1355f8e4ef0c69b2f41f154716197b1027a75afb094dbc1b5d96cd124b2d946c" + +[[package]] +name = "lfsr-instances" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c2fd4e3b24c4c995c6d89cffb1f346b68bfa37466bfde5023975af945bfb75" +dependencies = [ + "lfsr-base", + "lfsr-macro-generate", +] + +[[package]] +name = "lfsr-macro-generate" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b797be749e5d7d013b3e18954049468c228841a5068ceb55dd9da23a300ecff6" +dependencies = [ + "itertools", + "lfsr-base", + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", +] + +[[package]] +name = "lfsr-macro-lookup" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3a3a6a85a7aac81c9f94adc14ab565eaaac8fd91460d06b89e4dd93462cdf8" +dependencies = [ + "itertools", + "lfsr-base", + "lfsr-instances", + "proc-macro2 0.4.30", + "quote 0.6.13", + "syn 0.15.44", +] + [[package]] name = "libc" -version = "0.2.147" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "linked-hash-map" @@ -538,9 +713,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.5" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" @@ -560,9 +735,18 @@ checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "memoffset" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] [[package]] name = "num" @@ -641,6 +825,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi 0.3.3", + "libc", +] + [[package]] name = "once_cell" version = "1.18.0" @@ -662,7 +856,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "primeorder", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -694,28 +888,18 @@ dependencies = [ "cfg-if", "instant", "libc", - "redox_syscall 0.2.16", + "redox_syscall", "smallvec", "winapi", ] [[package]] -name = "paste" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" -dependencies = [ - "paste-impl", - "proc-macro-hack", -] - -[[package]] -name = "paste-impl" -version = "0.1.18" +name = "pbkdf2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "proc-macro-hack", + "digest 0.10.7", ] [[package]] @@ -753,10 +937,23 @@ dependencies = [ ] [[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" +name = "proc-macro-crate" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid", +] [[package]] name = "proc-macro2" @@ -769,59 +966,81 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.14.5" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35100f9347670a566a67aa623369293703322bb9db77d99d7df7313b575ae0c8" +checksum = "9a89dc7a5850d0e983be1ec2a463a171d20990487c3cfcd68b5363f1ee3d6fe0" dependencies = [ "cfg-if", - "indoc 0.3.6", + "indoc 2.0.4", "libc", + "memoffset", "parking_lot", - "paste", - "pyo3-build-config 0.14.5", + "pyo3-build-config 0.20.2", + "pyo3-ffi", "pyo3-macros", "unindent", ] [[package]] name = "pyo3-build-config" -version = "0.14.5" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d12961738cacbd7f91b7c43bc25cfeeaa2698ad07a04b3be0aa88b950865738f" +checksum = "779239fc40b8e18bc8416d3a37d280ca9b9fb04bda54b98037bb6748595c2410" dependencies = [ "once_cell", ] [[package]] name = "pyo3-build-config" -version = "0.15.2" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "779239fc40b8e18bc8416d3a37d280ca9b9fb04bda54b98037bb6748595c2410" +checksum = "07426f0d8fe5a601f26293f300afd1a7b1ed5e78b2a705870c5f30893c5163be" dependencies = [ "once_cell", + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb7dec17e17766b46bca4f1a4215a85006b4c2ecde122076c562dd058da6cf1" +dependencies = [ + "libc", + "pyo3-build-config 0.20.2", ] [[package]] name = "pyo3-macros" -version = "0.14.5" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0bc5215d704824dfddddc03f93cb572e1155c68b6761c37005e1c288808ea8" +checksum = "05f738b4e40d50b5711957f142878cfa0f28e054aa0ebdfc3fd137a843f74ed3" dependencies = [ + "proc-macro2 1.0.66", "pyo3-macros-backend", - "quote", - "syn 1.0.109", + "quote 1.0.32", + "syn 2.0.28", ] [[package]] name = "pyo3-macros-backend" -version = "0.14.5" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71623fc593224afaab918aa3afcaf86ed2f43d34f6afde7f3922608f253240df" +checksum = "0fc910d4851847827daf9d6cdd4a823fbdaab5b8818325c5e97a86da79e8881f" dependencies = [ - "proc-macro2", - "pyo3-build-config 0.14.5", - "quote", - "syn 1.0.109", + "heck", + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.28", +] + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", ] [[package]] @@ -830,7 +1049,7 @@ version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.66", ] [[package]] @@ -878,20 +1097,11 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "regex" -version = "1.9.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", @@ -901,9 +1111,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7b6d6190b7594385f61bd3911cd1be99dfddcfc365a4160cc2ab5bff4aed294" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", @@ -912,9 +1122,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "rfc6979" @@ -926,13 +1136,19 @@ dependencies = [ "subtle", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustix" -version = "0.38.6" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee020b1716f0a80e2ace9b03441a749e402e86712f15f16fe8a8f75afac732f" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.2", "errno", "libc", "linux-raw-sys", @@ -986,8 +1202,8 @@ version = "1.0.180" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24e744d7782b686ab3b73267ef05697159cc0e5abbed3f47f9933165e5219036" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.66", + "quote 1.0.32", "syn 2.0.28", ] @@ -1017,9 +1233,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -1058,14 +1274,25 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +dependencies = [ + "proc-macro2 0.4.30", + "quote 0.6.13", + "unicode-xid", +] + [[package]] name = "syn" version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.66", + "quote 1.0.32", "unicode-ident", ] @@ -1075,8 +1302,8 @@ version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.66", + "quote 1.0.32", "unicode-ident", ] @@ -1086,28 +1313,113 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "target-lexicon" +version = "0.12.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae" + [[package]] name = "tempfile" -version = "3.7.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.3.5", "rustix", "windows-sys", ] [[package]] name = "termcolor" -version = "1.2.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] +[[package]] +name = "thiserror" +version = "1.0.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" +dependencies = [ + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.28", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "tiny-bip39" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62cc94d358b5a1e84a5cb9109f559aa3c4d634d2b1b4de3d0fa4adc7c78e2861" +dependencies = [ + "anyhow", + "hmac", + "once_cell", + "pbkdf2", + "rand", + "rustc-hash", + "sha2 0.10.8", + "thiserror", + "unicode-normalization", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + [[package]] name = "typenum" version = "1.16.0" @@ -1120,17 +1432,32 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-segmentation" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + [[package]] name = "unindent" -version = "0.1.11" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" +checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" [[package]] name = "version_check" @@ -1165,8 +1492,8 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2", - "quote", + "proc-macro2 1.0.66", + "quote 1.0.32", "syn 2.0.28", "wasm-bindgen-shared", ] @@ -1189,7 +1516,7 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ - "quote", + "quote 1.0.32", "wasm-bindgen-macro-support", ] @@ -1199,8 +1526,8 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.66", + "quote 1.0.32", "syn 2.0.28", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -1232,8 +1559,8 @@ version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ecb993dd8c836930ed130e020e77d9b2e65dd0fbab1b67c790b0f5d80b11a575" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.66", + "quote 1.0.32", ] [[package]] @@ -1264,9 +1591,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -1279,18 +1606,18 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -1303,45 +1630,54 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + +[[package]] +name = "winnow" +version = "0.5.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b5c3db89721d50d0e2a673f5043fc4722f76dcc352d7b1ab8b8288bed4ed2c5" +dependencies = [ + "memchr", +] [[package]] name = "wyz" @@ -1366,3 +1702,17 @@ name = "zeroize" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2 1.0.66", + "quote 1.0.32", + "syn 2.0.28", +] diff --git a/Cargo.toml b/Cargo.toml index 201390b7d..902a98719 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clvm_tools_rs" -version = "0.1.35" +version = "0.1.40" edition = "2018" authors = ["Art Yerkes "] description = "tools for working with chialisp language; compiler, repl, python and wasm bindings" @@ -31,23 +31,26 @@ indoc = "1.0" do-notation = "0.1.3" serde_json = "1.0" sha2 = "0.9.5" -tempfile = "3.3.0" -clvmr = { version = "0.3.0", features = ["pre-eval"] } +tempfile = "3.10.1" +clvmr = { version = "0.3.2", features = ["pre-eval"] } env_logger = "0.9.0" log = "0.4.17" binascii = "0.1.4" yaml-rust = "0.4" linked-hash-map = "0.5.6" serde = { version = "1.0", features = ["derive", "rc"] } +regex = "1.8.4" [dependencies.pyo3] -version = "0.14.2" +version = "0.20.2" features = ["abi3-py38", "extension-module"] optional = true [dev-dependencies] rand = "0.8.5" rand_chacha = "0.3.1" +lfsr = "0.3.0" +ctor = "0.2.7" [lib] name = "clvm_tools_rs" @@ -100,7 +103,3 @@ path = "src/classic/bins/clisp_to_json.rs" [[bin]] name = "repl" path = "src/classic/bins/repl.rs" - -[[bin]] -name = "typetest" -path = "src/classic/bins/typetest.rs" diff --git a/pyproject.toml b/pyproject.toml index 6049eb79b..45e59490c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["maturin>=1.1.0,<1.3.0"] +requires = ["maturin>=1.3.2,<1.4.0"] build-backend = "maturin" [tool.maturin] diff --git a/resources/coverage/run_coverage.py b/resources/coverage/run_coverage.py index 4c6b48b06..411620c43 100644 --- a/resources/coverage/run_coverage.py +++ b/resources/coverage/run_coverage.py @@ -28,7 +28,7 @@ def run_coverage_test(): subprocess.check_call(['cargo','test'],env=env) def is_my_code(desc): - for path in ['.cargo','library/std','src/py','src/classic/bins']: + for path in ['.cargo','library/std','src/py','src/classic/bins','/rustc']: if path in desc['name']: return False diff --git a/resources/tests/cse-complex-21.clsp b/resources/tests/cse-complex-21.clsp new file mode 100644 index 000000000..531bb5c41 --- /dev/null +++ b/resources/tests/cse-complex-21.clsp @@ -0,0 +1,28 @@ +(mod (X) + (include *standard-cl-21*) + + (defun mess (X) ;; 11 41 + (assign + Y (+ X 1) ;; 12 42 + Z (+ Y 2) ;; 14 44 + + (if (= X 11) + (assign + Y (* X 2) ;; 22 82 + Z (+ Y 1) ;; 23 83 + + (* Y Z) ;; 22 * 23 = 506 + ) + + (assign + Y (* X 3) ;; 33 123 + Z (+ Y 2) ;; 35 125 + + (* Y Z) ;; 123 * 125 = 15375 + ) + ) + ) + ) + + (mess X) + ) diff --git a/resources/tests/deinline/test-basic-deinline.clsp b/resources/tests/deinline/test-basic-deinline.clsp new file mode 100644 index 000000000..67dd10e5b --- /dev/null +++ b/resources/tests/deinline/test-basic-deinline.clsp @@ -0,0 +1,15 @@ +;; This program should ideally become very terse when compiled since everything +;; is constant in it, which means we won't necessarily get a runnable program +;; from chialisp compilation. +;; +;; This is used as one test for --test-deinline. +(mod () + (include *standard-cl-22*) + (include utility_macros.clib) + (defun-inline test-me (X) (* 3 X)) + (assert + (= (test-me 5) 15) + (= (test-me 0) 0) + () + ) + ) diff --git a/resources/tests/game-referee-after-cl21/all-in-list.clinc b/resources/tests/game-referee-after-cl21/all-in-list.clinc new file mode 100644 index 000000000..1db5f26ad --- /dev/null +++ b/resources/tests/game-referee-after-cl21/all-in-list.clinc @@ -0,0 +1,12 @@ +( + (defun enquote-rest (L) + (if L + (c (c 1 (f L)) (enquote-rest (r L))) + () + ) + ) + + (defun all-in-list (L) + (a (c 34 (enquote-rest L)) ()) + ) +) diff --git a/resources/tests/game-referee-after-cl21/assert.clinc b/resources/tests/game-referee-after-cl21/assert.clinc new file mode 100644 index 000000000..c9f212394 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/assert.clinc @@ -0,0 +1,8 @@ +( + (defmacro assert items + (if (r items) + (list if (f items) (c assert (r items)) (q . (x))) + (f items) + ) + ) +) diff --git a/resources/tests/game-referee-after-cl21/busy.clinc b/resources/tests/game-referee-after-cl21/busy.clinc new file mode 100644 index 000000000..e534d2125 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/busy.clinc @@ -0,0 +1,11 @@ +( + (defun busy (myfunc mylist returnval) + (if mylist + (last + (a myfunc (list (f mylist))) + (busy myfunc (r mylist) returnval) + ) + returnval + ) + ) +) diff --git a/resources/tests/game-referee-after-cl21/condition_codes.clinc b/resources/tests/game-referee-after-cl21/condition_codes.clinc new file mode 100644 index 000000000..45f3265da --- /dev/null +++ b/resources/tests/game-referee-after-cl21/condition_codes.clinc @@ -0,0 +1,41 @@ +; See chia/types/condition_opcodes.py + +( + (defconstant AGG_SIG_UNSAFE 49) + (defconstant AGG_SIG_ME 50) + + ; the conditions below reserve coin amounts and have to be accounted for in output totals + + (defconstant CREATE_COIN 51) + (defconstant RESERVE_FEE 52) + + ; the conditions below deal with announcements, for inter-coin communication + + ; coin announcements + (defconstant CREATE_COIN_ANNOUNCEMENT 60) + (defconstant ASSERT_COIN_ANNOUNCEMENT 61) + + ; puzzle announcements + (defconstant CREATE_PUZZLE_ANNOUNCEMENT 62) + (defconstant ASSERT_PUZZLE_ANNOUNCEMENT 63) + + ; the conditions below let coins inquire about themselves + + (defconstant ASSERT_MY_COIN_ID 70) + (defconstant ASSERT_MY_PARENT_ID 71) + (defconstant ASSERT_MY_PUZZLEHASH 72) + (defconstant ASSERT_MY_AMOUNT 73) + + ; the conditions below ensure that we're "far enough" in the future + + ; wall-clock time + (defconstant ASSERT_SECONDS_RELATIVE 80) + (defconstant ASSERT_SECONDS_ABSOLUTE 81) + + ; block index + (defconstant ASSERT_HEIGHT_RELATIVE 82) + (defconstant ASSERT_HEIGHT_ABSOLUTE 83) + + ; A condition that is always true and always ignore all arguments + (defconstant REMARK 1) +) diff --git a/resources/tests/game-referee-after-cl21/curry-and-treehash.clinc b/resources/tests/game-referee-after-cl21/curry-and-treehash.clinc new file mode 100644 index 000000000..6a63e9364 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/curry-and-treehash.clinc @@ -0,0 +1,92 @@ +( + ;; The code below is used to calculate of the tree hash of a curried function + ;; without actually doing the curry, and using other optimization tricks + ;; like unrolling `shatree`. + + (defconstant ONE 1) + (defconstant TWO 2) + (defconstant A_KW #a) + (defconstant Q_KW #q) + (defconstant C_KW #c) + + ;; Given the tree hash `environment-hash` of an environment tree E + ;; and the tree hash `parameter-hash` of a constant parameter P + ;; return the tree hash of the tree corresponding to + ;; `(c (q . P) E)` + ;; This is the new environment tree with the addition parameter P curried in. + ;; + ;; Note that `(c (q . P) E)` = `(c . ((q . P) . (E . 0)))` + + (defun-inline update-hash-for-parameter-hash (parameter-hash environment-hash) + (sha256 TWO (sha256 ONE C_KW) + (sha256 TWO (sha256 TWO (sha256 ONE Q_KW) parameter-hash) + (sha256 TWO environment-hash (sha256 ONE 0)))) + ) + + ;; This function recursively calls `update-hash-for-parameter-hash`, updating `environment-hash` + ;; along the way. + + (defun build-curry-list (reversed-curry-parameter-hashes environment-hash) + (if reversed-curry-parameter-hashes + (build-curry-list (r reversed-curry-parameter-hashes) + (update-hash-for-parameter-hash (f reversed-curry-parameter-hashes) environment-hash)) + environment-hash + ) + ) + + ;; Given the tree hash `environment-hash` of an environment tree E + ;; and the tree hash `function-hash` of a function tree F + ;; return the tree hash of the tree corresponding to + ;; `(a (q . F) E)` + ;; This is the hash of a new function that adopts the new environment E. + ;; This is used to build of the tree hash of a curried function. + ;; + ;; Note that `(a (q . F) E)` = `(a . ((q . F) . (E . 0)))` + + (defun-inline tree-hash-of-apply (function-hash environment-hash) + (sha256 TWO (sha256 ONE A_KW) + (sha256 TWO (sha256 TWO (sha256 ONE Q_KW) function-hash) + (sha256 TWO environment-hash (sha256 ONE 0)))) + ) + + ;; function-hash: + ;; the hash of a puzzle function, ie. a `mod` + ;; + ;; reversed-curry-parameter-hashes: + ;; a list of pre-hashed trees representing parameters to be curried into the puzzle. + ;; Note that this must be applied in REVERSED order. This may seem strange, but it greatly simplifies + ;; the underlying code, since we calculate the tree hash from the bottom nodes up, and the last + ;; parameters curried must have their hashes calculated first. + ;; + ;; we return the hash of the curried expression + ;; (a (q . function-hash) (c (cp1 (c cp2 (c ... 1)...)))) + ;; + ;; Note that from a user's perspective the hashes passed in here aren't simply + ;; the hashes of the desired parameters, but their treehash representation since + ;; that's the form we're assuming they take in the actual curried program. + + (defun puzzle-hash-of-curried-function (function-hash . reversed-curry-parameter-hashes) + (tree-hash-of-apply function-hash + (build-curry-list reversed-curry-parameter-hashes (sha256 ONE ONE))) + ) + + (defconstant b32 32) + + (defun-inline size_b32 (var) + (= (strlen var) b32) + ) + + (defun calculate_coin_id (parent puzzlehash amount) + (if (all (size_b32 parent) (size_b32 puzzlehash) (> amount -1)) + (sha256 parent puzzlehash amount) + (x) + ) + ) + + ; takes a lisp tree and returns the hash of it + (defun shatree (TREE) + (if (l TREE) + (sha256 2 (shatree (f TREE)) (shatree (r TREE))) + (sha256 1 TREE))) + +) diff --git a/resources/tests/game-referee-after-cl21/curry.clinc b/resources/tests/game-referee-after-cl21/curry.clinc new file mode 100644 index 000000000..81a1ec3a6 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/curry.clinc @@ -0,0 +1,104 @@ +( + ;; The code below is used to calculate of the tree hash of a curried function + ;; without actually doing the curry, and using other optimization tricks + ;; like unrolling `shatree`. + + (defconstant TWO 2) + (defconstant constant-tree ( + (0x4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a . ; = `(sha256 1)` + 0x9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2) . ; = `(sha256 1 1)` = `(sha256 1 #q)` + (0x02a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222 . ; = `(concat 2 (sha256 1 #a))` + 0x02a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5) ; = `(concat 2 (sha256 1 #c))` + ) + ) + + ; I looked into calculating the values of `constant-tree` because it's pretty easy to code-golf + ; out an implementation that produces the values cheaper than just inlining them. The problem is, + ; when do we calculate them? If there were a way to calculate it "before main" and include it in + ; the globally-accessible constant table, we could do that. But we can't which means to be optimal, + ; client code should call the "build table" code once, then pass it around to anyone that wants to + ; call `curry` or `curry2`. This is pretty intrusive, so for now we'll just use the existing + ; global constant infrastructure, and include it as a fixed table so the tree of four values will + ; appear in all code that includes this file, and it will compress better in generators. + + (defun-inline sha256_one _noargs (f (f constant-tree))) + (defun-inline sha256_one_one _noargs (r (f constant-tree))) + (defun-inline two_sha256_one_a_kw _noargs (f (r constant-tree))) + (defun-inline two_sha256_one_c_kw _noargs (r (r constant-tree))) + + ;; this returns the sha256 tree hash of expression F = `((q . a1) a2)` + (defun hash-expression-F (a1 a2) + (sha256 TWO (sha256 TWO (sha256_one_one) a1) + (sha256 TWO a2 (sha256_one))) + ) + + ;; Given the tree hash `environment-hash` of an environment tree E + ;; and the tree hash `parameter-hash` of a constant parameter P + ;; return the tree hash of the tree corresponding to + ;; `(c (q . P) E)` + ;; This is the new environment tree with the addition parameter P curried in. + ;; + ;; Note that `(c (q . P) E)` = `(c . ((q . P) . (E . 0)))` + + (defun-inline update-hash-for-parameter-hash (parameter-hash environment-hash) + (sha256 (two_sha256_one_c_kw) (hash-expression-F parameter-hash environment-hash)) + ) + + ;; Given the tree hash `environment-hash` of an environment tree E + ;; and the tree hash `mod-hash` of a mod M + ;; return the tree hash of the tree corresponding to + ;; `(a (q . M) E)` + ;; This is the hash of a new function that adopts the new environment E. + ;; This is used to build of the tree hash of a curried function. + ;; + ;; Note that `(a (q . M) E)` = `(a . ((q . M) . (E . 0)))` + + (defun-inline tree-hash-of-apply (mod-hash environment-hash) + (sha256 (two_sha256_one_a_kw) (hash-expression-F mod-hash environment-hash)) + ) + + ;; This function recursively calls `update-hash-for-parameter-hash` + + (defun calculate-hash-of-curried-parameters (curry-parameter-hashes) + (if curry-parameter-hashes + (update-hash-for-parameter-hash (f curry-parameter-hashes) (calculate-hash-of-curried-parameters (r curry-parameter-hashes))) + (sha256_one_one) + ) + ) + + ;; mod-hash: + ;; the hash of a puzzle function, ie. a `mod` + ;; + ;; curry-parameter-hashes: + ;; a list of pre-hashed trees representing parameters to be curried into the puzzle. + ;; + ;; we return the hash of the curried expression + ;; (a (q . mod-hash) (c (cp1 (c cp2 (c ... 1)...)))) + ;; + ;; Note that from a user's perspective the hashes passed in here aren't simply + ;; the hashes of the desired parameters, but their treehash representation since + ;; that's the form we're assuming they take in the acutal curried program. + + ;; inline functions that take varargs don't seem to work, so we can't inline `curry` + + (defun curry_hashes (mod-hash . curry-parameter-hashes) + (tree-hash-of-apply mod-hash + (calculate-hash-of-curried-parameters curry-parameter-hashes)) + ) + + + ;; this is included for future compilers that handle it properly. If you get weird + ;; errors using this, it may be your tooling. Use `curry` above instead, or inline manually. + + (defun-inline curry_hashes_inline (mod-hash . curry-parameter-hashes) + (tree-hash-of-apply mod-hash + (calculate-hash-of-curried-parameters curry-parameter-hashes)) + ) + + ;; `curry_mod_hashes_inline` takes exactly two parameters rather than varags, and it can be inlined + + (defun-inline curry_mod_hashes_inline (mod-hash curry-parameter-hashes) + (tree-hash-of-apply mod-hash + (calculate-hash-of-curried-parameters curry-parameter-hashes)) + ) +) diff --git a/resources/tests/game-referee-after-cl21/deep_compare.clinc b/resources/tests/game-referee-after-cl21/deep_compare.clinc new file mode 100644 index 000000000..0a863ae33 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/deep_compare.clinc @@ -0,0 +1,41 @@ + +( + (defun deep_compare (a b) + (if (l a) + (if (l b) + (assign-lambda inner_result (deep_compare (f a) (f b)) + (if inner_result + inner_result + (deep_compare (r a) (r b)) + ) + ) + 1 + ) + (if (l b) + -1 + (if (> a b) + 1 + (- 0 (> b a)) + ) + ) + ) + ) + (defun deep< (a b) + (= (deep_compare a b) -1) + ) + (defun deep> (a b) + (= (deep_compare a b) 1) + ) + (defun deep= (a b) + (= (deep_compare a b) 0) + ) + (defun deep<= (a b) + (not (deep> a b)) + ) + (defun deep>= (a b) + (not (deep< a b)) + ) + (defun deep!= (a b) + (not (deep= a b)) + ) +) diff --git a/resources/tests/game-referee-after-cl21/filtermap.clinc b/resources/tests/game-referee-after-cl21/filtermap.clinc new file mode 100644 index 000000000..59c827858 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/filtermap.clinc @@ -0,0 +1,14 @@ + +( + (defun filtermap (process remaining init) + (if remaining + (assign next (a process (list (f remaining))) + (if next + (c next (filtermap process (r remaining) init)) + (filtermap process (r remaining) init) + ) + ) + init + ) + ) +) \ No newline at end of file diff --git a/resources/tests/game-referee-after-cl21/flatten.clinc b/resources/tests/game-referee-after-cl21/flatten.clinc new file mode 100644 index 000000000..ab3815abd --- /dev/null +++ b/resources/tests/game-referee-after-cl21/flatten.clinc @@ -0,0 +1,12 @@ +( + (defun flatten_list (everything) + (if + (not everything) 0 + (prepend (f everything) (flatten_list (r everything))) + ) + ) + (defun flatten everything + (flatten_list everything) + ) + +) \ No newline at end of file diff --git a/resources/tests/game-referee-after-cl21/handcalc.clinc b/resources/tests/game-referee-after-cl21/handcalc.clinc new file mode 100644 index 000000000..6317733f4 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/handcalc.clinc @@ -0,0 +1,140 @@ + +; ranks are 2-14 with 2 being two, 13 being king, and 14 being ace +; suits are 1-4 with no particular labelling +; takes a list of cards (rank . suit) and returns the value of the best poker +; hand which can be made with them +; returned list is hand type followed by cards in descending order +; doesn't work for ten or more cards if there are multiple flushes +; all sorting is done highest to lowest +( + (defconstant STRAIGHT_FLUSH 9) + (defconstant FOUR_OF_A_KIND 8) + (defconstant FULL_HOUSE 7) + (defconstant FLUSH 6) + (defconstant STRAIGHT 5) + (defconstant THREE_OF_A_KIND 4) + (defconstant TWO_PAIR 3) + (defconstant PAIR 2) + (defconstant HIGH_CARD 1) + (defun find_flush_inner (suits last count) + (if (not suits) + 0 + (if (= (f suits) last) + (if (= count 4) + last + (find_flush_inner (r suits) last (+ count 1)) + ) + (find_flush_inner (r suits) (f suits) 1) + ) + ) + ) + ; returns the flush suit or 0 if there isn't any + ; suits must be clustered/sorted + (defun find_flush (suits) + (find_flush_inner (sort (lambda (x y) (deep> x y)) suits) 0 0) + ) + (defun straight_high_inner (ranks started_ace last count) + (if (not ranks) + ; at the end of the list + (if (logand (= last 2) (= count 4) started_ace) + ; ace to five + 5 + ; no straight + 0 + ) + (if (= last (f ranks)) + ; skip identical cards + (straight_high_inner (r ranks) started_ace last count) + ; if the partial straight continues + (if (= (f ranks) (- last 1)) + (if (= count 4) + ; found a straight, add 3 to last because next and last are included + (+ last 3) + ; keep looking for a straight with the count going up by one + (straight_high_inner (r ranks) started_ace (f ranks) (+ count 1)) + ) + ; reset the count + (straight_high_inner (r ranks) started_ace (f ranks) 1) + ) + ) + ) + ) + ; returns the high card of a straight or 0 if there isn't any + ; ranks must be sorted in descending order + (defun straight_high (ranks) + (straight_high_inner ranks (= (f ranks) 14) 0 0) + ) + (defun group_by_count_inner (items last count) + (if (not items) + (list (c count last)) + (if (= (f items) last) + (group_by_count_inner (r items) last (+ count 1)) + (assign val (group_by_count_inner (r items) (f items) 1) + (c (c count last) val) + ) + ) + ) + ) + (defun group_by_count (items) + (group_by_count_inner items (f items) 0) + ) + (defun handcalc (cards) + (assign-lambda + first (lambda (x) (f x)) + rest (lambda (x) (r x)) + fsuit (find_flush (map rest cards)) + max_flush (if (not fsuit) + 0 + (assign-lambda + fnosuits + (sort + (lambda (x y) (deep> x y)) + (filtermap + (lambda ((& fsuit) (card_rank . card_suit)) + (if (= fsuit card_suit) + card_rank + 0 + ) + ) + cards + 0 + ) + ) + + fsh (straight_high fnosuits) + (if fsh + (list STRAIGHT_FLUSH fsh) + (c FLUSH (slice fnosuits 5)) + ) + ) + ) + nosuits (sort (lambda (x y) (deep> x y)) (map first cards)) + sh (straight_high nosuits) + max_straight (if sh + (list STRAIGHT sh) + 0 + ) + groups (sort (lambda (x y) (deep> x y)) (group_by_count nosuits)) + (top_count . top_card) (f groups) + (second_count . second_card) (f (r groups)) + topcards (map rest groups) + max_group (if (= top_count 1) + (c HIGH_CARD (slice topcards 5)) + (if (= top_count 2) + (if (= second_count 1) + (c PAIR (slice topcards 4)) + (c TWO_PAIR (slice topcards 3)) + ) + (if (= top_count 3) + (if (= second_count 1) + (c THREE_OF_A_KIND (slice topcards 3)) + (c FULL_HOUSE (slice topcards 2)) + ) + (c FOUR_OF_A_KIND (slice topcards 2)) + ) + ) + ) + (max (lambda (x y) (deep< x y)) (list max_flush max_straight max_group)) + ) + ) +) diff --git a/resources/tests/game-referee-after-cl21/handcalc_a.clinc b/resources/tests/game-referee-after-cl21/handcalc_a.clinc new file mode 100644 index 000000000..06c326392 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/handcalc_a.clinc @@ -0,0 +1,256 @@ + +; ranks are 2-14 with 2 being two, 13 being king, and 14 being ace +; suits are 1-4 with no particular labelling +; takes a list of cards (rank . suit) and returns the value of the best poker +; hand which can be made with them +; returned list is hand type followed by cards in descending order +; doesn't work for ten or more cards if there are multiple flushes +; all sorting is done highest to lowest +( + (defconstant STRAIGHT_FLUSH 9) + (defconstant FOUR_OF_A_KIND 8) + (defconstant FULL_HOUSE 7) + (defconstant FLUSH 6) + (defconstant STRAIGHT 5) + (defconstant THREE_OF_A_KIND 4) + (defconstant TWO_PAIR 3) + (defconstant PAIR 2) + (defconstant HIGH_CARD 1) + (defun hand_compare (a b) + (if (= (f a) (f b)) + (if (r a) + (hand_compare (r a) (r b)) + 0 + ) + (- (* 2 (> (f a) (f b))) 1) + ) + ) + (defun hand< (a b) + (= (hand_compare a b) -1) + ) + (defun merge (a b) + (if (not a) + b + (if (not b) + a + (if (> (f a) (f b)) + (c (f a) (merge (r a) b)) + (c (f b) (merge a (r b))) + ) + ) + ) + ) + ; Sorts atoms into descending order + ; This is optimized for sorting short lists + ; A more general function would return a list of lists of ascending sizes + ; to be merged + (defun atomsort ((@ firstpos (first @ secondpos (second @ thirdpos (third . remaining))))) + (if firstpos + (if secondpos + (if thirdpos + (assign-lambda + mylist + (if (> first second) + (if (> second third) + (list first second third) + (if (> first third) + (list first third second) + (list third first second) + ) + ) + (if (> first third) + (list second first third) + (if (> second third) + (list second third first) + (list third second first) + ) + ) + ) + (merge mylist (atomsort remaining)) + ) + (if (> first second) + firstpos + (list second first) + ) + ) + firstpos + ) + 0 + ) + ) + (defun count_suits_2 ((@ suits (firstsuit . remaining))) + (if (not suits) + (c (c 0 0) (c 0 0)) + (assign-lambda ((@ cd (clubs . diamonds)) . (@ hs (hearts . spades))) (count_suits remaining) + (if (= firstsuit 1) + (c (c (+ clubs 1) diamonds) hs) + (if (= firstsuit 2) + (c (c clubs (+ diamonds 1)) hs) + (if (= firstsuit 3) + (c cd (c (+ hearts 1) spades)) + (c cd (c hearts (+ spades 1))) + ) + ) + ) + ) + ) + ) + (defun find_flush_2 (suits) + (assign-lambda ((clubs . diamonds) . (hearts . spades)) (count_suits suits) + (if (> clubs 4) + 1 + (if (> diamonds 4) + 2 + (if (> hearts 4) + 3 + (if (> spades 4) + 4 + 0 + ) + ) + ) + ) + ) + ) + (defun count_suits (suits) + (if suits + (+ (count_suits (r suits)) (ash 1 (* 4 (- (f suits) 1)))) + 0 + ) + ) + (defun find_flush (suits) + (assign-lambda + myvals (count_suits suits) + (if (> (logand myvals 0xF000) 0x4000) + 4 + (if (> (logand myvals 0x0F00) 0x0400) + 3 + (if (> (logand myvals 0x00F0) 0x0040) + 2 + (if (> (logand myvals 0x0F) 0x04) + 1 + 0 + ) + ) + ) + ) + ) + ) + (defun straight_high_inner (ranks last count) + (if (not ranks) + (if (logand (= last 2) (= count 4)) + ; maybe ace to five + 5 + 0 + ) + (if (= last (f ranks)) + ; skip identical cards + (straight_high_inner (r ranks) last count) + ; if the partial straight continues + (if (= (f ranks) (- last 1)) + (if (= count 4) + ; found a straight, add 3 to last because next and last are included + (+ last 3) + ; keep looking for a straight with the count going up by one + (straight_high_inner (r ranks) (f ranks) (+ count 1)) + ) + ; reset the count + (straight_high_inner (r ranks) (f ranks) 1) + ) + ) + ) + ) + ; returns the high card of a straight or 0 if there isn't any + ; ranks must be sorted in descending order + (defun straight_high (ranks) + (assign-lambda high (straight_high_inner ranks 0 0) + (if (= high 5) + (* (= (f ranks) 14) 5) + high + ) + ) + ) + (defun group_by_count_inner (items last count) + (if (not items) + (list (logior (lsh count 4) last)) + (if (= (f items) last) + (group_by_count_inner (r items) last (+ count 1)) + (assign-inline val (group_by_count_inner (r items) (f items) 1) + (c (logior (lsh count 4) last) val) + ) + ) + ) + ) + (defun group_by_count (items) + (group_by_count_inner items (f items) 0) + ) + (defun handcalc (cards) + (assign-lambda + first (lambda (x) (f x)) + rest (lambda (x) (r x)) + fsuit (find_flush (map rest cards)) + max_flush (if (not fsuit) + (list 0) + (assign-lambda + flushcards + (filtermap + (lambda ((& fsuit) (card_rank . card_suit)) + (if (= fsuit card_suit) + card_rank + 0 + ) + ) + cards + 0 + ) + flushranks (atomsort flushcards) + fsh (straight_high flushranks) + (if fsh + (list STRAIGHT_FLUSH fsh) + (c FLUSH (slice flushranks 5)) + ) + ) + ) + ranks (atomsort (map first cards)) + sh (straight_high ranks) + max_straight (if sh + (list STRAIGHT sh) + (list 0) + ) + groups (map + (lambda (myval) (c (lsh myval -4) (logand myval 0x0F))) + (atomsort (group_by_count ranks)) + ) + (top_count . top_card) (f groups) + (second_count . second_card) (f (r groups)) + topcards (map rest groups) + max_group (if (= top_count 1) + (c HIGH_CARD (slice topcards 5)) + (if (= top_count 2) + (if (= second_count 1) + (c PAIR (slice topcards 4)) + (c TWO_PAIR (slice topcards 3)) + ) + (if (= top_count 3) + (if (= second_count 1) + (c THREE_OF_A_KIND (slice topcards 3)) + (c FULL_HOUSE (slice topcards 2)) + ) + (c FOUR_OF_A_KIND (slice topcards 2)) + ) + ) + ) + ; max of max_flush max_straight and max_group + (if (> (f max_flush) (f max_straight)) + (if (> (f max_flush) (f max_group)) + max_flush + max_group + ) + (if (> (f max_straight) (f max_group)) + max_straight + max_group + ) + ) + ) + ) +) diff --git a/resources/tests/game-referee-after-cl21/last.clinc b/resources/tests/game-referee-after-cl21/last.clinc new file mode 100644 index 000000000..5a6ffd73e --- /dev/null +++ b/resources/tests/game-referee-after-cl21/last.clinc @@ -0,0 +1,39 @@ +( + (defun last_inner ((next . remainder)) + (if remainder + (last_inner remainder) + next + ) + ) + + (defmacro last ARGS + (defun snoc (L agg) + (if L + (if (r L) + (snoc (r L) (c (f L) agg)) + (c (f L) agg) + ) + (c () ()) + ) + ) + + (defun prefix (L P) + (if L + (c (f L) (prefix (r L) P)) + P + ) + ) + + (if ARGS + (if (r ARGS) + (assign + (final . rest) (snoc ARGS ()) + reversed (prefix rest (list final)) + (qq (last_inner (unquote (c list reversed)))) + ) + (qq (last_inner (unquote (f ARGS)))) + ) + (x "Last takes at least one argument") + ) + ) +) diff --git a/resources/tests/game-referee-after-cl21/len.clinc b/resources/tests/game-referee-after-cl21/len.clinc new file mode 100644 index 000000000..407c36694 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/len.clinc @@ -0,0 +1,3 @@ +( + (defun len (L) (if L (+ 1 (len (r L))) 0)) +) diff --git a/resources/tests/game-referee-after-cl21/map.clinc b/resources/tests/game-referee-after-cl21/map.clinc new file mode 100644 index 000000000..016c3a0e4 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/map.clinc @@ -0,0 +1,17 @@ +( + (defun map-with-rest (F L R) + (if L + (c (a F (list (f L))) (map-with-rest F (r L) R)) + R + ) + ) + + (defmacro map ARGS + (defun list-len (X) (if X (+ 1 (list-len (r X))) 0)) + + (if (= (list-len ARGS) 3) + (qq (map-with-rest (unquote (f ARGS)) (unquote (f (r ARGS))) (unquote (f (r (r ARGS)))))) + (qq (map-with-rest (unquote (f ARGS)) (unquote (f (r ARGS))) ())) + ) + ) +) diff --git a/resources/tests/game-referee-after-cl21/match.clinc b/resources/tests/game-referee-after-cl21/match.clinc new file mode 100644 index 000000000..d66593c55 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/match.clinc @@ -0,0 +1,12 @@ + +( + (defun match (process remaining) + (if remaining + (if (a process (list (f remaining))) + (f remaining) + (match process (r remaining)) + ) + 0 + ) + ) +) diff --git a/resources/tests/game-referee-after-cl21/max.clinc b/resources/tests/game-referee-after-cl21/max.clinc new file mode 100644 index 000000000..5ec6d54f6 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/max.clinc @@ -0,0 +1,13 @@ +( + (defun max_inner (myless best_so_far mylist) + (if (not mylist) best_so_far + (if (a myless (list best_so_far (f mylist))) + (max_inner myless (f mylist) (r mylist)) + (max_inner myless best_so_far (r mylist)) + ) + ) + ) + (defun max (myless mylist) + (max_inner myless (f mylist) (r mylist)) + ) +) diff --git a/resources/tests/game-referee-after-cl21/permutations.clinc b/resources/tests/game-referee-after-cl21/permutations.clinc new file mode 100644 index 000000000..9664c6aff --- /dev/null +++ b/resources/tests/game-referee-after-cl21/permutations.clinc @@ -0,0 +1,21 @@ +( + (defun permutations_inner (pre post agg) + (if (not post) + agg + (assign + myatom (f post) + newrest (r post) + (map (lambda ((& myatom) x) (c myatom x)) + (permutations (prepend pre newrest)) + (permutations_inner (c myatom pre) newrest agg) + ) + ) + ) + ) + (defun permutations (vals) + (if vals + (permutations_inner 0 vals 0) + (q ()) + ) + ) +) diff --git a/resources/tests/game-referee-after-cl21/prefix.clinc b/resources/tests/game-referee-after-cl21/prefix.clinc new file mode 100644 index 000000000..641723dad --- /dev/null +++ b/resources/tests/game-referee-after-cl21/prefix.clinc @@ -0,0 +1,16 @@ +( + (defmacro prefix ARGS + (defun compile-list (args) + (if args + (if (r args) + ;; We have at least 2 things left... recurse once. + (qq (c (unquote (f args)) (unquote (compile-list (r args))))) + ;; This is the last item, so we return it whole (improper list form). + (qq (unquote (f args))) + ) + 0 + ) + ) + (compile-list ARGS) + ) +) \ No newline at end of file diff --git a/resources/tests/game-referee-after-cl21/prepend.clinc b/resources/tests/game-referee-after-cl21/prepend.clinc new file mode 100644 index 000000000..2ea293409 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/prepend.clinc @@ -0,0 +1,8 @@ +( + (defun prepend (a b) + (if a + (c (f a) (prepend (r a) b)) + b + ) + ) +) \ No newline at end of file diff --git a/resources/tests/game-referee-after-cl21/print.clinc b/resources/tests/game-referee-after-cl21/print.clinc new file mode 100644 index 000000000..95d459b36 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/print.clinc @@ -0,0 +1,3 @@ +( + (defun print (R P) (if (all "$print$" R P) P P)) +) diff --git a/resources/tests/game-referee-after-cl21/range.clinc b/resources/tests/game-referee-after-cl21/range.clinc new file mode 100644 index 000000000..dc1e61ca3 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/range.clinc @@ -0,0 +1,11 @@ +( + (defun range_inner (next final) + (if (= next final) + 0 + (c next (range_inner (+ next 1) final)) + ) + ) + (defun range (i) + (range_inner 0 i) + ) +) \ No newline at end of file diff --git a/resources/tests/game-referee-after-cl21/reduce.clinc b/resources/tests/game-referee-after-cl21/reduce.clinc new file mode 100644 index 000000000..3251c79a7 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/reduce.clinc @@ -0,0 +1,10 @@ + +( + ; From here to the meat should be in a standard library + (defun reduce (fun lst init) + (if lst + (reduce fun (r lst) (a fun (list (f lst) init))) + init + ) + ) +) diff --git a/resources/tests/game-referee-after-cl21/reverse.clinc b/resources/tests/game-referee-after-cl21/reverse.clinc new file mode 100644 index 000000000..389963ee9 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/reverse.clinc @@ -0,0 +1,11 @@ +( + (defun reverse_inner (reversed rest) + (if rest + (reverse_inner (c (f rest) reversed) (r rest)) + reversed + ) + ) + (defun reverse (vals) + (reverse_inner 0 vals) + ) +) diff --git a/resources/tests/game-referee-after-cl21/shatree.clinc b/resources/tests/game-referee-after-cl21/shatree.clinc new file mode 100644 index 000000000..05bdb2699 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/shatree.clinc @@ -0,0 +1,11 @@ +( + ;; hash a tree + ;; This is used to calculate a puzzle hash given a puzzle program. + (defun shatree + (TREE) + (if (l TREE) + (sha256 2 (shatree (f TREE)) (shatree (r TREE))) + (sha256 1 TREE) + ) + ) +) \ No newline at end of file diff --git a/resources/tests/game-referee-after-cl21/slice.clinc b/resources/tests/game-referee-after-cl21/slice.clinc new file mode 100644 index 000000000..2c98a09c5 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/slice.clinc @@ -0,0 +1,10 @@ + +( + ; returns the first count elements of mylist + (defun slice (mylist count) + (if (print (list "slice inputs" nylist count) (not count)) + 0 + (c (f mylist) (slice (r mylist) (- count 1))) + ) + ) +) diff --git a/resources/tests/game-referee-after-cl21/smoke_test_deep_compare.clsp b/resources/tests/game-referee-after-cl21/smoke_test_deep_compare.clsp new file mode 100644 index 000000000..8df629518 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/smoke_test_deep_compare.clsp @@ -0,0 +1,28 @@ +(mod () + (include *standard-cl-21*) + (include print.clinc) + (include prepend.clinc) + (include sort.clinc) + (include assert.clinc) + (include map.clinc) + (include deep_compare.clinc) + + (map + (lambda ((want_cmp_val cmp_a cmp_b)) + (= (deep_compare cmp_a cmp_b) want_cmp_val) + ) + (q + (0 0 0) + (-1 () (1 14 5 4 3 2)) + (1 (1 14 5 4 3 2) ()) + (-1 "X" (1 2)) + (1 (1 2) "X") + (0 (3 2) (3 2)) + (-1 (3 1) (3 3)) + (1 (3 3) (3 1)) + (-1 (1 1) (2 1)) + (1 (3 1) (2 2)) + (-1 (2 2) (3 1)) + ) + ) + ) diff --git a/resources/tests/game-referee-after-cl21/smoke_test_deep_compare.clvm.hex b/resources/tests/game-referee-after-cl21/smoke_test_deep_compare.clvm.hex new file mode 100644 index 000000000..cb3eb0bf7 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/smoke_test_deep_compare.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff08ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff0e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ffff01ffff80ff80ff8080ffff81ffff80ffff01ff0eff05ff04ff03ff028080ffff01ffff01ff0eff05ff04ff03ff0280ff8080ffff81ffff58ffff01ff028080ffff01ffff01ff0280ff5880ffff80ffff03ff0280ffff03ff028080ffff81ffffff03ff0180ffff03ff038080ffff01ffff03ff0380ffff03ff018080ffff81ffffff01ff0180ffff02ff018080ffff01ffff03ff0180ffff02ff028080ffff81ffffff02ff0280ffff03ff01808080ffff04ffff0180ff808080808080ffff04ffff01ffffff02ffff03ff0bffff01ff02ffff01ff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff02ff08ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff80808080808080ff0180ffff01ff02ffff0117ff018080ff0180ff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff06ff0180ffff04ffff02ff0cffff04ff02ffff04ffff05ff0580ffff04ffff05ff0b80ff8080808080ff8080808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff0181ffff0180ffff01ff02ffff01ff02ffff03ffff15ff05ff0b80ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff11ffff0180ffff15ff0bff058080ff018080ff0180ff018080ff0180ff018080ff0180ffff02ffff03ff0bffff01ff02ffff010bff0180ffff01ff02ffff01ff02ff0cffff04ff02ffff04ffff06ff0980ffff04ffff06ff1580ff8080808080ff018080ff0180ff09ffff02ff0cffff04ff02ffff04ff2bffff04ff5bff8080808080ff1380ff018080 diff --git a/resources/tests/game-referee-after-cl21/smoke_test_deep_compare.sym b/resources/tests/game-referee-after-cl21/smoke_test_deep_compare.sym new file mode 100644 index 000000000..f9bcf963b --- /dev/null +++ b/resources/tests/game-referee-after-cl21/smoke_test_deep_compare.sym @@ -0,0 +1 @@ +{"4fd7e0dfbd7ac5775e6d61670f548dc35ff62a1a4b14f2f3efe09d8b39e6988b": "map-with-rest", "d9f6d93919b2fb79bc296ac80d73b5c48bf044e457f0f678b210f990efeea743_left_env": "1", "4fd7e0dfbd7ac5775e6d61670f548dc35ff62a1a4b14f2f3efe09d8b39e6988b_left_env": "1", "026e28eecfeb07594300bd6c3bce34bd4fe340a189ddd5312c7361e242b52160": "lambda_$_199", "a08c534dd3a89e22a8fadaa027c6b9a8dd4f9a00b72c315821703d8ee1c8f687": "deep_compare", "4fd7e0dfbd7ac5775e6d61670f548dc35ff62a1a4b14f2f3efe09d8b39e6988b_arguments": "(F L R)", "a08c534dd3a89e22a8fadaa027c6b9a8dd4f9a00b72c315821703d8ee1c8f687_arguments": "(a b)", "d9f6d93919b2fb79bc296ac80d73b5c48bf044e457f0f678b210f990efeea743_arguments": "((a_$_181 b_$_182) inner_result_$_183)", "026e28eecfeb07594300bd6c3bce34bd4fe340a189ddd5312c7361e242b52160_left_env": "1", "026e28eecfeb07594300bd6c3bce34bd4fe340a189ddd5312c7361e242b52160_arguments": "(() (want_cmp_val_$_196 cmp_a_$_197 cmp_b_$_198))", "a08c534dd3a89e22a8fadaa027c6b9a8dd4f9a00b72c315821703d8ee1c8f687_left_env": "1", "d9f6d93919b2fb79bc296ac80d73b5c48bf044e457f0f678b210f990efeea743": "letbinding_$_200", "source_file": "/home/arty/dev/chia/clvm_tools_rs/resources/tests/game-referee-after-cl21/smoke_test_deep_compare.clsp", "__chia__main_arguments": "()"} \ No newline at end of file diff --git a/resources/tests/game-referee-after-cl21/smoke_test_permutations.clsp b/resources/tests/game-referee-after-cl21/smoke_test_permutations.clsp new file mode 100644 index 000000000..2ed3fbbcc --- /dev/null +++ b/resources/tests/game-referee-after-cl21/smoke_test_permutations.clsp @@ -0,0 +1,9 @@ +(mod (X) + (include *standard-cl-21*) + (include map.clinc) + (include prepend.clinc) + (include print.clinc) + (include permutations.clinc) + + (permutations X) + ) diff --git a/resources/tests/game-referee-after-cl21/smoke_test_permutations.clvm.hex b/resources/tests/game-referee-after-cl21/smoke_test_permutations.clvm.hex new file mode 100644 index 000000000..813027e6d --- /dev/null +++ b/resources/tests/game-referee-after-cl21/smoke_test_permutations.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff1effff04ff02ffff04ff05ff80808080ffff04ffff01ffffff02ffff03ff0bffff01ff02ffff01ff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff02ff08ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff80808080808080ff0180ffff01ff02ffff0117ff018080ff0180ffff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff14ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff02ffff03ffff20ff0b80ffff01ff02ffff0117ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff06ff0180ffff04ffff06ff0b80ffff04ffff05ff0b80ff808080808080ff018080ff0180ffff02ff08ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff1680ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff17ff808080ffff01ff01808080ff80808080ffff04ffff02ff1effff04ff02ffff04ffff02ff14ffff04ff02ffff04ff09ffff04ff0bff8080808080ff80808080ffff04ffff02ff1cffff04ff02ffff04ffff04ff17ff0980ffff04ff0bffff04ff2dff808080808080ff808080808080ffff04ff09ff0b80ff02ffff03ff05ffff01ff02ffff01ff02ff1cffff04ff02ffff04ffff0180ffff04ff05ffff04ffff0180ff808080808080ff0180ffff01ff02ffff01ff01ff8080ff018080ff0180ff018080 diff --git a/resources/tests/game-referee-after-cl21/smoke_test_permutations.sym b/resources/tests/game-referee-after-cl21/smoke_test_permutations.sym new file mode 100644 index 000000000..ce21d4fac --- /dev/null +++ b/resources/tests/game-referee-after-cl21/smoke_test_permutations.sym @@ -0,0 +1 @@ +{"ce9e2b2b4940b8e6b74f2eb0935a66717ce0f8ae750cea80407fdc2f89650833_arguments": "((pre_$_1375 post_$_1376 agg_$_1377) newrest_$_1379 myatom_$_1378)", "__chia__main_arguments": "(X)", "bdc4b151632158e39adf669800ccfaa731e9f01d6adbfe935422aecdd4c4088b_left_env": "1", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708_arguments": "((myatom_$_1378) x_$_1380)", "048d5413ce5265ab36813735bc75ba7b7c5e9454553198bfdafef009677e420b_left_env": "1", "048d5413ce5265ab36813735bc75ba7b7c5e9454553198bfdafef009677e420b_arguments": "(a b)", "source_file": "/home/arty/dev/chia/clvm_tools_rs/resources/tests/game-referee-after-cl21/smoke_test_permutations.clsp", "4fd7e0dfbd7ac5775e6d61670f548dc35ff62a1a4b14f2f3efe09d8b39e6988b_arguments": "(F L R)", "bdc4b151632158e39adf669800ccfaa731e9f01d6adbfe935422aecdd4c4088b": "permutations_inner", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708": "lambda_$_1383", "e209270f1dc5e9d4b9d3c077d401c47f47bb866e87d1707551d101b8717f4edf_left_env": "1", "ce9e2b2b4940b8e6b74f2eb0935a66717ce0f8ae750cea80407fdc2f89650833": "letbinding_$_1382", "bdc4b151632158e39adf669800ccfaa731e9f01d6adbfe935422aecdd4c4088b_arguments": "(pre post agg)", "e209270f1dc5e9d4b9d3c077d401c47f47bb866e87d1707551d101b8717f4edf_arguments": "(vals)", "048d5413ce5265ab36813735bc75ba7b7c5e9454553198bfdafef009677e420b": "prepend", "4fd7e0dfbd7ac5775e6d61670f548dc35ff62a1a4b14f2f3efe09d8b39e6988b_left_env": "1", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708_left_env": "1", "4fd7e0dfbd7ac5775e6d61670f548dc35ff62a1a4b14f2f3efe09d8b39e6988b": "map-with-rest", "ce9e2b2b4940b8e6b74f2eb0935a66717ce0f8ae750cea80407fdc2f89650833_left_env": "1", "e209270f1dc5e9d4b9d3c077d401c47f47bb866e87d1707551d101b8717f4edf": "permutations"} \ No newline at end of file diff --git a/resources/tests/game-referee-after-cl21/smoke_test_sort.clsp b/resources/tests/game-referee-after-cl21/smoke_test_sort.clsp new file mode 100644 index 000000000..59b8a886e --- /dev/null +++ b/resources/tests/game-referee-after-cl21/smoke_test_sort.clsp @@ -0,0 +1,11 @@ +(mod (X) + (include *standard-cl-21*) + (include prepend.clinc) + (include sort.clinc) + (include assert.clinc) + (include map.clinc) + (include reverse.clinc) + (include print.clinc) + + (sort (lambda (a b) (> b a)) X) + ) diff --git a/resources/tests/game-referee-after-cl21/smoke_test_sort.clvm.hex b/resources/tests/game-referee-after-cl21/smoke_test_sort.clvm.hex new file mode 100644 index 000000000..476b5f74e --- /dev/null +++ b/resources/tests/game-referee-after-cl21/smoke_test_sort.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff12ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff3e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ff05ff8080808080ffff04ffff01ffffffff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff10ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff02ffff03ff05ffff01ff02ffff01ff02ff18ffff04ff02ffff04ffff06ff0580ffff04ff17ffff04ffff04ffff05ff0580ff0b80ff808080808080ff0180ffff01ff02ffff01ff06ff0380ff018080ff0180ffff02ff18ffff04ff02ffff04ff05ffff01ff80ff8080808080ffff02ffff03ffff20ff0b80ffff01ff02ffff01ff02ff10ffff04ff02ffff04ffff02ff2effff04ff02ffff04ff2fff80808080ffff04ff17ff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff20ff1780ffff01ff02ffff01ff02ff10ffff04ff02ffff04ffff02ff2effff04ff02ffff04ff2fff80808080ffff04ff0bff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff02ff05ffff04ffff05ff0b80ffff04ffff05ff1780ffff0180808080ffff01ff02ffff01ff02ff2cffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ffff04ffff04ffff05ff0b80ff2f80ff80808080808080ff0180ffff01ff02ffff01ff02ff2cffff04ff02ffff04ff05ffff04ff0bffff04ffff06ff1780ffff04ffff04ffff05ff1780ff2f80ff80808080808080ff018080ff0180ff018080ff0180ff018080ff0180ff02ff2cffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff01ff80808080808080ffffff02ffff03ff0bffff01ff02ffff01ff02ffff03ffff06ff0b80ffff01ff02ffff01ff02ff2affff04ff02ffff04ffff06ff0180ffff04ffff02ff14ffff04ff02ffff04ff0bff80808080ff8080808080ff0180ffff01ff02ffff010bff018080ff0180ff0180ffff01ff02ffff01ff0180ff018080ff0180ffff02ff3affff04ff02ffff04ff03ffff04ffff02ff12ffff04ff02ffff04ff09ffff04ff13ff8080808080ffff04ffff02ff12ffff04ff02ffff04ff09ffff04ff2bff8080808080ff808080808080ff02ff3cffff04ff02ffff04ff11ffff04ff0bffff04ff17ff808080808080ffff02ffff03ff0bffff01ff02ffff01ff02ff16ffff04ff02ffff04ffff04ffff05ff0b80ff0580ffff04ffff06ff0b80ff8080808080ff0180ffff01ff02ffff0105ff018080ff0180ffff02ff16ffff04ff02ffff04ff80ffff04ff05ff8080808080ff15ff17ff0b80ff018080 diff --git a/resources/tests/game-referee-after-cl21/smoke_test_sort.sym b/resources/tests/game-referee-after-cl21/smoke_test_sort.sym new file mode 100644 index 000000000..0a2b030b8 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/smoke_test_sort.sym @@ -0,0 +1 @@ +{"f51796fc523809b04629ca42cffbb3514471eade8cd7d6908f3015f535a97de4": "letbinding_$_369", "1b7d3888612a5d795887e5e192e68b15536e0e4c08e19324569a576ff06c6299_left_env": "1", "1b7d3888612a5d795887e5e192e68b15536e0e4c08e19324569a576ff06c6299_arguments": "(reversed rest)", "__chia__main_arguments": "(X)", "842642e018168c91bd70ba0be54c311ce3947fe0ce5e418f6a1c88289e11c84b": "lambda_$_368", "107eecc0e2d1b059c660f3c81d6e61dd2fc7f71d4f446067132a09d395202140_arguments": "(vals)", "aa2a43f5d1d2ed44bd135ee807b27cb33eea736d2e50b2787c5fd4100f128f47": "letbinding_$_370", "fa9304ef33f250463c38ac3368ad79c5416173e5a666c6571e9b4c5d8b983da1_left_env": "1", "f51796fc523809b04629ca42cffbb3514471eade8cd7d6908f3015f535a97de4_left_env": "1", "6336806e19a49e9e91a62932f741d94eeca9a3656f35ecf39bc22e15d9940d53": "split", "6336806e19a49e9e91a62932f741d94eeca9a3656f35ecf39bc22e15d9940d53_arguments": "(mylist)", "1b7d3888612a5d795887e5e192e68b15536e0e4c08e19324569a576ff06c6299": "reverse_inner", "b8edc250e5666a96397652bb34bdc9979fcd8df7f5aec90e481b7ae4234525aa_arguments": "(myless a b)", "aa2a43f5d1d2ed44bd135ee807b27cb33eea736d2e50b2787c5fd4100f128f47_left_env": "1", "107eecc0e2d1b059c660f3c81d6e61dd2fc7f71d4f446067132a09d395202140_left_env": "1", "9d8df0b4587c62404485833b9a811fe717b4f9eb3ff4a11a7806e7fd07a1c5f8_arguments": "(a b)", "842642e018168c91bd70ba0be54c311ce3947fe0ce5e418f6a1c88289e11c84b_arguments": "(() a_$_366 b_$_367)", "a3ddf8cdd53afc8bcdd3082f709b5f66156f31f8a56e603da27b4e382a68b9f3_arguments": "(myless mylist)", "f51796fc523809b04629ca42cffbb3514471eade8cd7d6908f3015f535a97de4_arguments": "((myless_$_347 mylist_$_348) (a_$_349 b_$_350))", "9d8df0b4587c62404485833b9a811fe717b4f9eb3ff4a11a7806e7fd07a1c5f8_left_env": "1", "b8edc250e5666a96397652bb34bdc9979fcd8df7f5aec90e481b7ae4234525aa_left_env": "1", "fa9304ef33f250463c38ac3368ad79c5416173e5a666c6571e9b4c5d8b983da1_arguments": "(myless A B agg)", "95e75b36710d3038b1cfe847cc61158c78d91e4d6db6757217c8b32ac4ae13b3_left_env": "1", "95e75b36710d3038b1cfe847cc61158c78d91e4d6db6757217c8b32ac4ae13b3_arguments": "(@ everything (rest aggl aggr))", "6336806e19a49e9e91a62932f741d94eeca9a3656f35ecf39bc22e15d9940d53_left_env": "1", "a3ddf8cdd53afc8bcdd3082f709b5f66156f31f8a56e603da27b4e382a68b9f3": "sort", "source_file": "/home/arty/dev/chia/clvm_tools_rs/resources/tests/game-referee-after-cl21/smoke_test_sort.clsp", "b8edc250e5666a96397652bb34bdc9979fcd8df7f5aec90e481b7ae4234525aa": "merge", "107eecc0e2d1b059c660f3c81d6e61dd2fc7f71d4f446067132a09d395202140": "reverse", "9d8df0b4587c62404485833b9a811fe717b4f9eb3ff4a11a7806e7fd07a1c5f8": "prepend", "842642e018168c91bd70ba0be54c311ce3947fe0ce5e418f6a1c88289e11c84b_left_env": "1", "95e75b36710d3038b1cfe847cc61158c78d91e4d6db6757217c8b32ac4ae13b3": "split_inner", "fa9304ef33f250463c38ac3368ad79c5416173e5a666c6571e9b4c5d8b983da1": "merge_inner", "a3ddf8cdd53afc8bcdd3082f709b5f66156f31f8a56e603da27b4e382a68b9f3_left_env": "1", "aa2a43f5d1d2ed44bd135ee807b27cb33eea736d2e50b2787c5fd4100f128f47_arguments": "(((myless_$_347 mylist_$_348) (a_$_349 b_$_350)) sa_$_351 sb_$_352)"} \ No newline at end of file diff --git a/resources/tests/game-referee-after-cl21/sort.clinc b/resources/tests/game-referee-after-cl21/sort.clinc new file mode 100644 index 000000000..a9afed46a --- /dev/null +++ b/resources/tests/game-referee-after-cl21/sort.clinc @@ -0,0 +1,44 @@ + +( + (defun split_inner (@ everything (rest aggl aggr)) + (if rest + (split_inner (r rest) aggr (c (f rest) aggl)) + (r everything) + ) + ) + (defun split (mylist) + (split_inner mylist 0 0) + ) + (defun merge_inner (myless A B agg) + ; this should use continued if + (if (not A) + (prepend (reverse agg) B) + (if (not B) + (prepend (reverse agg) A) + (if (a myless (list (f A) (f B))) + (merge_inner myless (r A) B (c (f A) agg)) + (merge_inner myless A (r B) (c (f B) agg)) + ) + ) + ) + ) + (defun merge (myless a b) + (merge_inner myless a b 0) + ) + (defun sort-split (myless (a b)) + (merge myless (sort myless a) (sort myless b)) + ) + (defun sort (myless mylist) + (if mylist + (if (r mylist) + (assign (a b) (split mylist) + sa (sort myless a) + sb (sort myless b) + (merge myless sa sb) + ) + mylist + ) + () + ) + ) +) diff --git a/resources/tests/game-referee-after-cl21/spacehandcalc.clinc b/resources/tests/game-referee-after-cl21/spacehandcalc.clinc new file mode 100644 index 000000000..3bfae65ca --- /dev/null +++ b/resources/tests/game-referee-after-cl21/spacehandcalc.clinc @@ -0,0 +1,104 @@ + +; ranks are 1-13 with 1 being two, 12 being king, and 13 being ace +; there are no suits, flushes, or ace-to-four straights +; takes a list of card ranks and returns the value of the best poker +; hand which can be made with them +; returned list is hand type followed by cards in descending order +; all sorting is done highest to lowest +( + (include *standard-cl-22*) + (include sort.clinc) + (include deep_compare.clinc) + (include filtermap.clinc) + (include slice.clinc) + (include max.clinc) + (defconstant FIVE_OF_A_KIND 10) + (defconstant STRAIGHT_FLUSH 9) + (defconstant FOUR_OF_A_KIND 8) + (defconstant FULL_HOUSE 7) + (defconstant FLUSH 6) + (defconstant STRAIGHT 5) + (defconstant THREE_OF_A_KIND 4) + (defconstant TWO_PAIR 3) + (defconstant PAIR 2) + (defconstant HIGH_CARD 1) + (defun straight_high_inner (ranks last count) + (if (not ranks) + ; at the end of the list + 0 + (if (= last (f ranks)) + ; skip identical cards + (straight_high_inner (r ranks) started_ace last count) + ; if the partial straight continues + (if (= (f ranks) (- last 1)) + (if (= count 4) + ; found a straight, add 3 to last because next and last are included + (+ last 3) + ; keep looking for a straight with the count going up by one + (straight_high_inner (r ranks) started_ace (f ranks) (+ count 1)) + ) + ; reset the count + (straight_high_inner (r ranks) started_ace (f ranks) 1) + ) + ) + ) + ) + ; returns the high card of a straight or 0 if there isn't any + ; ranks must be sorted in descending order + (defun straight_high (ranks) + (straight_high_inner (ranks (= (f ranks) 13) 0 0)) + ) + (defun group_by_count_inner (items last count) + (if (not items) + 0 + (if (= (f items) last) + (group_by_count_inner (r items) last (+ count 1)) + (assign val (group_by_count_inner (r items) (f items) 1) + (if last + (c (c count last) val) + val + ) + ) + ) + ) + ) + (defun group_by_count (items) + (group_by_count_inner items 0 0) + ) + (defun space_hand_calc (cards) + (assign + rest (lambda (x) (r x)) + greater (lambda (x y) (> x y)) + ranks (sort greater cards) + sh (straight_high ranks) + max_straight (if sh + (list STRAIGHT sh) + 0 + ) + groups (sort deep> (group_by_count ranks)) + (top_count . top_card) (f groups) + (second_count . second_card) (f (r groups)) + topcards (map rest groups) + max_group (if (= top_count 1) + (c HIGH_CARD (slice topcards 5)) + (if (= top_count 2) + (if (= second_count 1) + (c PAIR (slice topcards 4)) + (c TWO_PAIR (slice topcards 3)) + ) + (if (= top_count 3) + (if (= second_count 1) + (c THREE_OF_A_KIND (slice topcards 3)) + (c FULL_HOUSE (slice topcards 2)) + ) + (if (= top_count 4) + (c FOUR_OF_A_KIND (slice topcards 2)) + (c FIVE_OF_A_KIND (slice topcards 1)) + ) + ) + ) + ) + (max deep< (list max_straight max_group)) + ) + ) +) diff --git a/resources/tests/game-referee-after-cl21/test_handcalc.clsp b/resources/tests/game-referee-after-cl21/test_handcalc.clsp new file mode 100644 index 000000000..16c46f664 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_handcalc.clsp @@ -0,0 +1,379 @@ + +(mod () + (include *standard-cl-21*) + (include deep_compare.clinc) + (include assert.clinc) + (include reverse.clinc) + (include prepend.clinc) + (include map.clinc) + (include filtermap.clinc) + (include slice.clinc) + (include print.clinc) + (include sort.clinc) + (include max.clinc) + (include handcalc.clinc) + + (defun runtests_inner ((myfunc firstarg secondarg . remaining)) + (assign-lambda + firstval (handcalc firstarg) + secondval (handcalc secondarg) + (assert + (a myfunc (list firstval secondval)) + (deep= firstval (handcalc (reverse firstarg))) + (deep= secondval (handcalc (reverse secondarg))) + (if remaining + (runtests_inner remaining) + 0 + ) + ) + ) + ) + + (defun runtests tests (if tests (runtests_inner tests) ())) + + ;; Join these up when large application bug is fixed. + (runtests + ; all beats both emerge over and measure higher + ; straight flush with higher kicker ties + ; A1 K1 Q1 J1 T1 91 = A1 K1 Q1 J1 T1 81 + deep= + (list (c 12 1) (c 11 1) (c 14 1) (c 13 1) (c 10 1) (c 9 1)) + (list (c 12 1) (c 11 1) (c 14 1) (c 13 1) (c 10 1) (c 8 1)) + ; straight flushes of different suits tie + ; A1 K1 Q1 J1 T1 = A2 K2 Q2 J2 T2 + deep= + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 10 1)) + (list (c 14 2) (c 13 2) (c 12 2) (c 11 2) (c 10 2)) + ; higher straight flush beats lower straight flush + ; A1 K1 Q1 J1 T1 > 61 51 41 31 21 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 10 1)) + (list (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + ; A1 K1 Q1 J1 T1 91 = A1 K1 Q1 J1 T1 + deep= + (list (c 12 1) (c 11 1) (c 14 1) (c 13 1) (c 10 1) (c 9 1)) + (list (c 14 2) (c 11 2) (c 10 2) (c 13 2) (c 12 2)) + ; lower (2-6) straight flush beats ace to four straight flush + ; 61 51 41 31 21 > A2 52 42 32 22 + deep> + (list (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 14 2) (c 5 2) (c 4 2) (c 3 2) (c 2 2)) + ; A1 61 51 41 31 21 = 61 51 41 31 21 + deep= + (list (c 14 1) (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + ; ace to four straight flush with higher kicker ties + ; A2 52 42 32 22 61 = A1 51 41 31 21 71 + deep= + (list (c 14 2) (c 5 2) (c 4 2) (c 3 2) (c 2 2) (c 6 1)) + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1) (c 7 1)) + ; ace to four straight flushes of different suits tie + ; A1 51 41 31 21 = A2 52 42 32 22 + deep= + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 14 2) (c 5 2) (c 4 2) (c 3 2) (c 2 2)) + ; ace to four straight flush beats four of a kind + ; A1 51 41 31 21 > K1 K2 K3 K4 J1 + deep> + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 11 1)) + ; A1 A2 A3 A4 51 41 31 21 = A1 51 41 31 21 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + ; four of a kind with higher kicker wins + ; K1 K2 K3 K4 Q1 > K1 K2 K3 K4 J1 + deep> + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 12 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 11 1)) + ; K1 K2 K3 K4 T1 91 = K1 K2 K3 K4 T1 + deep= + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 10 1) (c 9 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 10 1)) + ; four of a kind with higher second kicker ties + ; K1 K2 K3 K4 Q1 J1 = K1 K2 K3 K4 Q1 T1 + deep= + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 12 1) (c 11 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 12 1) (c 10 1)) + ; higher four of a kind beats lower four of a kind + ; K1 K2 K3 K4 21 > 31 32 33 34 A1 + deep> + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 2 1)) + (list (c 3 1) (c 3 2) (c 3 3) (c 3 4) (c 14 1)) + ; K1 K2 K3 K4 31 32 33 34 = K1 K2 K3 K4 32 + deep= + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 3 1) (c 3 2) (c 3 3) (c 3 4)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 3 2)) + ; four of a kind beats full house + ; 21 22 23 24 31 > A1 A2 A3 K1 K2 + deep> + (list (c 2 1) (c 2 2) (c 2 3) (c 2 4) (c 3 1)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2)) + ; 21 22 23 24 A1 A2 A3 = 21 22 23 24 A2 + deep= + (list (c 2 1) (c 2 2) (c 2 3) (c 2 4) (c 14 1) (c 14 2) (c 14 3)) + (list (c 2 1) (c 2 2) (c 2 3) (c 2 4) (c 14 2)) + ; full house with higher set wins + ; 51 52 53 21 22 > 31 32 33 71 72 + deep> + (list (c 5 1) (c 5 2) (c 5 3) (c 2 1) (c 2 2)) + (list (c 3 1) (c 3 2) (c 3 3) (c 7 1) (c 7 2)) + ; A1 A2 A3 K1 K2 K3 = A1 A2 A3 K1 K2 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2) (c 13 3)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2)) + ; full house with same set and higher pair wins + ; 51 52 53 41 42 > 51 52 53 31 32 + deep> + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2)) + (list (c 5 1) (c 5 2) (c 5 3) (c 3 1) (c 3 2)) + ; A1 A2 A3 K1 K2 51 52 = A1 A2 A3 K1 K2 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2) (c 5 1) (c 5 2)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2)) + ; full house ties with two sets + ; 51 52 53 41 42 A1 = 51 52 53 41 42 43 + deep= + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2) (c 14 1)) + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2) (c 4 3)) + ; full house beats flush + ; 51 52 53 41 42 > A1 Q1 T1 81 71 + deep> + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2)) + (list (c 14 1) (c 12 1) (c 10 1) (c 8 1) (c 7 1)) + ; 51 52 53 41 42 A1 K1 Q1 = 51 52 53 41 42 + deep= + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2) (c 14 1) (c 13 1) (c 12 1)) + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2)) + ; higher flush beats lower flush + ; A1 61 51 41 31 > K1 Q1 J1 T1 81 + deep> + (list (c 14 1) (c 6 1) (c 5 1) (c 4 1) (c 3 1)) + (list (c 13 1) (c 12 2) (c 11 1) (c 10 1) (c 8 1)) + ; A1 K1 Q1 J1 81 71 = A1 K1 Q1 J1 81 + deep= + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 8 1) (c 7 1)) + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 8 1)) + ; flush with higher second card wins + ; A1 K1 51 41 31 > A1 Q1 J1 T1 91 + deep> + (list (c 14 1) (c 13 1) (c 5 1) (c 4 1) (c 3 1)) + (list (c 14 1) (c 12 2) (c 11 1) (c 10 1) (c 9 1)) + ; flush with higher third card wins + ; A1 K1 Q1 41 31 > A1 K1 J1 T1 91 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 4 1) (c 3 1)) + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 9 1)) + ; flush with higher fourth card wins + ; A1 K1 Q1 T1 21 > A1 K1 Q1 91 81 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 10 1) (c 2 1)) + (list (c 14 1) (c 13 1) (c 12 1) (c 9 1) (c 8 1)) + ; flush with higher fifth card wins + ; A1 K1 Q1 T1 81 > A1 K1 Q1 T1 71 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 10 1) (c 8 1)) + (list (c 14 1) (c 13 1) (c 12 1) (c 10 1) (c 7 1)) + ; flushes of different suits tie + ; A1 K1 J1 T1 81 = A2 K2 J2 T2 82 + deep= + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 8 1)) + (list (c 14 2) (c 13 2) (c 11 2) (c 10 2) (c 8 2)) + ; same flush with higher sixth card ties + ; A1 K1 J1 T1 81 71 = A1 K1 J1 T1 81 61 + deep= + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 8 1) (c 7 1)) + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 8 1) (c 6 1)) + ; flush beats straight + ; 71 61 51 41 21 > A1 K2 Q3 J4 T1 + deep> + (list (c 7 1) (c 6 1) (c 5 1) (c 4 1) (c 2 1)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1)) + ; A1 K2 Q3 J4 T1 81 71 61 = A1 T1 81 71 61 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 8 1) (c 7 1) (c 6 1)) + (list (c 14 1) (c 10 1) (c 8 1) (c 7 1) (c 6 1)) + ; straight with higher kicker ties + ; A1 K2 Q3 J4 T1 92 = A1 K2 Q3 J4 T1 22 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 9 2)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 2 2)) + ; straights of different suits tie + ; A1 K2 Q3 J4 T1 = A2 K3 Q4 J1 T2 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1)) + (list (c 14 2) (c 13 3) (c 12 4) (c 11 1) (c 10 2)) + ; higher straight beats lower straight + ; A1 K2 Q3 J4 T1 > 61 52 43 34 21 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1)) + (list (c 6 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + ; A1 K2 Q3 J4 T1 92 83 = A1 K2 Q3 J4 T1 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 9 2) (c 8 3)) + (list (c 14 2) (c 13 3) (c 12 4) (c 11 1) (c 10 2)) + ; lower (2-6) straight beats ace to four straight + ; 61 52 43 34 21 > A1 52 43 34 21 + deep> + (list (c 6 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + ; A1 62 53 44 31 22 = 62 53 44 31 22 + deep= + (list (c 14 1) (c 6 2) (c 5 3) (c 4 4) (c 3 1) (c 2 2)) + (list (c 6 2) (c 5 3) (c 4 4) (c 3 1) (c 2 2)) + ; ace to four straight with higher kicker ties + ; A1 52 43 34 21 K2 = A1 52 43 34 21 72 + deep= + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1) (c 13 2)) + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1) (c 7 2)) + ; ace to fours of different suits tie + ; A1 52 43 34 21 = A2 53 44 31 22 + deep= + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 2) (c 5 3) (c 4 4) (c 3 1) (c 2 2)) + ; ace to four straight beats set + ; A1 52 43 34 21 > A1 A2 A3 K1 Q2 + deep> + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 12 2)) + ; A1 A2 A3 52 43 34 21 = A1 52 43 34 21 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 5 2) (c 4 3) (c 3 2) (c 2 1)) + ; higher set wins + ; 71 72 73 34 21 > 51 52 53 A4 K1 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 3 4) (c 2 1)) + (list (c 5 1) (c 5 2) (c 5 3) (c 14 4) (c 13 1)) + ; set with higher first kicker wins + ; 71 72 73 A1 22 > 71 72 73 K1 Q2 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 2 2)) + (list (c 7 1) (c 7 2) (c 7 3) (c 13 1) (c 12 2)) + ; 71 72 73 A1 K2 J3 54 43 = 71 72 73 A1 K2 + deep= + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2) (c 11 3) (c 5 4) (c 4 3)) + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2)) + ; set with higher second kicker wins + ; 71 72 73 A1 K2 > 71 72 73 A1 Q2 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2)) + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 12 2)) + ; set with higher third kicker ties + ; 71 72 73 A1 K2 Q3 = 71 72 73 A1 K2 J3 + deep= + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2) (c 12 3)) + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2) (c 11 3)) + ; set beats two pair + ; 71 72 73 34 21 > A1 A2 K3 K4 Q1 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 14 2) (c 13 3) (c 13 4) (c 12 1)) + ; two pair with higher high pair wins + ; K1 K2 33 34 21 > Q1 Q2 J3 J4 A1 + deep> + (list (c 13 1) (c 13 2) (c 3 3) (c 3 4) (c 2 1)) + (list (c 12 1) (c 12 2) (c 11 3) (c 11 4) (c 14 1)) + ; A1 A2 K1 K2 J1 J2 = A1 A2 K1 K2 J3 + deep= + (list (c 14 1) (c 14 2) (c 13 1) (c 13 2) (c 11 1) (c 11 2)) + (list (c 14 1) (c 14 2) (c 13 1) (c 13 2) (c 11 3)) + ; two pair with tied higher pair and higher lower pair wins + ; K1 K2 71 72 23 > K1 K2 63 64 A1 + deep> + (list (c 13 1) (c 13 2) (c 7 1) (c 7 2) (c 2 3)) + (list (c 13 1) (c 13 2) (c 6 3) (c 6 4) (c 14 1)) + ; two pair with higher kicker wins + ; K1 K2 Q3 Q4 J1 > K1 K2 Q3 Q4 T1 + deep> + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 11 1)) + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 10 1)) + ; K1 K2 Q3 Q4 A1 T1 92 63 = K1 K2 Q3 Q4 A1 + deep= + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 14 1) (c 10 1) (c 9 2) (c 6 3)) + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 14 1)) + ; two pair with higher second kicker ties + ; K1 K2 Q3 Q4 J1 T2 = K1 K2 Q3 Q4 J1 92 + deep= + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 11 1) (c 10 2)) + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 11 1) (c 9 2)) + ; two pair beats pair + ; 41 42 33 34 21 > A1 A2 K3 Q4 J1 + deep> + (list (c 4 1) (c 4 2) (c 3 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 14 2) (c 13 3) (c 12 4) (c 11 1)) + ; higher pair wins + ; 71 72 53 44 31 > 61 62 A3 K4 Q1 + deep> + (list (c 7 1) (c 7 2) (c 5 3) (c 4 4) (c 3 1)) + (list (c 6 1) (c 6 2) (c 14 3) (c 13 4) (c 12 1)) + ; tied pair with higher first kicker wins + ; 91 92 A3 34 21 > 91 92 K3 Q4 J1 + deep> + (list (c 9 1) (c 9 2) (c 14 3) (c 3 4) (c 2 1)) + (list (c 9 1) (c 9 2) (c 13 3) (c 12 4) (c 11 1)) + ; 21 22 A1 Q2 J3 94 81 = 21 22 A1 Q2 J3 + deep= + (list (c 2 1) (c 2 2) (c 14 1) (c 12 2) (c 11 3) (c 9 4) (c 8 1)) + (list (c 2 1) (c 2 2) (c 14 1) (c 12 2) (c 11 3)) + ; tied pair with higher second kicker wins + ; 91 92 A3 K4 21 > 91 92 A3 Q4 J1 + deep> + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 2 1)) + (list (c 9 1) (c 9 2) (c 14 3) (c 12 4) (c 11 1)) + ; tied pair with higher third kicker wins + ; 91 92 A3 K4 Q1 > 91 92 A3 K4 J1 + deep> + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 12 1)) + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 11 1)) + ; tied pair with higher fourth kicker ties + ; 91 92 A3 K4 Q1 J2 = 91 92 A3 K4 Q1 T2 + deep= + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 12 1) (c 11 2)) + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 12 1) (c 10 2)) + ; pair beats high card + ; 21 22 33 44 51 > A1 Q2 J3 T4 91 + deep> + (list (c 2 1) (c 2 2) (c 3 3) (c 4 4) (c 5 1)) + (list (c 14 1) (c 12 2) (c 11 3) (c 10 4) (c 9 1)) + ; higher high card wins + ; A1 22 33 44 61 > K1 Q2 J3 T4 81 + deep> + (list (c 14 1) (c 2 2) (c 3 3) (c 4 4) (c 6 1)) + (list (c 13 1) (c 12 2) (c 11 3) (c 10 4) (c 8 1)) + ; A1 K2 J3 T4 81 72 53 = A1 K2 J3 T4 81 + deep= + (list (c 14 1) (c 13 2) (c 11 3) (c 10 4) (c 8 1) (c 7 2) (c 5 3)) + (list (c 14 1) (c 13 2) (c 11 3) (c 10 4) (c 8 1)) + ; higher second card wins + ; A1 K2 23 34 41 > A1 Q2 J3 T4 91 + deep> + (list (c 14 1) (c 13 2) (c 2 3) (c 3 4) (c 4 1)) + (list (c 14 1) (c 12 2) (c 11 3) (c 10 4) (c 9 1)) + ; higher third card wins + ; A1 K2 Q3 24 41 > A1 K2 J3 T4 91 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 2 4) (c 4 1)) + (list (c 14 1) (c 13 2) (c 11 3) (c 10 4) (c 9 1)) + ; higher fourth card wins + ; A1 K2 Q3 J4 31 > A1 K2 Q3 T4 91 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 3 1)) + (list (c 14 1) (c 13 2) (c 12 3) (c 10 4) (c 9 1)) + ; higher fifth card wins + ; A1 K2 Q3 J4 91 > A1 K2 Q3 J4 81 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 8 1)) + ; higher sixth card ties + ; A1 K2 Q3 J4 91 22 = A1 K2 Q3 J4 91 82 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1) (c 2 2)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1) (c 8 2)) + ; high cards of different suits ties + ; A1 K2 Q3 J4 91 = A2 K3 Q4 J1 92 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1)) + (list (c 14 2) (c 13 3) (c 12 4) (c 11 1) (c 9 2)) + ) +) diff --git a/resources/tests/game-referee-after-cl21/test_handcalc.clvm.hex b/resources/tests/game-referee-after-cl21/test_handcalc.clvm.hex new file mode 100644 index 000000000..8a8aedd7f --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_handcalc.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff8200feffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010180ffff0180808080808080ffff04ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010280ffff04ffff04ffff010affff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010180ffff0180808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff010bffff010280ffff04ffff04ffff010affff010280ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010280ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0102ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff0180808080808080ffff04ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010280ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0102ffff010280ffff04ffff04ffff0106ffff010180ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0107ffff010180ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010280ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0102ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff018080808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff01808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010180ffff0180808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff0180808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff04ffff04ffff010affff010180ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff010effff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0103ffff010480ffff01808080808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff0103ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff0102ffff010380ffff04ffff04ffff0102ffff010480ffff04ffff04ffff0103ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff0102ffff010380ffff04ffff04ffff0102ffff010480ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff018080808080808080ffff04ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff0102ffff010380ffff04ffff04ffff0102ffff010480ffff04ffff04ffff010effff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff01808080808080ffff04ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff01808080808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0103ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff018080808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff04ffff04ffff010effff010180ffff0180808080808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff04ffff04ffff0104ffff010380ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0107ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff01808080808080808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff01808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0107ffff010180ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0107ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010280ffff04ffff04ffff010affff010280ffff04ffff04ffff0108ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0107ffff010180ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0106ffff010180ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0106ffff010180ffff01808080808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0106ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010280ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff04ffff04ffff0102ffff010280ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff0108ffff010380ffff018080808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0106ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010480ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010280ffff0180808080808080ffff04ffff04ffff04ffff0106ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010480ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff04ffff04ffff010dffff010280ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0107ffff010280ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010480ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff018080808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff010effff010480ffff04ffff04ffff010dffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff0102ffff010280ffff01808080808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff0105ffff010480ffff04ffff04ffff0104ffff010380ffff01808080808080808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff01808080808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff0180808080808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010380ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010cffff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010effff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010180ffff04ffff04ffff010bffff010280ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010380ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0102ffff010380ffff01808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff0106ffff010380ffff04ffff04ffff0106ffff010480ffff04ffff04ffff010effff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010effff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff0106ffff010380ffff01808080808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010effff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010280ffff0180808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff04ffff04ffff0109ffff010280ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010480ffff04ffff04ffff0103ffff010180ffff01808080808080ffff04ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0106ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff0109ffff010480ffff04ffff04ffff0108ffff010180ffff018080808080808080ffff04ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010380ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff01808080808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010280ffff0180808080808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff04ffff04ffff010affff010280ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0104ffff010480ffff04ffff04ffff0105ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0104ffff010480ffff04ffff04ffff0106ffff010180ffff01808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0105ffff010380ffff018080808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff0102ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0104ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff0102ffff010480ffff04ffff04ffff0104ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff0103ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0102ffff010280ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0108ffff010280ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff04ffff04ffff0109ffff010280ffff01808080808080ff808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080ffff04ffff01ffffffffffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff02ff8200a0ffff04ff02ffff04ffff06ff0180ffff04ffff02ff40ffff04ff02ffff04ffff05ff0580ffff04ffff05ff0b80ff8080808080ff8080808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff0181ffff0180ffff01ff02ffff01ff02ffff03ffff15ff05ff0b80ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff11ffff0180ffff15ff0bff058080ff018080ff0180ff018080ff0180ff018080ff0180ffff02ffff03ff0bffff01ff02ffff010bff0180ffff01ff02ffff01ff02ff40ffff04ff02ffff04ffff06ff0980ffff04ffff06ff1580ff8080808080ff018080ff0180ff09ffff02ff40ffff04ff02ffff04ff05ffff04ff0bff8080808080ffff0181ff80ffff09ffff02ff40ffff04ff02ffff04ff05ffff04ff0bff8080808080ffff010180ffff09ffff02ff40ffff04ff02ffff04ff05ffff04ff0bff8080808080ff8080ff02ffff03ff0bffff01ff02ffff01ff02ff8200f0ffff04ff02ffff04ffff04ffff05ff0b80ff0580ffff04ffff06ff0b80ff8080808080ff0180ffff01ff02ffff0105ff018080ff0180ffffff02ff8200f0ffff04ff02ffff04ff80ffff04ff05ff8080808080ffff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff8200a8ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff02ffff03ff0bffff01ff02ffff01ff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff02ff8200e8ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff80808080808080ff0180ffff01ff02ffff0117ff018080ff0180ffff02ffff03ff0bffff01ff02ffff01ff02ff8200b8ffff04ff02ffff04ffff06ff0180ffff04ffff02ff05ffff04ffff05ff0b80ffff01808080ff8080808080ff0180ffff01ff02ffff0117ff018080ff0180ffff02ffff03ff0bffff01ff02ffff01ff04ff0bffff02ff58ffff04ff02ffff04ff09ffff04ffff06ff1580ffff04ff2dff80808080808080ff0180ffff01ff02ffff01ff02ff58ffff04ff02ffff04ff09ffff04ffff06ff1580ffff04ff2dff808080808080ff018080ff0180ff02ffff03ffff02ff44ffff04ff02ffff04ffff04ffff018c736c69636520696e70757473ffff04ffff01866e796c697374ffff04ff0bff80808080ffff04ffff20ff0b80ff8080808080ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff04ffff05ff0580ffff02ff8200f8ffff04ff02ffff04ffff06ff0580ffff04ffff11ff0bffff010180ff808080808080ff018080ff0180ffffffff02ffff03ffff22ffff0187247072696e7424ff05ff0b80ffff01ff02ffff010bff0180ffff01ff02ffff010bff018080ff0180ffff02ffff03ff05ffff01ff02ffff01ff02ff8200a4ffff04ff02ffff04ffff06ff0580ffff04ff17ffff04ffff04ffff05ff0580ff0b80ff808080808080ff0180ffff01ff02ffff01ff06ff0380ff018080ff0180ff02ff8200a4ffff04ff02ffff04ff05ffff01ff80ff8080808080ffff02ffff03ffff20ff0b80ffff01ff02ffff01ff02ff8200a8ffff04ff02ffff04ffff02ff48ffff04ff02ffff04ff2fff80808080ffff04ff17ff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff20ff1780ffff01ff02ffff01ff02ff8200a8ffff04ff02ffff04ffff02ff48ffff04ff02ffff04ff2fff80808080ffff04ff0bff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff02ff05ffff04ffff05ff0b80ffff04ffff05ff1780ffff0180808080ffff01ff02ffff01ff02ff54ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ffff04ffff04ffff05ff0b80ff2f80ff80808080808080ff0180ffff01ff02ffff01ff02ff54ffff04ff02ffff04ff05ffff04ff0bffff04ffff06ff1780ffff04ffff04ffff05ff1780ff2f80ff80808080808080ff018080ff0180ff018080ff0180ff018080ff0180ffff02ff54ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff01ff80808080808080ff02ffff03ff0bffff01ff02ffff01ff02ffff03ffff06ff0b80ffff01ff02ffff01ff02ff4cffff04ff02ffff04ffff06ff0180ffff04ffff02ff8200e4ffff04ff02ffff04ff0bff80808080ff8080808080ff0180ffff01ff02ffff010bff018080ff0180ff0180ffff01ff02ffff01ff0180ff018080ff0180ffffff02ff8200acffff04ff02ffff04ff03ffff04ffff02ff8200f4ffff04ff02ffff04ff09ffff04ff13ff8080808080ffff04ffff02ff8200f4ffff04ff02ffff04ff09ffff04ff2bff8080808080ff808080808080ffff02ff8200b4ffff04ff02ffff04ff11ffff04ff0bffff04ff17ff808080808080ff02ffff03ffff20ff1780ffff01ff02ffff010bff0180ffff01ff02ffff01ff02ffff03ffff02ff05ffff04ff0bffff04ffff05ff1780ffff0180808080ffff01ff02ffff01ff02ff8200ecffff04ff02ffff04ff05ffff04ffff05ff1780ffff04ffff06ff1780ff808080808080ff0180ffff01ff02ffff01ff02ff8200ecffff04ff02ffff04ff05ffff04ff0bffff04ffff06ff1780ff808080808080ff018080ff0180ff018080ff0180ffff02ff8200ecffff04ff02ffff04ff05ffff04ff13ffff04ff1bff808080808080ffff02ffff03ffff20ff0580ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff02ffff03ffff09ffff05ff0580ff0b80ffff01ff02ffff01ff02ffff03ffff09ff17ffff010480ffff01ff02ffff010bff0180ffff01ff02ffff01ff02ff8200bcffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ffff10ff17ffff010180ff808080808080ff018080ff0180ff0180ffff01ff02ffff01ff02ff8200bcffff04ff02ffff04ffff06ff0580ffff04ffff05ff0580ffff04ffff0101ff808080808080ff018080ff0180ff018080ff0180ff02ff8200bcffff04ff02ffff04ffff02ff8200f4ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff4280ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ffff04ff05ff8080808080ffff01ff80ff8080808080ffffffffff02ff50ffff04ff02ffff04ff0bffff04ff17ff8080808080ffff02ffff03ffff20ff0580ffff01ff02ffff01ff02ffff03ffff18ffff09ff17ffff010280ffff09ff2fffff010480ff0b80ffff01ff02ffff01ff0105ff0180ffff01ff02ffff01ff0180ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff09ff17ffff05ff058080ffff01ff02ffff01ff02ff8200a2ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fff80808080808080ff0180ffff01ff02ffff01ff02ffff03ffff09ffff05ff0580ffff11ff17ffff01018080ffff01ff02ffff01ff02ffff03ffff09ff2fffff010480ffff01ff02ffff01ff10ff17ffff010380ff0180ffff01ff02ffff01ff02ff8200a2ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ffff05ff0580ffff04ffff10ff2fffff010180ff80808080808080ff018080ff0180ff0180ffff01ff02ffff01ff02ff8200a2ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ffff05ff0580ffff04ffff0101ff80808080808080ff018080ff0180ff018080ff0180ff018080ff0180ff02ff8200a2ffff04ff02ffff04ff05ffff04ffff09ff09ffff010e80ffff01ff80ff808080808080ffff02ffff03ffff20ff0580ffff01ff02ffff01ff04ffff04ff17ff0b80ffff018080ff0180ffff01ff02ffff01ff02ffff03ffff09ffff05ff0580ff0b80ffff01ff02ffff01ff02ff52ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ffff10ff17ffff010180ff808080808080ff0180ffff01ff02ffff01ff02ff8200b2ffff04ff02ffff04ffff06ff0180ffff04ffff02ff52ffff04ff02ffff04ffff06ff0580ffff04ffff05ff0580ffff04ffff0101ff808080808080ff8080808080ff018080ff0180ff018080ff0180ffff04ffff04ff2dff1580ff0b80ff02ff52ffff04ff02ffff04ff05ffff04ff09ffff01ff808080808080ffffff02ff5affff04ff02ffff04ff03ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200aa80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200ea80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ff808080808080ff1b13ffff02ff8200faffff04ff02ffff04ff03ffff04ffff02ff8200f4ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200ba80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ffff04ffff02ff8200e8ffff04ff02ffff04ff17ffff04ff09ffff01ff808080808080ff8080808080ffff04ffff02ff8200fcffff04ff02ffff04ffff02ff8200e8ffff04ff02ffff04ff0bffff04ff09ffff01ff808080808080ff80808080ff808080808080ffff02ff50ffff04ff02ffff04ff0bffff04ff17ff8080808080ff02ff8200f6ffff04ff02ffff04ff03ffff04ffff02ff8200f4ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff4680ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ffff04ffff02ff8200f2ffff04ff02ffff04ff0bff80808080ff8080808080ffff04ffff02ff8200e2ffff04ff02ffff04ff0bff80808080ffff04ffff02ffff03ffff20ff1780ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff02ff56ffff04ff02ffff04ffff06ff0180ffff04ffff02ff8200f4ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200a680ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ffff02ff58ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200e680ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff17ffff01808080ffff04ffff0101ffff0180808080ffff0180808080ffff04ff11ffff04ffff0180ff808080808080ff8080808080ff8080808080ff018080ff0180ff80808080808080ffffffff02ff50ffff04ff02ffff04ff0bffff04ff17ff8080808080ffff02ff50ffff04ff02ffff04ff0bffff04ff17ff8080808080ff02ffff03ffff09ff09ff1b80ffff01ff02ffff0113ff0180ffff01ff02ffff01ff0180ff018080ff0180ffff02ff8200b6ffff04ff02ffff04ff03ffff04ffff02ff8200e2ffff04ff02ffff04ff0bff80808080ff8080808080ffff02ffff03ff0bffff01ff02ffff01ff04ffff0109ffff04ff0bffff01808080ff0180ffff01ff02ffff01ff04ffff0106ffff02ff8200f8ffff04ff02ffff04ff15ffff04ffff0105ff808080808080ff018080ff0180ff02ff4effff04ff02ffff04ff03ffff04ffff02ffff03ff17ffff01ff02ffff01ff04ffff0105ffff04ff17ffff01808080ff0180ffff01ff02ffff01ff0180ff018080ff0180ffff04ff2bffff04ff13ffff04ffff02ff8200e8ffff04ff02ffff04ff29ffff04ff0bffff01ff808080808080ff8080808080808080ffffff02ff8200aeffff04ff02ffff04ff03ffff04ffff02ffff03ffff09ff4fffff010180ffff01ff02ffff01ff04ffff0101ffff02ff8200f8ffff04ff02ffff04ff5fffff04ffff0105ff808080808080ff0180ffff01ff02ffff01ff02ffff03ffff09ff4fffff010280ffff01ff02ffff01ff02ffff03ffff09ff27ffff010180ffff01ff02ffff01ff04ffff0102ffff02ff8200f8ffff04ff02ffff04ff5fffff04ffff0104ff808080808080ff0180ffff01ff02ffff01ff04ffff0103ffff02ff8200f8ffff04ff02ffff04ff5fffff04ffff0103ff808080808080ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff09ff4fffff010380ffff01ff02ffff01ff02ffff03ffff09ff27ffff010180ffff01ff02ffff01ff04ffff0104ffff02ff8200f8ffff04ff02ffff04ff5fffff04ffff0103ff808080808080ff0180ffff01ff02ffff01ff04ffff0107ffff02ff8200f8ffff04ff02ffff04ff5fffff04ffff0102ff808080808080ff018080ff0180ff0180ffff01ff02ffff01ff04ffff0108ffff02ff8200f8ffff04ff02ffff04ff5fffff04ffff0102ff808080808080ff018080ff0180ff018080ff0180ff018080ff0180ff8080808080ffff02ff5cffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200ee80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ffff04ffff04ff8200b9ffff04ff15ffff04ff0bff80808080ff8080808080ff02ff8200e0ffff04ff02ffff04ff0bffff04ff17ff8080808080ffff02ff8200beffff04ff02ffff04ff03ffff04ffff02ff4affff04ff02ffff04ff2dff80808080ffff04ffff02ff4affff04ff02ffff04ff15ff80808080ff808080808080ffff02ffff03ffff02ff11ffff04ff17ffff04ff0bff80808080ffff01ff02ffff01ff02ffff03ffff02ff8200b0ffff04ff02ffff04ff17ffff04ffff02ff4affff04ff02ffff04ffff02ff48ffff04ff02ffff04ff29ff80808080ff80808080ff8080808080ffff01ff02ffff01ff02ffff03ffff02ff8200b0ffff04ff02ffff04ff0bffff04ffff02ff4affff04ff02ffff04ffff02ff48ffff04ff02ffff04ff59ff80808080ff80808080ff8080808080ffff01ff02ffff01ff02ffff03ff79ffff01ff02ffff01ff02ff5effff04ff02ffff04ff79ff80808080ff0180ffff01ff02ffff01ff0180ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff02ffff03ff03ffff01ff02ffff01ff02ff5effff04ff02ffff04ff03ff80808080ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080 diff --git a/resources/tests/game-referee-after-cl21/test_handcalc.sym b/resources/tests/game-referee-after-cl21/test_handcalc.sym new file mode 100644 index 000000000..082402ad3 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_handcalc.sym @@ -0,0 +1 @@ +{"ca3aa00f92cd656fbf2e7c7863a2bd3ebfcdf0bdb05ca8f00ce9d51648d38b1f_left_env": "1", "79f3cf5c572162105f8688174041050314a154956ef27d7ea6414a9dcd402faa_arguments": "(items)", "4b216afca35845442571c30c6d827724285ca82490dbdae1b27f2d082e85ff66_arguments": "tests", "source_file": "/home/arty/dev/chia/clvm_tools_rs/resources/tests/game-referee-after-cl21/test_handcalc.clsp", "0dda9e9f845e653fbb9f1065f098a0c439bf605b2e8830546184c95eae822f25_left_env": "1", "a87d2e2e13539c8f9f66137bdee9a7fd750b8bdb6a07fc1e6cd8416d771d9958_left_env": "1", "cbfdd91c91e2fc43ef49a82e173f49c6cc73a6a022b1378b885ff9ea94f373b0_arguments": "(((((cards_$_1747) rest_$_1750 first_$_1748) nosuits_$_1753 fsuit_$_1752) groups_$_1764 sh_$_1763 max_flush_$_1756) max_straight_$_1767 (second_count_$_1770 . second_card_$_1771) (top_count_$_1768 . top_card_$_1769) topcards_$_1772)", "d3a1931b023b08bc00d8335c069b7d488fa1930ee6c312dcf11cb54a6d5761b1_arguments": "((myfunc firstarg secondarg . remaining))", "5c2c8bfc9ac6c103562c9017a5cee2634da7ee43d44bd4f3d46d11e519942ea6": "straight_high", "ff5f6181808cb059cffecd54a408a6b4566b861a8905208bbeb87a10e3c8ec65_arguments": "(myless a b)", "3ac370c3d91282c6eb94742d40cdb371de392eaca8a0a213d3d3ade6d1b03367": "deep_compare", "ff5f6181808cb059cffecd54a408a6b4566b861a8905208bbeb87a10e3c8ec65": "merge", "d8c50d6282a1ba47f0a23430d177bbfbb72e2b84713745e894f575570f1f3d6e": "lambda_$_1791", "f4c3c71dddb1c7ee50bc104032f26172d61ff77f9bca9876d1846c47cd72020e_left_env": "1", "01ed928ebc640669bfdc000b292962b919f6635176dd9119325f5f912d7567b8_arguments": "(() x_$_1774 y_$_1775)", "68a51341b984c77341ffa8fd755e2b80544914c95cd78caf10312d7e818b48d9": "letbinding_$_1794", "145bfb83f7b3ef33ac1eada788c187e4d1feb7326bcf340bb060a62e75434854_left_env": "1", "c4e96a2219a3d6389693cfb81c4309f5bf5f1a89f300c7c12d019e08d14cde09_left_env": "1", "64499f3fb4ed1322a24ece83ce5664a10e41b8cb291c4c395d961004680802ca": "filtermap", "2df345b9e040f0cdefc0db6e59e9ea40894c26003d4bb35d4c0b88bfdc5d2d8f": "letbinding_$_1801", "e51e3ecc739e0c9b646889ad797fa268d9acbb09f42f70b1a75be411440dcf36_arguments": "((fsuit_$_1752) (card_rank_$_1760 . card_suit_$_1761))", "724d50ee95e66b90e255e2cecc58cc35c2eb27302b1952948538ad95f7387a4b_arguments": "(F L R)", "8afd8fa01ef33b8744033203c10bd0c52e1da692d02ff4094f7b42d5ef7ddd47": "letbinding_$_1803", "2379a74341919286585b51fa8ff2bf5a2e76254197c786fdcd96d4b004be17ba_arguments": "(a b)", "d121f71fcb5513b6d2b097255deb884ff40c26dd366b0ba7cf2eea1440b07901": "split", "24d45638962c8ac6b0923f0f2c912177b1b1c710bbcd3e10fccf01fc6f771263_arguments": "(myless mylist)", "76751a9c95444501c3ad57278f9ace3e6a1e41fca43bd93d6e5a8ca125e8c4a3": "letbinding_$_1786", "76751a9c95444501c3ad57278f9ace3e6a1e41fca43bd93d6e5a8ca125e8c4a3_left_env": "1", "ea58983a62a5d0a526c32f3423717af26c6d9d5963eb4831a0d1049227eba060_arguments": "(suits last count)", "f4c3c71dddb1c7ee50bc104032f26172d61ff77f9bca9876d1846c47cd72020e": "handcalc", "9d29b02858791632bc362c1460848641e331d92b120c8b18e241a6a7375b387e": "letbinding_$_1796", "64499f3fb4ed1322a24ece83ce5664a10e41b8cb291c4c395d961004680802ca_arguments": "(process remaining init)", "2df345b9e040f0cdefc0db6e59e9ea40894c26003d4bb35d4c0b88bfdc5d2d8f_left_env": "1", "c64dc59aae25053fe8d872e13fca4e2c43765a1a83335d520435180f3ab55485_left_env": "1", "c64b0acdb9bfc5a1bec80732d64bee90fd12e869207674a220042725441f9cb3": "find_flush", "d8c50d6282a1ba47f0a23430d177bbfbb72e2b84713745e894f575570f1f3d6e_left_env": "1", "5c2c8bfc9ac6c103562c9017a5cee2634da7ee43d44bd4f3d46d11e519942ea6_arguments": "(ranks)", "79f3cf5c572162105f8688174041050314a154956ef27d7ea6414a9dcd402faa_left_env": "1", "ea58983a62a5d0a526c32f3423717af26c6d9d5963eb4831a0d1049227eba060": "find_flush_inner", "d013fcaaa576d263aa86406509a11272424931651d958cff6ba9be6d2b9a7fed_arguments": "(items last count)", "cbfdd91c91e2fc43ef49a82e173f49c6cc73a6a022b1378b885ff9ea94f373b0_left_env": "1", "76751a9c95444501c3ad57278f9ace3e6a1e41fca43bd93d6e5a8ca125e8c4a3_arguments": "(((myless_$_1720 mylist_$_1721) (a_$_1722 b_$_1723)) sa_$_1724 sb_$_1725)", "d013fcaaa576d263aa86406509a11272424931651d958cff6ba9be6d2b9a7fed_left_env": "1", "01ed928ebc640669bfdc000b292962b919f6635176dd9119325f5f912d7567b8": "lambda_$_1802", "c64dc59aae25053fe8d872e13fca4e2c43765a1a83335d520435180f3ab55485": "merge_inner", "145bfb83f7b3ef33ac1eada788c187e4d1feb7326bcf340bb060a62e75434854": "lambda_$_1790", "d121f71fcb5513b6d2b097255deb884ff40c26dd366b0ba7cf2eea1440b07901_left_env": "1", "ff5f6181808cb059cffecd54a408a6b4566b861a8905208bbeb87a10e3c8ec65_left_env": "1", "24d45638962c8ac6b0923f0f2c912177b1b1c710bbcd3e10fccf01fc6f771263_left_env": "1", "d013fcaaa576d263aa86406509a11272424931651d958cff6ba9be6d2b9a7fed": "group_by_count_inner", "7245d12b7785f1ee23a0ec0d3a03432057ec41fb0561d373d91cda267f44c3e9": "reverse", "e51e3ecc739e0c9b646889ad797fa268d9acbb09f42f70b1a75be411440dcf36": "lambda_$_1798", "d8c50d6282a1ba47f0a23430d177bbfbb72e2b84713745e894f575570f1f3d6e_arguments": "(() x_$_1749)", "64499f3fb4ed1322a24ece83ce5664a10e41b8cb291c4c395d961004680802ca_left_env": "1", "145bfb83f7b3ef33ac1eada788c187e4d1feb7326bcf340bb060a62e75434854_arguments": "(() x_$_1751)", "471488bbd4b64848f0c6592900ef2a751e8907a72557b0ba794e0d6f1252c374_left_env": "1", "00c86eab1caeadaaf967420becbefef7170e5e996890edc355d16c263ea32e27_arguments": "(myless best_so_far mylist)", "c64b0acdb9bfc5a1bec80732d64bee90fd12e869207674a220042725441f9cb3_left_env": "1", "ca3aa00f92cd656fbf2e7c7863a2bd3ebfcdf0bdb05ca8f00ce9d51648d38b1f_arguments": "(a b)", "c60f4e2e12ab7285ef437f63bb24f4e5e6267fc76479893a179ebae738aca004_left_env": "1", "042c55b626937b8d6be258a97f8d25cdedeee2e712dbddef9438fa900eff883e": "print", "36900466483b112787abffe419202a499c8e5467e750cf3aec03ac5fd0ba9cfd_left_env": "1", "26df51fddc60f80f199438e505e3832df819036418c8bf439a572679ebfd1897_arguments": "(@ everything (rest aggl aggr))", "ca3aa00f92cd656fbf2e7c7863a2bd3ebfcdf0bdb05ca8f00ce9d51648d38b1f": "deep=", "7245d12b7785f1ee23a0ec0d3a03432057ec41fb0561d373d91cda267f44c3e9_arguments": "(vals)", "c64b0acdb9bfc5a1bec80732d64bee90fd12e869207674a220042725441f9cb3_arguments": "(suits)", "8bda8ccb43702a3e1a1b2354adfb39e9a229ae4dc896e7481a569ecc19dd2d6d_left_env": "1", "042c55b626937b8d6be258a97f8d25cdedeee2e712dbddef9438fa900eff883e_arguments": "(R P)", "36900466483b112787abffe419202a499c8e5467e750cf3aec03ac5fd0ba9cfd": "max", "40fe864fddcab141770d7e0c0be5d5d07bcb8efd496a6f4bb2cdc3834e94eab9_left_env": "1", "3ac370c3d91282c6eb94742d40cdb371de392eaca8a0a213d3d3ade6d1b03367_arguments": "(a b)", "f5470fda7b930fc12a27be2810e4c48ad7e35ceda81273ba026cd6da98d94c3c": "slice", "f4c3c71dddb1c7ee50bc104032f26172d61ff77f9bca9876d1846c47cd72020e_arguments": "(cards)", "f5470fda7b930fc12a27be2810e4c48ad7e35ceda81273ba026cd6da98d94c3c_arguments": "(mylist count)", "cbfdd91c91e2fc43ef49a82e173f49c6cc73a6a022b1378b885ff9ea94f373b0": "letbinding_$_1800", "1bde90fbef9d7a4c5cb7133780d4275aa03dfc0a54a905b899d65b4b578f6661_arguments": "((a_$_1669 b_$_1670) inner_result_$_1671)", "042c55b626937b8d6be258a97f8d25cdedeee2e712dbddef9438fa900eff883e_left_env": "1", "724d50ee95e66b90e255e2cecc58cc35c2eb27302b1952948538ad95f7387a4b_left_env": "1", "d121f71fcb5513b6d2b097255deb884ff40c26dd366b0ba7cf2eea1440b07901_arguments": "(mylist)", "24d7dbd0fece56391d516812ca037a910985789b424144b4dc8f8c57cf3ce108": "straight_high_inner", "4b216afca35845442571c30c6d827724285ca82490dbdae1b27f2d082e85ff66_left_env": "1", "8afd8fa01ef33b8744033203c10bd0c52e1da692d02ff4094f7b42d5ef7ddd47_arguments": "(((myfunc_$_1776 firstarg_$_1777 secondarg_$_1778 . remaining_$_1779)) secondval_$_1781 firstval_$_1780)", "faf326970cccbdcee02916d1e40ff5146aa7b1e2dfcac2bfaee7ceaaa3d5965e_left_env": "1", "471488bbd4b64848f0c6592900ef2a751e8907a72557b0ba794e0d6f1252c374": "reverse_inner", "4b216afca35845442571c30c6d827724285ca82490dbdae1b27f2d082e85ff66": "runtests", "8afd8fa01ef33b8744033203c10bd0c52e1da692d02ff4094f7b42d5ef7ddd47_left_env": "1", "a87d2e2e13539c8f9f66137bdee9a7fd750b8bdb6a07fc1e6cd8416d771d9958_arguments": "(() x_$_1758 y_$_1759)", "2df345b9e040f0cdefc0db6e59e9ea40894c26003d4bb35d4c0b88bfdc5d2d8f_arguments": "((((((cards_$_1747) rest_$_1750 first_$_1748) nosuits_$_1753 fsuit_$_1752) groups_$_1764 sh_$_1763 max_flush_$_1756) max_straight_$_1767 (second_count_$_1770 . second_card_$_1771) (top_count_$_1768 . top_card_$_1769) topcards_$_1772) max_group_$_1773)", "1bde90fbef9d7a4c5cb7133780d4275aa03dfc0a54a905b899d65b4b578f6661_left_env": "1", "9d29b02858791632bc362c1460848641e331d92b120c8b18e241a6a7375b387e_left_env": "1", "d3a1931b023b08bc00d8335c069b7d488fa1930ee6c312dcf11cb54a6d5761b1_left_env": "1", "e51e3ecc739e0c9b646889ad797fa268d9acbb09f42f70b1a75be411440dcf36_left_env": "1", "c64dc59aae25053fe8d872e13fca4e2c43765a1a83335d520435180f3ab55485_arguments": "(myless A B agg)", "0dda9e9f845e653fbb9f1065f098a0c439bf605b2e8830546184c95eae822f25": "letbinding_$_1784", "c60f4e2e12ab7285ef437f63bb24f4e5e6267fc76479893a179ebae738aca004_arguments": "((myless_$_1720 mylist_$_1721) (a_$_1722 b_$_1723))", "36900466483b112787abffe419202a499c8e5467e750cf3aec03ac5fd0ba9cfd_arguments": "(myless mylist)", "26df51fddc60f80f199438e505e3832df819036418c8bf439a572679ebfd1897": "split_inner", "5c2c8bfc9ac6c103562c9017a5cee2634da7ee43d44bd4f3d46d11e519942ea6_left_env": "1", "40fe864fddcab141770d7e0c0be5d5d07bcb8efd496a6f4bb2cdc3834e94eab9_arguments": "((items_$_1742 last_$_1743 count_$_1744) val_$_1745)", "24d45638962c8ac6b0923f0f2c912177b1b1c710bbcd3e10fccf01fc6f771263": "sort", "a87d2e2e13539c8f9f66137bdee9a7fd750b8bdb6a07fc1e6cd8416d771d9958": "lambda_$_1797", "471488bbd4b64848f0c6592900ef2a751e8907a72557b0ba794e0d6f1252c374_arguments": "(reversed rest)", "68a51341b984c77341ffa8fd755e2b80544914c95cd78caf10312d7e818b48d9_arguments": "((((cards_$_1747) rest_$_1750 first_$_1748) nosuits_$_1753 fsuit_$_1752) groups_$_1764 sh_$_1763 max_flush_$_1756)", "8bda8ccb43702a3e1a1b2354adfb39e9a229ae4dc896e7481a569ecc19dd2d6d": "deep<", "3ac370c3d91282c6eb94742d40cdb371de392eaca8a0a213d3d3ade6d1b03367_left_env": "1", "24d7dbd0fece56391d516812ca037a910985789b424144b4dc8f8c57cf3ce108_left_env": "1", "00c86eab1caeadaaf967420becbefef7170e5e996890edc355d16c263ea32e27_left_env": "1", "24d7dbd0fece56391d516812ca037a910985789b424144b4dc8f8c57cf3ce108_arguments": "(ranks started_ace last count)", "724d50ee95e66b90e255e2cecc58cc35c2eb27302b1952948538ad95f7387a4b": "map-with-rest", "53480b9619c61ae7111a964382f8a884a6ec22e384b92025271b48d1fe231b1e_arguments": "((cards_$_1747) rest_$_1750 first_$_1748)", "faf326970cccbdcee02916d1e40ff5146aa7b1e2dfcac2bfaee7ceaaa3d5965e_arguments": "(((cards_$_1747) rest_$_1750 first_$_1748) nosuits_$_1753 fsuit_$_1752)", "ea58983a62a5d0a526c32f3423717af26c6d9d5963eb4831a0d1049227eba060_left_env": "1", "dd3953423ae82b313d5361cb4c9ea7d18b43294e1c0801e1c021d101a7ce58f6_left_env": "1", "dd3953423ae82b313d5361cb4c9ea7d18b43294e1c0801e1c021d101a7ce58f6_arguments": "(((((cards_$_1747) rest_$_1750 first_$_1748) nosuits_$_1753 fsuit_$_1752) fnosuits_$_1757) fsh_$_1762)", "2379a74341919286585b51fa8ff2bf5a2e76254197c786fdcd96d4b004be17ba": "deep>", "40fe864fddcab141770d7e0c0be5d5d07bcb8efd496a6f4bb2cdc3834e94eab9": "letbinding_$_1788", "1bde90fbef9d7a4c5cb7133780d4275aa03dfc0a54a905b899d65b4b578f6661": "letbinding_$_1783", "c60f4e2e12ab7285ef437f63bb24f4e5e6267fc76479893a179ebae738aca004": "letbinding_$_1785", "53480b9619c61ae7111a964382f8a884a6ec22e384b92025271b48d1fe231b1e": "letbinding_$_1789", "01ed928ebc640669bfdc000b292962b919f6635176dd9119325f5f912d7567b8_left_env": "1", "7245d12b7785f1ee23a0ec0d3a03432057ec41fb0561d373d91cda267f44c3e9_left_env": "1", "dd3953423ae82b313d5361cb4c9ea7d18b43294e1c0801e1c021d101a7ce58f6": "letbinding_$_1799", "79f3cf5c572162105f8688174041050314a154956ef27d7ea6414a9dcd402faa": "group_by_count", "d3a1931b023b08bc00d8335c069b7d488fa1930ee6c312dcf11cb54a6d5761b1": "runtests_inner", "68a51341b984c77341ffa8fd755e2b80544914c95cd78caf10312d7e818b48d9_left_env": "1", "00c86eab1caeadaaf967420becbefef7170e5e996890edc355d16c263ea32e27": "max_inner", "9d29b02858791632bc362c1460848641e331d92b120c8b18e241a6a7375b387e_arguments": "((((cards_$_1747) rest_$_1750 first_$_1748) nosuits_$_1753 fsuit_$_1752) fnosuits_$_1757)", "53480b9619c61ae7111a964382f8a884a6ec22e384b92025271b48d1fe231b1e_left_env": "1", "faf326970cccbdcee02916d1e40ff5146aa7b1e2dfcac2bfaee7ceaaa3d5965e": "letbinding_$_1792", "c4e96a2219a3d6389693cfb81c4309f5bf5f1a89f300c7c12d019e08d14cde09": "prepend", "8bda8ccb43702a3e1a1b2354adfb39e9a229ae4dc896e7481a569ecc19dd2d6d_arguments": "(a b)", "f5470fda7b930fc12a27be2810e4c48ad7e35ceda81273ba026cd6da98d94c3c_left_env": "1", "26df51fddc60f80f199438e505e3832df819036418c8bf439a572679ebfd1897_left_env": "1", "c4e96a2219a3d6389693cfb81c4309f5bf5f1a89f300c7c12d019e08d14cde09_arguments": "(a b)", "0dda9e9f845e653fbb9f1065f098a0c439bf605b2e8830546184c95eae822f25_arguments": "((process_$_1697 remaining_$_1698 init_$_1699) next_$_1700)", "__chia__main_arguments": "()", "2379a74341919286585b51fa8ff2bf5a2e76254197c786fdcd96d4b004be17ba_left_env": "1"} \ No newline at end of file diff --git a/resources/tests/game-referee-after-cl21/test_handcalc_b.clsp b/resources/tests/game-referee-after-cl21/test_handcalc_b.clsp new file mode 100644 index 000000000..674bbd414 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_handcalc_b.clsp @@ -0,0 +1,377 @@ + +(mod () + (include *standard-cl-21*) + (include deep_compare.clinc) + (include assert.clinc) + (include reverse.clinc) + (include prepend.clinc) + (include map.clinc) + (include filtermap.clinc) + (include slice.clinc) + (include print.clinc) + (include handcalc.clinc) + + (defun runtests_inner ((myfunc firstarg secondarg . remaining)) + (assign-lambda + firstval (handcalc firstarg) + secondval (handcalc secondarg) + (assert + (a myfunc (list firstval secondval)) + (deep= firstval (handcalc (reverse firstarg))) + (deep= secondval (handcalc (reverse secondarg))) + (if remaining + (runtests_inner remaining) + 0 + ) + ) + ) + ) + + (defun runtests tests (if tests (runtests_inner tests) ())) + + ;; Join these up when large application bug is fixed. + (runtests + ; all beats both emerge over and measure higher + ; straight flush with higher kicker ties + ; A1 K1 Q1 J1 T1 91 = A1 K1 Q1 J1 T1 81 + deep= + (list (c 12 1) (c 11 1) (c 14 1) (c 13 1) (c 10 1) (c 9 1)) + (list (c 12 1) (c 11 1) (c 14 1) (c 13 1) (c 10 1) (c 8 1)) + ; straight flushes of different suits tie + ; A1 K1 Q1 J1 T1 = A2 K2 Q2 J2 T2 + deep= + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 10 1)) + (list (c 14 2) (c 13 2) (c 12 2) (c 11 2) (c 10 2)) + ; higher straight flush beats lower straight flush + ; A1 K1 Q1 J1 T1 > 61 51 41 31 21 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 10 1)) + (list (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + ; A1 K1 Q1 J1 T1 91 = A1 K1 Q1 J1 T1 + deep= + (list (c 12 1) (c 11 1) (c 14 1) (c 13 1) (c 10 1) (c 9 1)) + (list (c 14 2) (c 11 2) (c 10 2) (c 13 2) (c 12 2)) + ; lower (2-6) straight flush beats ace to four straight flush + ; 61 51 41 31 21 > A2 52 42 32 22 + deep> + (list (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 14 2) (c 5 2) (c 4 2) (c 3 2) (c 2 2)) + ; A1 61 51 41 31 21 = 61 51 41 31 21 + deep= + (list (c 14 1) (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + ; ace to four straight flush with higher kicker ties + ; A2 52 42 32 22 61 = A1 51 41 31 21 71 + deep= + (list (c 14 2) (c 5 2) (c 4 2) (c 3 2) (c 2 2) (c 6 1)) + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1) (c 7 1)) + ; ace to four straight flushes of different suits tie + ; A1 51 41 31 21 = A2 52 42 32 22 + deep= + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 14 2) (c 5 2) (c 4 2) (c 3 2) (c 2 2)) + ; ace to four straight flush beats four of a kind + ; A1 51 41 31 21 > K1 K2 K3 K4 J1 + deep> + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 11 1)) + ; A1 A2 A3 A4 51 41 31 21 = A1 51 41 31 21 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + ; four of a kind with higher kicker wins + ; K1 K2 K3 K4 Q1 > K1 K2 K3 K4 J1 + deep> + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 12 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 11 1)) + ; K1 K2 K3 K4 T1 91 = K1 K2 K3 K4 T1 + deep= + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 10 1) (c 9 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 10 1)) + ; four of a kind with higher second kicker ties + ; K1 K2 K3 K4 Q1 J1 = K1 K2 K3 K4 Q1 T1 + deep= + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 12 1) (c 11 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 12 1) (c 10 1)) + ; higher four of a kind beats lower four of a kind + ; K1 K2 K3 K4 21 > 31 32 33 34 A1 + deep> + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 2 1)) + (list (c 3 1) (c 3 2) (c 3 3) (c 3 4) (c 14 1)) + ; K1 K2 K3 K4 31 32 33 34 = K1 K2 K3 K4 32 + deep= + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 3 1) (c 3 2) (c 3 3) (c 3 4)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 3 2)) + ; four of a kind beats full house + ; 21 22 23 24 31 > A1 A2 A3 K1 K2 + deep> + (list (c 2 1) (c 2 2) (c 2 3) (c 2 4) (c 3 1)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2)) + ; 21 22 23 24 A1 A2 A3 = 21 22 23 24 A2 + deep= + (list (c 2 1) (c 2 2) (c 2 3) (c 2 4) (c 14 1) (c 14 2) (c 14 3)) + (list (c 2 1) (c 2 2) (c 2 3) (c 2 4) (c 14 2)) + ; full house with higher set wins + ; 51 52 53 21 22 > 31 32 33 71 72 + deep> + (list (c 5 1) (c 5 2) (c 5 3) (c 2 1) (c 2 2)) + (list (c 3 1) (c 3 2) (c 3 3) (c 7 1) (c 7 2)) + ; A1 A2 A3 K1 K2 K3 = A1 A2 A3 K1 K2 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2) (c 13 3)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2)) + ; full house with same set and higher pair wins + ; 51 52 53 41 42 > 51 52 53 31 32 + deep> + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2)) + (list (c 5 1) (c 5 2) (c 5 3) (c 3 1) (c 3 2)) + ; A1 A2 A3 K1 K2 51 52 = A1 A2 A3 K1 K2 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2) (c 5 1) (c 5 2)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2)) + ; full house ties with two sets + ; 51 52 53 41 42 A1 = 51 52 53 41 42 43 + deep= + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2) (c 14 1)) + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2) (c 4 3)) + ; full house beats flush + ; 51 52 53 41 42 > A1 Q1 T1 81 71 + deep> + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2)) + (list (c 14 1) (c 12 1) (c 10 1) (c 8 1) (c 7 1)) + ; 51 52 53 41 42 A1 K1 Q1 = 51 52 53 41 42 + deep= + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2) (c 14 1) (c 13 1) (c 12 1)) + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2)) + ; higher flush beats lower flush + ; A1 61 51 41 31 > K1 Q1 J1 T1 81 + deep> + (list (c 14 1) (c 6 1) (c 5 1) (c 4 1) (c 3 1)) + (list (c 13 1) (c 12 2) (c 11 1) (c 10 1) (c 8 1)) + ; A1 K1 Q1 J1 81 71 = A1 K1 Q1 J1 81 + deep= + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 8 1) (c 7 1)) + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 8 1)) + ; flush with higher second card wins + ; A1 K1 51 41 31 > A1 Q1 J1 T1 91 + deep> + (list (c 14 1) (c 13 1) (c 5 1) (c 4 1) (c 3 1)) + (list (c 14 1) (c 12 2) (c 11 1) (c 10 1) (c 9 1)) + ; flush with higher third card wins + ; A1 K1 Q1 41 31 > A1 K1 J1 T1 91 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 4 1) (c 3 1)) + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 9 1)) + ; flush with higher fourth card wins + ; A1 K1 Q1 T1 21 > A1 K1 Q1 91 81 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 10 1) (c 2 1)) + (list (c 14 1) (c 13 1) (c 12 1) (c 9 1) (c 8 1)) + ; flush with higher fifth card wins + ; A1 K1 Q1 T1 81 > A1 K1 Q1 T1 71 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 10 1) (c 8 1)) + (list (c 14 1) (c 13 1) (c 12 1) (c 10 1) (c 7 1)) + ; flushes of different suits tie + ; A1 K1 J1 T1 81 = A2 K2 J2 T2 82 + deep= + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 8 1)) + (list (c 14 2) (c 13 2) (c 11 2) (c 10 2) (c 8 2)) + ; same flush with higher sixth card ties + ; A1 K1 J1 T1 81 71 = A1 K1 J1 T1 81 61 + deep= + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 8 1) (c 7 1)) + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 8 1) (c 6 1)) + ; flush beats straight + ; 71 61 51 41 21 > A1 K2 Q3 J4 T1 + deep> + (list (c 7 1) (c 6 1) (c 5 1) (c 4 1) (c 2 1)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1)) + ; A1 K2 Q3 J4 T1 81 71 61 = A1 T1 81 71 61 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 8 1) (c 7 1) (c 6 1)) + (list (c 14 1) (c 10 1) (c 8 1) (c 7 1) (c 6 1)) + ; straight with higher kicker ties + ; A1 K2 Q3 J4 T1 92 = A1 K2 Q3 J4 T1 22 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 9 2)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 2 2)) + ; straights of different suits tie + ; A1 K2 Q3 J4 T1 = A2 K3 Q4 J1 T2 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1)) + (list (c 14 2) (c 13 3) (c 12 4) (c 11 1) (c 10 2)) + ; higher straight beats lower straight + ; A1 K2 Q3 J4 T1 > 61 52 43 34 21 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1)) + (list (c 6 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + ; A1 K2 Q3 J4 T1 92 83 = A1 K2 Q3 J4 T1 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 9 2) (c 8 3)) + (list (c 14 2) (c 13 3) (c 12 4) (c 11 1) (c 10 2)) + ; lower (2-6) straight beats ace to four straight + ; 61 52 43 34 21 > A1 52 43 34 21 + deep> + (list (c 6 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + ; A1 62 53 44 31 22 = 62 53 44 31 22 + deep= + (list (c 14 1) (c 6 2) (c 5 3) (c 4 4) (c 3 1) (c 2 2)) + (list (c 6 2) (c 5 3) (c 4 4) (c 3 1) (c 2 2)) + ; ace to four straight with higher kicker ties + ; A1 52 43 34 21 K2 = A1 52 43 34 21 72 + deep= + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1) (c 13 2)) + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1) (c 7 2)) + ; ace to fours of different suits tie + ; A1 52 43 34 21 = A2 53 44 31 22 + deep= + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 2) (c 5 3) (c 4 4) (c 3 1) (c 2 2)) + ; ace to four straight beats set + ; A1 52 43 34 21 > A1 A2 A3 K1 Q2 + deep> + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 12 2)) + ; A1 A2 A3 52 43 34 21 = A1 52 43 34 21 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 5 2) (c 4 3) (c 3 2) (c 2 1)) + ; higher set wins + ; 71 72 73 34 21 > 51 52 53 A4 K1 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 3 4) (c 2 1)) + (list (c 5 1) (c 5 2) (c 5 3) (c 14 4) (c 13 1)) + ; set with higher first kicker wins + ; 71 72 73 A1 22 > 71 72 73 K1 Q2 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 2 2)) + (list (c 7 1) (c 7 2) (c 7 3) (c 13 1) (c 12 2)) + ; 71 72 73 A1 K2 J3 54 43 = 71 72 73 A1 K2 + deep= + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2) (c 11 3) (c 5 4) (c 4 3)) + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2)) + ; set with higher second kicker wins + ; 71 72 73 A1 K2 > 71 72 73 A1 Q2 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2)) + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 12 2)) + ; set with higher third kicker ties + ; 71 72 73 A1 K2 Q3 = 71 72 73 A1 K2 J3 + deep= + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2) (c 12 3)) + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2) (c 11 3)) + ; set beats two pair + ; 71 72 73 34 21 > A1 A2 K3 K4 Q1 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 14 2) (c 13 3) (c 13 4) (c 12 1)) + ; two pair with higher high pair wins + ; K1 K2 33 34 21 > Q1 Q2 J3 J4 A1 + deep> + (list (c 13 1) (c 13 2) (c 3 3) (c 3 4) (c 2 1)) + (list (c 12 1) (c 12 2) (c 11 3) (c 11 4) (c 14 1)) + ; A1 A2 K1 K2 J1 J2 = A1 A2 K1 K2 J3 + deep= + (list (c 14 1) (c 14 2) (c 13 1) (c 13 2) (c 11 1) (c 11 2)) + (list (c 14 1) (c 14 2) (c 13 1) (c 13 2) (c 11 3)) + ; two pair with tied higher pair and higher lower pair wins + ; K1 K2 71 72 23 > K1 K2 63 64 A1 + deep> + (list (c 13 1) (c 13 2) (c 7 1) (c 7 2) (c 2 3)) + (list (c 13 1) (c 13 2) (c 6 3) (c 6 4) (c 14 1)) + ; two pair with higher kicker wins + ; K1 K2 Q3 Q4 J1 > K1 K2 Q3 Q4 T1 + deep> + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 11 1)) + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 10 1)) + ; K1 K2 Q3 Q4 A1 T1 92 63 = K1 K2 Q3 Q4 A1 + deep= + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 14 1) (c 10 1) (c 9 2) (c 6 3)) + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 14 1)) + ; two pair with higher second kicker ties + ; K1 K2 Q3 Q4 J1 T2 = K1 K2 Q3 Q4 J1 92 + deep= + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 11 1) (c 10 2)) + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 11 1) (c 9 2)) + ; two pair beats pair + ; 41 42 33 34 21 > A1 A2 K3 Q4 J1 + deep> + (list (c 4 1) (c 4 2) (c 3 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 14 2) (c 13 3) (c 12 4) (c 11 1)) + ; higher pair wins + ; 71 72 53 44 31 > 61 62 A3 K4 Q1 + deep> + (list (c 7 1) (c 7 2) (c 5 3) (c 4 4) (c 3 1)) + (list (c 6 1) (c 6 2) (c 14 3) (c 13 4) (c 12 1)) + ; tied pair with higher first kicker wins + ; 91 92 A3 34 21 > 91 92 K3 Q4 J1 + deep> + (list (c 9 1) (c 9 2) (c 14 3) (c 3 4) (c 2 1)) + (list (c 9 1) (c 9 2) (c 13 3) (c 12 4) (c 11 1)) + ; 21 22 A1 Q2 J3 94 81 = 21 22 A1 Q2 J3 + deep= + (list (c 2 1) (c 2 2) (c 14 1) (c 12 2) (c 11 3) (c 9 4) (c 8 1)) + (list (c 2 1) (c 2 2) (c 14 1) (c 12 2) (c 11 3)) + ; tied pair with higher second kicker wins + ; 91 92 A3 K4 21 > 91 92 A3 Q4 J1 + deep> + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 2 1)) + (list (c 9 1) (c 9 2) (c 14 3) (c 12 4) (c 11 1)) + ; tied pair with higher third kicker wins + ; 91 92 A3 K4 Q1 > 91 92 A3 K4 J1 + deep> + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 12 1)) + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 11 1)) + ; tied pair with higher fourth kicker ties + ; 91 92 A3 K4 Q1 J2 = 91 92 A3 K4 Q1 T2 + deep= + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 12 1) (c 11 2)) + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 12 1) (c 10 2)) + ; pair beats high card + ; 21 22 33 44 51 > A1 Q2 J3 T4 91 + deep> + (list (c 2 1) (c 2 2) (c 3 3) (c 4 4) (c 5 1)) + (list (c 14 1) (c 12 2) (c 11 3) (c 10 4) (c 9 1)) + ; higher high card wins + ; A1 22 33 44 61 > K1 Q2 J3 T4 81 + deep> + (list (c 14 1) (c 2 2) (c 3 3) (c 4 4) (c 6 1)) + (list (c 13 1) (c 12 2) (c 11 3) (c 10 4) (c 8 1)) + ; A1 K2 J3 T4 81 72 53 = A1 K2 J3 T4 81 + deep= + (list (c 14 1) (c 13 2) (c 11 3) (c 10 4) (c 8 1) (c 7 2) (c 5 3)) + (list (c 14 1) (c 13 2) (c 11 3) (c 10 4) (c 8 1)) + ; higher second card wins + ; A1 K2 23 34 41 > A1 Q2 J3 T4 91 + deep> + (list (c 14 1) (c 13 2) (c 2 3) (c 3 4) (c 4 1)) + (list (c 14 1) (c 12 2) (c 11 3) (c 10 4) (c 9 1)) + ; higher third card wins + ; A1 K2 Q3 24 41 > A1 K2 J3 T4 91 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 2 4) (c 4 1)) + (list (c 14 1) (c 13 2) (c 11 3) (c 10 4) (c 9 1)) + ; higher fourth card wins + ; A1 K2 Q3 J4 31 > A1 K2 Q3 T4 91 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 3 1)) + (list (c 14 1) (c 13 2) (c 12 3) (c 10 4) (c 9 1)) + ; higher fifth card wins + ; A1 K2 Q3 J4 91 > A1 K2 Q3 J4 81 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 8 1)) + ; higher sixth card ties + ; A1 K2 Q3 J4 91 22 = A1 K2 Q3 J4 91 82 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1) (c 2 2)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1) (c 8 2)) + ; high cards of different suits ties + ; A1 K2 Q3 J4 91 = A2 K3 Q4 J1 92 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1)) + (list (c 14 2) (c 13 3) (c 12 4) (c 11 1) (c 9 2)) + ) +) diff --git a/resources/tests/game-referee-after-cl21/test_library_basics.py b/resources/tests/game-referee-after-cl21/test_library_basics.py new file mode 100644 index 000000000..c8cce6664 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_library_basics.py @@ -0,0 +1,165 @@ +import os +import pytest +import random +from itertools import permutations +from typing import List +#from hsms.streamables.program import Program +#from steprun import diag_run_clvm, compile_module_with_symbols +#from lib.program import Program +from pathlib import Path +from clvm_rs import Program +from lib.steprun import diag_run_clvm, compile_module_with_symbols +from clvm_tools_rs import get_version + +print(f"clvm_tools_rs version is {get_version()}") +#include_dirs = os.getcwd() +include_dirs = [Path(__file__).parent, Path(__file__).parent.parent / "lib"] +Program.set_run_unsafe_max_cost(11000000000) + +print(f"XXX: {include_dirs}") +compile_module_with_symbols(include_dirs, 'smoke_test_deep_compare.clsp') +compare_program = Program.from_bytes(bytes.fromhex(open('smoke_test_deep_compare.clvm.hex').read())) + +compile_module_with_symbols(include_dirs, 'smoke_test_sort.clsp') +sort_program = Program.from_bytes(bytes.fromhex(open('smoke_test_sort.clvm.hex').read())) + +compile_module_with_symbols(include_dirs, 'test_sort.clsp') +test_sort_program = Program.from_bytes(bytes.fromhex(open('test_sort.clvm.hex').read())) + +compile_module_with_symbols(include_dirs, 'test_permutations.clsp') +test_permutations_program = Program.from_bytes(bytes.fromhex(open('test_permutations.clvm.hex').read())) + +compile_module_with_symbols(include_dirs, 'test_reverse.clsp') +test_reverse_program = Program.from_bytes(bytes.fromhex(open('test_reverse.clvm.hex').read())) + +compile_module_with_symbols(include_dirs, 'test_prepend.clsp') +test_prepend_program = Program.from_bytes(bytes.fromhex(open('test_prepend.clvm.hex').read())) + +compile_module_with_symbols(include_dirs, 'test_range.clsp') +test_range_program = Program.from_bytes(bytes.fromhex(open('test_range.clvm.hex').read())) + +compile_module_with_symbols(include_dirs, 'smoke_test_permutations.clsp') +smoke_test_permutations_program = Program.from_bytes(bytes.fromhex(open('smoke_test_permutations.clvm.hex').read())) + +compile_module_with_symbols(include_dirs, 'test_handcalc.clsp') +test_handcalc_program = Program.from_bytes(bytes.fromhex(open('test_handcalc.clvm.hex').read())) + +def as_atom_list(prg: Program) -> List[bytes]: + """ + Pretend `prg` is a list of atoms. Return the corresponding + python list of atoms. + + At each step, we always assume a node to be an atom or a pair. + If the assumption is wrong, we exit early. This way we never fail + and always return SOMETHING. + """ + items = [] + obj = prg + while True: + pair = obj.pair + if pair is None: + break + atom = pair[0].atom + if atom is None: + break + items.append(atom) + obj = pair[1] + return items + +def test_smoke_compare(): + compare_program.run(Program.to([])) + +def test_handcalc(): + diag_run_clvm(test_handcalc_program, Program.to([]), 'test_handcalc.sym', {'print': True}) + +def proper_list_inner(result,cl): + if hasattr(cl, 'pair') and cl.pair is not None: + result.append(cl.pair[0]) + return proper_list_inner(result,cl.pair[1]) + else: + return result + +def proper_list(cl): + result = [] + return proper_list_inner(result,cl) + +def int_list(cl): + return [Program.to(x).as_int() for x in as_atom_list(Program.to(cl))] + +def de_none_list(l): + return [x if x is not None else [] for x in l] + +def with_random_lists(n,f): + for length in range(n): # 0-10 length + for i in range(1 + (3 * length)): # A few orders each + orig_list = [random.randint(0,100) for x in range(length)] + f(orig_list) + +def test_prepend(): + for length1 in range(5): + list_1 = list(range(length1)) + for length2 in range(length1): + prepend_result = test_prepend_program.run([Program.to(list_1[:length2]),Program.to(list_1[length2:])]) + assert list_1 == int_list(prepend_result) + +def test_reverse(): + def test_reverse_list(l): + rev_args = Program.to([l]) + reversed_result = Program.to(list(reversed(l))) + reversed_by_prog = test_reverse_program.run(rev_args) + assert reversed_result == reversed_by_prog + + with_random_lists(10,test_reverse_list) + +def test_range(): + for length in range(10): + want_list = list(range(length)) + result = test_range_program.run(Program.to([length])) + assert want_list == result + +def do_test_permutations_of_size_n(n): + try_list = [random.randint(0,100) for x in range(n)] + want_set = list([list(v) for v in sorted(permutations(try_list))]) + listed_result = smoke_test_permutations_program.run(Program.to([try_list])) + pl = proper_list(listed_result) + perms_result = sorted([int_list(x) for x in de_none_list(pl)]) + assert want_set == perms_result + +def test_permutations_0(): + do_test_permutations_of_size_n(0) + +def test_permutations_1(): + do_test_permutations_of_size_n(1) + +def test_permutations_2(): + n = 2 + all_a_string = 0x616161616161 + all_b_string = 0x626262626262 + for try_list in [[all_a_string,all_b_string], [all_b_string,all_a_string]]: + want_set = list([list(v) for v in sorted(permutations(try_list))]) + listed_result = diag_run_clvm(smoke_test_permutations_program, Program.to([try_list]), 'smoke_test_permutations.sym', {'print': True}) + pl = proper_list(listed_result) + perms_result = sorted([int_list(x) for x in de_none_list(pl)]) + assert want_set == perms_result + +def test_chialisp_sort_program(): + diag_run_clvm(test_sort_program, Program.to([]), 'test_sort.sym', {'print': True}) + +def test_permutations_n(): + for i in range(3,6): + do_test_permutations_of_size_n(i) + +def test_chialisp_permutations_program(): + diag_run_clvm(test_permutations_program, Program.to([3, 5]), 'test_permutations.sym', {'print': True}) + +def test_smoke_sort(): + for length in range(7): # 0-7 length + for i in range(1 + (3 * length)): # A few orders each + orig_list = [random.randint(0,100) for x in range(length)] + sort_args = Program.to([orig_list]) + sorted_list = Program.to(sorted(orig_list)) + sort_res = sort_program.run(sort_args) + assert sort_res == sorted_list + +if __name__ == '__main__': + test_smoke_sort() diff --git a/resources/tests/game-referee-after-cl21/test_permutations.clsp b/resources/tests/game-referee-after-cl21/test_permutations.clsp new file mode 100644 index 000000000..d5b6d125f --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_permutations.clsp @@ -0,0 +1,63 @@ +(mod (M N) + (include *standard-cl-21*) + (include prepend.clinc) + (include reverse.clinc) + (include map.clinc) + (include len.clinc) + (include range.clinc) + (include sort.clinc) + (include assert.clinc) + (include deep_compare.clinc) + (include permutations.clinc) + (include last.clinc) + (include busy.clinc) + (include all-in-list.clinc) + (include print.clinc) + + (defun ! (x) + (if x + (* x (! (- x 1))) + 1 + ) + ) + (defun no_repeats_inner ((first . remainder)) + (if remainder + (if (deep= first (f remainder)) + 0 + (no_repeats_inner remainder) + ) + 1 + ) + ) + (defun no_repeats (mylist) + (if mylist + (no_repeats_inner (sort (lambda (a b) (= (deep_compare a b) -1)) mylist)) + 1 + ) + ) + (assert + ;; Is permutations expected to collapse equal alternatives when two of + ;; the items to shuffle are equal? + (= (* (! M) 4) (len (permutations (c 0 (range M))))) + (busy + (lambda (listlen) + (assign + mylist (range listlen) + permed (permutations mylist) + (assert + (= (len permed) (! listlen)) + ;; ensure we didn't produce any permutations that have + ;; repeated elements in them, which would indicate that + ;; the permutation function misbehaved + (all-in-list (map (lambda (L) (no_repeats L)) permed)) + (no_repeats permed) + ) + ) + ) + (reverse (range N)) + 1 + ) + (deep= (permutations 0) (q ())) + 0 + ) +) diff --git a/resources/tests/game-referee-after-cl21/test_permutations.clvm.hex b/resources/tests/game-referee-after-cl21/test_permutations.clvm.hex new file mode 100644 index 000000000..ccbc2f4aa --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_permutations.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ffff03ffff09ffff12ffff02ff66ffff04ff02ffff04ff05ff80808080ffff010480ffff02ff48ffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff04ffff0180ffff02ff58ffff04ff02ffff04ff05ff8080808080ff80808080ff8080808080ffff01ff02ffff01ff02ffff03ffff02ff5affff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200fe80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ffff02ff50ffff04ff02ffff04ffff02ff58ffff04ff02ffff04ff0bff80808080ff80808080ffff04ffff0101ff808080808080ffff01ff02ffff01ff02ffff03ffff02ff42ffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff0180ff80808080ffff04ffff01ff8080ff8080808080ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ffff04ffff01ffffffffffff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff40ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff02ffff03ff0bffff01ff02ffff01ff02ff60ffff04ff02ffff04ffff04ffff05ff0b80ff0580ffff04ffff06ff0b80ff8080808080ff0180ffff01ff02ffff0105ff018080ff0180ffff02ff60ffff04ff02ffff04ff80ffff04ff05ff8080808080ff02ffff03ff0bffff01ff02ffff01ff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff02ff70ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff80808080808080ff0180ffff01ff02ffff0117ff018080ff0180ffffff02ffff03ff05ffff01ff02ffff01ff10ffff0101ffff02ff48ffff04ff02ffff04ffff06ff0580ff8080808080ff0180ffff01ff02ffff01ff0180ff018080ff0180ff02ffff03ffff09ff05ff0b80ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff04ff05ffff02ff68ffff04ff02ffff04ffff10ff05ffff010180ffff04ff0bff808080808080ff018080ff0180ffff02ff68ffff04ff02ffff04ff80ffff04ff05ff8080808080ff02ffff03ff05ffff01ff02ffff01ff02ff78ffff04ff02ffff04ffff06ff0580ffff04ff17ffff04ffff04ffff05ff0580ff0b80ff808080808080ff0180ffff01ff02ffff01ff06ff0380ff018080ff0180ffffffff02ff78ffff04ff02ffff04ff05ffff01ff80ff8080808080ff02ffff03ffff20ff0b80ffff01ff02ffff01ff02ff40ffff04ff02ffff04ffff02ff50ffff04ff02ffff04ff2fff80808080ffff04ff17ff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff20ff1780ffff01ff02ffff01ff02ff40ffff04ff02ffff04ffff02ff50ffff04ff02ffff04ff2fff80808080ffff04ff0bff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff02ff05ffff04ffff05ff0b80ffff04ffff05ff1780ffff0180808080ffff01ff02ffff01ff02ff64ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ffff04ffff04ffff05ff0b80ff2f80ff80808080808080ff0180ffff01ff02ffff01ff02ff64ffff04ff02ffff04ff05ffff04ff0bffff04ffff06ff1780ffff04ffff04ffff05ff1780ff2f80ff80808080808080ff018080ff0180ff018080ff0180ff018080ff0180ffff02ff64ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff01ff80808080808080ff02ffff03ff0bffff01ff02ffff01ff02ffff03ffff06ff0b80ffff01ff02ffff01ff02ff4cffff04ff02ffff04ffff06ff0180ffff04ffff02ff44ffff04ff02ffff04ff0bff80808080ff8080808080ff0180ffff01ff02ffff010bff018080ff0180ff0180ffff01ff02ffff01ff0180ff018080ff0180ffffff02ff6cffff04ff02ffff04ff03ffff04ffff02ff74ffff04ff02ffff04ff09ffff04ff13ff8080808080ffff04ffff02ff74ffff04ff02ffff04ff09ffff04ff2bff8080808080ff808080808080ff02ff54ffff04ff02ffff04ff11ffff04ff0bffff04ff17ff808080808080ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff02ff7cffff04ff02ffff04ffff06ff0180ffff04ffff02ff5cffff04ff02ffff04ffff05ff0580ffff04ffff05ff0b80ff8080808080ff8080808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff0181ffff0180ffff01ff02ffff01ff02ffff03ffff15ff05ff0b80ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff11ffff0180ffff15ff0bff058080ff018080ff0180ff018080ff0180ff018080ff0180ff02ffff03ff0bffff01ff02ffff010bff0180ffff01ff02ffff01ff02ff5cffff04ff02ffff04ffff06ff0980ffff04ffff06ff1580ff8080808080ff018080ff0180ffffffffff09ffff02ff5cffff04ff02ffff04ff05ffff04ff0bff8080808080ff8080ff02ffff03ffff20ff0b80ffff01ff02ffff0117ff0180ffff01ff02ffff01ff02ff52ffff04ff02ffff04ffff06ff0180ffff04ffff06ff0b80ffff04ffff05ff0b80ff808080808080ff018080ff0180ffff02ff70ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff7280ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff17ff808080ffff01ff01808080ff80808080ffff04ffff02ff4affff04ff02ffff04ffff02ff40ffff04ff02ffff04ff09ffff04ff0bff8080808080ff80808080ffff04ffff02ff62ffff04ff02ffff04ffff04ff17ff0980ffff04ff0bffff04ff2dff808080808080ff808080808080ff04ff09ff0b80ffffff02ffff03ff05ffff01ff02ffff01ff02ff62ffff04ff02ffff04ffff0180ffff04ff05ffff04ffff0180ff808080808080ff0180ffff01ff02ffff01ff01ff8080ff018080ff0180ff02ffff03ff0dffff01ff02ffff01ff02ff6affff04ff02ffff04ff0dff80808080ff0180ffff01ff02ffff0109ff018080ff0180ffff02ffff03ff0bffff01ff02ffff01ff02ff6affff04ff02ffff04ffff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff04ffff02ff5affff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff808080808080ffff01808080ff80808080ff0180ffff01ff02ffff0117ff018080ff0180ff02ffff03ff05ffff01ff02ffff01ff04ffff04ffff0101ffff05ff058080ffff02ff7affff04ff02ffff04ffff06ff0580ff8080808080ff0180ffff01ff02ffff01ff0180ff018080ff0180ffffffff02ffff04ffff0122ffff02ff7affff04ff02ffff04ff05ff8080808080ff8080ff02ffff03ff05ffff01ff02ffff01ff12ff05ffff02ff66ffff04ff02ffff04ffff11ff05ffff010180ff8080808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ffff02ffff03ff0dffff01ff02ffff01ff02ffff03ffff02ff42ffff04ff02ffff04ff09ffff04ffff05ff0d80ff8080808080ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff02ff56ffff04ff02ffff04ff0dff80808080ff018080ff0180ff0180ffff01ff02ffff01ff0101ff018080ff0180ff02ffff03ff05ffff01ff02ffff01ff02ff56ffff04ff02ffff04ffff02ff74ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff4e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ff05ff8080808080ff80808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ffffff09ffff02ff5cffff04ff02ffff04ff0bffff04ff17ff8080808080ffff0181ff80ff02ff5effff04ff02ffff04ff03ffff04ffff02ff4affff04ff02ffff04ff0bff80808080ff8080808080ffff02ffff03ffff09ffff02ff48ffff04ff02ffff04ff0bff80808080ffff02ff66ffff04ff02ffff04ff29ff8080808080ffff01ff02ffff01ff02ffff03ffff02ff46ffff04ff02ffff04ffff02ff70ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200be80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ff0bffff04ffff0180ff808080808080ff80808080ffff01ff02ffff01ff02ff76ffff04ff02ffff04ff0bff80808080ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ffff02ff76ffff04ff02ffff04ff0bff80808080ff02ff6effff04ff02ffff04ffff04ff80ffff04ff0bff808080ffff04ffff02ff58ffff04ff02ffff04ff0bff80808080ff8080808080ff018080 diff --git a/resources/tests/game-referee-after-cl21/test_permutations.sym b/resources/tests/game-referee-after-cl21/test_permutations.sym new file mode 100644 index 000000000..5822e3a17 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_permutations.sym @@ -0,0 +1 @@ +{"9fbce34b16a7c4618d5816009b42c6e661cb7efbcaf90314a2f840362f175793_arguments": "(() a_$_1091 b_$_1092)", "2c82355dea6595dde07e0d5e05aa96b89052c8b97d0e0c868356df4914f2fe68_left_env": "1", "657a0532257810b1c203d201026eccd16b845b156e25600b57a7ed5429c59682": "no_repeats", "02c081d44a600583556699febd4e3bc2eb117b61bd5cfc612c2bf091c952fa0a": "len", "9242b5b6b2f9c8d952001db1fbcffc4b477638bf957f6a5dd3a2cc742919c977": "reverse", "f8de27975a5aa0f0169626c8874de2ee78c9879c44424bfc1153bc150c6282fe_left_env": "1", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708_arguments": "((myatom_$_1065) x_$_1067)", "7381ec0d3e15950009d8b999a34b828e9964b79470270e7ed6c5409cf2f69bb9_arguments": "(L)", "9acbd39570d133bd1318e96254949ed3f9d84fb6796324d393b68b898c4999c8_arguments": "(F L R)", "a91dc4bec838278871d09bbe4a7206242b852404596d71f8e7962df872da447e": "all-in-list", "791c1745272da279ba038d8a0f093ab9076ff98d02ff09a3b35888c454f9d203_left_env": "1", "6c37e5a9ce5bcf0ae750dd4bb1db5898f49d63eadcdf27fbe04c787362459f5d": "letbinding_$_1105", "bde59c348f4163416518c666a1c5a1d39560d2b09c9b2b38b047e4da574c745e": "split", "ae7e4ed6da640a7bd1e9ef3b1d683440bf9297b217bf0743328f9ae54bbc5b53_left_env": "1", "2e3d155705dec0e05e5d4c87c93395ffe98fffe9f21542faca3c5c8751a18047_arguments": "(a b)", "7381ec0d3e15950009d8b999a34b828e9964b79470270e7ed6c5409cf2f69bb9_left_env": "1", "42e1f82cf8542a5f31de7edcd596df9a08e48bcf0aa637f866be044a0c96841f": "merge_inner", "1c9d01e44e9c5f35a282358422033e4e960609d9f5ef0efc7c7b48bf311208ff": "letbinding_$_1101", "9acbd39570d133bd1318e96254949ed3f9d84fb6796324d393b68b898c4999c8_left_env": "1", "42e1f82cf8542a5f31de7edcd596df9a08e48bcf0aa637f866be044a0c96841f_left_env": "1", "483fcccf52dd01c7be19ebb1f6ec50a0c235873236a8ab545236771af634b706_left_env": "1", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708_left_env": "1", "42e1f82cf8542a5f31de7edcd596df9a08e48bcf0aa637f866be044a0c96841f_arguments": "(myless A B agg)", "0ebdfa3c097ba5b3ef741e8a33b6af2f741209b3e29d94c1c55deb599e4c41d7_left_env": "1", "ae7e4ed6da640a7bd1e9ef3b1d683440bf9297b217bf0743328f9ae54bbc5b53_arguments": "(reversed rest)", "c6e0bf4deaac4dc5ac02244c56fcaba2652b33bfb38f812ba0a6ef67d3049f61_arguments": "(vals)", "f8de27975a5aa0f0169626c8874de2ee78c9879c44424bfc1153bc150c6282fe_arguments": "(i)", "1443073ed355cb83607d1c2a6d5612f28a038d3887fa750de973e6aa0ed83f08": "merge", "53fd31d2089bb8aa123a7e81215cafd80d667659bf3a51447a5cc7d80346e193_arguments": "(pre post agg)", "78956ca35a10cbc40b04bd0a14ca12faae5f292d70b9e072da61ef82f3677522": "no_repeats_inner", "9fbce34b16a7c4618d5816009b42c6e661cb7efbcaf90314a2f840362f175793_left_env": "1", "5087819cc352ab86b0b64eebf0a29725fb6306291a42ac51f17253919f7b899c_arguments": "((myless_$_1039 mylist_$_1040) (a_$_1041 b_$_1042))", "858e89b0997add55f954ceda806d5a77e9914f6d31bed3dedd1e9b67581ee202_left_env": "1", "1c9d01e44e9c5f35a282358422033e4e960609d9f5ef0efc7c7b48bf311208ff_arguments": "((a_$_1047 b_$_1048) inner_result_$_1049)", "bde59c348f4163416518c666a1c5a1d39560d2b09c9b2b38b047e4da574c745e_arguments": "(mylist)", "0871deba30de6d95a0b04a45e6e036162f8abe844ae21b31f7d7cd518845fe9c_left_env": "1", "791c1745272da279ba038d8a0f093ab9076ff98d02ff09a3b35888c454f9d203": "letbinding_$_1102", "a91dc4bec838278871d09bbe4a7206242b852404596d71f8e7962df872da447e_arguments": "(L)", "61f9f86f9df2ce0986b2ae605b74b6111f767e89b83729af6f34110bf65bdeb2_arguments": "(x)", "e23db45dac9015daa0e667d0d846c354b2b9d9aaa3faedb560854d8662f2e238_arguments": "((() listlen_$_1093) mylist_$_1094)", "2e3d155705dec0e05e5d4c87c93395ffe98fffe9f21542faca3c5c8751a18047_left_env": "1", "1443073ed355cb83607d1c2a6d5612f28a038d3887fa750de973e6aa0ed83f08_arguments": "(myless a b)", "85c5c955b32be4fef52509b26fe07ce1c3086244572fde3f3bc47636c20f86de_arguments": "(a b)", "791c1745272da279ba038d8a0f093ab9076ff98d02ff09a3b35888c454f9d203_arguments": "((pre_$_1062 post_$_1063 agg_$_1064) newrest_$_1066 myatom_$_1065)", "19f60e08ef187986cf06532ba696b5b91efeb5c043318b9e6b731f1cd80adf79_left_env": "1", "61f9f86f9df2ce0986b2ae605b74b6111f767e89b83729af6f34110bf65bdeb2_left_env": "1", "9242b5b6b2f9c8d952001db1fbcffc4b477638bf957f6a5dd3a2cc742919c977_left_env": "1", "78956ca35a10cbc40b04bd0a14ca12faae5f292d70b9e072da61ef82f3677522_arguments": "((first . remainder))", "a0c582b1c6b05c8a3f5d5d7afd51404b874bb63f21ef73f31c383007fce81e87_arguments": "(a b)", "c6e0bf4deaac4dc5ac02244c56fcaba2652b33bfb38f812ba0a6ef67d3049f61_left_env": "1", "657a0532257810b1c203d201026eccd16b845b156e25600b57a7ed5429c59682_left_env": "1", "f8de27975a5aa0f0169626c8874de2ee78c9879c44424bfc1153bc150c6282fe": "range", "ae16459987997a1c9872031a855e1dfe8138fde4d1d5b9a5f188d3292ea97565": "sort", "19f60e08ef187986cf06532ba696b5b91efeb5c043318b9e6b731f1cd80adf79_arguments": "((next . remainder))", "2c82355dea6595dde07e0d5e05aa96b89052c8b97d0e0c868356df4914f2fe68": "lambda_$_1106", "5f7a25198045f0621cc78620e8739d731e1761a379e94ee1dae0717e4192e860": "letbinding_$_1100", "0871deba30de6d95a0b04a45e6e036162f8abe844ae21b31f7d7cd518845fe9c_arguments": "(next final)", "ae7e4ed6da640a7bd1e9ef3b1d683440bf9297b217bf0743328f9ae54bbc5b53": "reverse_inner", "78956ca35a10cbc40b04bd0a14ca12faae5f292d70b9e072da61ef82f3677522_left_env": "1", "6c37e5a9ce5bcf0ae750dd4bb1db5898f49d63eadcdf27fbe04c787362459f5d_arguments": "(((() listlen_$_1093) mylist_$_1094) permed_$_1095)", "2c82355dea6595dde07e0d5e05aa96b89052c8b97d0e0c868356df4914f2fe68_arguments": "(() L_$_1096)", "483fcccf52dd01c7be19ebb1f6ec50a0c235873236a8ab545236771af634b706_arguments": "(() listlen_$_1093)", "__chia__main_arguments": "(M N)", "02c081d44a600583556699febd4e3bc2eb117b61bd5cfc612c2bf091c952fa0a_arguments": "(L)", "ae16459987997a1c9872031a855e1dfe8138fde4d1d5b9a5f188d3292ea97565_arguments": "(myless mylist)", "858e89b0997add55f954ceda806d5a77e9914f6d31bed3dedd1e9b67581ee202": "split_inner", "0871deba30de6d95a0b04a45e6e036162f8abe844ae21b31f7d7cd518845fe9c": "range_inner", "85c5c955b32be4fef52509b26fe07ce1c3086244572fde3f3bc47636c20f86de_left_env": "1", "a0c582b1c6b05c8a3f5d5d7afd51404b874bb63f21ef73f31c383007fce81e87_left_env": "1", "61f9f86f9df2ce0986b2ae605b74b6111f767e89b83729af6f34110bf65bdeb2": "!", "7381ec0d3e15950009d8b999a34b828e9964b79470270e7ed6c5409cf2f69bb9": "enquote-rest", "e23db45dac9015daa0e667d0d846c354b2b9d9aaa3faedb560854d8662f2e238_left_env": "1", "5087819cc352ab86b0b64eebf0a29725fb6306291a42ac51f17253919f7b899c_left_env": "1", "6c37e5a9ce5bcf0ae750dd4bb1db5898f49d63eadcdf27fbe04c787362459f5d_left_env": "1", "source_file": "/home/arty/dev/chia/clvm_tools_rs/resources/tests/game-referee-after-cl21/test_permutations.clsp", "02c081d44a600583556699febd4e3bc2eb117b61bd5cfc612c2bf091c952fa0a_left_env": "1", "483fcccf52dd01c7be19ebb1f6ec50a0c235873236a8ab545236771af634b706": "lambda_$_1097", "1443073ed355cb83607d1c2a6d5612f28a038d3887fa750de973e6aa0ed83f08_left_env": "1", "e23db45dac9015daa0e667d0d846c354b2b9d9aaa3faedb560854d8662f2e238": "letbinding_$_1098", "5f7a25198045f0621cc78620e8739d731e1761a379e94ee1dae0717e4192e860_arguments": "(((myless_$_1039 mylist_$_1040) (a_$_1041 b_$_1042)) sa_$_1043 sb_$_1044)", "1c9d01e44e9c5f35a282358422033e4e960609d9f5ef0efc7c7b48bf311208ff_left_env": "1", "bde59c348f4163416518c666a1c5a1d39560d2b09c9b2b38b047e4da574c745e_left_env": "1", "9acbd39570d133bd1318e96254949ed3f9d84fb6796324d393b68b898c4999c8": "map-with-rest", "858e89b0997add55f954ceda806d5a77e9914f6d31bed3dedd1e9b67581ee202_arguments": "(@ everything (rest aggl aggr))", "c6e0bf4deaac4dc5ac02244c56fcaba2652b33bfb38f812ba0a6ef67d3049f61": "permutations", "9242b5b6b2f9c8d952001db1fbcffc4b477638bf957f6a5dd3a2cc742919c977_arguments": "(vals)", "2e3d155705dec0e05e5d4c87c93395ffe98fffe9f21542faca3c5c8751a18047": "deep=", "0ebdfa3c097ba5b3ef741e8a33b6af2f741209b3e29d94c1c55deb599e4c41d7_arguments": "(myfunc mylist returnval)", "657a0532257810b1c203d201026eccd16b845b156e25600b57a7ed5429c59682_arguments": "(mylist)", "53fd31d2089bb8aa123a7e81215cafd80d667659bf3a51447a5cc7d80346e193_left_env": "1", "5087819cc352ab86b0b64eebf0a29725fb6306291a42ac51f17253919f7b899c": "letbinding_$_1099", "ae16459987997a1c9872031a855e1dfe8138fde4d1d5b9a5f188d3292ea97565_left_env": "1", "85c5c955b32be4fef52509b26fe07ce1c3086244572fde3f3bc47636c20f86de": "deep_compare", "53fd31d2089bb8aa123a7e81215cafd80d667659bf3a51447a5cc7d80346e193": "permutations_inner", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708": "lambda_$_1103", "a0c582b1c6b05c8a3f5d5d7afd51404b874bb63f21ef73f31c383007fce81e87": "prepend", "19f60e08ef187986cf06532ba696b5b91efeb5c043318b9e6b731f1cd80adf79": "last_inner", "0ebdfa3c097ba5b3ef741e8a33b6af2f741209b3e29d94c1c55deb599e4c41d7": "busy", "a91dc4bec838278871d09bbe4a7206242b852404596d71f8e7962df872da447e_left_env": "1", "5f7a25198045f0621cc78620e8739d731e1761a379e94ee1dae0717e4192e860_left_env": "1", "9fbce34b16a7c4618d5816009b42c6e661cb7efbcaf90314a2f840362f175793": "lambda_$_1104"} \ No newline at end of file diff --git a/resources/tests/game-referee-after-cl21/test_prepend.clsp b/resources/tests/game-referee-after-cl21/test_prepend.clsp new file mode 100644 index 000000000..9f0d45819 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_prepend.clsp @@ -0,0 +1,5 @@ +(mod (X Y) + (include *standard-cl-21*) + (include prepend.clinc) + (prepend X Y) + ) diff --git a/resources/tests/game-referee-after-cl21/test_prepend.clvm.hex b/resources/tests/game-referee-after-cl21/test_prepend.clvm.hex new file mode 100644 index 000000000..47dd7f1f1 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_prepend.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff02ffff04ff02ffff04ff05ffff04ff0bff8080808080ffff04ffff01ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff02ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080 diff --git a/resources/tests/game-referee-after-cl21/test_prepend.sym b/resources/tests/game-referee-after-cl21/test_prepend.sym new file mode 100644 index 000000000..71e8d1cc4 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_prepend.sym @@ -0,0 +1 @@ +{"source_file": "/home/arty/dev/chia/clvm_tools_rs/resources/tests/game-referee-after-cl21/test_prepend.clsp", "dfe61be8d5db02605605573b4d298395c7a871cc5390a79d535d07bbd2338987": "prepend", "dfe61be8d5db02605605573b4d298395c7a871cc5390a79d535d07bbd2338987_arguments": "(a b)", "dfe61be8d5db02605605573b4d298395c7a871cc5390a79d535d07bbd2338987_left_env": "1", "__chia__main_arguments": "(X Y)"} \ No newline at end of file diff --git a/resources/tests/game-referee-after-cl21/test_range.clsp b/resources/tests/game-referee-after-cl21/test_range.clsp new file mode 100644 index 000000000..a7dc5edd9 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_range.clsp @@ -0,0 +1,6 @@ +(mod (X) + (include *standard-cl-21*) + (include range.clinc) + + (range X) + ) diff --git a/resources/tests/game-referee-after-cl21/test_range.clvm.hex b/resources/tests/game-referee-after-cl21/test_range.clvm.hex new file mode 100644 index 000000000..628a68fe6 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_range.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff06ffff04ff02ffff04ff05ff80808080ffff04ffff01ffff02ffff03ffff09ff05ff0b80ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff04ff05ffff02ff04ffff04ff02ffff04ffff10ff05ffff010180ffff04ff0bff808080808080ff018080ff0180ff02ff04ffff04ff02ffff04ff80ffff04ff05ff8080808080ff018080 diff --git a/resources/tests/game-referee-after-cl21/test_range.sym b/resources/tests/game-referee-after-cl21/test_range.sym new file mode 100644 index 000000000..5a414f20e --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_range.sym @@ -0,0 +1 @@ +{"6ba774998680757c6e60d6d6e8a94176f76b74e5f8c6f2cf5d99fb134e916556": "range_inner", "0f035685b03df70de81cbdbd4e600f5d2f148f6c02b0e0a73ef96a26e7121f2a": "range", "0f035685b03df70de81cbdbd4e600f5d2f148f6c02b0e0a73ef96a26e7121f2a_left_env": "1", "6ba774998680757c6e60d6d6e8a94176f76b74e5f8c6f2cf5d99fb134e916556_arguments": "(next final)", "__chia__main_arguments": "(X)", "0f035685b03df70de81cbdbd4e600f5d2f148f6c02b0e0a73ef96a26e7121f2a_arguments": "(i)", "source_file": "/home/arty/dev/chia/clvm_tools_rs/resources/tests/game-referee-after-cl21/test_range.clsp", "6ba774998680757c6e60d6d6e8a94176f76b74e5f8c6f2cf5d99fb134e916556_left_env": "1"} \ No newline at end of file diff --git a/resources/tests/game-referee-after-cl21/test_reverse.clsp b/resources/tests/game-referee-after-cl21/test_reverse.clsp new file mode 100644 index 000000000..b1d843648 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_reverse.clsp @@ -0,0 +1,6 @@ +(mod (X) + (include *standard-cl-21*) + (include reverse.clinc) + + (reverse X) + ) diff --git a/resources/tests/game-referee-after-cl21/test_reverse.clvm.hex b/resources/tests/game-referee-after-cl21/test_reverse.clvm.hex new file mode 100644 index 000000000..492966787 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_reverse.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff06ffff04ff02ffff04ff05ff80808080ffff04ffff01ffff02ffff03ff0bffff01ff02ffff01ff02ff04ffff04ff02ffff04ffff04ffff05ff0b80ff0580ffff04ffff06ff0b80ff8080808080ff0180ffff01ff02ffff0105ff018080ff0180ff02ff04ffff04ff02ffff04ff80ffff04ff05ff8080808080ff018080 diff --git a/resources/tests/game-referee-after-cl21/test_reverse.sym b/resources/tests/game-referee-after-cl21/test_reverse.sym new file mode 100644 index 000000000..c8868f67d --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_reverse.sym @@ -0,0 +1 @@ +{"0f035685b03df70de81cbdbd4e600f5d2f148f6c02b0e0a73ef96a26e7121f2a_arguments": "(vals)", "893ed9a33d9ef594068ddc5aa4e669dce55ad0e7588062968c1d76ba4c830c01_left_env": "1", "0f035685b03df70de81cbdbd4e600f5d2f148f6c02b0e0a73ef96a26e7121f2a": "reverse", "__chia__main_arguments": "(X)", "source_file": "/home/arty/dev/chia/clvm_tools_rs/resources/tests/game-referee-after-cl21/test_reverse.clsp", "893ed9a33d9ef594068ddc5aa4e669dce55ad0e7588062968c1d76ba4c830c01_arguments": "(reversed rest)", "893ed9a33d9ef594068ddc5aa4e669dce55ad0e7588062968c1d76ba4c830c01": "reverse_inner", "0f035685b03df70de81cbdbd4e600f5d2f148f6c02b0e0a73ef96a26e7121f2a_left_env": "1"} \ No newline at end of file diff --git a/resources/tests/game-referee-after-cl21/test_sort.clsp b/resources/tests/game-referee-after-cl21/test_sort.clsp new file mode 100644 index 000000000..8185024d0 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_sort.clsp @@ -0,0 +1,37 @@ + +(mod () + (include *standard-cl-21*) + (include print.clinc) + (include sort.clinc) + (include assert.clinc) + (include deep_compare.clinc) + (include reverse.clinc) + (include prepend.clinc) + (include map.clinc) + (include range.clinc) + (include permutations.clinc) + (include last.clinc) + (include busy.clinc) + + (defun try_list (mylist newlist) + (assert (deep= (print "sorted" (sort (lambda (A B) (deep< A B)) newlist)) mylist) 0) + ) + + (defun try_permuted_list (mylist) + (busy (lambda ((& mylist) newlist) (try_list mylist newlist)) + (print "sort all these" (permutations (print "mylist" mylist))) + 0 + ) + ) + (last + (try_list 0 0) + (try_list (range 15) (range 15)) + (try_list (range 15) (reverse (range 15))) + (try_permuted_list (list -1 -1 0 0 2)) + (busy (lambda (i) (try_permuted_list (print "sortme" (range i)))) + (range 4) + 0 + ) + 1 + ) +) diff --git a/resources/tests/game-referee-after-cl21/test_sort.clvm.hex b/resources/tests/game-referee-after-cl21/test_sort.clvm.hex new file mode 100644 index 000000000..cf5d0409c --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_sort.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff66ffff04ff02ffff04ffff04ffff02ff56ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff7e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ffff02ff4affff04ff02ffff04ffff0104ff80808080ffff04ffff0180ff808080808080ffff04ffff02ff6effff04ff02ffff04ffff04ffff0181ffffff04ffff0181ffffff04ffff0180ffff04ffff0180ffff04ffff0102ffff01808080808080ff80808080ffff04ffff02ff76ffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff010fff80808080ffff04ffff02ff7cffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff010fff80808080ff80808080ff8080808080ffff04ffff02ff76ffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff010fff80808080ffff04ffff02ff4affff04ff02ffff04ffff010fff80808080ff8080808080ffff04ffff02ff76ffff04ff02ffff04ffff0180ffff04ffff0180ff8080808080ffff04ffff0101ffff0180808080808080ff80808080ffff04ffff01ffffffffff02ffff03ffff22ffff0187247072696e7424ff05ff0b80ffff01ff02ffff010bff0180ffff01ff02ffff010bff018080ff0180ffff02ffff03ff05ffff01ff02ffff01ff02ff50ffff04ff02ffff04ffff06ff0580ffff04ff17ffff04ffff04ffff05ff0580ff0b80ff808080808080ff0180ffff01ff02ffff01ff06ff0380ff018080ff0180ff02ff50ffff04ff02ffff04ff05ffff01ff80ff8080808080ffffff02ffff03ffff20ff0b80ffff01ff02ffff01ff02ff22ffff04ff02ffff04ffff02ff7cffff04ff02ffff04ff2fff80808080ffff04ff17ff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff20ff1780ffff01ff02ffff01ff02ff22ffff04ff02ffff04ffff02ff7cffff04ff02ffff04ff2fff80808080ffff04ff0bff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff02ff05ffff04ffff05ff0b80ffff04ffff05ff1780ffff0180808080ffff01ff02ffff01ff02ff48ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ffff04ffff04ffff05ff0b80ff2f80ff80808080808080ff0180ffff01ff02ffff01ff02ff48ffff04ff02ffff04ff05ffff04ff0bffff04ffff06ff1780ffff04ffff04ffff05ff1780ff2f80ff80808080808080ff018080ff0180ff018080ff0180ff018080ff0180ff02ff48ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff01ff80808080808080ffff02ffff03ff0bffff01ff02ffff01ff02ffff03ffff06ff0b80ffff01ff02ffff01ff02ff78ffff04ff02ffff04ffff06ff0180ffff04ffff02ff70ffff04ff02ffff04ff0bff80808080ff8080808080ff0180ffff01ff02ffff010bff018080ff0180ff0180ffff01ff02ffff01ff0180ff018080ff0180ff02ff24ffff04ff02ffff04ff03ffff04ffff02ff58ffff04ff02ffff04ff09ffff04ff13ff8080808080ffff04ffff02ff58ffff04ff02ffff04ff09ffff04ff2bff8080808080ff808080808080ffffff02ff68ffff04ff02ffff04ff11ffff04ff0bffff04ff17ff808080808080ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff02ff74ffff04ff02ffff04ffff06ff0180ffff04ffff02ff54ffff04ff02ffff04ffff05ff0580ffff04ffff05ff0b80ff8080808080ff8080808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff0181ffff0180ffff01ff02ffff01ff02ffff03ffff15ff05ff0b80ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff11ffff0180ffff15ff0bff058080ff018080ff0180ff018080ff0180ff018080ff0180ff02ffff03ff0bffff01ff02ffff010bff0180ffff01ff02ffff01ff02ff54ffff04ff02ffff04ffff06ff0980ffff04ffff06ff1580ff8080808080ff018080ff0180ffffff09ffff02ff54ffff04ff02ffff04ff05ffff04ff0bff8080808080ffff0181ff80ff09ffff02ff54ffff04ff02ffff04ff05ffff04ff0bff8080808080ff8080ffff02ffff03ff0bffff01ff02ffff01ff02ff5cffff04ff02ffff04ffff04ffff05ff0b80ff0580ffff04ffff06ff0b80ff8080808080ff0180ffff01ff02ffff0105ff018080ff0180ff02ff5cffff04ff02ffff04ff80ffff04ff05ff8080808080ffffffff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff22ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ffff02ffff03ff0bffff01ff02ffff01ff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff02ff52ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff80808080808080ff0180ffff01ff02ffff0117ff018080ff0180ff02ffff03ffff09ff05ff0b80ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff04ff05ffff02ff72ffff04ff02ffff04ffff10ff05ffff010180ffff04ff0bff808080808080ff018080ff0180ffffff02ff72ffff04ff02ffff04ff80ffff04ff05ff8080808080ff02ffff03ffff20ff0b80ffff01ff02ffff0117ff0180ffff01ff02ffff01ff02ff5affff04ff02ffff04ffff06ff0180ffff04ffff06ff0b80ffff04ffff05ff0b80ff808080808080ff018080ff0180ffff02ff52ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff7a80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff17ff808080ffff01ff01808080ff80808080ffff04ffff02ff46ffff04ff02ffff04ffff02ff22ffff04ff02ffff04ff09ffff04ff0bff8080808080ff80808080ffff04ffff02ff6affff04ff02ffff04ffff04ff17ff0980ffff04ff0bffff04ff2dff808080808080ff808080808080ff04ff09ff0b80ffffffff02ffff03ff05ffff01ff02ffff01ff02ff6affff04ff02ffff04ffff0180ffff04ff05ffff04ffff0180ff808080808080ff0180ffff01ff02ffff01ff01ff8080ff018080ff0180ff02ffff03ff0dffff01ff02ffff01ff02ff66ffff04ff02ffff04ff0dff80808080ff0180ffff01ff02ffff0109ff018080ff0180ffff02ffff03ff0bffff01ff02ffff01ff02ff66ffff04ff02ffff04ffff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff04ffff02ff56ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff808080808080ffff01808080ff80808080ff0180ffff01ff02ffff0117ff018080ff0180ff02ffff03ffff02ff6cffff04ff02ffff04ffff02ff20ffff04ff02ffff04ffff0186736f72746564ffff04ffff02ff58ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff4e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ffff04ff0bff8080808080ff8080808080ffff04ff05ff8080808080ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ffffff02ff4cffff04ff02ffff04ff0bffff04ff17ff8080808080ff02ff56ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff5e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff05ff808080ffff01ff01808080ff80808080ffff04ffff02ff20ffff04ff02ffff04ffff018e736f727420616c6c207468657365ffff04ffff02ff46ffff04ff02ffff04ffff02ff20ffff04ff02ffff04ffff01866d796c697374ffff04ff05ff8080808080ff80808080ff8080808080ffff01ff808080808080ffff02ff76ffff04ff02ffff04ff09ffff04ff0bff8080808080ff02ff6effff04ff02ffff04ffff02ff20ffff04ff02ffff04ffff0186736f72746d65ffff04ffff02ff4affff04ff02ffff04ff0bff80808080ff8080808080ff80808080ff018080 diff --git a/resources/tests/game-referee-after-cl21/test_sort.sym b/resources/tests/game-referee-after-cl21/test_sort.sym new file mode 100644 index 000000000..29ae5f0b1 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/test_sort.sym @@ -0,0 +1 @@ +{"6b79b32d680005d302468e9d2c1592335cee3e4e0a454c9ede7653eb17b9c26d": "deep<", "6a477b54f8811bb3d5111ee9d39d29db7e3cca8f2521efd80f46dcfd9bc0573b_arguments": "(i)", "d2b16ed82a656d685d88e5e248fe3221b20f9082377d1263d95076bda402dd8d": "merge_inner", "e31ef9039be21ebbff9fca105dadf444914415d83cf1f74f6e299ccc760ca58c": "map-with-rest", "131cca40e81a7248781e5edf321f83b96282a9cf4e5ff0151b8dd2fdd5078499_left_env": "1", "1a3f28c2eeaf6c592d86f46dc96c10910a05739bbeda09e147e67fa64927c6f5": "sort", "e9570c55a298e52c75e1ab676bdb601ab3a9939994f3f50be22ce4ebe6a1cc24": "permutations", "ca9b60a19af98d1290d1161582331f43d6518cbe383dcb87452e253773cf9329": "split_inner", "85734bcc0a0243b28bb41bedb69f548a97a473bd3e87b1b5c8acb3a1140ba3d5_left_env": "1", "6a477b54f8811bb3d5111ee9d39d29db7e3cca8f2521efd80f46dcfd9bc0573b_left_env": "1", "7aaf175b403f21a9b93e40356ff378a531810f127922e726506b07915393384f": "reverse_inner", "e31ef9039be21ebbff9fca105dadf444914415d83cf1f74f6e299ccc760ca58c_left_env": "1", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708": "lambda_$_719", "b8b601fdb8fab0e12e98d10b1e8169d4209f502a901b4084e2f2c099065460e7": "deep=", "24c1a323b918bc0b01064cb6171c20899e9d4e4e08a81d7e88013815e7c3fc22_left_env": "1", "bcf06844cee9589ac2df23d9cf5d9a372b71fc3725db9c7249f0db72a2c7fdc3_left_env": "1", "1a3f28c2eeaf6c592d86f46dc96c10910a05739bbeda09e147e67fa64927c6f5_arguments": "(myless mylist)", "d155f473544dcda36e0bfa2a3f1579d2e32e251b1b2683a1a1eb73f919eefef2_left_env": "1", "b1f7d740362f526a0b859fb374c75a41ed23c0e463ae675bf7b4f6176e9cb517": "permutations_inner", "1d6bc99de7f858798725d96803a52ef1fa5cf7315c337ea51e560209f7366de5_arguments": "((next . remainder))", "2d2168734160822b5569309f8541a5b632b035f41c89907e79cb1983fc851a7b_left_env": "1", "b8b601fdb8fab0e12e98d10b1e8169d4209f502a901b4084e2f2c099065460e7_arguments": "(a b)", "02eae9c80ab3ae5e70fcb788e6753ac557297c5b882f6318db705b18b766e872_left_env": "1", "7aaf175b403f21a9b93e40356ff378a531810f127922e726506b07915393384f_left_env": "1", "aff6f9e4b1d082994645068345db6e378e1839b24b4947111b4fd5d77bef5b4b_arguments": "(next final)", "aff6f9e4b1d082994645068345db6e378e1839b24b4947111b4fd5d77bef5b4b_left_env": "1", "24c1a323b918bc0b01064cb6171c20899e9d4e4e08a81d7e88013815e7c3fc22": "merge", "02eae9c80ab3ae5e70fcb788e6753ac557297c5b882f6318db705b18b766e872": "letbinding_$_717", "5b656ea16b982e0b3da35bd883c9ff6407dadbbf05faeca2d53f4348dad67679_left_env": "1", "2a7aff98de69b1fef1b6bc350cb81e2dd99d40254e7f541ef22f8837937ffdbb_arguments": "(myfunc mylist returnval)", "6b79b32d680005d302468e9d2c1592335cee3e4e0a454c9ede7653eb17b9c26d_arguments": "(a b)", "cff048daaf258f18d48b6c65fe30a7391599f4689e75b054472943dee16c5904_arguments": "((pre_$_686 post_$_687 agg_$_688) newrest_$_690 myatom_$_689)", "d155f473544dcda36e0bfa2a3f1579d2e32e251b1b2683a1a1eb73f919eefef2": "letbinding_$_716", "d2586583545bb886183ab7b08b5c6561b6fdd931d8ee8e12b993d114579e6219": "try_list", "d76bbcd6d3800803e66cb762aa942d5836553c18a50638e3dfcf3deca86f4141_arguments": "(mylist)", "962986191da6874f39aeb123a2daa2d87bd1d8a68f612e83d33070a0315fa3d7_arguments": "(() i_$_713)", "1d6bc99de7f858798725d96803a52ef1fa5cf7315c337ea51e560209f7366de5_left_env": "1", "b1f7d740362f526a0b859fb374c75a41ed23c0e463ae675bf7b4f6176e9cb517_arguments": "(pre post agg)", "e31ef9039be21ebbff9fca105dadf444914415d83cf1f74f6e299ccc760ca58c_arguments": "(F L R)", "c5bd34dcdeed87a6c78ea6b36052df8f96895a13a69b4179c15faf9f83ba4560": "lambda_$_721", "cff048daaf258f18d48b6c65fe30a7391599f4689e75b054472943dee16c5904_left_env": "1", "042c55b626937b8d6be258a97f8d25cdedeee2e712dbddef9438fa900eff883e": "print", "b8b601fdb8fab0e12e98d10b1e8169d4209f502a901b4084e2f2c099065460e7_left_env": "1", "042c55b626937b8d6be258a97f8d25cdedeee2e712dbddef9438fa900eff883e_left_env": "1", "bcf06844cee9589ac2df23d9cf5d9a372b71fc3725db9c7249f0db72a2c7fdc3_arguments": "(vals)", "d76bbcd6d3800803e66cb762aa942d5836553c18a50638e3dfcf3deca86f4141": "split", "2d2168734160822b5569309f8541a5b632b035f41c89907e79cb1983fc851a7b_arguments": "((myless_$_649 mylist_$_650) (a_$_651 b_$_652))", "27306e11834170f40679ff25b0e24deeb74c7a9b32495134103d6f952600b48d_arguments": "(a b)", "85734bcc0a0243b28bb41bedb69f548a97a473bd3e87b1b5c8acb3a1140ba3d5_arguments": "(() A_$_709 B_$_710)", "c5bd34dcdeed87a6c78ea6b36052df8f96895a13a69b4179c15faf9f83ba4560_left_env": "1", "d76bbcd6d3800803e66cb762aa942d5836553c18a50638e3dfcf3deca86f4141_left_env": "1", "d2b16ed82a656d685d88e5e248fe3221b20f9082377d1263d95076bda402dd8d_left_env": "1", "1a3f28c2eeaf6c592d86f46dc96c10910a05739bbeda09e147e67fa64927c6f5_left_env": "1", "6b79b32d680005d302468e9d2c1592335cee3e4e0a454c9ede7653eb17b9c26d_left_env": "1", "bcf06844cee9589ac2df23d9cf5d9a372b71fc3725db9c7249f0db72a2c7fdc3": "reverse", "5b656ea16b982e0b3da35bd883c9ff6407dadbbf05faeca2d53f4348dad67679": "prepend", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708_arguments": "((myatom_$_689) x_$_691)", "ca9b60a19af98d1290d1161582331f43d6518cbe383dcb87452e253773cf9329_left_env": "1", "042c55b626937b8d6be258a97f8d25cdedeee2e712dbddef9438fa900eff883e_arguments": "(R P)", "2a7aff98de69b1fef1b6bc350cb81e2dd99d40254e7f541ef22f8837937ffdbb_left_env": "1", "1d6bc99de7f858798725d96803a52ef1fa5cf7315c337ea51e560209f7366de5": "last_inner", "131cca40e81a7248781e5edf321f83b96282a9cf4e5ff0151b8dd2fdd5078499": "try_permuted_list", "02eae9c80ab3ae5e70fcb788e6753ac557297c5b882f6318db705b18b766e872_arguments": "((a_$_657 b_$_658) inner_result_$_659)", "d2b16ed82a656d685d88e5e248fe3221b20f9082377d1263d95076bda402dd8d_arguments": "(myless A B agg)", "cff048daaf258f18d48b6c65fe30a7391599f4689e75b054472943dee16c5904": "letbinding_$_718", "962986191da6874f39aeb123a2daa2d87bd1d8a68f612e83d33070a0315fa3d7": "lambda_$_714", "e9570c55a298e52c75e1ab676bdb601ab3a9939994f3f50be22ce4ebe6a1cc24_arguments": "(vals)", "e9570c55a298e52c75e1ab676bdb601ab3a9939994f3f50be22ce4ebe6a1cc24_left_env": "1", "d2586583545bb886183ab7b08b5c6561b6fdd931d8ee8e12b993d114579e6219_arguments": "(mylist newlist)", "85734bcc0a0243b28bb41bedb69f548a97a473bd3e87b1b5c8acb3a1140ba3d5": "lambda_$_720", "d155f473544dcda36e0bfa2a3f1579d2e32e251b1b2683a1a1eb73f919eefef2_arguments": "(((myless_$_649 mylist_$_650) (a_$_651 b_$_652)) sa_$_653 sb_$_654)", "27306e11834170f40679ff25b0e24deeb74c7a9b32495134103d6f952600b48d_left_env": "1", "source_file": "/home/arty/dev/chia/clvm_tools_rs/resources/tests/game-referee-after-cl21/test_sort.clsp", "__chia__main_arguments": "()", "2d2168734160822b5569309f8541a5b632b035f41c89907e79cb1983fc851a7b": "letbinding_$_715", "c5bd34dcdeed87a6c78ea6b36052df8f96895a13a69b4179c15faf9f83ba4560_arguments": "((mylist_$_711) newlist_$_712)", "ca9b60a19af98d1290d1161582331f43d6518cbe383dcb87452e253773cf9329_arguments": "(@ everything (rest aggl aggr))", "5b656ea16b982e0b3da35bd883c9ff6407dadbbf05faeca2d53f4348dad67679_arguments": "(a b)", "2a7aff98de69b1fef1b6bc350cb81e2dd99d40254e7f541ef22f8837937ffdbb": "busy", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708_left_env": "1", "27306e11834170f40679ff25b0e24deeb74c7a9b32495134103d6f952600b48d": "deep_compare", "131cca40e81a7248781e5edf321f83b96282a9cf4e5ff0151b8dd2fdd5078499_arguments": "(mylist)", "24c1a323b918bc0b01064cb6171c20899e9d4e4e08a81d7e88013815e7c3fc22_arguments": "(myless a b)", "aff6f9e4b1d082994645068345db6e378e1839b24b4947111b4fd5d77bef5b4b": "range_inner", "7aaf175b403f21a9b93e40356ff378a531810f127922e726506b07915393384f_arguments": "(reversed rest)", "6a477b54f8811bb3d5111ee9d39d29db7e3cca8f2521efd80f46dcfd9bc0573b": "range", "d2586583545bb886183ab7b08b5c6561b6fdd931d8ee8e12b993d114579e6219_left_env": "1", "962986191da6874f39aeb123a2daa2d87bd1d8a68f612e83d33070a0315fa3d7_left_env": "1", "b1f7d740362f526a0b859fb374c75a41ed23c0e463ae675bf7b4f6176e9cb517_left_env": "1"} \ No newline at end of file diff --git a/resources/tests/game-referee-after-cl21/testnoncegame.py b/resources/tests/game-referee-after-cl21/testnoncegame.py new file mode 100644 index 000000000..3b4cd2c2a --- /dev/null +++ b/resources/tests/game-referee-after-cl21/testnoncegame.py @@ -0,0 +1,33 @@ +import hashlib + +from hsms.streamables.program import Program + +from clvm.EvalError import EvalError + +noncegame = Program.from_bytes(bytes.fromhex(open("noncegame.clvm.hex").read())) +noncehash = noncegame.tree_hash() + +def drun(prog: Program, args: Program): + try: + return prog.run(args) + except EvalError as ee: + print(f"brun -x -y main.sym {prog} {Program.to(args)}") + raise + +def testnonce(startnonce, maxnonce): + for i in range(startnonce, maxnonce): + mygame = noncegame.curry(i, noncehash) + good_parameters = [i*2, noncegame.curry(i+1, noncehash).tree_hash(), 1, (i*4, b'g')] + bad_parameters = [i*3, noncegame.curry(i+2, noncehash).tree_hash(), 2, (i*5, b'g')] + assert drun(mygame, good_parameters) == b'g' + for j in range(len(good_parameters)): + try: + p = list(good_parameters) + p[j] = bad_parameters[j] + mygame.run(p) + assert False + except EvalError as ee: + pass + +if __name__ == '__main__': + testnonce(3, 7) diff --git a/resources/tests/game-referee-after-cl21/testreferee.py b/resources/tests/game-referee-after-cl21/testreferee.py new file mode 100644 index 000000000..01eb53643 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/testreferee.py @@ -0,0 +1,479 @@ +import pytest +from hashlib import sha256 +from contextlib import asynccontextmanager +from chia.clvm.spend_sim import SimClient, SpendSim +from pathlib import Path +from clvm.casts import int_to_bytes, int_from_bytes + +from hsms.streamables.program import Program +from clvm_tools_rs import compile_clvm +from clvm_tools.binutils import disassemble + +from clvm.EvalError import EvalError +from chia.types.mempool_inclusion_status import MempoolInclusionStatus +from chia.util.errors import Err +from dataclasses import dataclass +from typing import Any +from chia_rs import Coin +from chia.types.spend_bundle import SpendBundle +from chia.types.coin_spend import CoinSpend +from blspy import G2Element + +from steprun import diag_run_clvm, compile_module_with_symbols + +compile_module_with_symbols(['.'],'referee.clsp') +referee = Program.from_bytes(bytes.fromhex(open("referee.clvm.hex").read())) +refhash = referee.tree_hash() +compile_module_with_symbols(['.'],'referee_accuse.clsp') +referee_accuse = Program.from_bytes(bytes.fromhex(open("referee_accuse.clvm.hex").read())) +refaccusehash = referee.tree_hash() +compile_clvm('rockpaperscissorsa.clsp', 'rockpaperscissorsa.clvm.hex', ['.']) +MOD_A = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsa.clvm.hex").read())) +compile_clvm('rockpaperscissorsb.clsp', 'rockpaperscissorsb.clvm.hex', ['.']) +MOD_B = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsb.clvm.hex").read())) +compile_clvm('rockpaperscissorsc.clsp', 'rockpaperscissorsc.clvm.hex', ['.']) +MOD_C = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsc.clvm.hex").read())) +compile_clvm('rockpaperscissorsd.clsp', 'rockpaperscissorsd.clvm.hex', ['.']) +MOD_D = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsd.clvm.hex").read())) + +move = 0 +accuse = 1 +timeout = 2 + +def drun(prog: Program, *args: Program): + try: + return prog.run(*args) + except EvalError as ee: + print(f"brun -x -y main.sym {prog} {Program.to(list(args))}") + raise + +def sha(blob:bytes) -> bytes: + return sha256(blob).digest() + +@pytest.fixture(scope="function") +@asynccontextmanager +async def setup_sim() : + sim = await SpendSim.create(db_path=Path("file:db_test?mode=memory&cache=shared")) + sim_client = SimClient(sim) + await sim.farm_block() + + try: + yield sim, sim_client + finally: + await sim.close() + +def bootstrap_referee(parent_coin_id, initial_validation_program_hash, initial_split, + amount, timeout, max_move_size, mover_puzzle, waiter_puzzle): + """ + returns referee_wrap + """ + puzzle_hash = referee.curry( + [initial_validation_program_hash, 0, initial_split, amount, timeout, max_move_size, mover_puzzle.tree_hash(), + waiter_puzzle.tree_hash(), referee.tree_hash()]).tree_hash() + coin = Coin(parent_coin_id, puzzle_hash, amount) + return RefereeWrap(coin, bytes(32), bytes(32), bytes(32), + initial_validation_program_hash, 0, initial_split, timeout, max_move_size, + mover_puzzle, waiter_puzzle) + +@dataclass +class RefereeWrap: + coin: Any + grandparent_id: Any + parent_validation_program_hash: Any + parent_everything_else_hash: Any + validation_program_hash: Any + move: Any + split: Any + timeout: Any + max_move_size: Any + mover_puzzle: Any + waiter_puzzle: Any + + def curried_parameters_for_our_puzzle(self, purpose, for_self, move_to_make, split, validation_program_hash): + result = Program.to([ + validation_program_hash, + move_to_make, + split, + self.coin.amount, + self.timeout, + self.max_move_size, + self.mover_puzzle.tree_hash() if for_self else self.waiter_puzzle.tree_hash(), + self.waiter_puzzle.tree_hash() if for_self else self.mover_puzzle.tree_hash(), + refhash + ]) + print(f'for {purpose} curried_parameters_for_our_puzzle is {result}') + return result + + def get_puzzle(self): + return referee.curry(self.curried_parameters_for_our_puzzle( + "GET_PUZZLE", + True, + self.move, + self.split, + self.validation_program_hash + )) + + def SpendMove(self, password, move_to_make, split, validation_program_hash): + """ + returns (solution, new RefereeWrap) + """ + print(f"MOVE referee mover_puzzle {self.mover_puzzle.tree_hash()}") + print(f"MOVE referee waiter_puzzle {self.waiter_puzzle.tree_hash()}") + curried_parameters = self.curried_parameters_for_our_puzzle( + "SPEND_MOVE", + False, + move_to_make, + split, + validation_program_hash + ) + print(f"MOVE referee curried parameters {curried_parameters}") + new_puzzle_hash = referee.curry(curried_parameters).tree_hash() + print(f"MOVE new puzzle hash {Program.to(new_puzzle_hash)}") + solution = Program.to([move, move_to_make, split, validation_program_hash, self.mover_puzzle, + [password, [51, new_puzzle_hash, self.coin.amount]]]) + coin = Coin(self.coin.name(), new_puzzle_hash, self.coin.amount) + everything_else_hash = Program.to([self.move, self.split, self.coin.amount, self.timeout, + self.max_move_size, self.mover_puzzle.tree_hash(), self.waiter_puzzle.tree_hash(), + referee.tree_hash()]).tree_hash() + return (solution, RefereeWrap(coin, self.coin.parent_coin_info, self.validation_program_hash, everything_else_hash, + validation_program_hash, move_to_make, split, self.timeout, self.max_move_size, + self.waiter_puzzle, self.mover_puzzle)) + + def SpendAccuse(self, password): + """ + returns (solution, RefereeAccuse) + """ + print(f"ACCUSE starting with puzzle hash {Program.to(self.get_puzzle().tree_hash())}") + print(f"ACCUSE parent_id {Program.to(self.coin.parent_coin_info)}") + print(f"ACCUSE referee mover_puzzle {self.mover_puzzle.tree_hash()}") + print(f"ACCUSE referee waiter_puzzle {self.waiter_puzzle.tree_hash()}") + new_puzzle_hash = referee_accuse.curry([ + self.parent_validation_program_hash, + self.validation_program_hash, + self.move, + self.split, + self.coin.amount, + self.timeout, + self.waiter_puzzle.tree_hash(), + self.mover_puzzle.tree_hash() + ]).tree_hash() + solution = Program.to([accuse, self.grandparent_id, self.parent_validation_program_hash, + self.parent_everything_else_hash, self.mover_puzzle, [password, [51, new_puzzle_hash, self.coin.amount]]]) + coin = Coin(self.coin.name(), new_puzzle_hash, self.coin.amount) + return (solution, RefereeAccuseWrap(coin, self.parent_validation_program_hash, self.validation_program_hash, + self.move, self.split, self.timeout, self.waiter_puzzle.tree_hash(), + self.mover_puzzle.tree_hash())) + + def SpendTimeout(self): + """ + returns (solution, movercoinid, waitercoinid) + """ + movercoinid = Coin(self.coin.name(), self.mover_puzzle.tree_hash(), self.split).name() + waitercoinid = Coin(self.coin.name(), self.waiter_puzzle.tree_hash(), + self.coin.amount - self.split).name() + return (Program.to((timeout, 0)), movercoinid, waitercoinid) + +@dataclass +class RefereeAccuseWrap: + coin: Any + old_validation_puzzle_hash: Any + new_validation_puzzle_hash: Any + move: Any + split: Any + timeout: Any + accused_puzzle_hash: Any + accuser_puzzle_hash: Any + + def get_puzzle(self): + return referee_accuse.curry([self.old_validation_puzzle_hash, self.new_validation_puzzle_hash, + self.move, self.split, self.coin.amount, self.timeout, self.accused_puzzle_hash, + self.accuser_puzzle_hash]) + + def SpendTimeout(self): + """ + returns (solution, coinid) + """ + coin = Coin(self.coin.name(), self.accuser_puzzle_hash, self.coin.amount) + return (Program.to(0), coin.name()) + + def SpendDefend(self, validation_program_reveal, validation_program_solution): + """ + returns (solution, coinid) + """ + solution = Program.to([validation_program_reveal, validation_program_solution]) + coin = Coin(self.coin.name(), self.accused_puzzle_hash, self.coin.amount) + return (solution, coin.name()) + +@pytest.mark.asyncio +@pytest.mark.parametrize('amove', [0, 1, 2]) +@pytest.mark.parametrize('bmove', [0, 1, 2]) +async def test_rps(amove, bmove, setup_sim): + total = 100 + alice_final = (total//2 if amove == bmove else (0 if bmove == (amove + 1) % 3 else total)) + alice_preimage = int_to_bytes(60 + amove) + alice_image = sha(alice_preimage) + bob_preimage = int_to_bytes(60 + bmove) + bob_image = sha(bob_preimage) + alice_move = int_to_bytes(amove) + nil = Program.to(0) + + # (mod (password . conditions) (if (= password 'alice') conditions (x))) + alice_puzzle = Program.from_bytes(bytes.fromhex('ff02ffff03ffff09ff02ffff0185616c69636580ffff0103ffff01ff088080ff0180')) + alice_puzzle_hash = alice_puzzle.tree_hash() + # (mod (password . conditions) (if (= password 'bob') conditions (x))) + bob_puzzle = Program.from_bytes(bytes.fromhex('ff02ffff03ffff09ff02ffff0183626f6280ffff0103ffff01ff088080ff0180')) + bob_puzzle_hash = bob_puzzle.tree_hash() + + async with setup_sim as (sym, client): + acs = Program.to(1) + acs_hash = acs.tree_hash() + await sym.farm_block(acs_hash) + mycoin = (await client.get_coin_records_by_puzzle_hashes([acs_hash], include_spent_coins = False))[0].coin + # make a coin for a game + referee = bootstrap_referee(mycoin.name(), MOD_A.tree_hash(), 2, total, 1000, 50, alice_puzzle, bob_puzzle) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(mycoin, acs, Program.to([[51, referee.coin.puzzle_hash, + referee.coin.amount]]))], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + savepoint = sym.block_height + # Alice accuse Bob of cheating (negative test, should fail) + solution, accuse = referee.SpendAccuse('alice') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(referee.coin, referee.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.ASSERT_MY_PARENT_ID_FAILED + # timeout too early fail + solution, alice_reward_id, bob_reward_id = referee.SpendTimeout() + spend = SpendBundle([CoinSpend(referee.coin, referee.get_puzzle(), solution)], G2Element()) + (status, err) = await client.push_tx(spend) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.ASSERT_SECONDS_RELATIVE_FAILED + # timeout succeeds + sym.pass_time(2000) + await sym.farm_block() + (status, err) = await client.push_tx(spend) + assert status == MempoolInclusionStatus.SUCCESS + assert err is None + await sym.farm_block() + assert (await client.get_coin_records_by_names([alice_reward_id], include_spent_coins = False))[0].coin.amount == 2 + assert (await client.get_coin_records_by_names([bob_reward_id], include_spent_coins = False))[0].coin.amount == total - 2 + await sym.rewind(savepoint) + # Alice makes an illegally large move, fails + solution, ref2 = referee.SpendMove('alice', bytes(100), 0, bytes(32)) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(referee.coin, referee.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + # Alice makes move with negative split, fails + solution, ref2 = referee.SpendMove('alice', 'abc', -1, bytes(32)) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(referee.coin, referee.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + # Alice makes move with split greater than amount, fails + solution, ref2 = referee.SpendMove('alice', 'abc', referee.coin.amount + 1, bytes(32)) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(referee.coin, referee.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + # Alice move 1 commit to image + bpuz = MOD_B.curry(alice_image) + solution, ref2 = referee.SpendMove('alice', alice_image, 0, bpuz.tree_hash()) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(referee.coin, referee.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + savepoint = sym.block_height + # Bob accuse Alice of cheating + solution, accuse = ref2.SpendAccuse('bob') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref2.coin, ref2.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + savepoint2 = sym.block_height + # Alice accusation defend, gets everything + solution, reward_id = accuse.SpendDefend(MOD_A, nil) + print(solution) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + reward_coin_wrapper = await client.get_coin_records_by_names([reward_id], include_spent_coins = + False) + reward_coin = reward_coin_wrapper[0].coin + assert reward_coin.amount == referee.coin.amount + assert reward_coin.puzzle_hash == alice_puzzle_hash + await sym.rewind(savepoint2) + # accusation timeout too early fail + solution, reward_id = accuse.SpendTimeout() + spend = SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), solution)], G2Element()) + (status, err) = await client.push_tx(spend) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.ASSERT_SECONDS_RELATIVE_FAILED + # accusation timeout succeed, Bob gets everything + sym.pass_time(2000) + await sym.farm_block() + (status, err) = await client.push_tx(spend) + assert status == MempoolInclusionStatus.SUCCESS + assert err is None + await sym.farm_block() + reward_coin_wrapper = await client.get_coin_records_by_names([reward_id], include_spent_coins = + False) + reward_coin = reward_coin_wrapper[0].coin + assert reward_coin.amount == referee.coin.amount + assert reward_coin.puzzle_hash == bob_puzzle_hash + await sym.rewind(savepoint) + # Bob move 2 commit to image + cpuz = MOD_C.curry([alice_image, bob_image]) + solution, ref3 = ref2.SpendMove('bob', bob_image, 0, cpuz.tree_hash()) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref2.coin, ref2.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + savepoint = sym.block_height + # Alice accuse + solution, accuse = ref3.SpendAccuse('alice') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref3.coin, ref3.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Bob defends + solution, reward_id = accuse.SpendDefend(bpuz, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + reward_coin = (await client.get_coin_records_by_names([reward_id], include_spent_coins = + False))[0].coin + assert reward_coin.amount == referee.coin.amount + assert reward_coin.puzzle_hash == bob_puzzle_hash + await sym.rewind(savepoint) + # Alice reveals wrong preimage + alice_bad_preimage = int_to_bytes(61 + amove) + dpuz = MOD_D.curry([(amove + 1) % 3, bob_image]) + solution, ref4 = ref3.SpendMove('alice', alice_bad_preimage, 0, dpuz.tree_hash()) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref3.coin, ref3.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Bob accuses + solution, accuse = ref4.SpendAccuse('bob') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref4.coin, ref4.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Alice defends, fails + solution, reward_id = accuse.SpendDefend(cpuz, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + await sym.rewind(savepoint) + # Alice move 3 reveal preimage + dpuz = MOD_D.curry([alice_move, bob_image]) + solution, ref4 = ref3.SpendMove('alice', alice_preimage, 0, dpuz.tree_hash()) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref3.coin, ref3.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + savepoint = sym.block_height + # Bob accuses + solution, accuse = ref4.SpendAccuse('bob') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref4.coin, ref4.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Alice defends + solution, reward_id = accuse.SpendDefend(cpuz, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.rewind(savepoint) + # Bob move 4 reveal wrong preimage + bob_bad_preimage = int_to_bytes(121 + amove) + solution, ref5 = ref4.SpendMove('bob', bob_bad_preimage, 0, dpuz.tree_hash()) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref4.coin, ref4.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Alice accuses + solution, accuse = ref5.SpendAccuse('alice') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref5.coin, ref5.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Bob attempts defense, fails + solution, reward_id = accuse.SpendDefend(dpuz, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + # Bob attempts defense with wrong validation program, fails + solution, reward_id = accuse.SpendDefend(acs, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + await sym.rewind(savepoint) + if amove == bmove: + # Bob move 4 gives wrong split + solution, ref5 = ref4.SpendMove('bob', bob_preimage, 0, dpuz.tree_hash()) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref4.coin, ref4.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Alice accuses + solution, accuse = ref5.SpendAccuse('alice') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref5.coin, ref5.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Bob attempts defense, fails + solution, reward_id = accuse.SpendDefend(dpuz, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + await sym.rewind(savepoint) + # Bob move 4 reveal preimage + solution, ref5 = ref4.SpendMove('bob', bob_preimage, alice_final, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref4.coin, ref4.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + savepoint = sym.block_height + # Alice attempts move, fails + solution, ref6 = ref5.SpendMove('alice', nil, 0, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref5.coin, ref5.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + # timeout, split correct + sym.pass_time(2000) + await sym.farm_block() + solution, alice_reward_id, bob_reward_id = ref5.SpendTimeout() + spend = SpendBundle([CoinSpend(ref5.coin, ref5.get_puzzle(), solution)], G2Element()) + (status, err) = await client.push_tx(spend) + assert status == MempoolInclusionStatus.SUCCESS + assert err is None + await sym.farm_block() + if alice_final != 0: + assert (await client.get_coin_records_by_names([alice_reward_id], include_spent_coins = False))[0].coin.amount == alice_final + else: + assert len(await client.get_coin_records_by_names([alice_reward_id], include_spent_coins = False)) == 0 + if alice_final != ref5.coin.amount: + assert (await client.get_coin_records_by_names([bob_reward_id], include_spent_coins = False))[0].coin.amount == ref5.coin.amount - alice_final + else: + assert len(await client.get_coin_records_by_names([bob_reward_id], include_spent_coins = False)) == 0 + await sym.rewind(savepoint) + # Alice accuses + solution, accuse = ref5.SpendAccuse('alice') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref5.coin, ref5.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Bob defends + solution, reward_id = accuse.SpendDefend(dpuz, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert (status, err) == (MempoolInclusionStatus.SUCCESS, None) diff --git a/resources/tests/game-referee-after-cl21/testrockpaperscissors.py b/resources/tests/game-referee-after-cl21/testrockpaperscissors.py new file mode 100644 index 000000000..ed45dbccc --- /dev/null +++ b/resources/tests/game-referee-after-cl21/testrockpaperscissors.py @@ -0,0 +1,48 @@ +import hashlib + +from hsms.streamables.program import Program +from hsms.puzzles.load_clvm import load_clvm + +from clvm.EvalError import EvalError + + +MOD_A = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsa.clvm.hex").read())) +MOD_B = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsb.clvm.hex").read())) +MOD_C = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsc.clvm.hex").read())) +MOD_D = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsd.clvm.hex").read())) + + +def drun(prog: Program, *args: Program): + try: + return prog.run(*args) + except EvalError as ee: + print(f"brun -x -y main.sym {prog} {Program.to(list(args))}") + raise + +def sha256(blob:bytes) -> bytes: + return hashlib.sha256(blob).digest() + +def testrps(amove, bmove): + total = 100 + alice_final = (total//2 if amove == bmove else (0 if bmove == (amove + 1) % 3 else total)) + alice_preimage = Program.to(60 + amove) + bob_preimage = Program.to(60 + bmove) + alice_image = sha256(alice_preimage.atom) + bob_image = sha256(bob_preimage.atom) + alice_move = Program.to(amove) + + cd = MOD_D.curry(alice_move, bob_image) + assert cd.run([total, bob_preimage, b'', alice_final, b'j']).atom == b'j' + cc = MOD_C.curry(alice_image, bob_image) + assert cc.run([total, alice_preimage, cd.tree_hash(), 0, b'j']).atom == b'j' + cb = MOD_B.curry(alice_image) + assert cb.run([total, bob_image, cc.tree_hash(), 0, b'j']).atom == b'j' + assert MOD_A.run([total, alice_image, cb.tree_hash(), 0, b'j']).atom == b'j' + +def testall(): + for i in range(3): + for j in range(3): + testrps(i, j) + +if __name__ == '__main__': + testall() diff --git a/resources/tests/game-referee-after-cl21/utils.clinc b/resources/tests/game-referee-after-cl21/utils.clinc new file mode 100644 index 000000000..7d754e001 --- /dev/null +++ b/resources/tests/game-referee-after-cl21/utils.clinc @@ -0,0 +1,17 @@ +( + (defmacro ifc ARGS + (defun list-length (lst) + (if (l lst) + (+ 1 (list-length (r lst))) + 0 + ) + ) + (defun do-continued-if (ARGS) + (if (= (list-length ARGS) 3) + (qq (i (unquote (f ARGS)) (com (unquote (f (r ARGS)))) (com (unquote (f (r (r ARGS))))))) + (qq (i (unquote (f ARGS)) (com (unquote (f (r ARGS)))) (unquote (do-continued-if (r (r ARGS)))))) + ) + ) + (qq (a (unquote (do-continued-if ARGS)) @)) + ) +) diff --git a/resources/tests/game-referee-in-cl21/all-in-list.clinc b/resources/tests/game-referee-in-cl21/all-in-list.clinc new file mode 100644 index 000000000..1db5f26ad --- /dev/null +++ b/resources/tests/game-referee-in-cl21/all-in-list.clinc @@ -0,0 +1,12 @@ +( + (defun enquote-rest (L) + (if L + (c (c 1 (f L)) (enquote-rest (r L))) + () + ) + ) + + (defun all-in-list (L) + (a (c 34 (enquote-rest L)) ()) + ) +) diff --git a/resources/tests/game-referee-in-cl21/assert.clinc b/resources/tests/game-referee-in-cl21/assert.clinc new file mode 100644 index 000000000..c9f212394 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/assert.clinc @@ -0,0 +1,8 @@ +( + (defmacro assert items + (if (r items) + (list if (f items) (c assert (r items)) (q . (x))) + (f items) + ) + ) +) diff --git a/resources/tests/game-referee-in-cl21/busy.clinc b/resources/tests/game-referee-in-cl21/busy.clinc new file mode 100644 index 000000000..e534d2125 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/busy.clinc @@ -0,0 +1,11 @@ +( + (defun busy (myfunc mylist returnval) + (if mylist + (last + (a myfunc (list (f mylist))) + (busy myfunc (r mylist) returnval) + ) + returnval + ) + ) +) diff --git a/resources/tests/game-referee-in-cl21/condition_codes.clinc b/resources/tests/game-referee-in-cl21/condition_codes.clinc new file mode 100644 index 000000000..45f3265da --- /dev/null +++ b/resources/tests/game-referee-in-cl21/condition_codes.clinc @@ -0,0 +1,41 @@ +; See chia/types/condition_opcodes.py + +( + (defconstant AGG_SIG_UNSAFE 49) + (defconstant AGG_SIG_ME 50) + + ; the conditions below reserve coin amounts and have to be accounted for in output totals + + (defconstant CREATE_COIN 51) + (defconstant RESERVE_FEE 52) + + ; the conditions below deal with announcements, for inter-coin communication + + ; coin announcements + (defconstant CREATE_COIN_ANNOUNCEMENT 60) + (defconstant ASSERT_COIN_ANNOUNCEMENT 61) + + ; puzzle announcements + (defconstant CREATE_PUZZLE_ANNOUNCEMENT 62) + (defconstant ASSERT_PUZZLE_ANNOUNCEMENT 63) + + ; the conditions below let coins inquire about themselves + + (defconstant ASSERT_MY_COIN_ID 70) + (defconstant ASSERT_MY_PARENT_ID 71) + (defconstant ASSERT_MY_PUZZLEHASH 72) + (defconstant ASSERT_MY_AMOUNT 73) + + ; the conditions below ensure that we're "far enough" in the future + + ; wall-clock time + (defconstant ASSERT_SECONDS_RELATIVE 80) + (defconstant ASSERT_SECONDS_ABSOLUTE 81) + + ; block index + (defconstant ASSERT_HEIGHT_RELATIVE 82) + (defconstant ASSERT_HEIGHT_ABSOLUTE 83) + + ; A condition that is always true and always ignore all arguments + (defconstant REMARK 1) +) diff --git a/resources/tests/game-referee-in-cl21/curry-and-treehash.clinc b/resources/tests/game-referee-in-cl21/curry-and-treehash.clinc new file mode 100644 index 000000000..6a63e9364 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/curry-and-treehash.clinc @@ -0,0 +1,92 @@ +( + ;; The code below is used to calculate of the tree hash of a curried function + ;; without actually doing the curry, and using other optimization tricks + ;; like unrolling `shatree`. + + (defconstant ONE 1) + (defconstant TWO 2) + (defconstant A_KW #a) + (defconstant Q_KW #q) + (defconstant C_KW #c) + + ;; Given the tree hash `environment-hash` of an environment tree E + ;; and the tree hash `parameter-hash` of a constant parameter P + ;; return the tree hash of the tree corresponding to + ;; `(c (q . P) E)` + ;; This is the new environment tree with the addition parameter P curried in. + ;; + ;; Note that `(c (q . P) E)` = `(c . ((q . P) . (E . 0)))` + + (defun-inline update-hash-for-parameter-hash (parameter-hash environment-hash) + (sha256 TWO (sha256 ONE C_KW) + (sha256 TWO (sha256 TWO (sha256 ONE Q_KW) parameter-hash) + (sha256 TWO environment-hash (sha256 ONE 0)))) + ) + + ;; This function recursively calls `update-hash-for-parameter-hash`, updating `environment-hash` + ;; along the way. + + (defun build-curry-list (reversed-curry-parameter-hashes environment-hash) + (if reversed-curry-parameter-hashes + (build-curry-list (r reversed-curry-parameter-hashes) + (update-hash-for-parameter-hash (f reversed-curry-parameter-hashes) environment-hash)) + environment-hash + ) + ) + + ;; Given the tree hash `environment-hash` of an environment tree E + ;; and the tree hash `function-hash` of a function tree F + ;; return the tree hash of the tree corresponding to + ;; `(a (q . F) E)` + ;; This is the hash of a new function that adopts the new environment E. + ;; This is used to build of the tree hash of a curried function. + ;; + ;; Note that `(a (q . F) E)` = `(a . ((q . F) . (E . 0)))` + + (defun-inline tree-hash-of-apply (function-hash environment-hash) + (sha256 TWO (sha256 ONE A_KW) + (sha256 TWO (sha256 TWO (sha256 ONE Q_KW) function-hash) + (sha256 TWO environment-hash (sha256 ONE 0)))) + ) + + ;; function-hash: + ;; the hash of a puzzle function, ie. a `mod` + ;; + ;; reversed-curry-parameter-hashes: + ;; a list of pre-hashed trees representing parameters to be curried into the puzzle. + ;; Note that this must be applied in REVERSED order. This may seem strange, but it greatly simplifies + ;; the underlying code, since we calculate the tree hash from the bottom nodes up, and the last + ;; parameters curried must have their hashes calculated first. + ;; + ;; we return the hash of the curried expression + ;; (a (q . function-hash) (c (cp1 (c cp2 (c ... 1)...)))) + ;; + ;; Note that from a user's perspective the hashes passed in here aren't simply + ;; the hashes of the desired parameters, but their treehash representation since + ;; that's the form we're assuming they take in the actual curried program. + + (defun puzzle-hash-of-curried-function (function-hash . reversed-curry-parameter-hashes) + (tree-hash-of-apply function-hash + (build-curry-list reversed-curry-parameter-hashes (sha256 ONE ONE))) + ) + + (defconstant b32 32) + + (defun-inline size_b32 (var) + (= (strlen var) b32) + ) + + (defun calculate_coin_id (parent puzzlehash amount) + (if (all (size_b32 parent) (size_b32 puzzlehash) (> amount -1)) + (sha256 parent puzzlehash amount) + (x) + ) + ) + + ; takes a lisp tree and returns the hash of it + (defun shatree (TREE) + (if (l TREE) + (sha256 2 (shatree (f TREE)) (shatree (r TREE))) + (sha256 1 TREE))) + +) diff --git a/resources/tests/game-referee-in-cl21/curry.clinc b/resources/tests/game-referee-in-cl21/curry.clinc new file mode 100644 index 000000000..81a1ec3a6 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/curry.clinc @@ -0,0 +1,104 @@ +( + ;; The code below is used to calculate of the tree hash of a curried function + ;; without actually doing the curry, and using other optimization tricks + ;; like unrolling `shatree`. + + (defconstant TWO 2) + (defconstant constant-tree ( + (0x4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a . ; = `(sha256 1)` + 0x9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2) . ; = `(sha256 1 1)` = `(sha256 1 #q)` + (0x02a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222 . ; = `(concat 2 (sha256 1 #a))` + 0x02a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5) ; = `(concat 2 (sha256 1 #c))` + ) + ) + + ; I looked into calculating the values of `constant-tree` because it's pretty easy to code-golf + ; out an implementation that produces the values cheaper than just inlining them. The problem is, + ; when do we calculate them? If there were a way to calculate it "before main" and include it in + ; the globally-accessible constant table, we could do that. But we can't which means to be optimal, + ; client code should call the "build table" code once, then pass it around to anyone that wants to + ; call `curry` or `curry2`. This is pretty intrusive, so for now we'll just use the existing + ; global constant infrastructure, and include it as a fixed table so the tree of four values will + ; appear in all code that includes this file, and it will compress better in generators. + + (defun-inline sha256_one _noargs (f (f constant-tree))) + (defun-inline sha256_one_one _noargs (r (f constant-tree))) + (defun-inline two_sha256_one_a_kw _noargs (f (r constant-tree))) + (defun-inline two_sha256_one_c_kw _noargs (r (r constant-tree))) + + ;; this returns the sha256 tree hash of expression F = `((q . a1) a2)` + (defun hash-expression-F (a1 a2) + (sha256 TWO (sha256 TWO (sha256_one_one) a1) + (sha256 TWO a2 (sha256_one))) + ) + + ;; Given the tree hash `environment-hash` of an environment tree E + ;; and the tree hash `parameter-hash` of a constant parameter P + ;; return the tree hash of the tree corresponding to + ;; `(c (q . P) E)` + ;; This is the new environment tree with the addition parameter P curried in. + ;; + ;; Note that `(c (q . P) E)` = `(c . ((q . P) . (E . 0)))` + + (defun-inline update-hash-for-parameter-hash (parameter-hash environment-hash) + (sha256 (two_sha256_one_c_kw) (hash-expression-F parameter-hash environment-hash)) + ) + + ;; Given the tree hash `environment-hash` of an environment tree E + ;; and the tree hash `mod-hash` of a mod M + ;; return the tree hash of the tree corresponding to + ;; `(a (q . M) E)` + ;; This is the hash of a new function that adopts the new environment E. + ;; This is used to build of the tree hash of a curried function. + ;; + ;; Note that `(a (q . M) E)` = `(a . ((q . M) . (E . 0)))` + + (defun-inline tree-hash-of-apply (mod-hash environment-hash) + (sha256 (two_sha256_one_a_kw) (hash-expression-F mod-hash environment-hash)) + ) + + ;; This function recursively calls `update-hash-for-parameter-hash` + + (defun calculate-hash-of-curried-parameters (curry-parameter-hashes) + (if curry-parameter-hashes + (update-hash-for-parameter-hash (f curry-parameter-hashes) (calculate-hash-of-curried-parameters (r curry-parameter-hashes))) + (sha256_one_one) + ) + ) + + ;; mod-hash: + ;; the hash of a puzzle function, ie. a `mod` + ;; + ;; curry-parameter-hashes: + ;; a list of pre-hashed trees representing parameters to be curried into the puzzle. + ;; + ;; we return the hash of the curried expression + ;; (a (q . mod-hash) (c (cp1 (c cp2 (c ... 1)...)))) + ;; + ;; Note that from a user's perspective the hashes passed in here aren't simply + ;; the hashes of the desired parameters, but their treehash representation since + ;; that's the form we're assuming they take in the acutal curried program. + + ;; inline functions that take varargs don't seem to work, so we can't inline `curry` + + (defun curry_hashes (mod-hash . curry-parameter-hashes) + (tree-hash-of-apply mod-hash + (calculate-hash-of-curried-parameters curry-parameter-hashes)) + ) + + + ;; this is included for future compilers that handle it properly. If you get weird + ;; errors using this, it may be your tooling. Use `curry` above instead, or inline manually. + + (defun-inline curry_hashes_inline (mod-hash . curry-parameter-hashes) + (tree-hash-of-apply mod-hash + (calculate-hash-of-curried-parameters curry-parameter-hashes)) + ) + + ;; `curry_mod_hashes_inline` takes exactly two parameters rather than varags, and it can be inlined + + (defun-inline curry_mod_hashes_inline (mod-hash curry-parameter-hashes) + (tree-hash-of-apply mod-hash + (calculate-hash-of-curried-parameters curry-parameter-hashes)) + ) +) diff --git a/resources/tests/game-referee-in-cl21/deep_compare.clinc b/resources/tests/game-referee-in-cl21/deep_compare.clinc new file mode 100644 index 000000000..0a863ae33 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/deep_compare.clinc @@ -0,0 +1,41 @@ + +( + (defun deep_compare (a b) + (if (l a) + (if (l b) + (assign-lambda inner_result (deep_compare (f a) (f b)) + (if inner_result + inner_result + (deep_compare (r a) (r b)) + ) + ) + 1 + ) + (if (l b) + -1 + (if (> a b) + 1 + (- 0 (> b a)) + ) + ) + ) + ) + (defun deep< (a b) + (= (deep_compare a b) -1) + ) + (defun deep> (a b) + (= (deep_compare a b) 1) + ) + (defun deep= (a b) + (= (deep_compare a b) 0) + ) + (defun deep<= (a b) + (not (deep> a b)) + ) + (defun deep>= (a b) + (not (deep< a b)) + ) + (defun deep!= (a b) + (not (deep= a b)) + ) +) diff --git a/resources/tests/game-referee-in-cl21/filtermap.clinc b/resources/tests/game-referee-in-cl21/filtermap.clinc new file mode 100644 index 000000000..59c827858 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/filtermap.clinc @@ -0,0 +1,14 @@ + +( + (defun filtermap (process remaining init) + (if remaining + (assign next (a process (list (f remaining))) + (if next + (c next (filtermap process (r remaining) init)) + (filtermap process (r remaining) init) + ) + ) + init + ) + ) +) \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl21/flatten.clinc b/resources/tests/game-referee-in-cl21/flatten.clinc new file mode 100644 index 000000000..ab3815abd --- /dev/null +++ b/resources/tests/game-referee-in-cl21/flatten.clinc @@ -0,0 +1,12 @@ +( + (defun flatten_list (everything) + (if + (not everything) 0 + (prepend (f everything) (flatten_list (r everything))) + ) + ) + (defun flatten everything + (flatten_list everything) + ) + +) \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl21/handcalc.clinc b/resources/tests/game-referee-in-cl21/handcalc.clinc new file mode 100644 index 000000000..6317733f4 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/handcalc.clinc @@ -0,0 +1,140 @@ + +; ranks are 2-14 with 2 being two, 13 being king, and 14 being ace +; suits are 1-4 with no particular labelling +; takes a list of cards (rank . suit) and returns the value of the best poker +; hand which can be made with them +; returned list is hand type followed by cards in descending order +; doesn't work for ten or more cards if there are multiple flushes +; all sorting is done highest to lowest +( + (defconstant STRAIGHT_FLUSH 9) + (defconstant FOUR_OF_A_KIND 8) + (defconstant FULL_HOUSE 7) + (defconstant FLUSH 6) + (defconstant STRAIGHT 5) + (defconstant THREE_OF_A_KIND 4) + (defconstant TWO_PAIR 3) + (defconstant PAIR 2) + (defconstant HIGH_CARD 1) + (defun find_flush_inner (suits last count) + (if (not suits) + 0 + (if (= (f suits) last) + (if (= count 4) + last + (find_flush_inner (r suits) last (+ count 1)) + ) + (find_flush_inner (r suits) (f suits) 1) + ) + ) + ) + ; returns the flush suit or 0 if there isn't any + ; suits must be clustered/sorted + (defun find_flush (suits) + (find_flush_inner (sort (lambda (x y) (deep> x y)) suits) 0 0) + ) + (defun straight_high_inner (ranks started_ace last count) + (if (not ranks) + ; at the end of the list + (if (logand (= last 2) (= count 4) started_ace) + ; ace to five + 5 + ; no straight + 0 + ) + (if (= last (f ranks)) + ; skip identical cards + (straight_high_inner (r ranks) started_ace last count) + ; if the partial straight continues + (if (= (f ranks) (- last 1)) + (if (= count 4) + ; found a straight, add 3 to last because next and last are included + (+ last 3) + ; keep looking for a straight with the count going up by one + (straight_high_inner (r ranks) started_ace (f ranks) (+ count 1)) + ) + ; reset the count + (straight_high_inner (r ranks) started_ace (f ranks) 1) + ) + ) + ) + ) + ; returns the high card of a straight or 0 if there isn't any + ; ranks must be sorted in descending order + (defun straight_high (ranks) + (straight_high_inner ranks (= (f ranks) 14) 0 0) + ) + (defun group_by_count_inner (items last count) + (if (not items) + (list (c count last)) + (if (= (f items) last) + (group_by_count_inner (r items) last (+ count 1)) + (assign val (group_by_count_inner (r items) (f items) 1) + (c (c count last) val) + ) + ) + ) + ) + (defun group_by_count (items) + (group_by_count_inner items (f items) 0) + ) + (defun handcalc (cards) + (assign-lambda + first (lambda (x) (f x)) + rest (lambda (x) (r x)) + fsuit (find_flush (map rest cards)) + max_flush (if (not fsuit) + 0 + (assign-lambda + fnosuits + (sort + (lambda (x y) (deep> x y)) + (filtermap + (lambda ((& fsuit) (card_rank . card_suit)) + (if (= fsuit card_suit) + card_rank + 0 + ) + ) + cards + 0 + ) + ) + + fsh (straight_high fnosuits) + (if fsh + (list STRAIGHT_FLUSH fsh) + (c FLUSH (slice fnosuits 5)) + ) + ) + ) + nosuits (sort (lambda (x y) (deep> x y)) (map first cards)) + sh (straight_high nosuits) + max_straight (if sh + (list STRAIGHT sh) + 0 + ) + groups (sort (lambda (x y) (deep> x y)) (group_by_count nosuits)) + (top_count . top_card) (f groups) + (second_count . second_card) (f (r groups)) + topcards (map rest groups) + max_group (if (= top_count 1) + (c HIGH_CARD (slice topcards 5)) + (if (= top_count 2) + (if (= second_count 1) + (c PAIR (slice topcards 4)) + (c TWO_PAIR (slice topcards 3)) + ) + (if (= top_count 3) + (if (= second_count 1) + (c THREE_OF_A_KIND (slice topcards 3)) + (c FULL_HOUSE (slice topcards 2)) + ) + (c FOUR_OF_A_KIND (slice topcards 2)) + ) + ) + ) + (max (lambda (x y) (deep< x y)) (list max_flush max_straight max_group)) + ) + ) +) diff --git a/resources/tests/game-referee-in-cl21/handcalc_a.clinc b/resources/tests/game-referee-in-cl21/handcalc_a.clinc new file mode 100644 index 000000000..06c326392 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/handcalc_a.clinc @@ -0,0 +1,256 @@ + +; ranks are 2-14 with 2 being two, 13 being king, and 14 being ace +; suits are 1-4 with no particular labelling +; takes a list of cards (rank . suit) and returns the value of the best poker +; hand which can be made with them +; returned list is hand type followed by cards in descending order +; doesn't work for ten or more cards if there are multiple flushes +; all sorting is done highest to lowest +( + (defconstant STRAIGHT_FLUSH 9) + (defconstant FOUR_OF_A_KIND 8) + (defconstant FULL_HOUSE 7) + (defconstant FLUSH 6) + (defconstant STRAIGHT 5) + (defconstant THREE_OF_A_KIND 4) + (defconstant TWO_PAIR 3) + (defconstant PAIR 2) + (defconstant HIGH_CARD 1) + (defun hand_compare (a b) + (if (= (f a) (f b)) + (if (r a) + (hand_compare (r a) (r b)) + 0 + ) + (- (* 2 (> (f a) (f b))) 1) + ) + ) + (defun hand< (a b) + (= (hand_compare a b) -1) + ) + (defun merge (a b) + (if (not a) + b + (if (not b) + a + (if (> (f a) (f b)) + (c (f a) (merge (r a) b)) + (c (f b) (merge a (r b))) + ) + ) + ) + ) + ; Sorts atoms into descending order + ; This is optimized for sorting short lists + ; A more general function would return a list of lists of ascending sizes + ; to be merged + (defun atomsort ((@ firstpos (first @ secondpos (second @ thirdpos (third . remaining))))) + (if firstpos + (if secondpos + (if thirdpos + (assign-lambda + mylist + (if (> first second) + (if (> second third) + (list first second third) + (if (> first third) + (list first third second) + (list third first second) + ) + ) + (if (> first third) + (list second first third) + (if (> second third) + (list second third first) + (list third second first) + ) + ) + ) + (merge mylist (atomsort remaining)) + ) + (if (> first second) + firstpos + (list second first) + ) + ) + firstpos + ) + 0 + ) + ) + (defun count_suits_2 ((@ suits (firstsuit . remaining))) + (if (not suits) + (c (c 0 0) (c 0 0)) + (assign-lambda ((@ cd (clubs . diamonds)) . (@ hs (hearts . spades))) (count_suits remaining) + (if (= firstsuit 1) + (c (c (+ clubs 1) diamonds) hs) + (if (= firstsuit 2) + (c (c clubs (+ diamonds 1)) hs) + (if (= firstsuit 3) + (c cd (c (+ hearts 1) spades)) + (c cd (c hearts (+ spades 1))) + ) + ) + ) + ) + ) + ) + (defun find_flush_2 (suits) + (assign-lambda ((clubs . diamonds) . (hearts . spades)) (count_suits suits) + (if (> clubs 4) + 1 + (if (> diamonds 4) + 2 + (if (> hearts 4) + 3 + (if (> spades 4) + 4 + 0 + ) + ) + ) + ) + ) + ) + (defun count_suits (suits) + (if suits + (+ (count_suits (r suits)) (ash 1 (* 4 (- (f suits) 1)))) + 0 + ) + ) + (defun find_flush (suits) + (assign-lambda + myvals (count_suits suits) + (if (> (logand myvals 0xF000) 0x4000) + 4 + (if (> (logand myvals 0x0F00) 0x0400) + 3 + (if (> (logand myvals 0x00F0) 0x0040) + 2 + (if (> (logand myvals 0x0F) 0x04) + 1 + 0 + ) + ) + ) + ) + ) + ) + (defun straight_high_inner (ranks last count) + (if (not ranks) + (if (logand (= last 2) (= count 4)) + ; maybe ace to five + 5 + 0 + ) + (if (= last (f ranks)) + ; skip identical cards + (straight_high_inner (r ranks) last count) + ; if the partial straight continues + (if (= (f ranks) (- last 1)) + (if (= count 4) + ; found a straight, add 3 to last because next and last are included + (+ last 3) + ; keep looking for a straight with the count going up by one + (straight_high_inner (r ranks) (f ranks) (+ count 1)) + ) + ; reset the count + (straight_high_inner (r ranks) (f ranks) 1) + ) + ) + ) + ) + ; returns the high card of a straight or 0 if there isn't any + ; ranks must be sorted in descending order + (defun straight_high (ranks) + (assign-lambda high (straight_high_inner ranks 0 0) + (if (= high 5) + (* (= (f ranks) 14) 5) + high + ) + ) + ) + (defun group_by_count_inner (items last count) + (if (not items) + (list (logior (lsh count 4) last)) + (if (= (f items) last) + (group_by_count_inner (r items) last (+ count 1)) + (assign-inline val (group_by_count_inner (r items) (f items) 1) + (c (logior (lsh count 4) last) val) + ) + ) + ) + ) + (defun group_by_count (items) + (group_by_count_inner items (f items) 0) + ) + (defun handcalc (cards) + (assign-lambda + first (lambda (x) (f x)) + rest (lambda (x) (r x)) + fsuit (find_flush (map rest cards)) + max_flush (if (not fsuit) + (list 0) + (assign-lambda + flushcards + (filtermap + (lambda ((& fsuit) (card_rank . card_suit)) + (if (= fsuit card_suit) + card_rank + 0 + ) + ) + cards + 0 + ) + flushranks (atomsort flushcards) + fsh (straight_high flushranks) + (if fsh + (list STRAIGHT_FLUSH fsh) + (c FLUSH (slice flushranks 5)) + ) + ) + ) + ranks (atomsort (map first cards)) + sh (straight_high ranks) + max_straight (if sh + (list STRAIGHT sh) + (list 0) + ) + groups (map + (lambda (myval) (c (lsh myval -4) (logand myval 0x0F))) + (atomsort (group_by_count ranks)) + ) + (top_count . top_card) (f groups) + (second_count . second_card) (f (r groups)) + topcards (map rest groups) + max_group (if (= top_count 1) + (c HIGH_CARD (slice topcards 5)) + (if (= top_count 2) + (if (= second_count 1) + (c PAIR (slice topcards 4)) + (c TWO_PAIR (slice topcards 3)) + ) + (if (= top_count 3) + (if (= second_count 1) + (c THREE_OF_A_KIND (slice topcards 3)) + (c FULL_HOUSE (slice topcards 2)) + ) + (c FOUR_OF_A_KIND (slice topcards 2)) + ) + ) + ) + ; max of max_flush max_straight and max_group + (if (> (f max_flush) (f max_straight)) + (if (> (f max_flush) (f max_group)) + max_flush + max_group + ) + (if (> (f max_straight) (f max_group)) + max_straight + max_group + ) + ) + ) + ) +) diff --git a/resources/tests/game-referee-in-cl21/last.clinc b/resources/tests/game-referee-in-cl21/last.clinc new file mode 100644 index 000000000..5a6ffd73e --- /dev/null +++ b/resources/tests/game-referee-in-cl21/last.clinc @@ -0,0 +1,39 @@ +( + (defun last_inner ((next . remainder)) + (if remainder + (last_inner remainder) + next + ) + ) + + (defmacro last ARGS + (defun snoc (L agg) + (if L + (if (r L) + (snoc (r L) (c (f L) agg)) + (c (f L) agg) + ) + (c () ()) + ) + ) + + (defun prefix (L P) + (if L + (c (f L) (prefix (r L) P)) + P + ) + ) + + (if ARGS + (if (r ARGS) + (assign + (final . rest) (snoc ARGS ()) + reversed (prefix rest (list final)) + (qq (last_inner (unquote (c list reversed)))) + ) + (qq (last_inner (unquote (f ARGS)))) + ) + (x "Last takes at least one argument") + ) + ) +) diff --git a/resources/tests/game-referee-in-cl21/len.clinc b/resources/tests/game-referee-in-cl21/len.clinc new file mode 100644 index 000000000..407c36694 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/len.clinc @@ -0,0 +1,3 @@ +( + (defun len (L) (if L (+ 1 (len (r L))) 0)) +) diff --git a/resources/tests/game-referee-in-cl21/map.clinc b/resources/tests/game-referee-in-cl21/map.clinc new file mode 100644 index 000000000..016c3a0e4 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/map.clinc @@ -0,0 +1,17 @@ +( + (defun map-with-rest (F L R) + (if L + (c (a F (list (f L))) (map-with-rest F (r L) R)) + R + ) + ) + + (defmacro map ARGS + (defun list-len (X) (if X (+ 1 (list-len (r X))) 0)) + + (if (= (list-len ARGS) 3) + (qq (map-with-rest (unquote (f ARGS)) (unquote (f (r ARGS))) (unquote (f (r (r ARGS)))))) + (qq (map-with-rest (unquote (f ARGS)) (unquote (f (r ARGS))) ())) + ) + ) +) diff --git a/resources/tests/game-referee-in-cl21/match.clinc b/resources/tests/game-referee-in-cl21/match.clinc new file mode 100644 index 000000000..d66593c55 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/match.clinc @@ -0,0 +1,12 @@ + +( + (defun match (process remaining) + (if remaining + (if (a process (list (f remaining))) + (f remaining) + (match process (r remaining)) + ) + 0 + ) + ) +) diff --git a/resources/tests/game-referee-in-cl21/max.clinc b/resources/tests/game-referee-in-cl21/max.clinc new file mode 100644 index 000000000..5ec6d54f6 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/max.clinc @@ -0,0 +1,13 @@ +( + (defun max_inner (myless best_so_far mylist) + (if (not mylist) best_so_far + (if (a myless (list best_so_far (f mylist))) + (max_inner myless (f mylist) (r mylist)) + (max_inner myless best_so_far (r mylist)) + ) + ) + ) + (defun max (myless mylist) + (max_inner myless (f mylist) (r mylist)) + ) +) diff --git a/resources/tests/game-referee-in-cl21/permutations.clinc b/resources/tests/game-referee-in-cl21/permutations.clinc new file mode 100644 index 000000000..9664c6aff --- /dev/null +++ b/resources/tests/game-referee-in-cl21/permutations.clinc @@ -0,0 +1,21 @@ +( + (defun permutations_inner (pre post agg) + (if (not post) + agg + (assign + myatom (f post) + newrest (r post) + (map (lambda ((& myatom) x) (c myatom x)) + (permutations (prepend pre newrest)) + (permutations_inner (c myatom pre) newrest agg) + ) + ) + ) + ) + (defun permutations (vals) + (if vals + (permutations_inner 0 vals 0) + (q ()) + ) + ) +) diff --git a/resources/tests/game-referee-in-cl21/prefix.clinc b/resources/tests/game-referee-in-cl21/prefix.clinc new file mode 100644 index 000000000..641723dad --- /dev/null +++ b/resources/tests/game-referee-in-cl21/prefix.clinc @@ -0,0 +1,16 @@ +( + (defmacro prefix ARGS + (defun compile-list (args) + (if args + (if (r args) + ;; We have at least 2 things left... recurse once. + (qq (c (unquote (f args)) (unquote (compile-list (r args))))) + ;; This is the last item, so we return it whole (improper list form). + (qq (unquote (f args))) + ) + 0 + ) + ) + (compile-list ARGS) + ) +) \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl21/prepend.clinc b/resources/tests/game-referee-in-cl21/prepend.clinc new file mode 100644 index 000000000..2ea293409 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/prepend.clinc @@ -0,0 +1,8 @@ +( + (defun prepend (a b) + (if a + (c (f a) (prepend (r a) b)) + b + ) + ) +) \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl21/print.clinc b/resources/tests/game-referee-in-cl21/print.clinc new file mode 100644 index 000000000..95d459b36 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/print.clinc @@ -0,0 +1,3 @@ +( + (defun print (R P) (if (all "$print$" R P) P P)) +) diff --git a/resources/tests/game-referee-in-cl21/range.clinc b/resources/tests/game-referee-in-cl21/range.clinc new file mode 100644 index 000000000..dc1e61ca3 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/range.clinc @@ -0,0 +1,11 @@ +( + (defun range_inner (next final) + (if (= next final) + 0 + (c next (range_inner (+ next 1) final)) + ) + ) + (defun range (i) + (range_inner 0 i) + ) +) \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl21/reduce.clinc b/resources/tests/game-referee-in-cl21/reduce.clinc new file mode 100644 index 000000000..3251c79a7 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/reduce.clinc @@ -0,0 +1,10 @@ + +( + ; From here to the meat should be in a standard library + (defun reduce (fun lst init) + (if lst + (reduce fun (r lst) (a fun (list (f lst) init))) + init + ) + ) +) diff --git a/resources/tests/game-referee-in-cl21/reverse.clinc b/resources/tests/game-referee-in-cl21/reverse.clinc new file mode 100644 index 000000000..389963ee9 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/reverse.clinc @@ -0,0 +1,11 @@ +( + (defun reverse_inner (reversed rest) + (if rest + (reverse_inner (c (f rest) reversed) (r rest)) + reversed + ) + ) + (defun reverse (vals) + (reverse_inner 0 vals) + ) +) diff --git a/resources/tests/game-referee-in-cl21/shatree.clinc b/resources/tests/game-referee-in-cl21/shatree.clinc new file mode 100644 index 000000000..05bdb2699 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/shatree.clinc @@ -0,0 +1,11 @@ +( + ;; hash a tree + ;; This is used to calculate a puzzle hash given a puzzle program. + (defun shatree + (TREE) + (if (l TREE) + (sha256 2 (shatree (f TREE)) (shatree (r TREE))) + (sha256 1 TREE) + ) + ) +) \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl21/slice.clinc b/resources/tests/game-referee-in-cl21/slice.clinc new file mode 100644 index 000000000..2c98a09c5 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/slice.clinc @@ -0,0 +1,10 @@ + +( + ; returns the first count elements of mylist + (defun slice (mylist count) + (if (print (list "slice inputs" nylist count) (not count)) + 0 + (c (f mylist) (slice (r mylist) (- count 1))) + ) + ) +) diff --git a/resources/tests/game-referee-in-cl21/smoke_test_deep_compare.clsp b/resources/tests/game-referee-in-cl21/smoke_test_deep_compare.clsp new file mode 100644 index 000000000..8df629518 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/smoke_test_deep_compare.clsp @@ -0,0 +1,28 @@ +(mod () + (include *standard-cl-21*) + (include print.clinc) + (include prepend.clinc) + (include sort.clinc) + (include assert.clinc) + (include map.clinc) + (include deep_compare.clinc) + + (map + (lambda ((want_cmp_val cmp_a cmp_b)) + (= (deep_compare cmp_a cmp_b) want_cmp_val) + ) + (q + (0 0 0) + (-1 () (1 14 5 4 3 2)) + (1 (1 14 5 4 3 2) ()) + (-1 "X" (1 2)) + (1 (1 2) "X") + (0 (3 2) (3 2)) + (-1 (3 1) (3 3)) + (1 (3 3) (3 1)) + (-1 (1 1) (2 1)) + (1 (3 1) (2 2)) + (-1 (2 2) (3 1)) + ) + ) + ) diff --git a/resources/tests/game-referee-in-cl21/smoke_test_deep_compare.clvm.hex b/resources/tests/game-referee-in-cl21/smoke_test_deep_compare.clvm.hex new file mode 100644 index 000000000..cb3eb0bf7 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/smoke_test_deep_compare.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff08ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff0e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ffff01ffff80ff80ff8080ffff81ffff80ffff01ff0eff05ff04ff03ff028080ffff01ffff01ff0eff05ff04ff03ff0280ff8080ffff81ffff58ffff01ff028080ffff01ffff01ff0280ff5880ffff80ffff03ff0280ffff03ff028080ffff81ffffff03ff0180ffff03ff038080ffff01ffff03ff0380ffff03ff018080ffff81ffffff01ff0180ffff02ff018080ffff01ffff03ff0180ffff02ff028080ffff81ffffff02ff0280ffff03ff01808080ffff04ffff0180ff808080808080ffff04ffff01ffffff02ffff03ff0bffff01ff02ffff01ff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff02ff08ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff80808080808080ff0180ffff01ff02ffff0117ff018080ff0180ff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff06ff0180ffff04ffff02ff0cffff04ff02ffff04ffff05ff0580ffff04ffff05ff0b80ff8080808080ff8080808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff0181ffff0180ffff01ff02ffff01ff02ffff03ffff15ff05ff0b80ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff11ffff0180ffff15ff0bff058080ff018080ff0180ff018080ff0180ff018080ff0180ffff02ffff03ff0bffff01ff02ffff010bff0180ffff01ff02ffff01ff02ff0cffff04ff02ffff04ffff06ff0980ffff04ffff06ff1580ff8080808080ff018080ff0180ff09ffff02ff0cffff04ff02ffff04ff2bffff04ff5bff8080808080ff1380ff018080 diff --git a/resources/tests/game-referee-in-cl21/smoke_test_deep_compare.clvm.hex.reference b/resources/tests/game-referee-in-cl21/smoke_test_deep_compare.clvm.hex.reference new file mode 100644 index 000000000..cb3eb0bf7 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/smoke_test_deep_compare.clvm.hex.reference @@ -0,0 +1 @@ +ff02ffff01ff02ff08ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff0e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ffff01ffff80ff80ff8080ffff81ffff80ffff01ff0eff05ff04ff03ff028080ffff01ffff01ff0eff05ff04ff03ff0280ff8080ffff81ffff58ffff01ff028080ffff01ffff01ff0280ff5880ffff80ffff03ff0280ffff03ff028080ffff81ffffff03ff0180ffff03ff038080ffff01ffff03ff0380ffff03ff018080ffff81ffffff01ff0180ffff02ff018080ffff01ffff03ff0180ffff02ff028080ffff81ffffff02ff0280ffff03ff01808080ffff04ffff0180ff808080808080ffff04ffff01ffffff02ffff03ff0bffff01ff02ffff01ff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff02ff08ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff80808080808080ff0180ffff01ff02ffff0117ff018080ff0180ff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff06ff0180ffff04ffff02ff0cffff04ff02ffff04ffff05ff0580ffff04ffff05ff0b80ff8080808080ff8080808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff0181ffff0180ffff01ff02ffff01ff02ffff03ffff15ff05ff0b80ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff11ffff0180ffff15ff0bff058080ff018080ff0180ff018080ff0180ff018080ff0180ffff02ffff03ff0bffff01ff02ffff010bff0180ffff01ff02ffff01ff02ff0cffff04ff02ffff04ffff06ff0980ffff04ffff06ff1580ff8080808080ff018080ff0180ff09ffff02ff0cffff04ff02ffff04ff2bffff04ff5bff8080808080ff1380ff018080 diff --git a/resources/tests/game-referee-in-cl21/smoke_test_deep_compare.sym b/resources/tests/game-referee-in-cl21/smoke_test_deep_compare.sym new file mode 100644 index 000000000..3d2e104b3 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/smoke_test_deep_compare.sym @@ -0,0 +1 @@ +{"026e28eecfeb07594300bd6c3bce34bd4fe340a189ddd5312c7361e242b52160_arguments": "(() (want_cmp_val cmp_a cmp_b))", "source_file": "/home/arty/dev/chia/clvm_tools_rs/resources/tests/game-referee-in-cl21/smoke_test_deep_compare.clsp", "__chia__main_arguments": "()", "4fd7e0dfbd7ac5775e6d61670f548dc35ff62a1a4b14f2f3efe09d8b39e6988b_left_env": "1", "a08c534dd3a89e22a8fadaa027c6b9a8dd4f9a00b72c315821703d8ee1c8f687": "deep_compare", "026e28eecfeb07594300bd6c3bce34bd4fe340a189ddd5312c7361e242b52160_left_env": "1", "a08c534dd3a89e22a8fadaa027c6b9a8dd4f9a00b72c315821703d8ee1c8f687_arguments": "(a b)", "d9f6d93919b2fb79bc296ac80d73b5c48bf044e457f0f678b210f990efeea743": "letbinding_$_58", "d9f6d93919b2fb79bc296ac80d73b5c48bf044e457f0f678b210f990efeea743_left_env": "1", "a08c534dd3a89e22a8fadaa027c6b9a8dd4f9a00b72c315821703d8ee1c8f687_left_env": "1", "4fd7e0dfbd7ac5775e6d61670f548dc35ff62a1a4b14f2f3efe09d8b39e6988b": "map-with-rest", "4fd7e0dfbd7ac5775e6d61670f548dc35ff62a1a4b14f2f3efe09d8b39e6988b_arguments": "(F L R)", "d9f6d93919b2fb79bc296ac80d73b5c48bf044e457f0f678b210f990efeea743_arguments": "((a_$_43 b_$_44) inner_result)", "026e28eecfeb07594300bd6c3bce34bd4fe340a189ddd5312c7361e242b52160": "lambda_$_57"} \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl21/smoke_test_permutations.clsp b/resources/tests/game-referee-in-cl21/smoke_test_permutations.clsp new file mode 100644 index 000000000..2ed3fbbcc --- /dev/null +++ b/resources/tests/game-referee-in-cl21/smoke_test_permutations.clsp @@ -0,0 +1,9 @@ +(mod (X) + (include *standard-cl-21*) + (include map.clinc) + (include prepend.clinc) + (include print.clinc) + (include permutations.clinc) + + (permutations X) + ) diff --git a/resources/tests/game-referee-in-cl21/smoke_test_permutations.clvm.hex b/resources/tests/game-referee-in-cl21/smoke_test_permutations.clvm.hex new file mode 100644 index 000000000..813027e6d --- /dev/null +++ b/resources/tests/game-referee-in-cl21/smoke_test_permutations.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff1effff04ff02ffff04ff05ff80808080ffff04ffff01ffffff02ffff03ff0bffff01ff02ffff01ff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff02ff08ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff80808080808080ff0180ffff01ff02ffff0117ff018080ff0180ffff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff14ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff02ffff03ffff20ff0b80ffff01ff02ffff0117ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff06ff0180ffff04ffff06ff0b80ffff04ffff05ff0b80ff808080808080ff018080ff0180ffff02ff08ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff1680ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff17ff808080ffff01ff01808080ff80808080ffff04ffff02ff1effff04ff02ffff04ffff02ff14ffff04ff02ffff04ff09ffff04ff0bff8080808080ff80808080ffff04ffff02ff1cffff04ff02ffff04ffff04ff17ff0980ffff04ff0bffff04ff2dff808080808080ff808080808080ffff04ff09ff0b80ff02ffff03ff05ffff01ff02ffff01ff02ff1cffff04ff02ffff04ffff0180ffff04ff05ffff04ffff0180ff808080808080ff0180ffff01ff02ffff01ff01ff8080ff018080ff0180ff018080 diff --git a/resources/tests/game-referee-in-cl21/smoke_test_permutations.clvm.hex.reference b/resources/tests/game-referee-in-cl21/smoke_test_permutations.clvm.hex.reference new file mode 100644 index 000000000..ad4e2fba6 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/smoke_test_permutations.clvm.hex.reference @@ -0,0 +1 @@ +ff02ffff01ff02ff1effff04ff02ffff04ff05ff80808080ffff04ffff01ffffff02ffff03ff0bffff01ff02ffff01ff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff02ff08ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff80808080808080ff0180ffff01ff02ffff0117ff018080ff0180ffff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff14ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff02ffff03ffff20ff0b80ffff01ff02ffff0117ff0180ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff06ff0180ffff04ffff05ff0b80ffff04ffff06ff0b80ff808080808080ff018080ff0180ffff02ff08ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff1680ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff0bff808080ffff01ff01808080ff80808080ffff04ffff02ff1effff04ff02ffff04ffff02ff14ffff04ff02ffff04ff09ffff04ff17ff8080808080ff80808080ffff04ffff02ff1cffff04ff02ffff04ffff04ff0bff0980ffff04ff17ffff04ff2dff808080808080ff808080808080ffff04ff09ff0b80ff02ffff03ff05ffff01ff02ffff01ff02ff1cffff04ff02ffff04ffff0180ffff04ff05ffff04ffff0180ff808080808080ff0180ffff01ff02ffff01ff01ff8080ff018080ff0180ff018080 diff --git a/resources/tests/game-referee-in-cl21/smoke_test_permutations.sym b/resources/tests/game-referee-in-cl21/smoke_test_permutations.sym new file mode 100644 index 000000000..c53c294de --- /dev/null +++ b/resources/tests/game-referee-in-cl21/smoke_test_permutations.sym @@ -0,0 +1 @@ +{"0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708_arguments": "((myatom) x)", "4fd7e0dfbd7ac5775e6d61670f548dc35ff62a1a4b14f2f3efe09d8b39e6988b": "map-with-rest", "cbc879391ee3747e5a0a6457916b75a38118f0febf74e14983e66c8105ffb9c8": "permutations_inner", "f6344fd0045418e460a57d88fc880464d12fcafb3b3c3adbc52e0e39672bf0c8": "letbinding_$_387", "e209270f1dc5e9d4b9d3c077d401c47f47bb866e87d1707551d101b8717f4edf_arguments": "(vals)", "source_file": "/home/arty/dev/chia/clvm_tools_rs/resources/tests/game-referee-in-cl21/smoke_test_permutations.clsp", "cbc879391ee3747e5a0a6457916b75a38118f0febf74e14983e66c8105ffb9c8_arguments": "(pre post agg)", "048d5413ce5265ab36813735bc75ba7b7c5e9454553198bfdafef009677e420b_arguments": "(a b)", "e209270f1dc5e9d4b9d3c077d401c47f47bb866e87d1707551d101b8717f4edf_left_env": "1", "4fd7e0dfbd7ac5775e6d61670f548dc35ff62a1a4b14f2f3efe09d8b39e6988b_arguments": "(F L R)", "4fd7e0dfbd7ac5775e6d61670f548dc35ff62a1a4b14f2f3efe09d8b39e6988b_left_env": "1", "048d5413ce5265ab36813735bc75ba7b7c5e9454553198bfdafef009677e420b": "prepend", "cbc879391ee3747e5a0a6457916b75a38118f0febf74e14983e66c8105ffb9c8_left_env": "1", "__chia__main_arguments": "(X)", "e209270f1dc5e9d4b9d3c077d401c47f47bb866e87d1707551d101b8717f4edf": "permutations", "f6344fd0045418e460a57d88fc880464d12fcafb3b3c3adbc52e0e39672bf0c8_left_env": "1", "f6344fd0045418e460a57d88fc880464d12fcafb3b3c3adbc52e0e39672bf0c8_arguments": "((pre_$_383 post_$_384 agg_$_385) myatom newrest)", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708": "lambda_$_388", "048d5413ce5265ab36813735bc75ba7b7c5e9454553198bfdafef009677e420b_left_env": "1", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708_left_env": "1"} \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl21/smoke_test_sort.clsp b/resources/tests/game-referee-in-cl21/smoke_test_sort.clsp new file mode 100644 index 000000000..59b8a886e --- /dev/null +++ b/resources/tests/game-referee-in-cl21/smoke_test_sort.clsp @@ -0,0 +1,11 @@ +(mod (X) + (include *standard-cl-21*) + (include prepend.clinc) + (include sort.clinc) + (include assert.clinc) + (include map.clinc) + (include reverse.clinc) + (include print.clinc) + + (sort (lambda (a b) (> b a)) X) + ) diff --git a/resources/tests/game-referee-in-cl21/smoke_test_sort.clvm.hex b/resources/tests/game-referee-in-cl21/smoke_test_sort.clvm.hex new file mode 100644 index 000000000..476b5f74e --- /dev/null +++ b/resources/tests/game-referee-in-cl21/smoke_test_sort.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff12ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff3e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ff05ff8080808080ffff04ffff01ffffffff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff10ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff02ffff03ff05ffff01ff02ffff01ff02ff18ffff04ff02ffff04ffff06ff0580ffff04ff17ffff04ffff04ffff05ff0580ff0b80ff808080808080ff0180ffff01ff02ffff01ff06ff0380ff018080ff0180ffff02ff18ffff04ff02ffff04ff05ffff01ff80ff8080808080ffff02ffff03ffff20ff0b80ffff01ff02ffff01ff02ff10ffff04ff02ffff04ffff02ff2effff04ff02ffff04ff2fff80808080ffff04ff17ff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff20ff1780ffff01ff02ffff01ff02ff10ffff04ff02ffff04ffff02ff2effff04ff02ffff04ff2fff80808080ffff04ff0bff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff02ff05ffff04ffff05ff0b80ffff04ffff05ff1780ffff0180808080ffff01ff02ffff01ff02ff2cffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ffff04ffff04ffff05ff0b80ff2f80ff80808080808080ff0180ffff01ff02ffff01ff02ff2cffff04ff02ffff04ff05ffff04ff0bffff04ffff06ff1780ffff04ffff04ffff05ff1780ff2f80ff80808080808080ff018080ff0180ff018080ff0180ff018080ff0180ff02ff2cffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff01ff80808080808080ffffff02ffff03ff0bffff01ff02ffff01ff02ffff03ffff06ff0b80ffff01ff02ffff01ff02ff2affff04ff02ffff04ffff06ff0180ffff04ffff02ff14ffff04ff02ffff04ff0bff80808080ff8080808080ff0180ffff01ff02ffff010bff018080ff0180ff0180ffff01ff02ffff01ff0180ff018080ff0180ffff02ff3affff04ff02ffff04ff03ffff04ffff02ff12ffff04ff02ffff04ff09ffff04ff13ff8080808080ffff04ffff02ff12ffff04ff02ffff04ff09ffff04ff2bff8080808080ff808080808080ff02ff3cffff04ff02ffff04ff11ffff04ff0bffff04ff17ff808080808080ffff02ffff03ff0bffff01ff02ffff01ff02ff16ffff04ff02ffff04ffff04ffff05ff0b80ff0580ffff04ffff06ff0b80ff8080808080ff0180ffff01ff02ffff0105ff018080ff0180ffff02ff16ffff04ff02ffff04ff80ffff04ff05ff8080808080ff15ff17ff0b80ff018080 diff --git a/resources/tests/game-referee-in-cl21/smoke_test_sort.clvm.hex.reference b/resources/tests/game-referee-in-cl21/smoke_test_sort.clvm.hex.reference new file mode 100644 index 000000000..476b5f74e --- /dev/null +++ b/resources/tests/game-referee-in-cl21/smoke_test_sort.clvm.hex.reference @@ -0,0 +1 @@ +ff02ffff01ff02ff12ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff3e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ff05ff8080808080ffff04ffff01ffffffff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff10ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff02ffff03ff05ffff01ff02ffff01ff02ff18ffff04ff02ffff04ffff06ff0580ffff04ff17ffff04ffff04ffff05ff0580ff0b80ff808080808080ff0180ffff01ff02ffff01ff06ff0380ff018080ff0180ffff02ff18ffff04ff02ffff04ff05ffff01ff80ff8080808080ffff02ffff03ffff20ff0b80ffff01ff02ffff01ff02ff10ffff04ff02ffff04ffff02ff2effff04ff02ffff04ff2fff80808080ffff04ff17ff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff20ff1780ffff01ff02ffff01ff02ff10ffff04ff02ffff04ffff02ff2effff04ff02ffff04ff2fff80808080ffff04ff0bff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff02ff05ffff04ffff05ff0b80ffff04ffff05ff1780ffff0180808080ffff01ff02ffff01ff02ff2cffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ffff04ffff04ffff05ff0b80ff2f80ff80808080808080ff0180ffff01ff02ffff01ff02ff2cffff04ff02ffff04ff05ffff04ff0bffff04ffff06ff1780ffff04ffff04ffff05ff1780ff2f80ff80808080808080ff018080ff0180ff018080ff0180ff018080ff0180ff02ff2cffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff01ff80808080808080ffffff02ffff03ff0bffff01ff02ffff01ff02ffff03ffff06ff0b80ffff01ff02ffff01ff02ff2affff04ff02ffff04ffff06ff0180ffff04ffff02ff14ffff04ff02ffff04ff0bff80808080ff8080808080ff0180ffff01ff02ffff010bff018080ff0180ff0180ffff01ff02ffff01ff0180ff018080ff0180ffff02ff3affff04ff02ffff04ff03ffff04ffff02ff12ffff04ff02ffff04ff09ffff04ff13ff8080808080ffff04ffff02ff12ffff04ff02ffff04ff09ffff04ff2bff8080808080ff808080808080ff02ff3cffff04ff02ffff04ff11ffff04ff0bffff04ff17ff808080808080ffff02ffff03ff0bffff01ff02ffff01ff02ff16ffff04ff02ffff04ffff04ffff05ff0b80ff0580ffff04ffff06ff0b80ff8080808080ff0180ffff01ff02ffff0105ff018080ff0180ffff02ff16ffff04ff02ffff04ff80ffff04ff05ff8080808080ff15ff17ff0b80ff018080 diff --git a/resources/tests/game-referee-in-cl21/smoke_test_sort.sym b/resources/tests/game-referee-in-cl21/smoke_test_sort.sym new file mode 100644 index 000000000..2a0f8ed38 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/smoke_test_sort.sym @@ -0,0 +1 @@ +{"aa2a43f5d1d2ed44bd135ee807b27cb33eea736d2e50b2787c5fd4100f128f47": "letbinding_$_108", "source_file": "/home/arty/dev/chia/clvm_tools_rs/resources/tests/game-referee-in-cl21/smoke_test_sort.clsp", "842642e018168c91bd70ba0be54c311ce3947fe0ce5e418f6a1c88289e11c84b_left_env": "1", "fa9304ef33f250463c38ac3368ad79c5416173e5a666c6571e9b4c5d8b983da1_left_env": "1", "6336806e19a49e9e91a62932f741d94eeca9a3656f35ecf39bc22e15d9940d53_arguments": "(mylist)", "f51796fc523809b04629ca42cffbb3514471eade8cd7d6908f3015f535a97de4": "letbinding_$_107", "842642e018168c91bd70ba0be54c311ce3947fe0ce5e418f6a1c88289e11c84b": "lambda_$_106", "842642e018168c91bd70ba0be54c311ce3947fe0ce5e418f6a1c88289e11c84b_arguments": "(() a b)", "a3ddf8cdd53afc8bcdd3082f709b5f66156f31f8a56e603da27b4e382a68b9f3": "sort", "aa2a43f5d1d2ed44bd135ee807b27cb33eea736d2e50b2787c5fd4100f128f47_left_env": "1", "b8edc250e5666a96397652bb34bdc9979fcd8df7f5aec90e481b7ae4234525aa": "merge", "9d8df0b4587c62404485833b9a811fe717b4f9eb3ff4a11a7806e7fd07a1c5f8": "prepend", "9d8df0b4587c62404485833b9a811fe717b4f9eb3ff4a11a7806e7fd07a1c5f8_arguments": "(a b)", "95e75b36710d3038b1cfe847cc61158c78d91e4d6db6757217c8b32ac4ae13b3_arguments": "(@ everything (rest aggl aggr))", "a3ddf8cdd53afc8bcdd3082f709b5f66156f31f8a56e603da27b4e382a68b9f3_arguments": "(myless mylist)", "9d8df0b4587c62404485833b9a811fe717b4f9eb3ff4a11a7806e7fd07a1c5f8_left_env": "1", "1b7d3888612a5d795887e5e192e68b15536e0e4c08e19324569a576ff06c6299_left_env": "1", "a3ddf8cdd53afc8bcdd3082f709b5f66156f31f8a56e603da27b4e382a68b9f3_left_env": "1", "107eecc0e2d1b059c660f3c81d6e61dd2fc7f71d4f446067132a09d395202140_left_env": "1", "95e75b36710d3038b1cfe847cc61158c78d91e4d6db6757217c8b32ac4ae13b3": "split_inner", "b8edc250e5666a96397652bb34bdc9979fcd8df7f5aec90e481b7ae4234525aa_left_env": "1", "f51796fc523809b04629ca42cffbb3514471eade8cd7d6908f3015f535a97de4_arguments": "((myless_$_91 mylist_$_92) (a b))", "b8edc250e5666a96397652bb34bdc9979fcd8df7f5aec90e481b7ae4234525aa_arguments": "(myless a b)", "107eecc0e2d1b059c660f3c81d6e61dd2fc7f71d4f446067132a09d395202140_arguments": "(vals)", "95e75b36710d3038b1cfe847cc61158c78d91e4d6db6757217c8b32ac4ae13b3_left_env": "1", "f51796fc523809b04629ca42cffbb3514471eade8cd7d6908f3015f535a97de4_left_env": "1", "__chia__main_arguments": "(X)", "107eecc0e2d1b059c660f3c81d6e61dd2fc7f71d4f446067132a09d395202140": "reverse", "6336806e19a49e9e91a62932f741d94eeca9a3656f35ecf39bc22e15d9940d53": "split", "1b7d3888612a5d795887e5e192e68b15536e0e4c08e19324569a576ff06c6299": "reverse_inner", "fa9304ef33f250463c38ac3368ad79c5416173e5a666c6571e9b4c5d8b983da1": "merge_inner", "1b7d3888612a5d795887e5e192e68b15536e0e4c08e19324569a576ff06c6299_arguments": "(reversed rest)", "6336806e19a49e9e91a62932f741d94eeca9a3656f35ecf39bc22e15d9940d53_left_env": "1", "aa2a43f5d1d2ed44bd135ee807b27cb33eea736d2e50b2787c5fd4100f128f47_arguments": "(((myless_$_91 mylist_$_92) (a b)) sa sb)", "fa9304ef33f250463c38ac3368ad79c5416173e5a666c6571e9b4c5d8b983da1_arguments": "(myless A B agg)"} \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl21/sort.clinc b/resources/tests/game-referee-in-cl21/sort.clinc new file mode 100644 index 000000000..a9afed46a --- /dev/null +++ b/resources/tests/game-referee-in-cl21/sort.clinc @@ -0,0 +1,44 @@ + +( + (defun split_inner (@ everything (rest aggl aggr)) + (if rest + (split_inner (r rest) aggr (c (f rest) aggl)) + (r everything) + ) + ) + (defun split (mylist) + (split_inner mylist 0 0) + ) + (defun merge_inner (myless A B agg) + ; this should use continued if + (if (not A) + (prepend (reverse agg) B) + (if (not B) + (prepend (reverse agg) A) + (if (a myless (list (f A) (f B))) + (merge_inner myless (r A) B (c (f A) agg)) + (merge_inner myless A (r B) (c (f B) agg)) + ) + ) + ) + ) + (defun merge (myless a b) + (merge_inner myless a b 0) + ) + (defun sort-split (myless (a b)) + (merge myless (sort myless a) (sort myless b)) + ) + (defun sort (myless mylist) + (if mylist + (if (r mylist) + (assign (a b) (split mylist) + sa (sort myless a) + sb (sort myless b) + (merge myless sa sb) + ) + mylist + ) + () + ) + ) +) diff --git a/resources/tests/game-referee-in-cl21/spacehandcalc.clinc b/resources/tests/game-referee-in-cl21/spacehandcalc.clinc new file mode 100644 index 000000000..3bfae65ca --- /dev/null +++ b/resources/tests/game-referee-in-cl21/spacehandcalc.clinc @@ -0,0 +1,104 @@ + +; ranks are 1-13 with 1 being two, 12 being king, and 13 being ace +; there are no suits, flushes, or ace-to-four straights +; takes a list of card ranks and returns the value of the best poker +; hand which can be made with them +; returned list is hand type followed by cards in descending order +; all sorting is done highest to lowest +( + (include *standard-cl-22*) + (include sort.clinc) + (include deep_compare.clinc) + (include filtermap.clinc) + (include slice.clinc) + (include max.clinc) + (defconstant FIVE_OF_A_KIND 10) + (defconstant STRAIGHT_FLUSH 9) + (defconstant FOUR_OF_A_KIND 8) + (defconstant FULL_HOUSE 7) + (defconstant FLUSH 6) + (defconstant STRAIGHT 5) + (defconstant THREE_OF_A_KIND 4) + (defconstant TWO_PAIR 3) + (defconstant PAIR 2) + (defconstant HIGH_CARD 1) + (defun straight_high_inner (ranks last count) + (if (not ranks) + ; at the end of the list + 0 + (if (= last (f ranks)) + ; skip identical cards + (straight_high_inner (r ranks) started_ace last count) + ; if the partial straight continues + (if (= (f ranks) (- last 1)) + (if (= count 4) + ; found a straight, add 3 to last because next and last are included + (+ last 3) + ; keep looking for a straight with the count going up by one + (straight_high_inner (r ranks) started_ace (f ranks) (+ count 1)) + ) + ; reset the count + (straight_high_inner (r ranks) started_ace (f ranks) 1) + ) + ) + ) + ) + ; returns the high card of a straight or 0 if there isn't any + ; ranks must be sorted in descending order + (defun straight_high (ranks) + (straight_high_inner (ranks (= (f ranks) 13) 0 0)) + ) + (defun group_by_count_inner (items last count) + (if (not items) + 0 + (if (= (f items) last) + (group_by_count_inner (r items) last (+ count 1)) + (assign val (group_by_count_inner (r items) (f items) 1) + (if last + (c (c count last) val) + val + ) + ) + ) + ) + ) + (defun group_by_count (items) + (group_by_count_inner items 0 0) + ) + (defun space_hand_calc (cards) + (assign + rest (lambda (x) (r x)) + greater (lambda (x y) (> x y)) + ranks (sort greater cards) + sh (straight_high ranks) + max_straight (if sh + (list STRAIGHT sh) + 0 + ) + groups (sort deep> (group_by_count ranks)) + (top_count . top_card) (f groups) + (second_count . second_card) (f (r groups)) + topcards (map rest groups) + max_group (if (= top_count 1) + (c HIGH_CARD (slice topcards 5)) + (if (= top_count 2) + (if (= second_count 1) + (c PAIR (slice topcards 4)) + (c TWO_PAIR (slice topcards 3)) + ) + (if (= top_count 3) + (if (= second_count 1) + (c THREE_OF_A_KIND (slice topcards 3)) + (c FULL_HOUSE (slice topcards 2)) + ) + (if (= top_count 4) + (c FOUR_OF_A_KIND (slice topcards 2)) + (c FIVE_OF_A_KIND (slice topcards 1)) + ) + ) + ) + ) + (max deep< (list max_straight max_group)) + ) + ) +) diff --git a/resources/tests/game-referee-in-cl21/test_handcalc.clsp b/resources/tests/game-referee-in-cl21/test_handcalc.clsp new file mode 100644 index 000000000..16c46f664 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_handcalc.clsp @@ -0,0 +1,379 @@ + +(mod () + (include *standard-cl-21*) + (include deep_compare.clinc) + (include assert.clinc) + (include reverse.clinc) + (include prepend.clinc) + (include map.clinc) + (include filtermap.clinc) + (include slice.clinc) + (include print.clinc) + (include sort.clinc) + (include max.clinc) + (include handcalc.clinc) + + (defun runtests_inner ((myfunc firstarg secondarg . remaining)) + (assign-lambda + firstval (handcalc firstarg) + secondval (handcalc secondarg) + (assert + (a myfunc (list firstval secondval)) + (deep= firstval (handcalc (reverse firstarg))) + (deep= secondval (handcalc (reverse secondarg))) + (if remaining + (runtests_inner remaining) + 0 + ) + ) + ) + ) + + (defun runtests tests (if tests (runtests_inner tests) ())) + + ;; Join these up when large application bug is fixed. + (runtests + ; all beats both emerge over and measure higher + ; straight flush with higher kicker ties + ; A1 K1 Q1 J1 T1 91 = A1 K1 Q1 J1 T1 81 + deep= + (list (c 12 1) (c 11 1) (c 14 1) (c 13 1) (c 10 1) (c 9 1)) + (list (c 12 1) (c 11 1) (c 14 1) (c 13 1) (c 10 1) (c 8 1)) + ; straight flushes of different suits tie + ; A1 K1 Q1 J1 T1 = A2 K2 Q2 J2 T2 + deep= + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 10 1)) + (list (c 14 2) (c 13 2) (c 12 2) (c 11 2) (c 10 2)) + ; higher straight flush beats lower straight flush + ; A1 K1 Q1 J1 T1 > 61 51 41 31 21 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 10 1)) + (list (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + ; A1 K1 Q1 J1 T1 91 = A1 K1 Q1 J1 T1 + deep= + (list (c 12 1) (c 11 1) (c 14 1) (c 13 1) (c 10 1) (c 9 1)) + (list (c 14 2) (c 11 2) (c 10 2) (c 13 2) (c 12 2)) + ; lower (2-6) straight flush beats ace to four straight flush + ; 61 51 41 31 21 > A2 52 42 32 22 + deep> + (list (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 14 2) (c 5 2) (c 4 2) (c 3 2) (c 2 2)) + ; A1 61 51 41 31 21 = 61 51 41 31 21 + deep= + (list (c 14 1) (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + ; ace to four straight flush with higher kicker ties + ; A2 52 42 32 22 61 = A1 51 41 31 21 71 + deep= + (list (c 14 2) (c 5 2) (c 4 2) (c 3 2) (c 2 2) (c 6 1)) + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1) (c 7 1)) + ; ace to four straight flushes of different suits tie + ; A1 51 41 31 21 = A2 52 42 32 22 + deep= + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 14 2) (c 5 2) (c 4 2) (c 3 2) (c 2 2)) + ; ace to four straight flush beats four of a kind + ; A1 51 41 31 21 > K1 K2 K3 K4 J1 + deep> + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 11 1)) + ; A1 A2 A3 A4 51 41 31 21 = A1 51 41 31 21 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + ; four of a kind with higher kicker wins + ; K1 K2 K3 K4 Q1 > K1 K2 K3 K4 J1 + deep> + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 12 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 11 1)) + ; K1 K2 K3 K4 T1 91 = K1 K2 K3 K4 T1 + deep= + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 10 1) (c 9 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 10 1)) + ; four of a kind with higher second kicker ties + ; K1 K2 K3 K4 Q1 J1 = K1 K2 K3 K4 Q1 T1 + deep= + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 12 1) (c 11 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 12 1) (c 10 1)) + ; higher four of a kind beats lower four of a kind + ; K1 K2 K3 K4 21 > 31 32 33 34 A1 + deep> + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 2 1)) + (list (c 3 1) (c 3 2) (c 3 3) (c 3 4) (c 14 1)) + ; K1 K2 K3 K4 31 32 33 34 = K1 K2 K3 K4 32 + deep= + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 3 1) (c 3 2) (c 3 3) (c 3 4)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 3 2)) + ; four of a kind beats full house + ; 21 22 23 24 31 > A1 A2 A3 K1 K2 + deep> + (list (c 2 1) (c 2 2) (c 2 3) (c 2 4) (c 3 1)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2)) + ; 21 22 23 24 A1 A2 A3 = 21 22 23 24 A2 + deep= + (list (c 2 1) (c 2 2) (c 2 3) (c 2 4) (c 14 1) (c 14 2) (c 14 3)) + (list (c 2 1) (c 2 2) (c 2 3) (c 2 4) (c 14 2)) + ; full house with higher set wins + ; 51 52 53 21 22 > 31 32 33 71 72 + deep> + (list (c 5 1) (c 5 2) (c 5 3) (c 2 1) (c 2 2)) + (list (c 3 1) (c 3 2) (c 3 3) (c 7 1) (c 7 2)) + ; A1 A2 A3 K1 K2 K3 = A1 A2 A3 K1 K2 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2) (c 13 3)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2)) + ; full house with same set and higher pair wins + ; 51 52 53 41 42 > 51 52 53 31 32 + deep> + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2)) + (list (c 5 1) (c 5 2) (c 5 3) (c 3 1) (c 3 2)) + ; A1 A2 A3 K1 K2 51 52 = A1 A2 A3 K1 K2 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2) (c 5 1) (c 5 2)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2)) + ; full house ties with two sets + ; 51 52 53 41 42 A1 = 51 52 53 41 42 43 + deep= + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2) (c 14 1)) + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2) (c 4 3)) + ; full house beats flush + ; 51 52 53 41 42 > A1 Q1 T1 81 71 + deep> + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2)) + (list (c 14 1) (c 12 1) (c 10 1) (c 8 1) (c 7 1)) + ; 51 52 53 41 42 A1 K1 Q1 = 51 52 53 41 42 + deep= + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2) (c 14 1) (c 13 1) (c 12 1)) + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2)) + ; higher flush beats lower flush + ; A1 61 51 41 31 > K1 Q1 J1 T1 81 + deep> + (list (c 14 1) (c 6 1) (c 5 1) (c 4 1) (c 3 1)) + (list (c 13 1) (c 12 2) (c 11 1) (c 10 1) (c 8 1)) + ; A1 K1 Q1 J1 81 71 = A1 K1 Q1 J1 81 + deep= + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 8 1) (c 7 1)) + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 8 1)) + ; flush with higher second card wins + ; A1 K1 51 41 31 > A1 Q1 J1 T1 91 + deep> + (list (c 14 1) (c 13 1) (c 5 1) (c 4 1) (c 3 1)) + (list (c 14 1) (c 12 2) (c 11 1) (c 10 1) (c 9 1)) + ; flush with higher third card wins + ; A1 K1 Q1 41 31 > A1 K1 J1 T1 91 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 4 1) (c 3 1)) + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 9 1)) + ; flush with higher fourth card wins + ; A1 K1 Q1 T1 21 > A1 K1 Q1 91 81 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 10 1) (c 2 1)) + (list (c 14 1) (c 13 1) (c 12 1) (c 9 1) (c 8 1)) + ; flush with higher fifth card wins + ; A1 K1 Q1 T1 81 > A1 K1 Q1 T1 71 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 10 1) (c 8 1)) + (list (c 14 1) (c 13 1) (c 12 1) (c 10 1) (c 7 1)) + ; flushes of different suits tie + ; A1 K1 J1 T1 81 = A2 K2 J2 T2 82 + deep= + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 8 1)) + (list (c 14 2) (c 13 2) (c 11 2) (c 10 2) (c 8 2)) + ; same flush with higher sixth card ties + ; A1 K1 J1 T1 81 71 = A1 K1 J1 T1 81 61 + deep= + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 8 1) (c 7 1)) + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 8 1) (c 6 1)) + ; flush beats straight + ; 71 61 51 41 21 > A1 K2 Q3 J4 T1 + deep> + (list (c 7 1) (c 6 1) (c 5 1) (c 4 1) (c 2 1)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1)) + ; A1 K2 Q3 J4 T1 81 71 61 = A1 T1 81 71 61 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 8 1) (c 7 1) (c 6 1)) + (list (c 14 1) (c 10 1) (c 8 1) (c 7 1) (c 6 1)) + ; straight with higher kicker ties + ; A1 K2 Q3 J4 T1 92 = A1 K2 Q3 J4 T1 22 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 9 2)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 2 2)) + ; straights of different suits tie + ; A1 K2 Q3 J4 T1 = A2 K3 Q4 J1 T2 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1)) + (list (c 14 2) (c 13 3) (c 12 4) (c 11 1) (c 10 2)) + ; higher straight beats lower straight + ; A1 K2 Q3 J4 T1 > 61 52 43 34 21 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1)) + (list (c 6 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + ; A1 K2 Q3 J4 T1 92 83 = A1 K2 Q3 J4 T1 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 9 2) (c 8 3)) + (list (c 14 2) (c 13 3) (c 12 4) (c 11 1) (c 10 2)) + ; lower (2-6) straight beats ace to four straight + ; 61 52 43 34 21 > A1 52 43 34 21 + deep> + (list (c 6 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + ; A1 62 53 44 31 22 = 62 53 44 31 22 + deep= + (list (c 14 1) (c 6 2) (c 5 3) (c 4 4) (c 3 1) (c 2 2)) + (list (c 6 2) (c 5 3) (c 4 4) (c 3 1) (c 2 2)) + ; ace to four straight with higher kicker ties + ; A1 52 43 34 21 K2 = A1 52 43 34 21 72 + deep= + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1) (c 13 2)) + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1) (c 7 2)) + ; ace to fours of different suits tie + ; A1 52 43 34 21 = A2 53 44 31 22 + deep= + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 2) (c 5 3) (c 4 4) (c 3 1) (c 2 2)) + ; ace to four straight beats set + ; A1 52 43 34 21 > A1 A2 A3 K1 Q2 + deep> + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 12 2)) + ; A1 A2 A3 52 43 34 21 = A1 52 43 34 21 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 5 2) (c 4 3) (c 3 2) (c 2 1)) + ; higher set wins + ; 71 72 73 34 21 > 51 52 53 A4 K1 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 3 4) (c 2 1)) + (list (c 5 1) (c 5 2) (c 5 3) (c 14 4) (c 13 1)) + ; set with higher first kicker wins + ; 71 72 73 A1 22 > 71 72 73 K1 Q2 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 2 2)) + (list (c 7 1) (c 7 2) (c 7 3) (c 13 1) (c 12 2)) + ; 71 72 73 A1 K2 J3 54 43 = 71 72 73 A1 K2 + deep= + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2) (c 11 3) (c 5 4) (c 4 3)) + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2)) + ; set with higher second kicker wins + ; 71 72 73 A1 K2 > 71 72 73 A1 Q2 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2)) + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 12 2)) + ; set with higher third kicker ties + ; 71 72 73 A1 K2 Q3 = 71 72 73 A1 K2 J3 + deep= + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2) (c 12 3)) + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2) (c 11 3)) + ; set beats two pair + ; 71 72 73 34 21 > A1 A2 K3 K4 Q1 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 14 2) (c 13 3) (c 13 4) (c 12 1)) + ; two pair with higher high pair wins + ; K1 K2 33 34 21 > Q1 Q2 J3 J4 A1 + deep> + (list (c 13 1) (c 13 2) (c 3 3) (c 3 4) (c 2 1)) + (list (c 12 1) (c 12 2) (c 11 3) (c 11 4) (c 14 1)) + ; A1 A2 K1 K2 J1 J2 = A1 A2 K1 K2 J3 + deep= + (list (c 14 1) (c 14 2) (c 13 1) (c 13 2) (c 11 1) (c 11 2)) + (list (c 14 1) (c 14 2) (c 13 1) (c 13 2) (c 11 3)) + ; two pair with tied higher pair and higher lower pair wins + ; K1 K2 71 72 23 > K1 K2 63 64 A1 + deep> + (list (c 13 1) (c 13 2) (c 7 1) (c 7 2) (c 2 3)) + (list (c 13 1) (c 13 2) (c 6 3) (c 6 4) (c 14 1)) + ; two pair with higher kicker wins + ; K1 K2 Q3 Q4 J1 > K1 K2 Q3 Q4 T1 + deep> + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 11 1)) + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 10 1)) + ; K1 K2 Q3 Q4 A1 T1 92 63 = K1 K2 Q3 Q4 A1 + deep= + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 14 1) (c 10 1) (c 9 2) (c 6 3)) + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 14 1)) + ; two pair with higher second kicker ties + ; K1 K2 Q3 Q4 J1 T2 = K1 K2 Q3 Q4 J1 92 + deep= + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 11 1) (c 10 2)) + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 11 1) (c 9 2)) + ; two pair beats pair + ; 41 42 33 34 21 > A1 A2 K3 Q4 J1 + deep> + (list (c 4 1) (c 4 2) (c 3 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 14 2) (c 13 3) (c 12 4) (c 11 1)) + ; higher pair wins + ; 71 72 53 44 31 > 61 62 A3 K4 Q1 + deep> + (list (c 7 1) (c 7 2) (c 5 3) (c 4 4) (c 3 1)) + (list (c 6 1) (c 6 2) (c 14 3) (c 13 4) (c 12 1)) + ; tied pair with higher first kicker wins + ; 91 92 A3 34 21 > 91 92 K3 Q4 J1 + deep> + (list (c 9 1) (c 9 2) (c 14 3) (c 3 4) (c 2 1)) + (list (c 9 1) (c 9 2) (c 13 3) (c 12 4) (c 11 1)) + ; 21 22 A1 Q2 J3 94 81 = 21 22 A1 Q2 J3 + deep= + (list (c 2 1) (c 2 2) (c 14 1) (c 12 2) (c 11 3) (c 9 4) (c 8 1)) + (list (c 2 1) (c 2 2) (c 14 1) (c 12 2) (c 11 3)) + ; tied pair with higher second kicker wins + ; 91 92 A3 K4 21 > 91 92 A3 Q4 J1 + deep> + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 2 1)) + (list (c 9 1) (c 9 2) (c 14 3) (c 12 4) (c 11 1)) + ; tied pair with higher third kicker wins + ; 91 92 A3 K4 Q1 > 91 92 A3 K4 J1 + deep> + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 12 1)) + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 11 1)) + ; tied pair with higher fourth kicker ties + ; 91 92 A3 K4 Q1 J2 = 91 92 A3 K4 Q1 T2 + deep= + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 12 1) (c 11 2)) + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 12 1) (c 10 2)) + ; pair beats high card + ; 21 22 33 44 51 > A1 Q2 J3 T4 91 + deep> + (list (c 2 1) (c 2 2) (c 3 3) (c 4 4) (c 5 1)) + (list (c 14 1) (c 12 2) (c 11 3) (c 10 4) (c 9 1)) + ; higher high card wins + ; A1 22 33 44 61 > K1 Q2 J3 T4 81 + deep> + (list (c 14 1) (c 2 2) (c 3 3) (c 4 4) (c 6 1)) + (list (c 13 1) (c 12 2) (c 11 3) (c 10 4) (c 8 1)) + ; A1 K2 J3 T4 81 72 53 = A1 K2 J3 T4 81 + deep= + (list (c 14 1) (c 13 2) (c 11 3) (c 10 4) (c 8 1) (c 7 2) (c 5 3)) + (list (c 14 1) (c 13 2) (c 11 3) (c 10 4) (c 8 1)) + ; higher second card wins + ; A1 K2 23 34 41 > A1 Q2 J3 T4 91 + deep> + (list (c 14 1) (c 13 2) (c 2 3) (c 3 4) (c 4 1)) + (list (c 14 1) (c 12 2) (c 11 3) (c 10 4) (c 9 1)) + ; higher third card wins + ; A1 K2 Q3 24 41 > A1 K2 J3 T4 91 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 2 4) (c 4 1)) + (list (c 14 1) (c 13 2) (c 11 3) (c 10 4) (c 9 1)) + ; higher fourth card wins + ; A1 K2 Q3 J4 31 > A1 K2 Q3 T4 91 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 3 1)) + (list (c 14 1) (c 13 2) (c 12 3) (c 10 4) (c 9 1)) + ; higher fifth card wins + ; A1 K2 Q3 J4 91 > A1 K2 Q3 J4 81 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 8 1)) + ; higher sixth card ties + ; A1 K2 Q3 J4 91 22 = A1 K2 Q3 J4 91 82 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1) (c 2 2)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1) (c 8 2)) + ; high cards of different suits ties + ; A1 K2 Q3 J4 91 = A2 K3 Q4 J1 92 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1)) + (list (c 14 2) (c 13 3) (c 12 4) (c 11 1) (c 9 2)) + ) +) diff --git a/resources/tests/game-referee-in-cl21/test_handcalc.clvm.hex b/resources/tests/game-referee-in-cl21/test_handcalc.clvm.hex new file mode 100644 index 000000000..8a8aedd7f --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_handcalc.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff8200feffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010180ffff0180808080808080ffff04ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010280ffff04ffff04ffff010affff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010180ffff0180808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff010bffff010280ffff04ffff04ffff010affff010280ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010280ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0102ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff0180808080808080ffff04ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010280ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0102ffff010280ffff04ffff04ffff0106ffff010180ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0107ffff010180ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010280ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0102ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff018080808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff01808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010180ffff0180808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff0180808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff04ffff04ffff010affff010180ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff010effff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0103ffff010480ffff01808080808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff0103ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff0102ffff010380ffff04ffff04ffff0102ffff010480ffff04ffff04ffff0103ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff0102ffff010380ffff04ffff04ffff0102ffff010480ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff018080808080808080ffff04ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff0102ffff010380ffff04ffff04ffff0102ffff010480ffff04ffff04ffff010effff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff01808080808080ffff04ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff01808080808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0103ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff018080808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff04ffff04ffff010effff010180ffff0180808080808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff04ffff04ffff0104ffff010380ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0107ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff01808080808080808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff01808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0107ffff010180ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0107ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010280ffff04ffff04ffff010affff010280ffff04ffff04ffff0108ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0107ffff010180ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0106ffff010180ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0106ffff010180ffff01808080808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0106ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010280ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff04ffff04ffff0102ffff010280ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff0108ffff010380ffff018080808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0106ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010480ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010280ffff0180808080808080ffff04ffff04ffff04ffff0106ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010480ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff04ffff04ffff010dffff010280ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0107ffff010280ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010480ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff018080808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff010effff010480ffff04ffff04ffff010dffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff0102ffff010280ffff01808080808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff0105ffff010480ffff04ffff04ffff0104ffff010380ffff01808080808080808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff01808080808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff0180808080808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010380ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010cffff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010effff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010180ffff04ffff04ffff010bffff010280ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010380ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0102ffff010380ffff01808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff0106ffff010380ffff04ffff04ffff0106ffff010480ffff04ffff04ffff010effff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010effff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff0106ffff010380ffff01808080808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010effff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010280ffff0180808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff04ffff04ffff0109ffff010280ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010480ffff04ffff04ffff0103ffff010180ffff01808080808080ffff04ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0106ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff0109ffff010480ffff04ffff04ffff0108ffff010180ffff018080808080808080ffff04ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010380ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff01808080808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010280ffff0180808080808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff04ffff04ffff010affff010280ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0104ffff010480ffff04ffff04ffff0105ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0104ffff010480ffff04ffff04ffff0106ffff010180ffff01808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0105ffff010380ffff018080808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff0102ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0104ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff0102ffff010480ffff04ffff04ffff0104ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff0103ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0102ffff010280ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0108ffff010280ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff04ffff04ffff0109ffff010280ffff01808080808080ff808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080ffff04ffff01ffffffffffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff02ff8200a0ffff04ff02ffff04ffff06ff0180ffff04ffff02ff40ffff04ff02ffff04ffff05ff0580ffff04ffff05ff0b80ff8080808080ff8080808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff0181ffff0180ffff01ff02ffff01ff02ffff03ffff15ff05ff0b80ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff11ffff0180ffff15ff0bff058080ff018080ff0180ff018080ff0180ff018080ff0180ffff02ffff03ff0bffff01ff02ffff010bff0180ffff01ff02ffff01ff02ff40ffff04ff02ffff04ffff06ff0980ffff04ffff06ff1580ff8080808080ff018080ff0180ff09ffff02ff40ffff04ff02ffff04ff05ffff04ff0bff8080808080ffff0181ff80ffff09ffff02ff40ffff04ff02ffff04ff05ffff04ff0bff8080808080ffff010180ffff09ffff02ff40ffff04ff02ffff04ff05ffff04ff0bff8080808080ff8080ff02ffff03ff0bffff01ff02ffff01ff02ff8200f0ffff04ff02ffff04ffff04ffff05ff0b80ff0580ffff04ffff06ff0b80ff8080808080ff0180ffff01ff02ffff0105ff018080ff0180ffffff02ff8200f0ffff04ff02ffff04ff80ffff04ff05ff8080808080ffff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff8200a8ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff02ffff03ff0bffff01ff02ffff01ff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff02ff8200e8ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff80808080808080ff0180ffff01ff02ffff0117ff018080ff0180ffff02ffff03ff0bffff01ff02ffff01ff02ff8200b8ffff04ff02ffff04ffff06ff0180ffff04ffff02ff05ffff04ffff05ff0b80ffff01808080ff8080808080ff0180ffff01ff02ffff0117ff018080ff0180ffff02ffff03ff0bffff01ff02ffff01ff04ff0bffff02ff58ffff04ff02ffff04ff09ffff04ffff06ff1580ffff04ff2dff80808080808080ff0180ffff01ff02ffff01ff02ff58ffff04ff02ffff04ff09ffff04ffff06ff1580ffff04ff2dff808080808080ff018080ff0180ff02ffff03ffff02ff44ffff04ff02ffff04ffff04ffff018c736c69636520696e70757473ffff04ffff01866e796c697374ffff04ff0bff80808080ffff04ffff20ff0b80ff8080808080ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff04ffff05ff0580ffff02ff8200f8ffff04ff02ffff04ffff06ff0580ffff04ffff11ff0bffff010180ff808080808080ff018080ff0180ffffffff02ffff03ffff22ffff0187247072696e7424ff05ff0b80ffff01ff02ffff010bff0180ffff01ff02ffff010bff018080ff0180ffff02ffff03ff05ffff01ff02ffff01ff02ff8200a4ffff04ff02ffff04ffff06ff0580ffff04ff17ffff04ffff04ffff05ff0580ff0b80ff808080808080ff0180ffff01ff02ffff01ff06ff0380ff018080ff0180ff02ff8200a4ffff04ff02ffff04ff05ffff01ff80ff8080808080ffff02ffff03ffff20ff0b80ffff01ff02ffff01ff02ff8200a8ffff04ff02ffff04ffff02ff48ffff04ff02ffff04ff2fff80808080ffff04ff17ff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff20ff1780ffff01ff02ffff01ff02ff8200a8ffff04ff02ffff04ffff02ff48ffff04ff02ffff04ff2fff80808080ffff04ff0bff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff02ff05ffff04ffff05ff0b80ffff04ffff05ff1780ffff0180808080ffff01ff02ffff01ff02ff54ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ffff04ffff04ffff05ff0b80ff2f80ff80808080808080ff0180ffff01ff02ffff01ff02ff54ffff04ff02ffff04ff05ffff04ff0bffff04ffff06ff1780ffff04ffff04ffff05ff1780ff2f80ff80808080808080ff018080ff0180ff018080ff0180ff018080ff0180ffff02ff54ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff01ff80808080808080ff02ffff03ff0bffff01ff02ffff01ff02ffff03ffff06ff0b80ffff01ff02ffff01ff02ff4cffff04ff02ffff04ffff06ff0180ffff04ffff02ff8200e4ffff04ff02ffff04ff0bff80808080ff8080808080ff0180ffff01ff02ffff010bff018080ff0180ff0180ffff01ff02ffff01ff0180ff018080ff0180ffffff02ff8200acffff04ff02ffff04ff03ffff04ffff02ff8200f4ffff04ff02ffff04ff09ffff04ff13ff8080808080ffff04ffff02ff8200f4ffff04ff02ffff04ff09ffff04ff2bff8080808080ff808080808080ffff02ff8200b4ffff04ff02ffff04ff11ffff04ff0bffff04ff17ff808080808080ff02ffff03ffff20ff1780ffff01ff02ffff010bff0180ffff01ff02ffff01ff02ffff03ffff02ff05ffff04ff0bffff04ffff05ff1780ffff0180808080ffff01ff02ffff01ff02ff8200ecffff04ff02ffff04ff05ffff04ffff05ff1780ffff04ffff06ff1780ff808080808080ff0180ffff01ff02ffff01ff02ff8200ecffff04ff02ffff04ff05ffff04ff0bffff04ffff06ff1780ff808080808080ff018080ff0180ff018080ff0180ffff02ff8200ecffff04ff02ffff04ff05ffff04ff13ffff04ff1bff808080808080ffff02ffff03ffff20ff0580ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff02ffff03ffff09ffff05ff0580ff0b80ffff01ff02ffff01ff02ffff03ffff09ff17ffff010480ffff01ff02ffff010bff0180ffff01ff02ffff01ff02ff8200bcffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ffff10ff17ffff010180ff808080808080ff018080ff0180ff0180ffff01ff02ffff01ff02ff8200bcffff04ff02ffff04ffff06ff0580ffff04ffff05ff0580ffff04ffff0101ff808080808080ff018080ff0180ff018080ff0180ff02ff8200bcffff04ff02ffff04ffff02ff8200f4ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff4280ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ffff04ff05ff8080808080ffff01ff80ff8080808080ffffffffff02ff50ffff04ff02ffff04ff0bffff04ff17ff8080808080ffff02ffff03ffff20ff0580ffff01ff02ffff01ff02ffff03ffff18ffff09ff17ffff010280ffff09ff2fffff010480ff0b80ffff01ff02ffff01ff0105ff0180ffff01ff02ffff01ff0180ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff09ff17ffff05ff058080ffff01ff02ffff01ff02ff8200a2ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fff80808080808080ff0180ffff01ff02ffff01ff02ffff03ffff09ffff05ff0580ffff11ff17ffff01018080ffff01ff02ffff01ff02ffff03ffff09ff2fffff010480ffff01ff02ffff01ff10ff17ffff010380ff0180ffff01ff02ffff01ff02ff8200a2ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ffff05ff0580ffff04ffff10ff2fffff010180ff80808080808080ff018080ff0180ff0180ffff01ff02ffff01ff02ff8200a2ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ffff05ff0580ffff04ffff0101ff80808080808080ff018080ff0180ff018080ff0180ff018080ff0180ff02ff8200a2ffff04ff02ffff04ff05ffff04ffff09ff09ffff010e80ffff01ff80ff808080808080ffff02ffff03ffff20ff0580ffff01ff02ffff01ff04ffff04ff17ff0b80ffff018080ff0180ffff01ff02ffff01ff02ffff03ffff09ffff05ff0580ff0b80ffff01ff02ffff01ff02ff52ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ffff10ff17ffff010180ff808080808080ff0180ffff01ff02ffff01ff02ff8200b2ffff04ff02ffff04ffff06ff0180ffff04ffff02ff52ffff04ff02ffff04ffff06ff0580ffff04ffff05ff0580ffff04ffff0101ff808080808080ff8080808080ff018080ff0180ff018080ff0180ffff04ffff04ff2dff1580ff0b80ff02ff52ffff04ff02ffff04ff05ffff04ff09ffff01ff808080808080ffffff02ff5affff04ff02ffff04ff03ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200aa80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200ea80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ff808080808080ff1b13ffff02ff8200faffff04ff02ffff04ff03ffff04ffff02ff8200f4ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200ba80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ffff04ffff02ff8200e8ffff04ff02ffff04ff17ffff04ff09ffff01ff808080808080ff8080808080ffff04ffff02ff8200fcffff04ff02ffff04ffff02ff8200e8ffff04ff02ffff04ff0bffff04ff09ffff01ff808080808080ff80808080ff808080808080ffff02ff50ffff04ff02ffff04ff0bffff04ff17ff8080808080ff02ff8200f6ffff04ff02ffff04ff03ffff04ffff02ff8200f4ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff4680ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ffff04ffff02ff8200f2ffff04ff02ffff04ff0bff80808080ff8080808080ffff04ffff02ff8200e2ffff04ff02ffff04ff0bff80808080ffff04ffff02ffff03ffff20ff1780ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff02ff56ffff04ff02ffff04ffff06ff0180ffff04ffff02ff8200f4ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200a680ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ffff02ff58ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200e680ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff17ffff01808080ffff04ffff0101ffff0180808080ffff0180808080ffff04ff11ffff04ffff0180ff808080808080ff8080808080ff8080808080ff018080ff0180ff80808080808080ffffffff02ff50ffff04ff02ffff04ff0bffff04ff17ff8080808080ffff02ff50ffff04ff02ffff04ff0bffff04ff17ff8080808080ff02ffff03ffff09ff09ff1b80ffff01ff02ffff0113ff0180ffff01ff02ffff01ff0180ff018080ff0180ffff02ff8200b6ffff04ff02ffff04ff03ffff04ffff02ff8200e2ffff04ff02ffff04ff0bff80808080ff8080808080ffff02ffff03ff0bffff01ff02ffff01ff04ffff0109ffff04ff0bffff01808080ff0180ffff01ff02ffff01ff04ffff0106ffff02ff8200f8ffff04ff02ffff04ff15ffff04ffff0105ff808080808080ff018080ff0180ff02ff4effff04ff02ffff04ff03ffff04ffff02ffff03ff17ffff01ff02ffff01ff04ffff0105ffff04ff17ffff01808080ff0180ffff01ff02ffff01ff0180ff018080ff0180ffff04ff2bffff04ff13ffff04ffff02ff8200e8ffff04ff02ffff04ff29ffff04ff0bffff01ff808080808080ff8080808080808080ffffff02ff8200aeffff04ff02ffff04ff03ffff04ffff02ffff03ffff09ff4fffff010180ffff01ff02ffff01ff04ffff0101ffff02ff8200f8ffff04ff02ffff04ff5fffff04ffff0105ff808080808080ff0180ffff01ff02ffff01ff02ffff03ffff09ff4fffff010280ffff01ff02ffff01ff02ffff03ffff09ff27ffff010180ffff01ff02ffff01ff04ffff0102ffff02ff8200f8ffff04ff02ffff04ff5fffff04ffff0104ff808080808080ff0180ffff01ff02ffff01ff04ffff0103ffff02ff8200f8ffff04ff02ffff04ff5fffff04ffff0103ff808080808080ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff09ff4fffff010380ffff01ff02ffff01ff02ffff03ffff09ff27ffff010180ffff01ff02ffff01ff04ffff0104ffff02ff8200f8ffff04ff02ffff04ff5fffff04ffff0103ff808080808080ff0180ffff01ff02ffff01ff04ffff0107ffff02ff8200f8ffff04ff02ffff04ff5fffff04ffff0102ff808080808080ff018080ff0180ff0180ffff01ff02ffff01ff04ffff0108ffff02ff8200f8ffff04ff02ffff04ff5fffff04ffff0102ff808080808080ff018080ff0180ff018080ff0180ff018080ff0180ff8080808080ffff02ff5cffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200ee80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ffff04ffff04ff8200b9ffff04ff15ffff04ff0bff80808080ff8080808080ff02ff8200e0ffff04ff02ffff04ff0bffff04ff17ff8080808080ffff02ff8200beffff04ff02ffff04ff03ffff04ffff02ff4affff04ff02ffff04ff2dff80808080ffff04ffff02ff4affff04ff02ffff04ff15ff80808080ff808080808080ffff02ffff03ffff02ff11ffff04ff17ffff04ff0bff80808080ffff01ff02ffff01ff02ffff03ffff02ff8200b0ffff04ff02ffff04ff17ffff04ffff02ff4affff04ff02ffff04ffff02ff48ffff04ff02ffff04ff29ff80808080ff80808080ff8080808080ffff01ff02ffff01ff02ffff03ffff02ff8200b0ffff04ff02ffff04ff0bffff04ffff02ff4affff04ff02ffff04ffff02ff48ffff04ff02ffff04ff59ff80808080ff80808080ff8080808080ffff01ff02ffff01ff02ffff03ff79ffff01ff02ffff01ff02ff5effff04ff02ffff04ff79ff80808080ff0180ffff01ff02ffff01ff0180ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff02ffff03ff03ffff01ff02ffff01ff02ff5effff04ff02ffff04ff03ff80808080ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080 diff --git a/resources/tests/game-referee-in-cl21/test_handcalc.clvm.hex.reference b/resources/tests/game-referee-in-cl21/test_handcalc.clvm.hex.reference new file mode 100644 index 000000000..441ac847b --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_handcalc.clvm.hex.reference @@ -0,0 +1 @@ +ff02ffff01ff02ff8200feffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010180ffff0180808080808080ffff04ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010280ffff04ffff04ffff010affff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010180ffff0180808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff010bffff010280ffff04ffff04ffff010affff010280ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010280ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0102ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff0180808080808080ffff04ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010280ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0102ffff010280ffff04ffff04ffff0106ffff010180ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0107ffff010180ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010280ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0102ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff018080808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff01808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010180ffff0180808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff0180808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff04ffff04ffff010affff010180ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff010effff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0103ffff010480ffff01808080808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff0103ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff0102ffff010380ffff04ffff04ffff0102ffff010480ffff04ffff04ffff0103ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff0102ffff010380ffff04ffff04ffff0102ffff010480ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff018080808080808080ffff04ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff0102ffff010380ffff04ffff04ffff0102ffff010480ffff04ffff04ffff010effff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff01808080808080ffff04ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010dffff010380ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff01808080808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0103ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff018080808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff04ffff04ffff010effff010180ffff0180808080808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff04ffff04ffff0104ffff010380ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0107ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff01808080808080808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff01808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0107ffff010180ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0103ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0107ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010280ffff04ffff04ffff010affff010280ffff04ffff04ffff0108ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0107ffff010180ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010180ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0106ffff010180ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0106ffff010180ffff01808080808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0106ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010280ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff04ffff04ffff0102ffff010280ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff0108ffff010380ffff018080808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0106ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010480ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010280ffff0180808080808080ffff04ffff04ffff04ffff0106ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010480ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff04ffff04ffff010dffff010280ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0107ffff010280ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010480ffff04ffff04ffff0103ffff010180ffff04ffff04ffff0102ffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff018080808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0104ffff010380ffff04ffff04ffff0103ffff010280ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff0105ffff010180ffff04ffff04ffff0105ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff010effff010480ffff04ffff04ffff010dffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff0102ffff010280ffff01808080808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff0105ffff010480ffff04ffff04ffff0104ffff010380ffff01808080808080808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff01808080808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010280ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff0180808080808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010380ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0107ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010cffff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff010effff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010180ffff04ffff04ffff010bffff010280ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010380ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0102ffff010380ffff01808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff0106ffff010380ffff04ffff04ffff0106ffff010480ffff04ffff04ffff010effff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010affff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010effff010180ffff04ffff04ffff010affff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff0106ffff010380ffff01808080808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010effff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff04ffff04ffff010affff010280ffff0180808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff04ffff04ffff0109ffff010280ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0104ffff010180ffff04ffff04ffff0104ffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0107ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0105ffff010380ffff04ffff04ffff0104ffff010480ffff04ffff04ffff0103ffff010180ffff01808080808080ffff04ffff04ffff04ffff0106ffff010180ffff04ffff04ffff0106ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff0109ffff010480ffff04ffff04ffff0108ffff010180ffff018080808080808080ffff04ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010380ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff0102ffff010180ffff01808080808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff01808080808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010bffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff04ffff04ffff010bffff010280ffff0180808080808080ffff04ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0109ffff010280ffff04ffff04ffff010effff010380ffff04ffff04ffff010dffff010480ffff04ffff04ffff010cffff010180ffff04ffff04ffff010affff010280ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff0102ffff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0104ffff010480ffff04ffff04ffff0105ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff0102ffff010280ffff04ffff04ffff0103ffff010380ffff04ffff04ffff0104ffff010480ffff04ffff04ffff0106ffff010180ffff01808080808080ffff04ffff04ffff04ffff010dffff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0108ffff010180ffff04ffff04ffff0107ffff010280ffff04ffff04ffff0105ffff010380ffff018080808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff0102ffff010380ffff04ffff04ffff0103ffff010480ffff04ffff04ffff0104ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010cffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff0102ffff010480ffff04ffff04ffff0104ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010bffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff0103ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010affff010480ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff5080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff0108ffff010180ffff01808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0102ffff010280ffff0180808080808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff0109ffff010180ffff04ffff04ffff0108ffff010280ffff0180808080808080ffff04ffff04ffff0102ffff04ffff04ffff0101ff8200b080ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff80808080ffff04ffff04ffff04ffff010effff010180ffff04ffff04ffff010dffff010280ffff04ffff04ffff010cffff010380ffff04ffff04ffff010bffff010480ffff04ffff04ffff0109ffff010180ffff01808080808080ffff04ffff04ffff04ffff010effff010280ffff04ffff04ffff010dffff010380ffff04ffff04ffff010cffff010480ffff04ffff04ffff010bffff010180ffff04ffff04ffff0109ffff010280ffff01808080808080ff808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080ffff04ffff01ffffffffffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff02ff8200a0ffff04ff02ffff04ffff06ff0180ffff04ffff02ff40ffff04ff02ffff04ffff05ff0580ffff04ffff05ff0b80ff8080808080ff8080808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff0181ffff0180ffff01ff02ffff01ff02ffff03ffff15ff05ff0b80ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff11ffff0180ffff15ff0bff058080ff018080ff0180ff018080ff0180ff018080ff0180ffff02ffff03ff0bffff01ff02ffff010bff0180ffff01ff02ffff01ff02ff40ffff04ff02ffff04ffff06ff0980ffff04ffff06ff1580ff8080808080ff018080ff0180ff09ffff02ff40ffff04ff02ffff04ff05ffff04ff0bff8080808080ffff0181ff80ffff09ffff02ff40ffff04ff02ffff04ff05ffff04ff0bff8080808080ffff010180ffff09ffff02ff40ffff04ff02ffff04ff05ffff04ff0bff8080808080ff8080ff02ffff03ff0bffff01ff02ffff01ff02ff8200f0ffff04ff02ffff04ffff04ffff05ff0b80ff0580ffff04ffff06ff0b80ff8080808080ff0180ffff01ff02ffff0105ff018080ff0180ffffff02ff8200f0ffff04ff02ffff04ff80ffff04ff05ff8080808080ffff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff8200a8ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff02ffff03ff0bffff01ff02ffff01ff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff02ff8200e8ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff80808080808080ff0180ffff01ff02ffff0117ff018080ff0180ffff02ffff03ff0bffff01ff02ffff01ff02ff8200b8ffff04ff02ffff04ffff06ff0180ffff04ffff02ff05ffff04ffff05ff0b80ffff01808080ff8080808080ff0180ffff01ff02ffff0117ff018080ff0180ffff02ffff03ff0bffff01ff02ffff01ff04ff0bffff02ff58ffff04ff02ffff04ff09ffff04ffff06ff1580ffff04ff2dff80808080808080ff0180ffff01ff02ffff01ff02ff58ffff04ff02ffff04ff09ffff04ffff06ff1580ffff04ff2dff808080808080ff018080ff0180ff02ffff03ffff02ff44ffff04ff02ffff04ffff04ffff018c736c69636520696e70757473ffff04ffff01866e796c697374ffff04ff0bff80808080ffff04ffff20ff0b80ff8080808080ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff04ffff05ff0580ffff02ff8200f8ffff04ff02ffff04ffff06ff0580ffff04ffff11ff0bffff010180ff808080808080ff018080ff0180ffffffff02ffff03ffff22ffff0187247072696e7424ff05ff0b80ffff01ff02ffff010bff0180ffff01ff02ffff010bff018080ff0180ffff02ffff03ff05ffff01ff02ffff01ff02ff8200a4ffff04ff02ffff04ffff06ff0580ffff04ff17ffff04ffff04ffff05ff0580ff0b80ff808080808080ff0180ffff01ff02ffff01ff06ff0380ff018080ff0180ff02ff8200a4ffff04ff02ffff04ff05ffff01ff80ff8080808080ffff02ffff03ffff20ff0b80ffff01ff02ffff01ff02ff8200a8ffff04ff02ffff04ffff02ff48ffff04ff02ffff04ff2fff80808080ffff04ff17ff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff20ff1780ffff01ff02ffff01ff02ff8200a8ffff04ff02ffff04ffff02ff48ffff04ff02ffff04ff2fff80808080ffff04ff0bff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff02ff05ffff04ffff05ff0b80ffff04ffff05ff1780ffff0180808080ffff01ff02ffff01ff02ff54ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ffff04ffff04ffff05ff0b80ff2f80ff80808080808080ff0180ffff01ff02ffff01ff02ff54ffff04ff02ffff04ff05ffff04ff0bffff04ffff06ff1780ffff04ffff04ffff05ff1780ff2f80ff80808080808080ff018080ff0180ff018080ff0180ff018080ff0180ffff02ff54ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff01ff80808080808080ff02ffff03ff0bffff01ff02ffff01ff02ffff03ffff06ff0b80ffff01ff02ffff01ff02ff4cffff04ff02ffff04ffff06ff0180ffff04ffff02ff8200e4ffff04ff02ffff04ff0bff80808080ff8080808080ff0180ffff01ff02ffff010bff018080ff0180ff0180ffff01ff02ffff01ff0180ff018080ff0180ffffff02ff8200acffff04ff02ffff04ff03ffff04ffff02ff8200f4ffff04ff02ffff04ff09ffff04ff13ff8080808080ffff04ffff02ff8200f4ffff04ff02ffff04ff09ffff04ff2bff8080808080ff808080808080ffff02ff8200b4ffff04ff02ffff04ff11ffff04ff0bffff04ff17ff808080808080ff02ffff03ffff20ff1780ffff01ff02ffff010bff0180ffff01ff02ffff01ff02ffff03ffff02ff05ffff04ff0bffff04ffff05ff1780ffff0180808080ffff01ff02ffff01ff02ff8200ecffff04ff02ffff04ff05ffff04ffff05ff1780ffff04ffff06ff1780ff808080808080ff0180ffff01ff02ffff01ff02ff8200ecffff04ff02ffff04ff05ffff04ff0bffff04ffff06ff1780ff808080808080ff018080ff0180ff018080ff0180ffff02ff8200ecffff04ff02ffff04ff05ffff04ff13ffff04ff1bff808080808080ffff02ffff03ffff20ff0580ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff02ffff03ffff09ffff05ff0580ff0b80ffff01ff02ffff01ff02ffff03ffff09ff17ffff010480ffff01ff02ffff010bff0180ffff01ff02ffff01ff02ff8200bcffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ffff10ff17ffff010180ff808080808080ff018080ff0180ff0180ffff01ff02ffff01ff02ff8200bcffff04ff02ffff04ffff06ff0580ffff04ffff05ff0580ffff04ffff0101ff808080808080ff018080ff0180ff018080ff0180ff02ff8200bcffff04ff02ffff04ffff02ff8200f4ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff4280ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ffff04ff05ff8080808080ffff01ff80ff8080808080ffffffffff02ff50ffff04ff02ffff04ff0bffff04ff17ff8080808080ffff02ffff03ffff20ff0580ffff01ff02ffff01ff02ffff03ffff18ffff09ff17ffff010280ffff09ff2fffff010480ff0b80ffff01ff02ffff01ff0105ff0180ffff01ff02ffff01ff0180ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff09ff17ffff05ff058080ffff01ff02ffff01ff02ff8200a2ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ff17ffff04ff2fff80808080808080ff0180ffff01ff02ffff01ff02ffff03ffff09ffff05ff0580ffff11ff17ffff01018080ffff01ff02ffff01ff02ffff03ffff09ff2fffff010480ffff01ff02ffff01ff10ff17ffff010380ff0180ffff01ff02ffff01ff02ff8200a2ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ffff05ff0580ffff04ffff10ff2fffff010180ff80808080808080ff018080ff0180ff0180ffff01ff02ffff01ff02ff8200a2ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ffff05ff0580ffff04ffff0101ff80808080808080ff018080ff0180ff018080ff0180ff018080ff0180ff02ff8200a2ffff04ff02ffff04ff05ffff04ffff09ff09ffff010e80ffff01ff80ff808080808080ffff02ffff03ffff20ff0580ffff01ff02ffff01ff04ffff04ff17ff0b80ffff018080ff0180ffff01ff02ffff01ff02ffff03ffff09ffff05ff0580ff0b80ffff01ff02ffff01ff02ff52ffff04ff02ffff04ffff06ff0580ffff04ff0bffff04ffff10ff17ffff010180ff808080808080ff0180ffff01ff02ffff01ff02ff8200b2ffff04ff02ffff04ffff06ff0180ffff04ffff02ff52ffff04ff02ffff04ffff06ff0580ffff04ffff05ff0580ffff04ffff0101ff808080808080ff8080808080ff018080ff0180ff018080ff0180ffff04ffff04ff2dff1580ff0b80ff02ff52ffff04ff02ffff04ff05ffff04ff09ffff01ff808080808080ffffff02ff5affff04ff02ffff04ff03ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200aa80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200ea80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ff808080808080ff131bffff02ff8200faffff04ff02ffff04ff03ffff04ffff02ff8200fcffff04ff02ffff04ffff02ff8200e8ffff04ff02ffff04ff17ffff04ff09ffff01ff808080808080ff80808080ffff04ffff02ff8200f4ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200ba80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ffff04ffff02ff8200e8ffff04ff02ffff04ff0bffff04ff09ffff01ff808080808080ff8080808080ff808080808080ffff02ff50ffff04ff02ffff04ff0bffff04ff17ff8080808080ff02ff8200f6ffff04ff02ffff04ff03ffff04ffff02ffff03ffff20ff0b80ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff02ff8200e6ffff04ff02ffff04ffff06ff0180ffff04ffff02ff8200f4ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff4680ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ffff02ff58ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200a680ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff0bffff01808080ffff04ffff0101ffff0180808080ffff0180808080ffff04ff11ffff04ffff0180ff808080808080ff8080808080ff8080808080ff018080ff0180ffff04ffff02ff8200e2ffff04ff02ffff04ff17ff80808080ffff04ffff02ff8200f4ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200b680ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ffff04ffff02ff8200f2ffff04ff02ffff04ff17ff80808080ff8080808080ff80808080808080ffffffff02ff50ffff04ff02ffff04ff0bffff04ff17ff8080808080ffff02ffff03ffff09ff09ff1b80ffff01ff02ffff0113ff0180ffff01ff02ffff01ff0180ff018080ff0180ff02ff56ffff04ff02ffff04ff03ffff04ffff02ff8200e2ffff04ff02ffff04ff0bff80808080ff8080808080ffff02ffff03ff0bffff01ff02ffff01ff04ffff0109ffff04ff0bffff01808080ff0180ffff01ff02ffff01ff04ffff0106ffff02ff8200f8ffff04ff02ffff04ff15ffff04ffff0105ff808080808080ff018080ff0180ffff02ff50ffff04ff02ffff04ff0bffff04ff17ff8080808080ff02ff4effff04ff02ffff04ff03ffff04ffff02ffff03ff17ffff01ff02ffff01ff04ffff0105ffff04ff17ffff01808080ff0180ffff01ff02ffff01ff0180ff018080ff0180ffff04ff4fffff04ff81afffff04ffff02ff8200e8ffff04ff02ffff04ff59ffff04ff2fffff01ff808080808080ff8080808080808080ffffff02ff8200aeffff04ff02ffff04ff03ffff04ffff02ffff03ffff09ff27ffff010180ffff01ff02ffff01ff04ffff0101ffff02ff8200f8ffff04ff02ffff04ff5fffff04ffff0105ff808080808080ff0180ffff01ff02ffff01ff02ffff03ffff09ff27ffff010280ffff01ff02ffff01ff02ffff03ffff09ff4fffff010180ffff01ff02ffff01ff04ffff0102ffff02ff8200f8ffff04ff02ffff04ff5fffff04ffff0104ff808080808080ff0180ffff01ff02ffff01ff04ffff0103ffff02ff8200f8ffff04ff02ffff04ff5fffff04ffff0103ff808080808080ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff09ff27ffff010380ffff01ff02ffff01ff02ffff03ffff09ff4fffff010180ffff01ff02ffff01ff04ffff0104ffff02ff8200f8ffff04ff02ffff04ff5fffff04ffff0103ff808080808080ff0180ffff01ff02ffff01ff04ffff0107ffff02ff8200f8ffff04ff02ffff04ff5fffff04ffff0102ff808080808080ff018080ff0180ff0180ffff01ff02ffff01ff04ffff0108ffff02ff8200f8ffff04ff02ffff04ff5fffff04ffff0102ff808080808080ff018080ff0180ff018080ff0180ff018080ff0180ff8080808080ffff02ff5cffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200ee80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ffff04ffff04ff29ffff04ff15ffff04ff0bff80808080ff8080808080ff02ff8200e0ffff04ff02ffff04ff0bffff04ff17ff8080808080ffff02ff8200beffff04ff02ffff04ff03ffff04ffff02ff4affff04ff02ffff04ff15ff80808080ffff04ffff02ff4affff04ff02ffff04ff2dff80808080ff808080808080ffff02ffff03ffff02ff11ffff04ff0bffff04ff17ff80808080ffff01ff02ffff01ff02ffff03ffff02ff8200b0ffff04ff02ffff04ff0bffff04ffff02ff4affff04ff02ffff04ffff02ff48ffff04ff02ffff04ff29ff80808080ff80808080ff8080808080ffff01ff02ffff01ff02ffff03ffff02ff8200b0ffff04ff02ffff04ff17ffff04ffff02ff4affff04ff02ffff04ffff02ff48ffff04ff02ffff04ff59ff80808080ff80808080ff8080808080ffff01ff02ffff01ff02ffff03ff79ffff01ff02ffff01ff02ff5effff04ff02ffff04ff79ff80808080ff0180ffff01ff02ffff01ff0180ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff02ffff03ff03ffff01ff02ffff01ff02ff5effff04ff02ffff04ff03ff80808080ff0180ffff01ff02ffff01ff0180ff018080ff0180ff018080 diff --git a/resources/tests/game-referee-in-cl21/test_handcalc.sym b/resources/tests/game-referee-in-cl21/test_handcalc.sym new file mode 100644 index 000000000..4ff5ca1eb --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_handcalc.sym @@ -0,0 +1 @@ +{"dd3953423ae82b313d5361cb4c9ea7d18b43294e1c0801e1c021d101a7ce58f6_left_env": "1", "24d7dbd0fece56391d516812ca037a910985789b424144b4dc8f8c57cf3ce108": "straight_high_inner", "e51e3ecc739e0c9b646889ad797fa268d9acbb09f42f70b1a75be411440dcf36_left_env": "1", "76751a9c95444501c3ad57278f9ace3e6a1e41fca43bd93d6e5a8ca125e8c4a3_arguments": "(((myless_$_453 mylist_$_454) (a b)) sa sb)", "3ac370c3d91282c6eb94742d40cdb371de392eaca8a0a213d3d3ade6d1b03367_left_env": "1", "36900466483b112787abffe419202a499c8e5467e750cf3aec03ac5fd0ba9cfd_left_env": "1", "36900466483b112787abffe419202a499c8e5467e750cf3aec03ac5fd0ba9cfd_arguments": "(myless mylist)", "40fe864fddcab141770d7e0c0be5d5d07bcb8efd496a6f4bb2cdc3834e94eab9_left_env": "1", "c4e96a2219a3d6389693cfb81c4309f5bf5f1a89f300c7c12d019e08d14cde09_arguments": "(a b)", "1c2f95563ff25508afc464b19cd91787c95ac0b12f1d4fa16addeaa6335aac8d_arguments": "((((((cards_$_473) first rest) fsuit nosuits) max_flush sh groups) max_straight (top_count . top_card) (second_count . second_card) topcards) max_group)", "01ed928ebc640669bfdc000b292962b919f6635176dd9119325f5f912d7567b8_arguments": "(() x y)", "a87d2e2e13539c8f9f66137bdee9a7fd750b8bdb6a07fc1e6cd8416d771d9958_arguments": "(() x y)", "c60f4e2e12ab7285ef437f63bb24f4e5e6267fc76479893a179ebae738aca004": "letbinding_$_481", "64499f3fb4ed1322a24ece83ce5664a10e41b8cb291c4c395d961004680802ca_arguments": "(process remaining init)", "ff5f6181808cb059cffecd54a408a6b4566b861a8905208bbeb87a10e3c8ec65": "merge", "d8c50d6282a1ba47f0a23430d177bbfbb72e2b84713745e894f575570f1f3d6e": "lambda_$_486", "973ed02dde4588cd7699bdec8c1138e788edf49380ca7a8c62c74ad021bf8022_arguments": "((((cards_$_473) first rest) fsuit nosuits) fnosuits)", "1bde90fbef9d7a4c5cb7133780d4275aa03dfc0a54a905b899d65b4b578f6661": "letbinding_$_479", "4b216afca35845442571c30c6d827724285ca82490dbdae1b27f2d082e85ff66": "runtests", "64499f3fb4ed1322a24ece83ce5664a10e41b8cb291c4c395d961004680802ca_left_env": "1", "f5470fda7b930fc12a27be2810e4c48ad7e35ceda81273ba026cd6da98d94c3c_left_env": "1", "5c2c8bfc9ac6c103562c9017a5cee2634da7ee43d44bd4f3d46d11e519942ea6": "straight_high", "724d50ee95e66b90e255e2cecc58cc35c2eb27302b1952948538ad95f7387a4b_arguments": "(F L R)", "24d7dbd0fece56391d516812ca037a910985789b424144b4dc8f8c57cf3ce108_arguments": "(ranks started_ace last count)", "ea58983a62a5d0a526c32f3423717af26c6d9d5963eb4831a0d1049227eba060_arguments": "(suits last count)", "26df51fddc60f80f199438e505e3832df819036418c8bf439a572679ebfd1897": "split_inner", "d8c50d6282a1ba47f0a23430d177bbfbb72e2b84713745e894f575570f1f3d6e_left_env": "1", "2379a74341919286585b51fa8ff2bf5a2e76254197c786fdcd96d4b004be17ba": "deep>", "3ac370c3d91282c6eb94742d40cdb371de392eaca8a0a213d3d3ade6d1b03367_arguments": "(a b)", "7245d12b7785f1ee23a0ec0d3a03432057ec41fb0561d373d91cda267f44c3e9": "reverse", "b131c2e07b1152ba1bd67a5398a6b58cde3020e01fa510f0f7c3cd502fcdb30d_left_env": "1", "c64dc59aae25053fe8d872e13fca4e2c43765a1a83335d520435180f3ab55485_arguments": "(myless A B agg)", "d121f71fcb5513b6d2b097255deb884ff40c26dd366b0ba7cf2eea1440b07901_left_env": "1", "6776e296095747790c1a208caea4e4b8633e2c146890367f13a0238f42b28c87_left_env": "1", "0dda9e9f845e653fbb9f1065f098a0c439bf605b2e8830546184c95eae822f25_arguments": "((process_$_431 remaining_$_432 init_$_433) next)", "76751a9c95444501c3ad57278f9ace3e6a1e41fca43bd93d6e5a8ca125e8c4a3_left_env": "1", "20f4eca5a09be558c75518290c48d6aad0e4e8306e79cf03e92b8ca828d35f99": "runtests_inner", "c4f6f8551c01bbcf52ab1fd2b92333649110b28aee8570a9422e2b3a671fe94b_arguments": "((((cards_$_473) first rest) fsuit nosuits) max_flush sh groups)", "d121f71fcb5513b6d2b097255deb884ff40c26dd366b0ba7cf2eea1440b07901_arguments": "(mylist)", "00c86eab1caeadaaf967420becbefef7170e5e996890edc355d16c263ea32e27_arguments": "(myless best_so_far mylist)", "ca3aa00f92cd656fbf2e7c7863a2bd3ebfcdf0bdb05ca8f00ce9d51648d38b1f_arguments": "(a b)", "042c55b626937b8d6be258a97f8d25cdedeee2e712dbddef9438fa900eff883e_left_env": "1", "24d7dbd0fece56391d516812ca037a910985789b424144b4dc8f8c57cf3ce108_left_env": "1", "6776e296095747790c1a208caea4e4b8633e2c146890367f13a0238f42b28c87_arguments": "(((((cards_$_473) first rest) fsuit nosuits) max_flush sh groups) max_straight (top_count . top_card) (second_count . second_card) topcards)", "40fe864fddcab141770d7e0c0be5d5d07bcb8efd496a6f4bb2cdc3834e94eab9_arguments": "((items_$_469 last_$_470 count_$_471) val)", "0dda9e9f845e653fbb9f1065f098a0c439bf605b2e8830546184c95eae822f25_left_env": "1", "5c2c8bfc9ac6c103562c9017a5cee2634da7ee43d44bd4f3d46d11e519942ea6_arguments": "(ranks)", "8bda8ccb43702a3e1a1b2354adfb39e9a229ae4dc896e7481a569ecc19dd2d6d": "deep<", "0dda9e9f845e653fbb9f1065f098a0c439bf605b2e8830546184c95eae822f25": "letbinding_$_480", "724d50ee95e66b90e255e2cecc58cc35c2eb27302b1952948538ad95f7387a4b": "map-with-rest", "40fe864fddcab141770d7e0c0be5d5d07bcb8efd496a6f4bb2cdc3834e94eab9": "letbinding_$_484", "8c4576eb20d2f8cc795c065e3a585703145c1f6beff372bf37b4634ad785adc8": "letbinding_$_488", "ff5f6181808cb059cffecd54a408a6b4566b861a8905208bbeb87a10e3c8ec65_left_env": "1", "ea58983a62a5d0a526c32f3423717af26c6d9d5963eb4831a0d1049227eba060_left_env": "1", "2379a74341919286585b51fa8ff2bf5a2e76254197c786fdcd96d4b004be17ba_arguments": "(a b)", "8c4576eb20d2f8cc795c065e3a585703145c1f6beff372bf37b4634ad785adc8_left_env": "1", "__chia__main_arguments": "()", "b131c2e07b1152ba1bd67a5398a6b58cde3020e01fa510f0f7c3cd502fcdb30d": "letbinding_$_485", "c64b0acdb9bfc5a1bec80732d64bee90fd12e869207674a220042725441f9cb3": "find_flush", "7245d12b7785f1ee23a0ec0d3a03432057ec41fb0561d373d91cda267f44c3e9_arguments": "(vals)", "a87d2e2e13539c8f9f66137bdee9a7fd750b8bdb6a07fc1e6cd8416d771d9958": "lambda_$_494", "01ed928ebc640669bfdc000b292962b919f6635176dd9119325f5f912d7567b8": "lambda_$_498", "b16167d2466d1fb9c6fd4b5636fa809f866e9b7a0a698f1a18ffa308d7280c42": "letbinding_$_499", "f5470fda7b930fc12a27be2810e4c48ad7e35ceda81273ba026cd6da98d94c3c": "slice", "76751a9c95444501c3ad57278f9ace3e6a1e41fca43bd93d6e5a8ca125e8c4a3": "letbinding_$_482", "1c2f95563ff25508afc464b19cd91787c95ac0b12f1d4fa16addeaa6335aac8d": "letbinding_$_497", "042c55b626937b8d6be258a97f8d25cdedeee2e712dbddef9438fa900eff883e_arguments": "(R P)", "8bda8ccb43702a3e1a1b2354adfb39e9a229ae4dc896e7481a569ecc19dd2d6d_left_env": "1", "26df51fddc60f80f199438e505e3832df819036418c8bf439a572679ebfd1897_arguments": "(@ everything (rest aggl aggr))", "24d45638962c8ac6b0923f0f2c912177b1b1c710bbcd3e10fccf01fc6f771263_arguments": "(myless mylist)", "d013fcaaa576d263aa86406509a11272424931651d958cff6ba9be6d2b9a7fed_arguments": "(items last count)", "24d45638962c8ac6b0923f0f2c912177b1b1c710bbcd3e10fccf01fc6f771263": "sort", "4b216afca35845442571c30c6d827724285ca82490dbdae1b27f2d082e85ff66_arguments": "tests", "b131c2e07b1152ba1bd67a5398a6b58cde3020e01fa510f0f7c3cd502fcdb30d_arguments": "((cards_$_473) first rest)", "c64dc59aae25053fe8d872e13fca4e2c43765a1a83335d520435180f3ab55485": "merge_inner", "973ed02dde4588cd7699bdec8c1138e788edf49380ca7a8c62c74ad021bf8022": "letbinding_$_491", "1bde90fbef9d7a4c5cb7133780d4275aa03dfc0a54a905b899d65b4b578f6661_left_env": "1", "973ed02dde4588cd7699bdec8c1138e788edf49380ca7a8c62c74ad021bf8022_left_env": "1", "source_file": "/home/arty/dev/chia/clvm_tools_rs/resources/tests/game-referee-in-cl21/test_handcalc.clsp", "ca3aa00f92cd656fbf2e7c7863a2bd3ebfcdf0bdb05ca8f00ce9d51648d38b1f_left_env": "1", "20f4eca5a09be558c75518290c48d6aad0e4e8306e79cf03e92b8ca828d35f99_arguments": "((myfunc firstarg secondarg . remaining))", "471488bbd4b64848f0c6592900ef2a751e8907a72557b0ba794e0d6f1252c374_left_env": "1", "ff5f6181808cb059cffecd54a408a6b4566b861a8905208bbeb87a10e3c8ec65_arguments": "(myless a b)", "00c86eab1caeadaaf967420becbefef7170e5e996890edc355d16c263ea32e27": "max_inner", "26df51fddc60f80f199438e505e3832df819036418c8bf439a572679ebfd1897_left_env": "1", "00c86eab1caeadaaf967420becbefef7170e5e996890edc355d16c263ea32e27_left_env": "1", "d013fcaaa576d263aa86406509a11272424931651d958cff6ba9be6d2b9a7fed": "group_by_count_inner", "c4e96a2219a3d6389693cfb81c4309f5bf5f1a89f300c7c12d019e08d14cde09": "prepend", "145bfb83f7b3ef33ac1eada788c187e4d1feb7326bcf340bb060a62e75434854_left_env": "1", "1c2f95563ff25508afc464b19cd91787c95ac0b12f1d4fa16addeaa6335aac8d_left_env": "1", "f4c3c71dddb1c7ee50bc104032f26172d61ff77f9bca9876d1846c47cd72020e": "handcalc", "7245d12b7785f1ee23a0ec0d3a03432057ec41fb0561d373d91cda267f44c3e9_left_env": "1", "a87d2e2e13539c8f9f66137bdee9a7fd750b8bdb6a07fc1e6cd8416d771d9958_left_env": "1", "c64b0acdb9bfc5a1bec80732d64bee90fd12e869207674a220042725441f9cb3_arguments": "(suits)", "c4e96a2219a3d6389693cfb81c4309f5bf5f1a89f300c7c12d019e08d14cde09_left_env": "1", "36900466483b112787abffe419202a499c8e5467e750cf3aec03ac5fd0ba9cfd": "max", "d013fcaaa576d263aa86406509a11272424931651d958cff6ba9be6d2b9a7fed_left_env": "1", "1bde90fbef9d7a4c5cb7133780d4275aa03dfc0a54a905b899d65b4b578f6661_arguments": "((a_$_404 b_$_405) inner_result)", "64499f3fb4ed1322a24ece83ce5664a10e41b8cb291c4c395d961004680802ca": "filtermap", "e51e3ecc739e0c9b646889ad797fa268d9acbb09f42f70b1a75be411440dcf36": "lambda_$_493", "c4f6f8551c01bbcf52ab1fd2b92333649110b28aee8570a9422e2b3a671fe94b_left_env": "1", "79f3cf5c572162105f8688174041050314a154956ef27d7ea6414a9dcd402faa_arguments": "(items)", "042c55b626937b8d6be258a97f8d25cdedeee2e712dbddef9438fa900eff883e": "print", "e51e3ecc739e0c9b646889ad797fa268d9acbb09f42f70b1a75be411440dcf36_arguments": "((fsuit) (card_rank . card_suit))", "f4c3c71dddb1c7ee50bc104032f26172d61ff77f9bca9876d1846c47cd72020e_arguments": "(cards)", "b16167d2466d1fb9c6fd4b5636fa809f866e9b7a0a698f1a18ffa308d7280c42_arguments": "(((myfunc_$_474 firstarg_$_475 secondarg_$_476 . remaining_$_477)) firstval secondval)", "8bda8ccb43702a3e1a1b2354adfb39e9a229ae4dc896e7481a569ecc19dd2d6d_arguments": "(a b)", "471488bbd4b64848f0c6592900ef2a751e8907a72557b0ba794e0d6f1252c374": "reverse_inner", "f5470fda7b930fc12a27be2810e4c48ad7e35ceda81273ba026cd6da98d94c3c_arguments": "(mylist count)", "c64dc59aae25053fe8d872e13fca4e2c43765a1a83335d520435180f3ab55485_left_env": "1", "79f3cf5c572162105f8688174041050314a154956ef27d7ea6414a9dcd402faa": "group_by_count", "b16167d2466d1fb9c6fd4b5636fa809f866e9b7a0a698f1a18ffa308d7280c42_left_env": "1", "2379a74341919286585b51fa8ff2bf5a2e76254197c786fdcd96d4b004be17ba_left_env": "1", "724d50ee95e66b90e255e2cecc58cc35c2eb27302b1952948538ad95f7387a4b_left_env": "1", "5c2c8bfc9ac6c103562c9017a5cee2634da7ee43d44bd4f3d46d11e519942ea6_left_env": "1", "c64b0acdb9bfc5a1bec80732d64bee90fd12e869207674a220042725441f9cb3_left_env": "1", "79f3cf5c572162105f8688174041050314a154956ef27d7ea6414a9dcd402faa_left_env": "1", "145bfb83f7b3ef33ac1eada788c187e4d1feb7326bcf340bb060a62e75434854": "lambda_$_487", "c60f4e2e12ab7285ef437f63bb24f4e5e6267fc76479893a179ebae738aca004_arguments": "((myless_$_453 mylist_$_454) (a b))", "dd3953423ae82b313d5361cb4c9ea7d18b43294e1c0801e1c021d101a7ce58f6_arguments": "(((((cards_$_473) first rest) fsuit nosuits) fnosuits) fsh)", "d8c50d6282a1ba47f0a23430d177bbfbb72e2b84713745e894f575570f1f3d6e_arguments": "(() x)", "f4c3c71dddb1c7ee50bc104032f26172d61ff77f9bca9876d1846c47cd72020e_left_env": "1", "6776e296095747790c1a208caea4e4b8633e2c146890367f13a0238f42b28c87": "letbinding_$_496", "24d45638962c8ac6b0923f0f2c912177b1b1c710bbcd3e10fccf01fc6f771263_left_env": "1", "d121f71fcb5513b6d2b097255deb884ff40c26dd366b0ba7cf2eea1440b07901": "split", "01ed928ebc640669bfdc000b292962b919f6635176dd9119325f5f912d7567b8_left_env": "1", "4b216afca35845442571c30c6d827724285ca82490dbdae1b27f2d082e85ff66_left_env": "1", "c4f6f8551c01bbcf52ab1fd2b92333649110b28aee8570a9422e2b3a671fe94b": "letbinding_$_490", "dd3953423ae82b313d5361cb4c9ea7d18b43294e1c0801e1c021d101a7ce58f6": "letbinding_$_495", "c60f4e2e12ab7285ef437f63bb24f4e5e6267fc76479893a179ebae738aca004_left_env": "1", "ca3aa00f92cd656fbf2e7c7863a2bd3ebfcdf0bdb05ca8f00ce9d51648d38b1f": "deep=", "ea58983a62a5d0a526c32f3423717af26c6d9d5963eb4831a0d1049227eba060": "find_flush_inner", "20f4eca5a09be558c75518290c48d6aad0e4e8306e79cf03e92b8ca828d35f99_left_env": "1", "8c4576eb20d2f8cc795c065e3a585703145c1f6beff372bf37b4634ad785adc8_arguments": "(((cards_$_473) first rest) fsuit nosuits)", "145bfb83f7b3ef33ac1eada788c187e4d1feb7326bcf340bb060a62e75434854_arguments": "(() x)", "3ac370c3d91282c6eb94742d40cdb371de392eaca8a0a213d3d3ade6d1b03367": "deep_compare", "471488bbd4b64848f0c6592900ef2a751e8907a72557b0ba794e0d6f1252c374_arguments": "(reversed rest)"} \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl21/test_handcalc_b.clsp b/resources/tests/game-referee-in-cl21/test_handcalc_b.clsp new file mode 100644 index 000000000..674bbd414 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_handcalc_b.clsp @@ -0,0 +1,377 @@ + +(mod () + (include *standard-cl-21*) + (include deep_compare.clinc) + (include assert.clinc) + (include reverse.clinc) + (include prepend.clinc) + (include map.clinc) + (include filtermap.clinc) + (include slice.clinc) + (include print.clinc) + (include handcalc.clinc) + + (defun runtests_inner ((myfunc firstarg secondarg . remaining)) + (assign-lambda + firstval (handcalc firstarg) + secondval (handcalc secondarg) + (assert + (a myfunc (list firstval secondval)) + (deep= firstval (handcalc (reverse firstarg))) + (deep= secondval (handcalc (reverse secondarg))) + (if remaining + (runtests_inner remaining) + 0 + ) + ) + ) + ) + + (defun runtests tests (if tests (runtests_inner tests) ())) + + ;; Join these up when large application bug is fixed. + (runtests + ; all beats both emerge over and measure higher + ; straight flush with higher kicker ties + ; A1 K1 Q1 J1 T1 91 = A1 K1 Q1 J1 T1 81 + deep= + (list (c 12 1) (c 11 1) (c 14 1) (c 13 1) (c 10 1) (c 9 1)) + (list (c 12 1) (c 11 1) (c 14 1) (c 13 1) (c 10 1) (c 8 1)) + ; straight flushes of different suits tie + ; A1 K1 Q1 J1 T1 = A2 K2 Q2 J2 T2 + deep= + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 10 1)) + (list (c 14 2) (c 13 2) (c 12 2) (c 11 2) (c 10 2)) + ; higher straight flush beats lower straight flush + ; A1 K1 Q1 J1 T1 > 61 51 41 31 21 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 10 1)) + (list (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + ; A1 K1 Q1 J1 T1 91 = A1 K1 Q1 J1 T1 + deep= + (list (c 12 1) (c 11 1) (c 14 1) (c 13 1) (c 10 1) (c 9 1)) + (list (c 14 2) (c 11 2) (c 10 2) (c 13 2) (c 12 2)) + ; lower (2-6) straight flush beats ace to four straight flush + ; 61 51 41 31 21 > A2 52 42 32 22 + deep> + (list (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 14 2) (c 5 2) (c 4 2) (c 3 2) (c 2 2)) + ; A1 61 51 41 31 21 = 61 51 41 31 21 + deep= + (list (c 14 1) (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + ; ace to four straight flush with higher kicker ties + ; A2 52 42 32 22 61 = A1 51 41 31 21 71 + deep= + (list (c 14 2) (c 5 2) (c 4 2) (c 3 2) (c 2 2) (c 6 1)) + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1) (c 7 1)) + ; ace to four straight flushes of different suits tie + ; A1 51 41 31 21 = A2 52 42 32 22 + deep= + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 14 2) (c 5 2) (c 4 2) (c 3 2) (c 2 2)) + ; ace to four straight flush beats four of a kind + ; A1 51 41 31 21 > K1 K2 K3 K4 J1 + deep> + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 11 1)) + ; A1 A2 A3 A4 51 41 31 21 = A1 51 41 31 21 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + ; four of a kind with higher kicker wins + ; K1 K2 K3 K4 Q1 > K1 K2 K3 K4 J1 + deep> + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 12 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 11 1)) + ; K1 K2 K3 K4 T1 91 = K1 K2 K3 K4 T1 + deep= + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 10 1) (c 9 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 10 1)) + ; four of a kind with higher second kicker ties + ; K1 K2 K3 K4 Q1 J1 = K1 K2 K3 K4 Q1 T1 + deep= + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 12 1) (c 11 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 12 1) (c 10 1)) + ; higher four of a kind beats lower four of a kind + ; K1 K2 K3 K4 21 > 31 32 33 34 A1 + deep> + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 2 1)) + (list (c 3 1) (c 3 2) (c 3 3) (c 3 4) (c 14 1)) + ; K1 K2 K3 K4 31 32 33 34 = K1 K2 K3 K4 32 + deep= + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 3 1) (c 3 2) (c 3 3) (c 3 4)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 3 2)) + ; four of a kind beats full house + ; 21 22 23 24 31 > A1 A2 A3 K1 K2 + deep> + (list (c 2 1) (c 2 2) (c 2 3) (c 2 4) (c 3 1)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2)) + ; 21 22 23 24 A1 A2 A3 = 21 22 23 24 A2 + deep= + (list (c 2 1) (c 2 2) (c 2 3) (c 2 4) (c 14 1) (c 14 2) (c 14 3)) + (list (c 2 1) (c 2 2) (c 2 3) (c 2 4) (c 14 2)) + ; full house with higher set wins + ; 51 52 53 21 22 > 31 32 33 71 72 + deep> + (list (c 5 1) (c 5 2) (c 5 3) (c 2 1) (c 2 2)) + (list (c 3 1) (c 3 2) (c 3 3) (c 7 1) (c 7 2)) + ; A1 A2 A3 K1 K2 K3 = A1 A2 A3 K1 K2 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2) (c 13 3)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2)) + ; full house with same set and higher pair wins + ; 51 52 53 41 42 > 51 52 53 31 32 + deep> + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2)) + (list (c 5 1) (c 5 2) (c 5 3) (c 3 1) (c 3 2)) + ; A1 A2 A3 K1 K2 51 52 = A1 A2 A3 K1 K2 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2) (c 5 1) (c 5 2)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2)) + ; full house ties with two sets + ; 51 52 53 41 42 A1 = 51 52 53 41 42 43 + deep= + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2) (c 14 1)) + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2) (c 4 3)) + ; full house beats flush + ; 51 52 53 41 42 > A1 Q1 T1 81 71 + deep> + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2)) + (list (c 14 1) (c 12 1) (c 10 1) (c 8 1) (c 7 1)) + ; 51 52 53 41 42 A1 K1 Q1 = 51 52 53 41 42 + deep= + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2) (c 14 1) (c 13 1) (c 12 1)) + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2)) + ; higher flush beats lower flush + ; A1 61 51 41 31 > K1 Q1 J1 T1 81 + deep> + (list (c 14 1) (c 6 1) (c 5 1) (c 4 1) (c 3 1)) + (list (c 13 1) (c 12 2) (c 11 1) (c 10 1) (c 8 1)) + ; A1 K1 Q1 J1 81 71 = A1 K1 Q1 J1 81 + deep= + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 8 1) (c 7 1)) + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 8 1)) + ; flush with higher second card wins + ; A1 K1 51 41 31 > A1 Q1 J1 T1 91 + deep> + (list (c 14 1) (c 13 1) (c 5 1) (c 4 1) (c 3 1)) + (list (c 14 1) (c 12 2) (c 11 1) (c 10 1) (c 9 1)) + ; flush with higher third card wins + ; A1 K1 Q1 41 31 > A1 K1 J1 T1 91 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 4 1) (c 3 1)) + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 9 1)) + ; flush with higher fourth card wins + ; A1 K1 Q1 T1 21 > A1 K1 Q1 91 81 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 10 1) (c 2 1)) + (list (c 14 1) (c 13 1) (c 12 1) (c 9 1) (c 8 1)) + ; flush with higher fifth card wins + ; A1 K1 Q1 T1 81 > A1 K1 Q1 T1 71 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 10 1) (c 8 1)) + (list (c 14 1) (c 13 1) (c 12 1) (c 10 1) (c 7 1)) + ; flushes of different suits tie + ; A1 K1 J1 T1 81 = A2 K2 J2 T2 82 + deep= + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 8 1)) + (list (c 14 2) (c 13 2) (c 11 2) (c 10 2) (c 8 2)) + ; same flush with higher sixth card ties + ; A1 K1 J1 T1 81 71 = A1 K1 J1 T1 81 61 + deep= + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 8 1) (c 7 1)) + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 8 1) (c 6 1)) + ; flush beats straight + ; 71 61 51 41 21 > A1 K2 Q3 J4 T1 + deep> + (list (c 7 1) (c 6 1) (c 5 1) (c 4 1) (c 2 1)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1)) + ; A1 K2 Q3 J4 T1 81 71 61 = A1 T1 81 71 61 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 8 1) (c 7 1) (c 6 1)) + (list (c 14 1) (c 10 1) (c 8 1) (c 7 1) (c 6 1)) + ; straight with higher kicker ties + ; A1 K2 Q3 J4 T1 92 = A1 K2 Q3 J4 T1 22 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 9 2)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 2 2)) + ; straights of different suits tie + ; A1 K2 Q3 J4 T1 = A2 K3 Q4 J1 T2 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1)) + (list (c 14 2) (c 13 3) (c 12 4) (c 11 1) (c 10 2)) + ; higher straight beats lower straight + ; A1 K2 Q3 J4 T1 > 61 52 43 34 21 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1)) + (list (c 6 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + ; A1 K2 Q3 J4 T1 92 83 = A1 K2 Q3 J4 T1 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 9 2) (c 8 3)) + (list (c 14 2) (c 13 3) (c 12 4) (c 11 1) (c 10 2)) + ; lower (2-6) straight beats ace to four straight + ; 61 52 43 34 21 > A1 52 43 34 21 + deep> + (list (c 6 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + ; A1 62 53 44 31 22 = 62 53 44 31 22 + deep= + (list (c 14 1) (c 6 2) (c 5 3) (c 4 4) (c 3 1) (c 2 2)) + (list (c 6 2) (c 5 3) (c 4 4) (c 3 1) (c 2 2)) + ; ace to four straight with higher kicker ties + ; A1 52 43 34 21 K2 = A1 52 43 34 21 72 + deep= + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1) (c 13 2)) + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1) (c 7 2)) + ; ace to fours of different suits tie + ; A1 52 43 34 21 = A2 53 44 31 22 + deep= + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 2) (c 5 3) (c 4 4) (c 3 1) (c 2 2)) + ; ace to four straight beats set + ; A1 52 43 34 21 > A1 A2 A3 K1 Q2 + deep> + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 12 2)) + ; A1 A2 A3 52 43 34 21 = A1 52 43 34 21 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 5 2) (c 4 3) (c 3 2) (c 2 1)) + ; higher set wins + ; 71 72 73 34 21 > 51 52 53 A4 K1 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 3 4) (c 2 1)) + (list (c 5 1) (c 5 2) (c 5 3) (c 14 4) (c 13 1)) + ; set with higher first kicker wins + ; 71 72 73 A1 22 > 71 72 73 K1 Q2 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 2 2)) + (list (c 7 1) (c 7 2) (c 7 3) (c 13 1) (c 12 2)) + ; 71 72 73 A1 K2 J3 54 43 = 71 72 73 A1 K2 + deep= + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2) (c 11 3) (c 5 4) (c 4 3)) + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2)) + ; set with higher second kicker wins + ; 71 72 73 A1 K2 > 71 72 73 A1 Q2 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2)) + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 12 2)) + ; set with higher third kicker ties + ; 71 72 73 A1 K2 Q3 = 71 72 73 A1 K2 J3 + deep= + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2) (c 12 3)) + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2) (c 11 3)) + ; set beats two pair + ; 71 72 73 34 21 > A1 A2 K3 K4 Q1 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 14 2) (c 13 3) (c 13 4) (c 12 1)) + ; two pair with higher high pair wins + ; K1 K2 33 34 21 > Q1 Q2 J3 J4 A1 + deep> + (list (c 13 1) (c 13 2) (c 3 3) (c 3 4) (c 2 1)) + (list (c 12 1) (c 12 2) (c 11 3) (c 11 4) (c 14 1)) + ; A1 A2 K1 K2 J1 J2 = A1 A2 K1 K2 J3 + deep= + (list (c 14 1) (c 14 2) (c 13 1) (c 13 2) (c 11 1) (c 11 2)) + (list (c 14 1) (c 14 2) (c 13 1) (c 13 2) (c 11 3)) + ; two pair with tied higher pair and higher lower pair wins + ; K1 K2 71 72 23 > K1 K2 63 64 A1 + deep> + (list (c 13 1) (c 13 2) (c 7 1) (c 7 2) (c 2 3)) + (list (c 13 1) (c 13 2) (c 6 3) (c 6 4) (c 14 1)) + ; two pair with higher kicker wins + ; K1 K2 Q3 Q4 J1 > K1 K2 Q3 Q4 T1 + deep> + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 11 1)) + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 10 1)) + ; K1 K2 Q3 Q4 A1 T1 92 63 = K1 K2 Q3 Q4 A1 + deep= + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 14 1) (c 10 1) (c 9 2) (c 6 3)) + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 14 1)) + ; two pair with higher second kicker ties + ; K1 K2 Q3 Q4 J1 T2 = K1 K2 Q3 Q4 J1 92 + deep= + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 11 1) (c 10 2)) + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 11 1) (c 9 2)) + ; two pair beats pair + ; 41 42 33 34 21 > A1 A2 K3 Q4 J1 + deep> + (list (c 4 1) (c 4 2) (c 3 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 14 2) (c 13 3) (c 12 4) (c 11 1)) + ; higher pair wins + ; 71 72 53 44 31 > 61 62 A3 K4 Q1 + deep> + (list (c 7 1) (c 7 2) (c 5 3) (c 4 4) (c 3 1)) + (list (c 6 1) (c 6 2) (c 14 3) (c 13 4) (c 12 1)) + ; tied pair with higher first kicker wins + ; 91 92 A3 34 21 > 91 92 K3 Q4 J1 + deep> + (list (c 9 1) (c 9 2) (c 14 3) (c 3 4) (c 2 1)) + (list (c 9 1) (c 9 2) (c 13 3) (c 12 4) (c 11 1)) + ; 21 22 A1 Q2 J3 94 81 = 21 22 A1 Q2 J3 + deep= + (list (c 2 1) (c 2 2) (c 14 1) (c 12 2) (c 11 3) (c 9 4) (c 8 1)) + (list (c 2 1) (c 2 2) (c 14 1) (c 12 2) (c 11 3)) + ; tied pair with higher second kicker wins + ; 91 92 A3 K4 21 > 91 92 A3 Q4 J1 + deep> + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 2 1)) + (list (c 9 1) (c 9 2) (c 14 3) (c 12 4) (c 11 1)) + ; tied pair with higher third kicker wins + ; 91 92 A3 K4 Q1 > 91 92 A3 K4 J1 + deep> + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 12 1)) + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 11 1)) + ; tied pair with higher fourth kicker ties + ; 91 92 A3 K4 Q1 J2 = 91 92 A3 K4 Q1 T2 + deep= + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 12 1) (c 11 2)) + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 12 1) (c 10 2)) + ; pair beats high card + ; 21 22 33 44 51 > A1 Q2 J3 T4 91 + deep> + (list (c 2 1) (c 2 2) (c 3 3) (c 4 4) (c 5 1)) + (list (c 14 1) (c 12 2) (c 11 3) (c 10 4) (c 9 1)) + ; higher high card wins + ; A1 22 33 44 61 > K1 Q2 J3 T4 81 + deep> + (list (c 14 1) (c 2 2) (c 3 3) (c 4 4) (c 6 1)) + (list (c 13 1) (c 12 2) (c 11 3) (c 10 4) (c 8 1)) + ; A1 K2 J3 T4 81 72 53 = A1 K2 J3 T4 81 + deep= + (list (c 14 1) (c 13 2) (c 11 3) (c 10 4) (c 8 1) (c 7 2) (c 5 3)) + (list (c 14 1) (c 13 2) (c 11 3) (c 10 4) (c 8 1)) + ; higher second card wins + ; A1 K2 23 34 41 > A1 Q2 J3 T4 91 + deep> + (list (c 14 1) (c 13 2) (c 2 3) (c 3 4) (c 4 1)) + (list (c 14 1) (c 12 2) (c 11 3) (c 10 4) (c 9 1)) + ; higher third card wins + ; A1 K2 Q3 24 41 > A1 K2 J3 T4 91 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 2 4) (c 4 1)) + (list (c 14 1) (c 13 2) (c 11 3) (c 10 4) (c 9 1)) + ; higher fourth card wins + ; A1 K2 Q3 J4 31 > A1 K2 Q3 T4 91 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 3 1)) + (list (c 14 1) (c 13 2) (c 12 3) (c 10 4) (c 9 1)) + ; higher fifth card wins + ; A1 K2 Q3 J4 91 > A1 K2 Q3 J4 81 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 8 1)) + ; higher sixth card ties + ; A1 K2 Q3 J4 91 22 = A1 K2 Q3 J4 91 82 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1) (c 2 2)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1) (c 8 2)) + ; high cards of different suits ties + ; A1 K2 Q3 J4 91 = A2 K3 Q4 J1 92 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1)) + (list (c 14 2) (c 13 3) (c 12 4) (c 11 1) (c 9 2)) + ) +) diff --git a/resources/tests/game-referee-in-cl21/test_library_basics.py b/resources/tests/game-referee-in-cl21/test_library_basics.py new file mode 100644 index 000000000..c8cce6664 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_library_basics.py @@ -0,0 +1,165 @@ +import os +import pytest +import random +from itertools import permutations +from typing import List +#from hsms.streamables.program import Program +#from steprun import diag_run_clvm, compile_module_with_symbols +#from lib.program import Program +from pathlib import Path +from clvm_rs import Program +from lib.steprun import diag_run_clvm, compile_module_with_symbols +from clvm_tools_rs import get_version + +print(f"clvm_tools_rs version is {get_version()}") +#include_dirs = os.getcwd() +include_dirs = [Path(__file__).parent, Path(__file__).parent.parent / "lib"] +Program.set_run_unsafe_max_cost(11000000000) + +print(f"XXX: {include_dirs}") +compile_module_with_symbols(include_dirs, 'smoke_test_deep_compare.clsp') +compare_program = Program.from_bytes(bytes.fromhex(open('smoke_test_deep_compare.clvm.hex').read())) + +compile_module_with_symbols(include_dirs, 'smoke_test_sort.clsp') +sort_program = Program.from_bytes(bytes.fromhex(open('smoke_test_sort.clvm.hex').read())) + +compile_module_with_symbols(include_dirs, 'test_sort.clsp') +test_sort_program = Program.from_bytes(bytes.fromhex(open('test_sort.clvm.hex').read())) + +compile_module_with_symbols(include_dirs, 'test_permutations.clsp') +test_permutations_program = Program.from_bytes(bytes.fromhex(open('test_permutations.clvm.hex').read())) + +compile_module_with_symbols(include_dirs, 'test_reverse.clsp') +test_reverse_program = Program.from_bytes(bytes.fromhex(open('test_reverse.clvm.hex').read())) + +compile_module_with_symbols(include_dirs, 'test_prepend.clsp') +test_prepend_program = Program.from_bytes(bytes.fromhex(open('test_prepend.clvm.hex').read())) + +compile_module_with_symbols(include_dirs, 'test_range.clsp') +test_range_program = Program.from_bytes(bytes.fromhex(open('test_range.clvm.hex').read())) + +compile_module_with_symbols(include_dirs, 'smoke_test_permutations.clsp') +smoke_test_permutations_program = Program.from_bytes(bytes.fromhex(open('smoke_test_permutations.clvm.hex').read())) + +compile_module_with_symbols(include_dirs, 'test_handcalc.clsp') +test_handcalc_program = Program.from_bytes(bytes.fromhex(open('test_handcalc.clvm.hex').read())) + +def as_atom_list(prg: Program) -> List[bytes]: + """ + Pretend `prg` is a list of atoms. Return the corresponding + python list of atoms. + + At each step, we always assume a node to be an atom or a pair. + If the assumption is wrong, we exit early. This way we never fail + and always return SOMETHING. + """ + items = [] + obj = prg + while True: + pair = obj.pair + if pair is None: + break + atom = pair[0].atom + if atom is None: + break + items.append(atom) + obj = pair[1] + return items + +def test_smoke_compare(): + compare_program.run(Program.to([])) + +def test_handcalc(): + diag_run_clvm(test_handcalc_program, Program.to([]), 'test_handcalc.sym', {'print': True}) + +def proper_list_inner(result,cl): + if hasattr(cl, 'pair') and cl.pair is not None: + result.append(cl.pair[0]) + return proper_list_inner(result,cl.pair[1]) + else: + return result + +def proper_list(cl): + result = [] + return proper_list_inner(result,cl) + +def int_list(cl): + return [Program.to(x).as_int() for x in as_atom_list(Program.to(cl))] + +def de_none_list(l): + return [x if x is not None else [] for x in l] + +def with_random_lists(n,f): + for length in range(n): # 0-10 length + for i in range(1 + (3 * length)): # A few orders each + orig_list = [random.randint(0,100) for x in range(length)] + f(orig_list) + +def test_prepend(): + for length1 in range(5): + list_1 = list(range(length1)) + for length2 in range(length1): + prepend_result = test_prepend_program.run([Program.to(list_1[:length2]),Program.to(list_1[length2:])]) + assert list_1 == int_list(prepend_result) + +def test_reverse(): + def test_reverse_list(l): + rev_args = Program.to([l]) + reversed_result = Program.to(list(reversed(l))) + reversed_by_prog = test_reverse_program.run(rev_args) + assert reversed_result == reversed_by_prog + + with_random_lists(10,test_reverse_list) + +def test_range(): + for length in range(10): + want_list = list(range(length)) + result = test_range_program.run(Program.to([length])) + assert want_list == result + +def do_test_permutations_of_size_n(n): + try_list = [random.randint(0,100) for x in range(n)] + want_set = list([list(v) for v in sorted(permutations(try_list))]) + listed_result = smoke_test_permutations_program.run(Program.to([try_list])) + pl = proper_list(listed_result) + perms_result = sorted([int_list(x) for x in de_none_list(pl)]) + assert want_set == perms_result + +def test_permutations_0(): + do_test_permutations_of_size_n(0) + +def test_permutations_1(): + do_test_permutations_of_size_n(1) + +def test_permutations_2(): + n = 2 + all_a_string = 0x616161616161 + all_b_string = 0x626262626262 + for try_list in [[all_a_string,all_b_string], [all_b_string,all_a_string]]: + want_set = list([list(v) for v in sorted(permutations(try_list))]) + listed_result = diag_run_clvm(smoke_test_permutations_program, Program.to([try_list]), 'smoke_test_permutations.sym', {'print': True}) + pl = proper_list(listed_result) + perms_result = sorted([int_list(x) for x in de_none_list(pl)]) + assert want_set == perms_result + +def test_chialisp_sort_program(): + diag_run_clvm(test_sort_program, Program.to([]), 'test_sort.sym', {'print': True}) + +def test_permutations_n(): + for i in range(3,6): + do_test_permutations_of_size_n(i) + +def test_chialisp_permutations_program(): + diag_run_clvm(test_permutations_program, Program.to([3, 5]), 'test_permutations.sym', {'print': True}) + +def test_smoke_sort(): + for length in range(7): # 0-7 length + for i in range(1 + (3 * length)): # A few orders each + orig_list = [random.randint(0,100) for x in range(length)] + sort_args = Program.to([orig_list]) + sorted_list = Program.to(sorted(orig_list)) + sort_res = sort_program.run(sort_args) + assert sort_res == sorted_list + +if __name__ == '__main__': + test_smoke_sort() diff --git a/resources/tests/game-referee-in-cl21/test_permutations.clsp b/resources/tests/game-referee-in-cl21/test_permutations.clsp new file mode 100644 index 000000000..d5b6d125f --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_permutations.clsp @@ -0,0 +1,63 @@ +(mod (M N) + (include *standard-cl-21*) + (include prepend.clinc) + (include reverse.clinc) + (include map.clinc) + (include len.clinc) + (include range.clinc) + (include sort.clinc) + (include assert.clinc) + (include deep_compare.clinc) + (include permutations.clinc) + (include last.clinc) + (include busy.clinc) + (include all-in-list.clinc) + (include print.clinc) + + (defun ! (x) + (if x + (* x (! (- x 1))) + 1 + ) + ) + (defun no_repeats_inner ((first . remainder)) + (if remainder + (if (deep= first (f remainder)) + 0 + (no_repeats_inner remainder) + ) + 1 + ) + ) + (defun no_repeats (mylist) + (if mylist + (no_repeats_inner (sort (lambda (a b) (= (deep_compare a b) -1)) mylist)) + 1 + ) + ) + (assert + ;; Is permutations expected to collapse equal alternatives when two of + ;; the items to shuffle are equal? + (= (* (! M) 4) (len (permutations (c 0 (range M))))) + (busy + (lambda (listlen) + (assign + mylist (range listlen) + permed (permutations mylist) + (assert + (= (len permed) (! listlen)) + ;; ensure we didn't produce any permutations that have + ;; repeated elements in them, which would indicate that + ;; the permutation function misbehaved + (all-in-list (map (lambda (L) (no_repeats L)) permed)) + (no_repeats permed) + ) + ) + ) + (reverse (range N)) + 1 + ) + (deep= (permutations 0) (q ())) + 0 + ) +) diff --git a/resources/tests/game-referee-in-cl21/test_permutations.clvm.hex b/resources/tests/game-referee-in-cl21/test_permutations.clvm.hex new file mode 100644 index 000000000..ccbc2f4aa --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_permutations.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ffff03ffff09ffff12ffff02ff66ffff04ff02ffff04ff05ff80808080ffff010480ffff02ff48ffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff04ffff0180ffff02ff58ffff04ff02ffff04ff05ff8080808080ff80808080ff8080808080ffff01ff02ffff01ff02ffff03ffff02ff5affff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200fe80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ffff02ff50ffff04ff02ffff04ffff02ff58ffff04ff02ffff04ff0bff80808080ff80808080ffff04ffff0101ff808080808080ffff01ff02ffff01ff02ffff03ffff02ff42ffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff0180ff80808080ffff04ffff01ff8080ff8080808080ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ffff04ffff01ffffffffffff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff40ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff02ffff03ff0bffff01ff02ffff01ff02ff60ffff04ff02ffff04ffff04ffff05ff0b80ff0580ffff04ffff06ff0b80ff8080808080ff0180ffff01ff02ffff0105ff018080ff0180ffff02ff60ffff04ff02ffff04ff80ffff04ff05ff8080808080ff02ffff03ff0bffff01ff02ffff01ff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff02ff70ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff80808080808080ff0180ffff01ff02ffff0117ff018080ff0180ffffff02ffff03ff05ffff01ff02ffff01ff10ffff0101ffff02ff48ffff04ff02ffff04ffff06ff0580ff8080808080ff0180ffff01ff02ffff01ff0180ff018080ff0180ff02ffff03ffff09ff05ff0b80ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff04ff05ffff02ff68ffff04ff02ffff04ffff10ff05ffff010180ffff04ff0bff808080808080ff018080ff0180ffff02ff68ffff04ff02ffff04ff80ffff04ff05ff8080808080ff02ffff03ff05ffff01ff02ffff01ff02ff78ffff04ff02ffff04ffff06ff0580ffff04ff17ffff04ffff04ffff05ff0580ff0b80ff808080808080ff0180ffff01ff02ffff01ff06ff0380ff018080ff0180ffffffff02ff78ffff04ff02ffff04ff05ffff01ff80ff8080808080ff02ffff03ffff20ff0b80ffff01ff02ffff01ff02ff40ffff04ff02ffff04ffff02ff50ffff04ff02ffff04ff2fff80808080ffff04ff17ff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff20ff1780ffff01ff02ffff01ff02ff40ffff04ff02ffff04ffff02ff50ffff04ff02ffff04ff2fff80808080ffff04ff0bff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff02ff05ffff04ffff05ff0b80ffff04ffff05ff1780ffff0180808080ffff01ff02ffff01ff02ff64ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ffff04ffff04ffff05ff0b80ff2f80ff80808080808080ff0180ffff01ff02ffff01ff02ff64ffff04ff02ffff04ff05ffff04ff0bffff04ffff06ff1780ffff04ffff04ffff05ff1780ff2f80ff80808080808080ff018080ff0180ff018080ff0180ff018080ff0180ffff02ff64ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff01ff80808080808080ff02ffff03ff0bffff01ff02ffff01ff02ffff03ffff06ff0b80ffff01ff02ffff01ff02ff4cffff04ff02ffff04ffff06ff0180ffff04ffff02ff44ffff04ff02ffff04ff0bff80808080ff8080808080ff0180ffff01ff02ffff010bff018080ff0180ff0180ffff01ff02ffff01ff0180ff018080ff0180ffffff02ff6cffff04ff02ffff04ff03ffff04ffff02ff74ffff04ff02ffff04ff09ffff04ff13ff8080808080ffff04ffff02ff74ffff04ff02ffff04ff09ffff04ff2bff8080808080ff808080808080ff02ff54ffff04ff02ffff04ff11ffff04ff0bffff04ff17ff808080808080ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff02ff7cffff04ff02ffff04ffff06ff0180ffff04ffff02ff5cffff04ff02ffff04ffff05ff0580ffff04ffff05ff0b80ff8080808080ff8080808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff0181ffff0180ffff01ff02ffff01ff02ffff03ffff15ff05ff0b80ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff11ffff0180ffff15ff0bff058080ff018080ff0180ff018080ff0180ff018080ff0180ff02ffff03ff0bffff01ff02ffff010bff0180ffff01ff02ffff01ff02ff5cffff04ff02ffff04ffff06ff0980ffff04ffff06ff1580ff8080808080ff018080ff0180ffffffffff09ffff02ff5cffff04ff02ffff04ff05ffff04ff0bff8080808080ff8080ff02ffff03ffff20ff0b80ffff01ff02ffff0117ff0180ffff01ff02ffff01ff02ff52ffff04ff02ffff04ffff06ff0180ffff04ffff06ff0b80ffff04ffff05ff0b80ff808080808080ff018080ff0180ffff02ff70ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff7280ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff17ff808080ffff01ff01808080ff80808080ffff04ffff02ff4affff04ff02ffff04ffff02ff40ffff04ff02ffff04ff09ffff04ff0bff8080808080ff80808080ffff04ffff02ff62ffff04ff02ffff04ffff04ff17ff0980ffff04ff0bffff04ff2dff808080808080ff808080808080ff04ff09ff0b80ffffff02ffff03ff05ffff01ff02ffff01ff02ff62ffff04ff02ffff04ffff0180ffff04ff05ffff04ffff0180ff808080808080ff0180ffff01ff02ffff01ff01ff8080ff018080ff0180ff02ffff03ff0dffff01ff02ffff01ff02ff6affff04ff02ffff04ff0dff80808080ff0180ffff01ff02ffff0109ff018080ff0180ffff02ffff03ff0bffff01ff02ffff01ff02ff6affff04ff02ffff04ffff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff04ffff02ff5affff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff808080808080ffff01808080ff80808080ff0180ffff01ff02ffff0117ff018080ff0180ff02ffff03ff05ffff01ff02ffff01ff04ffff04ffff0101ffff05ff058080ffff02ff7affff04ff02ffff04ffff06ff0580ff8080808080ff0180ffff01ff02ffff01ff0180ff018080ff0180ffffffff02ffff04ffff0122ffff02ff7affff04ff02ffff04ff05ff8080808080ff8080ff02ffff03ff05ffff01ff02ffff01ff12ff05ffff02ff66ffff04ff02ffff04ffff11ff05ffff010180ff8080808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ffff02ffff03ff0dffff01ff02ffff01ff02ffff03ffff02ff42ffff04ff02ffff04ff09ffff04ffff05ff0d80ff8080808080ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff02ff56ffff04ff02ffff04ff0dff80808080ff018080ff0180ff0180ffff01ff02ffff01ff0101ff018080ff0180ff02ffff03ff05ffff01ff02ffff01ff02ff56ffff04ff02ffff04ffff02ff74ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff4e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ff05ff8080808080ff80808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ffffff09ffff02ff5cffff04ff02ffff04ff0bffff04ff17ff8080808080ffff0181ff80ff02ff5effff04ff02ffff04ff03ffff04ffff02ff4affff04ff02ffff04ff0bff80808080ff8080808080ffff02ffff03ffff09ffff02ff48ffff04ff02ffff04ff0bff80808080ffff02ff66ffff04ff02ffff04ff29ff8080808080ffff01ff02ffff01ff02ffff03ffff02ff46ffff04ff02ffff04ffff02ff70ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200be80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ff0bffff04ffff0180ff808080808080ff80808080ffff01ff02ffff01ff02ff76ffff04ff02ffff04ff0bff80808080ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ffff02ff76ffff04ff02ffff04ff0bff80808080ff02ff6effff04ff02ffff04ffff04ff80ffff04ff0bff808080ffff04ffff02ff58ffff04ff02ffff04ff0bff80808080ff8080808080ff018080 diff --git a/resources/tests/game-referee-in-cl21/test_permutations.clvm.hex.reference b/resources/tests/game-referee-in-cl21/test_permutations.clvm.hex.reference new file mode 100644 index 000000000..9758d6fd7 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_permutations.clvm.hex.reference @@ -0,0 +1 @@ +ff02ffff01ff02ffff03ffff09ffff12ffff02ff66ffff04ff02ffff04ff05ff80808080ffff010480ffff02ff48ffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff04ffff0180ffff02ff58ffff04ff02ffff04ff05ff8080808080ff80808080ff8080808080ffff01ff02ffff01ff02ffff03ffff02ff5affff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200fe80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ffff02ff50ffff04ff02ffff04ffff02ff58ffff04ff02ffff04ff0bff80808080ff80808080ffff04ffff0101ff808080808080ffff01ff02ffff01ff02ffff03ffff02ff42ffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff0180ff80808080ffff04ffff01ff8080ff8080808080ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ffff04ffff01ffffffffffff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff40ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff02ffff03ff0bffff01ff02ffff01ff02ff60ffff04ff02ffff04ffff04ffff05ff0b80ff0580ffff04ffff06ff0b80ff8080808080ff0180ffff01ff02ffff0105ff018080ff0180ffff02ff60ffff04ff02ffff04ff80ffff04ff05ff8080808080ff02ffff03ff0bffff01ff02ffff01ff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff02ff70ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff80808080808080ff0180ffff01ff02ffff0117ff018080ff0180ffffff02ffff03ff05ffff01ff02ffff01ff10ffff0101ffff02ff48ffff04ff02ffff04ffff06ff0580ff8080808080ff0180ffff01ff02ffff01ff0180ff018080ff0180ff02ffff03ffff09ff05ff0b80ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff04ff05ffff02ff68ffff04ff02ffff04ffff10ff05ffff010180ffff04ff0bff808080808080ff018080ff0180ffff02ff68ffff04ff02ffff04ff80ffff04ff05ff8080808080ff02ffff03ff05ffff01ff02ffff01ff02ff78ffff04ff02ffff04ffff06ff0580ffff04ff17ffff04ffff04ffff05ff0580ff0b80ff808080808080ff0180ffff01ff02ffff01ff06ff0380ff018080ff0180ffffffff02ff78ffff04ff02ffff04ff05ffff01ff80ff8080808080ff02ffff03ffff20ff0b80ffff01ff02ffff01ff02ff40ffff04ff02ffff04ffff02ff50ffff04ff02ffff04ff2fff80808080ffff04ff17ff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff20ff1780ffff01ff02ffff01ff02ff40ffff04ff02ffff04ffff02ff50ffff04ff02ffff04ff2fff80808080ffff04ff0bff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff02ff05ffff04ffff05ff0b80ffff04ffff05ff1780ffff0180808080ffff01ff02ffff01ff02ff64ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ffff04ffff04ffff05ff0b80ff2f80ff80808080808080ff0180ffff01ff02ffff01ff02ff64ffff04ff02ffff04ff05ffff04ff0bffff04ffff06ff1780ffff04ffff04ffff05ff1780ff2f80ff80808080808080ff018080ff0180ff018080ff0180ff018080ff0180ffff02ff64ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff01ff80808080808080ff02ffff03ff0bffff01ff02ffff01ff02ffff03ffff06ff0b80ffff01ff02ffff01ff02ff4cffff04ff02ffff04ffff06ff0180ffff04ffff02ff44ffff04ff02ffff04ff0bff80808080ff8080808080ff0180ffff01ff02ffff010bff018080ff0180ff0180ffff01ff02ffff01ff0180ff018080ff0180ffffff02ff6cffff04ff02ffff04ff03ffff04ffff02ff74ffff04ff02ffff04ff09ffff04ff13ff8080808080ffff04ffff02ff74ffff04ff02ffff04ff09ffff04ff2bff8080808080ff808080808080ff02ff54ffff04ff02ffff04ff11ffff04ff0bffff04ff17ff808080808080ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff02ff7cffff04ff02ffff04ffff06ff0180ffff04ffff02ff5cffff04ff02ffff04ffff05ff0580ffff04ffff05ff0b80ff8080808080ff8080808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff0181ffff0180ffff01ff02ffff01ff02ffff03ffff15ff05ff0b80ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff11ffff0180ffff15ff0bff058080ff018080ff0180ff018080ff0180ff018080ff0180ff02ffff03ff0bffff01ff02ffff010bff0180ffff01ff02ffff01ff02ff5cffff04ff02ffff04ffff06ff0980ffff04ffff06ff1580ff8080808080ff018080ff0180ffffffffff09ffff02ff5cffff04ff02ffff04ff05ffff04ff0bff8080808080ff8080ff02ffff03ffff20ff0b80ffff01ff02ffff0117ff0180ffff01ff02ffff01ff02ff52ffff04ff02ffff04ffff06ff0180ffff04ffff05ff0b80ffff04ffff06ff0b80ff808080808080ff018080ff0180ffff02ff70ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff7280ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff0bff808080ffff01ff01808080ff80808080ffff04ffff02ff4affff04ff02ffff04ffff02ff40ffff04ff02ffff04ff09ffff04ff17ff8080808080ff80808080ffff04ffff02ff62ffff04ff02ffff04ffff04ff0bff0980ffff04ff17ffff04ff2dff808080808080ff808080808080ff04ff09ff0b80ffffff02ffff03ff05ffff01ff02ffff01ff02ff62ffff04ff02ffff04ffff0180ffff04ff05ffff04ffff0180ff808080808080ff0180ffff01ff02ffff01ff01ff8080ff018080ff0180ff02ffff03ff0dffff01ff02ffff01ff02ff6affff04ff02ffff04ff0dff80808080ff0180ffff01ff02ffff0109ff018080ff0180ffff02ffff03ff0bffff01ff02ffff01ff02ff6affff04ff02ffff04ffff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff04ffff02ff5affff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff808080808080ffff01808080ff80808080ff0180ffff01ff02ffff0117ff018080ff0180ff02ffff03ff05ffff01ff02ffff01ff04ffff04ffff0101ffff05ff058080ffff02ff7affff04ff02ffff04ffff06ff0580ff8080808080ff0180ffff01ff02ffff01ff0180ff018080ff0180ffffffff02ffff04ffff0122ffff02ff7affff04ff02ffff04ff05ff8080808080ff8080ff02ffff03ff05ffff01ff02ffff01ff12ff05ffff02ff66ffff04ff02ffff04ffff11ff05ffff010180ff8080808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ffff02ffff03ff0dffff01ff02ffff01ff02ffff03ffff02ff42ffff04ff02ffff04ff09ffff04ffff05ff0d80ff8080808080ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff02ff56ffff04ff02ffff04ff0dff80808080ff018080ff0180ff0180ffff01ff02ffff01ff0101ff018080ff0180ff02ffff03ff05ffff01ff02ffff01ff02ff56ffff04ff02ffff04ffff02ff74ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff4e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ff05ff8080808080ff80808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ffffff09ffff02ff5cffff04ff02ffff04ff0bffff04ff17ff8080808080ffff0181ff80ff02ff5effff04ff02ffff04ff03ffff04ffff02ff4affff04ff02ffff04ff0bff80808080ff8080808080ffff02ffff03ffff09ffff02ff48ffff04ff02ffff04ff0bff80808080ffff02ff66ffff04ff02ffff04ff29ff8080808080ffff01ff02ffff01ff02ffff03ffff02ff46ffff04ff02ffff04ffff02ff70ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200be80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ff0bffff04ffff0180ff808080808080ff80808080ffff01ff02ffff01ff02ff76ffff04ff02ffff04ff0bff80808080ff0180ffff01ff02ffff01ff0880ff018080ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ffff02ff76ffff04ff02ffff04ff0bff80808080ff02ff6effff04ff02ffff04ffff04ff80ffff04ff0bff808080ffff04ffff02ff58ffff04ff02ffff04ff0bff80808080ff8080808080ff018080 diff --git a/resources/tests/game-referee-in-cl21/test_permutations.sym b/resources/tests/game-referee-in-cl21/test_permutations.sym new file mode 100644 index 000000000..d28b3e38a --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_permutations.sym @@ -0,0 +1 @@ +{"42e1f82cf8542a5f31de7edcd596df9a08e48bcf0aa637f866be044a0c96841f_left_env": "1", "78956ca35a10cbc40b04bd0a14ca12faae5f292d70b9e072da61ef82f3677522": "no_repeats_inner", "9acbd39570d133bd1318e96254949ed3f9d84fb6796324d393b68b898c4999c8_left_env": "1", "ae7e4ed6da640a7bd1e9ef3b1d683440bf9297b217bf0743328f9ae54bbc5b53_arguments": "(reversed rest)", "85c5c955b32be4fef52509b26fe07ce1c3086244572fde3f3bc47636c20f86de": "deep_compare", "93ebb2292470d39d1a556d1294e5da2de17b55aa7d6b591cb885754273777746": "permutations_inner", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708_left_env": "1", "19f60e08ef187986cf06532ba696b5b91efeb5c043318b9e6b731f1cd80adf79": "last_inner", "85c5c955b32be4fef52509b26fe07ce1c3086244572fde3f3bc47636c20f86de_arguments": "(a b)", "1c9d01e44e9c5f35a282358422033e4e960609d9f5ef0efc7c7b48bf311208ff_left_env": "1", "0ebdfa3c097ba5b3ef741e8a33b6af2f741209b3e29d94c1c55deb599e4c41d7_left_env": "1", "657a0532257810b1c203d201026eccd16b845b156e25600b57a7ed5429c59682": "no_repeats", "858e89b0997add55f954ceda806d5a77e9914f6d31bed3dedd1e9b67581ee202_arguments": "(@ everything (rest aggl aggr))", "93ebb2292470d39d1a556d1294e5da2de17b55aa7d6b591cb885754273777746_left_env": "1", "42e1f82cf8542a5f31de7edcd596df9a08e48bcf0aa637f866be044a0c96841f_arguments": "(myless A B agg)", "0ebdfa3c097ba5b3ef741e8a33b6af2f741209b3e29d94c1c55deb599e4c41d7": "busy", "e23db45dac9015daa0e667d0d846c354b2b9d9aaa3faedb560854d8662f2e238_arguments": "((() listlen) mylist)", "source_file": "/home/arty/dev/chia/clvm_tools_rs/resources/tests/game-referee-in-cl21/test_permutations.clsp", "0871deba30de6d95a0b04a45e6e036162f8abe844ae21b31f7d7cd518845fe9c": "range_inner", "ae7e4ed6da640a7bd1e9ef3b1d683440bf9297b217bf0743328f9ae54bbc5b53": "reverse_inner", "93ebb2292470d39d1a556d1294e5da2de17b55aa7d6b591cb885754273777746_arguments": "(pre post agg)", "a91dc4bec838278871d09bbe4a7206242b852404596d71f8e7962df872da447e_arguments": "(L)", "9fbce34b16a7c4618d5816009b42c6e661cb7efbcaf90314a2f840362f175793": "lambda_$_305", "ae7e4ed6da640a7bd1e9ef3b1d683440bf9297b217bf0743328f9ae54bbc5b53_left_env": "1", "5087819cc352ab86b0b64eebf0a29725fb6306291a42ac51f17253919f7b899c_left_env": "1", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708": "lambda_$_304", "657a0532257810b1c203d201026eccd16b845b156e25600b57a7ed5429c59682_left_env": "1", "9242b5b6b2f9c8d952001db1fbcffc4b477638bf957f6a5dd3a2cc742919c977_arguments": "(vals)", "6c37e5a9ce5bcf0ae750dd4bb1db5898f49d63eadcdf27fbe04c787362459f5d_arguments": "(((() listlen) mylist) permed)", "9acbd39570d133bd1318e96254949ed3f9d84fb6796324d393b68b898c4999c8_arguments": "(F L R)", "1443073ed355cb83607d1c2a6d5612f28a038d3887fa750de973e6aa0ed83f08_arguments": "(myless a b)", "85c5c955b32be4fef52509b26fe07ce1c3086244572fde3f3bc47636c20f86de_left_env": "1", "5087819cc352ab86b0b64eebf0a29725fb6306291a42ac51f17253919f7b899c": "letbinding_$_300", "ae16459987997a1c9872031a855e1dfe8138fde4d1d5b9a5f188d3292ea97565": "sort", "2c82355dea6595dde07e0d5e05aa96b89052c8b97d0e0c868356df4914f2fe68_left_env": "1", "2e3d155705dec0e05e5d4c87c93395ffe98fffe9f21542faca3c5c8751a18047": "deep=", "483fcccf52dd01c7be19ebb1f6ec50a0c235873236a8ab545236771af634b706": "lambda_$_298", "ae16459987997a1c9872031a855e1dfe8138fde4d1d5b9a5f188d3292ea97565_arguments": "(myless mylist)", "a0c582b1c6b05c8a3f5d5d7afd51404b874bb63f21ef73f31c383007fce81e87": "prepend", "7381ec0d3e15950009d8b999a34b828e9964b79470270e7ed6c5409cf2f69bb9_left_env": "1", "6c37e5a9ce5bcf0ae750dd4bb1db5898f49d63eadcdf27fbe04c787362459f5d": "letbinding_$_306", "6c37e5a9ce5bcf0ae750dd4bb1db5898f49d63eadcdf27fbe04c787362459f5d_left_env": "1", "657a0532257810b1c203d201026eccd16b845b156e25600b57a7ed5429c59682_arguments": "(mylist)", "6eb64b0043f60821f8c78916633c5d028164853a0ef677c0b35666673f4163ba_left_env": "1", "02c081d44a600583556699febd4e3bc2eb117b61bd5cfc612c2bf091c952fa0a_left_env": "1", "61f9f86f9df2ce0986b2ae605b74b6111f767e89b83729af6f34110bf65bdeb2": "!", "02c081d44a600583556699febd4e3bc2eb117b61bd5cfc612c2bf091c952fa0a": "len", "a91dc4bec838278871d09bbe4a7206242b852404596d71f8e7962df872da447e_left_env": "1", "9242b5b6b2f9c8d952001db1fbcffc4b477638bf957f6a5dd3a2cc742919c977": "reverse", "858e89b0997add55f954ceda806d5a77e9914f6d31bed3dedd1e9b67581ee202_left_env": "1", "6eb64b0043f60821f8c78916633c5d028164853a0ef677c0b35666673f4163ba_arguments": "((pre_$_275 post_$_276 agg_$_277) myatom newrest)", "5f7a25198045f0621cc78620e8739d731e1761a379e94ee1dae0717e4192e860": "letbinding_$_301", "c6e0bf4deaac4dc5ac02244c56fcaba2652b33bfb38f812ba0a6ef67d3049f61": "permutations", "f8de27975a5aa0f0169626c8874de2ee78c9879c44424bfc1153bc150c6282fe": "range", "5f7a25198045f0621cc78620e8739d731e1761a379e94ee1dae0717e4192e860_arguments": "(((myless_$_257 mylist_$_258) (a b)) sa sb)", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708_arguments": "((myatom) x)", "7381ec0d3e15950009d8b999a34b828e9964b79470270e7ed6c5409cf2f69bb9_arguments": "(L)", "bde59c348f4163416518c666a1c5a1d39560d2b09c9b2b38b047e4da574c745e_arguments": "(mylist)", "2e3d155705dec0e05e5d4c87c93395ffe98fffe9f21542faca3c5c8751a18047_left_env": "1", "61f9f86f9df2ce0986b2ae605b74b6111f767e89b83729af6f34110bf65bdeb2_left_env": "1", "2c82355dea6595dde07e0d5e05aa96b89052c8b97d0e0c868356df4914f2fe68": "lambda_$_307", "9fbce34b16a7c4618d5816009b42c6e661cb7efbcaf90314a2f840362f175793_left_env": "1", "483fcccf52dd01c7be19ebb1f6ec50a0c235873236a8ab545236771af634b706_arguments": "(() listlen)", "9acbd39570d133bd1318e96254949ed3f9d84fb6796324d393b68b898c4999c8": "map-with-rest", "1443073ed355cb83607d1c2a6d5612f28a038d3887fa750de973e6aa0ed83f08": "merge", "e23db45dac9015daa0e667d0d846c354b2b9d9aaa3faedb560854d8662f2e238": "letbinding_$_299", "bde59c348f4163416518c666a1c5a1d39560d2b09c9b2b38b047e4da574c745e_left_env": "1", "a0c582b1c6b05c8a3f5d5d7afd51404b874bb63f21ef73f31c383007fce81e87_arguments": "(a b)", "0871deba30de6d95a0b04a45e6e036162f8abe844ae21b31f7d7cd518845fe9c_arguments": "(next final)", "__chia__main_arguments": "(M N)", "bde59c348f4163416518c666a1c5a1d39560d2b09c9b2b38b047e4da574c745e": "split", "02c081d44a600583556699febd4e3bc2eb117b61bd5cfc612c2bf091c952fa0a_arguments": "(L)", "f8de27975a5aa0f0169626c8874de2ee78c9879c44424bfc1153bc150c6282fe_arguments": "(i)", "0871deba30de6d95a0b04a45e6e036162f8abe844ae21b31f7d7cd518845fe9c_left_env": "1", "78956ca35a10cbc40b04bd0a14ca12faae5f292d70b9e072da61ef82f3677522_left_env": "1", "e23db45dac9015daa0e667d0d846c354b2b9d9aaa3faedb560854d8662f2e238_left_env": "1", "c6e0bf4deaac4dc5ac02244c56fcaba2652b33bfb38f812ba0a6ef67d3049f61_left_env": "1", "6eb64b0043f60821f8c78916633c5d028164853a0ef677c0b35666673f4163ba": "letbinding_$_303", "1443073ed355cb83607d1c2a6d5612f28a038d3887fa750de973e6aa0ed83f08_left_env": "1", "61f9f86f9df2ce0986b2ae605b74b6111f767e89b83729af6f34110bf65bdeb2_arguments": "(x)", "a0c582b1c6b05c8a3f5d5d7afd51404b874bb63f21ef73f31c383007fce81e87_left_env": "1", "7381ec0d3e15950009d8b999a34b828e9964b79470270e7ed6c5409cf2f69bb9": "enquote-rest", "ae16459987997a1c9872031a855e1dfe8138fde4d1d5b9a5f188d3292ea97565_left_env": "1", "9fbce34b16a7c4618d5816009b42c6e661cb7efbcaf90314a2f840362f175793_arguments": "(() a b)", "858e89b0997add55f954ceda806d5a77e9914f6d31bed3dedd1e9b67581ee202": "split_inner", "78956ca35a10cbc40b04bd0a14ca12faae5f292d70b9e072da61ef82f3677522_arguments": "((first . remainder))", "f8de27975a5aa0f0169626c8874de2ee78c9879c44424bfc1153bc150c6282fe_left_env": "1", "9242b5b6b2f9c8d952001db1fbcffc4b477638bf957f6a5dd3a2cc742919c977_left_env": "1", "19f60e08ef187986cf06532ba696b5b91efeb5c043318b9e6b731f1cd80adf79_arguments": "((next . remainder))", "2c82355dea6595dde07e0d5e05aa96b89052c8b97d0e0c868356df4914f2fe68_arguments": "(() L)", "483fcccf52dd01c7be19ebb1f6ec50a0c235873236a8ab545236771af634b706_left_env": "1", "5f7a25198045f0621cc78620e8739d731e1761a379e94ee1dae0717e4192e860_left_env": "1", "5087819cc352ab86b0b64eebf0a29725fb6306291a42ac51f17253919f7b899c_arguments": "((myless_$_257 mylist_$_258) (a b))", "a91dc4bec838278871d09bbe4a7206242b852404596d71f8e7962df872da447e": "all-in-list", "42e1f82cf8542a5f31de7edcd596df9a08e48bcf0aa637f866be044a0c96841f": "merge_inner", "1c9d01e44e9c5f35a282358422033e4e960609d9f5ef0efc7c7b48bf311208ff": "letbinding_$_302", "2e3d155705dec0e05e5d4c87c93395ffe98fffe9f21542faca3c5c8751a18047_arguments": "(a b)", "19f60e08ef187986cf06532ba696b5b91efeb5c043318b9e6b731f1cd80adf79_left_env": "1", "0ebdfa3c097ba5b3ef741e8a33b6af2f741209b3e29d94c1c55deb599e4c41d7_arguments": "(myfunc mylist returnval)", "1c9d01e44e9c5f35a282358422033e4e960609d9f5ef0efc7c7b48bf311208ff_arguments": "((a_$_261 b_$_262) inner_result)", "c6e0bf4deaac4dc5ac02244c56fcaba2652b33bfb38f812ba0a6ef67d3049f61_arguments": "(vals)"} \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl21/test_prepend.clsp b/resources/tests/game-referee-in-cl21/test_prepend.clsp new file mode 100644 index 000000000..9f0d45819 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_prepend.clsp @@ -0,0 +1,5 @@ +(mod (X Y) + (include *standard-cl-21*) + (include prepend.clinc) + (prepend X Y) + ) diff --git a/resources/tests/game-referee-in-cl21/test_prepend.clvm.hex b/resources/tests/game-referee-in-cl21/test_prepend.clvm.hex new file mode 100644 index 000000000..47dd7f1f1 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_prepend.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff02ffff04ff02ffff04ff05ffff04ff0bff8080808080ffff04ffff01ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff02ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080 diff --git a/resources/tests/game-referee-in-cl21/test_prepend.clvm.hex.reference b/resources/tests/game-referee-in-cl21/test_prepend.clvm.hex.reference new file mode 100644 index 000000000..47dd7f1f1 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_prepend.clvm.hex.reference @@ -0,0 +1 @@ +ff02ffff01ff02ff02ffff04ff02ffff04ff05ffff04ff0bff8080808080ffff04ffff01ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff02ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080 diff --git a/resources/tests/game-referee-in-cl21/test_prepend.sym b/resources/tests/game-referee-in-cl21/test_prepend.sym new file mode 100644 index 000000000..368cc453d --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_prepend.sym @@ -0,0 +1 @@ +{"source_file": "/home/arty/dev/chia/clvm_tools_rs/resources/tests/game-referee-in-cl21/test_prepend.clsp", "dfe61be8d5db02605605573b4d298395c7a871cc5390a79d535d07bbd2338987_left_env": "1", "__chia__main_arguments": "(X Y)", "dfe61be8d5db02605605573b4d298395c7a871cc5390a79d535d07bbd2338987": "prepend", "dfe61be8d5db02605605573b4d298395c7a871cc5390a79d535d07bbd2338987_arguments": "(a b)"} \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl21/test_range.clsp b/resources/tests/game-referee-in-cl21/test_range.clsp new file mode 100644 index 000000000..a7dc5edd9 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_range.clsp @@ -0,0 +1,6 @@ +(mod (X) + (include *standard-cl-21*) + (include range.clinc) + + (range X) + ) diff --git a/resources/tests/game-referee-in-cl21/test_range.clvm.hex b/resources/tests/game-referee-in-cl21/test_range.clvm.hex new file mode 100644 index 000000000..628a68fe6 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_range.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff06ffff04ff02ffff04ff05ff80808080ffff04ffff01ffff02ffff03ffff09ff05ff0b80ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff04ff05ffff02ff04ffff04ff02ffff04ffff10ff05ffff010180ffff04ff0bff808080808080ff018080ff0180ff02ff04ffff04ff02ffff04ff80ffff04ff05ff8080808080ff018080 diff --git a/resources/tests/game-referee-in-cl21/test_range.clvm.hex.reference b/resources/tests/game-referee-in-cl21/test_range.clvm.hex.reference new file mode 100644 index 000000000..628a68fe6 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_range.clvm.hex.reference @@ -0,0 +1 @@ +ff02ffff01ff02ff06ffff04ff02ffff04ff05ff80808080ffff04ffff01ffff02ffff03ffff09ff05ff0b80ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff04ff05ffff02ff04ffff04ff02ffff04ffff10ff05ffff010180ffff04ff0bff808080808080ff018080ff0180ff02ff04ffff04ff02ffff04ff80ffff04ff05ff8080808080ff018080 diff --git a/resources/tests/game-referee-in-cl21/test_range.sym b/resources/tests/game-referee-in-cl21/test_range.sym new file mode 100644 index 000000000..fabe9f400 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_range.sym @@ -0,0 +1 @@ +{"0f035685b03df70de81cbdbd4e600f5d2f148f6c02b0e0a73ef96a26e7121f2a_left_env": "1", "6ba774998680757c6e60d6d6e8a94176f76b74e5f8c6f2cf5d99fb134e916556": "range_inner", "source_file": "/home/arty/dev/chia/clvm_tools_rs/resources/tests/game-referee-in-cl21/test_range.clsp", "0f035685b03df70de81cbdbd4e600f5d2f148f6c02b0e0a73ef96a26e7121f2a_arguments": "(i)", "6ba774998680757c6e60d6d6e8a94176f76b74e5f8c6f2cf5d99fb134e916556_left_env": "1", "6ba774998680757c6e60d6d6e8a94176f76b74e5f8c6f2cf5d99fb134e916556_arguments": "(next final)", "0f035685b03df70de81cbdbd4e600f5d2f148f6c02b0e0a73ef96a26e7121f2a": "range", "__chia__main_arguments": "(X)"} \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl21/test_reverse.clsp b/resources/tests/game-referee-in-cl21/test_reverse.clsp new file mode 100644 index 000000000..b1d843648 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_reverse.clsp @@ -0,0 +1,6 @@ +(mod (X) + (include *standard-cl-21*) + (include reverse.clinc) + + (reverse X) + ) diff --git a/resources/tests/game-referee-in-cl21/test_reverse.clvm.hex b/resources/tests/game-referee-in-cl21/test_reverse.clvm.hex new file mode 100644 index 000000000..492966787 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_reverse.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff06ffff04ff02ffff04ff05ff80808080ffff04ffff01ffff02ffff03ff0bffff01ff02ffff01ff02ff04ffff04ff02ffff04ffff04ffff05ff0b80ff0580ffff04ffff06ff0b80ff8080808080ff0180ffff01ff02ffff0105ff018080ff0180ff02ff04ffff04ff02ffff04ff80ffff04ff05ff8080808080ff018080 diff --git a/resources/tests/game-referee-in-cl21/test_reverse.clvm.hex.reference b/resources/tests/game-referee-in-cl21/test_reverse.clvm.hex.reference new file mode 100644 index 000000000..492966787 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_reverse.clvm.hex.reference @@ -0,0 +1 @@ +ff02ffff01ff02ff06ffff04ff02ffff04ff05ff80808080ffff04ffff01ffff02ffff03ff0bffff01ff02ffff01ff02ff04ffff04ff02ffff04ffff04ffff05ff0b80ff0580ffff04ffff06ff0b80ff8080808080ff0180ffff01ff02ffff0105ff018080ff0180ff02ff04ffff04ff02ffff04ff80ffff04ff05ff8080808080ff018080 diff --git a/resources/tests/game-referee-in-cl21/test_reverse.sym b/resources/tests/game-referee-in-cl21/test_reverse.sym new file mode 100644 index 000000000..e573ba66a --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_reverse.sym @@ -0,0 +1 @@ +{"0f035685b03df70de81cbdbd4e600f5d2f148f6c02b0e0a73ef96a26e7121f2a_arguments": "(vals)", "893ed9a33d9ef594068ddc5aa4e669dce55ad0e7588062968c1d76ba4c830c01_left_env": "1", "source_file": "/home/arty/dev/chia/clvm_tools_rs/resources/tests/game-referee-in-cl21/test_reverse.clsp", "0f035685b03df70de81cbdbd4e600f5d2f148f6c02b0e0a73ef96a26e7121f2a_left_env": "1", "893ed9a33d9ef594068ddc5aa4e669dce55ad0e7588062968c1d76ba4c830c01": "reverse_inner", "0f035685b03df70de81cbdbd4e600f5d2f148f6c02b0e0a73ef96a26e7121f2a": "reverse", "893ed9a33d9ef594068ddc5aa4e669dce55ad0e7588062968c1d76ba4c830c01_arguments": "(reversed rest)", "__chia__main_arguments": "(X)"} \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl21/test_sort.clsp b/resources/tests/game-referee-in-cl21/test_sort.clsp new file mode 100644 index 000000000..8185024d0 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_sort.clsp @@ -0,0 +1,37 @@ + +(mod () + (include *standard-cl-21*) + (include print.clinc) + (include sort.clinc) + (include assert.clinc) + (include deep_compare.clinc) + (include reverse.clinc) + (include prepend.clinc) + (include map.clinc) + (include range.clinc) + (include permutations.clinc) + (include last.clinc) + (include busy.clinc) + + (defun try_list (mylist newlist) + (assert (deep= (print "sorted" (sort (lambda (A B) (deep< A B)) newlist)) mylist) 0) + ) + + (defun try_permuted_list (mylist) + (busy (lambda ((& mylist) newlist) (try_list mylist newlist)) + (print "sort all these" (permutations (print "mylist" mylist))) + 0 + ) + ) + (last + (try_list 0 0) + (try_list (range 15) (range 15)) + (try_list (range 15) (reverse (range 15))) + (try_permuted_list (list -1 -1 0 0 2)) + (busy (lambda (i) (try_permuted_list (print "sortme" (range i)))) + (range 4) + 0 + ) + 1 + ) +) diff --git a/resources/tests/game-referee-in-cl21/test_sort.clvm.hex b/resources/tests/game-referee-in-cl21/test_sort.clvm.hex new file mode 100644 index 000000000..cf5d0409c --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_sort.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff66ffff04ff02ffff04ffff04ffff02ff56ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff7e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ffff02ff4affff04ff02ffff04ffff0104ff80808080ffff04ffff0180ff808080808080ffff04ffff02ff6effff04ff02ffff04ffff04ffff0181ffffff04ffff0181ffffff04ffff0180ffff04ffff0180ffff04ffff0102ffff01808080808080ff80808080ffff04ffff02ff76ffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff010fff80808080ffff04ffff02ff7cffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff010fff80808080ff80808080ff8080808080ffff04ffff02ff76ffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff010fff80808080ffff04ffff02ff4affff04ff02ffff04ffff010fff80808080ff8080808080ffff04ffff02ff76ffff04ff02ffff04ffff0180ffff04ffff0180ff8080808080ffff04ffff0101ffff0180808080808080ff80808080ffff04ffff01ffffffffff02ffff03ffff22ffff0187247072696e7424ff05ff0b80ffff01ff02ffff010bff0180ffff01ff02ffff010bff018080ff0180ffff02ffff03ff05ffff01ff02ffff01ff02ff50ffff04ff02ffff04ffff06ff0580ffff04ff17ffff04ffff04ffff05ff0580ff0b80ff808080808080ff0180ffff01ff02ffff01ff06ff0380ff018080ff0180ff02ff50ffff04ff02ffff04ff05ffff01ff80ff8080808080ffffff02ffff03ffff20ff0b80ffff01ff02ffff01ff02ff22ffff04ff02ffff04ffff02ff7cffff04ff02ffff04ff2fff80808080ffff04ff17ff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff20ff1780ffff01ff02ffff01ff02ff22ffff04ff02ffff04ffff02ff7cffff04ff02ffff04ff2fff80808080ffff04ff0bff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff02ff05ffff04ffff05ff0b80ffff04ffff05ff1780ffff0180808080ffff01ff02ffff01ff02ff48ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ffff04ffff04ffff05ff0b80ff2f80ff80808080808080ff0180ffff01ff02ffff01ff02ff48ffff04ff02ffff04ff05ffff04ff0bffff04ffff06ff1780ffff04ffff04ffff05ff1780ff2f80ff80808080808080ff018080ff0180ff018080ff0180ff018080ff0180ff02ff48ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff01ff80808080808080ffff02ffff03ff0bffff01ff02ffff01ff02ffff03ffff06ff0b80ffff01ff02ffff01ff02ff78ffff04ff02ffff04ffff06ff0180ffff04ffff02ff70ffff04ff02ffff04ff0bff80808080ff8080808080ff0180ffff01ff02ffff010bff018080ff0180ff0180ffff01ff02ffff01ff0180ff018080ff0180ff02ff24ffff04ff02ffff04ff03ffff04ffff02ff58ffff04ff02ffff04ff09ffff04ff13ff8080808080ffff04ffff02ff58ffff04ff02ffff04ff09ffff04ff2bff8080808080ff808080808080ffffff02ff68ffff04ff02ffff04ff11ffff04ff0bffff04ff17ff808080808080ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff02ff74ffff04ff02ffff04ffff06ff0180ffff04ffff02ff54ffff04ff02ffff04ffff05ff0580ffff04ffff05ff0b80ff8080808080ff8080808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff0181ffff0180ffff01ff02ffff01ff02ffff03ffff15ff05ff0b80ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff11ffff0180ffff15ff0bff058080ff018080ff0180ff018080ff0180ff018080ff0180ff02ffff03ff0bffff01ff02ffff010bff0180ffff01ff02ffff01ff02ff54ffff04ff02ffff04ffff06ff0980ffff04ffff06ff1580ff8080808080ff018080ff0180ffffff09ffff02ff54ffff04ff02ffff04ff05ffff04ff0bff8080808080ffff0181ff80ff09ffff02ff54ffff04ff02ffff04ff05ffff04ff0bff8080808080ff8080ffff02ffff03ff0bffff01ff02ffff01ff02ff5cffff04ff02ffff04ffff04ffff05ff0b80ff0580ffff04ffff06ff0b80ff8080808080ff0180ffff01ff02ffff0105ff018080ff0180ff02ff5cffff04ff02ffff04ff80ffff04ff05ff8080808080ffffffff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff22ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ffff02ffff03ff0bffff01ff02ffff01ff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff02ff52ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff80808080808080ff0180ffff01ff02ffff0117ff018080ff0180ff02ffff03ffff09ff05ff0b80ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff04ff05ffff02ff72ffff04ff02ffff04ffff10ff05ffff010180ffff04ff0bff808080808080ff018080ff0180ffffff02ff72ffff04ff02ffff04ff80ffff04ff05ff8080808080ff02ffff03ffff20ff0b80ffff01ff02ffff0117ff0180ffff01ff02ffff01ff02ff5affff04ff02ffff04ffff06ff0180ffff04ffff06ff0b80ffff04ffff05ff0b80ff808080808080ff018080ff0180ffff02ff52ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff7a80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff17ff808080ffff01ff01808080ff80808080ffff04ffff02ff46ffff04ff02ffff04ffff02ff22ffff04ff02ffff04ff09ffff04ff0bff8080808080ff80808080ffff04ffff02ff6affff04ff02ffff04ffff04ff17ff0980ffff04ff0bffff04ff2dff808080808080ff808080808080ff04ff09ff0b80ffffffff02ffff03ff05ffff01ff02ffff01ff02ff6affff04ff02ffff04ffff0180ffff04ff05ffff04ffff0180ff808080808080ff0180ffff01ff02ffff01ff01ff8080ff018080ff0180ff02ffff03ff0dffff01ff02ffff01ff02ff66ffff04ff02ffff04ff0dff80808080ff0180ffff01ff02ffff0109ff018080ff0180ffff02ffff03ff0bffff01ff02ffff01ff02ff66ffff04ff02ffff04ffff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff04ffff02ff56ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff808080808080ffff01808080ff80808080ff0180ffff01ff02ffff0117ff018080ff0180ff02ffff03ffff02ff6cffff04ff02ffff04ffff02ff20ffff04ff02ffff04ffff0186736f72746564ffff04ffff02ff58ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff4e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ffff04ff0bff8080808080ff8080808080ffff04ff05ff8080808080ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ffffff02ff4cffff04ff02ffff04ff0bffff04ff17ff8080808080ff02ff56ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff5e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff05ff808080ffff01ff01808080ff80808080ffff04ffff02ff20ffff04ff02ffff04ffff018e736f727420616c6c207468657365ffff04ffff02ff46ffff04ff02ffff04ffff02ff20ffff04ff02ffff04ffff01866d796c697374ffff04ff05ff8080808080ff80808080ff8080808080ffff01ff808080808080ffff02ff76ffff04ff02ffff04ff09ffff04ff0bff8080808080ff02ff6effff04ff02ffff04ffff02ff20ffff04ff02ffff04ffff0186736f72746d65ffff04ffff02ff4affff04ff02ffff04ff0bff80808080ff8080808080ff80808080ff018080 diff --git a/resources/tests/game-referee-in-cl21/test_sort.clvm.hex.reference b/resources/tests/game-referee-in-cl21/test_sort.clvm.hex.reference new file mode 100644 index 000000000..4cf09e661 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_sort.clvm.hex.reference @@ -0,0 +1 @@ +ff02ffff01ff02ff66ffff04ff02ffff04ffff04ffff02ff56ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff7e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ffff02ff4affff04ff02ffff04ffff0104ff80808080ffff04ffff0180ff808080808080ffff04ffff02ff6effff04ff02ffff04ffff04ffff0181ffffff04ffff0181ffffff04ffff0180ffff04ffff0180ffff04ffff0102ffff01808080808080ff80808080ffff04ffff02ff76ffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff010fff80808080ffff04ffff02ff7cffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff010fff80808080ff80808080ff8080808080ffff04ffff02ff76ffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff010fff80808080ffff04ffff02ff4affff04ff02ffff04ffff010fff80808080ff8080808080ffff04ffff02ff76ffff04ff02ffff04ffff0180ffff04ffff0180ff8080808080ffff04ffff0101ffff0180808080808080ff80808080ffff04ffff01ffffffffff02ffff03ffff22ffff0187247072696e7424ff05ff0b80ffff01ff02ffff010bff0180ffff01ff02ffff010bff018080ff0180ffff02ffff03ff05ffff01ff02ffff01ff02ff50ffff04ff02ffff04ffff06ff0580ffff04ff17ffff04ffff04ffff05ff0580ff0b80ff808080808080ff0180ffff01ff02ffff01ff06ff0380ff018080ff0180ff02ff50ffff04ff02ffff04ff05ffff01ff80ff8080808080ffffff02ffff03ffff20ff0b80ffff01ff02ffff01ff02ff22ffff04ff02ffff04ffff02ff7cffff04ff02ffff04ff2fff80808080ffff04ff17ff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff20ff1780ffff01ff02ffff01ff02ff22ffff04ff02ffff04ffff02ff7cffff04ff02ffff04ff2fff80808080ffff04ff0bff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff02ff05ffff04ffff05ff0b80ffff04ffff05ff1780ffff0180808080ffff01ff02ffff01ff02ff48ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ffff04ffff04ffff05ff0b80ff2f80ff80808080808080ff0180ffff01ff02ffff01ff02ff48ffff04ff02ffff04ff05ffff04ff0bffff04ffff06ff1780ffff04ffff04ffff05ff1780ff2f80ff80808080808080ff018080ff0180ff018080ff0180ff018080ff0180ff02ff48ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff01ff80808080808080ffff02ffff03ff0bffff01ff02ffff01ff02ffff03ffff06ff0b80ffff01ff02ffff01ff02ff78ffff04ff02ffff04ffff06ff0180ffff04ffff02ff70ffff04ff02ffff04ff0bff80808080ff8080808080ff0180ffff01ff02ffff010bff018080ff0180ff0180ffff01ff02ffff01ff0180ff018080ff0180ff02ff24ffff04ff02ffff04ff03ffff04ffff02ff58ffff04ff02ffff04ff09ffff04ff13ff8080808080ffff04ffff02ff58ffff04ff02ffff04ff09ffff04ff2bff8080808080ff808080808080ffffff02ff68ffff04ff02ffff04ff11ffff04ff0bffff04ff17ff808080808080ffff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff02ff74ffff04ff02ffff04ffff06ff0180ffff04ffff02ff54ffff04ff02ffff04ffff05ff0580ffff04ffff05ff0b80ff8080808080ff8080808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff0181ffff0180ffff01ff02ffff01ff02ffff03ffff15ff05ff0b80ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff11ffff0180ffff15ff0bff058080ff018080ff0180ff018080ff0180ff018080ff0180ff02ffff03ff0bffff01ff02ffff010bff0180ffff01ff02ffff01ff02ff54ffff04ff02ffff04ffff06ff0980ffff04ffff06ff1580ff8080808080ff018080ff0180ffffff09ffff02ff54ffff04ff02ffff04ff05ffff04ff0bff8080808080ffff0181ff80ff09ffff02ff54ffff04ff02ffff04ff05ffff04ff0bff8080808080ff8080ffff02ffff03ff0bffff01ff02ffff01ff02ff5cffff04ff02ffff04ffff04ffff05ff0b80ff0580ffff04ffff06ff0b80ff8080808080ff0180ffff01ff02ffff0105ff018080ff0180ff02ff5cffff04ff02ffff04ff80ffff04ff05ff8080808080ffffffff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff22ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ffff02ffff03ff0bffff01ff02ffff01ff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff02ff52ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff80808080808080ff0180ffff01ff02ffff0117ff018080ff0180ff02ffff03ffff09ff05ff0b80ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff04ff05ffff02ff72ffff04ff02ffff04ffff10ff05ffff010180ffff04ff0bff808080808080ff018080ff0180ffffff02ff72ffff04ff02ffff04ff80ffff04ff05ff8080808080ff02ffff03ffff20ff0b80ffff01ff02ffff0117ff0180ffff01ff02ffff01ff02ff5affff04ff02ffff04ffff06ff0180ffff04ffff05ff0b80ffff04ffff06ff0b80ff808080808080ff018080ff0180ffff02ff52ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff7a80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff0bff808080ffff01ff01808080ff80808080ffff04ffff02ff46ffff04ff02ffff04ffff02ff22ffff04ff02ffff04ff09ffff04ff17ff8080808080ff80808080ffff04ffff02ff6affff04ff02ffff04ffff04ff0bff0980ffff04ff17ffff04ff2dff808080808080ff808080808080ff04ff09ff0b80ffffffff02ffff03ff05ffff01ff02ffff01ff02ff6affff04ff02ffff04ffff0180ffff04ff05ffff04ffff0180ff808080808080ff0180ffff01ff02ffff01ff01ff8080ff018080ff0180ff02ffff03ff0dffff01ff02ffff01ff02ff66ffff04ff02ffff04ff0dff80808080ff0180ffff01ff02ffff0109ff018080ff0180ffff02ffff03ff0bffff01ff02ffff01ff02ff66ffff04ff02ffff04ffff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff04ffff02ff56ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff808080808080ffff01808080ff80808080ff0180ffff01ff02ffff0117ff018080ff0180ff02ffff03ffff02ff6cffff04ff02ffff04ffff02ff20ffff04ff02ffff04ffff0186736f72746564ffff04ffff02ff58ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff4e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff01ffff04ffff0180ff0180808080ffff04ff0bff8080808080ff8080808080ffff04ff05ff8080808080ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff0880ff018080ff0180ffffff02ff4cffff04ff02ffff04ff0bffff04ff17ff8080808080ff02ff56ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff5e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff01ff01808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff05ff808080ffff01ff01808080ff80808080ffff04ffff02ff20ffff04ff02ffff04ffff018e736f727420616c6c207468657365ffff04ffff02ff46ffff04ff02ffff04ffff02ff20ffff04ff02ffff04ffff01866d796c697374ffff04ff05ff8080808080ff80808080ff8080808080ffff01ff808080808080ffff02ff76ffff04ff02ffff04ff09ffff04ff0bff8080808080ff02ff6effff04ff02ffff04ffff02ff20ffff04ff02ffff04ffff0186736f72746d65ffff04ffff02ff4affff04ff02ffff04ff0bff80808080ff8080808080ff80808080ff018080 diff --git a/resources/tests/game-referee-in-cl21/test_sort.sym b/resources/tests/game-referee-in-cl21/test_sort.sym new file mode 100644 index 000000000..6bea76365 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/test_sort.sym @@ -0,0 +1 @@ +{"e31ef9039be21ebbff9fca105dadf444914415d83cf1f74f6e299ccc760ca58c": "map-with-rest", "bcf06844cee9589ac2df23d9cf5d9a372b71fc3725db9c7249f0db72a2c7fdc3": "reverse", "7aaf175b403f21a9b93e40356ff378a531810f127922e726506b07915393384f": "reverse_inner", "997e0518ff66cefb408f6f6b874f0395ae1399f73650dc57f45d6f4eb79daccc_left_env": "1", "ca9b60a19af98d1290d1161582331f43d6518cbe383dcb87452e253773cf9329_arguments": "(@ everything (rest aggl aggr))", "d2586583545bb886183ab7b08b5c6561b6fdd931d8ee8e12b993d114579e6219_left_env": "1", "1d6bc99de7f858798725d96803a52ef1fa5cf7315c337ea51e560209f7366de5_arguments": "((next . remainder))", "1a3f28c2eeaf6c592d86f46dc96c10910a05739bbeda09e147e67fa64927c6f5_left_env": "1", "aff6f9e4b1d082994645068345db6e378e1839b24b4947111b4fd5d77bef5b4b": "range_inner", "2d2168734160822b5569309f8541a5b632b035f41c89907e79cb1983fc851a7b_arguments": "((myless_$_144 mylist_$_145) (a b))", "e31ef9039be21ebbff9fca105dadf444914415d83cf1f74f6e299ccc760ca58c_arguments": "(F L R)", "131cca40e81a7248781e5edf321f83b96282a9cf4e5ff0151b8dd2fdd5078499": "try_permuted_list", "2a7aff98de69b1fef1b6bc350cb81e2dd99d40254e7f541ef22f8837937ffdbb_left_env": "1", "131cca40e81a7248781e5edf321f83b96282a9cf4e5ff0151b8dd2fdd5078499_arguments": "(mylist)", "d2b16ed82a656d685d88e5e248fe3221b20f9082377d1263d95076bda402dd8d_left_env": "1", "1a3f28c2eeaf6c592d86f46dc96c10910a05739bbeda09e147e67fa64927c6f5": "sort", "b8b601fdb8fab0e12e98d10b1e8169d4209f502a901b4084e2f2c099065460e7_arguments": "(a b)", "02eae9c80ab3ae5e70fcb788e6753ac557297c5b882f6318db705b18b766e872": "letbinding_$_197", "85734bcc0a0243b28bb41bedb69f548a97a473bd3e87b1b5c8acb3a1140ba3d5_left_env": "1", "d155f473544dcda36e0bfa2a3f1579d2e32e251b1b2683a1a1eb73f919eefef2": "letbinding_$_196", "042c55b626937b8d6be258a97f8d25cdedeee2e712dbddef9438fa900eff883e_arguments": "(R P)", "d155f473544dcda36e0bfa2a3f1579d2e32e251b1b2683a1a1eb73f919eefef2_arguments": "(((myless_$_144 mylist_$_145) (a b)) sa sb)", "d5c36bb1c58c5974069b15c197ca27352476f19db460fb8cfa79fc1f35f55b13_left_env": "1", "c5bd34dcdeed87a6c78ea6b36052df8f96895a13a69b4179c15faf9f83ba4560": "lambda_$_201", "d2b16ed82a656d685d88e5e248fe3221b20f9082377d1263d95076bda402dd8d": "merge_inner", "d76bbcd6d3800803e66cb762aa942d5836553c18a50638e3dfcf3deca86f4141": "split", "24c1a323b918bc0b01064cb6171c20899e9d4e4e08a81d7e88013815e7c3fc22": "merge", "6b79b32d680005d302468e9d2c1592335cee3e4e0a454c9ede7653eb17b9c26d_arguments": "(a b)", "7aaf175b403f21a9b93e40356ff378a531810f127922e726506b07915393384f_arguments": "(reversed rest)", "bcf06844cee9589ac2df23d9cf5d9a372b71fc3725db9c7249f0db72a2c7fdc3_left_env": "1", "d76bbcd6d3800803e66cb762aa942d5836553c18a50638e3dfcf3deca86f4141_arguments": "(mylist)", "c5bd34dcdeed87a6c78ea6b36052df8f96895a13a69b4179c15faf9f83ba4560_arguments": "((mylist_$_193) newlist)", "962986191da6874f39aeb123a2daa2d87bd1d8a68f612e83d33070a0315fa3d7": "lambda_$_194", "27306e11834170f40679ff25b0e24deeb74c7a9b32495134103d6f952600b48d_arguments": "(a b)", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708": "lambda_$_199", "ca9b60a19af98d1290d1161582331f43d6518cbe383dcb87452e253773cf9329_left_env": "1", "bcf06844cee9589ac2df23d9cf5d9a372b71fc3725db9c7249f0db72a2c7fdc3_arguments": "(vals)", "e31ef9039be21ebbff9fca105dadf444914415d83cf1f74f6e299ccc760ca58c_left_env": "1", "aff6f9e4b1d082994645068345db6e378e1839b24b4947111b4fd5d77bef5b4b_left_env": "1", "aff6f9e4b1d082994645068345db6e378e1839b24b4947111b4fd5d77bef5b4b_arguments": "(next final)", "27306e11834170f40679ff25b0e24deeb74c7a9b32495134103d6f952600b48d": "deep_compare", "27306e11834170f40679ff25b0e24deeb74c7a9b32495134103d6f952600b48d_left_env": "1", "d2586583545bb886183ab7b08b5c6561b6fdd931d8ee8e12b993d114579e6219_arguments": "(mylist newlist)", "c5bd34dcdeed87a6c78ea6b36052df8f96895a13a69b4179c15faf9f83ba4560_left_env": "1", "1d6bc99de7f858798725d96803a52ef1fa5cf7315c337ea51e560209f7366de5_left_env": "1", "131cca40e81a7248781e5edf321f83b96282a9cf4e5ff0151b8dd2fdd5078499_left_env": "1", "6b79b32d680005d302468e9d2c1592335cee3e4e0a454c9ede7653eb17b9c26d_left_env": "1", "2a7aff98de69b1fef1b6bc350cb81e2dd99d40254e7f541ef22f8837937ffdbb": "busy", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708_arguments": "((myatom) x)", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708_left_env": "1", "5b656ea16b982e0b3da35bd883c9ff6407dadbbf05faeca2d53f4348dad67679": "prepend", "02eae9c80ab3ae5e70fcb788e6753ac557297c5b882f6318db705b18b766e872_left_env": "1", "962986191da6874f39aeb123a2daa2d87bd1d8a68f612e83d33070a0315fa3d7_arguments": "(() i)", "d155f473544dcda36e0bfa2a3f1579d2e32e251b1b2683a1a1eb73f919eefef2_left_env": "1", "042c55b626937b8d6be258a97f8d25cdedeee2e712dbddef9438fa900eff883e": "print", "997e0518ff66cefb408f6f6b874f0395ae1399f73650dc57f45d6f4eb79daccc_arguments": "(pre post agg)", "7aaf175b403f21a9b93e40356ff378a531810f127922e726506b07915393384f_left_env": "1", "d5c36bb1c58c5974069b15c197ca27352476f19db460fb8cfa79fc1f35f55b13": "letbinding_$_198", "2d2168734160822b5569309f8541a5b632b035f41c89907e79cb1983fc851a7b_left_env": "1", "ca9b60a19af98d1290d1161582331f43d6518cbe383dcb87452e253773cf9329": "split_inner", "6a477b54f8811bb3d5111ee9d39d29db7e3cca8f2521efd80f46dcfd9bc0573b_arguments": "(i)", "d76bbcd6d3800803e66cb762aa942d5836553c18a50638e3dfcf3deca86f4141_left_env": "1", "e9570c55a298e52c75e1ab676bdb601ab3a9939994f3f50be22ce4ebe6a1cc24": "permutations", "d2586583545bb886183ab7b08b5c6561b6fdd931d8ee8e12b993d114579e6219": "try_list", "85734bcc0a0243b28bb41bedb69f548a97a473bd3e87b1b5c8acb3a1140ba3d5_arguments": "(() A B)", "962986191da6874f39aeb123a2daa2d87bd1d8a68f612e83d33070a0315fa3d7_left_env": "1", "997e0518ff66cefb408f6f6b874f0395ae1399f73650dc57f45d6f4eb79daccc": "permutations_inner", "1d6bc99de7f858798725d96803a52ef1fa5cf7315c337ea51e560209f7366de5": "last_inner", "24c1a323b918bc0b01064cb6171c20899e9d4e4e08a81d7e88013815e7c3fc22_left_env": "1", "d5c36bb1c58c5974069b15c197ca27352476f19db460fb8cfa79fc1f35f55b13_arguments": "((pre_$_176 post_$_177 agg_$_178) myatom newrest)", "6a477b54f8811bb3d5111ee9d39d29db7e3cca8f2521efd80f46dcfd9bc0573b_left_env": "1", "b8b601fdb8fab0e12e98d10b1e8169d4209f502a901b4084e2f2c099065460e7_left_env": "1", "1a3f28c2eeaf6c592d86f46dc96c10910a05739bbeda09e147e67fa64927c6f5_arguments": "(myless mylist)", "__chia__main_arguments": "()", "e9570c55a298e52c75e1ab676bdb601ab3a9939994f3f50be22ce4ebe6a1cc24_arguments": "(vals)", "d2b16ed82a656d685d88e5e248fe3221b20f9082377d1263d95076bda402dd8d_arguments": "(myless A B agg)", "02eae9c80ab3ae5e70fcb788e6753ac557297c5b882f6318db705b18b766e872_arguments": "((a_$_148 b_$_149) inner_result)", "b8b601fdb8fab0e12e98d10b1e8169d4209f502a901b4084e2f2c099065460e7": "deep=", "24c1a323b918bc0b01064cb6171c20899e9d4e4e08a81d7e88013815e7c3fc22_arguments": "(myless a b)", "5b656ea16b982e0b3da35bd883c9ff6407dadbbf05faeca2d53f4348dad67679_arguments": "(a b)", "6b79b32d680005d302468e9d2c1592335cee3e4e0a454c9ede7653eb17b9c26d": "deep<", "5b656ea16b982e0b3da35bd883c9ff6407dadbbf05faeca2d53f4348dad67679_left_env": "1", "042c55b626937b8d6be258a97f8d25cdedeee2e712dbddef9438fa900eff883e_left_env": "1", "source_file": "/home/arty/dev/chia/clvm_tools_rs/resources/tests/game-referee-in-cl21/test_sort.clsp", "85734bcc0a0243b28bb41bedb69f548a97a473bd3e87b1b5c8acb3a1140ba3d5": "lambda_$_200", "2d2168734160822b5569309f8541a5b632b035f41c89907e79cb1983fc851a7b": "letbinding_$_195", "2a7aff98de69b1fef1b6bc350cb81e2dd99d40254e7f541ef22f8837937ffdbb_arguments": "(myfunc mylist returnval)", "6a477b54f8811bb3d5111ee9d39d29db7e3cca8f2521efd80f46dcfd9bc0573b": "range", "e9570c55a298e52c75e1ab676bdb601ab3a9939994f3f50be22ce4ebe6a1cc24_left_env": "1"} \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl21/testnoncegame.py b/resources/tests/game-referee-in-cl21/testnoncegame.py new file mode 100644 index 000000000..3b4cd2c2a --- /dev/null +++ b/resources/tests/game-referee-in-cl21/testnoncegame.py @@ -0,0 +1,33 @@ +import hashlib + +from hsms.streamables.program import Program + +from clvm.EvalError import EvalError + +noncegame = Program.from_bytes(bytes.fromhex(open("noncegame.clvm.hex").read())) +noncehash = noncegame.tree_hash() + +def drun(prog: Program, args: Program): + try: + return prog.run(args) + except EvalError as ee: + print(f"brun -x -y main.sym {prog} {Program.to(args)}") + raise + +def testnonce(startnonce, maxnonce): + for i in range(startnonce, maxnonce): + mygame = noncegame.curry(i, noncehash) + good_parameters = [i*2, noncegame.curry(i+1, noncehash).tree_hash(), 1, (i*4, b'g')] + bad_parameters = [i*3, noncegame.curry(i+2, noncehash).tree_hash(), 2, (i*5, b'g')] + assert drun(mygame, good_parameters) == b'g' + for j in range(len(good_parameters)): + try: + p = list(good_parameters) + p[j] = bad_parameters[j] + mygame.run(p) + assert False + except EvalError as ee: + pass + +if __name__ == '__main__': + testnonce(3, 7) diff --git a/resources/tests/game-referee-in-cl21/testreferee.py b/resources/tests/game-referee-in-cl21/testreferee.py new file mode 100644 index 000000000..01eb53643 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/testreferee.py @@ -0,0 +1,479 @@ +import pytest +from hashlib import sha256 +from contextlib import asynccontextmanager +from chia.clvm.spend_sim import SimClient, SpendSim +from pathlib import Path +from clvm.casts import int_to_bytes, int_from_bytes + +from hsms.streamables.program import Program +from clvm_tools_rs import compile_clvm +from clvm_tools.binutils import disassemble + +from clvm.EvalError import EvalError +from chia.types.mempool_inclusion_status import MempoolInclusionStatus +from chia.util.errors import Err +from dataclasses import dataclass +from typing import Any +from chia_rs import Coin +from chia.types.spend_bundle import SpendBundle +from chia.types.coin_spend import CoinSpend +from blspy import G2Element + +from steprun import diag_run_clvm, compile_module_with_symbols + +compile_module_with_symbols(['.'],'referee.clsp') +referee = Program.from_bytes(bytes.fromhex(open("referee.clvm.hex").read())) +refhash = referee.tree_hash() +compile_module_with_symbols(['.'],'referee_accuse.clsp') +referee_accuse = Program.from_bytes(bytes.fromhex(open("referee_accuse.clvm.hex").read())) +refaccusehash = referee.tree_hash() +compile_clvm('rockpaperscissorsa.clsp', 'rockpaperscissorsa.clvm.hex', ['.']) +MOD_A = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsa.clvm.hex").read())) +compile_clvm('rockpaperscissorsb.clsp', 'rockpaperscissorsb.clvm.hex', ['.']) +MOD_B = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsb.clvm.hex").read())) +compile_clvm('rockpaperscissorsc.clsp', 'rockpaperscissorsc.clvm.hex', ['.']) +MOD_C = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsc.clvm.hex").read())) +compile_clvm('rockpaperscissorsd.clsp', 'rockpaperscissorsd.clvm.hex', ['.']) +MOD_D = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsd.clvm.hex").read())) + +move = 0 +accuse = 1 +timeout = 2 + +def drun(prog: Program, *args: Program): + try: + return prog.run(*args) + except EvalError as ee: + print(f"brun -x -y main.sym {prog} {Program.to(list(args))}") + raise + +def sha(blob:bytes) -> bytes: + return sha256(blob).digest() + +@pytest.fixture(scope="function") +@asynccontextmanager +async def setup_sim() : + sim = await SpendSim.create(db_path=Path("file:db_test?mode=memory&cache=shared")) + sim_client = SimClient(sim) + await sim.farm_block() + + try: + yield sim, sim_client + finally: + await sim.close() + +def bootstrap_referee(parent_coin_id, initial_validation_program_hash, initial_split, + amount, timeout, max_move_size, mover_puzzle, waiter_puzzle): + """ + returns referee_wrap + """ + puzzle_hash = referee.curry( + [initial_validation_program_hash, 0, initial_split, amount, timeout, max_move_size, mover_puzzle.tree_hash(), + waiter_puzzle.tree_hash(), referee.tree_hash()]).tree_hash() + coin = Coin(parent_coin_id, puzzle_hash, amount) + return RefereeWrap(coin, bytes(32), bytes(32), bytes(32), + initial_validation_program_hash, 0, initial_split, timeout, max_move_size, + mover_puzzle, waiter_puzzle) + +@dataclass +class RefereeWrap: + coin: Any + grandparent_id: Any + parent_validation_program_hash: Any + parent_everything_else_hash: Any + validation_program_hash: Any + move: Any + split: Any + timeout: Any + max_move_size: Any + mover_puzzle: Any + waiter_puzzle: Any + + def curried_parameters_for_our_puzzle(self, purpose, for_self, move_to_make, split, validation_program_hash): + result = Program.to([ + validation_program_hash, + move_to_make, + split, + self.coin.amount, + self.timeout, + self.max_move_size, + self.mover_puzzle.tree_hash() if for_self else self.waiter_puzzle.tree_hash(), + self.waiter_puzzle.tree_hash() if for_self else self.mover_puzzle.tree_hash(), + refhash + ]) + print(f'for {purpose} curried_parameters_for_our_puzzle is {result}') + return result + + def get_puzzle(self): + return referee.curry(self.curried_parameters_for_our_puzzle( + "GET_PUZZLE", + True, + self.move, + self.split, + self.validation_program_hash + )) + + def SpendMove(self, password, move_to_make, split, validation_program_hash): + """ + returns (solution, new RefereeWrap) + """ + print(f"MOVE referee mover_puzzle {self.mover_puzzle.tree_hash()}") + print(f"MOVE referee waiter_puzzle {self.waiter_puzzle.tree_hash()}") + curried_parameters = self.curried_parameters_for_our_puzzle( + "SPEND_MOVE", + False, + move_to_make, + split, + validation_program_hash + ) + print(f"MOVE referee curried parameters {curried_parameters}") + new_puzzle_hash = referee.curry(curried_parameters).tree_hash() + print(f"MOVE new puzzle hash {Program.to(new_puzzle_hash)}") + solution = Program.to([move, move_to_make, split, validation_program_hash, self.mover_puzzle, + [password, [51, new_puzzle_hash, self.coin.amount]]]) + coin = Coin(self.coin.name(), new_puzzle_hash, self.coin.amount) + everything_else_hash = Program.to([self.move, self.split, self.coin.amount, self.timeout, + self.max_move_size, self.mover_puzzle.tree_hash(), self.waiter_puzzle.tree_hash(), + referee.tree_hash()]).tree_hash() + return (solution, RefereeWrap(coin, self.coin.parent_coin_info, self.validation_program_hash, everything_else_hash, + validation_program_hash, move_to_make, split, self.timeout, self.max_move_size, + self.waiter_puzzle, self.mover_puzzle)) + + def SpendAccuse(self, password): + """ + returns (solution, RefereeAccuse) + """ + print(f"ACCUSE starting with puzzle hash {Program.to(self.get_puzzle().tree_hash())}") + print(f"ACCUSE parent_id {Program.to(self.coin.parent_coin_info)}") + print(f"ACCUSE referee mover_puzzle {self.mover_puzzle.tree_hash()}") + print(f"ACCUSE referee waiter_puzzle {self.waiter_puzzle.tree_hash()}") + new_puzzle_hash = referee_accuse.curry([ + self.parent_validation_program_hash, + self.validation_program_hash, + self.move, + self.split, + self.coin.amount, + self.timeout, + self.waiter_puzzle.tree_hash(), + self.mover_puzzle.tree_hash() + ]).tree_hash() + solution = Program.to([accuse, self.grandparent_id, self.parent_validation_program_hash, + self.parent_everything_else_hash, self.mover_puzzle, [password, [51, new_puzzle_hash, self.coin.amount]]]) + coin = Coin(self.coin.name(), new_puzzle_hash, self.coin.amount) + return (solution, RefereeAccuseWrap(coin, self.parent_validation_program_hash, self.validation_program_hash, + self.move, self.split, self.timeout, self.waiter_puzzle.tree_hash(), + self.mover_puzzle.tree_hash())) + + def SpendTimeout(self): + """ + returns (solution, movercoinid, waitercoinid) + """ + movercoinid = Coin(self.coin.name(), self.mover_puzzle.tree_hash(), self.split).name() + waitercoinid = Coin(self.coin.name(), self.waiter_puzzle.tree_hash(), + self.coin.amount - self.split).name() + return (Program.to((timeout, 0)), movercoinid, waitercoinid) + +@dataclass +class RefereeAccuseWrap: + coin: Any + old_validation_puzzle_hash: Any + new_validation_puzzle_hash: Any + move: Any + split: Any + timeout: Any + accused_puzzle_hash: Any + accuser_puzzle_hash: Any + + def get_puzzle(self): + return referee_accuse.curry([self.old_validation_puzzle_hash, self.new_validation_puzzle_hash, + self.move, self.split, self.coin.amount, self.timeout, self.accused_puzzle_hash, + self.accuser_puzzle_hash]) + + def SpendTimeout(self): + """ + returns (solution, coinid) + """ + coin = Coin(self.coin.name(), self.accuser_puzzle_hash, self.coin.amount) + return (Program.to(0), coin.name()) + + def SpendDefend(self, validation_program_reveal, validation_program_solution): + """ + returns (solution, coinid) + """ + solution = Program.to([validation_program_reveal, validation_program_solution]) + coin = Coin(self.coin.name(), self.accused_puzzle_hash, self.coin.amount) + return (solution, coin.name()) + +@pytest.mark.asyncio +@pytest.mark.parametrize('amove', [0, 1, 2]) +@pytest.mark.parametrize('bmove', [0, 1, 2]) +async def test_rps(amove, bmove, setup_sim): + total = 100 + alice_final = (total//2 if amove == bmove else (0 if bmove == (amove + 1) % 3 else total)) + alice_preimage = int_to_bytes(60 + amove) + alice_image = sha(alice_preimage) + bob_preimage = int_to_bytes(60 + bmove) + bob_image = sha(bob_preimage) + alice_move = int_to_bytes(amove) + nil = Program.to(0) + + # (mod (password . conditions) (if (= password 'alice') conditions (x))) + alice_puzzle = Program.from_bytes(bytes.fromhex('ff02ffff03ffff09ff02ffff0185616c69636580ffff0103ffff01ff088080ff0180')) + alice_puzzle_hash = alice_puzzle.tree_hash() + # (mod (password . conditions) (if (= password 'bob') conditions (x))) + bob_puzzle = Program.from_bytes(bytes.fromhex('ff02ffff03ffff09ff02ffff0183626f6280ffff0103ffff01ff088080ff0180')) + bob_puzzle_hash = bob_puzzle.tree_hash() + + async with setup_sim as (sym, client): + acs = Program.to(1) + acs_hash = acs.tree_hash() + await sym.farm_block(acs_hash) + mycoin = (await client.get_coin_records_by_puzzle_hashes([acs_hash], include_spent_coins = False))[0].coin + # make a coin for a game + referee = bootstrap_referee(mycoin.name(), MOD_A.tree_hash(), 2, total, 1000, 50, alice_puzzle, bob_puzzle) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(mycoin, acs, Program.to([[51, referee.coin.puzzle_hash, + referee.coin.amount]]))], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + savepoint = sym.block_height + # Alice accuse Bob of cheating (negative test, should fail) + solution, accuse = referee.SpendAccuse('alice') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(referee.coin, referee.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.ASSERT_MY_PARENT_ID_FAILED + # timeout too early fail + solution, alice_reward_id, bob_reward_id = referee.SpendTimeout() + spend = SpendBundle([CoinSpend(referee.coin, referee.get_puzzle(), solution)], G2Element()) + (status, err) = await client.push_tx(spend) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.ASSERT_SECONDS_RELATIVE_FAILED + # timeout succeeds + sym.pass_time(2000) + await sym.farm_block() + (status, err) = await client.push_tx(spend) + assert status == MempoolInclusionStatus.SUCCESS + assert err is None + await sym.farm_block() + assert (await client.get_coin_records_by_names([alice_reward_id], include_spent_coins = False))[0].coin.amount == 2 + assert (await client.get_coin_records_by_names([bob_reward_id], include_spent_coins = False))[0].coin.amount == total - 2 + await sym.rewind(savepoint) + # Alice makes an illegally large move, fails + solution, ref2 = referee.SpendMove('alice', bytes(100), 0, bytes(32)) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(referee.coin, referee.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + # Alice makes move with negative split, fails + solution, ref2 = referee.SpendMove('alice', 'abc', -1, bytes(32)) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(referee.coin, referee.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + # Alice makes move with split greater than amount, fails + solution, ref2 = referee.SpendMove('alice', 'abc', referee.coin.amount + 1, bytes(32)) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(referee.coin, referee.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + # Alice move 1 commit to image + bpuz = MOD_B.curry(alice_image) + solution, ref2 = referee.SpendMove('alice', alice_image, 0, bpuz.tree_hash()) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(referee.coin, referee.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + savepoint = sym.block_height + # Bob accuse Alice of cheating + solution, accuse = ref2.SpendAccuse('bob') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref2.coin, ref2.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + savepoint2 = sym.block_height + # Alice accusation defend, gets everything + solution, reward_id = accuse.SpendDefend(MOD_A, nil) + print(solution) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + reward_coin_wrapper = await client.get_coin_records_by_names([reward_id], include_spent_coins = + False) + reward_coin = reward_coin_wrapper[0].coin + assert reward_coin.amount == referee.coin.amount + assert reward_coin.puzzle_hash == alice_puzzle_hash + await sym.rewind(savepoint2) + # accusation timeout too early fail + solution, reward_id = accuse.SpendTimeout() + spend = SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), solution)], G2Element()) + (status, err) = await client.push_tx(spend) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.ASSERT_SECONDS_RELATIVE_FAILED + # accusation timeout succeed, Bob gets everything + sym.pass_time(2000) + await sym.farm_block() + (status, err) = await client.push_tx(spend) + assert status == MempoolInclusionStatus.SUCCESS + assert err is None + await sym.farm_block() + reward_coin_wrapper = await client.get_coin_records_by_names([reward_id], include_spent_coins = + False) + reward_coin = reward_coin_wrapper[0].coin + assert reward_coin.amount == referee.coin.amount + assert reward_coin.puzzle_hash == bob_puzzle_hash + await sym.rewind(savepoint) + # Bob move 2 commit to image + cpuz = MOD_C.curry([alice_image, bob_image]) + solution, ref3 = ref2.SpendMove('bob', bob_image, 0, cpuz.tree_hash()) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref2.coin, ref2.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + savepoint = sym.block_height + # Alice accuse + solution, accuse = ref3.SpendAccuse('alice') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref3.coin, ref3.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Bob defends + solution, reward_id = accuse.SpendDefend(bpuz, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + reward_coin = (await client.get_coin_records_by_names([reward_id], include_spent_coins = + False))[0].coin + assert reward_coin.amount == referee.coin.amount + assert reward_coin.puzzle_hash == bob_puzzle_hash + await sym.rewind(savepoint) + # Alice reveals wrong preimage + alice_bad_preimage = int_to_bytes(61 + amove) + dpuz = MOD_D.curry([(amove + 1) % 3, bob_image]) + solution, ref4 = ref3.SpendMove('alice', alice_bad_preimage, 0, dpuz.tree_hash()) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref3.coin, ref3.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Bob accuses + solution, accuse = ref4.SpendAccuse('bob') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref4.coin, ref4.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Alice defends, fails + solution, reward_id = accuse.SpendDefend(cpuz, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + await sym.rewind(savepoint) + # Alice move 3 reveal preimage + dpuz = MOD_D.curry([alice_move, bob_image]) + solution, ref4 = ref3.SpendMove('alice', alice_preimage, 0, dpuz.tree_hash()) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref3.coin, ref3.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + savepoint = sym.block_height + # Bob accuses + solution, accuse = ref4.SpendAccuse('bob') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref4.coin, ref4.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Alice defends + solution, reward_id = accuse.SpendDefend(cpuz, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.rewind(savepoint) + # Bob move 4 reveal wrong preimage + bob_bad_preimage = int_to_bytes(121 + amove) + solution, ref5 = ref4.SpendMove('bob', bob_bad_preimage, 0, dpuz.tree_hash()) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref4.coin, ref4.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Alice accuses + solution, accuse = ref5.SpendAccuse('alice') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref5.coin, ref5.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Bob attempts defense, fails + solution, reward_id = accuse.SpendDefend(dpuz, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + # Bob attempts defense with wrong validation program, fails + solution, reward_id = accuse.SpendDefend(acs, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + await sym.rewind(savepoint) + if amove == bmove: + # Bob move 4 gives wrong split + solution, ref5 = ref4.SpendMove('bob', bob_preimage, 0, dpuz.tree_hash()) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref4.coin, ref4.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Alice accuses + solution, accuse = ref5.SpendAccuse('alice') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref5.coin, ref5.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Bob attempts defense, fails + solution, reward_id = accuse.SpendDefend(dpuz, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + await sym.rewind(savepoint) + # Bob move 4 reveal preimage + solution, ref5 = ref4.SpendMove('bob', bob_preimage, alice_final, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref4.coin, ref4.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + savepoint = sym.block_height + # Alice attempts move, fails + solution, ref6 = ref5.SpendMove('alice', nil, 0, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref5.coin, ref5.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + # timeout, split correct + sym.pass_time(2000) + await sym.farm_block() + solution, alice_reward_id, bob_reward_id = ref5.SpendTimeout() + spend = SpendBundle([CoinSpend(ref5.coin, ref5.get_puzzle(), solution)], G2Element()) + (status, err) = await client.push_tx(spend) + assert status == MempoolInclusionStatus.SUCCESS + assert err is None + await sym.farm_block() + if alice_final != 0: + assert (await client.get_coin_records_by_names([alice_reward_id], include_spent_coins = False))[0].coin.amount == alice_final + else: + assert len(await client.get_coin_records_by_names([alice_reward_id], include_spent_coins = False)) == 0 + if alice_final != ref5.coin.amount: + assert (await client.get_coin_records_by_names([bob_reward_id], include_spent_coins = False))[0].coin.amount == ref5.coin.amount - alice_final + else: + assert len(await client.get_coin_records_by_names([bob_reward_id], include_spent_coins = False)) == 0 + await sym.rewind(savepoint) + # Alice accuses + solution, accuse = ref5.SpendAccuse('alice') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref5.coin, ref5.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Bob defends + solution, reward_id = accuse.SpendDefend(dpuz, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert (status, err) == (MempoolInclusionStatus.SUCCESS, None) diff --git a/resources/tests/game-referee-in-cl21/testrockpaperscissors.py b/resources/tests/game-referee-in-cl21/testrockpaperscissors.py new file mode 100644 index 000000000..ed45dbccc --- /dev/null +++ b/resources/tests/game-referee-in-cl21/testrockpaperscissors.py @@ -0,0 +1,48 @@ +import hashlib + +from hsms.streamables.program import Program +from hsms.puzzles.load_clvm import load_clvm + +from clvm.EvalError import EvalError + + +MOD_A = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsa.clvm.hex").read())) +MOD_B = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsb.clvm.hex").read())) +MOD_C = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsc.clvm.hex").read())) +MOD_D = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsd.clvm.hex").read())) + + +def drun(prog: Program, *args: Program): + try: + return prog.run(*args) + except EvalError as ee: + print(f"brun -x -y main.sym {prog} {Program.to(list(args))}") + raise + +def sha256(blob:bytes) -> bytes: + return hashlib.sha256(blob).digest() + +def testrps(amove, bmove): + total = 100 + alice_final = (total//2 if amove == bmove else (0 if bmove == (amove + 1) % 3 else total)) + alice_preimage = Program.to(60 + amove) + bob_preimage = Program.to(60 + bmove) + alice_image = sha256(alice_preimage.atom) + bob_image = sha256(bob_preimage.atom) + alice_move = Program.to(amove) + + cd = MOD_D.curry(alice_move, bob_image) + assert cd.run([total, bob_preimage, b'', alice_final, b'j']).atom == b'j' + cc = MOD_C.curry(alice_image, bob_image) + assert cc.run([total, alice_preimage, cd.tree_hash(), 0, b'j']).atom == b'j' + cb = MOD_B.curry(alice_image) + assert cb.run([total, bob_image, cc.tree_hash(), 0, b'j']).atom == b'j' + assert MOD_A.run([total, alice_image, cb.tree_hash(), 0, b'j']).atom == b'j' + +def testall(): + for i in range(3): + for j in range(3): + testrps(i, j) + +if __name__ == '__main__': + testall() diff --git a/resources/tests/game-referee-in-cl21/utils.clinc b/resources/tests/game-referee-in-cl21/utils.clinc new file mode 100644 index 000000000..7d754e001 --- /dev/null +++ b/resources/tests/game-referee-in-cl21/utils.clinc @@ -0,0 +1,17 @@ +( + (defmacro ifc ARGS + (defun list-length (lst) + (if (l lst) + (+ 1 (list-length (r lst))) + 0 + ) + ) + (defun do-continued-if (ARGS) + (if (= (list-length ARGS) 3) + (qq (i (unquote (f ARGS)) (com (unquote (f (r ARGS)))) (com (unquote (f (r (r ARGS))))))) + (qq (i (unquote (f ARGS)) (com (unquote (f (r ARGS)))) (unquote (do-continued-if (r (r ARGS)))))) + ) + ) + (qq (a (unquote (do-continued-if ARGS)) @)) + ) +) diff --git a/resources/tests/game-referee-in-cl23/all-in-list.clinc b/resources/tests/game-referee-in-cl23/all-in-list.clinc new file mode 100644 index 000000000..1db5f26ad --- /dev/null +++ b/resources/tests/game-referee-in-cl23/all-in-list.clinc @@ -0,0 +1,12 @@ +( + (defun enquote-rest (L) + (if L + (c (c 1 (f L)) (enquote-rest (r L))) + () + ) + ) + + (defun all-in-list (L) + (a (c 34 (enquote-rest L)) ()) + ) +) diff --git a/resources/tests/game-referee-in-cl23/append.clinc b/resources/tests/game-referee-in-cl23/append.clinc new file mode 100644 index 000000000..885a90bb2 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/append.clinc @@ -0,0 +1,8 @@ +( + (defun append (L R) + (if L + (c (f L) (append (r L) R)) + R + ) + ) +) \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/assert.clinc b/resources/tests/game-referee-in-cl23/assert.clinc new file mode 100644 index 000000000..67376b08a --- /dev/null +++ b/resources/tests/game-referee-in-cl23/assert.clinc @@ -0,0 +1,10 @@ +( + (defun assert_ (items) + (if (r items) + (qq (if (unquote (f items)) (unquote (assert_ (r items))) (x))) + (f items) + ) + ) + + (defmac assert items (assert_ items)) +) diff --git a/resources/tests/game-referee-in-cl23/busy.clinc b/resources/tests/game-referee-in-cl23/busy.clinc new file mode 100644 index 000000000..e534d2125 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/busy.clinc @@ -0,0 +1,11 @@ +( + (defun busy (myfunc mylist returnval) + (if mylist + (last + (a myfunc (list (f mylist))) + (busy myfunc (r mylist) returnval) + ) + returnval + ) + ) +) diff --git a/resources/tests/game-referee-in-cl23/calpoker_generate.clinc b/resources/tests/game-referee-in-cl23/calpoker_generate.clinc new file mode 100644 index 000000000..4bbf26f7c --- /dev/null +++ b/resources/tests/game-referee-in-cl23/calpoker_generate.clinc @@ -0,0 +1,466 @@ +( +; Proposer function takes readable_info and returns (player_contribution, +; [(whether_my_move driver validation_program_hash state mover_share)]) +; Accepter function takes (player_contribution +; [(whether_opponent_move validation_program_hash state mover_share)]) and returns +; (UNHANDLED) or (ERROR) or (ACCEPTABLE readable_info initial_driver) +; Driver functions are either moving or waiting type +; Moving driver takes (local_move amount state entropy) and returns +; (move validation_program_hash state split waiting_driver message_parser) +; Waiting driver takes (amount state move split) and returns +; (MAKE_MOVE readable_info validation_program_hash state moving_driver message) or +; (SLASH evidence) +; Message parsers take a message and return readable_info or asserts + +(include assert.clinc) +(include shatree.clinc) + +(defconst MAKE_MOVE 0) +(defconst SLASH 1) +(defconst ERROR 0) +(defconst UNHANDLED 1) +(defconst ACCEPTABLE 2) + +(defun calpoker_alice_proposer (bet_size) + (list + bet_size + (list + (list + 1 + calpoker_alice_driver_a + AHASH + 0 + bet_size + ) + ) + ) +) + +; state is empty +; local_move is nil +; makes a move using entropy +(defun calpoker_alice_driver_a (local_move amount validation_program_hash state entropy) + (assign + preimage (substr entropy 0 16) + image (sha256 preimage) + (list + image + BHASH + image + 0 + (curry calpoker_alice_driver_b preimage) + ) + ) +) + +; state is alice's commit +; move is bob's seed +; immediately sends a message giving Alice's seed +(defun calpoker_alice_driver_b (PREIMAGE amount image move split) + (list MAKE_MOVE (make_cards_readable (make_cards (sha256 PREIMAGE move))) CHASH (list image move) calpokerc + (curry calpoker_alice_driver_c PREIMAGE) PREIMAGE) +) + +(defun bitify (mylist) + (if (not mylist) + 0 + (logior (f mylist) (lsh (bitify (r mylist)) 1)) + ) +) + +; state is alice's commit and bob's seed +; move is alice's reveal of her card generating seed and her commit to which cards she's picking +(defun calpoker_alice_driver_c (PREIMAGE local_move amount (alice_commit bob_seed) entropy) + (assign + cards (make_cards (sha256 PREIMAGE bob_seed)) + my_picks (bitify local_move) + salt (substr entropy 0 16) + new_commit (sha256 (concat salt my_picks)) + (list + new_commit + DHASH + (list CARDS new_commit) + 0 + (curry calpoker_alice_driver_d salt my_picks) + PREIMAGE + ) + ) +) + +(defun split_cards (cards picks) + (if (not cards) + (list 0 0) + (assign + (inner_my_cards inner_other_cards) (split_cards (r cards) (r picks)) + (if (f picks) + (list (c (f cards) inner_my_cards) inner_other_cards) + (list inner_my_cards (c (f cards) inner_other_cards)) + ) + ) + ) +) + +; state is the cards for both players and alice's card pick commitment +; move is Bob's picks +; should immediately respond with a move revealing picks and selecting best cards and final split +(defun calpoker_alice_driver_d (MY_SALT MY_PICKS amount + (@ state (cards my_commit)) move split) + (assign + (my_cards_me my_cards_bob) (split_cards (f cards) MY_PICKS) + (bob_cards_bob bob_cards_me) (split_cards (r cards) move) + my_all_cards (map make_card (append my_cards_me bob_cards_me)) + bob_all_cards (map make_card (append bob_cards_bob my_cards_bob)) + my_picks (handcalc my_all_cards) + bob_picks (handcalc bob_all_cards) + my_hand_value (onehandcalc (pull_out_cards my_picks my_all_cards)) + bob_hand_value (onehandcalc (pull_out_cards bob_picks bob_all_cards)) + win_result (hand_compare my_hand_value bob_hand_value) + split (if (= win_result 1) 0 (= win_result 0) (lsh amount -1) amount) + (list MAKE_MOVE + (list (to_bitfield move) (to_bitfield my_picks) (to_bitfield bob_picks) + my_hand_value bob_hand_value win_result) + EHASH + 0 + (lambda (& MY_SALT MY_PICKS split) (list (concat MY_SALT MY_PICKS) 0 0 split)) + ) + ) +) + +(defun calpoker_bob_accepter (player_contribution ((whether_opponent_move + validation_program_hash state mover_share) . extra)) + (if (!= validation_program_hash AHASH) + (list UNHANDLED) + (any + extra + (not whether_opponent_move) + state + (!= player_contribution mover_share) + ) + (list ERROR) + (list ACCEPTABLE 0 calpoker_bob_driver_a) + ) +) + +; state is empty +; move is alice commit to a salted word +(defun calpoker_bob_driver_a (amount state move split) + (list MAKE_MOVE 0 BHASH move calpoker_alice_driver_b) +) + +; state is alice_commit +; move is bob_seed +(defun calpoker_bob_driver_b (amount alice_commit local_move entropy) + (assign + seed (substr entropy 0 16) + (list + seed + CHASH + (list alice_commit seed) + 0 + calpoker_alice_driver_c + parse_message + ) + ) +) + +; state is alice's commit and bob's seed +; move is alice's reveal of her card generating seed and her commit to which cards she's picking +; expecting a message revealing Alice's seed which results in local display once verified +(defun calpoker_bob_driver_c (amount (@ state (alice_commit bob_seed)) move split) + (assign + (@ cards (alice_cards bob_cards)) (make_cards (sha256 (substr move 0 16) bob_seed)) + alice_picks_commit (substr move 16 48) + (list MAKE_MOVE (make_cards_readable cards) DHASH (list cards alice_picks_commit) calpoker_alice_driver_d) + ) +) + +(defun parse_message (message (alice_commit bob_seed)) + (assert + (= (sha256 message) alice_commit) + (make_cards_readable (make_cards (sha256 message bob_seed))) + ) +) + +(defun slashable (amount validater state move new_validation_hash split evidence) + (assign + (returnval . exception) (run validater (list 0 (list move new_validation_hash split 0 0 0 amount) + state 0 0 0 evidence)) + (not exception) + ) +) + +; state is ((alice_cards bob_cards) alice_pick_commitment) +; move is Bob's picks +(defun calpoker_bob_driver_d (local_move amount ((alice_cards bob_cards) alice_commit_2)) + (assign + my_move (bitify local_move) + (list + my_move + EHASH + (list my_move (list alice_cards bob_cards) alice_commit_2) + 0 + calpoker_bob_driver_e + ) + ) +) + +; state is (Bob's picks (alice_cards bob_cards) alice_commit) +; move is alice_salted_picks +; either fraud proves or accepts split +(defun calpoker_bob_driver_e (amount (@ state (bob_selects (alice_cards_bob_cards) alice_commit_2)) move split) + (assign + alice_selects (substr move 16 17) + (alice_cards_alice alice_cards_bob) (split_cards alice_cards alice_picks) + (bob_cards_bob bob_cards_alice) (split_cards bob_cards bob_selects) + alice_all_cards (map make_card (append alice_cards_alice bob_cards_alice)) + bob_all_cards (map make_card (append bob_cards_bob alice_cards_bob)) + alice_picks (handcalc my_all_cards) + bob_picks (handcalc bob_all_cards) + alice_hand_value (onehandcalc (pull_out_cards alice_picks alice_all_cards)) + bob_hand_value (onehandcalc (pull_out_cards bob_picks bob_all_cards)) + win_result (hand_compare alice_hand_value bob_hand_value) + correct_split (if (= win_result 1) 0 (= win_result 0) (lsh amount -1) amount) + (if (< split correct_split) + (list SLASH bob_picks) + (list MAKE_MOVE + (list (to_bitfield alice_selects) (to_bitfield bob_picks) (to_bitfield alice_picks) + bob_hand_value alice_hand_value (- 0 win_result)) + 0 + ) + ) + ) +) + +(defconst EHASH (shatree calpokere)) +(defconst DHASH (shatree calpokerd)) +(defconst CHASH (shatree calpokerc)) +(defconst BHASH (shatree calpokerb)) +(defconst AHASH (shatree calpokera)) + +; Bob challenging +; state is empty +; move is alice commit to a salted word +; evidence is empty +(defun calpokera (mod_hash (move next_validation_hash mover_share previous_validation_hash + mover_puzzle_hash waiter_puzzle_hash amount timeout max_move_size referee_hash) + state me mover_puzzle solution evidence) + + (assert + (not + (all + (= new_validation_hash (sha256 BHASH (sha256 1 move))) + (= (strlen move) 32) + ) + ) + 0 + ) +) + +; Alice challenging +; state is alice's commit +; move is bob's seed +; evidence is empty +(defun calpokerb (mod_hash (move next_validation_hash mover_share previous_validation_hash + mover_puzzle_hash waiter_puzzle_hash amount timeout max_move_size referee_hash) + alice_commit me mover_puzzle solution evidence) + (assert + (not + (all + (= new_validation_hash (sha256 CHASH (shatree (list alice_commit bob_seed)))) + (= (strlen bob_seed) 16) + ) + ) + 0 + ) +) + +(defun make_card_readable (val) + (assign + (rank . suit) (divmod val 4) + (if (= rank 12) + (list 1 (+ 1 suit)) + (list (+ 2 rank) (+ 1 suit)) + ) + ) +) + +(defun make_cards_readable ((cardsa cardsb)) + (list (map make_card_readable cardsa) (map make_card cardsb)) +) + +(defun make_cards (randomness) + (assign + (handa newrandomness) (choose 52 8 randomness) + (handb newrandomness2) (choose (- 52 8) newrandomness) + (list handa (mergeover handa handb)) + ) +) + +(defun <= (a b) + (not (> a b)) +) + +; like mergein but only calculates the contents of inner with offsets +; applied and doesn't interleave the contents of outer +(defun mergeover (outer inner offset) + (if (not inner) + 0 + (assign first (+ (f inner) offset) + (if (not outer) + (c first (mergeover 0 (r inner) offset)) + (if (<= (f outer) first) + (mergeover (r outer) inner (+ offset 1)) + (c first (mergeover outer (r inner) offset)) + ) + ) + ) + ) +) + +; slide the things in inner in between the things in outer assuming +; things in inner are already bumped up by offset things from outer which +; came before +(defun mergein (outer inner offset) + (if (not inner) + outer + (assign first (+ (f inner) offset) + (if (not outer) + (c first (mergein 0 (r inner) offset)) + (if (<= (f outer) first) + (c (f outer) (mergein (r outer) inner (+ offset 1))) + (c first (mergein outer (r inner) offset)) + ) + ) + ) + ) +) + +; pick numchoose things out of numcards options with randomness extracted from vals +; returns (cards newvals) cards are always in sorted order +(defun choose (numcards numchoose randomness) + (if (= numchoose 1) + (assign (newrandomness card) (divmod randomness numcards) + (list (list card) newrandomness) + ) + (assign + half (lsh numchoose -1) + (cards1 newrandomness2) (choose numcards half randomness) + (cards2 newrandomness3) (choose (- numcards half) (- numchoose half) newrandomness2) + (list (mergein cards1 cards2 0) newrandomness3) + ) + ) +) + +; Bob challenging +; state is alice's commit and bob's seed +; move is alice's reveal of her card generating seed and her commit to which cards she's picking +; evidence is empty +(defun calpokerc (mod_hash (move next_validation_hash mover_share previous_validation_hash + mover_puzzle_hash waiter_puzzle_hash amount timeout max_move_size referee_hash) + (alice_commit bob_seed) me mover_puzzle solution evidence) + (assert + (not + (all + (= (strlen move) 48) + (= (sha256 (substr move 0 16)) alice_commit) + (= new_validation (sha256 DHASH (shatree (list (make_cards + (sha256 (substr move 0 16) bob_seed)) (substr move 16 48))))) + ) + ) + 0 + ) +) + +(defun onecount (mymask) + (if mymask + (+ (logand mymask 1) (onecount (lsh mymask -1))) + 0 + ) +) + +; Alice challenging +; state is the cards for both players and alice's card pick commitment +; move is Bob's picks +; evidence is empty +(defun calpokerd (mod_hash (bob_picks next_validation_hash mover_share previous_validation_hash + mover_puzzle_hash waiter_puzzle_hash amount timeout max_move_size referee_hash) + (cards alice_commit) me mover_puzzle solution evidence) + (assert + (not + (all + (= (strlen bob_picks) 1) + (= (onecount bob_picks) 4) + (= new_validation_hash (sha256 EHASH (shatree (list bob_picks cards alice_commit)))) + ) + ) + 0 + ) +) + +(include handcalc.clinc) +(include map.clinc) + +; Use mask to determine which cards are prepended to leftcards and which to rightcards +(defun extract_cards (mask cards leftcards rightcards) + (if (not cards) + (list leftcards rightcards) + (if (logand mask 1) + (extract_cards (lsh mask -1) (r cards) leftcards (c (f cards) rightcards)) + (extract_cards (lsh mask -1) (r cards) (c (f cards) leftcards) rightcards) + ) + ) +) + +(defun make_card (val) + (assign + (rank . suit) (divmod val 4) + (list (+ 2 rank) (+ 1 suit)) + ) +) + +(defun pull_out_cards (selections cards) + (if (not cards) + 0 + (if (logand selections 1) + (c (f cards) (pull_out_cards (lsh -1 selections) (r cards))) + (pull_out_cards (lsh -1 selections) (r cards)) + ) + ) +) + +; Bob challenging +; state is (Bob's picks (alice_cards bob_cards) alice_commit) +; move is alice_salted_picks +; evidence is Bob's card selections +(defun calpokere (mod_hash (move next_validation_hash mover_share previous_validation_hash + mover_puzzle_hash waiter_puzzle_hash amount timeout max_move_size referee_hash) + (bob_picks (alice_cards bob_cards) alice_commit) me mover_puzzle solution bob_card_selections) + (assign + alice_salted_picks (substr move 0 16) + alice_card_selections (substr move 16 17) + (alice_final_cards bob_final_cards) (extract_cards bob_picks bob_cards &rest (extract_cards alice_picks alice_cards 0 0)) + result (hand_compare (onehandcalc (pull_out_cards alice_card_selections alice_final_cards)) + (onehandcalc (pull_out_cards bob_card_selections bob_final_cards))) + (assert + (not + (all + (not new_validation_hash) + (= (strlen move) 18) + (= (sha256 alice_salted_picks alice_commit)) + (= (onecount alice_picks) 4) + (<= alice_share + (if (not result) + (/ total 2) + (if (= result 1) + 0 + total + ) + ) + ) + ) + ) + 0 + ) + ) +) +) \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/calpoker_include.clsp b/resources/tests/game-referee-in-cl23/calpoker_include.clsp new file mode 100644 index 000000000..8e821a7af --- /dev/null +++ b/resources/tests/game-referee-in-cl23/calpoker_include.clsp @@ -0,0 +1 @@ +(mod () (include *standard-cl-23*) (include calpoker_generate.clinc) ()) diff --git a/resources/tests/game-referee-in-cl23/condition_codes.clinc b/resources/tests/game-referee-in-cl23/condition_codes.clinc new file mode 100644 index 000000000..45f3265da --- /dev/null +++ b/resources/tests/game-referee-in-cl23/condition_codes.clinc @@ -0,0 +1,41 @@ +; See chia/types/condition_opcodes.py + +( + (defconstant AGG_SIG_UNSAFE 49) + (defconstant AGG_SIG_ME 50) + + ; the conditions below reserve coin amounts and have to be accounted for in output totals + + (defconstant CREATE_COIN 51) + (defconstant RESERVE_FEE 52) + + ; the conditions below deal with announcements, for inter-coin communication + + ; coin announcements + (defconstant CREATE_COIN_ANNOUNCEMENT 60) + (defconstant ASSERT_COIN_ANNOUNCEMENT 61) + + ; puzzle announcements + (defconstant CREATE_PUZZLE_ANNOUNCEMENT 62) + (defconstant ASSERT_PUZZLE_ANNOUNCEMENT 63) + + ; the conditions below let coins inquire about themselves + + (defconstant ASSERT_MY_COIN_ID 70) + (defconstant ASSERT_MY_PARENT_ID 71) + (defconstant ASSERT_MY_PUZZLEHASH 72) + (defconstant ASSERT_MY_AMOUNT 73) + + ; the conditions below ensure that we're "far enough" in the future + + ; wall-clock time + (defconstant ASSERT_SECONDS_RELATIVE 80) + (defconstant ASSERT_SECONDS_ABSOLUTE 81) + + ; block index + (defconstant ASSERT_HEIGHT_RELATIVE 82) + (defconstant ASSERT_HEIGHT_ABSOLUTE 83) + + ; A condition that is always true and always ignore all arguments + (defconstant REMARK 1) +) diff --git a/resources/tests/game-referee-in-cl23/curry-and-treehash.clinc b/resources/tests/game-referee-in-cl23/curry-and-treehash.clinc new file mode 100644 index 000000000..6a63e9364 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/curry-and-treehash.clinc @@ -0,0 +1,92 @@ +( + ;; The code below is used to calculate of the tree hash of a curried function + ;; without actually doing the curry, and using other optimization tricks + ;; like unrolling `shatree`. + + (defconstant ONE 1) + (defconstant TWO 2) + (defconstant A_KW #a) + (defconstant Q_KW #q) + (defconstant C_KW #c) + + ;; Given the tree hash `environment-hash` of an environment tree E + ;; and the tree hash `parameter-hash` of a constant parameter P + ;; return the tree hash of the tree corresponding to + ;; `(c (q . P) E)` + ;; This is the new environment tree with the addition parameter P curried in. + ;; + ;; Note that `(c (q . P) E)` = `(c . ((q . P) . (E . 0)))` + + (defun-inline update-hash-for-parameter-hash (parameter-hash environment-hash) + (sha256 TWO (sha256 ONE C_KW) + (sha256 TWO (sha256 TWO (sha256 ONE Q_KW) parameter-hash) + (sha256 TWO environment-hash (sha256 ONE 0)))) + ) + + ;; This function recursively calls `update-hash-for-parameter-hash`, updating `environment-hash` + ;; along the way. + + (defun build-curry-list (reversed-curry-parameter-hashes environment-hash) + (if reversed-curry-parameter-hashes + (build-curry-list (r reversed-curry-parameter-hashes) + (update-hash-for-parameter-hash (f reversed-curry-parameter-hashes) environment-hash)) + environment-hash + ) + ) + + ;; Given the tree hash `environment-hash` of an environment tree E + ;; and the tree hash `function-hash` of a function tree F + ;; return the tree hash of the tree corresponding to + ;; `(a (q . F) E)` + ;; This is the hash of a new function that adopts the new environment E. + ;; This is used to build of the tree hash of a curried function. + ;; + ;; Note that `(a (q . F) E)` = `(a . ((q . F) . (E . 0)))` + + (defun-inline tree-hash-of-apply (function-hash environment-hash) + (sha256 TWO (sha256 ONE A_KW) + (sha256 TWO (sha256 TWO (sha256 ONE Q_KW) function-hash) + (sha256 TWO environment-hash (sha256 ONE 0)))) + ) + + ;; function-hash: + ;; the hash of a puzzle function, ie. a `mod` + ;; + ;; reversed-curry-parameter-hashes: + ;; a list of pre-hashed trees representing parameters to be curried into the puzzle. + ;; Note that this must be applied in REVERSED order. This may seem strange, but it greatly simplifies + ;; the underlying code, since we calculate the tree hash from the bottom nodes up, and the last + ;; parameters curried must have their hashes calculated first. + ;; + ;; we return the hash of the curried expression + ;; (a (q . function-hash) (c (cp1 (c cp2 (c ... 1)...)))) + ;; + ;; Note that from a user's perspective the hashes passed in here aren't simply + ;; the hashes of the desired parameters, but their treehash representation since + ;; that's the form we're assuming they take in the actual curried program. + + (defun puzzle-hash-of-curried-function (function-hash . reversed-curry-parameter-hashes) + (tree-hash-of-apply function-hash + (build-curry-list reversed-curry-parameter-hashes (sha256 ONE ONE))) + ) + + (defconstant b32 32) + + (defun-inline size_b32 (var) + (= (strlen var) b32) + ) + + (defun calculate_coin_id (parent puzzlehash amount) + (if (all (size_b32 parent) (size_b32 puzzlehash) (> amount -1)) + (sha256 parent puzzlehash amount) + (x) + ) + ) + + ; takes a lisp tree and returns the hash of it + (defun shatree (TREE) + (if (l TREE) + (sha256 2 (shatree (f TREE)) (shatree (r TREE))) + (sha256 1 TREE))) + +) diff --git a/resources/tests/game-referee-in-cl23/curry.clinc b/resources/tests/game-referee-in-cl23/curry.clinc new file mode 100644 index 000000000..81a1ec3a6 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/curry.clinc @@ -0,0 +1,104 @@ +( + ;; The code below is used to calculate of the tree hash of a curried function + ;; without actually doing the curry, and using other optimization tricks + ;; like unrolling `shatree`. + + (defconstant TWO 2) + (defconstant constant-tree ( + (0x4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a . ; = `(sha256 1)` + 0x9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2) . ; = `(sha256 1 1)` = `(sha256 1 #q)` + (0x02a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222 . ; = `(concat 2 (sha256 1 #a))` + 0x02a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5) ; = `(concat 2 (sha256 1 #c))` + ) + ) + + ; I looked into calculating the values of `constant-tree` because it's pretty easy to code-golf + ; out an implementation that produces the values cheaper than just inlining them. The problem is, + ; when do we calculate them? If there were a way to calculate it "before main" and include it in + ; the globally-accessible constant table, we could do that. But we can't which means to be optimal, + ; client code should call the "build table" code once, then pass it around to anyone that wants to + ; call `curry` or `curry2`. This is pretty intrusive, so for now we'll just use the existing + ; global constant infrastructure, and include it as a fixed table so the tree of four values will + ; appear in all code that includes this file, and it will compress better in generators. + + (defun-inline sha256_one _noargs (f (f constant-tree))) + (defun-inline sha256_one_one _noargs (r (f constant-tree))) + (defun-inline two_sha256_one_a_kw _noargs (f (r constant-tree))) + (defun-inline two_sha256_one_c_kw _noargs (r (r constant-tree))) + + ;; this returns the sha256 tree hash of expression F = `((q . a1) a2)` + (defun hash-expression-F (a1 a2) + (sha256 TWO (sha256 TWO (sha256_one_one) a1) + (sha256 TWO a2 (sha256_one))) + ) + + ;; Given the tree hash `environment-hash` of an environment tree E + ;; and the tree hash `parameter-hash` of a constant parameter P + ;; return the tree hash of the tree corresponding to + ;; `(c (q . P) E)` + ;; This is the new environment tree with the addition parameter P curried in. + ;; + ;; Note that `(c (q . P) E)` = `(c . ((q . P) . (E . 0)))` + + (defun-inline update-hash-for-parameter-hash (parameter-hash environment-hash) + (sha256 (two_sha256_one_c_kw) (hash-expression-F parameter-hash environment-hash)) + ) + + ;; Given the tree hash `environment-hash` of an environment tree E + ;; and the tree hash `mod-hash` of a mod M + ;; return the tree hash of the tree corresponding to + ;; `(a (q . M) E)` + ;; This is the hash of a new function that adopts the new environment E. + ;; This is used to build of the tree hash of a curried function. + ;; + ;; Note that `(a (q . M) E)` = `(a . ((q . M) . (E . 0)))` + + (defun-inline tree-hash-of-apply (mod-hash environment-hash) + (sha256 (two_sha256_one_a_kw) (hash-expression-F mod-hash environment-hash)) + ) + + ;; This function recursively calls `update-hash-for-parameter-hash` + + (defun calculate-hash-of-curried-parameters (curry-parameter-hashes) + (if curry-parameter-hashes + (update-hash-for-parameter-hash (f curry-parameter-hashes) (calculate-hash-of-curried-parameters (r curry-parameter-hashes))) + (sha256_one_one) + ) + ) + + ;; mod-hash: + ;; the hash of a puzzle function, ie. a `mod` + ;; + ;; curry-parameter-hashes: + ;; a list of pre-hashed trees representing parameters to be curried into the puzzle. + ;; + ;; we return the hash of the curried expression + ;; (a (q . mod-hash) (c (cp1 (c cp2 (c ... 1)...)))) + ;; + ;; Note that from a user's perspective the hashes passed in here aren't simply + ;; the hashes of the desired parameters, but their treehash representation since + ;; that's the form we're assuming they take in the acutal curried program. + + ;; inline functions that take varargs don't seem to work, so we can't inline `curry` + + (defun curry_hashes (mod-hash . curry-parameter-hashes) + (tree-hash-of-apply mod-hash + (calculate-hash-of-curried-parameters curry-parameter-hashes)) + ) + + + ;; this is included for future compilers that handle it properly. If you get weird + ;; errors using this, it may be your tooling. Use `curry` above instead, or inline manually. + + (defun-inline curry_hashes_inline (mod-hash . curry-parameter-hashes) + (tree-hash-of-apply mod-hash + (calculate-hash-of-curried-parameters curry-parameter-hashes)) + ) + + ;; `curry_mod_hashes_inline` takes exactly two parameters rather than varags, and it can be inlined + + (defun-inline curry_mod_hashes_inline (mod-hash curry-parameter-hashes) + (tree-hash-of-apply mod-hash + (calculate-hash-of-curried-parameters curry-parameter-hashes)) + ) +) diff --git a/resources/tests/game-referee-in-cl23/deep_compare.clinc b/resources/tests/game-referee-in-cl23/deep_compare.clinc new file mode 100644 index 000000000..0a863ae33 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/deep_compare.clinc @@ -0,0 +1,41 @@ + +( + (defun deep_compare (a b) + (if (l a) + (if (l b) + (assign-lambda inner_result (deep_compare (f a) (f b)) + (if inner_result + inner_result + (deep_compare (r a) (r b)) + ) + ) + 1 + ) + (if (l b) + -1 + (if (> a b) + 1 + (- 0 (> b a)) + ) + ) + ) + ) + (defun deep< (a b) + (= (deep_compare a b) -1) + ) + (defun deep> (a b) + (= (deep_compare a b) 1) + ) + (defun deep= (a b) + (= (deep_compare a b) 0) + ) + (defun deep<= (a b) + (not (deep> a b)) + ) + (defun deep>= (a b) + (not (deep< a b)) + ) + (defun deep!= (a b) + (not (deep= a b)) + ) +) diff --git a/resources/tests/game-referee-in-cl23/deep_compare_t2.clsp b/resources/tests/game-referee-in-cl23/deep_compare_t2.clsp new file mode 100644 index 000000000..6df52dd65 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/deep_compare_t2.clsp @@ -0,0 +1,6 @@ +(mod (A B) + (include *standard-cl-23*) + (include deep_compare.clinc) + + (deep_compare A B) + ) diff --git a/resources/tests/game-referee-in-cl23/detectwrap.clinc b/resources/tests/game-referee-in-cl23/detectwrap.clinc new file mode 100644 index 000000000..c6364bb36 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/detectwrap.clinc @@ -0,0 +1,17 @@ +( + (defun get-straight-hand (my_straight_high last cards) + (if (print "gsh cards" cards) + (let ((next (get-straight-hand my_straight_high (r cards)))) + (if (logior + (logand (= my_straight_high 5) (= (f (f cards)) 14)) + (logand + (>= my_straight_high (f (f cards))) + (<= (- my_straight_high 4) (f (f cards))))) + (c (f cards) next) + next + ) + ) + () + ) + ) +) diff --git a/resources/tests/game-referee-in-cl23/filtermap.clinc b/resources/tests/game-referee-in-cl23/filtermap.clinc new file mode 100644 index 000000000..f37cb862d --- /dev/null +++ b/resources/tests/game-referee-in-cl23/filtermap.clinc @@ -0,0 +1,21 @@ + +( + (defun filtermap_fun (process remaining init) + (if remaining + (assign next (a process (list (f remaining))) + (if next + (c next (filtermap process (r remaining) init)) + (filtermap process (r remaining) init) + ) + ) + init + ) + ) + + (defmac filtermap (process remaining . maybe_init) + (if maybe_init + (qq (filtermap_fun (unquote process) (unquote remaining) (unquote (f maybe_init)))) + (qq (filtermap_fun (unquote process) (unquote remaining) ())) + ) + ) +) \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/flatten.clinc b/resources/tests/game-referee-in-cl23/flatten.clinc new file mode 100644 index 000000000..ab3815abd --- /dev/null +++ b/resources/tests/game-referee-in-cl23/flatten.clinc @@ -0,0 +1,12 @@ +( + (defun flatten_list (everything) + (if + (not everything) 0 + (prepend (f everything) (flatten_list (r everything))) + ) + ) + (defun flatten everything + (flatten_list everything) + ) + +) \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/handbitmap.clinc b/resources/tests/game-referee-in-cl23/handbitmap.clinc new file mode 100644 index 000000000..7becb0f95 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/handbitmap.clinc @@ -0,0 +1,66 @@ +( + (defun mem (choice lst) + (if lst + (if (deep= choice (f lst)) + lst + (mem choice (r lst)) + ) + () + ) + ) + + (defun bitmap_from_members (chosen cards) + (if cards + (logior (not (not (mem (f cards) chosen))) (lsh (bitmap_from_members chosen (r cards)) 1)) + 0 + ) + ) + + (defun find_hand_indices_x (hand cards) + (bitmap_from_members (ranks_from_hand hand cards) cards) + ) + + (defun find_hand_indices (hand cards) + (find_hand_indices_x hand cards) + ) + + (defun member_of_hand (rank hand) + (if hand + (if (= (f (f hand)) rank) + 1 + (member_of_hand rank (r hand)) + ) + 0 + ) + ) + + (defun remove_rank_from_hand (rank (@ hand (f_hand . r_hand))) + (if hand + (if (= (f f_hand) rank) + (if (> (r f_hand) 1) + (c (c (f f_hand) (- (r f_hand) 1)) r_hand) + r_hand + ) + (c (f hand) (remove_rank_from_hand rank r_hand)) + ) + () + ) + ) + + (defun ranks_from_hand_real (hand (@ cards ((@ first_card (first_rank . first_suit)) . remaining_cards))) + (if cards + (if (member_of_hand first_rank hand) + (assign + new_hand (remove_rank_from_hand first_rank hand) + (c first_card (ranks_from_hand new_hand remaining_cards)) + ) + (ranks_from_hand hand remaining_cards) + ) + () + ) + ) + + (defun ranks_from_hand (hand cards) + (ranks_from_hand_real (map (lambda (count . rank) (c rank count)) cards)) + ) +) diff --git a/resources/tests/game-referee-in-cl23/handcalc.clinc b/resources/tests/game-referee-in-cl23/handcalc.clinc new file mode 100644 index 000000000..d85154890 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/handcalc.clinc @@ -0,0 +1,232 @@ + +; ranks are 2-14 with 2 being two, 13 being king, and 14 being ace +; suits are 1-4 with no particular labelling +; takes a list of cards (rank . suit) and returns the value of the best poker +; hand which can be made with them +; doesn't work for ten or more cards if there are multiple flushes +; all sorting is done highest to lowest +( + (defun find_flush (suits) + (assign + ((count1 . suit1)) (group_by_count_clean (atomsort suits)) + (* suit1 (>= count1 5)) + ) + ) + + (defun straight_high_inner (ranks last count) + (if (not ranks) + (if (logand (= last 2) (= count 4)) + ; maybe ace to five + 5 + 0 + ) + (if (= last (f ranks)) + ; skip identical cards + (straight_high_inner (r ranks) last count) + ; if the partial straight continues + (if (= (f ranks) (- last 1)) + (if (= count 4) + ; found a straight, add 3 to last because next and last are included + (+ last 3) + ; keep looking for a straight with the count going up by one + (straight_high_inner (r ranks) (f ranks) (+ count 1)) + ) + ; reset the count + (straight_high_inner (r ranks) (f ranks) 1) + ) + ) + ) + ) + + ; returns the high card of a straight or 0 if there isn't any + ; ranks must be sorted in descending order + (defun straight_high_extended (ranks) + (assign + high (straight_high_inner ranks 0 0) + (if (= high 5) + (* (= (f ranks) 14) 5) + high + ) + ) + ) + + (defun group_by_count_clean (items) + (map + unflatten_card + (atomsort (group_by_count_inner items (f items) 0)) + ) + ) + + (defun find_straight_flush_indices (flush_suit straight_flush_high (@ cards ((first_rank . first_suit) . remaining))) + (if (not cards) + 0 + (assign + straight_to_ace_match + (logand + (= straight_flush_high 5) + (= first_rank 14) + ) + + rank_in_range + (logand + (<= first_rank straight_flush_high) + (> first_rank (- straight_flush_high 5)) + ) + + hit + (logand + (= first_suit flush_suit) + (logior straight_to_ace_match rank_in_range) + ) + + (logior (lsh (find_straight_flush_indices flush_suit straight_flush_high remaining) 1) hit) + ) + ) + ) + + (defun flush_cards_with_index (flush_suit index (@ cards ((first_rank . first_suit)))) + (if (not cards) + 0 + (if (= flush_suit first_suit) + (c (flatten_card (c first_rank index)) (flush_cards_with_index flush_suit (+ index 1) (r cards))) + (flush_cards_with_index flush_suit (+ index 1) (r cards)) + ) + ) + ) + + (defun find_flush_indices (flush_suit cards) + (assign + myfiltered (truncate 5 (atomsort (flush_cards_with_index flush_suit 0 cards))) + (to_bitfield 0 (reverse (atomsort (map (lambda (x) (logand x 15)) myfiltered)))) + ) + ) + + ; includes should be in ascending order + (defun to_bitfield (index includes) + (if (not includes) + 0 + (if (= index (f includes)) + (logior 1 (lsh (to_bitfield (+ index 1) (r includes)) 1)) + (lsh (to_bitfield (+ index 1) includes) 1) + ) + ) + ) + + (defun find_straight_includes (ranks with_index) + (if (all ranks with_index) + (if (= (f ranks) (lsh (f with_index) -4)) + (c (logand 15 (f with_index)) (find_straight_includes (r ranks) (r with_index))) + (find_straight_includes ranks (r with_index)) + ) + 0 + ) + ) + + (defun find_straight_indices (my_straight_high cards) + (assign + with_index (atomsort (ranks_with_indices 0 cards)) + my_ranks + (if (= my_straight_high 5) + (list 14 5 4 3 2) + (list + my_straight_high + (- my_straight_high 1) + (- my_straight_high 2) + (- my_straight_high 3) + (- my_straight_high 4) + ) + ) + + includes (reverse (atomsort (find_straight_includes my_ranks with_index))) + (to_bitfield 0 includes) + ) + ) + + (defun ranks_with_indices (index cards) + (if (not cards) + 0 + (c (flatten_card (c (f (f cards)) index)) (ranks_with_indices (+ index 1) (r cards))) + ) + ) + + (defun find_hand_indices ((@ numbered-cards ((number . card) . rest))) + (if numbered-cards + (logior (lsh 1 number) (find_hand_indices rest)) + 0 + ) + ) + + (defun number_cards (num cards) + (if cards + (c (c num (f cards)) (number_cards (+ num 1) (r cards))) + () + ) + ) + + ;; Sorts the cards by group size according to hand. + ;; Hand has pairs of count and rank. We pull out cards based on their rank + ;; until each bucket is empty in hand and then give the remaining cards. + (defun bucket_cards_by_frequency_groups (hand cards) + (if hand + (assign + (hand_freq . want_rank) (f hand) + + (cards_with_rank . cards_without_rank) (partition (lambda ((& want_rank) (num . (rank . suit))) (= rank want_rank)) cards) + + ;; We have the cards with this rank... go to the next wanted rank. + (append cards_with_rank (bucket_cards_by_frequency_groups (r hand) cards_without_rank)) + ) + cards + ) + ) + + (defun normal_full_house (firstcount secondcount hand cards) + (find_hand_indices (truncate 5 (bucket_cards_by_frequency_groups hand (number_cards 0 cards)))) + ) + + (defun handcalc (cards) + (assign-lambda + first (lambda (x) (f x)) + rest (lambda (x) (r x)) + sorted_ranks (atomsort (map first cards)) + hand (group_by_count_clean sorted_ranks) + ((firstcount . firstrank) (secondcount . secondrank)) hand + flush_suit (find_flush (map rest cards)) + (if ;; Full house + (logand (= firstcount 3) (= secondcount 2)) + (normal_full_house firstcount secondcount hand cards) + + ;; Flush + flush_suit + (assign-lambda + flush_cards (filtermap (lambda ((& flush_suit) (@ thecard (rank . suit))) (if (= suit flush_suit) rank 0)) cards) + straight_flush_high (straight_high_extended (atomsort flush_cards)) + (if straight_flush_high + (find_straight_flush_indices flush_suit straight_flush_high cards) + (if (logior (< firstcount 3) (logand (= firstcount 3) (= secondcount 1))) + (find_flush_indices flush_suit cards) + (find_hand_indices (truncate 5 (bucket_cards_by_frequency_groups hand (number_cards 0 cards)))) + ) + ) + ) + + ;; Else + (assign + my_straight_high (straight_high_extended sorted_ranks) + (if (all + my_straight_high + (logior + (< firstcount 3) + (logand (= firstcount 3) (= secondcount 1)) + ) + ) + + (find_straight_indices my_straight_high cards) + + (find_hand_indices (truncate 5 (bucket_cards_by_frequency_groups hand (number_cards 0 cards)))) + ) + ) + ) + ) + ) +) diff --git a/resources/tests/game-referee-in-cl23/handcalc2.clinc b/resources/tests/game-referee-in-cl23/handcalc2.clinc new file mode 100644 index 000000000..c9e2bef17 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/handcalc2.clinc @@ -0,0 +1,233 @@ + +; ranks are 2-14 with 2 being two, 13 being king, and 14 being ace +; suits are 1-4 with no particular labelling +; takes a list of cards (rank . suit) and returns the value of the best poker +; hand which can be made with them +; returned list is hand type followed by cards in descending order +; doesn't work for ten or more cards if there are multiple flushes +; all sorting is done highest to lowest +( + (defconstant STRAIGHT_FLUSH 9) + (defconstant FOUR_OF_A_KIND 8) + (defconstant FULL_HOUSE 7) + (defconstant FLUSH 6) + (defconstant STRAIGHT 5) + (defconstant THREE_OF_A_KIND 4) + (defconstant TWO_PAIR 3) + (defconstant PAIR 2) + (defconstant HIGH_CARD 1) + (defun hand< (a b) + (if a + (if (= (f a) (f b)) + (hand< (r a) (r b)) + (< (f a) (f b)) + ) + 0 + ) + ) + (defun merge (a b) + (if (not a) + b + (if (not b) + a + (if (hand< (f a) (f b)) + (c (f a) (merge (r a) b)) + (c (f b) (merge a (r b))) + ) + ) + ) + ) + (defun handsort_inner (@ mylist (first second third) length) + (if (> length 3) + (merge (handsort_inner mylist (/ length 2)) + (handsort_inner (sliceright mylist (/ length 2)) (- length (/ length 2)))) + (if (= length 3) + (if (hand< first second) + (if (hand< second third) + (list first second third) + (if (hand< first third) + (list first third second) + (list third first second) + ) + ) + (if (hand< first third) + (list second first third) + (if (hand< second third) + (list second third first) + (list third second first) + ) + ) + ) + (if (hand< first second) + (list first second) + (list second first) + ) + ) + ) + ) + (defun handsort (@ mylist (first) length) + (if length + (if (= length 1) + (list first) + (handsort_inner mylist length) + ) + 0 + ) + ) + (defund count_suits (@ cards ((firstrank . firstsuit) . remaining)) + (if (not cards) + (list 0 0 0 0) + ; this should use capture + (assign (clubs diamonds hearts spades) (count_suits (r cards)) + (if (= firstsuit 1) + (list (+ clubs 1) diamonds hearts spades) + (if (= firstsuit 2) + (list clubs (+ diamonds 1) hearts spades) + (if (= firstsuit 3) + (list clubs diamonds (+ hearts 1) spades) + (list clubs diamonds hearts (+ spades 1)) + ) + ) + ) + ) + ) + ) + (defun find_flush_2 (cards) + (assign (clubs diamonds hearts spades) (count_suits cards) + (if (> 4 clubs) + 1 + (if (> 4 diamonds) + 2 + (if (> 4 hearts) + 3 + (if (> 4 spades) + 4 + 0 + ) + ) + ) + ) + ) + ) + (defun find_flush_inner (suits last count) + (if (not suits) + 0 + (if (= (f suits) last) + (if (= count 4) + last + (find_flush_inner (r suits) last (+ count 1)) + ) + (find_flush_inner (r suits) (f suits) 1) + ) + ) + ) + ; returns the flush suit or 0 if there isn't any + ; suits must be clustered/sorted + (defun find_flush (suits) + (find_flush_inner (sort (lambda (x y) (deep> x y)) suits) 0 0) + ) + (defun straight_high_inner (ranks started_ace last count) + (if (not ranks) + ; at the end of the list + (if (logand (= last 2) (= count 4) started_ace) + ; ace to five + 5 + ; no straight + 0 + ) + (if (= last (f ranks)) + ; skip identical cards + (straight_high_inner (r ranks) started_ace last count) + ; if the partial straight continues + (if (= (f ranks) (- last 1)) + (if (= count 4) + ; found a straight, add 3 to last because next and last are included + (+ last 3) + ; keep looking for a straight with the count going up by one + (straight_high_inner (r ranks) started_ace (f ranks) (+ count 1)) + ) + ; reset the count + (straight_high_inner (r ranks) started_ace (f ranks) 1) + ) + ) + ) + ) + ; returns the high card of a straight or 0 if there isn't any + ; ranks must be sorted in descending order + (defun straight_high (ranks) + (straight_high_inner ranks (= (f ranks) 14) 0 0) + ) + (defun group_by_count_inner (items last count) + (if (not items) + (list (c count last)) + (if (= (f items) last) + (group_by_count_inner (r items) last (+ count 1)) + (assign val (group_by_count_inner (r items) (f items) 1) + (c (c count last) val) + ) + ) + ) + ) + (defun group_by_count (items) + (group_by_count_inner items (f items) 0) + ) + (defun handcalc (cards) + (assign-lambda + first (lambda (x) (f x)) + rest (lambda (x) (r x)) + fsuit (find_flush2 (map rest cards)) + max_flush (if (not fsuit) + 0 + (assign-lambda + fnosuits + (sort + (lambda (x y) (deep> x y)) + (filtermap + (lambda ((& fsuit) (card_rank . card_suit)) + (if (= fsuit card_suit) + card_rank + 0 + ) + ) + cards + 0 + ) + ) + + fsh (straight_high fnosuits) + (if fsh + (list STRAIGHT_FLUSH fsh) + (c FLUSH (slice fnosuits 5)) + ) + ) + ) + nosuits (sort (lambda (x y) (deep> x y)) (map first cards)) + sh (straight_high nosuits) + max_straight (if sh + (list STRAIGHT sh) + 0 + ) + groups (sort (lambda (x y) (deep> x y)) (group_by_count nosuits)) + (top_count . top_card) (f groups) + (second_count . second_card) (f (r groups)) + topcards (map rest groups) + max_group (if (= top_count 1) + (c HIGH_CARD (slice topcards 5)) + (if (= top_count 2) + (if (= second_count 1) + (c PAIR (slice topcards 4)) + (c TWO_PAIR (slice topcards 3)) + ) + (if (= top_count 3) + (if (= second_count 1) + (c THREE_OF_A_KIND (slice topcards 3)) + (c FULL_HOUSE (slice topcards 2)) + ) + (c FOUR_OF_A_KIND (slice topcards 2)) + ) + ) + ) + (max (lambda (x y) (deep< x y)) (list max_flush max_straight max_group)) + ) + ) +) diff --git a/resources/tests/game-referee-in-cl23/krunk_generate.clinc b/resources/tests/game-referee-in-cl23/krunk_generate.clinc new file mode 100644 index 000000000..9214804d0 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/krunk_generate.clinc @@ -0,0 +1,404 @@ +( +; Alternates moving and validating +; Moving takes (readable_move amount) and returns (0 readable_state move new_validator new_validation_hash split) +; or (1 error_info) +; The validator and hash will be nil if the game is done + +; Validating takes (move new_validation_hash split amount) and returns either (0 readable_state mover) +; or (1 state validation_program evidence aggsig) if there's cheating +; mover is nil if it's the end of the game + +; Checking takes complete args and either assert fails if there's no sign of cheating or returns +; a list of extra conditions, usually empty + +(include assert.clinc) +(include shatree.clinc) +(include curry.clinc) + +(defun make_mover_a (dictionary dictionary_key) + (assign (next next_hash) (make_validator_b dictionary dictionary_key amount) + (curry mover_a (list next next_hash dictionary dictionary_key amount)) + ) +) + +(defun make_validator_a (dictionary dictionary_key) + (assign (next next_hash) (make_mover_b dictionary dictionary_key amount) + (curry mover_a (list next next_hash dictionary dictionary_key amount)) + ) +) + +; Alice challenging +; curried a next program hash and a dictionary key +; state is an Alice commitment +; move is a Bob guess +; evidence may be range of exclusion if Alice is showing Bob's guess is invalid +(defun make_mover_b (dictionary dictionary_key) + (curry krunk_b (list (make_c dictionary_key) (curry krunk_adjudicate dictionary_key))) +) + +(defun make_validator_b (dictionary dictionary_key) +) + +; Bob challenging +; curried a next program hash and a dictionary key +; state is an Alice commitment and a Bob guess +; move is an Alice clue or word reveal if hit +; evidence may be range of exclusion if Bob is showing Alice's word is invalid +(defun make_mover_c (dictionary dictionary_key) + (curry krunk_c (list (make_d dictionary_key) (curry krunk_adjudicate dictionary_key))) +) + +(defun make_validator_c (dictionary dictionary_key) +) + +; Alice challenging +; curried a list of possible next program hashes and a dictionary key +; state is a Alice commitment, Bob guess and Alice clue +; move is a Bob guess and number of remaining guesses +; evidence may be range of exclusion if Alice is showing Bob's word is invalid +(defun make_mover_d (dictionary dictionary_key) + (curry krunk_d (list (list + (make_e dictionary_key 100 0) + (make_e dictionary_key 20 1) + (make_e dictionary_key 5 2) + (make_e dictionary_key 1 3) + ) + (curry krunk_adjudicate dictionary_key)) + ) +) + +(defun make_validator_d (dictionary dictionary_key) +) + +; Bob challenging +; curried a next program hash, dictionary key, and bet amount +; state is an Alice commitment and series of Bob guesses and Alice clues with the +; latest being a guess +; move is an Alice clue or word reveal if hit +; evidence can be index where clue is wrong or be range of exclusion if +; Bob is showing Alice's word is invalid +(defun make_mover_e (turns_left dictionary dictionary_key bet_amount) + (if (not turns_left) + (make_g dictionary_key bet_amount) + (curry krunk_e (list (make_f dictionary_key bet_amount turns_left) + (curry krunk_adjudicate dictionary_key) bet_amount) + ) + ) +) + +(defun make_validator_e (turns_left dictionary dictionary_key bet_amount) +) + +; Alice challenging +; curried a next program hash, dictionary key, and bet amount +; state is an Alice commitment and series of Bob guesses and Alice clues with the +; latest being a clue +; move is a Bob guess +; evidence may be a range of exclusion if Alice is showing that Bob's guess is invalid +(defun make_mover_f (turns_left dictionary dictionary_key bet_amount) + (curry krunk_f (list (make_e dictionary_key bet_amount (- turns_left 1)) + (curry krunk_adjudicate dictionary_key) bet_amount) + ) +) + +(defun make_validator_f (turns_left dictionary dictionary_key bet_amount) +) + +; Bob challenging +; curried a dictionary key and a bet amount +; move is Alice word reveal +; evidence can be index where clue is wrong or range of exclusion if Alice's word is +; not in the dictionary +(defun make_mover_g (dictionary dictionary_key bet_amount) + (curry krunk_g (list (curry krunk_adjudicate dictionary_key) bet_amount)) +) + +(defun make_validator_g (dictionary dictionary_key bet_amount) +) + +(defconst GHASH (shatree krunk_g)) +(defconst FHASH (shatree krunk_f)) +(defconst EHASH (shatree krunk_e)) +(defconst EHASH1 (shatree (curry_hashes EHASH (shatree (curry_hashes FHASH (shatree GHASH)))))) +(defconst EHASH2 (shatree (curry_hashes EHASH (shatree (curry_hashes FHASH (shatree EHASH1)))))) +(defconst EHASH3 (shatree (curry_hashes EHASH (shatree (curry_hashes FHASH (shatree EHASH2)))))) +(defconst DHASH (shatree krunk_d)) +(defconst CHASH (shatree krunk_c)) +(defconst BHASH (shatree krunk_b)) +(defconst AHASH (shatree krunk_a)) + + +; Bob challenging +; state is the dictionary key +; move is an Alice commit to a salted word +; evidence is empty +(defun krunk_a ((move next_validation_hash mover_share previous_validation_hash + mover_puzzle_hash waiter_puzzle_hash amount timeout max_move_size referee_hash) + dictionary_key me mover_puzzle solution evidence) + + (assert + (not + (all + (= (strlen move) 32) + (= next_validation_hash (sha256 BHASH (shatree (list move dictionary_key)))) + ) + ) + 0 + ) +) + +; Alice challenging +; state is (alice_commit dictionary_key) +; move is a Bob guess +; evidence may be range of exclusion if Alice is showing Bob's guess is invalid +(defun krunk_b ((move next_validation_hash mover_share previous_validation_hash + mover_puzzle_hash waiter_puzzle_hash amount timeout max_move_size referee_hash) + (@ state (alice_commit dictionary_key)) me mover_puzzle solution evidence) + + (if + (all + (= (strlen move) 5) + (= next_validation_hash (sha256 CHASH (shatree (c move state)))) + ) + (assert + (>= move (substr evidence 0 5)) + (<= move (substr evidence 5 10)) + (list (list AGG_SIG_UNSAFE evidence dictionary_key)) + ) + 0 + ) +) + +; Bob challenging +; state is (bob_guess alice_commit dictionary_key) +; move is an Alice clue or commit preimage if hit +; evidence is empty +(defun krunk_c ((move next_validation_hash mover_share previous_validation_hash + mover_puzzle_hash waiter_puzzle_hash amount timeout max_move_size referee_hash) + (@ state (bob_guess alice_commit dictionary_key)) me mover_puzzle solution evidence) + + (assert + (if (= (strlen move) 1) + (any + (>= move 114) + (!= next_validation_hash (sha256 DHASH (shatree (c move state)))) + ) + (any + (!= (strlen move) 37) + (!= (sha256 move) alice_commit) + (!= (substr move 0 5) bob_guess) + ) + ) + 0 + ) +) + +(defun index (myliist num) + (if (not num) + (f mylist) + (index (r mylist) (- num 1)) + ) +) + +; Alice challenging +; state is a (alice_clue bob_guess alice_commit dictionary_key) +; move is a Bob guess and number of remaining guesses +; evidence may be range of exclusion if Alice is showing Bob's word is invalid +(defun krunk_d ((move next_validation_hash mover_share previous_validation_hash + mover_puzzle_hash waiter_puzzle_hash amount timeout max_move_size referee_hash) + (@ state (alice_clue bob_guess @ constants (alice_commit dictionary_key))) me mover_puzzle solution evidence) + + (assign + new_bob_guess (substr move 0 5) + turns_left (substr move 5 6) + (next_hash bet_amount) + (if (not turns_left) (list GHASH 100) + (= turns_left 1) (list EHASH1 20) + (= turns_left 2) (list EHASH2 5) + (list EHASH3 1) + ) + (if + (all + (= (strlen move) 6) + (= next_validation_hash + (sha256 next_hash + (shatree (list (list new_bob_guess alice_clue bob_guess) + bet_amount &rest constants)) + ) + ) + ) + (assert + (>= new_bob_guess (substr evidence 0 5)) + (<= new_bob_guess (substr evidence 5 10)) + (list (list AGG_SIG_UNSAFE evidence dictionary_key)) + ) + 0 + ) + ) +) + +(defun myindex (mylist num) + (if (not num) + mylist + (myindex (r (r mylist)) (- num 1)) + ) +) + +; Bob challenging +; state is ((bob_guess alice_clue bob_guess alice_clue ...) bet_amount alice_commit dictionary_key) +; move is an Alice clue or word reveal if hit +; evidence can be index where clue is wrong +(defun krunk_e (NEXT_HASH (move next_validation_hash mover_share previous_validation_hash + mover_puzzle_hash waiter_puzzle_hash amount timeout max_move_size referee_hash) + (move_list @ constants (bet_amount alice_commit dictionary_key)) me mover_puzzle solution evidence) + + (if (= (strlen move) 37) + (assert + (any + (!= (substr move 0 5) (f move_list)) + (!= (sha256 move) alice_commit) + (!= mover_share (* (div amount 200) (+ 100 bet_amount))) + (assign + (myclue guess) (myindex move_list evidence) + (!= myclue (make_clue (substr move 0 5) guess)) + ) + ) + 0 + ) + (assert + (any + (!= (len move) 1) + (>= move 114) + (!= next_validation_hash (sha256 NEXT_HASH (shatree (c (c move move_list) constants)))) + ) + 0 + ) + ) +) + +(defun move_f ((NEXT_VALIDATOR NEXT_HASH DICTIONARY_KEY BET_SIZE) (@STATE ((alice_commit . move_list))) move amount) + (list + (curry NEXT_VALIDATOR (c alice_commit ())) + ) +) + +(defun validate_f ((NEXT_VALIDATOR HASH DICTIONARY_KEY BET_SIZE) STATE move new_validation_hash split amount) + booga booga +) + +; Alice challenging +; state is ((alice_clue bob_guess alice_clue bob_guess ...) bet_amount alice_commit dictionary_key) +; move is a Bob guess +; evidence may be a range of exclusion if Alice is showing that Bob's guess is invalid +(defun krunk_f (NEXT_HASH (move next_validation_hash mover_share previous_validation_hash + mover_puzzle_hash waiter_puzzle_hash amount timeout max_move_size referee_hash) + (move_list @ constants (bet_amount alice_commit dictionary_key)) me mover_puzzle solution evidence) + + (if + (all + (= (strlen move) 5) + (= next_validation_hash (sha256 NEXT_HASH + (shatree (c (c move move_list) constants)))) + ) + (assert + (>= move (substr evidence 0 5)) + (<= move (substr evidence 5 10)) + (list (list AGG_SIG_UNSAFE evidence dictionary_key)) + ) + 0 + ) +) + +; Moving takes (readable_move amount) and returns (0 readable_state move new_validator new_validation_hash split) +; or (1 error_info) +; The validator and hash will be nil if the game is done +(defun move_g (BET_SIZE (ALICE_PREIMAGE STATE) move amount) + (assign bob_wins (= (substr ALICE_PREIMAGE 0 5) (f (r STATE))) + (list 0 (+ bob_wins 1) ALICE_PREIMAGE 0 0 + (if bob_wins + (* (/ amount 100) (+ 100 BET_SIZE)) + (* (/ amount 100) (- 100 BET_SIZE)) + ) + ) + ) +) + +; Validating takes (move new_validation_hash split amount) and returns either (0 readable_state mover) +; or (1 state validation_program evidence aggsig) if there's cheating +; mover is nil if it's the end of the game +(defun validate_g ((DICTIONARY DICTIONARY_KEY BET_SIZE) (@STATE ((alice_commit . move_list))) + move new_validation_hash split amount) + (assign + validation_program (curry krunk_g (list DICTIONARY BET_SIZE)) + run_validation_program (lambda ((& move validation_program split STATE) evidence) + (validation_program (list (list move 0 split 0 0 0 amount) + STATE 0 0 0 evidence)) evidence) + proof (find_failure validation_program (list 0 1 2 3 4)) + (if proof + (list 1 STATE validation_program (r proof)) + (assign (@proof2 (begin_range end_range signature)) + (find_exclusion_proof (substr move 0 5) DICTIONARY) + (if proof + (list 1 STATE validation_program + (list (concat begin_range end_range)) signature) + 0 + ) + ) + ) + ) +) + +; Bob challenging +; move is Alice word reveal +; state is ((bob_guess alice_clue bob_guess ...) bet_amount alice_commit dictionary_key) +; evidence can be index where clue is wrong or range of exclusion if Alice's word is +; not in the dictionary +(defun krunk_g ((move next_validation_hash mover_share previous_validation_hash + mover_puzzle_hash waiter_puzzle_hash amount timeout max_move_size referee_hash) + (move_list bet_amount alice_commit dictionary_key) me mover_puzzle solution evidence) + + (if + (all + (= (strlen move) 37) + (= (sha256 move) alice_commit) + (= mover_share + (* (div amount 200) + (if (= (substr move 0 5) (f move_list)) + (+ 100 bet_amount) + (- 100 bet_amount) + ) + ) + ) + ) + (if (= (len evidence) 10) + (assign + word (substr 0 5 move) + (assert + (>= word (substr evidence 0 5)) + (<= word (substr evidence 5 10)) + (list (list AGG_SIG_UNSAFE evidence dictionary_key)) + ) + ) + (assert + (assign + (clue guess) (myindex (r move_list) evidence) + (!= clue (make_clue (substr move 0 5) guess)) + ) + 0 + ) + ) + 0 + ) +) + +; format of dictionary is (lower_dictionary word high_dictionary) or (low high signature) +(defun find_exclusion_proof (word @dictionary (first second third)) + (if (not (l first)) + (if (logand (>= word first) (<= word second)) + dictionary + 0 + ) + (find_exclusion_proof word (if (< word second) first third)) + ) +) +) \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/krunk_include.clsp b/resources/tests/game-referee-in-cl23/krunk_include.clsp new file mode 100644 index 000000000..6b392d08a --- /dev/null +++ b/resources/tests/game-referee-in-cl23/krunk_include.clsp @@ -0,0 +1 @@ +(mod () (include *standard-cl-23*) (include krunk_generate.clinc) ()) diff --git a/resources/tests/game-referee-in-cl23/krunk_make_clue.clinc b/resources/tests/game-referee-in-cl23/krunk_make_clue.clinc new file mode 100644 index 000000000..dea720af6 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/krunk_make_clue.clinc @@ -0,0 +1,58 @@ +( +(defun make_clue (word guess) + (assign + (not_green_word not_green_guess green) (make_green (expand_word word) (expand_word guess)) + yellow (make_yellow not_green_word not_green_guess) + (- (merge_colors green yellow 0) 128) + ) +) +(defun expand_word word + (list (substr word 0 1) (substr word 1 2) (substr word 2 3) (substr word 3 4) (substr word 4 5)) +) +(defun make_green (word guess) + (if (not word) + (list 0 0 0) + (assign (inner_not_green_word inner_not_green_guess inner_green) (make_green (r word) (r guess)) + (if (= (f word) (f guess)) + (list inner_not_green_word inner_not_green_guess (c 1 inner_green)) + (list (c (f word) inner_not_green_word) (c (f guess) inner_not_green_guess) (c 0 inner_green)) + ) + ) + ) +) +(defun make_yellow (word guess) + (if (not guess) + 0 + (if (is_yellow word (f guess)) + (c 1 (make_yellow (elide_one word (f guess)) (r guess))) + (c 0 (make_yellow word (r guess))) + ) + ) +) +(defun elide_one (word letter) + (if (= (f word) letter) + (r word) + (c (f word) (elide_one (r word) letter)) + ) +) +(defun is_yellow (word letter) + (if (not word) + 0 + (if (= (f word) letter) + 1 + (is_yellow (r word) letter) + ) + ) +) +(defun merge_colors (green yellow val) + (if (not green) + val + (merge_colors (r green) &rest + (if (f green) + (list yellow (+ 2 (* 3 val))) + (list (r yellow) (+ (f yellow) (* 3 val))) + ) + ) + ) +) +) \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/last.clinc b/resources/tests/game-referee-in-cl23/last.clinc new file mode 100644 index 000000000..aaa9afd24 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/last.clinc @@ -0,0 +1,44 @@ +( + (defun prefix (L P) + (if L + (c (f L) (prefix (r L) P)) + P + ) + ) + + (defun last_inner ((next . remainder)) + (if remainder + (last_inner remainder) + next + ) + ) + + (defun snoc (L agg) + (if L + (if (r L) + (snoc (r L) (c (f L) agg)) + (c (f L) agg) + ) + (c () ()) + ) + ) + + (defun echo myargs + myargs + ) + + (defmac last ARGS + + (if ARGS + (if (r ARGS) + (assign + (final . rest) (snoc ARGS ()) + reversed (prefix rest (echo final)) + (qq (last_inner (unquote (c (q . echo) reversed)))) + ) + (qq (last_inner (unquote (f ARGS)))) + ) + (x "Last takes at least one argument") + ) + ) +) diff --git a/resources/tests/game-referee-in-cl23/len.clinc b/resources/tests/game-referee-in-cl23/len.clinc new file mode 100644 index 000000000..407c36694 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/len.clinc @@ -0,0 +1,3 @@ +( + (defun len (L) (if L (+ 1 (len (r L))) 0)) +) diff --git a/resources/tests/game-referee-in-cl23/main.sym b/resources/tests/game-referee-in-cl23/main.sym new file mode 100644 index 000000000..d93f53a44 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/main.sym @@ -0,0 +1 @@ +{"ac9e61d54eb6967e212c06aab15408292f8558c48f06f9d705150063c68753b0":"prepend.clinc(4):19","ba4484b961b7a2369d948d06c55b64bdbfaffb326bc13b490ab1215dd33d8d46":"*macros*(9):10","35601454cdc8b6b253c2c153d20d41bd234d5af785bada2fec9b806f3d3e1149":"test_prepend.clsp(4):4-test_prepend.clsp(4):11","97f1aa5bc047fef07113607e3c373e96d8d5a1351cc37e2fa022c474c673b421":"prepend.clinc(4):14","a9549b4fbc9e2c4a761843a20b38d0f0409b2959e8c453269df95a2d4340a291":"test_prepend.clsp(4):4-test_prepend.clsp(4):11","959cbf257461e53cfdbbd650fa507fdd8efbe5cf821d4829a44a5f32c317ed06":"test_prepend.clsp(4):4-test_prepend.clsp(4):11","3a8056af8c4a0231c2291077461a84e838e8c12e743d034fbf886a129494d474":"*macros*(9):13","78d79d19cf0b65226f2e85c6320a095520dd28b892e92552eb75680681d89206_arguments":"(a b)","53cadf71ab3e0f40486e0062a0285d0abd49d62268e1c086de49332f345f59c2":"test_prepend.clsp(4):4-test_prepend.clsp(4):11","39517e6ea5ef07f65002b4f33e61d7dc402c1f66a4520b8abfcec4f8452753d0":"prepend.clinc(4):23-prepend.clinc(4):30","f59aaec4e89071300c56f15471775eb151259e1abf02ce04f7bc95945d4db6db":"prepend.clinc(4):14","c7b89cfb9abf2c4cb212a4840b37d762f4c880b8517b0dadb0c310ded24dd86d":"prepend.clinc(4):34","source_file":"test_prepend.clsp","35d2775f75f241d5134e28770c0b9113d64f7fad6e1178899cf93227c4e83ba4":"prepend.clinc(4):14","c4cef5b63c61fb11df3b67cb36408234ec7b97c9002cb15653b9d7b004b2c4bd":"test_prepend.clsp(4):4-test_prepend.clsp(4):11","ed770564041c855cba149d1e6060c78d9a9b8b72755bf18c75e3de33ea4a78c7":"*macros*(9):13","89f9d68742a70b0b54cd17626d61f123782f14a2fc2ef074b0c6721e94fbb59d":"test_prepend.clsp(4):4-test_prepend.clsp(4):11","80b185f76724c1ae194e5a11e268c917f3d9e51c147a65aebcc7c2e9ceff6c40":"test_prepend.clsp(4):12","d390be8fc0e62169431c8225ee915ea00662c05be9ff782c049ac86d3d0a7440":"*macros*(9):13","c77b3c3b64cd919e5791ba14c922e1b5fc7c402fcd7f7298d5a6c30060a1f6b9":"test_prepend.clsp(4):4-test_prepend.clsp(4):11","a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222":"prepend.clinc(4):23-prepend.clinc(4):30","b5e944526a144d4f467d0c0df6f9a450e38e67bec4959626a11baf63d2b4d5d2":"prepend.clinc(4):23-prepend.clinc(4):30","52db9ef97986e7382ef78b8eae2dacdbb2ce823ed1396a0fb2f7f120a2b40a63":"test_prepend.clsp(4):14","d14fb9ffc28a82755bf3c63fa2ecf4b45c0506a815ed2726d059e5af470e102e":"*macros*(8):35-*macros*(8):38","__chia__main_arguments":"(X Y)","bbfaf1ff8b0f26ab8988e690d72d73a7a15f0db4bd810f2483aeac706dc845f6":"test_prepend.clsp(4):14","78d79d19cf0b65226f2e85c6320a095520dd28b892e92552eb75680681d89206_left_env":"1","f720203ee97677a8739d12745eec7cb012253c670c0240eb4d5728c0f646e357":"test_prepend.clsp(4):4-test_prepend.clsp(4):11","74add896f7c7e53d1559c4249ea5d71cd04e0f84746df925434ed31963c9420d":"prepend.clinc(4):32","4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a":"test_prepend.clsp(4):4-test_prepend.clsp(4):11","a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5":"prepend.clinc(4):37","bc5959f43bc6e47175374b6716e53c9a7d72c59424c821336995bad760d9aeb3":"prepend.clinc(3):13","9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2":"test_prepend.clsp(4):4-test_prepend.clsp(4):11","18ad586ec1a16affa3f70278f5dca1dd99f07dabdc196ecff6373967f29ad4fa":"test_prepend.clsp(4):12","c79b932e1e1da3c0e098e5ad2c422937eb904a76cf61d83975a74a68fbb04b99":"*prims*(1):1","11904fe16d39a709fcb3cadbbb203b87cde315410d7dc29ed72f472b7427cc8b":"prepend.clinc(4):23-prepend.clinc(4):30","1e69ab8b04b2824c3fa1c4d7cb9eb9cb464fe3507ed3c153feda00fca2afb749":"*macros*(9):64-*macros*(9):67","03151c9662f0f9fc98270d58284a54e917789a677682f9619fa63c77e22f597d":"*macros*(9):13","8536aaab5cf1232394189671ea87e8570a435e77c48af7ee4888c5298ab21a10":"prepend.clinc(4):23-prepend.clinc(4):30","1babe98d1cee6b6a14b5f5d3236940f113fe8263b2bcbfaf5f3992e13f48fcc8":"prepend.clinc(4):23-prepend.clinc(4):30","2f2b9e2945827ae21eb961df0070926b5460ee4df944788649710d7e7db4eb31":"*macros*(9):10","92fc98892c58f1f36cf7b969422d98d1e96cac746a3113926a1e4a1d192c425b":"test_prepend.clsp(4):4-test_prepend.clsp(4):11","57bfd1cb0adda3d94315053fda723f2028320faa8338225d99f629e3d46d43a9":"prepend.clinc(5):13","78d79d19cf0b65226f2e85c6320a095520dd28b892e92552eb75680681d89206":"prepend","0234e285385f27e9d196c0a62860a3b2f933710ece95fc5325649cc1ced72c93":"test_prepend.clsp(4):14","9d09d3b4894f200226c2784e1d5235deed47acebee097cde63322d439eb81237":"test_prepend.clsp(4):12","7fc37b51fc53952d7983363e1fcb535cf6f7c325f4570259d9653aa5c163676c":"test_prepend.clsp(4):4-test_prepend.clsp(4):11","bfa3f9fa222b97f337eb69c35e17da4117f9d875d2c8b0a104d418326d71ca2a":"prepend.clinc(4):32","90d3695440786cce137dc24c6ddc72e899c4347b4f8efa26edefb001653f1439":"prepend.clinc(4):23-prepend.clinc(4):30","6a117e7a12837ecad43e5494eec3526f99489dbc040bc5b3434af888d997ee3a":"test_prepend.clsp(4):4-test_prepend.clsp(4):11","fba696389b83bed654427856423376a2c982ad649e04f982b7b7e05e8eb89070":"test_prepend.clsp(4):4-test_prepend.clsp(4):11","6e753b4ae3f1054677ac81c874e57f9a7ad961c6999e75705171094e2e1f1129":"test_prepend.clsp(4):4-test_prepend.clsp(4):11"} \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/map.clinc b/resources/tests/game-referee-in-cl23/map.clinc new file mode 100644 index 000000000..40a08a200 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/map.clinc @@ -0,0 +1,17 @@ +( + (defun map-with-rest (F L R) + (if L + (c (a F (list (f L))) (map-with-rest F (r L) R)) + R + ) + ) + + (defun list-len (X) (if X (+ 1 (list-len (r X))) 0)) + + (defmac map ARGS + (if (= (list-len ARGS) 3) + (qq (map-with-rest (unquote (f ARGS)) (unquote (f (r ARGS))) (unquote (f (r (r ARGS)))))) + (qq (map-with-rest (unquote (f ARGS)) (unquote (f (r ARGS))) ())) + ) + ) +) diff --git a/resources/tests/game-referee-in-cl23/match.clinc b/resources/tests/game-referee-in-cl23/match.clinc new file mode 100644 index 000000000..d66593c55 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/match.clinc @@ -0,0 +1,12 @@ + +( + (defun match (process remaining) + (if remaining + (if (a process (list (f remaining))) + (f remaining) + (match process (r remaining)) + ) + 0 + ) + ) +) diff --git a/resources/tests/game-referee-in-cl23/max.clinc b/resources/tests/game-referee-in-cl23/max.clinc new file mode 100644 index 000000000..5ec6d54f6 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/max.clinc @@ -0,0 +1,13 @@ +( + (defun max_inner (myless best_so_far mylist) + (if (not mylist) best_so_far + (if (a myless (list best_so_far (f mylist))) + (max_inner myless (f mylist) (r mylist)) + (max_inner myless best_so_far (r mylist)) + ) + ) + ) + (defun max (myless mylist) + (max_inner myless (f mylist) (r mylist)) + ) +) diff --git a/resources/tests/game-referee-in-cl23/noncegame.clsp b/resources/tests/game-referee-in-cl23/noncegame.clsp new file mode 100644 index 000000000..54e751e2a --- /dev/null +++ b/resources/tests/game-referee-in-cl23/noncegame.clsp @@ -0,0 +1,17 @@ +(mod (NONCE MODHASH mover_move new_validation mover_share (proof . conditions)) + +(include *standard-cl-23*) +(include assert.clinc) +(include curry-and-treehash.clinc) + +(defun check_new_validation (new_validation MODHASH NONCE) + (= new_validation (puzzle-hash-of-curried-function MODHASH (sha256 1 MODHASH) (shatree (+ NONCE 1)))) +) + +(assert + (check_new_validation new_validation MODHASH NONCE) + (= mover_move (* NONCE 2)) + (= mover_share 1) + (= proof (* NONCE 4)) + conditions) +) diff --git a/resources/tests/game-referee-in-cl23/onehandcalc.clinc b/resources/tests/game-referee-in-cl23/onehandcalc.clinc new file mode 100644 index 000000000..c939214d3 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/onehandcalc.clinc @@ -0,0 +1,147 @@ + +; ranks are 2-14 with 2 being two, 13 being king, and 14 being ace +; suits are 1-4 with no particular labelling +; takes a list of five cards (rank . suit) and returns the value of the best poker +; hand which can be made with them +; Hands are represented: +; straight flush (5 high_card) +; 4 of a kind (4 1 quad_rank kicker) +; full house (3 2 set_rank pair_rank) +; flush (3 1 3 high_card first_kicker second_kicker third_kicker fourth_kicker) +; straight (3 1 2 high_card) +; set (3 1 1 set_rank first_kicker second_kicker) +; two pair (2 2 1 high_pair_rank low_pair_rank kicker) +; pair (2 1 1 1 pair_rank first_kicker second_kicker third_kicker) +; high card (1 1 1 1 1 high_card first_kicker second_kicker third_kicker fourth_kicker) +( + (defun hand_compare (a b) + (if (= (f a) (f b)) + (if (r a) + (hand_compare (r a) (r b)) + 0 + ) + (- (* 2 (> (f a) (f b))) 1) + ) + ) + + (defun hand< (a b) + (= (hand_compare a b) -1) + ) + + (defun merge (a b) + (if (not a) + b + (if (not b) + a + (if (> (f a) (f b)) + (c (f a) (merge (r a) b)) + (c (f b) (merge a (r b))) + ) + ) + ) + ) + + ; Sorts atoms into descending order + ; This is optimized for sorting short lists + ; A more general function would return a list of lists of ascending sizes + ; to be merged + (defun atomsort ((@ firstpos (first @ secondpos (second @ thirdpos (third . remaining))))) + (if firstpos + (if secondpos + (if thirdpos + (assign-lambda + mylist + (if (> first second) + (if (> second third) + (list first second third) + (if (> first third) + (list first third second) + (list third first second) + ) + ) + (if (> first third) + (list second first third) + (if (> second third) + (list second third first) + (list third second first) + ) + ) + ) + (merge mylist (atomsort remaining)) + ) + (if (> first second) + firstpos + (list second first) + ) + ) + firstpos + ) + 0 + ) + ) + + (defun check_flush (@ cards ((rank1 . suit1) (rank2 . suit2) (rank3 . suit3) (rank4 . suit4) (rank5 . suit5))) + (logand (= suit1 suit2) (= suit1 suit3) (= suit1 suit4) (= suit1 suit5)) + ) + + ; returns the high card of a straight or 0 if there isn't any + (defun straight_high (@ all-args (count1 count2 count3 count4 count5 rank1 rank2 rank3 rank4 rank5)) + (if (not (= count1 1)) + 0 + (= rank5 (- rank1 4)) + rank1 + (= rank1 14) + (* (= rank2 5) 5) + 0 + ) + ) + + (defun flatten_card ((rank . suit)) + (logior (lsh rank 4) suit) + ) + + (defun unflatten_card (my_card) + (c (lsh my_card -4) (logand my_card 15)) + ) + + (defun group_by_count_inner (items last count) + (if (not items) + (list (flatten_card (c count last))) + (if (= (f items) last) + (group_by_count_inner (r items) last (+ count 1)) + (c (flatten_card (c count last)) (group_by_count_inner (r items) (f items) 1)) + ) + ) + ) + + (defun group_by_count (items) + (group_by_count_inner items (f items) 0) + ) + + (defun ranks_of_hand (count1 count2 count3 count4 count5 . ranks) + ranks + ) + + (defun onehandcalc ((@ cards ((card1rank . card1suit) (card2rank . card2suit) (card3rank . card3suit) + (card4rank . card4suit) (card5rank . card5suit)))) + (assign-lambda + ranks (atomsort (list card1rank card2rank card3rank card4rank card5rank)) + raw_groups (atomsort (group_by_count ranks)) + hand (map (lambda (x) (lsh x -4)) raw_groups (map (lambda (x) (logand x 15)) raw_groups)) + shigh (straight_high &rest hand) + (if shigh + (if (check_flush &rest cards) + (list 5 shigh) + (if (logior (= (f hand) 4) (logand (= (f hand) 3) (= (f (r hand)) 2))) + hand + (list 3 1 2 shigh) + ) + ) + (if (logand (check_flush &rest cards) (logior (< (f hand) 3) (logand (= (f hand) 3) (< (f (r hand)) 2)))) + (list 3 1 3 (ranks_of_hand &rest hand)) + hand + ) + ) + ) + ) +) diff --git a/resources/tests/game-referee-in-cl23/partition.clinc b/resources/tests/game-referee-in-cl23/partition.clinc new file mode 100644 index 000000000..8c8c268f6 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/partition.clinc @@ -0,0 +1,15 @@ +( + (defun partition_inner (matched not-matched F L) + (if L + (if (a F (list (f L))) + (partition_inner (c (f L) matched) not-matched F (r L)) + (partition_inner matched (c (f L) not-matched) F (r L)) + ) + (c matched not-matched) + ) + ) + + (defun partition (F L) + (partition_inner () () F L) + ) +) diff --git a/resources/tests/game-referee-in-cl23/permutations.clinc b/resources/tests/game-referee-in-cl23/permutations.clinc new file mode 100644 index 000000000..9664c6aff --- /dev/null +++ b/resources/tests/game-referee-in-cl23/permutations.clinc @@ -0,0 +1,21 @@ +( + (defun permutations_inner (pre post agg) + (if (not post) + agg + (assign + myatom (f post) + newrest (r post) + (map (lambda ((& myatom) x) (c myatom x)) + (permutations (prepend pre newrest)) + (permutations_inner (c myatom pre) newrest agg) + ) + ) + ) + ) + (defun permutations (vals) + (if vals + (permutations_inner 0 vals 0) + (q ()) + ) + ) +) diff --git a/resources/tests/game-referee-in-cl23/prefix.clinc b/resources/tests/game-referee-in-cl23/prefix.clinc new file mode 100644 index 000000000..0f7ee746a --- /dev/null +++ b/resources/tests/game-referee-in-cl23/prefix.clinc @@ -0,0 +1,15 @@ +( + (defun compile-list (args) + (if args + (if (r args) + ;; We have at least 2 things left... recurse once. + (qq (c (unquote (f args)) (unquote (compile-list (r args))))) + ;; This is the last item, so we return it whole (improper list form). + (qq (unquote (f args))) + ) + 0 + ) + ) + + (defmac prefix ARGS (compile-list ARGS)) +) diff --git a/resources/tests/game-referee-in-cl23/prepend.clinc b/resources/tests/game-referee-in-cl23/prepend.clinc new file mode 100644 index 000000000..2ea293409 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/prepend.clinc @@ -0,0 +1,8 @@ +( + (defun prepend (a b) + (if a + (c (f a) (prepend (r a) b)) + b + ) + ) +) \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/print.clinc b/resources/tests/game-referee-in-cl23/print.clinc new file mode 100644 index 000000000..95d459b36 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/print.clinc @@ -0,0 +1,3 @@ +( + (defun print (R P) (if (all "$print$" R P) P P)) +) diff --git a/resources/tests/game-referee-in-cl23/range.clinc b/resources/tests/game-referee-in-cl23/range.clinc new file mode 100644 index 000000000..dc1e61ca3 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/range.clinc @@ -0,0 +1,11 @@ +( + (defun range_inner (next final) + (if (= next final) + 0 + (c next (range_inner (+ next 1) final)) + ) + ) + (defun range (i) + (range_inner 0 i) + ) +) \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/reduce.clinc b/resources/tests/game-referee-in-cl23/reduce.clinc new file mode 100644 index 000000000..3251c79a7 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/reduce.clinc @@ -0,0 +1,10 @@ + +( + ; From here to the meat should be in a standard library + (defun reduce (fun lst init) + (if lst + (reduce fun (r lst) (a fun (list (f lst) init))) + init + ) + ) +) diff --git a/resources/tests/game-referee-in-cl23/referee.clsp b/resources/tests/game-referee-in-cl23/referee.clsp new file mode 100644 index 000000000..df7545e3b --- /dev/null +++ b/resources/tests/game-referee-in-cl23/referee.clsp @@ -0,0 +1,83 @@ + +; Adjudicates a two player turn based game +; MOVE, VALIDATION_HASH and MOVER_SHARE were all accepted optimistically from the last move +; Both VALIDATION_HASH values are a sha256 of a validation program hash and the shatree of a state +; The next validation program hash may be nil which means no futher moves are allowed +; MOVER_SHARE is how much the mover will get if they fold/accept +; MOD_HASH should be the shatree of referee itself +; NONCE is for anti-replay prevention +; If action is timeout args is nil +; If action is accuse args is (state validation_program mover_puzzle solution evidence) +; If action is move args is (new_move new_validation_info_hash new_mover_share mover_puzzle solution) +; validation programs get passed this: +; ((last_move next_validation_hash my_share me_hash my_puzzle_hash opponent_puzzle_hash +; amount timeout max_move_size referee_hash) +; state me mover_puzzle solution evidence) +(mod (@ all_args ((MOVE VALIDATION_INFO_HASH MOVER_SHARE PREVIOUS_VALIDATION_INFO_HASH + MOVER_PUZZLE_HASH WAITER_PUZZLE_HASH + @ constants (AMOUNT TIMEOUT MAX_MOVE_SIZE MOD_HASH NONCE)) . args)) + (include *standard-cl-23*) + ; This should be a bulk import from a standard library + (include assert.clinc) + (include curry.clinc) + (include match.clinc) + (include shatree.clinc) + (include prefix.clinc) + (include condition_codes.clinc) + + (defun <= (A B) (not (> A B))) + (defun >= (A B) (not (> B A))) + (defun concat (A B) + (if A + (c (f A) (concat (r A) B)) + B + ) + ) + + (if (not args) + ; timeout + (list + (list ASSERT_SECONDS_RELATIVE TIMEOUT) + (i MOVER_SHARE (list CREATE_COIN MOVER_PUZZLE_HASH MOVER_SHARE) (list 1)) + (i (- amount MOVER_SHARE) (list CREATE_COIN WAITER_PUZZLE_HASH (- amount MOVER_SHARE)) (list 1)) + ) + (l (f (r args))) + ; accuse + (assign + (previous_state previous_validation_program mover_puzzle solution) args + previous_validation_program_hash (shatree previous_validation_program) + (assert + (= MOVER_PUZZLE_HASH (shatree mover_puzzle)) + (= PREVIOUS_VALIDATION_INFO_HASH (sha256 previous_validation_program_hash (shatree + previous_state))) + ; usually returns the conditions verbatim + (concat (a previous_validation_program (c previous_validation_program_hash all_args)) + (a mover_puzzle solution)) + ) + ) + ; move + (assign + (new_move new_validation_info_hash new_mover_share mover_puzzle solution) args + new_puzzle_hash (curry_hashes MOD_HASH (shatree (list + new_move new_validation_info_hash new_mover_share + VALIDATION_INFO_HASH WAITER_PUZZLE_HASH MOVER_PUZZLE_HASH &rest constants))) + conditions (a mover_puzzle solution) + (assert + PREVIOUS_VALIDATION_INFO_HASH + (<= (strlen new_move) MAX_MOVE_SIZE) + (<= new_mover_share AMOUNT) + (>= new_mover_share 0) + (logior (not new_validation_info_hash) (= 32 (strlen new_validation_info_hash))) + (= MOVER_PUZZLE_HASH (shatree mover_puzzle)) + ; Check that the child output is made + (match + (lambda ((& new_puzzle_hash AMOUNT) (condname arg1 arg2)) + (logand (= condname CREATE_COIN) (= arg1 new_puzzle_hash) (= arg2 AMOUNT)) + ) + conditions + ) + conditions + ) + ) + ) +) diff --git a/resources/tests/game-referee-in-cl23/relops.clinc b/resources/tests/game-referee-in-cl23/relops.clinc new file mode 100644 index 000000000..ea5d52184 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/relops.clinc @@ -0,0 +1,5 @@ +( + (defun-inline >= (A B) (not (> B A))) + (defun-inline <= (A B) (not (> A B))) + (defun-inline < (A B) (>= B A)) +) diff --git a/resources/tests/game-referee-in-cl23/reverse.clinc b/resources/tests/game-referee-in-cl23/reverse.clinc new file mode 100644 index 000000000..389963ee9 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/reverse.clinc @@ -0,0 +1,11 @@ +( + (defun reverse_inner (reversed rest) + (if rest + (reverse_inner (c (f rest) reversed) (r rest)) + reversed + ) + ) + (defun reverse (vals) + (reverse_inner 0 vals) + ) +) diff --git a/resources/tests/game-referee-in-cl23/rockpaperscissorsa.clsp b/resources/tests/game-referee-in-cl23/rockpaperscissorsa.clsp new file mode 100644 index 000000000..a7d5113a9 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/rockpaperscissorsa.clsp @@ -0,0 +1,18 @@ +(mod (((alice_image new_validation_hash)) conditions) + (include *standard-cl-22*) + (include assert.clinc) + (include curry.clinc) + (include shatree.clinc) + (compile-file rockpaperscissorsb rockpaperscissorsb.clsp) + (defconst bhash (shatree rockpaperscissorsb)) + + (assert + (not + (all + (= new_validation_hash (sha256 bhash (shatree alice_image))) + (= (len alice_image) 32) + ) + ) + conditions + ) +) diff --git a/resources/tests/game-referee-in-cl23/rockpaperscissorsb.clsp b/resources/tests/game-referee-in-cl23/rockpaperscissorsb.clsp new file mode 100644 index 000000000..8c673c89c --- /dev/null +++ b/resources/tests/game-referee-in-cl23/rockpaperscissorsb.clsp @@ -0,0 +1,20 @@ + +(mod (((bob_move new_validation_hash) (ALICE_IMAGE)) conditions) + + (include *standard-cl-22*) + (include assert.clinc) + (include curry.clinc) + (include shatree.clinc) + (compile-file rockpaperscissorsc "rockpaperscissorsc.clsp") + (defconst chash (shatree rockpaperscissorsc)) + + (assert + (not + (all + (= new_validation (sha256 chash (shatree (list ALICE_IMAGE bob_move)))) + (= (len bob_move) 1) + ) + ) + conditions + ) +) diff --git a/resources/tests/game-referee-in-cl23/rockpaperscissorsc.clsp b/resources/tests/game-referee-in-cl23/rockpaperscissorsc.clsp new file mode 100644 index 000000000..91876cf67 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/rockpaperscissorsc.clsp @@ -0,0 +1,27 @@ +(mod (((alice_preimage new_validation_hash alice_share junk1 junk2 total) (ALICE_IMAGE BOB_MOVE)) conditions) + (include *standard-cl-22*) + (include assert.clinc) + (include curry.clinc) + + (assert + (not + (all + (not new_validation_hash) + (= ALICE_IMAGE (sha256 alice_preimage)) + (= alice_share + (assign + (junk3 result) (divmod (- alice_preimage BOB_MOVE) 3) + (if (not result) + (/ total 2) + (if (= result 2) + 0 + total + ) + ) + ) + ) + ) + ) + conditions + ) +) diff --git a/resources/tests/game-referee-in-cl23/shatree.clinc b/resources/tests/game-referee-in-cl23/shatree.clinc new file mode 100644 index 000000000..05bdb2699 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/shatree.clinc @@ -0,0 +1,11 @@ +( + ;; hash a tree + ;; This is used to calculate a puzzle hash given a puzzle program. + (defun shatree + (TREE) + (if (l TREE) + (sha256 2 (shatree (f TREE)) (shatree (r TREE))) + (sha256 1 TREE) + ) + ) +) \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/slice.clinc b/resources/tests/game-referee-in-cl23/slice.clinc new file mode 100644 index 000000000..2c98a09c5 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/slice.clinc @@ -0,0 +1,10 @@ + +( + ; returns the first count elements of mylist + (defun slice (mylist count) + (if (print (list "slice inputs" nylist count) (not count)) + 0 + (c (f mylist) (slice (r mylist) (- count 1))) + ) + ) +) diff --git a/resources/tests/game-referee-in-cl23/slice_runner.clsp b/resources/tests/game-referee-in-cl23/slice_runner.clsp new file mode 100644 index 000000000..3bbfebf7d --- /dev/null +++ b/resources/tests/game-referee-in-cl23/slice_runner.clsp @@ -0,0 +1,6 @@ +(mod (list n) + (include *standard-cl-23*) + (include slice.clinc) + + (slice list n) + ) diff --git a/resources/tests/game-referee-in-cl23/smoke_test_deep_compare.clsp b/resources/tests/game-referee-in-cl23/smoke_test_deep_compare.clsp new file mode 100644 index 000000000..1ce6dfd12 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/smoke_test_deep_compare.clsp @@ -0,0 +1,28 @@ +(mod () + (include *standard-cl-23*) + (include print.clinc) + (include prepend.clinc) + (include sort.clinc) + (include assert.clinc) + (include map.clinc) + (include deep_compare.clinc) + + (map + (lambda ((want_cmp_val cmp_a cmp_b)) + (= (deep_compare cmp_a cmp_b) want_cmp_val) + ) + (q + (0 0 0) + (-1 () (1 14 5 4 3 2)) + (1 (1 14 5 4 3 2) ()) + (-1 "X" (1 2)) + (1 (1 2) "X") + (0 (3 2) (3 2)) + (-1 (3 1) (3 3)) + (1 (3 3) (3 1)) + (-1 (1 1) (2 1)) + (1 (3 1) (2 2)) + (-1 (2 2) (3 1)) + ) + ) + ) diff --git a/resources/tests/game-referee-in-cl23/smoke_test_deep_compare.clvm.hex b/resources/tests/game-referee-in-cl23/smoke_test_deep_compare.clvm.hex new file mode 100644 index 000000000..cb3eb0bf7 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/smoke_test_deep_compare.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff08ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff0e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ffff01ffff80ff80ff8080ffff81ffff80ffff01ff0eff05ff04ff03ff028080ffff01ffff01ff0eff05ff04ff03ff0280ff8080ffff81ffff58ffff01ff028080ffff01ffff01ff0280ff5880ffff80ffff03ff0280ffff03ff028080ffff81ffffff03ff0180ffff03ff038080ffff01ffff03ff0380ffff03ff018080ffff81ffffff01ff0180ffff02ff018080ffff01ffff03ff0180ffff02ff028080ffff81ffffff02ff0280ffff03ff01808080ffff04ffff0180ff808080808080ffff04ffff01ffffff02ffff03ff0bffff01ff02ffff01ff04ffff02ff05ffff04ffff05ff0b80ffff01808080ffff02ff08ffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ff80808080808080ff0180ffff01ff02ffff0117ff018080ff0180ff02ffff03ffff07ff0580ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff02ff0affff04ff02ffff04ffff06ff0180ffff04ffff02ff0cffff04ff02ffff04ffff05ff0580ffff04ffff05ff0b80ff8080808080ff8080808080ff0180ffff01ff02ffff01ff0101ff018080ff0180ff0180ffff01ff02ffff01ff02ffff03ffff07ff0b80ffff01ff02ffff01ff0181ffff0180ffff01ff02ffff01ff02ffff03ffff15ff05ff0b80ffff01ff02ffff01ff0101ff0180ffff01ff02ffff01ff11ffff0180ffff15ff0bff058080ff018080ff0180ff018080ff0180ff018080ff0180ffff02ffff03ff0bffff01ff02ffff010bff0180ffff01ff02ffff01ff02ff0cffff04ff02ffff04ffff06ff0980ffff04ffff06ff1580ff8080808080ff018080ff0180ff09ffff02ff0cffff04ff02ffff04ff2bffff04ff5bff8080808080ff1380ff018080 diff --git a/resources/tests/game-referee-in-cl23/smoke_test_deep_compare.sym b/resources/tests/game-referee-in-cl23/smoke_test_deep_compare.sym new file mode 100644 index 000000000..51cab0f08 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/smoke_test_deep_compare.sym @@ -0,0 +1 @@ +{"026e28eecfeb07594300bd6c3bce34bd4fe340a189ddd5312c7361e242b52160_left_env": "1", "__chia__main_arguments": "()", "a08c534dd3a89e22a8fadaa027c6b9a8dd4f9a00b72c315821703d8ee1c8f687_arguments": "(a b)", "4fd7e0dfbd7ac5775e6d61670f548dc35ff62a1a4b14f2f3efe09d8b39e6988b_left_env": "1", "d9f6d93919b2fb79bc296ac80d73b5c48bf044e457f0f678b210f990efeea743_left_env": "1", "d9f6d93919b2fb79bc296ac80d73b5c48bf044e457f0f678b210f990efeea743_arguments": "((a_$_354 b_$_355) inner_result_$_356)", "source_file": "smoke_test_deep_compare.clsp", "d9f6d93919b2fb79bc296ac80d73b5c48bf044e457f0f678b210f990efeea743": "letbinding_$_373", "026e28eecfeb07594300bd6c3bce34bd4fe340a189ddd5312c7361e242b52160": "lambda_$_372", "4fd7e0dfbd7ac5775e6d61670f548dc35ff62a1a4b14f2f3efe09d8b39e6988b_arguments": "(F L R)", "a08c534dd3a89e22a8fadaa027c6b9a8dd4f9a00b72c315821703d8ee1c8f687_left_env": "1", "026e28eecfeb07594300bd6c3bce34bd4fe340a189ddd5312c7361e242b52160_arguments": "(() (want_cmp_val_$_369 cmp_a_$_370 cmp_b_$_371))", "4fd7e0dfbd7ac5775e6d61670f548dc35ff62a1a4b14f2f3efe09d8b39e6988b": "map-with-rest", "a08c534dd3a89e22a8fadaa027c6b9a8dd4f9a00b72c315821703d8ee1c8f687": "deep_compare"} \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/smoke_test_permutations.clsp b/resources/tests/game-referee-in-cl23/smoke_test_permutations.clsp new file mode 100644 index 000000000..cced719e1 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/smoke_test_permutations.clsp @@ -0,0 +1,9 @@ +(mod (X) + (include *standard-cl-23*) + (include map.clinc) + (include prepend.clinc) + (include print.clinc) + (include permutations.clinc) + + (permutations X) + ) diff --git a/resources/tests/game-referee-in-cl23/smoke_test_permutations.clvm.hex b/resources/tests/game-referee-in-cl23/smoke_test_permutations.clvm.hex new file mode 100644 index 000000000..2f159ecbb --- /dev/null +++ b/resources/tests/game-referee-in-cl23/smoke_test_permutations.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff1effff04ff02ffff04ff05ff80808080ffff04ffff01ffffff02ffff03ff0bffff01ff04ffff02ff05ffff04ff13ff808080ffff02ff08ffff04ff02ffff04ff05ffff04ff1bffff04ff17ff80808080808080ffff011780ff0180ff02ffff03ff05ffff01ff04ff09ffff02ff0cffff04ff02ffff04ff0dffff04ff0bff808080808080ffff010b80ff0180ffff02ffff03ff0bffff01ff02ff08ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff1680ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff13ff808080ffff04ffff0101ff80808080ff80808080ffff04ffff02ff1effff04ff02ffff04ffff02ff0cffff04ff02ffff04ff05ffff04ff1bff8080808080ff80808080ffff04ffff02ff0affff04ff02ffff04ffff04ff13ff0580ffff04ff1bffff04ff17ff808080808080ff808080808080ffff011780ff0180ffff04ff09ff0b80ff02ffff03ff05ffff01ff02ff0affff04ff02ffff04ff80ffff04ff05ffff04ff80ff808080808080ffff01ff01ff808080ff0180ff018080 diff --git a/resources/tests/game-referee-in-cl23/smoke_test_permutations.sym b/resources/tests/game-referee-in-cl23/smoke_test_permutations.sym new file mode 100644 index 000000000..f734f8249 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/smoke_test_permutations.sym @@ -0,0 +1 @@ +{"0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708": "lambda_$_247", "b97201305d0509980d3aa464611b7611b318739af0f2c4c459655f4e73510908_left_env": "1", "__chia__main_arguments": "(X)", "cad9d5be9f4271aab321579b5a3e8962ff95116798a47815da87f7e9ee9120c5": "map-with-rest", "28eb6a7a256c7907517678a492a10229cdcd605e4f14a9ef64a47291f879362e_left_env": "1", "source_file": "smoke_test_permutations.clsp", "cad9d5be9f4271aab321579b5a3e8962ff95116798a47815da87f7e9ee9120c5_arguments": "(F L R)", "817255a0bcf54eea9edf591ee53057239faf249b4ff7a970f0017eee3b89ed59_arguments": "(pre post agg)", "28eb6a7a256c7907517678a492a10229cdcd605e4f14a9ef64a47291f879362e_arguments": "(vals)", "b97201305d0509980d3aa464611b7611b318739af0f2c4c459655f4e73510908": "prepend", "cad9d5be9f4271aab321579b5a3e8962ff95116798a47815da87f7e9ee9120c5_left_env": "1", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708_arguments": "((myatom_$_242) x_$_244)", "817255a0bcf54eea9edf591ee53057239faf249b4ff7a970f0017eee3b89ed59": "permutations_inner", "b97201305d0509980d3aa464611b7611b318739af0f2c4c459655f4e73510908_arguments": "(a b)", "28eb6a7a256c7907517678a492a10229cdcd605e4f14a9ef64a47291f879362e": "permutations", "817255a0bcf54eea9edf591ee53057239faf249b4ff7a970f0017eee3b89ed59_left_env": "1", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708_left_env": "1"} \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/smoke_test_sort.clsp b/resources/tests/game-referee-in-cl23/smoke_test_sort.clsp new file mode 100644 index 000000000..ad5899da0 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/smoke_test_sort.clsp @@ -0,0 +1,11 @@ +(mod (X) + (include *standard-cl-23*) + (include prepend.clinc) + (include sort.clinc) + (include assert.clinc) + (include map.clinc) + (include reverse.clinc) + (include print.clinc) + + (sort (lambda (a b) (> b a)) X) + ) diff --git a/resources/tests/game-referee-in-cl23/smoke_test_sort.clvm.hex b/resources/tests/game-referee-in-cl23/smoke_test_sort.clvm.hex new file mode 100644 index 000000000..476b5f74e --- /dev/null +++ b/resources/tests/game-referee-in-cl23/smoke_test_sort.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff12ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff3e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff018080ffff04ffff0101ffff0180808080ffff0180808080ffff04ff05ff8080808080ffff04ffff01ffffffff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff10ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff02ffff03ff05ffff01ff02ffff01ff02ff18ffff04ff02ffff04ffff06ff0580ffff04ff17ffff04ffff04ffff05ff0580ff0b80ff808080808080ff0180ffff01ff02ffff01ff06ff0380ff018080ff0180ffff02ff18ffff04ff02ffff04ff05ffff01ff80ff8080808080ffff02ffff03ffff20ff0b80ffff01ff02ffff01ff02ff10ffff04ff02ffff04ffff02ff2effff04ff02ffff04ff2fff80808080ffff04ff17ff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff20ff1780ffff01ff02ffff01ff02ff10ffff04ff02ffff04ffff02ff2effff04ff02ffff04ff2fff80808080ffff04ff0bff8080808080ff0180ffff01ff02ffff01ff02ffff03ffff02ff05ffff04ffff05ff0b80ffff04ffff05ff1780ffff0180808080ffff01ff02ffff01ff02ff2cffff04ff02ffff04ff05ffff04ffff06ff0b80ffff04ff17ffff04ffff04ffff05ff0b80ff2f80ff80808080808080ff0180ffff01ff02ffff01ff02ff2cffff04ff02ffff04ff05ffff04ff0bffff04ffff06ff1780ffff04ffff04ffff05ff1780ff2f80ff80808080808080ff018080ff0180ff018080ff0180ff018080ff0180ff02ff2cffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff01ff80808080808080ffffff02ffff03ff0bffff01ff02ffff01ff02ffff03ffff06ff0b80ffff01ff02ffff01ff02ff2affff04ff02ffff04ffff06ff0180ffff04ffff02ff14ffff04ff02ffff04ff0bff80808080ff8080808080ff0180ffff01ff02ffff010bff018080ff0180ff0180ffff01ff02ffff01ff0180ff018080ff0180ffff02ff3affff04ff02ffff04ff03ffff04ffff02ff12ffff04ff02ffff04ff09ffff04ff13ff8080808080ffff04ffff02ff12ffff04ff02ffff04ff09ffff04ff2bff8080808080ff808080808080ff02ff3cffff04ff02ffff04ff11ffff04ff0bffff04ff17ff808080808080ffff02ffff03ff0bffff01ff02ffff01ff02ff16ffff04ff02ffff04ffff04ffff05ff0b80ff0580ffff04ffff06ff0b80ff8080808080ff0180ffff01ff02ffff0105ff018080ff0180ffff02ff16ffff04ff02ffff04ff80ffff04ff05ff8080808080ff15ff17ff0b80ff018080 diff --git a/resources/tests/game-referee-in-cl23/smoke_test_sort.sym b/resources/tests/game-referee-in-cl23/smoke_test_sort.sym new file mode 100644 index 000000000..a4c6667e3 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/smoke_test_sort.sym @@ -0,0 +1 @@ +{"b8edc250e5666a96397652bb34bdc9979fcd8df7f5aec90e481b7ae4234525aa_arguments": "(myless a b)", "107eecc0e2d1b059c660f3c81d6e61dd2fc7f71d4f446067132a09d395202140": "reverse", "b8edc250e5666a96397652bb34bdc9979fcd8df7f5aec90e481b7ae4234525aa": "merge", "842642e018168c91bd70ba0be54c311ce3947fe0ce5e418f6a1c88289e11c84b": "lambda_$_528", "fa9304ef33f250463c38ac3368ad79c5416173e5a666c6571e9b4c5d8b983da1_left_env": "1", "source_file": "smoke_test_sort.clsp", "6336806e19a49e9e91a62932f741d94eeca9a3656f35ecf39bc22e15d9940d53_arguments": "(mylist)", "95e75b36710d3038b1cfe847cc61158c78d91e4d6db6757217c8b32ac4ae13b3_left_env": "1", "fa9304ef33f250463c38ac3368ad79c5416173e5a666c6571e9b4c5d8b983da1_arguments": "(myless A B agg)", "f51796fc523809b04629ca42cffbb3514471eade8cd7d6908f3015f535a97de4_arguments": "((myless_$_506 mylist_$_507) (a_$_508 b_$_509))", "aa2a43f5d1d2ed44bd135ee807b27cb33eea736d2e50b2787c5fd4100f128f47_arguments": "(((myless_$_506 mylist_$_507) (a_$_508 b_$_509)) sa_$_510 sb_$_511)", "f51796fc523809b04629ca42cffbb3514471eade8cd7d6908f3015f535a97de4_left_env": "1", "95e75b36710d3038b1cfe847cc61158c78d91e4d6db6757217c8b32ac4ae13b3_arguments": "(@ everything (rest aggl aggr))", "fa9304ef33f250463c38ac3368ad79c5416173e5a666c6571e9b4c5d8b983da1": "merge_inner", "9d8df0b4587c62404485833b9a811fe717b4f9eb3ff4a11a7806e7fd07a1c5f8": "prepend", "95e75b36710d3038b1cfe847cc61158c78d91e4d6db6757217c8b32ac4ae13b3": "split_inner", "1b7d3888612a5d795887e5e192e68b15536e0e4c08e19324569a576ff06c6299_left_env": "1", "6336806e19a49e9e91a62932f741d94eeca9a3656f35ecf39bc22e15d9940d53": "split", "aa2a43f5d1d2ed44bd135ee807b27cb33eea736d2e50b2787c5fd4100f128f47_left_env": "1", "a3ddf8cdd53afc8bcdd3082f709b5f66156f31f8a56e603da27b4e382a68b9f3": "sort", "107eecc0e2d1b059c660f3c81d6e61dd2fc7f71d4f446067132a09d395202140_arguments": "(vals)", "b8edc250e5666a96397652bb34bdc9979fcd8df7f5aec90e481b7ae4234525aa_left_env": "1", "9d8df0b4587c62404485833b9a811fe717b4f9eb3ff4a11a7806e7fd07a1c5f8_left_env": "1", "a3ddf8cdd53afc8bcdd3082f709b5f66156f31f8a56e603da27b4e382a68b9f3_left_env": "1", "842642e018168c91bd70ba0be54c311ce3947fe0ce5e418f6a1c88289e11c84b_left_env": "1", "6336806e19a49e9e91a62932f741d94eeca9a3656f35ecf39bc22e15d9940d53_left_env": "1", "__chia__main_arguments": "(X)", "f51796fc523809b04629ca42cffbb3514471eade8cd7d6908f3015f535a97de4": "letbinding_$_529", "1b7d3888612a5d795887e5e192e68b15536e0e4c08e19324569a576ff06c6299": "reverse_inner", "9d8df0b4587c62404485833b9a811fe717b4f9eb3ff4a11a7806e7fd07a1c5f8_arguments": "(a b)", "1b7d3888612a5d795887e5e192e68b15536e0e4c08e19324569a576ff06c6299_arguments": "(reversed rest)", "a3ddf8cdd53afc8bcdd3082f709b5f66156f31f8a56e603da27b4e382a68b9f3_arguments": "(myless mylist)", "107eecc0e2d1b059c660f3c81d6e61dd2fc7f71d4f446067132a09d395202140_left_env": "1", "842642e018168c91bd70ba0be54c311ce3947fe0ce5e418f6a1c88289e11c84b_arguments": "(() a_$_526 b_$_527)", "aa2a43f5d1d2ed44bd135ee807b27cb33eea736d2e50b2787c5fd4100f128f47": "letbinding_$_530"} \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/sort.clinc b/resources/tests/game-referee-in-cl23/sort.clinc new file mode 100644 index 000000000..a9afed46a --- /dev/null +++ b/resources/tests/game-referee-in-cl23/sort.clinc @@ -0,0 +1,44 @@ + +( + (defun split_inner (@ everything (rest aggl aggr)) + (if rest + (split_inner (r rest) aggr (c (f rest) aggl)) + (r everything) + ) + ) + (defun split (mylist) + (split_inner mylist 0 0) + ) + (defun merge_inner (myless A B agg) + ; this should use continued if + (if (not A) + (prepend (reverse agg) B) + (if (not B) + (prepend (reverse agg) A) + (if (a myless (list (f A) (f B))) + (merge_inner myless (r A) B (c (f A) agg)) + (merge_inner myless A (r B) (c (f B) agg)) + ) + ) + ) + ) + (defun merge (myless a b) + (merge_inner myless a b 0) + ) + (defun sort-split (myless (a b)) + (merge myless (sort myless a) (sort myless b)) + ) + (defun sort (myless mylist) + (if mylist + (if (r mylist) + (assign (a b) (split mylist) + sa (sort myless a) + sb (sort myless b) + (merge myless sa sb) + ) + mylist + ) + () + ) + ) +) diff --git a/resources/tests/game-referee-in-cl23/space_poker.clinc b/resources/tests/game-referee-in-cl23/space_poker.clinc new file mode 100644 index 000000000..ee4d7647b --- /dev/null +++ b/resources/tests/game-referee-in-cl23/space_poker.clinc @@ -0,0 +1,214 @@ +( +(include spacehandcalc.clinc) +(include assert.clinc) + +(defconst END_HASH (shatree space_poker_end)) +(defconst CONTINUE_RIVER (curry space_poker_continue_street END_HASH)) +(defconst CONTINUE_RIVER_HASH (shatree CONTINUE_RIVER)) +(defconst START_RIVER (curry space_poker_start_street CONTINUE_RIVER_HASH)) +(defconst START_RIVER_HASH (shatree START_RIVER)) +(defconst CONTINUE_TURN (curry space_poker_continue_street START_RIVER_HASH)) +(defconst CONTINUE_TURN_HASH (shatree CONTINUE_TURN)) +(defconst START_TURN (curry space_poker_start_street CONTINUE_TURN_HASH)) +(defconst START_TURN_HASH (shatree START_TURN)) +(defconst CONTINUE_FLOP (curry space_poker_continue_street START_TURN_HASH)) +(defconst CONTINUE_FLOP_HASH (shatree CONTINUE_FLOP)) +(defconst START_FLOP (curry space_poker_start_street CONTINUE_FLOP_HASH)) +(defconst START_FLOP_HASH (shatree START_FLOP)) +(defconst CONTINUE_PREFLOP (curry space_poker_continue_street START_FLOP_HASH)) +(defconst CONTINUE_PREFLOP_HASH (shatree CONTINUE_PREFLOP)) +(defconst START_PREFLOP (curry space_poker_start_street CONTINUE_PREFLOP_HASH)) +(defconst START_PREFLOP_HASH (shatree START_PREFLOP)) +(defconst BHASH (shatree space_poker_b)) +(defconst AHASH (shatree space_poker_a)) + + +; Bob challenging +; state is minraise +; move is Alice image5 +; evidence is nil +; split should be Alice keeps an ante +(defun space_poker_a (mod_hash (move next_validation_hash mover_share previous_validation_hash + mover_puzzle_hash waiter_puzzle_hash amount timeout max_move_size referee_hash) + state me mover_puzzle solution evidence) + (assert + (not + (all + (= (strlen move) 32) + (= next_validation_hash (sha256 BHASH (shatree (list state move)))) + (= mover_share (- (/ amount 2) state)) + ) + ) + 0 + ) +) + +; Alice challenging +; state is minraise and Alice image5 +; move is Bob image4 +; evidence is nil +; split should be Bob keeps an ante +(defun space_poker_b (mod_hash (move next_validation_hash mover_share previous_validation_hash + mover_puzzle_hash waiter_puzzle_hash amount timeout max_move_size referee_hash) + (minraise alice_image5) me mover_puzzle solution evidence) + (assert + (not + (all + (= (strlen move) 32) + (= next_validation_hash (sha256 START_FLOP_HASH (shatree (list minraise (+ minraise minraise) + (- (/ amount 2) minraise) alice_image5 move)))) + (= mover_share (- (/ amount 2) state)) + ) + ) + 0 + ) +) + +; Elsa challlenging +; state is minraise, amount in pot, Anna's stack size, Anna's imageN, and Elsa's imageN-1 +; move is Anna's imageN-1 and raise amount (0 for check) +; split should be Anna keeps new amount in pot +(defun space_poker_start_street (NEXT_PROGRAM mod_hash (move next_validation_hash mover_share previous_validation_hash + mover_puzzle_hash waiter_puzzle_hash amount timeout max_move_size referee_hash) + (minraise pot_size anna_stack anna_imagen elsa_imagen-1) me mover_puzzle solution evidence) + (assign + anna_imagen-1 (substr move 0 32) + raise_amount (substr move 32 (strlen move)) + (assert + (not + (all + (= (sha256 anna_imagen-1) anna_imagen) + (>= raise_amount minraise) + (<= raise_amount anna_stack) + (= next_validation_hash (sha256 NEXT_PROGRAM (shatree (list minraise (+ pot_size raise_amount) + (- (- amount anna_stack) pot_size) elsa_imagen-1 anna_imagen-1)))) + (= mover_share (+ raise_amount (- amount anna_stack))) + ) + ) + 0 + ) + ) +) + +; Elsa challenging +; state is minraise, amount in pot, raise amount, Anna's stack size, Anna's imageN, and Elsa's imageN +; move is raise or Anna's imageN-1 +; split should be Anna keeps new amount in pot +(defun space_poker_continue_street (NEXT_PROGRAM mod_hash (move next_validation_hash mover_share previous_validation_hash + mover_puzzle_hash waiter_puzzle_hash amount timeout max_move_size referee_hash) + (minraise pot_size raise_amount anna_stack_size anna_imagen elsa_imagen) me mover_puzzle solution evidence) + (if (= (strlen move) 32) + (assert + (not + (all + (= (sha256 move) anna_imagen) + (= next_validation_hash (sha256 NEXT_PROGRAM (shatree (list minraise (+ pot_size raise_amount) + (- (- amount anna_stack_size) pot_size) elsa_imagen move)))) + (= mover_share (+ raise_amount (- amount anna_stack_size))) + ) + ) + 0 + ) + (assert + (not + (all + (<= minraise move) + (>= anna_stack_size move) + (= next_validation_hash (sha256 mod_hash (shatree (list minraise (+ pot_size raise_amount move) + (- (- amount anna_stack_size) pot_size) elsa_imagen anna_imagen)))) + ) + ) + 0 + ) + ) +) + +(defun extract_one_card (vala valb) + (+ 2 (% (sha256 (logxor vala valb)) 13)) +) + +(defun extract_hole_cards (vala valb pre) + (assign + v1 (% (sha256 (logxor vala valb) (* 13 13))) + (card1 . card2) (divmod v1 13) + (list (+ card1 2) (+ card2 2) &rest pre) + ) +) + +(defun extract_three_cards (vala valb) + (assign + v1 (% (sha256 (logxor vala valb) (* 13 13 13))) + (card1 . v2) (divmod v1 (* 13 13)) + (card2 . card3) (divmod v2 13) + (list (+ card1 2) (+ card2 2) (+ card3 2)) + ) +) + +(defun select_cards (card_list selections) + (assign + (pos1 . pos2) (divmod selections 7) + (assert + (> pos2 pos1) + (>= 0 pos1) + (select_cards_inner 0 (list pos1 pos2 100) card_list) + ) + ) +) + +(defun select_cards_inner (mypos poslist cards) + (if (not cards) + 0 + (if (= mypos (f poslist)) + (select_cards_inner (+ 1 mypos) (r poslist) (r cards)) + (c (f cards) (select_cards_inner (+ 1 mypos) poslist (r cards))) + ) + ) +) + +(defun amount_due (pot_size result) + (if (not result) + (/ pot_size 2) + (= result 1) + pot_size + 0 + ) +) + +; Elsa challenging +; state is minraise, amount in pot, Anna's stack size, Anna's image1 and Elsa's preimage +; move is Anna's preimage and card selection +; evidence is Elsa's card selection +; split should send pot to winner of the hand or even split if chop +(defun space_poker_end (mod_hash (move next_validation_hash mover_share previous_validation_hash + mover_puzzle_hash waiter_puzzle_hash amount timeout max_move_size referee_hash) + (minraise pot_size anna_stack_size anna_image1 elsa_preimage) me mover_puzzle solution evidence) + (assign + anna_preimage (substr move 0 32) + anna_card_selection (substr move 32 33) + elsa_image1 (sha256 elsa_preimage) + elsa_image2 (sha256 elsa_image1) + elsa_image3 (sha256 elsa_image2) + elsa_image4 (sha256 elsa_image3) + anna_image2 (sha256 anna_image1) + anna_image3 (sha256 anna_image2) + anna_image4 (sha256 anna_image3) + table_cards (list (extract_one_card anna_image2 elsa_image2) (extract_one_card anna_image1 elsa_image1) &rest + (extract_three_cards anna_image3 elsa_image3)) + anna_all_cards (extract_hole_cards anna_preimage elsa_image4 table_cards) + anna_hand (spacehandcalc (select_cards anna_all_cards anna_card_selection)) + elsa_all_cards (extract_hole_cards elsa_preimage anna_image4 table_cards) + elsa_hand (spacehandcalc (select_cards elsa_all_cards evidence)) + (assert + (not + (all + (= (sha256 anna_preimage anna_image1)) + (= next_validation_hash 0) + (>= mover_share (+ (- (- amount anna_stack_size) pot_size) + (amount_due pot_size (hand_compare elsa_hand anna_hand)))) + ) + ) + 0 + ) + ) +) +) diff --git a/resources/tests/game-referee-in-cl23/spacehandcalc.clinc b/resources/tests/game-referee-in-cl23/spacehandcalc.clinc new file mode 100644 index 000000000..9db553972 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/spacehandcalc.clinc @@ -0,0 +1,107 @@ + +; ranks are 1-13 with 1 being two, 12 being king, and 13 being ace +; there are no suits, flushes, or ace-to-four straights +; takes a list of card ranks and returns the value of the best poker +; hand which can be made with them +; returned list is hand type followed by cards in descending order +; all sorting is done highest to lowest +( + (include sort.clinc) + (include deep_compare.clinc) + (include filtermap.clinc) + (include slice.clinc) + (include max.clinc) + (defconstant FIVE_OF_A_KIND 8) + (defconstant FOUR_OF_A_KIND 7) + (defconstant FULL_HOUSE 6) + (defconstant STRAIGHT 5) + (defconstant THREE_OF_A_KIND 4) + (defconstant TWO_PAIR 3) + (defconstant PAIR 2) + (defconstant HIGH_CARD 1) + (defun straight_high_inner (ranks last count) + (if (not ranks) + ; at the end of the list + 0 + (if (= last (f ranks)) + ; skip identical cards + (straight_high_inner (r ranks) last count) + ; if the partial straight continues + (if (= (f ranks) (- last 1)) + (if (= count 4) + ; found a straight, add 3 to last because next and last are included + (+ last 3) + ; keep looking for a straight with the count going up by one + (straight_high_inner (r ranks) (f ranks) (+ count 1)) + ) + ; reset the count + (straight_high_inner (r ranks) (f ranks) 1) + ) + ) + ) + ) + ; returns the high card of a straight or 0 if there isn't any + ; ranks must be sorted in descending order + (defun straight_high (ranks) + (straight_high_inner (ranks (= (f ranks) 13) 0 0)) + ) + (defun group_by_count_inner (items last count) + (if (not items) + 0 + (if (= (f items) last) + (group_by_count_inner (r items) last (+ count 1)) + (assign val (group_by_count_inner (r items) (f items) 1) + (if last + (c (c count last) val) + val + ) + ) + ) + ) + ) + (defun group_by_count (items) + (group_by_count_inner items 0 0) + ) + (defun space_hand_calc_inner (cards) + (assign + rest (lambda (x) (r x)) + greater (lambda (x y) (> x y)) + ranks (sort greater cards) + sh (straight_high ranks) + max_straight (if sh + (list STRAIGHT sh) + 0 + ) + groups (sort deep> (group_by_count ranks)) + (top_count . top_card) (f groups) + (second_count . second_card) (f (r groups)) + topcards (map rest groups) + max_group (if (= top_count 1) + (c HIGH_CARD (slice topcards 5)) + (if (= top_count 2) + (if (= second_count 1) + (c PAIR (slice topcards 4)) + (c TWO_PAIR (slice topcards 3)) + ) + (if (= top_count 3) + (if (= second_count 1) + (c THREE_OF_A_KIND (slice topcards 3)) + (c FULL_HOUSE (slice topcards 2)) + ) + (if (= top_count 4) + (c FOUR_OF_A_KIND (slice topcards 2)) + (c FIVE_OF_A_KIND (slice topcards 1)) + ) + ) + ) + ) + (max deep< (list max_straight max_group)) + ) + ) + (defun space_hand_calc (cards boosted) + (assign + result (space_hand_calc_inner cards) + (list (f result) boosted (r result)) + ) + ) +) diff --git a/resources/tests/game-referee-in-cl23/spacepoker_include.clsp b/resources/tests/game-referee-in-cl23/spacepoker_include.clsp new file mode 100644 index 000000000..c0b5d9aa8 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/spacepoker_include.clsp @@ -0,0 +1 @@ +(mod () (include *standard-cl-23*) (include space_poker.clinc) ()) diff --git a/resources/tests/game-referee-in-cl23/steprun.py b/resources/tests/game-referee-in-cl23/steprun.py new file mode 100644 index 000000000..64a8d84cb --- /dev/null +++ b/resources/tests/game-referee-in-cl23/steprun.py @@ -0,0 +1,55 @@ +import os +from pathlib import Path +import binascii +import json +from clvm_tools.binutils import assemble, disassemble +from clvm_tools_rs import start_clvm_program, compose_run_function, compile_clvm +from clvm_rs import Program + +def compile_module_with_symbols(include_paths,source): + path_obj = Path(source) + file_path = path_obj.parent + file_stem = path_obj.stem + target_file = file_path / (file_stem + ".clvm.hex") + sym_file = file_path / (file_stem + ".sym") + compile_result = compile_clvm(source, str(target_file.absolute()), include_paths, True) + symbols = compile_result['symbols'] + if len(symbols) != 0: + with open(str(sym_file.absolute()),'w') as symfile: + symfile.write(json.dumps(symbols)) + +def run_until_end(p): + last = None + location = None + + while not p.is_ended(): + step_result = p.step() + if step_result is not None: + last = step_result + if 'Print' in last: + to_print = last['Print'] + if 'Print-Location' in last: + print(f"{last['Print-Location']}: print {to_print}") + else: + print(f"print {to_print}") + + return last + +def diag_run_clvm(program, args, symbols): + hex_form_of_program = binascii.hexlify(bytes(program)).decode('utf8') + hex_form_of_args = binascii.hexlify(bytes(args)).decode('utf8') + symbols = json.loads(open(symbols).read()) + p = start_clvm_program(hex_form_of_program, hex_form_of_args, symbols, None) + report = run_until_end(p) + if 'Failure' in report: + raise Exception(report) + else: + return assemble(report['Final']) + +if __name__ == '__main__': + # smoke test + import sys + program = Program.fromhex(open(sys.argv[1]).read()) + args = Program.fromhex(open(sys.argv[2]).read()) + diag_run_clvm(program, args) + diff --git a/resources/tests/game-referee-in-cl23/test_detectwrap.clsp b/resources/tests/game-referee-in-cl23/test_detectwrap.clsp new file mode 100644 index 000000000..f58a57fea --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_detectwrap.clsp @@ -0,0 +1,8 @@ +(mod (rank cards) + (include *standard-cl-23*) + (include relops.clinc) + (include print.clinc) + (include detectwrap.clinc) + + (get-straight-hand rank cards) +) diff --git a/resources/tests/game-referee-in-cl23/test_handbitmap.clsp b/resources/tests/game-referee-in-cl23/test_handbitmap.clsp new file mode 100644 index 000000000..f2603b31d --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_handbitmap.clsp @@ -0,0 +1,13 @@ +(mod () + + (include *standard-cl-23*) + (include print.clinc) + (include map.clinc) + (include deep_compare.clinc) + (include handbitmap.clinc) + + (ranks_from_hand + (list ((1 . 14) (1 . 13) (1 . 12) (1 . 11) (1 . 10) (1 . 8))) + (list (12 . 1) (11 . 1) (14 . 1) (13 . 1) (10 . 1) (8 . 1)) + ) + ) diff --git a/resources/tests/game-referee-in-cl23/test_handcalc.clsp b/resources/tests/game-referee-in-cl23/test_handcalc.clsp new file mode 100644 index 000000000..92f306907 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_handcalc.clsp @@ -0,0 +1,444 @@ + +(mod () + (include *standard-cl-23*) + (include relops.clinc) + (include deep_compare.clinc) + (include assert.clinc) + (include reverse.clinc) + (include prepend.clinc) + (include truncate.clinc) + (include map.clinc) + (include filtermap.clinc) + (include slice.clinc) + (include print.clinc) + (include partition.clinc) + (include append.clinc) + (include onehandcalc.clinc) + (include handcalc.clinc) + + (defun cards-by-bitmask (mask cards) + (if cards + (let ((next-cards (cards-by-bitmask (lsh mask -1) (r cards)))) + (if (logand 1 mask) + (c (f cards) next-cards) + next-cards + ) + ) + () + ) + ) + + (defun count-bits (mask) + (if mask + (let ((next (count-bits (lsh mask -1)))) + (if (logand mask 1) + (+ 1 next) + next + ) + ) + 0 + ) + ) + + (defun must-have-bits (N M) + (if (= (count-bits M) N) + M + (x "Mask" M "should have" N "bits") + ) + ) + + (defun must-be-len (N L) + (if (= (list-len L) N) + L + (x "List" L "should have" N "elements") + ) + ) + + (defun generate_handcalc_and_reverse_response (cards) + (assign + reversed-cards (reverse cards) + + handcalc-result (print (list "handcalc fwd result for cards" cards) (handcalc cards)) + + reverse-handcalc-result (print (list "handcalc rev result for cards" reversed-cards) (handcalc reversed-cards)) + + chosen-cards (cards-by-bitmask (must-have-bits 5 handcalc-result) cards) + + reverse-chosen-cards (cards-by-bitmask (must-have-bits 5 reverse-handcalc-result) reversed-cards) + + (c (must-be-len 5 chosen-cards) (must-be-len 5 reverse-chosen-cards)) + ) + ) + + (defun runtests_inner ((myfunc firstarg secondarg . remaining)) + (assign-lambda + (first-chosen-cards . first-rev-cards) (generate_handcalc_and_reverse_response firstarg) + + (second-chosen-cards . second-rev-cards) (generate_handcalc_and_reverse_response secondarg) + + first-ohc (print (list "first onehandcalc from " first-chosen-cards) (onehandcalc (must-be-len 5 first-chosen-cards))) + second-ohc (print (list "second onehandcalc from " second-chosen-cards) (onehandcalc (must-be-len 5 second-chosen-cards))) + + first-rev-ohc (print (list "first rev onehandcalc from " first-rev-cards) (onehandcalc (must-be-len 5 first-rev-cards))) + second-rev-ohc (print (list "second rev onehandcalc from " second-rev-cards) (onehandcalc (must-be-len 5 second-rev-cards))) + + (assert + (print (list "======== compare hands ========" first-ohc second-ohc) (a myfunc (list first-ohc second-ohc))) + (print (list "======== first equal ==========" first-ohc first-rev-ohc) (deep= first-ohc first-rev-ohc)) + (print (list "======== second equal =========" second-ohc second-rev-ohc) (deep= second-ohc second-rev-ohc)) + (if remaining + (runtests_inner remaining) + 0 + ) + ) + ) + ) + + (defun runtests tests (if tests (runtests_inner tests) ())) + + ;; Join these up when large application bug is fixed. + (runtests + ; all beats both emerge over and measure higher + ; straight flush with higher kicker ties + ; A1 K1 Q1 J1 T1 91 = A1 K1 Q1 J1 T1 81 + deep= + (list (c 12 1) (c 11 1) (c 14 1) (c 13 1) (c 10 1) (c 9 1)) + (list (c 12 1) (c 11 1) (c 14 1) (c 13 1) (c 10 1) (c 8 1)) + ; straight flushes of different suits tie + ; A1 K1 Q1 J1 T1 = A2 K2 Q2 J2 T2 + deep= + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 10 1)) + (list (c 14 2) (c 13 2) (c 12 2) (c 11 2) (c 10 2)) + ; higher straight flush beats lower straight flush + ; A1 K1 Q1 J1 T1 > 61 51 41 31 21 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 10 1)) + (list (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + ; A1 K1 Q1 J1 T1 91 = A1 K1 Q1 J1 T1 + deep= + (list (c 12 1) (c 11 1) (c 14 1) (c 13 1) (c 10 1) (c 9 1)) + (list (c 14 2) (c 11 2) (c 10 2) (c 13 2) (c 12 2)) + ; lower (2-6) straight flush beats ace to four straight flush + ; 61 51 41 31 21 > A2 52 42 32 22 + deep> + (list (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 14 2) (c 5 2) (c 4 2) (c 3 2) (c 2 2)) + ; A1 61 51 41 31 21 = 61 51 41 31 21 + deep= + (list (c 14 1) (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 6 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + ; ace to four straight flush with higher kicker ties + ; A2 52 42 32 22 61 = A1 51 41 31 21 71 + deep= + (list (c 14 2) (c 5 2) (c 4 2) (c 3 2) (c 2 2) (c 6 1)) + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1) (c 7 1)) + ; ace to four straight flushes of different suits tie + ; A1 51 41 31 21 = A2 52 42 32 22 + deep= + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 14 2) (c 5 2) (c 4 2) (c 3 2) (c 2 2)) + ; ace to four straight flush beats four of a kind + ; A1 51 41 31 21 > K1 K2 K3 K4 J1 + deep> + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 11 1)) + ; A1 A2 A3 A4 51 41 31 21 = A1 51 41 31 21 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + (list (c 14 1) (c 5 1) (c 4 1) (c 3 1) (c 2 1)) + ; four of a kind with higher kicker wins + ; K1 K2 K3 K4 Q1 > K1 K2 K3 K4 J1 + deep> + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 12 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 11 1)) + ; K1 K2 K3 K4 T1 91 = K1 K2 K3 K4 T1 + deep= + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 10 1) (c 9 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 10 1)) + ; four of a kind with higher second kicker ties + ; K1 K2 K3 K4 Q1 J1 = K1 K2 K3 K4 Q1 T1 + deep= + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 12 1) (c 11 1)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 12 1) (c 10 1)) + ; higher four of a kind beats lower four of a kind + ; K1 K2 K3 K4 21 > 31 32 33 34 A1 + deep> + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 2 1)) + (list (c 3 1) (c 3 2) (c 3 3) (c 3 4) (c 14 1)) + ; K1 K2 K3 K4 31 32 33 34 = K1 K2 K3 K4 32 + deep= + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 3 1) (c 3 2) (c 3 3) (c 3 4)) + (list (c 13 1) (c 13 2) (c 13 3) (c 13 4) (c 3 2)) + ; four of a kind beats full house + ; 21 22 23 24 31 > A1 A2 A3 K1 K2 + deep> + (list (c 2 1) (c 2 2) (c 2 3) (c 2 4) (c 3 1)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2)) + ; four of a kind equality: 21 22 23 24 A1 A2 A3 = 21 22 23 24 A2 + deep= + (list (c 2 1) (c 2 2) (c 2 3) (c 2 4) (c 14 1) (c 14 2) (c 14 3)) + (list (c 2 1) (c 2 2) (c 2 3) (c 2 4) (c 14 2)) + ; full house with higher set wins + ; 51 52 53 21 22 > 31 32 33 71 72 + deep> + (list (c 5 1) (c 5 2) (c 5 3) (c 2 1) (c 2 2)) + (list (c 3 1) (c 3 2) (c 3 3) (c 7 1) (c 7 2)) + ; A1 A2 A3 K1 K2 K3 = A1 A2 A3 K1 K2 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2) (c 13 3)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2)) + ; full house with same set and higher pair wins + ; 51 52 53 41 42 > 51 52 53 31 32 + deep> + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2)) + (list (c 5 1) (c 5 2) (c 5 3) (c 3 1) (c 3 2)) + ; A1 A2 A3 K1 K2 51 52 = A1 A2 A3 K1 K2 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2) (c 5 1) (c 5 2)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 13 2)) + ; full house ties with two sets + ; 51 52 53 41 42 A1 = 51 52 53 41 42 43 + deep= + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2) (c 14 1)) + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2) (c 4 3)) + ; full house beats flush + ; 51 52 53 41 42 > A1 Q1 T1 81 71 + deep> + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2)) + (list (c 14 1) (c 12 1) (c 10 1) (c 8 1) (c 7 1)) + ; 51 52 53 41 42 A1 K1 Q1 = 51 52 53 41 42 + deep= + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2) (c 14 1) (c 13 1) (c 12 1)) + (list (c 5 1) (c 5 2) (c 5 3) (c 4 1) (c 4 2)) + ; higher flush beats lower flush + ; A1 61 51 41 31 > K1 Q1 J1 T1 81 + deep> + (list (c 14 1) (c 6 1) (c 5 1) (c 4 1) (c 3 1)) + (list (c 13 1) (c 12 2) (c 11 1) (c 10 1) (c 8 1)) + ; A1 K1 Q1 J1 81 71 = A1 K1 Q1 J1 81 + deep= + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 8 1) (c 7 1)) + (list (c 14 1) (c 13 1) (c 12 1) (c 11 1) (c 8 1)) + ; flush with higher second card wins + ; A1 K1 51 41 31 > A1 Q1 J1 T1 91 + deep> + (list (c 14 1) (c 13 1) (c 5 1) (c 4 1) (c 3 1)) + (list (c 14 1) (c 12 2) (c 11 1) (c 10 1) (c 9 1)) + ; flush with higher third card wins + ; A1 K1 Q1 41 31 > A1 K1 J1 T1 91 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 4 1) (c 3 1)) + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 9 1)) + ; flush with higher fourth card wins + ; A1 K1 Q1 T1 21 > A1 K1 Q1 91 81 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 10 1) (c 2 1)) + (list (c 14 1) (c 13 1) (c 12 1) (c 9 1) (c 8 1)) + ; flush with higher fifth card wins + ; A1 K1 Q1 T1 81 > A1 K1 Q1 T1 71 + deep> + (list (c 14 1) (c 13 1) (c 12 1) (c 10 1) (c 8 1)) + (list (c 14 1) (c 13 1) (c 12 1) (c 10 1) (c 7 1)) + ; flushes of different suits tie + ; A1 K1 J1 T1 81 = A2 K2 J2 T2 82 + deep= + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 8 1)) + (list (c 14 2) (c 13 2) (c 11 2) (c 10 2) (c 8 2)) + ; same flush with higher sixth card ties + ; A1 K1 J1 T1 81 71 = A1 K1 J1 T1 81 61 + deep= + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 8 1) (c 7 1)) + (list (c 14 1) (c 13 1) (c 11 1) (c 10 1) (c 8 1) (c 6 1)) + ; flush beats straight + ; 71 61 51 41 21 > A1 K2 Q3 J4 T1 + deep> + (list (c 7 1) (c 6 1) (c 5 1) (c 4 1) (c 2 1)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1)) + ; A1 K2 Q3 J4 T1 81 71 61 = A1 T1 81 71 61 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 8 1) (c 7 1) (c 6 1)) + (list (c 14 1) (c 10 1) (c 8 1) (c 7 1) (c 6 1)) + ; straight with higher kicker ties + ; A1 K2 Q3 J4 T1 92 = A1 K2 Q3 J4 T1 22 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 9 2)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 2 2)) + ; straights of different suits tie + ; A1 K2 Q3 J4 T1 = A2 K3 Q4 J1 T2 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1)) + (list (c 14 2) (c 13 3) (c 12 4) (c 11 1) (c 10 2)) + ; higher straight beats lower straight + ; A1 K2 Q3 J4 T1 > 61 52 43 34 21 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1)) + (list (c 6 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + ; A1 K2 Q3 J4 T1 92 83 = A1 K2 Q3 J4 T1 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 10 1) (c 9 2) (c 8 3)) + (list (c 14 2) (c 13 3) (c 12 4) (c 11 1) (c 10 2)) + ; lower (2-6) straight beats ace to four straight + ; 61 52 43 34 21 > A1 52 43 34 21 + deep> + (list (c 6 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + ; A1 62 53 44 31 22 = 62 53 44 31 22 + deep= + (list (c 14 1) (c 6 2) (c 5 3) (c 4 4) (c 3 1) (c 2 2)) + (list (c 6 2) (c 5 3) (c 4 4) (c 3 1) (c 2 2)) + ; ace to four straight with higher kicker ties + ; A1 52 43 34 21 K2 = A1 52 43 34 21 72 + deep= + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1) (c 13 2)) + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1) (c 7 2)) + ; ace to fours of different suits tie + ; A1 52 43 34 21 = A2 53 44 31 22 + deep= + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 2) (c 5 3) (c 4 4) (c 3 1) (c 2 2)) + ; ace to four straight beats set + ; A1 52 43 34 21 > A1 A2 A3 K1 Q2 + deep> + (list (c 14 1) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 14 2) (c 14 3) (c 13 1) (c 12 2)) + ; A1 A2 A3 52 43 34 21 = A1 52 43 34 21 + deep= + (list (c 14 1) (c 14 2) (c 14 3) (c 5 2) (c 4 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 5 2) (c 4 3) (c 3 2) (c 2 1)) + ; higher set wins + ; 71 72 73 34 21 > 51 52 53 A4 K1 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 3 4) (c 2 1)) + (list (c 5 1) (c 5 2) (c 5 3) (c 14 4) (c 13 1)) + ; set with higher first kicker wins + ; 71 72 73 A1 22 > 71 72 73 K1 Q2 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 2 2)) + (list (c 7 1) (c 7 2) (c 7 3) (c 13 1) (c 12 2)) + ; 71 72 73 A1 K2 J3 54 43 = 71 72 73 A1 K2 + deep= + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2) (c 11 3) (c 5 4) (c 4 3)) + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2)) + ; set with higher second kicker wins + ; 71 72 73 A1 K2 > 71 72 73 A1 Q2 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2)) + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 12 2)) + ; set with higher third kicker ties + ; 71 72 73 A1 K2 Q3 = 71 72 73 A1 K2 J3 + deep= + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2) (c 12 3)) + (list (c 7 1) (c 7 2) (c 7 3) (c 14 1) (c 13 2) (c 11 3)) + ; set beats two pair + ; 71 72 73 34 21 > A1 A2 K3 K4 Q1 + deep> + (list (c 7 1) (c 7 2) (c 7 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 14 2) (c 13 3) (c 13 4) (c 12 1)) + ; two pair with higher high pair wins + ; K1 K2 33 34 21 > Q1 Q2 J3 J4 A1 + deep> + (list (c 13 1) (c 13 2) (c 3 3) (c 3 4) (c 2 1)) + (list (c 12 1) (c 12 2) (c 11 3) (c 11 4) (c 14 1)) + ; A1 A2 K1 K2 J1 J2 = A1 A2 K1 K2 J3 + deep= + (list (c 14 1) (c 14 2) (c 13 1) (c 13 2) (c 11 1) (c 11 2)) + (list (c 14 1) (c 14 2) (c 13 1) (c 13 2) (c 11 3)) + ; two pair with tied higher pair and higher lower pair wins + ; K1 K2 71 72 23 > K1 K2 63 64 A1 + deep> + (list (c 13 1) (c 13 2) (c 7 1) (c 7 2) (c 2 3)) + (list (c 13 1) (c 13 2) (c 6 3) (c 6 4) (c 14 1)) + ; two pair with higher kicker wins + ; K1 K2 Q3 Q4 J1 > K1 K2 Q3 Q4 T1 + deep> + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 11 1)) + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 10 1)) + ; K1 K2 Q3 Q4 A1 T1 92 63 = K1 K2 Q3 Q4 A1 + deep= + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 14 1) (c 10 1) (c 9 2) (c 6 3)) + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 14 1)) + ; two pair with higher second kicker ties + ; K1 K2 Q3 Q4 J1 T2 = K1 K2 Q3 Q4 J1 92 + deep= + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 11 1) (c 10 2)) + (list (c 13 1) (c 13 2) (c 12 3) (c 12 4) (c 11 1) (c 9 2)) + ; two pair beats pair + ; 41 42 33 34 21 > A1 A2 K3 Q4 J1 + deep> + (list (c 4 1) (c 4 2) (c 3 3) (c 3 4) (c 2 1)) + (list (c 14 1) (c 14 2) (c 13 3) (c 12 4) (c 11 1)) + ; higher pair wins + ; 71 72 53 44 31 > 61 62 A3 K4 Q1 + deep> + (list (c 7 1) (c 7 2) (c 5 3) (c 4 4) (c 3 1)) + (list (c 6 1) (c 6 2) (c 14 3) (c 13 4) (c 12 1)) + ; tied pair with higher first kicker wins + ; 91 92 A3 34 21 > 91 92 K3 Q4 J1 + deep> + (list (c 9 1) (c 9 2) (c 14 3) (c 3 4) (c 2 1)) + (list (c 9 1) (c 9 2) (c 13 3) (c 12 4) (c 11 1)) + ; 21 22 A1 Q2 J3 94 81 = 21 22 A1 Q2 J3 + deep= + (list (c 2 1) (c 2 2) (c 14 1) (c 12 2) (c 11 3) (c 9 4) (c 8 1)) + (list (c 2 1) (c 2 2) (c 14 1) (c 12 2) (c 11 3)) + ; tied pair with higher second kicker wins + ; 91 92 A3 K4 21 > 91 92 A3 Q4 J1 + deep> + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 2 1)) + (list (c 9 1) (c 9 2) (c 14 3) (c 12 4) (c 11 1)) + ; tied pair with higher third kicker wins + ; 91 92 A3 K4 Q1 > 91 92 A3 K4 J1 + deep> + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 12 1)) + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 11 1)) + ; tied pair with higher fourth kicker ties + ; 91 92 A3 K4 Q1 J2 = 91 92 A3 K4 Q1 T2 + deep= + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 12 1) (c 11 2)) + (list (c 9 1) (c 9 2) (c 14 3) (c 13 4) (c 12 1) (c 10 2)) + ; pair beats high card + ; 21 22 33 44 51 > A1 Q2 J3 T4 91 + deep> + (list (c 2 1) (c 2 2) (c 3 3) (c 4 4) (c 5 1)) + (list (c 14 1) (c 12 2) (c 11 3) (c 10 4) (c 9 1)) + ; higher high card wins + ; A1 22 33 44 61 > K1 Q2 J3 T4 81 + deep> + (list (c 14 1) (c 2 2) (c 3 3) (c 4 4) (c 6 1)) + (list (c 13 1) (c 12 2) (c 11 3) (c 10 4) (c 8 1)) + ; A1 K2 J3 T4 81 72 53 = A1 K2 J3 T4 81 + deep= + (list (c 14 1) (c 13 2) (c 11 3) (c 10 4) (c 8 1) (c 7 2) (c 5 3)) + (list (c 14 1) (c 13 2) (c 11 3) (c 10 4) (c 8 1)) + ; higher second card wins + ; A1 K2 23 34 41 > A1 Q2 J3 T4 91 + deep> + (list (c 14 1) (c 13 2) (c 2 3) (c 3 4) (c 4 1)) + (list (c 14 1) (c 12 2) (c 11 3) (c 10 4) (c 9 1)) + ; higher third card wins + ; A1 K2 Q3 24 41 > A1 K2 J3 T4 91 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 2 4) (c 4 1)) + (list (c 14 1) (c 13 2) (c 11 3) (c 10 4) (c 9 1)) + ; higher fourth card wins + ; A1 K2 Q3 J4 31 > A1 K2 Q3 T4 91 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 3 1)) + (list (c 14 1) (c 13 2) (c 12 3) (c 10 4) (c 9 1)) + ; higher fifth card wins + ; A1 K2 Q3 J4 91 > A1 K2 Q3 J4 81 + deep> + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 8 1)) + ; higher sixth card ties + ; A1 K2 Q3 J4 91 22 = A1 K2 Q3 J4 91 82 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1) (c 2 2)) + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1) (c 8 2)) + ; high cards of different suits ties + ; A1 K2 Q3 J4 91 = A2 K3 Q4 J1 92 + deep= + (list (c 14 1) (c 13 2) (c 12 3) (c 11 4) (c 9 1)) + (list (c 14 2) (c 13 3) (c 12 4) (c 11 1) (c 9 2)) + ) +) diff --git a/resources/tests/game-referee-in-cl23/test_library_basics.py b/resources/tests/game-referee-in-cl23/test_library_basics.py new file mode 100644 index 000000000..10327d01f --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_library_basics.py @@ -0,0 +1,132 @@ +import pytest +import random +from itertools import permutations +from clvm_rs import Program +from steprun import diag_run_clvm, compile_module_with_symbols + +Program.set_run_unsafe_max_cost(11000000000) + +compile_module_with_symbols(['.'], 'smoke_test_deep_compare.clsp') +compare_program = Program.from_bytes(bytes.fromhex(open('smoke_test_deep_compare.clvm.hex').read())) + +compile_module_with_symbols(['.'], 'smoke_test_sort.clsp') +sort_program = Program.from_bytes(bytes.fromhex(open('smoke_test_sort.clvm.hex').read())) + +compile_module_with_symbols(['.'], 'test_sort.clsp') +test_sort_program = Program.from_bytes(bytes.fromhex(open('test_sort.clvm.hex').read())) + +compile_module_with_symbols(['.'], 'test_permutations.clsp') +test_permutations_program = Program.from_bytes(bytes.fromhex(open('test_permutations.clvm.hex').read())) + +compile_module_with_symbols(['.'], 'test_reverse.clsp') +test_reverse_program = Program.from_bytes(bytes.fromhex(open('test_reverse.clvm.hex').read())) + +compile_module_with_symbols(['.'], 'test_prepend.clsp') +test_prepend_program = Program.from_bytes(bytes.fromhex(open('test_prepend.clvm.hex').read())) + +compile_module_with_symbols(['.'], 'test_range.clsp') +test_range_program = Program.from_bytes(bytes.fromhex(open('test_range.clvm.hex').read())) + +compile_module_with_symbols(['.'], 'smoke_test_permutations.clsp') +smoke_test_permutations_program = Program.from_bytes(bytes.fromhex(open('smoke_test_permutations.clvm.hex').read())) + +compile_module_with_symbols(['.'], 'test_handcalc.clsp') +test_handcalc_program = Program.from_bytes(bytes.fromhex(open('test_handcalc.clvm.hex').read())) + +def test_smoke_compare(): + compare_program.run(Program.to([])) + +def test_handcalc(): + diag_run_clvm(test_handcalc_program, Program.to([]), 'test_handcalc.sym') + +def proper_list_inner(result,cl): + if hasattr(cl, 'pair') and cl.pair is not None: + result.append(cl.pair[0]) + return proper_list_inner(result,cl.pair[1]) + else: + return result + +def proper_list(cl): + result = [] + return proper_list_inner(result,cl) + +def int_list(cl): + return [int(x) for x in Program.to(cl).as_iter()] + +def de_none_list(l): + return [x if x is not None else [] for x in l] + +def with_random_lists(n,f): + for length in range(n): # 0-10 length + for i in range(1 + (3 * length)): # A few orders each + orig_list = [random.randint(0,100) for x in range(length)] + f(orig_list) + +def test_prepend(): + for length1 in range(5): + list_1 = list(range(length1)) + for length2 in range(length1): + prepend_result = test_prepend_program.run([Program.to(list_1[:length2]),Program.to(list_1[length2:])]) + assert list_1 == int_list(prepend_result) + +def test_reverse(): + def test_reverse_list(l): + rev_args = Program.to([l]) + reversed_result = Program.to(list(reversed(l))) + reversed_by_prog = test_reverse_program.run(rev_args) + assert reversed_result == reversed_by_prog + + with_random_lists(10,test_reverse_list) + +def test_range(): + for length in range(10): + want_list = list(range(length)) + result = test_range_program.run(Program.to([length])) + assert want_list == result + +def do_test_permutations_of_size_n(n): + try_list = [random.randint(0,100) for x in range(n)] + want_set = list([list(v) for v in sorted(permutations(try_list))]) + listed_result = smoke_test_permutations_program.run(Program.to([try_list])) + pl = proper_list(listed_result) + perms_result = sorted([int_list(x) for x in de_none_list(pl)]) + assert want_set == perms_result + +def test_permutations_0(): + do_test_permutations_of_size_n(0) + +def test_permutations_1(): + do_test_permutations_of_size_n(1) + +def test_permutations_2(): + n = 2 + all_a_string = 0x616161616161 + all_b_string = 0x626262626262 + for try_list in [[all_a_string,all_b_string], [all_b_string,all_a_string]]: + want_set = list([list(v) for v in sorted(permutations(try_list))]) + listed_result = diag_run_clvm(smoke_test_permutations_program, Program.to([try_list]), 'smoke_test_permutations.sym') + pl = proper_list(listed_result) + perms_result = sorted([int_list(x) for x in de_none_list(pl)]) + assert want_set == perms_result + +def test_chialisp_sort_program(): + diag_run_clvm(test_sort_program, Program.to([]), 'test_sort.sym') + +def test_permutations_n(): + for i in range(3,6): + do_test_permutations_of_size_n(i) + +def test_chialisp_permutations_program(): + diag_run_clvm(test_permutations_program, Program.to([3, 5]), 'test_permutations.sym') + +def test_smoke_sort(): + for length in range(7): # 0-7 length + for i in range(1 + (3 * length)): # A few orders each + orig_list = [random.randint(0,100) for x in range(length)] + sort_args = Program.to([orig_list]) + sorted_list = Program.to(sorted(orig_list)) + sort_res = sort_program.run(sort_args) + assert sort_res == sorted_list + +if __name__ == '__main__': + test_smoke_sort() diff --git a/resources/tests/game-referee-in-cl23/test_onehandcalc.clsp b/resources/tests/game-referee-in-cl23/test_onehandcalc.clsp new file mode 100644 index 000000000..983360bb5 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_onehandcalc.clsp @@ -0,0 +1,37 @@ + +(mod () + (include *standard-cl-23*) + (include print.clinc) + (include assert.clinc) + (include deep_compare.clinc) + (include reverse.clinc) + (include prepend.clinc) + (include map.clinc) + (include range.clinc) + (include permutations.clinc) + (include last.clinc) + (include busy.clinc) + (include onehandcalc.clinc) + + (defun try_list (mylist newlist) + (assert (deep= (print 'result' (atomsort (print 'about to sort' newlist))) mylist) 0) + ) + + (defun try_permuted_list (mylist) + (busy (lambda ((& mylist) newlist) (try_list (reverse mylist) newlist)) + (permutations mylist) + 0 + ) + ) + (last + (try_list 0 0) + (try_list (reverse (range 15)) (range 15)) + (try_list (reverse (range 15)) (reverse (range 15))) + (try_permuted_list (list -1 -1 0 0 2)) + (busy (lambda (i) (try_permuted_list (range i))) + (range 4) + 0 + ) + 1 + ) +) diff --git a/resources/tests/game-referee-in-cl23/test_permutations.clsp b/resources/tests/game-referee-in-cl23/test_permutations.clsp new file mode 100644 index 000000000..59dd075ec --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_permutations.clsp @@ -0,0 +1,63 @@ +(mod (M N) + (include *standard-cl-23*) + (include prepend.clinc) + (include reverse.clinc) + (include map.clinc) + (include len.clinc) + (include range.clinc) + (include sort.clinc) + (include assert.clinc) + (include deep_compare.clinc) + (include permutations.clinc) + (include last.clinc) + (include busy.clinc) + (include all-in-list.clinc) + (include print.clinc) + + (defun ! (x) + (if x + (* x (! (- x 1))) + 1 + ) + ) + (defun no_repeats_inner ((first . remainder)) + (if remainder + (if (deep= first (f remainder)) + 0 + (no_repeats_inner remainder) + ) + 1 + ) + ) + (defun no_repeats (mylist) + (if mylist + (no_repeats_inner (sort (lambda (a b) (= (deep_compare a b) -1)) mylist)) + 1 + ) + ) + (assert + ;; Is permutations expected to collapse equal alternatives when two of + ;; the items to shuffle are equal? + (= (* (! M) 4) (len (permutations (c 0 (range M))))) + (busy + (lambda (listlen) + (assign + mylist (range listlen) + permed (permutations mylist) + (assert + (= (len permed) (! listlen)) + ;; ensure we didn't produce any permutations that have + ;; repeated elements in them, which would indicate that + ;; the permutation function misbehaved + (all-in-list (map (lambda (L) (no_repeats L)) permed)) + (no_repeats permed) + ) + ) + ) + (reverse (range N)) + 1 + ) + (deep= (permutations 0) (q ())) + 0 + ) +) diff --git a/resources/tests/game-referee-in-cl23/test_permutations.clvm.hex b/resources/tests/game-referee-in-cl23/test_permutations.clvm.hex new file mode 100644 index 000000000..4f0911964 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_permutations.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ffff03ffff09ffff12ffff02ff66ffff04ff02ffff04ff05ff80808080ffff010480ffff02ff48ffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff04ff80ffff02ff58ffff04ff02ffff04ff05ff8080808080ff80808080ff8080808080ffff01ff02ffff03ffff02ff8200baffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200fe80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ff8080ffff04ffff0101ff80808080ff80808080ffff04ffff02ff50ffff04ff02ffff04ffff02ff58ffff04ff02ffff04ff0bff80808080ff80808080ffff04ffff0101ff808080808080ffff01ff02ffff03ffff02ff62ffff04ff02ffff04ffff02ff4affff04ff02ffff04ff80ff80808080ffff04ffff01ff8080ff8080808080ffff01ff0180ffff01ff088080ff0180ffff01ff088080ff0180ffff01ff088080ff0180ffff04ffff01ffffffffffff02ffff03ff05ffff01ff04ff09ffff02ff40ffff04ff02ffff04ff0dffff04ff0bff808080808080ffff010b80ff0180ff02ffff03ff0bffff01ff02ff60ffff04ff02ffff04ffff04ff13ff0580ffff04ff1bff8080808080ffff010580ff0180ffff02ff60ffff04ff02ffff04ff80ffff04ff05ff8080808080ff02ffff03ff0bffff01ff04ffff02ff05ffff04ff13ff808080ffff02ff70ffff04ff02ffff04ff05ffff04ff1bffff04ff17ff80808080808080ffff011780ff0180ffffff02ffff03ff05ffff01ff10ffff0101ffff02ff48ffff04ff02ffff04ff0dff8080808080ffff01ff018080ff0180ff02ffff03ffff09ff05ff0b80ffff01ff0180ffff01ff04ff05ffff02ff68ffff04ff02ffff04ffff10ff05ffff010180ffff04ff0bff80808080808080ff0180ffff02ff68ffff04ff02ffff04ff80ffff04ff05ff8080808080ff02ffff03ff05ffff01ff02ff78ffff04ff02ffff04ff0dffff04ff17ffff04ffff04ff09ff0b80ff808080808080ffff010780ff0180ffffffff02ff78ffff04ff02ffff04ff05ffff04ff80ffff04ff80ff808080808080ff02ff54ffff04ff02ffff04ff03ffff04ffff02ff50ffff04ff02ffff04ff2fff80808080ff8080808080ffff02ffff03ff15ffff01ff02ffff03ff2dffff01ff02ffff03ffff02ff09ffff04ff25ffff04ff4dff80808080ffff01ff02ff64ffff04ff02ffff04ff09ffff04ff35ffff04ff2dffff04ffff04ff25ff5d80ff80808080808080ffff01ff02ff64ffff04ff02ffff04ff09ffff04ff15ffff04ff6dffff04ffff04ff4dff5d80ff8080808080808080ff0180ffff01ff02ff40ffff04ff02ffff04ff0bffff04ff15ff808080808080ff0180ffff01ff02ff40ffff04ff02ffff04ff0bffff04ff2dff808080808080ff0180ff02ff64ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff04ff80ff80808080808080ffffff02ffff03ff0bffff01ff02ffff03ff1bffff01ff02ff6cffff04ff02ffff04ff03ffff04ffff02ff44ffff04ff02ffff04ff0bff80808080ff8080808080ffff010b80ff0180ffff01ff018080ff0180ff02ff5cffff04ff02ffff04ff03ffff04ffff02ff4cffff04ff02ffff04ff09ffff04ff13ff8080808080ffff04ffff02ff4cffff04ff02ffff04ff09ffff04ff2bff8080808080ff808080808080ffff02ff74ffff04ff02ffff04ff11ffff04ff0bffff04ff17ff808080808080ffff02ff8200fcffff04ff02ffff04ff03ffff04ffff07ff0b80ff8080808080ff02ffff03ffff07ff0980ffff01ff02ffff03ff0bffff01ff02ff42ffff04ff02ffff04ff03ffff04ffff02ff8200bcffff04ff02ffff04ff11ffff04ff25ff8080808080ff8080808080ffff01ff010180ff0180ffff01ff02ffff03ff0bffff01ff0181ffffff01ff02ffff03ffff15ff09ff1580ffff01ff0101ffff01ff11ff80ffff15ff15ff09808080ff018080ff018080ff0180ffffffffff02ffff03ff0bffff010bffff01ff02ff8200bcffff04ff02ffff04ff31ffff04ff69ff808080808080ff0180ff09ffff02ff8200bcffff04ff02ffff04ff05ffff04ff0bff8080808080ff8080ffff02ffff03ff0bffff01ff02ff70ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff7280ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff13ff808080ffff04ffff0101ff80808080ff80808080ffff04ffff02ff4affff04ff02ffff04ffff02ff40ffff04ff02ffff04ff05ffff04ff1bff8080808080ff80808080ffff04ffff02ff52ffff04ff02ffff04ffff04ff13ff0580ffff04ff1bffff04ff17ff808080808080ff808080808080ffff011780ff0180ff04ff09ff0b80ffffff02ffff03ff05ffff01ff02ff52ffff04ff02ffff04ff80ffff04ff05ffff04ff80ff808080808080ffff01ff01ff808080ff0180ff02ffff03ff0dffff01ff02ff6affff04ff02ffff04ff0dff80808080ffff010980ff0180ff03ffff02ffff03ff0bffff01ff02ff6affff04ff02ffff04ffff02ff5affff04ff02ffff04ffff02ff05ffff04ff13ff808080ffff04ffff02ff8200baffff04ff02ffff04ff05ffff04ff1bffff04ff17ff808080808080ff8080808080ff80808080ffff011780ff0180ff02ffff03ff05ffff01ff04ffff04ffff0101ff0980ffff02ff8200faffff04ff02ffff04ff0dff8080808080ffff01ff018080ff0180ffffffff02ffff04ffff0122ffff02ff8200faffff04ff02ffff04ff05ff8080808080ff8080ff02ffff03ff05ffff01ff12ff05ffff02ff66ffff04ff02ffff04ffff11ff05ffff010180ff8080808080ffff01ff010180ff0180ffff02ffff03ff0dffff01ff02ffff03ffff02ff62ffff04ff02ffff04ff09ffff04ff15ff8080808080ffff01ff0180ffff01ff02ff56ffff04ff02ffff04ff0dff8080808080ff0180ffff01ff010180ff0180ff02ffff03ff05ffff01ff02ff56ffff04ff02ffff04ffff02ff4cffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff4e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ff8080ffff04ffff0101ff80808080ff80808080ffff04ff05ff8080808080ff80808080ffff01ff010180ff0180ffffff09ffff02ff8200bcffff04ff02ffff04ff0bffff04ff17ff8080808080ffff0181ff80ff02ff5effff04ff02ffff04ff03ffff04ffff02ff4affff04ff02ffff04ff0bff80808080ff8080808080ffff02ffff03ffff09ffff02ff48ffff04ff02ffff04ff0bff80808080ffff02ff66ffff04ff02ffff04ff29ff8080808080ffff01ff02ffff03ffff02ff46ffff04ff02ffff04ffff02ff70ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff8200be80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ff8080ffff04ffff0101ff80808080ff80808080ffff04ff0bffff04ff80ff808080808080ff80808080ffff01ff02ff76ffff04ff02ffff04ff0bff80808080ffff01ff088080ff0180ffff01ff088080ff0180ffff02ff76ffff04ff02ffff04ff0bff80808080ff02ff6effff04ff02ffff04ffff04ff80ffff04ff0bff808080ffff04ffff02ff58ffff04ff02ffff04ff0bff80808080ff8080808080ff018080 diff --git a/resources/tests/game-referee-in-cl23/test_permutations.sym b/resources/tests/game-referee-in-cl23/test_permutations.sym new file mode 100644 index 000000000..8f716298b --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_permutations.sym @@ -0,0 +1 @@ +{"977f394242d63d635c3262f77623308d3dbb75be33fb0579ce068ef9aa61b95f": "lambda_$_1250", "179091fe2a0662e64286145e0bc8d8edbeec24a21caf28941d843233d7a07c18_arguments": "(((() listlen_$_1235) mylist_$_1236) permed_$_1237)", "2c82355dea6595dde07e0d5e05aa96b89052c8b97d0e0c868356df4914f2fe68_left_env": "1", "2f8924a67ce29174ab591e1eea042ab8a92b179aefc79724031aa32c1adca2ec_arguments": "(myless a b)", "179091fe2a0662e64286145e0bc8d8edbeec24a21caf28941d843233d7a07c18": "letbinding_$_1251", "d6959a1fe31bf33707ba5c402e83c70c28523ce1ec1fdfb7f6d1615b8b19ac6f": "permutations", "2c82355dea6595dde07e0d5e05aa96b89052c8b97d0e0c868356df4914f2fe68_arguments": "(() L_$_1238)", "483fcccf52dd01c7be19ebb1f6ec50a0c235873236a8ab545236771af634b706_left_env": "1", "7b49cb4430f8db99c728f68f250ce64b8d924edf982d256b9f1aa54bcd247bd3": "reverse_inner", "e23db45dac9015daa0e667d0d846c354b2b9d9aaa3faedb560854d8662f2e238_arguments": "((() listlen_$_1235) mylist_$_1236)", "bac4134726e8744a62cfc2fb8062f615dcbe07e3368df66c28e4ff3f1530b9d5_arguments": "((myless_$_1179 mylist_$_1180) (a_$_1181 b_$_1182))", "d6959a1fe31bf33707ba5c402e83c70c28523ce1ec1fdfb7f6d1615b8b19ac6f_arguments": "(vals)", "8e1010766ed1255e57bcb63d1b8e999065d2295e17e12e8da3a3200dcfe72d85_left_env": "1", "8e1010766ed1255e57bcb63d1b8e999065d2295e17e12e8da3a3200dcfe72d85_arguments": "(L)", "c79b932e1e1da3c0e098e5ad2c422937eb904a76cf61d83975a74a68fbb04b99_left_env": "1", "__chia__main_arguments": "(M N)", "c79b932e1e1da3c0e098e5ad2c422937eb904a76cf61d83975a74a68fbb04b99_arguments": "myargs", "00472c7e852d86221bd799ec98883737a50be0769918af368f85ef82b587c6a5": "no_repeats_inner", "f8de27975a5aa0f0169626c8874de2ee78c9879c44424bfc1153bc150c6282fe": "range", "bac4134726e8744a62cfc2fb8062f615dcbe07e3368df66c28e4ff3f1530b9d5": "letbinding_$_1244", "8aaa8445e30d0613c3bc4e69dc922682ab0ddb0037b2b6f962c93b8d39fac6cb_left_env": "1", "f998ceba24fd5237d4759441cb8180302942d3ff3b0df1b16c6ec8a42f9e8feb": "len", "6a6dee0c702d9c433c1574c7f9aec2f9cb96a7058a6ce3c060096f36966dcaf3_left_env": "1", "00472c7e852d86221bd799ec98883737a50be0769918af368f85ef82b587c6a5_left_env": "1", "9242b5b6b2f9c8d952001db1fbcffc4b477638bf957f6a5dd3a2cc742919c977": "reverse", "5a2304733a44ef0eb65b98013f01b8159c093d28f78f60a6e4e9cbf88d24712a": "map-with-rest", "d2c4cc3b76e22dc7dbace4355f717ea1562ed7e230d9eb109ccebcce5a286762_arguments": "((myless_$_1169 A_$_1170 B_$_1171 agg_$_1172) cse_$_1239)", "bac4134726e8744a62cfc2fb8062f615dcbe07e3368df66c28e4ff3f1530b9d5_left_env": "1", "25fa0c2e23b21e6ed2046ea41e3e0a8b23aaeabab533811fa67e9bc88c13f8b3_left_env": "1", "8aaa8445e30d0613c3bc4e69dc922682ab0ddb0037b2b6f962c93b8d39fac6cb_arguments": "(a b)", "a0f33bb8f86cde256b4b17ff57166f666ac72d124a31b71e4cb9465ac6187cb8_arguments": "(((a_$_1188 b_$_1189) cse_$_1240) inner_result_$_1190)", "9d555f8fa61351176d9cc7653ec69c08e3cf8d7f77b9e62a55672837e11ef8dc": "all-in-list", "075c87dd46d215233cc305592019c4e38d1f9ee8136270fa8ec63bf3b21a7555_left_env": "1", "3c3345d295fe1bf6e242b2447ac80d7a5df6672ce1d81199c6716cb1a11d91e2_arguments": "(x)", "3c3345d295fe1bf6e242b2447ac80d7a5df6672ce1d81199c6716cb1a11d91e2": "!", "483fcccf52dd01c7be19ebb1f6ec50a0c235873236a8ab545236771af634b706": "lambda_$_1241", "2f8924a67ce29174ab591e1eea042ab8a92b179aefc79724031aa32c1adca2ec_left_env": "1", "42cc7c1c4d655f713c4c3a973f05cf00a2309aa1f881c43b39c18388ad566f6f_arguments": "((next . remainder))", "64da80039b055b3985693281fa3dce6ed49038f5b8bfa0a401890ed4cc06f5b7_arguments": "(a b)", "56fcbb61222cecf3d0508c8f7de453b57ed273192d17b9babbcf949ade228fe3_left_env": "1", "f0d9971063cb915d1a1574f69cf10876e1eadf56199d5a5f646eaa74418e15cb_arguments": "(next final)", "25fa0c2e23b21e6ed2046ea41e3e0a8b23aaeabab533811fa67e9bc88c13f8b3": "permutations_inner", "14f1b1d1c5f29961feaba6098b44d2d5aae15c65d14c98eace0e2bad57a3f16e": "prepend", "7b49cb4430f8db99c728f68f250ce64b8d924edf982d256b9f1aa54bcd247bd3_arguments": "(reversed rest)", "a0f33bb8f86cde256b4b17ff57166f666ac72d124a31b71e4cb9465ac6187cb8_left_env": "1", "2aa95e83d492fad7448cace5ef16276a5120b7d686eaf19dd8ce5528debd16ec_arguments": "(@ everything (rest aggl aggr))", "8e1010766ed1255e57bcb63d1b8e999065d2295e17e12e8da3a3200dcfe72d85": "enquote-rest", "486a24fa9d6684522f2acd9a163da3dc2b927502310181a7a01a62a38511b4f5": "no_repeats", "179091fe2a0662e64286145e0bc8d8edbeec24a21caf28941d843233d7a07c18_left_env": "1", "486a24fa9d6684522f2acd9a163da3dc2b927502310181a7a01a62a38511b4f5_left_env": "1", "42cc7c1c4d655f713c4c3a973f05cf00a2309aa1f881c43b39c18388ad566f6f": "last_inner", "075c87dd46d215233cc305592019c4e38d1f9ee8136270fa8ec63bf3b21a7555_arguments": "((a_$_1188 b_$_1189) cse_$_1240)", "8aaa8445e30d0613c3bc4e69dc922682ab0ddb0037b2b6f962c93b8d39fac6cb": "deep_compare", "56fcbb61222cecf3d0508c8f7de453b57ed273192d17b9babbcf949ade228fe3_arguments": "(((myless_$_1179 mylist_$_1180) (a_$_1181 b_$_1182)) sa_$_1183 sb_$_1184)", "c227759e0110fa53a26da3ce95683321df862de7f55472e9b85abe37bda150e9": "sort", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708_left_env": "1", "d2c4cc3b76e22dc7dbace4355f717ea1562ed7e230d9eb109ccebcce5a286762_left_env": "1", "5a2304733a44ef0eb65b98013f01b8159c093d28f78f60a6e4e9cbf88d24712a_left_env": "1", "14f1b1d1c5f29961feaba6098b44d2d5aae15c65d14c98eace0e2bad57a3f16e_arguments": "(a b)", "2aa95e83d492fad7448cace5ef16276a5120b7d686eaf19dd8ce5528debd16ec": "split_inner", "c227759e0110fa53a26da3ce95683321df862de7f55472e9b85abe37bda150e9_arguments": "(myless mylist)", "7b49cb4430f8db99c728f68f250ce64b8d924edf982d256b9f1aa54bcd247bd3_left_env": "1", "2f8924a67ce29174ab591e1eea042ab8a92b179aefc79724031aa32c1adca2ec": "merge", "9d555f8fa61351176d9cc7653ec69c08e3cf8d7f77b9e62a55672837e11ef8dc_left_env": "1", "2c82355dea6595dde07e0d5e05aa96b89052c8b97d0e0c868356df4914f2fe68": "lambda_$_1252", "64da80039b055b3985693281fa3dce6ed49038f5b8bfa0a401890ed4cc06f5b7_left_env": "1", "9242b5b6b2f9c8d952001db1fbcffc4b477638bf957f6a5dd3a2cc742919c977_left_env": "1", "9242b5b6b2f9c8d952001db1fbcffc4b477638bf957f6a5dd3a2cc742919c977_arguments": "(vals)", "14f1b1d1c5f29961feaba6098b44d2d5aae15c65d14c98eace0e2bad57a3f16e_left_env": "1", "42cc7c1c4d655f713c4c3a973f05cf00a2309aa1f881c43b39c18388ad566f6f_left_env": "1", "977f394242d63d635c3262f77623308d3dbb75be33fb0579ce068ef9aa61b95f_arguments": "(() a_$_1233 b_$_1234)", "3c3345d295fe1bf6e242b2447ac80d7a5df6672ce1d81199c6716cb1a11d91e2_left_env": "1", "e23db45dac9015daa0e667d0d846c354b2b9d9aaa3faedb560854d8662f2e238": "letbinding_$_1242", "483fcccf52dd01c7be19ebb1f6ec50a0c235873236a8ab545236771af634b706_arguments": "(() listlen_$_1235)", "c79b932e1e1da3c0e098e5ad2c422937eb904a76cf61d83975a74a68fbb04b99": "echo", "f8de27975a5aa0f0169626c8874de2ee78c9879c44424bfc1153bc150c6282fe_left_env": "1", "5fe09c9286896c58fb9645e68670c83c492cc65becc9ff451e4de65b1c3f7c98": "split", "c227759e0110fa53a26da3ce95683321df862de7f55472e9b85abe37bda150e9_left_env": "1", "22656977815b97840394f07b4339f2a131a5786afba08ff9ba669f7fc3eb2aa3": "merge_inner", "f0d9971063cb915d1a1574f69cf10876e1eadf56199d5a5f646eaa74418e15cb": "range_inner", "5fe09c9286896c58fb9645e68670c83c492cc65becc9ff451e4de65b1c3f7c98_left_env": "1", "977f394242d63d635c3262f77623308d3dbb75be33fb0579ce068ef9aa61b95f_left_env": "1", "source_file": "test_permutations.clsp", "2aa95e83d492fad7448cace5ef16276a5120b7d686eaf19dd8ce5528debd16ec_left_env": "1", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708": "lambda_$_1249", "f998ceba24fd5237d4759441cb8180302942d3ff3b0df1b16c6ec8a42f9e8feb_arguments": "(L)", "f8de27975a5aa0f0169626c8874de2ee78c9879c44424bfc1153bc150c6282fe_arguments": "(i)", "5fe09c9286896c58fb9645e68670c83c492cc65becc9ff451e4de65b1c3f7c98_arguments": "(mylist)", "6a6dee0c702d9c433c1574c7f9aec2f9cb96a7058a6ce3c060096f36966dcaf3_arguments": "(myfunc mylist returnval)", "e23db45dac9015daa0e667d0d846c354b2b9d9aaa3faedb560854d8662f2e238_left_env": "1", "f998ceba24fd5237d4759441cb8180302942d3ff3b0df1b16c6ec8a42f9e8feb_left_env": "1", "f0d9971063cb915d1a1574f69cf10876e1eadf56199d5a5f646eaa74418e15cb_left_env": "1", "a0f33bb8f86cde256b4b17ff57166f666ac72d124a31b71e4cb9465ac6187cb8": "letbinding_$_1247", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708_arguments": "((myatom_$_1206) x_$_1208)", "6a6dee0c702d9c433c1574c7f9aec2f9cb96a7058a6ce3c060096f36966dcaf3": "busy", "d2c4cc3b76e22dc7dbace4355f717ea1562ed7e230d9eb109ccebcce5a286762": "letbinding_$_1243", "56fcbb61222cecf3d0508c8f7de453b57ed273192d17b9babbcf949ade228fe3": "letbinding_$_1245", "9d555f8fa61351176d9cc7653ec69c08e3cf8d7f77b9e62a55672837e11ef8dc_arguments": "(L)", "00472c7e852d86221bd799ec98883737a50be0769918af368f85ef82b587c6a5_arguments": "((first . remainder))", "075c87dd46d215233cc305592019c4e38d1f9ee8136270fa8ec63bf3b21a7555": "letbinding_$_1246", "64da80039b055b3985693281fa3dce6ed49038f5b8bfa0a401890ed4cc06f5b7": "deep=", "5a2304733a44ef0eb65b98013f01b8159c093d28f78f60a6e4e9cbf88d24712a_arguments": "(F L R)", "25fa0c2e23b21e6ed2046ea41e3e0a8b23aaeabab533811fa67e9bc88c13f8b3_arguments": "(pre post agg)", "486a24fa9d6684522f2acd9a163da3dc2b927502310181a7a01a62a38511b4f5_arguments": "(mylist)", "22656977815b97840394f07b4339f2a131a5786afba08ff9ba669f7fc3eb2aa3_left_env": "1", "d6959a1fe31bf33707ba5c402e83c70c28523ce1ec1fdfb7f6d1615b8b19ac6f_left_env": "1", "22656977815b97840394f07b4339f2a131a5786afba08ff9ba669f7fc3eb2aa3_arguments": "(myless A B agg)"} \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/test_prepend.clsp b/resources/tests/game-referee-in-cl23/test_prepend.clsp new file mode 100644 index 000000000..41b7015dc --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_prepend.clsp @@ -0,0 +1,5 @@ +(mod (X Y) + (include *standard-cl-23*) + (include prepend.clinc) + (prepend X Y) + ) diff --git a/resources/tests/game-referee-in-cl23/test_prepend.clvm.hex b/resources/tests/game-referee-in-cl23/test_prepend.clvm.hex new file mode 100644 index 000000000..47dd7f1f1 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_prepend.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff02ffff04ff02ffff04ff05ffff04ff0bff8080808080ffff04ffff01ff02ffff03ff05ffff01ff02ffff01ff04ffff05ff0580ffff02ff02ffff04ff02ffff04ffff06ff0580ffff04ff0bff808080808080ff0180ffff01ff02ffff010bff018080ff0180ff018080 diff --git a/resources/tests/game-referee-in-cl23/test_prepend.sym b/resources/tests/game-referee-in-cl23/test_prepend.sym new file mode 100644 index 000000000..83feb47c9 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_prepend.sym @@ -0,0 +1 @@ +{"dfe61be8d5db02605605573b4d298395c7a871cc5390a79d535d07bbd2338987_left_env": "1", "dfe61be8d5db02605605573b4d298395c7a871cc5390a79d535d07bbd2338987": "prepend", "dfe61be8d5db02605605573b4d298395c7a871cc5390a79d535d07bbd2338987_arguments": "(a b)", "source_file": "test_prepend.clsp", "__chia__main_arguments": "(X Y)"} \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/test_range.clsp b/resources/tests/game-referee-in-cl23/test_range.clsp new file mode 100644 index 000000000..b299e3859 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_range.clsp @@ -0,0 +1,6 @@ +(mod (X) + (include *standard-cl-23*) + (include range.clinc) + + (range X) + ) diff --git a/resources/tests/game-referee-in-cl23/test_range.clvm.hex b/resources/tests/game-referee-in-cl23/test_range.clvm.hex new file mode 100644 index 000000000..628a68fe6 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_range.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff06ffff04ff02ffff04ff05ff80808080ffff04ffff01ffff02ffff03ffff09ff05ff0b80ffff01ff02ffff01ff0180ff0180ffff01ff02ffff01ff04ff05ffff02ff04ffff04ff02ffff04ffff10ff05ffff010180ffff04ff0bff808080808080ff018080ff0180ff02ff04ffff04ff02ffff04ff80ffff04ff05ff8080808080ff018080 diff --git a/resources/tests/game-referee-in-cl23/test_range.sym b/resources/tests/game-referee-in-cl23/test_range.sym new file mode 100644 index 000000000..ade866ede --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_range.sym @@ -0,0 +1 @@ +{"6ba774998680757c6e60d6d6e8a94176f76b74e5f8c6f2cf5d99fb134e916556_arguments": "(next final)", "0f035685b03df70de81cbdbd4e600f5d2f148f6c02b0e0a73ef96a26e7121f2a_left_env": "1", "6ba774998680757c6e60d6d6e8a94176f76b74e5f8c6f2cf5d99fb134e916556_left_env": "1", "0f035685b03df70de81cbdbd4e600f5d2f148f6c02b0e0a73ef96a26e7121f2a_arguments": "(i)", "__chia__main_arguments": "(X)", "6ba774998680757c6e60d6d6e8a94176f76b74e5f8c6f2cf5d99fb134e916556": "range_inner", "0f035685b03df70de81cbdbd4e600f5d2f148f6c02b0e0a73ef96a26e7121f2a": "range", "source_file": "test_range.clsp"} \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/test_reverse.clsp b/resources/tests/game-referee-in-cl23/test_reverse.clsp new file mode 100644 index 000000000..a7d1d937e --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_reverse.clsp @@ -0,0 +1,6 @@ +(mod (X) + (include *standard-cl-23*) + (include reverse.clinc) + + (reverse X) + ) diff --git a/resources/tests/game-referee-in-cl23/test_reverse.clvm.hex b/resources/tests/game-referee-in-cl23/test_reverse.clvm.hex new file mode 100644 index 000000000..492966787 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_reverse.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff06ffff04ff02ffff04ff05ff80808080ffff04ffff01ffff02ffff03ff0bffff01ff02ffff01ff02ff04ffff04ff02ffff04ffff04ffff05ff0b80ff0580ffff04ffff06ff0b80ff8080808080ff0180ffff01ff02ffff0105ff018080ff0180ff02ff04ffff04ff02ffff04ff80ffff04ff05ff8080808080ff018080 diff --git a/resources/tests/game-referee-in-cl23/test_reverse.sym b/resources/tests/game-referee-in-cl23/test_reverse.sym new file mode 100644 index 000000000..6a95fc6f8 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_reverse.sym @@ -0,0 +1 @@ +{"source_file": "test_reverse.clsp", "0f035685b03df70de81cbdbd4e600f5d2f148f6c02b0e0a73ef96a26e7121f2a_arguments": "(vals)", "0f035685b03df70de81cbdbd4e600f5d2f148f6c02b0e0a73ef96a26e7121f2a_left_env": "1", "893ed9a33d9ef594068ddc5aa4e669dce55ad0e7588062968c1d76ba4c830c01_left_env": "1", "893ed9a33d9ef594068ddc5aa4e669dce55ad0e7588062968c1d76ba4c830c01_arguments": "(reversed rest)", "0f035685b03df70de81cbdbd4e600f5d2f148f6c02b0e0a73ef96a26e7121f2a": "reverse", "__chia__main_arguments": "(X)", "893ed9a33d9ef594068ddc5aa4e669dce55ad0e7588062968c1d76ba4c830c01": "reverse_inner"} \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/test_slice.clsp b/resources/tests/game-referee-in-cl23/test_slice.clsp new file mode 100644 index 000000000..8ae7f9955 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_slice.clsp @@ -0,0 +1,14 @@ +(mod () + (include *standard-cl-23*) + (include print.clinc) + (include range.clinc) + (include deep_compare.clinc) + (include slice.clinc) + (include assert.clinc) + + (assert + (deep= (range 3) (slice (range 5) 3)) + (deep= (range 5) (slice (range 5) 5)) + 0 + ) + ) diff --git a/resources/tests/game-referee-in-cl23/test_sort.clsp b/resources/tests/game-referee-in-cl23/test_sort.clsp new file mode 100644 index 000000000..1d5a2b56b --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_sort.clsp @@ -0,0 +1,37 @@ + +(mod () + (include *standard-cl-23*) + (include print.clinc) + (include sort.clinc) + (include assert.clinc) + (include deep_compare.clinc) + (include reverse.clinc) + (include prepend.clinc) + (include map.clinc) + (include range.clinc) + (include permutations.clinc) + (include last.clinc) + (include busy.clinc) + + (defun try_list (mylist newlist) + (assert (deep= (print "sorted" (sort (lambda (A B) (deep< A B)) newlist)) mylist) 0) + ) + + (defun try_permuted_list (mylist) + (busy (lambda ((& mylist) newlist) (try_list mylist newlist)) + (print "sort all these" (permutations (print "mylist" mylist))) + 0 + ) + ) + (last + (try_list 0 0) + (try_list (range 15) (range 15)) + (try_list (range 15) (reverse (range 15))) + (try_permuted_list (list -1 -1 0 0 2)) + (busy (lambda (i) (try_permuted_list (print "sortme" (range i)))) + (range 4) + 0 + ) + 1 + ) +) diff --git a/resources/tests/game-referee-in-cl23/test_sort.clvm.hex b/resources/tests/game-referee-in-cl23/test_sort.clvm.hex new file mode 100644 index 000000000..c6e978298 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_sort.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff46ffff04ff02ffff04ffff02ff66ffff04ff02ffff04ffff02ff56ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff7e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ff8080ffff04ffff0101ff80808080ff80808080ffff04ffff02ff4affff04ff02ffff04ffff0104ff80808080ffff04ff80ff808080808080ffff04ffff02ff6effff04ff02ffff04ffff04ffff0181ffffff04ffff0181ffffff04ff80ffff04ff80ffff04ffff0102ff808080808080ff80808080ffff04ffff02ff76ffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff010fff80808080ffff04ffff02ff42ffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff010fff80808080ff80808080ff8080808080ffff04ffff02ff76ffff04ff02ffff04ffff02ff4affff04ff02ffff04ffff010fff80808080ffff04ffff02ff4affff04ff02ffff04ffff010fff80808080ff8080808080ffff04ffff02ff76ffff04ff02ffff04ff80ffff04ff80ff8080808080ffff04ffff0101ff808080808080808080ff80808080ffff04ffff01ffffffffff02ffff03ffff22ffff0187247072696e7424ff05ff0b80ffff010bffff010b80ff0180ffff02ffff03ff05ffff01ff02ff50ffff04ff02ffff04ff0dffff04ff17ffff04ffff04ff09ff0b80ff808080808080ffff010780ff0180ff02ff50ffff04ff02ffff04ff05ffff04ff80ffff04ff80ff808080808080ffffff02ff68ffff04ff02ffff04ff03ffff04ffff02ff42ffff04ff02ffff04ff2fff80808080ff8080808080ff02ffff03ff15ffff01ff02ffff03ff2dffff01ff02ffff03ffff02ff09ffff04ff25ffff04ff4dff80808080ffff01ff02ff48ffff04ff02ffff04ff09ffff04ff35ffff04ff2dffff04ffff04ff25ff5d80ff80808080808080ffff01ff02ff48ffff04ff02ffff04ff09ffff04ff15ffff04ff6dffff04ffff04ff4dff5d80ff8080808080808080ff0180ffff01ff02ff62ffff04ff02ffff04ff0bffff04ff15ff808080808080ff0180ffff01ff02ff62ffff04ff02ffff04ff0bffff04ff2dff808080808080ff0180ffff02ff48ffff04ff02ffff04ff05ffff04ff0bffff04ff17ffff04ff80ff80808080808080ff02ffff03ff0bffff01ff02ffff03ff1bffff01ff02ff44ffff04ff02ffff04ff03ffff04ffff02ff70ffff04ff02ffff04ff0bff80808080ff8080808080ffff010b80ff0180ffff01ff018080ff0180ffffffff02ff64ffff04ff02ffff04ff03ffff04ffff02ff78ffff04ff02ffff04ff09ffff04ff13ff8080808080ffff04ffff02ff78ffff04ff02ffff04ff09ffff04ff2bff8080808080ff808080808080ff02ff58ffff04ff02ffff04ff11ffff04ff0bffff04ff17ff808080808080ffff02ff74ffff04ff02ffff04ff03ffff04ffff07ff0b80ff8080808080ff02ffff03ffff07ff0980ffff01ff02ffff03ff0bffff01ff02ff4cffff04ff02ffff04ff03ffff04ffff02ff54ffff04ff02ffff04ff11ffff04ff25ff8080808080ff8080808080ffff01ff010180ff0180ffff01ff02ffff03ff0bffff01ff0181ffffff01ff02ffff03ffff15ff09ff1580ffff01ff0101ffff01ff11ff80ffff15ff15ff09808080ff018080ff018080ff0180ffffff02ffff03ff0bffff010bffff01ff02ff54ffff04ff02ffff04ff31ffff04ff69ff808080808080ff0180ff09ffff02ff54ffff04ff02ffff04ff05ffff04ff0bff8080808080ffff0181ff80ffff09ffff02ff54ffff04ff02ffff04ff05ffff04ff0bff8080808080ff8080ff02ffff03ff0bffff01ff02ff7cffff04ff02ffff04ffff04ff13ff0580ffff04ff1bff8080808080ffff010580ff0180ffffffffff02ff7cffff04ff02ffff04ff80ffff04ff05ff8080808080ff02ffff03ff05ffff01ff04ff09ffff02ff62ffff04ff02ffff04ff0dffff04ff0bff808080808080ffff010b80ff0180ffff02ffff03ff0bffff01ff04ffff02ff05ffff04ff13ff808080ffff02ff52ffff04ff02ffff04ff05ffff04ff1bffff04ff17ff80808080808080ffff011780ff0180ff02ffff03ffff09ff05ff0b80ffff01ff0180ffff01ff04ff05ffff02ff72ffff04ff02ffff04ffff10ff05ffff010180ffff04ff0bff80808080808080ff0180ffffff02ff72ffff04ff02ffff04ff80ffff04ff05ff8080808080ff02ffff03ff0bffff01ff02ff52ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff5a80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff13ff808080ffff04ffff0101ff80808080ff80808080ffff04ffff02ff7affff04ff02ffff04ffff02ff62ffff04ff02ffff04ff05ffff04ff1bff8080808080ff80808080ffff04ffff02ff6affff04ff02ffff04ffff04ff13ff0580ffff04ff1bffff04ff17ff808080808080ff808080808080ffff011780ff0180ffff04ff09ff0b80ff02ffff03ff05ffff01ff02ff6affff04ff02ffff04ff80ffff04ff05ffff04ff80ff808080808080ffff01ff01ff808080ff0180ffffffff02ffff03ff0dffff01ff02ff46ffff04ff02ffff04ff0dff80808080ffff010980ff018003ffff02ffff03ff0bffff01ff02ff46ffff04ff02ffff04ffff02ff66ffff04ff02ffff04ffff02ff05ffff04ff13ff808080ffff04ffff02ff56ffff04ff02ffff04ff05ffff04ff1bffff04ff17ff808080808080ff8080808080ff80808080ffff011780ff0180ff02ffff03ffff02ff5cffff04ff02ffff04ffff02ff20ffff04ff02ffff04ffff0186736f72746564ffff04ffff02ff78ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff4e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ff8080ffff04ffff0101ff80808080ff80808080ffff04ff0bff8080808080ff8080808080ffff04ff05ff8080808080ffff01ff0180ffff01ff088080ff0180ffffff02ff6cffff04ff02ffff04ff0bffff04ff17ff8080808080ff02ff56ffff04ff02ffff04ffff04ffff0102ffff04ffff04ffff0101ffff04ffff0102ffff04ffff04ffff0101ff5e80ffff04ffff04ffff0104ffff04ffff04ffff0101ff0280ffff04ffff0101ff80808080ff8080808080ffff04ffff04ffff0104ffff04ffff04ffff0101ffff04ff05ff808080ffff04ffff0101ff80808080ff80808080ffff04ffff02ff20ffff04ff02ffff04ffff018e736f727420616c6c207468657365ffff04ffff02ff7affff04ff02ffff04ffff02ff20ffff04ff02ffff04ffff01866d796c697374ffff04ff05ff8080808080ff80808080ff8080808080ffff04ff80ff808080808080ffff02ff76ffff04ff02ffff04ff09ffff04ff0bff8080808080ff02ff6effff04ff02ffff04ffff02ff20ffff04ff02ffff04ffff0186736f72746d65ffff04ffff02ff4affff04ff02ffff04ff0bff80808080ff8080808080ff80808080ff018080 diff --git a/resources/tests/game-referee-in-cl23/test_sort.sym b/resources/tests/game-referee-in-cl23/test_sort.sym new file mode 100644 index 000000000..b52d7115d --- /dev/null +++ b/resources/tests/game-referee-in-cl23/test_sort.sym @@ -0,0 +1 @@ +{"652f68e12a6e59641993f596a5644dcf31df81ef40f2c29b254eea5d8c2d4bff": "letbinding_$_1213", "35c2901e470b807d5438698d60919740a425372207406f8e8d1028a848066afb_arguments": "(a b)", "962986191da6874f39aeb123a2daa2d87bd1d8a68f612e83d33070a0315fa3d7_left_env": "1", "dd43ffb7ff900c9b5de80a6caac0388e157acab4c76bdea782158c5e3faebe41_arguments": "(((myless_$_1139 mylist_$_1140) (a_$_1141 b_$_1142)) sa_$_1143 sb_$_1144)", "caf316830203f2531b0730970f0a1ff842cfaa3737b26f671863ba72d4dbcb23_arguments": "(myless A B agg)", "de8e4d6b56fcbccff581079e2fa7840526dd1060d28465da2df907d5479f5fc1": "reverse", "99bd5cd8b43a9260701043b5036b40e8eb88bb2fa9a8a1fc7a1615e956289bf3_arguments": "(F L R)", "3abbdef2c09f5ef57e45e9fea76bc483517f5d61f41b5d446ca2cd52194ab8ad": "permutations_inner", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708_left_env": "1", "d43c5858f7535807c689e442e4dd9eb4e168e42bf5d5ec32f385816127ea7cb7_left_env": "1", "source_file": "test_sort.clsp", "f274125ba4dc62cee2127718e542397ddb82bedc2dbc7f7e6ab7e99520f1369c_arguments": "(vals)", "646c25660b2e23796637423fb0cc798fc0cceee4c2c1ab694b40b29829de1918_left_env": "1", "652f68e12a6e59641993f596a5644dcf31df81ef40f2c29b254eea5d8c2d4bff_arguments": "(((a_$_1148 b_$_1149) cse_$_1207) inner_result_$_1150)", "8764fc26d5f82f12e520c8c83a44fcccd198c69ecef8ade84d878558b28312b6": "busy", "8764fc26d5f82f12e520c8c83a44fcccd198c69ecef8ade84d878558b28312b6_left_env": "1", "35c2901e470b807d5438698d60919740a425372207406f8e8d1028a848066afb": "prepend", "d43c5858f7535807c689e442e4dd9eb4e168e42bf5d5ec32f385816127ea7cb7": "sort", "de8e4d6b56fcbccff581079e2fa7840526dd1060d28465da2df907d5479f5fc1_arguments": "(vals)", "99bd5cd8b43a9260701043b5036b40e8eb88bb2fa9a8a1fc7a1615e956289bf3": "map-with-rest", "ec1a55e5177b6c05f4ca7658e0af6ec0949696fc2f5fd4b761885c2f1c486fc4": "last_inner", "0a7b5127d99d3480228e93a4e31e810ca331d7d28f388077f7d45eb823a18136_left_env": "1", "df831d1086e338ee8a71c0b7588c3939989ec70e5695ada095735c81cfac99ac_left_env": "1", "caf316830203f2531b0730970f0a1ff842cfaa3737b26f671863ba72d4dbcb23_left_env": "1", "3e817bd05c10040769ecf76668026b4091c623b991a02e9155fe9e68334733e2": "split", "0a7b5127d99d3480228e93a4e31e810ca331d7d28f388077f7d45eb823a18136_arguments": "(@ everything (rest aggl aggr))", "6a477b54f8811bb3d5111ee9d39d29db7e3cca8f2521efd80f46dcfd9bc0573b": "range", "d43c5858f7535807c689e442e4dd9eb4e168e42bf5d5ec32f385816127ea7cb7_arguments": "(myless mylist)", "f274125ba4dc62cee2127718e542397ddb82bedc2dbc7f7e6ab7e99520f1369c": "permutations", "baab8a8560e19f7a28f84d94e788a555f3b46610a47b17aa8ead22b041adcac6_left_env": "1", "eb5a821dfc5b93a6ae858750615a61afb12efe943c2f2350b05f80a49ef8994d_arguments": "(mylist)", "962986191da6874f39aeb123a2daa2d87bd1d8a68f612e83d33070a0315fa3d7": "lambda_$_1208", "ec1a55e5177b6c05f4ca7658e0af6ec0949696fc2f5fd4b761885c2f1c486fc4_arguments": "((next . remainder))", "86359b12df84412bbc1390766400eb618a779245f5dd827c50cbbccc2465734a_left_env": "1", "919ca3a7eebc8bdea24332f40426a170497c22b208c40c57ad229034da3052a6": "letbinding_$_1209", "df831d1086e338ee8a71c0b7588c3939989ec70e5695ada095735c81cfac99ac": "range_inner", "a837d2a0d80ec387d14894d2418203e4f44bed2668f3aba64c0d68e394d9611c": "reverse_inner", "c79b932e1e1da3c0e098e5ad2c422937eb904a76cf61d83975a74a68fbb04b99": "echo", "b8b601fdb8fab0e12e98d10b1e8169d4209f502a901b4084e2f2c099065460e7_left_env": "1", "6b79b32d680005d302468e9d2c1592335cee3e4e0a454c9ede7653eb17b9c26d": "deep<", "df831d1086e338ee8a71c0b7588c3939989ec70e5695ada095735c81cfac99ac_arguments": "(next final)", "86359b12df84412bbc1390766400eb618a779245f5dd827c50cbbccc2465734a": "try_list", "0a7b5127d99d3480228e93a4e31e810ca331d7d28f388077f7d45eb823a18136": "split_inner", "919ca3a7eebc8bdea24332f40426a170497c22b208c40c57ad229034da3052a6_left_env": "1", "ecb54631c39aa0e71f97b09a6d7e983c1f6f47771562912c33be097f5f187676": "letbinding_$_1212", "6b79b32d680005d302468e9d2c1592335cee3e4e0a454c9ede7653eb17b9c26d_left_env": "1", "dd43ffb7ff900c9b5de80a6caac0388e157acab4c76bdea782158c5e3faebe41": "letbinding_$_1211", "caf316830203f2531b0730970f0a1ff842cfaa3737b26f671863ba72d4dbcb23": "merge_inner", "199ffa2cf4049218a5f783a13b6f6539ea4b18fa43ab34f75b72336de7605f9b_left_env": "1", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708": "lambda_$_1215", "c79b932e1e1da3c0e098e5ad2c422937eb904a76cf61d83975a74a68fbb04b99_left_env": "1", "8e2bde2bc32ee2c6313247a0e3b49389312ad884f40296f73dd6c0f7336f2c6d_arguments": "(R P)", "199ffa2cf4049218a5f783a13b6f6539ea4b18fa43ab34f75b72336de7605f9b": "deep_compare", "8e2bde2bc32ee2c6313247a0e3b49389312ad884f40296f73dd6c0f7336f2c6d": "print", "919ca3a7eebc8bdea24332f40426a170497c22b208c40c57ad229034da3052a6_arguments": "((myless_$_1129 A_$_1130 B_$_1131 agg_$_1132) cse_$_1206)", "8ce1ca2d9aa6fd583306772cd9e122af4be26dc842a6679a1bfa22d328b1f379_left_env": "1", "b8b601fdb8fab0e12e98d10b1e8169d4209f502a901b4084e2f2c099065460e7": "deep=", "ecb54631c39aa0e71f97b09a6d7e983c1f6f47771562912c33be097f5f187676_arguments": "((a_$_1148 b_$_1149) cse_$_1207)", "a837d2a0d80ec387d14894d2418203e4f44bed2668f3aba64c0d68e394d9611c_arguments": "(reversed rest)", "6a477b54f8811bb3d5111ee9d39d29db7e3cca8f2521efd80f46dcfd9bc0573b_arguments": "(i)", "3abbdef2c09f5ef57e45e9fea76bc483517f5d61f41b5d446ca2cd52194ab8ad_left_env": "1", "8764fc26d5f82f12e520c8c83a44fcccd198c69ecef8ade84d878558b28312b6_arguments": "(myfunc mylist returnval)", "c5bd34dcdeed87a6c78ea6b36052df8f96895a13a69b4179c15faf9f83ba4560_arguments": "((mylist_$_1203) newlist_$_1204)", "b8b601fdb8fab0e12e98d10b1e8169d4209f502a901b4084e2f2c099065460e7_arguments": "(a b)", "c79b932e1e1da3c0e098e5ad2c422937eb904a76cf61d83975a74a68fbb04b99_arguments": "myargs", "99bd5cd8b43a9260701043b5036b40e8eb88bb2fa9a8a1fc7a1615e956289bf3_left_env": "1", "c5bd34dcdeed87a6c78ea6b36052df8f96895a13a69b4179c15faf9f83ba4560": "lambda_$_1217", "c5bd34dcdeed87a6c78ea6b36052df8f96895a13a69b4179c15faf9f83ba4560_left_env": "1", "__chia__main_arguments": "()", "f274125ba4dc62cee2127718e542397ddb82bedc2dbc7f7e6ab7e99520f1369c_left_env": "1", "962986191da6874f39aeb123a2daa2d87bd1d8a68f612e83d33070a0315fa3d7_arguments": "(() i_$_1205)", "646c25660b2e23796637423fb0cc798fc0cceee4c2c1ab694b40b29829de1918_arguments": "((myless_$_1139 mylist_$_1140) (a_$_1141 b_$_1142))", "6a477b54f8811bb3d5111ee9d39d29db7e3cca8f2521efd80f46dcfd9bc0573b_left_env": "1", "8ce1ca2d9aa6fd583306772cd9e122af4be26dc842a6679a1bfa22d328b1f379_arguments": "(myless a b)", "646c25660b2e23796637423fb0cc798fc0cceee4c2c1ab694b40b29829de1918": "letbinding_$_1210", "baab8a8560e19f7a28f84d94e788a555f3b46610a47b17aa8ead22b041adcac6_arguments": "(() A_$_1201 B_$_1202)", "eb5a821dfc5b93a6ae858750615a61afb12efe943c2f2350b05f80a49ef8994d_left_env": "1", "0912f05321a428d040bc76941cf4f8f7c74f28662f48098303e30cf1a6a43708_arguments": "((myatom_$_1180) x_$_1182)", "199ffa2cf4049218a5f783a13b6f6539ea4b18fa43ab34f75b72336de7605f9b_arguments": "(a b)", "3e817bd05c10040769ecf76668026b4091c623b991a02e9155fe9e68334733e2_arguments": "(mylist)", "ec1a55e5177b6c05f4ca7658e0af6ec0949696fc2f5fd4b761885c2f1c486fc4_left_env": "1", "3e817bd05c10040769ecf76668026b4091c623b991a02e9155fe9e68334733e2_left_env": "1", "35c2901e470b807d5438698d60919740a425372207406f8e8d1028a848066afb_left_env": "1", "8ce1ca2d9aa6fd583306772cd9e122af4be26dc842a6679a1bfa22d328b1f379": "merge", "652f68e12a6e59641993f596a5644dcf31df81ef40f2c29b254eea5d8c2d4bff_left_env": "1", "8e2bde2bc32ee2c6313247a0e3b49389312ad884f40296f73dd6c0f7336f2c6d_left_env": "1", "baab8a8560e19f7a28f84d94e788a555f3b46610a47b17aa8ead22b041adcac6": "lambda_$_1216", "dd43ffb7ff900c9b5de80a6caac0388e157acab4c76bdea782158c5e3faebe41_left_env": "1", "86359b12df84412bbc1390766400eb618a779245f5dd827c50cbbccc2465734a_arguments": "(mylist newlist)", "ecb54631c39aa0e71f97b09a6d7e983c1f6f47771562912c33be097f5f187676_left_env": "1", "de8e4d6b56fcbccff581079e2fa7840526dd1060d28465da2df907d5479f5fc1_left_env": "1", "3abbdef2c09f5ef57e45e9fea76bc483517f5d61f41b5d446ca2cd52194ab8ad_arguments": "(pre post agg)", "6b79b32d680005d302468e9d2c1592335cee3e4e0a454c9ede7653eb17b9c26d_arguments": "(a b)", "eb5a821dfc5b93a6ae858750615a61afb12efe943c2f2350b05f80a49ef8994d": "try_permuted_list", "a837d2a0d80ec387d14894d2418203e4f44bed2668f3aba64c0d68e394d9611c_left_env": "1"} \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/testnoncegame.py b/resources/tests/game-referee-in-cl23/testnoncegame.py new file mode 100644 index 000000000..523f01fab --- /dev/null +++ b/resources/tests/game-referee-in-cl23/testnoncegame.py @@ -0,0 +1,33 @@ +import hashlib + +from clvm_rs import Program + +from clvm.EvalError import EvalError + +noncegame = Program.from_bytes(bytes.fromhex(open("noncegame.clvm.hex").read())) +noncehash = noncegame.tree_hash() + +def drun(prog: Program, args: Program): + try: + return prog.run(args) + except EvalError as ee: + print(f"brun -x -y main.sym {prog} {Program.to(args)}") + raise + +def testnonce(startnonce, maxnonce): + for i in range(startnonce, maxnonce): + mygame = noncegame.curry(i, noncehash) + good_parameters = [i*2, noncegame.curry(i+1, noncehash).tree_hash(), 1, (i*4, b'g')] + bad_parameters = [i*3, noncegame.curry(i+2, noncehash).tree_hash(), 2, (i*5, b'g')] + assert drun(mygame, good_parameters) == b'g' + for j in range(len(good_parameters)): + try: + p = list(good_parameters) + p[j] = bad_parameters[j] + mygame.run(p) + assert False + except EvalError as ee: + pass + +if __name__ == '__main__': + testnonce(3, 7) diff --git a/resources/tests/game-referee-in-cl23/testreferee.py b/resources/tests/game-referee-in-cl23/testreferee.py new file mode 100644 index 000000000..a63769b35 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/testreferee.py @@ -0,0 +1,479 @@ +import pytest +from hashlib import sha256 +from contextlib import asynccontextmanager +from chia.clvm.spend_sim import SimClient, SpendSim +from pathlib import Path +from clvm.casts import int_to_bytes, int_from_bytes + +from clvm_rs import Program +from clvm_tools_rs import compile_clvm +from clvm_tools.binutils import disassemble + +from clvm.EvalError import EvalError +from chia.types.mempool_inclusion_status import MempoolInclusionStatus +from chia.util.errors import Err +from dataclasses import dataclass +from typing import Any +from chia_rs import Coin +from chia.types.spend_bundle import SpendBundle +from chia.types.coin_spend import CoinSpend +from blspy import G2Element + +from steprun import diag_run_clvm, compile_module_with_symbols + +compile_module_with_symbols(['.'],'referee.clsp') +referee = Program.from_bytes(bytes.fromhex(open("referee.clvm.hex").read())) +refhash = referee.tree_hash() +compile_module_with_symbols(['.'],'referee_accuse.clsp') +referee_accuse = Program.from_bytes(bytes.fromhex(open("referee_accuse.clvm.hex").read())) +refaccusehash = referee.tree_hash() +compile_clvm('rockpaperscissorsa.clsp', 'rockpaperscissorsa.clvm.hex', ['.']) +MOD_A = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsa.clvm.hex").read())) +compile_clvm('rockpaperscissorsb.clsp', 'rockpaperscissorsb.clvm.hex', ['.']) +MOD_B = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsb.clvm.hex").read())) +compile_clvm('rockpaperscissorsc.clsp', 'rockpaperscissorsc.clvm.hex', ['.']) +MOD_C = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsc.clvm.hex").read())) +compile_clvm('rockpaperscissorsd.clsp', 'rockpaperscissorsd.clvm.hex', ['.']) +MOD_D = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsd.clvm.hex").read())) + +move = 0 +accuse = 1 +timeout = 2 + +def drun(prog: Program, *args: Program): + try: + return prog.run(*args) + except EvalError as ee: + print(f"brun -x -y main.sym {prog} {Program.to(list(args))}") + raise + +def sha(blob:bytes) -> bytes: + return sha256(blob).digest() + +@pytest.fixture(scope="function") +@asynccontextmanager +async def setup_sim() : + sim = await SpendSim.create(db_path=Path("file:db_test?mode=memory&cache=shared")) + sim_client = SimClient(sim) + await sim.farm_block() + + try: + yield sim, sim_client + finally: + await sim.close() + +def bootstrap_referee(parent_coin_id, initial_validation_program_hash, initial_split, + amount, timeout, max_move_size, mover_puzzle, waiter_puzzle): + """ + returns referee_wrap + """ + puzzle_hash = referee.curry( + [initial_validation_program_hash, 0, initial_split, amount, timeout, max_move_size, mover_puzzle.tree_hash(), + waiter_puzzle.tree_hash(), referee.tree_hash()]).tree_hash() + coin = Coin(parent_coin_id, puzzle_hash, amount) + return RefereeWrap(coin, bytes(32), bytes(32), bytes(32), + initial_validation_program_hash, 0, initial_split, timeout, max_move_size, + mover_puzzle, waiter_puzzle) + +@dataclass +class RefereeWrap: + coin: Any + grandparent_id: Any + parent_validation_program_hash: Any + parent_everything_else_hash: Any + validation_program_hash: Any + move: Any + split: Any + timeout: Any + max_move_size: Any + mover_puzzle: Any + waiter_puzzle: Any + + def curried_parameters_for_our_puzzle(self, purpose, for_self, move_to_make, split, validation_program_hash): + result = Program.to([ + validation_program_hash, + move_to_make, + split, + self.coin.amount, + self.timeout, + self.max_move_size, + self.mover_puzzle.tree_hash() if for_self else self.waiter_puzzle.tree_hash(), + self.waiter_puzzle.tree_hash() if for_self else self.mover_puzzle.tree_hash(), + refhash + ]) + print(f'for {purpose} curried_parameters_for_our_puzzle is {result}') + return result + + def get_puzzle(self): + return referee.curry(self.curried_parameters_for_our_puzzle( + "GET_PUZZLE", + True, + self.move, + self.split, + self.validation_program_hash + )) + + def SpendMove(self, password, move_to_make, split, validation_program_hash): + """ + returns (solution, new RefereeWrap) + """ + print(f"MOVE referee mover_puzzle {self.mover_puzzle.tree_hash()}") + print(f"MOVE referee waiter_puzzle {self.waiter_puzzle.tree_hash()}") + curried_parameters = self.curried_parameters_for_our_puzzle( + "SPEND_MOVE", + False, + move_to_make, + split, + validation_program_hash + ) + print(f"MOVE referee curried parameters {curried_parameters}") + new_puzzle_hash = referee.curry(curried_parameters).tree_hash() + print(f"MOVE new puzzle hash {Program.to(new_puzzle_hash)}") + solution = Program.to([move, move_to_make, split, validation_program_hash, self.mover_puzzle, + [password, [51, new_puzzle_hash, self.coin.amount]]]) + coin = Coin(self.coin.name(), new_puzzle_hash, self.coin.amount) + everything_else_hash = Program.to([self.move, self.split, self.coin.amount, self.timeout, + self.max_move_size, self.mover_puzzle.tree_hash(), self.waiter_puzzle.tree_hash(), + referee.tree_hash()]).tree_hash() + return (solution, RefereeWrap(coin, self.coin.parent_coin_info, self.validation_program_hash, everything_else_hash, + validation_program_hash, move_to_make, split, self.timeout, self.max_move_size, + self.waiter_puzzle, self.mover_puzzle)) + + def SpendAccuse(self, password): + """ + returns (solution, RefereeAccuse) + """ + print(f"ACCUSE starting with puzzle hash {Program.to(self.get_puzzle().tree_hash())}") + print(f"ACCUSE parent_id {Program.to(self.coin.parent_coin_info)}") + print(f"ACCUSE referee mover_puzzle {self.mover_puzzle.tree_hash()}") + print(f"ACCUSE referee waiter_puzzle {self.waiter_puzzle.tree_hash()}") + new_puzzle_hash = referee_accuse.curry([ + self.parent_validation_program_hash, + self.validation_program_hash, + self.move, + self.split, + self.coin.amount, + self.timeout, + self.waiter_puzzle.tree_hash(), + self.mover_puzzle.tree_hash() + ]).tree_hash() + solution = Program.to([accuse, self.grandparent_id, self.parent_validation_program_hash, + self.parent_everything_else_hash, self.mover_puzzle, [password, [51, new_puzzle_hash, self.coin.amount]]]) + coin = Coin(self.coin.name(), new_puzzle_hash, self.coin.amount) + return (solution, RefereeAccuseWrap(coin, self.parent_validation_program_hash, self.validation_program_hash, + self.move, self.split, self.timeout, self.waiter_puzzle.tree_hash(), + self.mover_puzzle.tree_hash())) + + def SpendTimeout(self): + """ + returns (solution, movercoinid, waitercoinid) + """ + movercoinid = Coin(self.coin.name(), self.mover_puzzle.tree_hash(), self.split).name() + waitercoinid = Coin(self.coin.name(), self.waiter_puzzle.tree_hash(), + self.coin.amount - self.split).name() + return (Program.to((timeout, 0)), movercoinid, waitercoinid) + +@dataclass +class RefereeAccuseWrap: + coin: Any + old_validation_puzzle_hash: Any + new_validation_puzzle_hash: Any + move: Any + split: Any + timeout: Any + accused_puzzle_hash: Any + accuser_puzzle_hash: Any + + def get_puzzle(self): + return referee_accuse.curry([self.old_validation_puzzle_hash, self.new_validation_puzzle_hash, + self.move, self.split, self.coin.amount, self.timeout, self.accused_puzzle_hash, + self.accuser_puzzle_hash]) + + def SpendTimeout(self): + """ + returns (solution, coinid) + """ + coin = Coin(self.coin.name(), self.accuser_puzzle_hash, self.coin.amount) + return (Program.to(0), coin.name()) + + def SpendDefend(self, validation_program_reveal, validation_program_solution): + """ + returns (solution, coinid) + """ + solution = Program.to([validation_program_reveal, validation_program_solution]) + coin = Coin(self.coin.name(), self.accused_puzzle_hash, self.coin.amount) + return (solution, coin.name()) + +@pytest.mark.asyncio +@pytest.mark.parametrize('amove', [0, 1, 2]) +@pytest.mark.parametrize('bmove', [0, 1, 2]) +async def test_rps(amove, bmove, setup_sim): + total = 100 + alice_final = (total//2 if amove == bmove else (0 if bmove == (amove + 1) % 3 else total)) + alice_preimage = int_to_bytes(60 + amove) + alice_image = sha(alice_preimage) + bob_preimage = int_to_bytes(60 + bmove) + bob_image = sha(bob_preimage) + alice_move = int_to_bytes(amove) + nil = Program.to(0) + + # (mod (password . conditions) (if (= password 'alice') conditions (x))) + alice_puzzle = Program.from_bytes(bytes.fromhex('ff02ffff03ffff09ff02ffff0185616c69636580ffff0103ffff01ff088080ff0180')) + alice_puzzle_hash = alice_puzzle.tree_hash() + # (mod (password . conditions) (if (= password 'bob') conditions (x))) + bob_puzzle = Program.from_bytes(bytes.fromhex('ff02ffff03ffff09ff02ffff0183626f6280ffff0103ffff01ff088080ff0180')) + bob_puzzle_hash = bob_puzzle.tree_hash() + + async with setup_sim as (sym, client): + acs = Program.to(1) + acs_hash = acs.tree_hash() + await sym.farm_block(acs_hash) + mycoin = (await client.get_coin_records_by_puzzle_hashes([acs_hash], include_spent_coins = False))[0].coin + # make a coin for a game + referee = bootstrap_referee(mycoin.name(), MOD_A.tree_hash(), 2, total, 1000, 50, alice_puzzle, bob_puzzle) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(mycoin, acs, Program.to([[51, referee.coin.puzzle_hash, + referee.coin.amount]]))], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + savepoint = sym.block_height + # Alice accuse Bob of cheating (negative test, should fail) + solution, accuse = referee.SpendAccuse('alice') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(referee.coin, referee.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.ASSERT_MY_PARENT_ID_FAILED + # timeout too early fail + solution, alice_reward_id, bob_reward_id = referee.SpendTimeout() + spend = SpendBundle([CoinSpend(referee.coin, referee.get_puzzle(), solution)], G2Element()) + (status, err) = await client.push_tx(spend) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.ASSERT_SECONDS_RELATIVE_FAILED + # timeout succeeds + sym.pass_time(2000) + await sym.farm_block() + (status, err) = await client.push_tx(spend) + assert status == MempoolInclusionStatus.SUCCESS + assert err is None + await sym.farm_block() + assert (await client.get_coin_records_by_names([alice_reward_id], include_spent_coins = False))[0].coin.amount == 2 + assert (await client.get_coin_records_by_names([bob_reward_id], include_spent_coins = False))[0].coin.amount == total - 2 + await sym.rewind(savepoint) + # Alice makes an illegally large move, fails + solution, ref2 = referee.SpendMove('alice', bytes(100), 0, bytes(32)) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(referee.coin, referee.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + # Alice makes move with negative split, fails + solution, ref2 = referee.SpendMove('alice', 'abc', -1, bytes(32)) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(referee.coin, referee.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + # Alice makes move with split greater than amount, fails + solution, ref2 = referee.SpendMove('alice', 'abc', referee.coin.amount + 1, bytes(32)) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(referee.coin, referee.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + # Alice move 1 commit to image + bpuz = MOD_B.curry(alice_image) + solution, ref2 = referee.SpendMove('alice', alice_image, 0, bpuz.tree_hash()) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(referee.coin, referee.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + savepoint = sym.block_height + # Bob accuse Alice of cheating + solution, accuse = ref2.SpendAccuse('bob') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref2.coin, ref2.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + savepoint2 = sym.block_height + # Alice accusation defend, gets everything + solution, reward_id = accuse.SpendDefend(MOD_A, nil) + print(solution) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + reward_coin_wrapper = await client.get_coin_records_by_names([reward_id], include_spent_coins = + False) + reward_coin = reward_coin_wrapper[0].coin + assert reward_coin.amount == referee.coin.amount + assert reward_coin.puzzle_hash == alice_puzzle_hash + await sym.rewind(savepoint2) + # accusation timeout too early fail + solution, reward_id = accuse.SpendTimeout() + spend = SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), solution)], G2Element()) + (status, err) = await client.push_tx(spend) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.ASSERT_SECONDS_RELATIVE_FAILED + # accusation timeout succeed, Bob gets everything + sym.pass_time(2000) + await sym.farm_block() + (status, err) = await client.push_tx(spend) + assert status == MempoolInclusionStatus.SUCCESS + assert err is None + await sym.farm_block() + reward_coin_wrapper = await client.get_coin_records_by_names([reward_id], include_spent_coins = + False) + reward_coin = reward_coin_wrapper[0].coin + assert reward_coin.amount == referee.coin.amount + assert reward_coin.puzzle_hash == bob_puzzle_hash + await sym.rewind(savepoint) + # Bob move 2 commit to image + cpuz = MOD_C.curry([alice_image, bob_image]) + solution, ref3 = ref2.SpendMove('bob', bob_image, 0, cpuz.tree_hash()) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref2.coin, ref2.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + savepoint = sym.block_height + # Alice accuse + solution, accuse = ref3.SpendAccuse('alice') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref3.coin, ref3.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Bob defends + solution, reward_id = accuse.SpendDefend(bpuz, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + reward_coin = (await client.get_coin_records_by_names([reward_id], include_spent_coins = + False))[0].coin + assert reward_coin.amount == referee.coin.amount + assert reward_coin.puzzle_hash == bob_puzzle_hash + await sym.rewind(savepoint) + # Alice reveals wrong preimage + alice_bad_preimage = int_to_bytes(61 + amove) + dpuz = MOD_D.curry([(amove + 1) % 3, bob_image]) + solution, ref4 = ref3.SpendMove('alice', alice_bad_preimage, 0, dpuz.tree_hash()) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref3.coin, ref3.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Bob accuses + solution, accuse = ref4.SpendAccuse('bob') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref4.coin, ref4.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Alice defends, fails + solution, reward_id = accuse.SpendDefend(cpuz, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + await sym.rewind(savepoint) + # Alice move 3 reveal preimage + dpuz = MOD_D.curry([alice_move, bob_image]) + solution, ref4 = ref3.SpendMove('alice', alice_preimage, 0, dpuz.tree_hash()) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref3.coin, ref3.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + savepoint = sym.block_height + # Bob accuses + solution, accuse = ref4.SpendAccuse('bob') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref4.coin, ref4.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Alice defends + solution, reward_id = accuse.SpendDefend(cpuz, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.rewind(savepoint) + # Bob move 4 reveal wrong preimage + bob_bad_preimage = int_to_bytes(121 + amove) + solution, ref5 = ref4.SpendMove('bob', bob_bad_preimage, 0, dpuz.tree_hash()) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref4.coin, ref4.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Alice accuses + solution, accuse = ref5.SpendAccuse('alice') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref5.coin, ref5.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Bob attempts defense, fails + solution, reward_id = accuse.SpendDefend(dpuz, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + # Bob attempts defense with wrong validation program, fails + solution, reward_id = accuse.SpendDefend(acs, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + await sym.rewind(savepoint) + if amove == bmove: + # Bob move 4 gives wrong split + solution, ref5 = ref4.SpendMove('bob', bob_preimage, 0, dpuz.tree_hash()) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref4.coin, ref4.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Alice accuses + solution, accuse = ref5.SpendAccuse('alice') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref5.coin, ref5.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Bob attempts defense, fails + solution, reward_id = accuse.SpendDefend(dpuz, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + await sym.rewind(savepoint) + # Bob move 4 reveal preimage + solution, ref5 = ref4.SpendMove('bob', bob_preimage, alice_final, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref4.coin, ref4.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + savepoint = sym.block_height + # Alice attempts move, fails + solution, ref6 = ref5.SpendMove('alice', nil, 0, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref5.coin, ref5.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.FAILED + assert err == Err.GENERATOR_RUNTIME_ERROR + # timeout, split correct + sym.pass_time(2000) + await sym.farm_block() + solution, alice_reward_id, bob_reward_id = ref5.SpendTimeout() + spend = SpendBundle([CoinSpend(ref5.coin, ref5.get_puzzle(), solution)], G2Element()) + (status, err) = await client.push_tx(spend) + assert status == MempoolInclusionStatus.SUCCESS + assert err is None + await sym.farm_block() + if alice_final != 0: + assert (await client.get_coin_records_by_names([alice_reward_id], include_spent_coins = False))[0].coin.amount == alice_final + else: + assert len(await client.get_coin_records_by_names([alice_reward_id], include_spent_coins = False)) == 0 + if alice_final != ref5.coin.amount: + assert (await client.get_coin_records_by_names([bob_reward_id], include_spent_coins = False))[0].coin.amount == ref5.coin.amount - alice_final + else: + assert len(await client.get_coin_records_by_names([bob_reward_id], include_spent_coins = False)) == 0 + await sym.rewind(savepoint) + # Alice accuses + solution, accuse = ref5.SpendAccuse('alice') + (status, err) = await client.push_tx(SpendBundle([CoinSpend(ref5.coin, ref5.get_puzzle(), + solution)], G2Element())) + assert status == MempoolInclusionStatus.SUCCESS + await sym.farm_block() + # Bob defends + solution, reward_id = accuse.SpendDefend(dpuz, nil) + (status, err) = await client.push_tx(SpendBundle([CoinSpend(accuse.coin, accuse.get_puzzle(), + solution)], G2Element())) + assert (status, err) == (MempoolInclusionStatus.SUCCESS, None) diff --git a/resources/tests/game-referee-in-cl23/testrockpaperscissors.py b/resources/tests/game-referee-in-cl23/testrockpaperscissors.py new file mode 100644 index 000000000..f435a006e --- /dev/null +++ b/resources/tests/game-referee-in-cl23/testrockpaperscissors.py @@ -0,0 +1,47 @@ +import hashlib + +from clvm_rs import Program + +from clvm.EvalError import EvalError + + +MOD_A = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsa.clvm.hex").read())) +MOD_B = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsb.clvm.hex").read())) +MOD_C = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsc.clvm.hex").read())) +MOD_D = Program.from_bytes(bytes.fromhex(open("rockpaperscissorsd.clvm.hex").read())) + + +def drun(prog: Program, *args: Program): + try: + return prog.run(*args) + except EvalError as ee: + print(f"brun -x -y main.sym {prog} {Program.to(list(args))}") + raise + +def sha256(blob:bytes) -> bytes: + return hashlib.sha256(blob).digest() + +def testrps(amove, bmove): + total = 100 + alice_final = (total//2 if amove == bmove else (0 if bmove == (amove + 1) % 3 else total)) + alice_preimage = Program.to(60 + amove) + bob_preimage = Program.to(60 + bmove) + alice_image = sha256(alice_preimage.atom) + bob_image = sha256(bob_preimage.atom) + alice_move = Program.to(amove) + + cd = MOD_D.curry(alice_move, bob_image) + assert cd.run([total, bob_preimage, b'', alice_final, b'j']).atom == b'j' + cc = MOD_C.curry(alice_image, bob_image) + assert cc.run([total, alice_preimage, cd.tree_hash(), 0, b'j']).atom == b'j' + cb = MOD_B.curry(alice_image) + assert cb.run([total, bob_image, cc.tree_hash(), 0, b'j']).atom == b'j' + assert MOD_A.run([total, alice_image, cb.tree_hash(), 0, b'j']).atom == b'j' + +def testall(): + for i in range(3): + for j in range(3): + testrps(i, j) + +if __name__ == '__main__': + testall() diff --git a/resources/tests/game-referee-in-cl23/truncate.clinc b/resources/tests/game-referee-in-cl23/truncate.clinc new file mode 100644 index 000000000..e4557f31c --- /dev/null +++ b/resources/tests/game-referee-in-cl23/truncate.clinc @@ -0,0 +1,8 @@ +( +(defun truncate (N (@ L (LF . LR))) + (if (all N L) + (c LF (truncate (- N 1) LR)) + () + ) +) +) \ No newline at end of file diff --git a/resources/tests/game-referee-in-cl23/utils.clinc b/resources/tests/game-referee-in-cl23/utils.clinc new file mode 100644 index 000000000..72873dd66 --- /dev/null +++ b/resources/tests/game-referee-in-cl23/utils.clinc @@ -0,0 +1,2 @@ +( +) diff --git a/resources/tests/lib/__init__.py b/resources/tests/lib/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/resources/tests/lib/load_clvm.py b/resources/tests/lib/load_clvm.py new file mode 100644 index 000000000..a01f37fbc --- /dev/null +++ b/resources/tests/lib/load_clvm.py @@ -0,0 +1,168 @@ +from __future__ import annotations + +import importlib +import inspect +import os +import pathlib +import sys +import tempfile +from typing import List + +import pkg_resources +from clvm_tools_rs import compile_clvm as compile_clvm_rust + +from chia.types.blockchain_format.program import Program +from chia.types.blockchain_format.serialized_program import SerializedProgram +from chia.util.lock import Lockfile + +compile_clvm_py = None + +recompile_requested = ( + (os.environ.get("CHIA_DEV_COMPILE_CLVM_ON_IMPORT", "") != "") or ("pytest" in sys.modules) +) and os.environ.get("CHIA_DEV_COMPILE_CLVM_DISABLED", None) is None + + +def translate_path(p_): + p = str(p_) + if os.path.isdir(p): + return p + else: + module_object = importlib.import_module(p) + return os.path.dirname(inspect.getfile(module_object)) + + +# Handle optional use of python clvm_tools if available and requested +if "CLVM_TOOLS" in os.environ: + try: + from clvm_tools.clvmc import compile_clvm as compile_clvm_py_candidate + + compile_clvm_py = compile_clvm_py_candidate + finally: + pass + + +def compile_clvm_in_lock(full_path: pathlib.Path, output: pathlib.Path, search_paths: List[pathlib.Path]): + # Compile using rust (default) + + # Ensure path translation is done in the idiomatic way currently + # expected. It can use either a filesystem path or name a python + # module. + treated_include_paths = list(map(translate_path, search_paths)) + res = compile_clvm_rust(str(full_path), str(output), treated_include_paths) + + if "CLVM_TOOLS" in os.environ and os.environ["CLVM_TOOLS"] == "check" and compile_clvm_py is not None: + # Simple helper to read the compiled output + def sha256file(f): + import hashlib + + m = hashlib.sha256() + m.update(open(f).read().strip().encode("utf8")) + return m.hexdigest() + + orig = "%s.orig" % output + + compile_clvm_py(full_path, orig, search_paths=search_paths) + orig256 = sha256file(orig) + rs256 = sha256file(output) + + if orig256 != rs256: + print("Compiled original %s: %s vs rust %s\n" % (full_path, orig256, rs256)) + print("Aborting compilation due to mismatch with rust") + assert orig256 == rs256 + else: + print("Compilation match %s: %s\n" % (full_path, orig256)) + + return res + + +def compile_clvm(full_path: pathlib.Path, output: pathlib.Path, search_paths: List[pathlib.Path] = []): + with Lockfile.create(pathlib.Path(tempfile.gettempdir()) / "clvm_compile" / full_path.name): + compile_clvm_in_lock(full_path, output, search_paths) + + +def load_serialized_clvm( + clvm_filename, package_or_requirement=__name__, include_standard_libraries: bool = False, recompile: bool = True +) -> SerializedProgram: + """ + This function takes a .clsp file in the given package and compiles it to a + .clsp.hex file if the .hex file is missing or older than the .clsp file, then + returns the contents of the .hex file as a `Program`. + + clvm_filename: file name + package_or_requirement: usually `__name__` if the clvm file is in the same package + """ + hex_filename = f"{clvm_filename}.hex" + + # Set the CHIA_DEV_COMPILE_CLVM_ON_IMPORT environment variable to anything except + # "" or "0" to trigger automatic recompilation of the Chialisp on load. + if recompile: + try: + if pkg_resources.resource_exists(package_or_requirement, clvm_filename): + # Establish whether the size is zero on entry + full_path = pathlib.Path(pkg_resources.resource_filename(package_or_requirement, clvm_filename)) + output = full_path.parent / hex_filename + if not output.exists() or os.stat(full_path).st_mtime > os.stat(output).st_mtime: + search_paths = [full_path.parent] + if include_standard_libraries: + # we can't get the dir, but we can get a file then get its parent. + chia_puzzles_path = pathlib.Path( + pkg_resources.resource_filename(__name__, "__init__.py") + ).parent + search_paths.append(chia_puzzles_path) + compile_clvm(full_path, output, search_paths=search_paths) + + except NotImplementedError: + # pyinstaller doesn't support `pkg_resources.resource_exists` + # so we just fall through to loading the hex clvm + pass + + clvm_hex = pkg_resources.resource_string(package_or_requirement, hex_filename).decode("utf8") + assert len(clvm_hex.strip()) != 0 + clvm_blob = bytes.fromhex(clvm_hex) + return SerializedProgram.from_bytes(clvm_blob) + + +def load_clvm( + clvm_filename, + package_or_requirement=__name__, + include_standard_libraries: bool = False, + recompile: bool = True, +) -> Program: + return Program.from_bytes( + bytes( + load_serialized_clvm( + clvm_filename, + package_or_requirement=package_or_requirement, + include_standard_libraries=include_standard_libraries, + recompile=recompile, + ) + ) + ) + + +def load_clvm_maybe_recompile( + clvm_filename, + package_or_requirement=__name__, + include_standard_libraries: bool = False, + recompile: bool = recompile_requested, +) -> Program: + return load_clvm( + clvm_filename=clvm_filename, + package_or_requirement=package_or_requirement, + include_standard_libraries=include_standard_libraries, + recompile=recompile, + ) + + +def load_serialized_clvm_maybe_recompile( + clvm_filename, + package_or_requirement=__name__, + include_standard_libraries: bool = False, + recompile: bool = recompile_requested, +) -> SerializedProgram: + return load_serialized_clvm( + clvm_filename=clvm_filename, + package_or_requirement=package_or_requirement, + include_standard_libraries=include_standard_libraries, + recompile=recompile, + ) diff --git a/resources/tests/lib/program.py b/resources/tests/lib/program.py new file mode 100644 index 000000000..eff5badd0 --- /dev/null +++ b/resources/tests/lib/program.py @@ -0,0 +1,231 @@ +from __future__ import annotations + +import io +from typing import Any, Callable, Dict, Set, Tuple + +from chia_rs import run_chia_program, tree_hash +from clvm import SExp +from clvm.casts import int_from_bytes +from clvm.EvalError import EvalError +from clvm.serialize import sexp_from_stream, sexp_to_stream + +from chia.types.blockchain_format.sized_bytes import bytes32 +from chia.util.byte_types import hexstr_to_bytes +from chia.util.hash import std_hash + +from .tree_hash import sha256_treehash + +INFINITE_COST = 11000000000 + + +class Program(SExp): + """ + A thin wrapper around s-expression data intended to be invoked with "eval". + """ + + @classmethod + def parse(cls, f) -> "Program": + return sexp_from_stream(f, cls.to) + + def stream(self, f): + sexp_to_stream(self, f) + + @classmethod + def from_bytes(cls, blob: bytes) -> Program: + # this runs the program "1", which just returns the first argument. + # the first argument is the buffer we want to parse. This effectively + # leverages the rust parser and LazyNode, making it a lot faster to + # parse serialized programs into a python compatible structure + cost, ret = run_chia_program( + b"\x01", + blob, + 50, + 0, + ) + return Program.to(ret) + + @classmethod + def fromhex(cls, hexstr: str) -> "Program": + return cls.from_bytes(hexstr_to_bytes(hexstr)) + + def __bytes__(self) -> bytes: + f = io.BytesIO() + self.stream(f) # noqa + return f.getvalue() + + def __str__(self) -> str: + return bytes(self).hex() + + def at(self, position: str) -> "Program": + """ + Take a string of only `f` and `r` characters and follow the corresponding path. + + Example: + + `assert Program.to(17) == Program.to([10, 20, 30, [15, 17], 40, 50]).at("rrrfrf")` + + """ + v = self + for c in position.lower(): + if c == "f": + v = v.first() + elif c == "r": + v = v.rest() + else: + raise ValueError(f"`at` got illegal character `{c}`. Only `f` & `r` allowed") + return v + + def replace(self, **kwargs) -> "Program": + """ + Create a new program replacing the given paths (using `at` syntax). + Example: + ``` + >>> p1 = Program.to([100, 200, 300]) + >>> print(p1.replace(f=105) == Program.to([105, 200, 300])) + True + >>> print(p1.replace(rrf=[301, 302]) == Program.to([100, 200, [301, 302]])) + True + >>> print(p1.replace(f=105, rrf=[301, 302]) == Program.to([105, 200, [301, 302]])) + True + ``` + + This is a convenience method intended for use in the wallet or command-line hacks where + it would be easier to morph elements of an existing clvm object tree than to rebuild + one from scratch. + + Note that `Program` objects are immutable. This function returns a new object; the + original is left as-is. + """ + return _sexp_replace(self, self.to, **kwargs) + + def get_tree_hash_precalc(self, *args: bytes32) -> bytes32: + """ + Any values in `args` that appear in the tree + are presumed to have been hashed already. + """ + return sha256_treehash(self, set(args)) + + def get_tree_hash(self) -> bytes32: + return bytes32(tree_hash(bytes(self))) + + def run_with_cost(self, max_cost: int, args) -> Tuple[int, "Program"]: + prog_args = Program.to(args) + cost, r = run_chia_program(self.as_bin(), prog_args.as_bin(), max_cost, 0) + return cost, Program.to(r) + + def run(self, args) -> "Program": + cost, r = self.run_with_cost(INFINITE_COST, args) + return r + + # Replicates the curry function from clvm_tools, taking advantage of *args + # being a list. We iterate through args in reverse building the code to + # create a clvm list. + # + # Given arguments to a function addressable by the '1' reference in clvm + # + # fixed_args = 1 + # + # Each arg is prepended as fixed_args = (c (q . arg) fixed_args) + # + # The resulting argument list is interpreted with apply (2) + # + # (2 (1 . self) rest) + # + # Resulting in a function which places its own arguments after those + # curried in in the form of a proper list. + def curry(self, *args) -> "Program": + fixed_args: Any = 1 + for arg in reversed(args): + fixed_args = [4, (1, arg), fixed_args] + return Program.to([2, (1, self), fixed_args]) + + def uncurry(self) -> Tuple[Program, Program]: + def match(o: SExp, expected: bytes) -> None: + if o.atom != expected: + raise ValueError(f"expected: {expected.hex()}") + + try: + # (2 (1 . ) ) + ev, quoted_inner, args_list = self.as_iter() + match(ev, b"\x02") + match(quoted_inner.pair[0], b"\x01") + mod = quoted_inner.pair[1] + args = [] + while args_list.pair is not None: + # (4 (1 . ) ) + cons, quoted_arg, rest = args_list.as_iter() + match(cons, b"\x04") + match(quoted_arg.pair[0], b"\x01") + args.append(quoted_arg.pair[1]) + args_list = rest + match(args_list, b"\x01") + return Program.to(mod), Program.to(args) + except ValueError: # too many values to unpack + # when unpacking as_iter() + # or when a match() fails + return self, self.to(0) + except TypeError: # NoneType not subscriptable + # when an object is not a pair or atom as expected + return self, self.to(0) + except EvalError: # first of non-cons + # when as_iter() fails + return self, self.to(0) + + def as_int(self) -> int: + return int_from_bytes(self.as_atom()) + + def __deepcopy__(self, memo): + return type(self).from_bytes(bytes(self)) + + EvalError = EvalError + + +def _tree_hash(node: SExp, precalculated: Set[bytes32]) -> bytes32: + """ + Hash values in `precalculated` are presumed to have been hashed already. + """ + if node.listp(): + left = _tree_hash(node.first(), precalculated) + right = _tree_hash(node.rest(), precalculated) + s = b"\2" + left + right + else: + atom = node.as_atom() + if atom in precalculated: + return bytes32(atom) + s = b"\1" + atom + return bytes32(std_hash(s)) + + +NIL = Program.from_bytes(b"\x80") + + +def _sexp_replace(sexp: SExp, to_sexp: Callable[[Any], SExp], **kwargs) -> SExp: + # if `kwargs == {}` then `return sexp` unchanged + if len(kwargs) == 0: + return sexp + + if "" in kwargs: + if len(kwargs) > 1: + raise ValueError("conflicting paths") + return kwargs[""] + + # we've confirmed that no `kwargs` is the empty string. + # Now split `kwargs` into two groups: those + # that start with `f` and those that start with `r` + + args_by_prefix: Dict[str, SExp] = {} + for k, v in kwargs.items(): + c = k[0] + if c not in "fr": + raise ValueError("bad path containing %s: must only contain `f` and `r`") + args_by_prefix.setdefault(c, dict())[k[1:]] = v + + pair = sexp.pair + if pair is None: + raise ValueError("path into atom") + + # recurse down the tree + new_f = _sexp_replace(pair[0], to_sexp, **args_by_prefix.get("f", {})) + new_r = _sexp_replace(pair[1], to_sexp, **args_by_prefix.get("r", {})) + + return to_sexp((new_f, new_r)) diff --git a/resources/tests/lib/smoke_test_deep_compare.clsp b/resources/tests/lib/smoke_test_deep_compare.clsp new file mode 100644 index 000000000..8df629518 --- /dev/null +++ b/resources/tests/lib/smoke_test_deep_compare.clsp @@ -0,0 +1,28 @@ +(mod () + (include *standard-cl-21*) + (include print.clinc) + (include prepend.clinc) + (include sort.clinc) + (include assert.clinc) + (include map.clinc) + (include deep_compare.clinc) + + (map + (lambda ((want_cmp_val cmp_a cmp_b)) + (= (deep_compare cmp_a cmp_b) want_cmp_val) + ) + (q + (0 0 0) + (-1 () (1 14 5 4 3 2)) + (1 (1 14 5 4 3 2) ()) + (-1 "X" (1 2)) + (1 (1 2) "X") + (0 (3 2) (3 2)) + (-1 (3 1) (3 3)) + (1 (3 3) (3 1)) + (-1 (1 1) (2 1)) + (1 (3 1) (2 2)) + (-1 (2 2) (3 1)) + ) + ) + ) diff --git a/resources/tests/lib/smoke_test_permutations.clsp b/resources/tests/lib/smoke_test_permutations.clsp new file mode 100644 index 000000000..2ed3fbbcc --- /dev/null +++ b/resources/tests/lib/smoke_test_permutations.clsp @@ -0,0 +1,9 @@ +(mod (X) + (include *standard-cl-21*) + (include map.clinc) + (include prepend.clinc) + (include print.clinc) + (include permutations.clinc) + + (permutations X) + ) diff --git a/resources/tests/lib/smoke_test_sort.clsp b/resources/tests/lib/smoke_test_sort.clsp new file mode 100644 index 000000000..59b8a886e --- /dev/null +++ b/resources/tests/lib/smoke_test_sort.clsp @@ -0,0 +1,11 @@ +(mod (X) + (include *standard-cl-21*) + (include prepend.clinc) + (include sort.clinc) + (include assert.clinc) + (include map.clinc) + (include reverse.clinc) + (include print.clinc) + + (sort (lambda (a b) (> b a)) X) + ) diff --git a/resources/tests/lib/steprun.py b/resources/tests/lib/steprun.py new file mode 100644 index 000000000..fe3332660 --- /dev/null +++ b/resources/tests/lib/steprun.py @@ -0,0 +1,69 @@ +from typing import List +import binascii +import json +import os +from pathlib import Path +from clvm_tools_rs import start_clvm_program, compose_run_function, compile_clvm +from clvm_tools.binutils import assemble +from clvm_rs import Program + +def compile_module_with_symbols(include_paths: List[Path], source: Path): + path_obj = Path(source) + file_path = path_obj.parent + file_stem = path_obj.stem + target_file = file_path / (file_stem + ".clvm.hex") + sym_file = file_path / (file_stem + ".sym") + # print(f"compile_clvm({path_obj.absolute()}, {str(target_file.absolute().as_posix())}, {include_paths}, True)") + compile_result = compile_clvm( + str(path_obj.resolve()), str(target_file.absolute()), [str(p) for p in include_paths], True + ) + print(f"Writing to {target_file} {compile_result}") + symbols = compile_result["symbols"] + if len(symbols) != 0: + with open(str(sym_file.absolute()), "w") as symfile: + symfile.write(json.dumps(symbols)) + + +def run_until_end(p): + last = None + location = None + + while not p.is_ended(): + step_result = p.step() + if step_result is not None: + last = step_result + if 'Print' in last: + print(f"{last['Print']}") + + return last + +def diag_run_clvm(program, args, symbols, options=None): + if options is None: + options = {} + hex_form_of_program = binascii.hexlify(bytes(program)).decode('utf8') + hex_form_of_args = binascii.hexlify(bytes(args)).decode('utf8') + symbols = json.loads(open(symbols).read()) + p = start_clvm_program(hex_form_of_program, hex_form_of_args, symbols, None, options) + report = run_until_end(p) + if 'Failure' in report: + print(report['Failure']) + else: + return assemble(report['Final']) + +if __name__ == '__main__': + # smoke test + import sys + import argparse + import traceback + + parser = argparse.ArgumentParser() + parser.add_argument('-p', '--print', action='store_true', default=True) + parser.add_argument('program') + parser.add_argument('env') + parser.add_argument('symbols') + args = parser.parse_args() + + program = Program.fromhex(open(args.program).read()) + env = Program.fromhex(open(args.env).read()) + options = { 'print': args.print } + diag_run_clvm(program, env, args.symbols, options) diff --git a/resources/tests/lib/tree_hash.py b/resources/tests/lib/tree_hash.py new file mode 100644 index 000000000..1e59e9b7c --- /dev/null +++ b/resources/tests/lib/tree_hash.py @@ -0,0 +1,62 @@ +""" +This is an implementation of `sha256_treehash`, used to calculate +puzzle hashes in clvm. + +This implementation goes to great pains to be non-recursive so we don't +have to worry about blowing out the python stack. +""" + +from __future__ import annotations + +from typing import Callable, List, Optional, Set + +from clvm import CLVMObject + +from chia.types.blockchain_format.sized_bytes import bytes32 +from chia.util.hash import std_hash + +Op = Callable[[List["CLVMObject"], List["Op"], Set[bytes32]], None] + + +def sha256_treehash(sexp: CLVMObject, precalculated: Optional[Set[bytes32]] = None) -> bytes32: + """ + Hash values in `precalculated` are presumed to have been hashed already. + """ + + if precalculated is None: + precalculated = set() + + def handle_sexp(sexp_stack: List[CLVMObject], op_stack: List[Op], precalculated: Set[bytes32]) -> None: + sexp = sexp_stack.pop() + if sexp.pair: + p0, p1 = sexp.pair + sexp_stack.append(p0) + sexp_stack.append(p1) + op_stack.append(handle_pair) + op_stack.append(handle_sexp) + op_stack.append(roll) + op_stack.append(handle_sexp) + else: + if sexp.atom in precalculated: + r = sexp.atom + else: + r = std_hash(b"\1" + sexp.atom) + sexp_stack.append(r) + + def handle_pair(sexp_stack: List[CLVMObject], op_stack: List[Op], precalculated: Set[bytes32]) -> None: + p0 = sexp_stack.pop() + p1 = sexp_stack.pop() + sexp_stack.append(std_hash(b"\2" + p0 + p1)) + + def roll(sexp_stack: List[CLVMObject], op_stack: List[Op], precalculated: Set[bytes32]) -> None: + p0 = sexp_stack.pop() + p1 = sexp_stack.pop() + sexp_stack.append(p0) + sexp_stack.append(p1) + + sexp_stack = [sexp] + op_stack: List[Op] = [handle_sexp] + while len(op_stack) > 0: + op = op_stack.pop() + op(sexp_stack, op_stack, precalculated) + return bytes32(sexp_stack[0]) diff --git a/resources/tests/mandelbrot-cldb.py b/resources/tests/mandelbrot-cldb.py new file mode 100644 index 000000000..11a915fb6 --- /dev/null +++ b/resources/tests/mandelbrot-cldb.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +import subprocess + +command = ['../../target/debug/cldb', '-p', './mandelbrot/mandelbrot.clsp', '(-192 -128 -144 -96 8)'] +want_output = """--- +- Print: ((escape-at -152 -104) 14) +- Print: ((escape-at -160 -104) 14) +- Print: ((escape-at -168 -104) 14) +- Print: ((escape-at -176 -104) 11) +- Print: ((escape-at -184 -104) 8) +- Print: ((escape-at -192 -104) 7) +- Print: ((escape-at -152 -112) 14) +- Print: ((escape-at -160 -112) 14) +- Print: ((escape-at -168 -112) 14) +- Print: ((escape-at -176 -112) 14) +- Print: ((escape-at -184 -112) 8) +- Print: ((escape-at -192 -112) 7) +- Print: ((escape-at -152 -120) 14) +- Print: ((escape-at -160 -120) 14) +- Print: ((escape-at -168 -120) 14) +- Print: ((escape-at -176 -120) 13) +- Print: ((escape-at -184 -120) 8) +- Print: ((escape-at -192 -120) 6) +- Print: ((escape-at -152 -128) 12) +- Print: ((escape-at -160 -128) 10) +- Print: ((escape-at -168 -128) 10) +- Print: ((escape-at -176 -128) 7) +- Print: ((escape-at -184 -128) 6) +- Print: ((escape-at -192 -128) 5) +- Print: "(\\"result\\" \\"||567AAC|68DEEE|78EEEE|78BEEE\\")" +- Final: "3356114000950459963475899699747220812557867594760040767593731831711045" + Final-Location: "./mandelbrot/mandelbrot.clsp(8):43" +""" + +have_output = subprocess.check_output(command).decode('utf8') +assert have_output == want_output diff --git a/resources/tests/mandelbrot/mand_args.txt b/resources/tests/mandelbrot/mand_args.txt new file mode 100644 index 000000000..bc71d4f14 --- /dev/null +++ b/resources/tests/mandelbrot/mand_args.txt @@ -0,0 +1 @@ +ff82ff40ff8180ff82ff70ff81a0ff0880 diff --git a/resources/tests/mandelbrot/mand_test.txt b/resources/tests/mandelbrot/mand_test.txt new file mode 100644 index 000000000..8b1beda64 --- /dev/null +++ b/resources/tests/mandelbrot/mand_test.txt @@ -0,0 +1,25 @@ +(("escape-at" -152 -104) 14) +(("escape-at" -160 -104) 14) +(("escape-at" -168 -104) 14) +(("escape-at" -176 -104) 11) +(("escape-at" -184 -104) 8) +(("escape-at" -192 -104) 7) +(("escape-at" -152 -112) 14) +(("escape-at" -160 -112) 14) +(("escape-at" -168 -112) 14) +(("escape-at" -176 -112) 14) +(("escape-at" -184 -112) 8) +(("escape-at" -192 -112) 7) +(("escape-at" -152 -120) 14) +(("escape-at" -160 -120) 14) +(("escape-at" -168 -120) 14) +(("escape-at" -176 -120) 13) +(("escape-at" -184 -120) 8) +(("escape-at" -192 -120) 6) +(("escape-at" -152 -128) 12) +(("escape-at" -160 -128) 10) +(("escape-at" -168 -128) 10) +(("escape-at" -176 -128) 7) +(("escape-at" -184 -128) 6) +(("escape-at" -192 -128) 5) +("result" "||567AAC|68DEEE|78EEEE|78BEEE") diff --git a/resources/tests/mandelbrot/mandelbrot.clsp b/resources/tests/mandelbrot/mandelbrot.clsp new file mode 100644 index 000000000..cef47ee7a --- /dev/null +++ b/resources/tests/mandelbrot/mandelbrot.clsp @@ -0,0 +1,55 @@ +;; Mandelbrot set in chialisp +(mod (X1 Y1 X2 Y2 STEP) + (include *standard-cl-21*) + (defconstant LIMIT 0x0400) + (defconstant MAXITERS 15) + (defconstant CHARS "0123456789ABCDEF") + + (defun print (M P) (if (all "$print$" M P) P P)) + + (defun to-char (V) + (c 1 (substr CHARS V (+ 1 V))) + ) + + (defun escape-steps (X Y WX WY V) + (if (> MAXITERS V) + (let + ((xsqr (ash (* X X) -8)) + (ysqr (ash (* Y Y) -8))) + (if (> (+ xsqr ysqr) LIMIT) + (- V 1) + (let + ((next-x (+ (- xsqr ysqr) WX)) + (next-y (+ (* 2 (ash (* X Y) -8)) WY))) + (escape-steps next-x next-y WX WY (+ 1 V)) + ) + ) + ) + (- V 1) + ) + ) + + + (defun basic-scanline (X1 Y1 X2 STEP) + (if (> X2 X1) + (let ((escape (print (list "escape-at" X1 Y1) (escape-steps 0 0 X1 Y1 0))) + (rest (basic-scanline (+ X1 STEP) Y1 X2 STEP))) + (c (to-char escape) rest) + ) + () + ) + ) + + (defun stringify-row (R) + (a (c 14 (c (c 1 "|") R)) ()) + ) + + (defun scan (X1 Y1 X2 Y2 STEP) + (if (> Y2 Y1) + (c (c 1 (stringify-row (basic-scanline X1 Y1 X2 STEP))) (scan X1 (+ STEP Y1) X2 Y2 STEP)) + () + ) + ) + + (print "result" (stringify-row (scan X1 Y1 X2 Y2 STEP))) + ) diff --git a/resources/tests/mandelbrot/mandelbrot.clvm.hex b/resources/tests/mandelbrot/mandelbrot.clvm.hex new file mode 100644 index 000000000..cc02257d3 --- /dev/null +++ b/resources/tests/mandelbrot/mandelbrot.clvm.hex @@ -0,0 +1 @@ +ff02ffff01ff02ff08ffff04ff02ffff04ffff0186726573756c74ffff04ffff02ff16ffff04ff02ffff04ffff02ff1effff04ff02ffff04ff05ffff04ff0bffff04ff17ffff04ff2fffff04ff5fff8080808080808080ff80808080ff8080808080ffff04ffff01ffffff02ffff01ff02ffff03ffff22ffff0187247072696e7424ff05ff0b80ffff01ff02ffff010bff0180ffff01ff02ffff010bff018080ff0180ff0180ffff02ffff01ff04ffff0101ffff0cffff019030313233343536373839414243444546ff05ffff10ffff0101ff05808080ff0180ff02ffff01ff02ffff03ffff15ffff010fff5f80ffff01ff02ffff01ff02ffff03ffff15ffff10ffff16ffff12ff05ff0580ffff0181f880ffff16ffff12ff0bff0b80ffff0181f88080ffff0182040080ffff01ff02ffff01ff11ffff05ffff06ffff06ffff06ffff06ffff06ff01808080808080ffff010180ff0180ffff01ff02ffff01ff02ff1cffff04ff02ffff04ffff10ffff11ffff16ffff12ff05ff0580ffff0181f880ffff16ffff12ff0bff0b80ffff0181f88080ffff05ffff06ffff06ffff06ff018080808080ffff04ffff10ffff12ffff0102ffff16ffff12ffff05ffff06ff018080ffff05ffff06ffff06ff0180808080ffff0181f88080ffff05ffff06ffff06ffff06ffff06ff01808080808080ffff04ffff05ffff06ffff06ffff05ffff04ffff04ffff05ffff06ff018080ffff04ffff05ffff06ffff06ff01808080ffff04ffff05ffff06ffff06ffff06ff0180808080ffff04ffff05ffff06ffff06ffff06ffff06ff018080808080ffff04ffff05ffff06ffff06ffff06ffff06ffff06ff01808080808080ffff01808080808080ffff04ffff16ffff12ff05ff0580ffff0181f880ffff04ffff16ffff12ff0bff0b80ffff0181f880ffff018080808080808080ffff04ffff05ffff06ffff06ffff06ffff05ffff04ffff04ffff05ffff06ff018080ffff04ffff05ffff06ffff06ff01808080ffff04ffff05ffff06ffff06ffff06ff0180808080ffff04ffff05ffff06ffff06ffff06ffff06ff018080808080ffff04ffff05ffff06ffff06ffff06ffff06ffff06ff01808080808080ffff01808080808080ffff04ffff16ffff12ff05ff0580ffff0181f880ffff04ffff16ffff12ff0bff0b80ffff0181f880ffff01808080808080808080ffff04ffff10ffff0101ffff05ffff06ffff06ffff06ffff06ffff05ffff04ffff04ffff05ffff06ff018080ffff04ffff05ffff06ffff06ff01808080ffff04ffff05ffff06ffff06ffff06ff0180808080ffff04ffff05ffff06ffff06ffff06ffff06ff018080808080ffff04ffff05ffff06ffff06ffff06ffff06ffff06ff01808080808080ffff01808080808080ffff04ffff16ffff12ff05ff0580ffff0181f880ffff04ffff16ffff12ff0bff0b80ffff0181f880ffff018080808080808080808080ff8080808080808080ff018080ff0180ff0180ffff01ff02ffff01ff11ff5fffff010180ff018080ff0180ff0180ffff02ffff01ff02ffff03ffff15ff17ff0580ffff01ff02ffff01ff04ffff02ff14ffff04ff02ffff04ffff02ff08ffff04ff02ffff04ffff04ffff01896573636170652d6174ffff04ff05ffff04ff0bffff0180808080ffff04ffff02ff1cffff04ff02ffff04ffff0180ffff04ffff0180ffff04ff05ffff04ff0bffff04ffff0180ff8080808080808080ff8080808080ff80808080ffff02ff0affff04ff02ffff04ffff10ff05ff2f80ffff04ff0bffff04ff17ffff04ff2fff8080808080808080ff0180ffff01ff02ffff01ff0180ff018080ff0180ff0180ffff02ffff01ff02ffff04ffff010effff04ffff04ffff0101ffff017c80ff058080ffff018080ff0180ff02ffff01ff02ffff03ffff15ff2fff0b80ffff01ff02ffff01ff04ffff04ffff0101ffff02ff16ffff04ff02ffff04ffff02ff0affff04ff02ffff04ff05ffff04ff0bffff04ff17ffff04ff5fff80808080808080ff8080808080ffff02ff1effff04ff02ffff04ff05ffff04ffff10ff5fff0b80ffff04ff17ffff04ff2fffff04ff5fff808080808080808080ff0180ffff01ff02ffff01ff0180ff018080ff0180ff0180ff018080 diff --git a/resources/tests/mandelbrot/mandelbrot.sym b/resources/tests/mandelbrot/mandelbrot.sym new file mode 100644 index 000000000..4a22371ef --- /dev/null +++ b/resources/tests/mandelbrot/mandelbrot.sym @@ -0,0 +1 @@ +{"4450d921c3b1e4d2d0b689daa7f17ddb9faccf150c42e0bc25bedccb449b537c":"./mandelbrot.clsp(8):31-./mandelbrot.clsp(8):40","6b6daa8334bbcc8f6b5906b6c04be041d92700b74024f73f50e0a9f0dae5f06f":"*prims*(1):1","d3e0f134a2c055fb43aaff77cc14c45578c4b634789bbaf12d0c72e582da0411":"./mandelbrot.clsp(54):49-./mandelbrot.clsp(54):51","7b3aaa149b08ece69f8f69ccd24337922cb8fc8458456d8249e3e80e2e4bcf84_left_env":"1","594567f88230b7941db740e747a755fb52953e426e377bb573461523b4199555":"./mandelbrot.clsp(54):40-./mandelbrot.clsp(54):42","46f1ed138462f6d869464773eed5913ff10047020ec869fd2ac83a93ea8da02f_left_env":"1","1b949d6b278e028e3ec8cd7d7daef53c5417f9f3a86ea82a56792bda931f4de3":"./mandelbrot.clsp(16):8-./mandelbrot.clsp(16):11","f3891bd9a39a9d7b0fa4d1b78dff2aafee0c9ee492d29e91e7865530599835e4":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):25","4c9c45c76173dd2908c19f47a65585d8052adf5f89e0f758d136bc50c0b2aec4":"./mandelbrot.clsp(20):16","3f6ac88fd33af5263214784fc08997f6eb718bdf2b482efb1a7e3689ad185875":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):27","6a20a8d77b1b5b2b8348b909d97e8ef40976f3043e0cae182af681dffd4a2a38":"./mandelbrot.clsp(22):23","434648b85e6c5930169e369d6a83a0fa10122938ac4f3223da6d91f69e2d7ea7":"./mandelbrot.clsp(35):46-./mandelbrot.clsp(35):48","3334138d299f1de76c84b0d4090e2360def4a1c613f7de1decf048aa7d1197f6":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):27","e6252bdd0b00c42989e9b667482d349cbfa4296384cfbe833584bf22169668d7":"./mandelbrot.clsp(35):69","4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a":"./mandelbrot.clsp(54):4-./mandelbrot.clsp(54):9","09608e9c85cbcce6171589e6e289076b4301c8221dc8cc7644d4685149c1591a":"./mandelbrot.clsp(19):14","07e68843f37a4086657ab6de3d1aaae83ff4dc9852e33602ad82f8200862aac2":"./mandelbrot.clsp(20):12","223a6f32d5f71d5cf376a617e924617523c5c063455e4b6c4192a3f7f49349ab":"./mandelbrot.clsp(35):67","2e4a591bbbe0c79c73366e33ace99f76ba708a458ffb617e978467b74fee4d14":"./mandelbrot.clsp(36):38-./mandelbrot.clsp(36):40","89122ad41d83077facf794f65221c3144d7fcdca91b2113a1938371352487de0":"*macros*(2):44-*macros*(2):48","aa5ba8fe6b974ef11057153132832066c3445621c3a97facfaedb0adaf2d3684":"./mandelbrot.clsp(17):24","197d556587b3441efb11831053c7f0f6c198c2e2e360e232a46db8c8ce221aab":"*macros*(2):27","539c49322a85b5bdf9a8a677ed9020bf8991f2cafe6d868dd9852649f8c40e3e":"./mandelbrot.clsp(49):46-./mandelbrot.clsp(49):48","16f5fd57daa7d9788f6bbedbafbf6498a8f1a55c81a70b6cd1f884bcd32fe47f":"*macros*(2):30","9357197dc217c963e1e9b084d9742cd856741a585c0bfc3db060a5543c4b5c48":"*macros*(2):27","061863da78980eb8019dcaec1e5a6cc6147f96b767679160c46e922733d78532":"to-char","3f9e45d04ef985010b9699fbfed921611528a1bfe14a3c93e79067c60031f20c":"./mandelbrot.clsp(23):26","9bec9204059871252b76df417663fdeabbca3832f2bbcea74c35e1059f9815ec":"./mandelbrot.clsp(54):43-./mandelbrot.clsp(54):45","849315f3d2d1a8e89b3cfc009da8c7dc10a25af138b589c72e361d565c78789b":"./mandelbrot.clsp(36):53-./mandelbrot.clsp(36):57","a503a4d5f1403af3ee517a2725e7a4b55ef6bcec0946afa51bb7f30baf6e9bf6":"./mandelbrot.clsp(36):47-./mandelbrot.clsp(36):49","fc07c28f3ebc5f0a261597284630ff9624aa3e42af86b0d4b63855aef86313d2":"./mandelbrot.clsp(24):14-./mandelbrot.clsp(24):26","3e87daa5ebaf2ee5cd48b9438b42925fe907ac9c08218bd639b1be99af26e4c4":"*macros*(2):62-*macros*(2):66","ea4a9e5056b1789526c5ed997c0a158a5b22aaf22842000ce2e9cbf19b5cc219":"./mandelbrot.clsp(54):35-./mandelbrot.clsp(54):39","ae00e9a1052297b0781daa7a4c3e828f79bcb96967933a0d8beed96990291d07":"./mandelbrot.clsp(6):22-./mandelbrot.clsp(6):40","d9eb3c8d23e5befbc1d45029173db60059b820a7dfec2b2bc5e2d1c82863fa8f":"./mandelbrot.clsp(36):20-./mandelbrot.clsp(36):34","a224efd9ea0fc5576b802d33c5cb4e2e747fe35ff641358c6c283a517c72a9c2":"./mandelbrot.clsp(49):31-./mandelbrot.clsp(49):45","e9bf753365df837bef5dcc3e4988dde9a7d56ae56b1a6a21b2ed83961ab5c231":"./mandelbrot.clsp(54):4-./mandelbrot.clsp(54):9","5ca75215696c4e1cfeaab1bfcbf71513d176f05a849b283eb569e6bb5add46c5":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):33","1b7b61b9c0c1b1a2a0c9350d80e5bc54727137072415fdc7a5217e7e9edd39ef":"*macros*(2):44-*macros*(2):48","c302512931ec9f4af8fad29088125d3f3fe3974058c451ec83318dcf0405280b":"./mandelbrot.clsp(23):31-./mandelbrot.clsp(23):34","5d9703662ebae00022cb64042b40cf99794e70b15a595d1cbd67c0bdce72d0fd":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):33","29ef7156fdad6528ba3411182b1c58a173972d8a0844f81ab393617714d3642d":"./mandelbrot.clsp(49):87-./mandelbrot.clsp(49):89","78a86a80432b9091a380be930c43552a06c2d64996d8812463f757d362b62492":"./mandelbrot.clsp(11):6","29fafe8f93be3b524ace28517f02acc57cd681ce82f863f3856746a91e6da0a1":"./mandelbrot.clsp(24):14-./mandelbrot.clsp(24):26","38b204391a173c348b89eff00b1f7316ec53a487472770e07699167a77c2a945":"./mandelbrot.clsp(54):43-./mandelbrot.clsp(54):45","7c3815a1eb636c752709c028bfa64c05226bf12c8b5af6491198ba73346472b3":"./mandelbrot.clsp(24):14-./mandelbrot.clsp(24):26","16b895ddddbc4c9bd10d39d95164be2c33fb2ca3555a76086ad31da1d2e0a94d":"./mandelbrot.clsp(54):43-./mandelbrot.clsp(54):45","884eef994532b1cd3ec86ff3f7c4df6c9ffcc9104c28b69fb972fce0f137cb3d":"./mandelbrot.clsp(54):35-./mandelbrot.clsp(54):39","a459f7f4cdfb74f6a604468d2051253c723ed1921af39a2e118dd751ee7406df":"./mandelbrot.clsp(4):3-./mandelbrot.clsp(4):15","55da2d4ab580eb174ef0d60e6a3acc254cdaea9cf953af022a9ccfa2f27ea48f":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):33","8a537ba84ec85638174ab0cda197087552deae16db8646f517f7547b73c68605":"*macros*(2):62-*macros*(2):66","567bbd019a2a58d4fcd5e10a24dfd9a64dbff240b0ae09487a234a705a2d2c94":"./mandelbrot.clsp(18):24","3d1494c9b144b93171c1f2419e70ca29d6a6a6a8ff780e6a1525e17631c9d5cc":"./mandelbrot.clsp(35):22-./mandelbrot.clsp(35):27","4f3dc0185f579d9021bafbab55496d7e5c39a5e4f41ef55e19a55c6e5133be5a":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):33","5dad34896875f6daf7b967625bf6aac00b454bb1337abff61ad41845444f4316":"escape-steps","81fe15c959d94e34066dce10dbe61eb327e268f069cc276bc74c8fb263aa936e":"./mandelbrot.clsp(22):26","fde7336437fff05e284c51201609f0c5d39f1dbfd1cd2fb7815268ddc570cc19":"./mandelbrot.clsp(37):13-./mandelbrot.clsp(37):20","5bef23cfce6d5c27bb44ad76442bbe287ed5a631a1cee188b4309fb3b86b2666":"./mandelbrot.clsp(36):53-./mandelbrot.clsp(36):57","1f20af3739451bb5d65447048c6825f40528a2273e549b3b86969532e9c32b3f":"./mandelbrot.clsp(36):36","48f6eb3dcb192667016ff10dac09fb21b9388f18d91a863a270f4a91477e8528":"./mandelbrot.clsp(23):28","24a803f02e0a5257518e9f9d23fc7cbe0819a91edadc5abf0ef0ae57d27ea09c":"./mandelbrot.clsp(23):31-./mandelbrot.clsp(23):34","923b3160cd3468875985f94df688f8c8479f4871a4e06521ac237e36cc08c5f7":"./mandelbrot.clsp(54):20-./mandelbrot.clsp(54):33","cf9b94590392051bffc5bc8973ac4a50a2f30e3e53787c951db98b3cf8c78a72":"*macros*(7):33","5de4da88fe1ddee38f6809451626fd1011ea8329df0f6c18f003a2c940401d0b":"./mandelbrot.clsp(35):54-./mandelbrot.clsp(35):66","a74d51f16ad535cd1bb21237eb976e874c0d67ed8ef9b677e294eb989df1bc13":"./mandelbrot.clsp(36):20-./mandelbrot.clsp(36):34","d2d9d291c3d6dcbefad50fbdfec2090ea5f717730f6406ca05b4d2e5b5da7502":"*macros*(2):62-*macros*(2):66","c5692e2bbdb538d502925e148a96d6df05f56f03fa605fa5127134893e564bb0":"*macros*(2):27","f0fa1c8f22be6894e7c68cbebae552385bc4986d5f90fbaa8410802723c9ae58":"./mandelbrot.clsp(35):54-./mandelbrot.clsp(35):66","882b1693f43f5e102dd5e19556f93c6f428fdb1d1e55cdd05387b233d8738deb":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):27","b5a05d9eebd4b9d5ee8d44bed0d2966e3388e854e23362f19103a5820bcd7f97":"./mandelbrot.clsp(44):15","cc89c923a9e3276f8d8138ddeac04e07ac319e5af710d72d61a36bff10aa8202":"./mandelbrot.clsp(49):16-./mandelbrot.clsp(49):29","52db9ef97986e7382ef78b8eae2dacdbb2ce823ed1396a0fb2f7f120a2b40a63":"./mandelbrot.clsp(54):52-./mandelbrot.clsp(54):56","6b2884fef44bd4288621a2cda9f88ca07b4808619dcf88729412a0bef080a581":"./mandelbrot.clsp(49):90-./mandelbrot.clsp(49):94","620882dbaf649530c3ef3065b70e2740dcad4a1c77782f26f60a738bcfec1f6c":"./mandelbrot.clsp(18):29-./mandelbrot.clsp(18):31","2f5ff29521b993de6c1d397fc93a870229064ea9af3e18c5fb39fcf26bfac9ce":"./mandelbrot.clsp(44):6","4b5b8ebe890394a40aa0dcc9b8f94beab72e29f0bf9e77a3666727622818ed39":"*macros*(2):62-*macros*(2):66","9d6026a622a69c8055f771aa1bc5a544489883fa016edf356212272256a5e7b7":"./mandelbrot.clsp(49):11","59351c082d30c6133a61c4956e473275694de8bb91fcd63142d20eba518a959d":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):25","c80643a5f715da07a5a21db7371f2677f918dcc7dcad5042c4d9621b112b2e6d":"./mandelbrot.clsp(23):23","47ad8d4a1a53af2a5b94af0d46529cd4fa53dec5852eb2bfeed9620b072c3e99":"./mandelbrot.clsp(49):31-./mandelbrot.clsp(49):45","d6471351f36a2129317816775f6451f4e74e865bef4dfbbb98b4d59e8068e208":"./mandelbrot.clsp(54):4-./mandelbrot.clsp(54):9","dec4ed4c297e02ff76dccd6d37d9acf4c92d229c480089269691d96de243c627":"./mandelbrot.clsp(24):14-./mandelbrot.clsp(24):26","ff0e987bcf502abb6afca535aff650d2a5209541172863e6ab761d3a0477d7a3":"./mandelbrot.clsp(49):69-./mandelbrot.clsp(49):71","1ae0b1bf50e0b7691d36f19ff55f1c0b5cb1fd9e495e6bdd3c892a549d14fd6c":"./mandelbrot.clsp(49):69-./mandelbrot.clsp(49):71","76c85c0b1a02ccd0f9d278fb110232cfce365ce23c1abd41cddb2bff0ac7407e":"./mandelbrot.clsp(54):46-./mandelbrot.clsp(54):48","2cdca32b31f1fe1f022095209df8a814e78865792aa36838da1d97ac8804bd9b":"./mandelbrot.clsp(36):50-./mandelbrot.clsp(36):52","55e3787d6a9434a3eca44186565ffe1a4054127f0fbd3555dc1559d0771ab952":"./mandelbrot.clsp(4):22-./mandelbrot.clsp(4):28","8cb0ceb4b117150af4258ed6a11861f388200787d0345e60e2f42da4a2940ef7":"./mandelbrot.clsp(49):64-./mandelbrot.clsp(49):68","93f54cc969c6d48e8d96cde6b14d8e01f6b9be907e6555f48e9a383243e7f4b9":"*macros*(7):33","c0273cd964422e631339d301db8857e4c921b71e0e3eca814bd7738f2c9590ef":"./mandelbrot.clsp(37):10","7cad36d86280fb6b83a994dbb5d2197fd1d621dd4231ff472d0970e031f07a6f":"./mandelbrot.clsp(11):6","03c824b8202f36146c07455861cadeb55aee3eea277474322364144df20d1b97":"*macros*(2):44-*macros*(2):48","d09b948577b7b9b9a825b4974edcb1e4d47194848fd0eb85e7a8d9a7d11c98a8":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):35","d70864348248f5c52bf12eff7801d42a95e89e90ca912b2e2516e21951d3b8d9":"./mandelbrot.clsp(54):46-./mandelbrot.clsp(54):48","f18b8f2991a49cbd247bc3baaca852218c72f0808360ee7f7da907778510f92b":"./mandelbrot.clsp(54):10-./mandelbrot.clsp(54):18","b922a0a22d907eb42291f4031165e8c298e3b6a179059d7cc011ef966efdaab1":"./mandelbrot.clsp(23):36","4876725a057a543284746d102d274b81901de5934003ec7cb268facf5092ccf3":"./mandelbrot.clsp(28):8","74fe3ebaf58a999451ddadecab22a5e39c270b2f40100ca4f953bcc4da4a7ebd":"./mandelbrot.clsp(34):10","de5f93759073ee1e132bbb049b49df55036b0ca9dd5f66ee44c2a97f4af5d0b6":"*macros*(2):44-*macros*(2):48","36f37e323236f180acdcc05fd2c8122e099ff4abf9cc5fc69688ea048444f92f":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):27","8747e8226fc7f9799fdb8d3b697cf2c9c13576b6dedfb8cd7e0599074f2124bc":"./mandelbrot.clsp(16):8-./mandelbrot.clsp(16):11","93a6456382561b77ee999692c1e7d2fb648ee685e848196a60e8824e80a1f355":"./mandelbrot.clsp(2):1-./mandelbrot.clsp(2):5","ac7bbd322858f36037b228ebc6dd14bc945a572337ffabb7c56d6610300893b0":"./mandelbrot.clsp(49):64-./mandelbrot.clsp(49):68","1f44c101240629bd2a48c41d61c3bdf93a49b1dbffab9124b284e8d07e861b1f":"./mandelbrot.clsp(17):22","ba4484b961b7a2369d948d06c55b64bdbfaffb326bc13b490ab1215dd33d8d46":"./mandelbrot.clsp(8):43","19ecae439422e92a0aa42f82fec455b23e0445155a9bec61ef74208299bda147":"./mandelbrot.clsp(54):20-./mandelbrot.clsp(54):33","f7974ed1a08d2184335b5759a9408d87693862b29c32efbaa108f01a162df846":"./mandelbrot.clsp(11):6","6b501d1533e2e0474aec1fe8f64bdde06f88d08906556676d2e14dbda4fd08ca":"*macros*(2):44-*macros*(2):48","3dba991a3e7832d2d889c5e004a9f8f302cc523d3c69688c3b25a69213e0d479":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):30","d2a4943cb9d957b9f69f6151cf7659cb063e4e4c651677ff741ab21cd3f36641":"./mandelbrot.clsp(49):8","af340aa58ea7d72c2f9a7405f3734167bb27dd2a520d216addef65f8362102b6":"*prims*(1):1","fe3b2967fa2a6a9433ab52b13b72a39da5182e7e27eac2cca4feb333e9daa2dd":"./mandelbrot.clsp(8):41","18b0d0a1079d1c863616d8f0a8f468e8610a286934f6ba1a1e25fca2d099db4e":"./mandelbrot.clsp(4):3-./mandelbrot.clsp(4):15","8183752fd41561855fc5cd3e9278c9f4d93d7eb472076fcb886d535399d09ed4":"./mandelbrot.clsp(18):17-./mandelbrot.clsp(18):20","301fb3a3a77c72312105b1e7563b3836e75334b93d39212bd3c9a7148cb880c1":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):30","2bead8a7c10b51c09ff289eb7df2910ce4913ab5079ecad9440b8fd68dad396f":"./mandelbrot.clsp(28):8","45e48faf92f8dc6ed30131ee34f1180989ae895d85308039c4bdf6477ccd6fd4":"./mandelbrot.clsp(35):22-./mandelbrot.clsp(35):27","c7dbf122ed575ea7e4b3560b2f11504f95b1495e5c337a9b8b5d31ab70a175f8":"./mandelbrot.clsp(36):41-./mandelbrot.clsp(36):45","6685779900b54efb10c33c5dfbbf32529a2b06eb26aba6f7736162376fcdab9f":"./mandelbrot.clsp(35):77","50997e78f46c9f96e921c626e0cdf180d87bf3cb59d95061154f633fb9e39f39":"./mandelbrot.clsp(49):16-./mandelbrot.clsp(49):29","94fbd5901719bd8b406c75f65d638dc40a1797e89c3910be36d5383dbe49a0ce":"./mandelbrot.clsp(49):13","5d5f24a187d8025dc760a91c06102ea14820c4cf20e4f65312f58392e446b741":"./mandelbrot.clsp(36):20-./mandelbrot.clsp(36):34","c964f6070c2acd94830298b53597fbfed11a0ddabf0a215825e7bde0acd04795":"./mandelbrot.clsp(16):8-./mandelbrot.clsp(16):11","000210c2e752a93b0cf54840ccfbd4282132b7feb0b8598a8f84cbfff5c95680":"./mandelbrot.clsp(11):27","2fd44dc17723eca0691884d8fc135e52824584231e5325d0d8ddc8c09877f20a_arguments":"(X1 Y1 X2 STEP)","c04b5bb1a5b2eb3e9cd4805420dba5a9d133da5b7adeeafb5474c4adae9faa80":"./mandelbrot.clsp(49):31-./mandelbrot.clsp(49):45","91a441bc7b5d751fa55f8df2aa643ec0ad412e4f66ecc1ba310e140d32c2a358":"./mandelbrot.clsp(17):22","c1f8372ca12269e64acf510770506adab862b4cad6776d2c3b4cb1ddc79c3723":"*macros*(2):44-*macros*(2):48","d6e65f94133902de192e317565d60d26514e2eb337d5c969b7296559d8d72553":"*macros*(2):44-*macros*(2):48","02bdbc61375c496c56d7b9ef499d3af49bdde282c61e0f20c3d3996b283eaaff":"./mandelbrot.clsp(23):26","78c5f714d87fea5b56fb635aee2b53c79e95fdb935cd91db4d68880ef561a87a":"./mandelbrot.clsp(34):10","1cb2de17f861daaba687bd573193816c59963d4931444dde2ac5fb5720e0cfda":"./mandelbrot.clsp(54):4-./mandelbrot.clsp(54):9","7516e4e0597d19ad0b9515131a332ec5f1c19f17abf7b1d2c62fd3d7417a3bbd":"./mandelbrot.clsp(36):36","69646e956cb2c6cf794ca22b0f49e4a2d3def7193b706474a9552961f1a2031c":"*macros*(2):44-*macros*(2):48","43951e60bf4ed96961150527b56dc538ebed86d0917d11f85813ac8597c2c905":"./mandelbrot.clsp(49):49-./mandelbrot.clsp(49):51","20c0f569dd52dadd6afae9430a40f785fa346871ffb159621a574f2dd27c6821":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):30","de6a84ae3b385f53e2ef47aa749883f9a2262c9a6431b33dff3cceb98d8ee986":"./mandelbrot.clsp(20):12","ed9139a4b09a4441e7e6bd1108aa2667ef93e3fb20871937b13d62d0eba94919":"./mandelbrot.clsp(54):35-./mandelbrot.clsp(54):39","588d99d1b72c8b6d611c85b3e1e9c8491606589aeed3eebde9f5f58622f71919":"./mandelbrot.clsp(35):74-./mandelbrot.clsp(35):76","9911de70343613344dcbf53301d85226e2c6080cff4e4fd182bdcc3a7d516599":"./mandelbrot.clsp(35):22-./mandelbrot.clsp(35):27","f8604f8807b3199f0cf73cb7520337a6942c491f89326abe6b3a0019e85078f8":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):33","486631bbf2d1892ec94769a3e06c7e0796f51d9d417d62b4831474b75345ac76":"./mandelbrot.clsp(24):50","52dd0c0573bfb971380907bebc8fe4ed5eac739d4913782fa56a9f7909f78578":"*macros*(7):33","73678aa6442ccb57d00bf9f33dc621b9a11bef8eb8583c7e9f6af87b3c350f4e":"./mandelbrot.clsp(37):10","d5f647e2bb3c55f8b9ece7cb40b6578fe322086bf7ed745e504898245e8006f4":"./mandelbrot.clsp(49):64-./mandelbrot.clsp(49):68","2d93a3138dc33a0c34097b86a9a83e781808f6c065b97564befa8b2a3049840a":"./mandelbrot.clsp(49):73","a704cd228b68710cd62b6f3a9a0625a63b3d724cbd65d3b60ddaae13ab871613":"*macros*(2):44-*macros*(2):48","7ecd2773e54961073d513aec45f4bed6e60e4acc032cc4a204d4aab55181fb99":"./mandelbrot.clsp(54):4-./mandelbrot.clsp(54):9","042c55b626937b8d6be258a97f8d25cdedeee2e712dbddef9438fa900eff883e":"*macros*(2):27","d8485e197ea0b6f2f11780d2a735a2ec42303b38d7eb18bfe6ab9fe58d5ddf50":"./mandelbrot.clsp(17):29-./mandelbrot.clsp(17):31","f4f35aaedd5f692cb4c845b5d86141668076dfa622cf762c6ce9211a71dc8b54":"./mandelbrot.clsp(17):29-./mandelbrot.clsp(17):31","1974e6c12f4645021b388e9f7dcbde947fc730cd7f1f01a40d81782564a94c27":"./mandelbrot.clsp(35):34-./mandelbrot.clsp(35):45","2fd44dc17723eca0691884d8fc135e52824584231e5325d0d8ddc8c09877f20a_left_env":"1","c57d8b60a6c62f7737ce1db025521bfbc280e5b6736b67d2d51898d4253b58c3":"./mandelbrot.clsp(15):21","cb9c847f86251a5d97592a8fecd65e314f262e25dd63524e7d52998bae8ba841":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):30","09701390c7f4be7398c39300b97326444a233afa457072922189ce137cafe05f":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):30","19bc3eaee7d7b5cc33223479a4511731d7eebac9d91fc97b00b7207f6f6740b0":"./mandelbrot.clsp(35):67","b9e48d4b6e77b651b1a19589c95b9092f0313c5443511802ee9cc9d16794b051":"./mandelbrot.clsp(8):31-./mandelbrot.clsp(8):40","24255ef5d941493b9978f3aabb0ed07d084ade196d23f463ff058954cbf6e9b6":"./mandelbrot.clsp(5):25-./mandelbrot.clsp(5):27","a05b97e73bc28de3b3350fb79732e47382e49db2b3e611588b89f393fdcee6a8":"./mandelbrot.clsp(5):3-./mandelbrot.clsp(5):15","d58b3d4714a24620e1761c5029c1bce397452916a1f64cfd8e078f5c1c356555":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):33","26c27894c42bacec825f1fe68f930ade223beed2977895ced732262b141812b2":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):35","f1bbfd4aea1d2b42aa3d8e128e37ab2564c5e8f23dd80c7b7d3f9e6915481db1":"*macros*(2):27","8abae9f0d95e6754ee45c71605f8d567f4cd822042b9d1f3d19524fa49d449cc":"./mandelbrot.clsp(37):13-./mandelbrot.clsp(37):20","240db6ce2aa102856bacc2ce1b5f7e4fe4852a791ea02f360bfb643e007a041d":"./mandelbrot.clsp(49):31-./mandelbrot.clsp(49):45","5836e66e20081ee82faf3b94aa932220144674e85998e6ce81e20d67ab67cc8e":"./mandelbrot.clsp(44):20","5a7dc2e260e506304c6b8bcea38a15a0ddee7503d88bbbbe809cbfebd272c9d5":"*macros*(2):30","631e5fe753a0e6b819c4705d5551b00e5f9d63bb5bef305f04d85f2537ca4a95":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):27","3ff41d112d5d42fab83d3204fb618b36e31f10db02fa2bf04b68fe8032b8bfe8":"./mandelbrot.clsp(28):8","061863da78980eb8019dcaec1e5a6cc6147f96b767679160c46e922733d78532_arguments":"(V)","84a32717c39cb5423042c379c3d4b54a74bc4590463cbdd3318c11c37c6ab0f5":"./mandelbrot.clsp(6):3-./mandelbrot.clsp(6):15","a12871fee210fb8619291eaea194581cbd2531e4b23759d225f6806923f63222":"./mandelbrot.clsp(50):7-./mandelbrot.clsp(50):9","cfb036dc14f3d4fb977a0619668fa0b6f48fbc24479fa87d73506b9902657f3e":"./mandelbrot.clsp(15):10","feb8ff785ea3c2a99453a0248b4e8e5688557d4b7c73d92c03c21d9cbd2b68c5":"./mandelbrot.clsp(36):20-./mandelbrot.clsp(36):34","f2e82ac5fdb42480a3f73484cfa7cb44366c695deb253d3c547cbb7087844857":"./mandelbrot.clsp(54):49-./mandelbrot.clsp(54):51","0e169cdd7e431e402360732cf5dede578621536bfdf69dd9fec5e654febd1d41":"./mandelbrot.clsp(6):3-./mandelbrot.clsp(6):15","2f291b1e011d6c035bac8d2d87a700beeaa7f34a37ca344ee2c613897cef236c":"./mandelbrot.clsp(20):12","08cc9c079a254dcbbf30c8172e15a8e0b40b77e5e169524010940d5fcef7d67a":"./mandelbrot.clsp(54):4-./mandelbrot.clsp(54):9","387da93c57e24aca43495b2e241399d532048e038ee0ed9ca740c22a06cbce91":"./mandelbrot.clsp(35):54-./mandelbrot.clsp(35):66","95f36862dda90b60d7c2fe8a5f0ef350bc02969208e4f847bc1a3f4038eb8084":"./mandelbrot.clsp(22):26","cbc6606f011046556c24d20903574162478339946260bbb7fbce2886409a59a8":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):30","ab8f2cb3e0c9b003a6267bd4fb7d1e3e26148f33a0bbbfe65342fa0e02ca2222":"./mandelbrot.clsp(16):8-./mandelbrot.clsp(16):11","57d399996a6f69c888007a60f4f2dab98b68a95783a38ba69fb00bb3802daf87":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):30","bb0ea81768ff20d868536ad9003d43f3491675e44c5ecfb7c9d184201c0ec698":"*macros*(2):27","641d935acb7cbc7d0c71841a642e71c366b892cf1b2b7b83641a1705f857f971":"./mandelbrot.clsp(28):10","a252efa0d73bad23fed7a9148a0527b68c2e9787b2bbcfbb08df0991820f2f99":"./mandelbrot.clsp(54):49-./mandelbrot.clsp(54):51","1eb5fd9bfac583ca9fdc24cc2e12015e5974be4e8dbdc2b930eb492e60598f5e":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):30","061863da78980eb8019dcaec1e5a6cc6147f96b767679160c46e922733d78532_left_env":"1","57bfd1cb0adda3d94315053fda723f2028320faa8338225d99f629e3d46d43a9":"./mandelbrot.clsp(49):80-./mandelbrot.clsp(49):82","aeef4757d36b14fb7654e1cc67b3ea5b4aea9a8108ae54712b31bff989ebbdd5":"./mandelbrot.clsp(19):17","006bff8fe95364956c926bb544bb0e42d5709e874e7cc31c851c705fc5a47627":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):33","0a5af5ae61fae2e53cb309d4d9c2c64baf0261824823008b9cf2b21b09221e44":"./mandelbrot.clsp(8):43","13b7dcd665f5257f0c2351c366a3df2da385c68b244bdbc768ee05cb7845dc9c":"./mandelbrot.clsp(24):14-./mandelbrot.clsp(24):26","6c2486e256f1d35b04972492fd377c62d46b344f6c515c4086ce1d45b4baf0d0":"./mandelbrot.clsp(35):74-./mandelbrot.clsp(35):76","3492218e7e04e9350b06aa34971be853d8f55344affc2fe2a66f547bb983c7af":"./mandelbrot.clsp(37):13-./mandelbrot.clsp(37):20","5dad34896875f6daf7b967625bf6aac00b454bb1337abff61ad41845444f4316_arguments":"(X Y WX WY V)","8bd59b5acaecb6779640f6fd47adb9b3dce694777473e710858d341e29b7f515":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):25","94901f8ff3f22c1c8d475f03da3e5bad460ee16ad85373eb7a1633828d6aae01":"*macros*(2):30","653b3bb3e18ef84d5b1e8ff9884aecf1950c7a1c98715411c22b987663b86dda":"./mandelbrot.clsp(44):11-./mandelbrot.clsp(44):13","2098d8ceb40fe063596ac5cd73a8b21b7bf2ebaddcf62be7bf96889b44de1200":"./mandelbrot.clsp(44):18","51e3b5c13aa65e2a8b719f2c752f89f4a2e53fea0fba54d1039d80ca86b4252d":"./mandelbrot.clsp(49):49-./mandelbrot.clsp(49):51","8a76a7583b2ece4cb40c6cb7c211204882b8d539d5243b777c6b3308932bc891":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):33","4351796555753ee7f1ac53bf79c7c901cb1c8021395dadc4c322b6eea565ca15":"./mandelbrot.clsp(36):50-./mandelbrot.clsp(36):52","534b7996f58e3571f0cc67c210ca2eb856af7eec95457508ec6d46a21d32a47f":"*macros*(2):27","d066f9812625c40e18953381cb5d1b13c53553fd3eba6d4ade59cf707368098f":"./mandelbrot.clsp(37):10","f4500e4ba0a321c24636b173e70ec844c2aabd10c4ef3d69636b89d3701c823e":"./mandelbrot.clsp(54):4-./mandelbrot.clsp(54):9","47d0b492e50e145ee2fab7c3b164df0d2cdce80ffabcb00b19df7e5fb9e6c67b":"./mandelbrot.clsp(24):14-./mandelbrot.clsp(24):26","b98ea6eb7b4b99e5eeb6d1a3cfc3610ae93354fe1c322e8a74797004a750e60a":"./mandelbrot.clsp(36):20-./mandelbrot.clsp(36):34","b6b45134fa3b154152aee8b4c8d8e40d976d0c7d564993156c302ffad5046e30":"./mandelbrot.clsp(44):6","df70f052682504228b50fc0b868e52de96552bf4654d4948ec43be27d4765622":"./mandelbrot.clsp(49):73","870f1251c064791acaf21669f63f0c5b8b70c087d176fb647b05d9a97190f21d":"./mandelbrot.clsp(49):8","5dad345ae3c23d573a6560f4f46b8a824ad7109669e4d2b960b53b3bcfa5d4b9":"./mandelbrot.clsp(54):35-./mandelbrot.clsp(54):39","acfa5f9fcbd7cbc7a06ae863001da960f12302d27acfdea38ae7b003c5f5be20":"./mandelbrot.clsp(36):20-./mandelbrot.clsp(36):34","462b7380e2907434d4e0676219f9a0f57787aadc8bb3167a1b617ae5d9b4657b":"./mandelbrot.clsp(16):8-./mandelbrot.clsp(16):11","d185810df1bfc294d19d75a5bce24e14a7711d1dcdeb4517b1a4d7212e8c37e9":"*macros*(2):44-*macros*(2):48","cccff94de4e1cea74215e5d6370f5e52a9a4dff0fce75f9016e4de021b48d1ff":"./mandelbrot.clsp(35):77","d0e5290348881028d8bddf188318dcd15640a4843744dd1b9ae5a70f1b909302":"./mandelbrot.clsp(37):10","c65b39898818191e95c0bda9021af4eb69c78973edede92c6aa950f5fd66f75b":"./mandelbrot.clsp(49):16-./mandelbrot.clsp(49):29","e2b7805b720c1ec7c0a009f39dca1928ff911a0e6e046c1f0c50e1922f9e2eee":"./mandelbrot.clsp(16):8-./mandelbrot.clsp(16):11","28d0bcd82277a716a65520fd33fcacacaa220ecfb148efa9010e6e2db5499524":"./mandelbrot.clsp(8):27-./mandelbrot.clsp(8):30","1803d5ecc8f1ef577e52cd3904645e298c5edc1f4446bdafd603a5b1adcf47b0":"./mandelbrot.clsp(35):54-./mandelbrot.clsp(35):66","7c14174364837d391cf50b08ec6760d6b63ad88d2fefc71550ff4c6ac2a44360":"./mandelbrot.clsp(37):13-./mandelbrot.clsp(37):20","764c8a3561c7cf261771b4e1969b84c210836f3c034baebac5e49a394a6ee0a9":"*prims*(1):1","ad2cf336c8b4d4e1d7681f71f685e921a0f3d068ccb775cbce7d2851c7fdc565":"*macros*(7):33","115b498ce94335826baa16386cd1e2fde8ca408f6f50f3785964f263cdf37ebe":"*prims*(1):1","e8e1df5d0fb20bc4d578c4208beda333fc63c74c50c1a658091e27b2490bb41f":"./mandelbrot.clsp(11):11-./mandelbrot.clsp(11):17","461a46d263cf2f775539581ffb15736e7720f5320aef49258ad668886332ec96":"./mandelbrot.clsp(8):27-./mandelbrot.clsp(8):30","b70654fead634e1ede4518ef34872c9d4f083a53773bdbfb75ae926bd3a4ce47":"*prims*(1):1","6f421c534f410909658a60d0c35a30691dee19290a35b36fe44db5d68e89d8f9":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):35","8c0028f07e418b57a26c2fc48e0c1ff10a4f01db9847e1cf5d0c5b4f86ee15ed":"./mandelbrot.clsp(28):8","492ef8cb6ea502c54e14a14c35ce6e0573f9a7cac19b3be6d336419522c8ba5c":"*macros*(2):30","83a6579c642b8d702f3bc701119311357ea78c871791c560c9898f88dcb4327c":"*macros*(2):27","d9540129c8d25b0aa886b06d9a99d4ea93bea2b6df9ffa7c0706351132b49ce6":"*macros*(2):30","46027ef94d5f9e5f433cace3fe5cb704e1a4eae5820a0250d58fabeaddfd6bca":"*macros*(7):33","1d16a54d70b70c3a7150afaafe55e62ef0a24bae747d3f1287bb3bca893f861b":"./mandelbrot.clsp(36):47-./mandelbrot.clsp(36):49","d678eed223f93a31a64833d740fa3446634e1a5bb4633949fd4c6be87ce565bd":"./mandelbrot.clsp(36):47-./mandelbrot.clsp(36):49","093aea7495b2cea8dcfa7b715b96f849bab27cefbfd38f3a816b2b1a37f6b5df":"*macros*(2):27","e993481360cff6d1798522698baf3e6cac611d34a33f0ee8622288d64dda1e15":"./mandelbrot.clsp(44):11-./mandelbrot.clsp(44):13","032d4ced7a27276100e4f9a6f084f8c76529798a8e7f0a537f9369bb1b75ba40":"./mandelbrot.clsp(48):10","d9a505a6966253b0b602d5cd1731b50fdda58f96b22341689be996495a67e8fd":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):35","d2d50de29a287ac02a224293299411f235f3b1f3994d94d43b4e4d6e783b3c16":"./mandelbrot.clsp(35):69","c59908cff9dda698c6cd6d8412a11b44a688ef56a4c1c6a6708bdd110441a90d":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):25","187f5f4920b6aa7ab95f623a4f775878cda061335dd30cb4cba51f7dcd5d174c":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):25","d5db4e0b961efa15fc5db88991d25b224302c24c6d055a7a29bef40f08dc238d":"./mandelbrot.clsp(54):52-./mandelbrot.clsp(54):56","4b5974238f4f77a4f78fc568794c2922758fdfc99c0e470042fd47f9879e74b2":"./mandelbrot.clsp(11):8","7b3aaa149b08ece69f8f69ccd24337922cb8fc8458456d8249e3e80e2e4bcf84":"print","2b84bad14b6113746e1547c2ccc7fbde6f71d9632b24371ccd4cb17b321561d9":"./mandelbrot.clsp(16):8-./mandelbrot.clsp(16):11","5d673620c1551f0d113cefbb7ad432627112e665b11995d8ffb7346c31d8c749":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):30","source_file":"./mandelbrot.clsp","2f626e647d7ea5662d930b77c3ad61c038adedcab94e240f7a9a7447dddf89bd":"*macros*(2):27","edb091197e890ca2794aa8969995271fca9144447ab8fc37e1a3a342770ade44":"*macros*(7):33","733c6171213c38cb4f2338de312b6b271ec7f3cd048240142bc7bc899dde8e23":"./mandelbrot.clsp(35):74-./mandelbrot.clsp(35):76","f32af4d5808c759643cb0129d2394c2563b54c30d6df418694e6b8e41e7e5f99":"./mandelbrot.clsp(35):22-./mandelbrot.clsp(35):27","7638d6f19f8c4b1661fbfddd0bce6c4abff36c6f18aa52c8e5513c5d67f6ceca":"*macros*(7):33","3dbf38db11596fffdbadb99fffb800ecfbae4a34f51b5c95db3a8b2338687b00":"./mandelbrot.clsp(24):14-./mandelbrot.clsp(24):26","ef318c36a54fbf750c3393bfcb4e005789c96ca84e8bf590777422671658c4c4":"./mandelbrot.clsp(19):14","0945d00f8c5e75b7d372c94390a0dcff78624ba47492b7c4c56a1746ba57df2f":"./mandelbrot.clsp(15):10","d78282a250bd430da333eeadf387a1e5fcf549ff0ab49667e68fed9aefae8125":"./mandelbrot.clsp(35):34-./mandelbrot.clsp(35):45","9d748086dbfe2f3fc671d8a037b9f1923dc8f2c4d8a335de28a87efc6c72df95":"./mandelbrot.clsp(35):34-./mandelbrot.clsp(35):45","af2f5c0848be28991bf7afc8b4b6611bd017bcc128725b31d697a22bc035cf2f":"./mandelbrot.clsp(35):54-./mandelbrot.clsp(35):66","0ad33e725fb15991df4f6d7397ffb4f792a33f42c849a7495a5a827ff7352dc1":"./mandelbrot.clsp(36):36","4dc1ac5ca33dd21b551a3220f483f6d866adc9f7859e6e7790dfb7a71cfb012e":"./mandelbrot.clsp(35):77","7e88af07fe7d3756ff745346230e10a204817a488a27899a36df92d9771ffec3":"./mandelbrot.clsp(44):6","ef98d286a35becacc078a285b41f9c0e000e54e1d97c6adff7286765bdc95eee":"./mandelbrot.clsp(49):31-./mandelbrot.clsp(49):45","f595963cbe26a718677c1274180103a0eac93973842a855b6d074211d046b414":"./mandelbrot.clsp(49):31-./mandelbrot.clsp(49):45","4756c6d16e9cd878a37cefeedfc8fa380fa935227eda6d4ac37983d36b3ee7a2_left_env":"1","9394079ce11abf4105ee988738e5e16c196668055272b7a95ceffabfed3c292f":"./mandelbrot.clsp(36):20-./mandelbrot.clsp(36):34","26e7f98cfafee5b213726e22632923bf31bf3e988233235f8f5ca5466b3ac0ed":"*prims*(1):1","d6423421cd514c39b893e0f01c56de376cc909adf00bed2e637346a4b4915905":"./mandelbrot.clsp(24):14-./mandelbrot.clsp(24):26","3efad2b120ec04ead8b80dcaeb0ead48021e7cc84705bdba8d98d16d49fbf2df":"./mandelbrot.clsp(49):64-./mandelbrot.clsp(49):68","bf7969f41e3f44c2656752df835d74d0071fa7b01818f8d19b9efc6f1249991c":"./mandelbrot.clsp(54):52-./mandelbrot.clsp(54):56","76c02de572d12c3fc0953075230cce9a94b125bdd3680df4f213194f2a7ec2f9":"./mandelbrot.clsp(8):31-./mandelbrot.clsp(8):40","b4b690773ca7ccefc76e2371d8660030f853fce58c6159f54c4330508bc4b650":"./mandelbrot.clsp(24):14-./mandelbrot.clsp(24):26","fce7ea546f39e2fa276656015eb8b4c5a4fc2c7708bda55050fd0c474b61f91c":"*macros*(2):30","8544dde32c24d9f465d18db3797bca9e021474b1ae8eb9eda99e733bd92fb69d":"./mandelbrot.clsp(54):4-./mandelbrot.clsp(54):9","9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2":"./mandelbrot.clsp(54):4-./mandelbrot.clsp(54):9","5940533954bbc36e7e5834cb6cc3695fb4a1400e047043b217cdf9dfeb5ca49b":"./mandelbrot.clsp(49):8","536b0c61fff3474f46a605343ff0df83d974369f13a088b809123669c66fd8f8":"./mandelbrot.clsp(11):27","4756c6d16e9cd878a37cefeedfc8fa380fa935227eda6d4ac37983d36b3ee7a2_arguments":"(R)","30483f747949752783a80e6bb0a8a2cb7fbaa934ea44b0f30f36f935d2ef391d":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):30","8c8e14368079d92c7ce1d9dabf2335a7790c90fee26e5f45ce15cd043aa7ebe6":"./mandelbrot.clsp(44):22-./mandelbrot.clsp(44):25","4e0722cf28d67c4abe42848047e08c65284ab86908a6b94e1f157c6585813668":"./mandelbrot.clsp(44):9","91ee779e9599100bedcec1ec16c6a72fa8416d34a9b0be7cabe1c56ca6976c8c":"./mandelbrot.clsp(11):24","088cbb515ec0b5263653a681fc21956e8d04c4e723c02c40129c1769e876f63c":"./mandelbrot.clsp(2):1-./mandelbrot.clsp(2):5","fff586cc17a000df36970cc27ba7eb1095afcd61694e0c89ce139d95f12067bd":"./mandelbrot.clsp(8):43","155f2e1c4fb48e759a3ecf0d055dcef972a91906cd19d3fa1105075caa7cf9a3":"./mandelbrot.clsp(49):16-./mandelbrot.clsp(49):29","e2ae1fe78b53c261a95827186146bb8afb2ce065fce96cd51d44a1dd319526df":"./mandelbrot.clsp(24):48","6953a91e2c2a47eea11c61f5b71287f63f2b733e686edb9f335dfde5acbf06bd":"./mandelbrot.clsp(18):17-./mandelbrot.clsp(18):20","d5df60aa14af601f0a14296bb7360996f17ee16c5904ab44db46ea70356c9df9":"./mandelbrot.clsp(54):20-./mandelbrot.clsp(54):33","12a6eb7c301c87555ed8a084543129cf3816faa92fb94361386bd1423912b1ad":"./mandelbrot.clsp(54):35-./mandelbrot.clsp(54):39","026610f80f7caed612208aaeeba9d777c73eec98a477f403ee997f734de5502f":"./mandelbrot.clsp(54):10-./mandelbrot.clsp(54):18","7b3aaa149b08ece69f8f69ccd24337922cb8fc8458456d8249e3e80e2e4bcf84_arguments":"(M P)","5809addc9f6926fc5c4e20cf87958858c4454c21cdfc6b02f377f12c06b35cca":"./mandelbrot.clsp(49):84-./mandelbrot.clsp(49):86","ab51e0d32da318a9b5f48c6e81beb83ba9f6e93fd51168cf160dd80c899e82d8":"./mandelbrot.clsp(54):10-./mandelbrot.clsp(54):18","8b40786b5cb0989e5337390cf6ba93a3b6d641dc0a71a19ada52f8bb4865e0c3":"*macros*(2):62-*macros*(2):66","0763c1e3e33c124d58ba24b8c5c5e7b977e2043c096f4a0173bf08bdcc9b8654":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):33","44602a999abbebedf7de0ae1318e4f57e3cb1d67e482a65f9657f7541f3fe4bb":"*prims*(1):1","62eedd00022359daf488006b39b825aa9f0c2088c474ba24c1f09457894e159a":"./mandelbrot.clsp(16):8-./mandelbrot.clsp(16):11","a866d02017cc9cc4bbb31031495001e937dd641730c921fb87d8fa5ff73522d9":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):30","11c6118724a6966e3ed400816e1155d951f0330ae2a7f8e007938a8d552b9c93":"./mandelbrot.clsp(17):17-./mandelbrot.clsp(17):20","68a6e6c0fe45fc676d10299ad4d4d3d77e79c175a41b47ad9cf9d2ef85b501a4":"./mandelbrot.clsp(24):48","5ae951f94671144915f0a8f1c7bbd6c9adb805cd9c19d1879a102599154c603e":"./mandelbrot.clsp(35):71-./mandelbrot.clsp(35):73","477fba7a42ba568dd1fcd401b8063b75f19d9fbd2a9469687bb7fad50151ffc0":"./mandelbrot.clsp(35):22-./mandelbrot.clsp(35):27","7207999dcec15009b71d3c32ad5415bb914ae83cb83326bbfbfc38f4732d4b04":"./mandelbrot.clsp(35):22-./mandelbrot.clsp(35):27","54ac34cf4977340a7de0c847b37a974a727c66475bd5880c0ae40eb21047da7d":"./mandelbrot.clsp(35):77","e950ce0b56c2ea387b6c152e45422bf542c987587bede42fc30a8980b7b9a516":"*macros*(2):27","4e37cc6a79f5a52ddd99f1cd3fcf23e9f0af1be281f68cb21f65165a4eb2b657":"./mandelbrot.clsp(23):28","7f2dce06acdeea2633ff324e5cb502ee2a42d979278d8926a2e4e5728592fd87":"./mandelbrot.clsp(44):22-./mandelbrot.clsp(44):25","f16b9c4ae6091303b8fbdcc84d46daccbff782e664f38dc9c912aca09aafb522":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):35","822e62246f590c7324d8951d572b5b8818a526791fb321e79351e36dc3abfb2f":"./mandelbrot.clsp(2):1-./mandelbrot.clsp(2):5","5f3322021bc04a79aa63f5ce5234a819450411b6e6a1550afed7d0fc70b78e9f":"./mandelbrot.clsp(54):35-./mandelbrot.clsp(54):39","9f7769e5e3d1793d5841f813d73b3166e819055a759580e579b6a392e80c859e":"./mandelbrot.clsp(35):22-./mandelbrot.clsp(35):27","8a7ac2881d772500dba5f12903492cfae45f7bf7a36e9b749456f2b57505bbeb":"./mandelbrot.clsp(54):20-./mandelbrot.clsp(54):33","a374e1f0851fffb43fa5c33baa52e97d3beb3911638d3c5db4eb9427b3d8b1ea":"./mandelbrot.clsp(54):46-./mandelbrot.clsp(54):48","69ae360134b1fae04326e5546f25dc794a19192a1f22a44a46d038e7f0d1ecbb":"./mandelbrot.clsp(11):8","724790ad0b9e1d34577ef60026fb2d886272ab02b75748dcc900b7c5cd5b8531":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):36","e0d534c962a405ef38a2e3627d4245821c6e2aac1d62e03100db64bbd2e4cfc1":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):27","34af6938669a377ca6e5f4e06d8ef90ee0a2bc39169f50b42334225788a5fdfd":"./mandelbrot.clsp(35):49-./mandelbrot.clsp(35):51","46f1ed138462f6d869464773eed5913ff10047020ec869fd2ac83a93ea8da02f_arguments":"(X1 Y1 X2 Y2 STEP)","5e6f2db50a5ba492531b236b67c524112466b61222bebd43d4a06a9ecd7a3989":"*macros*(2):30","3d0be4daa73ea972c2ef6e418cef115d0de1fbade2ebd54c78b17c73169da363":"./mandelbrot.clsp(8):43","f528bdfc742ea058a1cfb97c6e30707b6cdda765e39936b20e61959c09d1eb95":"./mandelbrot.clsp(16):8-./mandelbrot.clsp(16):11","b20cb24a3d4131b8f456a996992a575bc1ee6dc4b90338028c40fd53df9a15c4":"./mandelbrot.clsp(49):46-./mandelbrot.clsp(49):48","502a705bf2aba777946441ea7af6af9614886faef067153a7c4e749de434235c":"./mandelbrot.clsp(49):16-./mandelbrot.clsp(49):29","6dbd79ff4ee9005b355d8dd703112e17978777191c131ab0cfaaf2e29a538590":"./mandelbrot.clsp(49):11","fbbfc73885b20795a10e3db453362278b98fa9e944b71bce529bde0f87992034":"./mandelbrot.clsp(35):77","__chia__main_arguments":"(X1 Y1 X2 Y2 STEP)","303ddbfff351571c8f52039b16e791f51cfe1c3f5717eaeacfad270f9fcd050b":"./mandelbrot.clsp(36):36","c73ef88f89c96dc3ef7b83d6d5bca89a298cff4510b08a3837cc6cf35ed7992e":"*macros*(2):27","42a819bf3c4247de5ab4ab183149e71ba49d7da9197534870e99f1f64ef4547f":"./mandelbrot.clsp(44):11-./mandelbrot.clsp(44):13","942e877c30fa70de8f7594bcea49124c361f900f46ad3928942449a244a98c48":"./mandelbrot.clsp(48):10","9b9e21db9e6a897eb51b478ca1a64cb33f4d26159a3f0683467b8e15980c74a6":"./mandelbrot.clsp(2):1-./mandelbrot.clsp(2):5","06b0ae9b621689e1c2259654a4aa7c68aa83bb72f211de871410c338de25a753":"*macros*(2):62-*macros*(2):66","c558a2bb59be7219100edde8844d94afed7f386aa89c3e1f7ce25df70f8cc7d5":"*macros*(2):62-*macros*(2):66","9a4b45b508f949e2482c46d2aea26fcf630d42841a21b7d71e16adb40bc61e7a":"./mandelbrot.clsp(54):10-./mandelbrot.clsp(54):18","0aa5c8c5a83ec11a75bdc024190702d715284d41b5195d5ecf496a6be52e7517":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):27","77f3fac0ade047e894991b86bb3b14b1a55e8c84787d635289502bb7a48120f4":"./mandelbrot.clsp(35):54-./mandelbrot.clsp(35):66","b81abe03a7b086d1a21c54bf04ee118d5129dda6bdc29d369611c2768e5733fa":"./mandelbrot.clsp(54):40-./mandelbrot.clsp(54):42","27a22d17a8739b2c80d86c2dc6a7f7b3be394335a5e5202bd9d349c68869eedb":"./mandelbrot.clsp(22):23","5bcba3add59b485320f3b612d1461b03af7632f203b123d68908a2f095919d46":"*macros*(2):27","3563a178fd0dd86b57134b9ff9e8a8e31a2637c9bb2b75b8f5f3fd7ff7a24d2e":"./mandelbrot.clsp(44):9","04b33101947ea7b950c0edefdac5ca49cb35303c694884c9535259856ae0938c":"./mandelbrot.clsp(49):52-./mandelbrot.clsp(49):54","391b4d96fe8d9830731ea7a316017f0470d1b5d6c45ddfb8ee84af64fe08a0e0":"./mandelbrot.clsp(23):36","f8d392cb57eea7a33e4987854f0540a9193814e407582a62216ff1f1b385d127":"./mandelbrot.clsp(49):8","46f1ed138462f6d869464773eed5913ff10047020ec869fd2ac83a93ea8da02f":"scan","def482f1f8cc690c01361da76aad34a0d103c622d252c3d2328dd6baede562f7":"./mandelbrot.clsp(54):20-./mandelbrot.clsp(54):33","a8daf08e9d9fb4aebdefaae0f248877e08b2e158402b163cc05baeb273d6fbd7":"./mandelbrot.clsp(35):54-./mandelbrot.clsp(35):66","94e72f09b749d14a28b0b9194c5394fcbfbd32a3b02fea0059c43d18c93fbf68":"./mandelbrot.clsp(17):17-./mandelbrot.clsp(17):20","9e6282e4f25e370ce617e21d6fe265e88b9e7b8682cf00059b9d128d9381f09d":"./mandelbrot.clsp(35):22-./mandelbrot.clsp(35):27","a88529d773f65ba97447b4af8acecb44062f9c7bf33769f13a5e5da7cdc7cb36":"./mandelbrot.clsp(36):50-./mandelbrot.clsp(36):52","7b9ac78486f7f4666f9baabcb44c2fa03059ddd4d0117378d84701deea9a38ce":"./mandelbrot.clsp(54):10-./mandelbrot.clsp(54):18","1048bd8314983bb84e47e9aefcc19aebc02d18271865659b37334bc60d428649":"./mandelbrot.clsp(18):22","f8821498f37c4f9616b227ddee128d4af97c34a6acd60c03ee4de2cbbf67ce0b":"./mandelbrot.clsp(35):67","943538e8aa6684606bd41d2b41f8c89783362c028fdf0f5ae3628e9442d4c2ab":"./mandelbrot.clsp(23):23","aea5e413ae6095893ff41a597f3fe2d08b55183f66aa1dddecf60379adad117c":"./mandelbrot.clsp(44):22-./mandelbrot.clsp(44):25","d31ed87c874e69ab40250e76d667738308301e3576fb7fa97464c230fe7bff09":"./mandelbrot.clsp(49):49-./mandelbrot.clsp(49):51","bc5959f43bc6e47175374b6716e53c9a7d72c59424c821336995bad760d9aeb3":"./mandelbrot.clsp(49):69-./mandelbrot.clsp(49):71","73bfff796ce0e83c7e33d2d1de730d69dbfbb28df9d59c771f0885dc651d5d02":"*macros*(7):33","2ce7d33e136c99843bc914384f1380620ab94d370cac6f37ba643190bcead691":"./mandelbrot.clsp(16):8-./mandelbrot.clsp(16):11","87ec3945171fd30b58f49aeb8768ed84fbbaaf3ba1c1f6ad10b47b4488750187":"./mandelbrot.clsp(24):48","6016333f3edd7ea4bab8509a314ef22d871fd3b3d7cb993054edcafd42f213dd":"./mandelbrot.clsp(22):23","63865961097d9653bdb0cd3720f44d95e40f56c2ec16e31fc26c534aaee2a884":"./mandelbrot.clsp(35):71-./mandelbrot.clsp(35):73","f359b3ad74817ef67e453957f4ef79e41a0a45a7c412a0e3c9bbd1020761adf1":"./mandelbrot.clsp(17):17-./mandelbrot.clsp(17):20","b25b1da71a74dead84c50033b1b26db4ea4022340544694fc2b807f189ba7815":"./mandelbrot.clsp(54):4-./mandelbrot.clsp(54):9","bc8ae71034c92b6682c97bd2a66219d05057458d1f73d9ee4a8905a04f4b27e0":"./mandelbrot.clsp(49):16-./mandelbrot.clsp(49):29","4580bcbb5d6102ec056777f1bf13f724b1912f27f7c502519e38c1344a07c87a":"./mandelbrot.clsp(44):18","dbe726e81a7221a385e007ef9e834a975a4b528c6f55a5d2ece288bee831a3d1":"./mandelbrot.clsp(37):13-./mandelbrot.clsp(37):20","ac9103f5282051571e5447dc82e8eb2c6b89a4bd56df3e6038e0ca036e93ba58":"./mandelbrot.clsp(11):29","52b5329430d1157b29c2a79df810dc2d6bb79b6683e3e26d1925eec1bb55cfc6":"./mandelbrot.clsp(35):69","f4b17c2d3d6b94253cb61a6fc619ee58e2ed34ff729d8d64a86d02da29c82dd9":"./mandelbrot.clsp(2):1-./mandelbrot.clsp(2):5","4756c6d16e9cd878a37cefeedfc8fa380fa935227eda6d4ac37983d36b3ee7a2":"stringify-row","867de77504b7d142e2528855a2931d0a55581a538f9cbfd9b17f58857d59f82b":"./mandelbrot.clsp(49):16-./mandelbrot.clsp(49):29","dde55600d50418ee692b84129d0511e805d5e317e5852a3afc6904c3c7aec4ea":"./mandelbrot.clsp(54):20-./mandelbrot.clsp(54):33","9b99edc96bbd13f5ba77dbea545943086e3c1bb06f5e379733c7493ce3deda65":"./mandelbrot.clsp(49):46-./mandelbrot.clsp(49):48","ca99ad4b2c3f54fed58ab8d6b46305d257e7724ecbf766af21fe592b303931e3":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):25","5df7504bc193ee4c3deadede1459eccca172e87cca35e81f11ce14be5e94acaf":"./mandelbrot.clsp(49):64-./mandelbrot.clsp(49):68","54118bd7409dddc9c343a6c39b0d459fa427f3de1729ca2305e7175ceee0d777":"./mandelbrot.clsp(34):12-./mandelbrot.clsp(34):14","d9029c8a6ecce948feb41869f7c44c6abe79c943101b23f8e2b5a9798c69bfce":"./mandelbrot.clsp(54):20-./mandelbrot.clsp(54):33","3bf487f927475571f0f787b1bad2fb2223831b27ce62b1639b897ba4a7deffa3":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):27","6c8c938018dc7eb21b1b2968ee6795893d308f2ae6cb19e34d644b89d1d9bb23":"*macros*(2):30","ae6e7ecb050bacd9132845906ccb1b1695508aa3b3ab9e8dd2cfc3b04a4c7055":"./mandelbrot.clsp(49):31-./mandelbrot.clsp(49):45","c783e31d1b575246fc592a0b7369166c666da61fd132156612787fae6568792b":"./mandelbrot.clsp(49):64-./mandelbrot.clsp(49):68","5dad34896875f6daf7b967625bf6aac00b454bb1337abff61ad41845444f4316_left_env":"1","0b57824abfb9582bd84d117dce0e060d6c930a99f178f490f61ee9aba5b55e13":"./mandelbrot.clsp(11):31","dc88dedb475e3b334f03ed9e4d61dd5528425198f9a243ae7f02617146412f36":"./mandelbrot.clsp(18):17-./mandelbrot.clsp(18):20","f32debb6d08ebcd3beafb0a065952d2579b39460f38ed8ca303c1e179c558898":"./mandelbrot.clsp(49):31-./mandelbrot.clsp(49):45","0df44b8f5cb8c2643b7e4d639689ff6a024c02b22ea9f71c80367fd8f889f1e0":"./mandelbrot.clsp(20):12","02b1ce3afa5f79e10e82c58322dc8a71352a2f219f13c9f587b460a2a59b932b":"./mandelbrot.clsp(23):23","c7d594f0a4193e3de597b1d675290c9cd66d99b5bceb67f3ca67d161f329d2d3":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):33","a8d5dd63fba471ebcb1f3e8f7c1e1879b7152a6e7298a91ce119a63400ade7c5":"./mandelbrot.clsp(49):90-./mandelbrot.clsp(49):94","63e093fee19d7defbec9edf55fb05e77185392445ce851d2cad3e2cd945cbd6e":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):25","dbb2bd6129db16922f214018983188da1f74546182491757cb6bae962a23248b":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):30","bfd0ac66e7e972108ce0fec4daa87bbc7edfc460511ea5df04e20fd40e2cd3ae":"./mandelbrot.clsp(54):35-./mandelbrot.clsp(54):39","905ca1d302a6c2f6aca2e1a1c6cf87e9420d8442b3803b448589b8cba66d4f5a":"*macros*(2):27","258ca94b68b2d818eb542f0fbd4b1e72df2cbd7a8f600e75bce8a89a715b6e41":"./mandelbrot.clsp(35):71-./mandelbrot.clsp(35):73","39c49587062166a79c55da9855a916587506ee87b66d84f2e32d84c1a7fa06ac":"./mandelbrot.clsp(35):54-./mandelbrot.clsp(35):66","7ce7ee01c7feafbba2d8da264881cdc2214c9edfff17c2ac7347f5262627b0e6":"./mandelbrot.clsp(48):12-./mandelbrot.clsp(48):14","d69be10416fb29ad0515fcfd94b0ee91ed3e8c89fe48871085e20a5250ac31b9":"./mandelbrot.clsp(49):69-./mandelbrot.clsp(49):71","2ee8bf5211e8deeaa66d444d1ccdfd7ae3921b8cc9039ccc01924884f64f4585":"./mandelbrot.clsp(49):64-./mandelbrot.clsp(49):68","7d370012bbc0b92777eaea27351b943ecac797af623f43e9651fcc08d77d48bb":"./mandelbrot.clsp(54):35-./mandelbrot.clsp(54):39","1e69ab8b04b2824c3fa1c4d7cb9eb9cb464fe3507ed3c153feda00fca2afb749":"./mandelbrot.clsp(8):43","c79b932e1e1da3c0e098e5ad2c422937eb904a76cf61d83975a74a68fbb04b99":"*prims*(1):1","fbec97a5f73546ed8eb86dd0b27e751f5811982e51328d44a11ca3d0d30123e4":"./mandelbrot.clsp(22):23","827af7172f157da208fb79733b5fceaa4b4a11ce8d8afce55a0e1237eb3cb906":"*macros*(2):30","6378d2cf7162395d6933367f2456e505d5da7da3c4557c58f19810965093a8c7":"./mandelbrot.clsp(49):73","0449ba2bae061ff636ee27fb882dc943f4b51ef66a880e20af033086065f17b7":"*macros*(2):27","c1873f940d1223d1d61f1f34d22457bb6613d95d7f72a640bd6a0bd1c152f83b":"./mandelbrot.clsp(54):4-./mandelbrot.clsp(54):9","7f4e0f9648a6705b92711aff33e6175be45b2ad34d7ac1fc738c97ae8b2b1f24":"./mandelbrot.clsp(19):17","51608d9cdfe6393b9f8c87fe23f960e3c093f70b323a6b801c1b5be408a35720":"./mandelbrot.clsp(5):3-./mandelbrot.clsp(5):15","744df121e99a3c9c89b6f14e7e4768872be48db3340ecc36adbfefc8e2a97962":"./mandelbrot.clsp(54):4-./mandelbrot.clsp(54):9","01b525cb2a6f8b763e77022a97c4519051dda3513955151bae305b63285071ca":"./mandelbrot.clsp(35):54-./mandelbrot.clsp(35):66","f4a150250cbe8ea6d65add7a7ee4020dac27113618fae4cbdb07fb3a682925d6":"./mandelbrot.clsp(49):75-./mandelbrot.clsp(49):79","dce37f3512b6337d27290436ba9289e2fd6c775494c33668dd177cf811fbd47a":"./mandelbrot.clsp(49):16-./mandelbrot.clsp(49):29","833ef47e743bbb86130af630a59a85c9ad3c515855102a975069fccc360f3cc8":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):25","4e023b2595ce01ffe9cbce4caafb54190eaf066dede85d065cbdc2875cfe0fdc":"./mandelbrot.clsp(54):4-./mandelbrot.clsp(54):9","c4c1ddb5716001cda175ca5c0ac25c14b4522f6cffe1cc5f7d81dd449ae00994":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):25","324d9a0fa7a7f95e4297c91c21f9a8d74e632047b94c2836c5b694a2e3e5419b":"./mandelbrot.clsp(49):52-./mandelbrot.clsp(49):54","0d989d311d6ece516d4f7b5944d4348dfa7ccc35204026420ee6e7381a59627c":"./mandelbrot.clsp(23):23","57481c14bfbbd6d7dbc587cdc0abedd960905f44cf13e2f548c4e19a58a242f0":"./mandelbrot.clsp(37):13-./mandelbrot.clsp(37):20","18e249e71e10d67d4f5d3fad5ac2999f26e27e3df94576bd48a74eaf6e8d3ccb":"./mandelbrot.clsp(18):22","0f91a6e15f8cb3e8e7ee09b736d856b5b3e9913254e87ed3b613fe4c08ffd04f":"*macros*(2):27","d0aa45f753fb9381e2ffffc321e1d14ddf3e93923eb5100bc63ac9a754f57be0":"./mandelbrot.clsp(49):64-./mandelbrot.clsp(49):68","47e4cfd46afccae981bf5d31a52b54029a60004f67ecd00f8b1858c956478ea1":"./mandelbrot.clsp(54):20-./mandelbrot.clsp(54):33","687d0de30bbdc157324f88bbcafa8bd84555c9ea63e2cf2aed50c71752b3a85e":"./mandelbrot.clsp(54):4-./mandelbrot.clsp(54):9","3bc1653dfbbf56863fd7a9d0532fbd1633755290029ef8f9bd63cb871f274aec":"*macros*(2):30","cb207bf0bf7469a53b6f3b0c41068e3a64e9bb2d906d4eb2d75343c6ddcb9485":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):33","4cee7c983848ae872f01b0f9e2cef01c776e433a48610c1a7e1f2c90eccfda46":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):30","c8f59113bc243854fec80dc25f13f53f037f9e51bcffdb54f57a21a629faeb13":"./mandelbrot.clsp(37):13-./mandelbrot.clsp(37):20","5c5f52d1d391b199eeada24f10c541bd01cb1065e512d9d9f17ab6bdfe242039":"./mandelbrot.clsp(44):15","3113de2dae47a7ca5fbe05c1fd3eadf2dde2ab329c779fbfd002388397c77920":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):35","67ce499a67ca76b487fe30c7ecf2556aed3a8bf65c75d72e086762d150ce9bfd":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):27","50acb7be79414d83f2c3cc2ab670b5e4d63cb833722e4afca1724cf6d8485eb8":"./mandelbrot.clsp(11):11-./mandelbrot.clsp(11):17","49c3235d881de538389729a5c716a882d104f6549ddfcb6e4c877500c5bcc450":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):33","4db25e31c1a9360861bfe10f7084ea70c98b97d6d041af9fe29ed2241ceef64f":"./mandelbrot.clsp(49):31-./mandelbrot.clsp(49):45","a3b3c5caf5eb78446c4bbce572a96b8cf3ea11d849dcbd8f8de7c64e67024533":"./mandelbrot.clsp(37):13-./mandelbrot.clsp(37):20","2bc736ac1df0c934c54fd0b436579b51958ff5aab99a513f6ca7913d9b9577f5":"./mandelbrot.clsp(35):22-./mandelbrot.clsp(35):27","27e648b49d240e1661611be90aec9fab35b96a1ed089b3c7c1dd4ef1543d7f0c":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):33","3717dc9b0e51dd5200d8d20a71f5949fb9bd4c8e041c6e8aac0d9386df2a5ae6":"./mandelbrot.clsp(54):40-./mandelbrot.clsp(54):42","2fd44dc17723eca0691884d8fc135e52824584231e5325d0d8ddc8c09877f20a":"basic-scanline","3f825a6ad7963cb166e559072469b8ee88e4e513e3d30f7f85117713473fbd63":"./mandelbrot.clsp(54):4-./mandelbrot.clsp(54):9","7cc8bb90648baa3abc349be36768805d9c246d008d973d0868cd71878d39b91a":"./mandelbrot.clsp(14):23-./mandelbrot.clsp(14):35"} \ No newline at end of file diff --git a/resources/tests/more_exhaustive/lambda_cse_1.clsp b/resources/tests/more_exhaustive/lambda_cse_1.clsp new file mode 100644 index 000000000..0fb2c2939 --- /dev/null +++ b/resources/tests/more_exhaustive/lambda_cse_1.clsp @@ -0,0 +1,9 @@ +(mod (A B) + (include *standard-cl-23*) + (defun F (X Y) + (let ((L (lambda ((& X Y) Z) (* Z (* X Y))))) + (* (a L (list X)) (* X Y)) + ) + ) + (F A B) + ) diff --git a/resources/tests/more_exhaustive/lambda_cse_1_desugared_form.clsp b/resources/tests/more_exhaustive/lambda_cse_1_desugared_form.clsp new file mode 100644 index 000000000..95cd90123 --- /dev/null +++ b/resources/tests/more_exhaustive/lambda_cse_1_desugared_form.clsp @@ -0,0 +1,8 @@ +(mod (A B) + (include *standard-cl-23*) + (defun lambda_$_53 ((cse_$_50 X_$_46 Y_$_47) Z_$_49) (* Z_$_49 cse_$_50)) + (defun-inline letbinding_$_52 (((X_$_46 Y_$_47) cse_$_50) L_$_48) (* (a L_$_48 (4 X_$_46 ())) cse_$_50)) + (defun letbinding_$_51 ((X_$_46 Y_$_47) cse_$_50) (letbinding_$_52 (r @) (4 2 (4 (4 1 lambda_$_53) (4 (4 4 (4 (4 1 (4 cse_$_50 (c X_$_46 (c Y_$_47 (q))))) (4 1 (q)))) (q)))))) + (defun F (X_$_46 Y_$_47) (letbinding_$_51 (r @) (* X_$_46 Y_$_47))) + (F A B) + ) diff --git a/resources/tests/more_exhaustive/lambda_cse_1_optimized_form.clsp b/resources/tests/more_exhaustive/lambda_cse_1_optimized_form.clsp new file mode 100644 index 000000000..443a0049c --- /dev/null +++ b/resources/tests/more_exhaustive/lambda_cse_1_optimized_form.clsp @@ -0,0 +1,11 @@ +(mod (A B) + (include *standard-cl-23*) + (defun F (X_$_37 Y_$_38) + (let ((cse_$_41 (* X_$_37 Y_$_38))) + (let ((L_$_39 (lambda ((& cse_$_41 X_$_37 Y_$_38) Z_$_40) (* Z_$_40 cse_$_41)))) + (* (a L_$_39 (4 X_$_37 ())) cse_$_41) + ) + ) + ) + (F A B) + ) diff --git a/resources/tests/more_exhaustive/lambda_cse_desugar_2.clsp b/resources/tests/more_exhaustive/lambda_cse_desugar_2.clsp new file mode 100644 index 000000000..20f6b4f1a --- /dev/null +++ b/resources/tests/more_exhaustive/lambda_cse_desugar_2.clsp @@ -0,0 +1,10 @@ +(mod (A B) + (include *standard-cl-23*) + + (defun F (X_$_37_$_17 Y_$_38_$_18) (letbinding_$_56 (r @) (* X_$_37_$_17 Y_$_38_$_18))) + (defun-inline letbinding_$_56 ((X_$_37_$_17 Y_$_38_$_18) cse_$_41_$_19) + (letbinding_$_57 (c (c X_$_37_$_17 (c Y_$_38_$_18 ())) (c cse_$_41_$_19 ())) (4 2 (4 (4 1 lambda_$_58) (4 (4 4 (4 (4 1 (c cse_$_41_$_19 (c X_$_37_$_17 (c Y_$_38_$_18 (q))))) (4 1 (q)))) (q)))))) + (defun lambda_$_58 ((cse_$_41_$_19 X_$_37_$_17 Y_$_38_$_18) Z_$_40_$_20_$_21) (* Z_$_40_$_20_$_21 cse_$_41_$_19)) + (defun letbinding_$_57 (((X_$_37_$_17 Y_$_38_$_18) cse_$_41_$_19) L_$_39) (* (a L_$_39 (4 X_$_37_$_17 ())) cse_$_41_$_19)) + (F A B) + ) diff --git a/resources/tests/more_exhaustive/lambda_cse_simple_desugar_1.clsp b/resources/tests/more_exhaustive/lambda_cse_simple_desugar_1.clsp new file mode 100644 index 000000000..d31279044 --- /dev/null +++ b/resources/tests/more_exhaustive/lambda_cse_simple_desugar_1.clsp @@ -0,0 +1,6 @@ +(mod (A B) + (include *standard-cl-23*) + (defun letbinding_$_51 ((X_$_46 Y_$_47) cse_$_50) (list X_$_46 Y_$_47 cse_$_50)) + (defun F (X_$_46 Y_$_47) (letbinding_$_51 (r @) (* X_$_46 Y_$_47))) + (F A B) + ) diff --git a/resources/tests/more_exhaustive/lambda_cse_simple_desugar_2.clsp b/resources/tests/more_exhaustive/lambda_cse_simple_desugar_2.clsp new file mode 100644 index 000000000..95cd90123 --- /dev/null +++ b/resources/tests/more_exhaustive/lambda_cse_simple_desugar_2.clsp @@ -0,0 +1,8 @@ +(mod (A B) + (include *standard-cl-23*) + (defun lambda_$_53 ((cse_$_50 X_$_46 Y_$_47) Z_$_49) (* Z_$_49 cse_$_50)) + (defun-inline letbinding_$_52 (((X_$_46 Y_$_47) cse_$_50) L_$_48) (* (a L_$_48 (4 X_$_46 ())) cse_$_50)) + (defun letbinding_$_51 ((X_$_46 Y_$_47) cse_$_50) (letbinding_$_52 (r @) (4 2 (4 (4 1 lambda_$_53) (4 (4 4 (4 (4 1 (4 cse_$_50 (c X_$_46 (c Y_$_47 (q))))) (4 1 (q)))) (q)))))) + (defun F (X_$_46 Y_$_47) (letbinding_$_51 (r @) (* X_$_46 Y_$_47))) + (F A B) + ) diff --git a/resources/tests/rps-referee-uncaptured.clsp b/resources/tests/rps-referee-uncaptured.clsp new file mode 100644 index 000000000..1dcf38858 --- /dev/null +++ b/resources/tests/rps-referee-uncaptured.clsp @@ -0,0 +1,29 @@ +(mod ((VALIDATION_PROGRAM_HASH AMOUNT) action . args) + + (include *standard-cl-21*) + + (defun reduce (fun lst init) + (if lst + (reduce fun (r lst) (a fun (list (f lst) init))) + init + ) + ) + + (let + ((new_puzzle_hash 38911) + ) + (reduce + (lambda ((@ condition (condname arg1 arg2)) agg) + (if agg + 1 + (if (= condname CREATE_COIN) + (logand (= arg1 new_puzzle_hash) (= arg2 AMOUNT)) + 0 + ) + ) + ) + conditions + 0 + ) + ) + ) diff --git a/resources/tests/rps-referee.clsp b/resources/tests/rps-referee.clsp new file mode 100644 index 000000000..38741b09f --- /dev/null +++ b/resources/tests/rps-referee.clsp @@ -0,0 +1,29 @@ +(mod ((VALIDATION_PROGRAM_HASH AMOUNT) action . args) + + (include *standard-cl-21*) + + (defun reduce (fun lst init) + (if lst + (reduce fun (r lst) (a fun (list (f lst) init))) + init + ) + ) + + (let + ((new_puzzle_hash 38911) + ) + (reduce + (lambda ((& AMOUNT new_puzzle_hash) (@ condition (condname arg1 arg2)) agg) + (if agg + 1 + (if (= condname CREATE_COIN) + (logand (= arg1 new_puzzle_hash) (= arg2 AMOUNT)) + 0 + ) + ) + ) + conditions + 0 + ) + ) + ) diff --git a/resources/tests/simple_deinline_case_23.clsp b/resources/tests/simple_deinline_case_23.clsp new file mode 100644 index 000000000..2dd68fae8 --- /dev/null +++ b/resources/tests/simple_deinline_case_23.clsp @@ -0,0 +1,8 @@ +(mod (X) + (include *standard-cl-23*) + (defconstant Z 1000000) + (let + ((X1 (+ X Z))) + (+ X1 X1 X1 X1 X1 X1) + ) + ) diff --git a/resources/tests/strict/append.clinc b/resources/tests/strict/append.clinc new file mode 100644 index 000000000..885a90bb2 --- /dev/null +++ b/resources/tests/strict/append.clinc @@ -0,0 +1,8 @@ +( + (defun append (L R) + (if L + (c (f L) (append (r L) R)) + R + ) + ) +) \ No newline at end of file diff --git a/resources/tests/strict/assert.clsp b/resources/tests/strict/assert.clsp new file mode 100644 index 000000000..cf9a3801e --- /dev/null +++ b/resources/tests/strict/assert.clsp @@ -0,0 +1,11 @@ +(mod (A) + (include *strict-cl-21*) + + (include defmac_assert.clib) + + (assert + 1 + A + 13 + ) + ) diff --git a/resources/tests/strict/assert23.clsp b/resources/tests/strict/assert23.clsp new file mode 100644 index 000000000..1a9d8ff39 --- /dev/null +++ b/resources/tests/strict/assert23.clsp @@ -0,0 +1,11 @@ +(mod (A) + (include *standard-cl-23*) + + (include defmac_assert.clib) + + (assert + 1 + A + 13 + ) + ) diff --git a/resources/tests/strict/atomsort.clinc b/resources/tests/strict/atomsort.clinc new file mode 100644 index 000000000..1eb66c9d7 --- /dev/null +++ b/resources/tests/strict/atomsort.clinc @@ -0,0 +1,53 @@ +( + (defun merge (a b) + (if (not a) + b + (if (not b) + a + (if (> (f a) (f b)) + (c (f a) (merge (r a) b)) + (c (f b) (merge a (r b))) + ) + ) + ) + ) + + ;; Sorts atoms into descending order + ;; This is optimized for sorting short lists + ;; A more general function would return a list of lists of ascending sizes + ;; to be merged + (defun atomsort ((@ firstpos (first @ secondpos (second @ thirdpos (third . remaining))))) + (if firstpos + (if secondpos + (if thirdpos + (assign-lambda + mylist + (if (> first second) + (if (> second third) + (list first second third) + (if (> first third) + (list first third second) + (list third first second) + ) + ) + (if (> first third) + (list second first third) + (if (> second third) + (list second third first) + (list third second first) + ) + ) + ) + (merge mylist (atomsort remaining)) + ) + (if (> first second) + firstpos + (list second first) + ) + ) + firstpos + ) + 0 + ) + ) +) diff --git a/resources/tests/strict/big-maybe.clsp b/resources/tests/strict/big-maybe.clsp new file mode 100644 index 000000000..e40e180be --- /dev/null +++ b/resources/tests/strict/big-maybe.clsp @@ -0,0 +1,9 @@ +(mod (p) + + (include *standard-cl-23*) + + (defun fromMaybe (v (@ m (content))) (if m content v)) + (defun mapMaybe (f (@ m (content))) (if m (list (a f (list content))) ())) + + (fromMaybe 0 (mapMaybe (lambda ((@ pt (x y))) (+ x y)) p)) + ) diff --git a/resources/tests/strict/chialisp-web-example.clsp b/resources/tests/strict/chialisp-web-example.clsp new file mode 100644 index 000000000..1caf8427c --- /dev/null +++ b/resources/tests/strict/chialisp-web-example.clsp @@ -0,0 +1,71 @@ + (mod (X) + + ;; Specify that this program is compiled with *standard-cl-23*. + ;; After release, the chialisp compiler guarantees that programs + ;; with a specific sigil (including no sigil) compile to the + ;; same representation forever (it is a bug that must be fixed + ;; if a program changes representation in a future compiler + ;; release). In this way, program source code can also provide + ;; enough information to re-produce a puzzle hash from source + ;; code. + (include *standard-cl-23*) + + (defun n-additions-inner (n value i) + (if (> i n) + () + (qq (c (+ (unquote i) (unquote value)) (unquote (n-additions-inner n value (+ 1 i))))) + ) + ) + + (defmac n-additions (n value) (n-additions-inner n value 1)) + + (defun F (X) (n-additions 3 X)) + + (defun odd (X) (logand X 1)) + + ;; Usual higher order functions work like you might hope. + ;; This filter function takes a predicate, "pred", which + ;; returns a truthy value to include the result or nil. + ;; (@ lst (first . rest)) is similar to a similar + ;; destructuring form in haskell. + ;; (@ lst (first . rest)) + ;; generates the same bindings as simultaneously having + ;; (pred lst) + ;; and + ;; (pred (first . rest)) + ;; as an argument list. + (defun filter (pred (@ lst (first . rest))) + (if lst + (if (a pred (list first)) + (c first (filter pred rest)) + (filter pred rest) + ) + () + ) + ) + + ;; @ destructuring here takes the place of the + ;; whole argument list. + (defun sum (@ the-list (first . rest)) + (if the-list + (+ first (a sum rest)) + 0 + ) + ) + + (assign + ;; We can destructure the result based on its shape. + ;; Assign reorders and groups assignments based on their dependencies. + (A B C) result-list + + ;; The bindings can be in any order, like the let forms in elm, haskell + ;; and others. + result-list (F X) + + summed (a sum result-list) + odds (filter odd result-list) + + ;; Result of this form. + (list summed odds) + ) + ) diff --git a/resources/tests/strict/cse-complex-1-lambda.clsp b/resources/tests/strict/cse-complex-1-lambda.clsp new file mode 100644 index 000000000..7e2c62202 --- /dev/null +++ b/resources/tests/strict/cse-complex-1-lambda.clsp @@ -0,0 +1,33 @@ +(mod (X) + (include *standard-cl-23*) + + (defun mess (X) ;; 11 41 + (assign + Y (+ X 1) ;; 12 42 + Z (+ Y 2) ;; 14 44 + + (if (> X 10) + (lambda ((& X Y Z) Q) + (if (= X 11) + (assign + Y (* X 2) ;; 22 82 + Z (+ Y 1) ;; 23 83 + + (* Q Y Z) ;; 11 * 22 * 23 = 506 + ) + + (assign + Y (* X 3) ;; 33 123 + Z (+ Y 2) ;; 35 125 + + (* Q Y Z) ;; 41 * 123 * 125 = 630375 + ) + ) + ) + (lambda ((& Y Z) Q) (* Q Y Z)) ;; 5 * 6 * 8 + ) + ) + ) + + (a (mess X) (list X)) + ) diff --git a/resources/tests/strict/cse-complex-1.clsp b/resources/tests/strict/cse-complex-1.clsp new file mode 100644 index 000000000..29b69a214 --- /dev/null +++ b/resources/tests/strict/cse-complex-1.clsp @@ -0,0 +1,28 @@ +(mod (X) + (include *standard-cl-23*) + + (defun mess (X) ;; 11 41 + (assign + Y (+ X 1) ;; 12 42 + Z (+ Y 2) ;; 14 44 + + (if (= X 11) + (assign + Y (* X 2) ;; 22 82 + Z (+ Y 1) ;; 23 83 + + (* Y Z) ;; 22 * 23 = 506 + ) + + (assign + Y (* X 3) ;; 33 123 + Z (+ Y 2) ;; 35 125 + + (* Y Z) ;; 123 * 125 = 15375 + ) + ) + ) + ) + + (mess X) + ) diff --git a/resources/tests/strict/cse-test-no-dom.clsp b/resources/tests/strict/cse-test-no-dom.clsp new file mode 100644 index 000000000..32758101d --- /dev/null +++ b/resources/tests/strict/cse-test-no-dom.clsp @@ -0,0 +1,23 @@ +(mod (X) + (include *standard-cl-23*) + + (defun S (C) + (if C + (assign-lambda + Z (f (f C)) + Y (r (f C)) + R (r C) + (if (= Z 2) + (if (= 1 (f Y)) + (r Y) + (S R) + ) + (S R) + ) + ) + () + ) + ) + + (S X) + ) diff --git a/resources/tests/strict/cse_doesnt_dominate.clsp b/resources/tests/strict/cse_doesnt_dominate.clsp new file mode 100644 index 000000000..2c5f1d197 --- /dev/null +++ b/resources/tests/strict/cse_doesnt_dominate.clsp @@ -0,0 +1,10 @@ +(mod (X) + (include *standard-cl-23*) + + ;; (+ X 1) should be an eliminated subexpression but it doesn't dominate the + ;; condition. + (if X + (* (+ X 1) (+ X 1) (+ X 1)) + 17 + ) + ) \ No newline at end of file diff --git a/resources/tests/strict/cse_doesnt_dominate_superior_let.clsp b/resources/tests/strict/cse_doesnt_dominate_superior_let.clsp new file mode 100644 index 000000000..505653d8b --- /dev/null +++ b/resources/tests/strict/cse_doesnt_dominate_superior_let.clsp @@ -0,0 +1,12 @@ +(mod (X) + (include *standard-cl-23*) + + ;; (+ X 1) should be an eliminated subexpression but it doesn't dominate the + ;; condition. + (if X + (let ((Z X)) + (* (+ Z 1) (+ Z 1) (+ Z 1)) + ) + 17 + ) + ) diff --git a/resources/tests/strict/cse_doesnt_dominate_superior_let_iodi.clsp b/resources/tests/strict/cse_doesnt_dominate_superior_let_iodi.clsp new file mode 100644 index 000000000..aa27f8795 --- /dev/null +++ b/resources/tests/strict/cse_doesnt_dominate_superior_let_iodi.clsp @@ -0,0 +1,20 @@ +(mod (X) + (include *standard-cl-23*) + + (defun-inline L (Z X) (* (+ Z 1) (+ Z 1) (+ Z 1) (+ X 1) (+ X 1) (+ X 1))) + + ;; (+ X 1) should be an eliminated subexpression but it doesn't dominate the + ;; condition. + (defun-inline F1 (X) + (let ((Z X)) + (if X + (L Z X) + 17 + ) + ) + ) + + (defun F (X) (F1 X)) + + (F X) + ) diff --git a/resources/tests/strict/cse_doesnt_dominate_superior_let_odi.clsp b/resources/tests/strict/cse_doesnt_dominate_superior_let_odi.clsp new file mode 100644 index 000000000..595a08019 --- /dev/null +++ b/resources/tests/strict/cse_doesnt_dominate_superior_let_odi.clsp @@ -0,0 +1,18 @@ +(mod (X) + (include *standard-cl-23*) + + ;; (+ X 1) should be an eliminated subexpression but it doesn't dominate the + ;; condition. + (defun-inline F1 (X) + (let ((Z X)) + (if X + (* (+ Z 1) (+ Z 1) (+ Z 1) (+ X 1) (+ X 1) (+ X 1)) + 17 + ) + ) + ) + + (defun F (X) (F1 X)) + + (F X) + ) diff --git a/resources/tests/strict/cse_doesnt_dominate_superior_let_outside.clsp b/resources/tests/strict/cse_doesnt_dominate_superior_let_outside.clsp new file mode 100644 index 000000000..1c970b850 --- /dev/null +++ b/resources/tests/strict/cse_doesnt_dominate_superior_let_outside.clsp @@ -0,0 +1,12 @@ +(mod (X) + (include *standard-cl-23*) + + ;; (+ X 1) should be an eliminated subexpression but it doesn't dominate the + ;; condition. + (let ((Z X)) + (if X + (* (+ Z 1) (+ Z 1) (+ Z 1) (+ X 1) (+ X 1) (+ X 1)) + 17 + ) + ) + ) diff --git a/resources/tests/strict/cse_doesnt_dominate_superior_let_outside_in_defun.clsp b/resources/tests/strict/cse_doesnt_dominate_superior_let_outside_in_defun.clsp new file mode 100644 index 000000000..3ed8f182f --- /dev/null +++ b/resources/tests/strict/cse_doesnt_dominate_superior_let_outside_in_defun.clsp @@ -0,0 +1,16 @@ +(mod (X) + (include *standard-cl-23*) + + ;; (+ X 1) should be an eliminated subexpression but it doesn't dominate the + ;; condition. + (defun F (X) + (let ((Z X)) + (if X + (* (+ Z 1) (+ Z 1) (+ Z 1) (+ X 1) (+ X 1) (+ X 1)) + 17 + ) + ) + ) + + (F X) + ) diff --git a/resources/tests/strict/cse_doesnt_dominate_superior_let_outside_in_inline.clsp b/resources/tests/strict/cse_doesnt_dominate_superior_let_outside_in_inline.clsp new file mode 100644 index 000000000..6790877fc --- /dev/null +++ b/resources/tests/strict/cse_doesnt_dominate_superior_let_outside_in_inline.clsp @@ -0,0 +1,16 @@ +(mod (X) + (include *standard-cl-23*) + + ;; (+ X 1) should be an eliminated subexpression but it doesn't dominate the + ;; condition. + (defun-inline F (X) + (let ((Z X)) + (if X + (* (+ Z 1) (+ Z 1) (+ Z 1) (+ X 1) (+ X 1) (+ X 1)) + 17 + ) + ) + ) + + (F X) + ) diff --git a/resources/tests/strict/cse_tricky_assign.clsp b/resources/tests/strict/cse_tricky_assign.clsp new file mode 100644 index 000000000..b77eb7a82 --- /dev/null +++ b/resources/tests/strict/cse_tricky_assign.clsp @@ -0,0 +1,57 @@ +(mod X + + (include *standard-cl-23*) + + (include truncate.clinc) + (include partition.clinc) + (include append.clinc) + + (defun find_hand_indices ((@ numbered-cards ((number . card) . rest))) + (if numbered-cards + (logior (lsh 1 number) (find_hand_indices rest)) + 0 + ) + ) + + (defun number_cards (num cards) + (if cards + (c (c num (f cards)) (number_cards (+ num 1) (r cards))) + () + ) + ) + + ;; Sorts the cards by group size according to hand. + ;; Hand has pairs of count and rank. We pull out cards based on their rank + ;; until each bucket is empty in hand and then give the remaining cards. + (defun bucket_cards_by_frequency_groups (hand cards) + (if hand + (assign + (hand_freq . want_rank) (f hand) + + (cards_with_rank . cards_without_rank) (partition (lambda ((& want_rank) (num . (rank . suit))) (= rank want_rank)) cards) + + ;; We have the cards with this rank... go to the next wanted rank. + (append cards_with_rank (bucket_cards_by_frequency_groups (r hand) cards_without_rank)) + ) + cards + ) + ) + + (defun handcalc (cards sorted_ranks hand firstcount firstrank secondcount secondrank flush_suit) + (if ;; Full house + (logand (= firstcount 3) (= secondcount 2)) + (find_hand_indices (truncate 5 (bucket_cards_by_frequency_groups hand (number_cards 0 cards)))) + + ;; Flush + (if + flush_suit + (find_hand_indices (truncate 5 (bucket_cards_by_frequency_groups hand (number_cards 0 cards)))) + + ;; Else + (find_hand_indices (truncate 5 (bucket_cards_by_frequency_groups hand (number_cards 0 cards)))) + ) + ) + ) + + (handcalc (q (14 . 1) (12 . 1) (11 . 1) (10 . 1) (9 . 1)) (list 14 12 11 10 9) (q (14 . 1) (12 . 1) (11 . 1) (10 . 1) (9 . 1)) 1 14 1 12 1) +) diff --git a/resources/tests/strict/csecond.clsp b/resources/tests/strict/csecond.clsp new file mode 100644 index 000000000..6d82de756 --- /dev/null +++ b/resources/tests/strict/csecond.clsp @@ -0,0 +1,33 @@ +(mod (X) + (include *standard-cl-23*) + + (defun asort ((@ firstpos (first @ secondpos (second @ thirdpos (third . remaining))))) + (if firstpos + (if secondpos + (if thirdpos + (if (> first second) + (if (> first third) + "test1" + (if (> second third) + "test2" + "test3" + ) + ) + (if (> first second) + "test4" + "test5" + ) + ) + (if (> first second) + "test6" + "test7" + ) + ) + firstpos + ) + 0 + ) + ) + + (asort X) + ) diff --git a/resources/tests/strict/defconst.clsp b/resources/tests/strict/defconst.clsp new file mode 100644 index 000000000..97c90794d --- /dev/null +++ b/resources/tests/strict/defconst.clsp @@ -0,0 +1,16 @@ +(mod (Z) + + (include *standard-cl-23*) + ; takes a lisp tree and returns the hash of it + + (defun sha256tree1 (TREE) + (if (l TREE) + (sha256 2 (sha256tree1 (f TREE)) (sha256tree1 (r TREE))) + (sha256 1 TREE) + ) + ) + + (defconst HELLO_HASH (sha256tree1 (c "hello" "world"))) + + (sha256 HELLO_HASH Z) + ) diff --git a/resources/tests/strict/defmac_assert.clib b/resources/tests/strict/defmac_assert.clib new file mode 100644 index 000000000..1dccb32c8 --- /dev/null +++ b/resources/tests/strict/defmac_assert.clib @@ -0,0 +1,10 @@ +( + (defun assert_ (items) + (if (r items) + (qq (if (unquote (f items)) (unquote (assert_ (r items))) (x))) + (f items) + ) + ) + + (defmac assert items (assert_ items)) +) \ No newline at end of file diff --git a/resources/tests/strict/defmac_if_smoke.clsp b/resources/tests/strict/defmac_if_smoke.clsp new file mode 100644 index 000000000..d3baf7cca --- /dev/null +++ b/resources/tests/strict/defmac_if_smoke.clsp @@ -0,0 +1,8 @@ +(mod () + (include *strict-cl-21*) + + (include defmac_simple_if.clib) + + (if_ t1 t2 t3) + ) + \ No newline at end of file diff --git a/resources/tests/strict/defmac_simple_if.clib b/resources/tests/strict/defmac_simple_if.clib new file mode 100644 index 000000000..32655f11f --- /dev/null +++ b/resources/tests/strict/defmac_simple_if.clib @@ -0,0 +1,3 @@ +( + (defmac if_ (C T E) (qq (if (unquote C) (unquote T) (unquote E)))) +) \ No newline at end of file diff --git a/resources/tests/strict/double-constant-fail.clsp b/resources/tests/strict/double-constant-fail.clsp new file mode 100644 index 000000000..7af9d1e23 --- /dev/null +++ b/resources/tests/strict/double-constant-fail.clsp @@ -0,0 +1,24 @@ +(mod (X) + (include *strict-cl-21*) + + ;; A macro-level function to pass through only real integers. + (defun pass-through-integers (X) + (if (not (number? X)) + (x "not a number given to only-integers" X) + X + ) + ) + + ;; A macro which at preprocessing time throws if the given argument + ;; wasn't a lexical integer. + (defmac only-integers (X) (pass-through-integers X)) + + ;; Note: when macro expanding, N is the N argument to the body of + ;; the double macro, not the integer literal, so we use the function + ;; version of pass-through-integers in the macro body. + (defmac double (N) (* 2 (pass-through-integers N))) + + ;; Here the macro form of only-integers can determine whether the + ;; double macro produced an integer or some other expression. + (only-integers (double "hithere")) + ) diff --git a/resources/tests/strict/double-constant-pass-in-function.clsp b/resources/tests/strict/double-constant-pass-in-function.clsp new file mode 100644 index 000000000..a3367039f --- /dev/null +++ b/resources/tests/strict/double-constant-pass-in-function.clsp @@ -0,0 +1,26 @@ +(mod (X) + (include *strict-cl-21*) + + ;; A macro-level function to pass through only real integers. + (defun pass-through-integers (X) + (if (not (number? X)) + (x "not a number given to only-integers" X) + X + ) + ) + + ;; A macro which at preprocessing time throws if the given argument + ;; wasn't a lexical integer. + (defmac only-integers (X) (pass-through-integers X)) + + ;; Note: when macro expanding, N is the N argument to the body of + ;; the double macro, not the integer literal, so we use the function + ;; version of pass-through-integers in the macro body. + (defmac double (N) (* 2 (pass-through-integers N))) + + ;; Here the macro form of only-integers can determine whether the + ;; double macro produced an integer or some other expression. + (defun F (N) (+ N (only-integers (double 99)))) + + (F X) + ) diff --git a/resources/tests/strict/double-constant-pass.clsp b/resources/tests/strict/double-constant-pass.clsp new file mode 100644 index 000000000..7b50bd1ee --- /dev/null +++ b/resources/tests/strict/double-constant-pass.clsp @@ -0,0 +1,24 @@ +(mod (X) + (include *strict-cl-21*) + + ;; A macro-level function to pass through only real integers. + (defun pass-through-integers (X) + (if (not (number? X)) + (x "not a number given to only-integers" X) + X + ) + ) + + ;; A macro which at preprocessing time throws if the given argument + ;; wasn't a lexical integer. + (defmac only-integers (X) (pass-through-integers X)) + + ;; Note: when macro expanding, N is the N argument to the body of + ;; the double macro, not the integer literal, so we use the function + ;; version of pass-through-integers in the macro body. + (defmac double (N) (* 2 (pass-through-integers N))) + + ;; Here the macro form of only-integers can determine whether the + ;; double macro produced an integer or some other expression. + (only-integers (double 99)) + ) diff --git a/resources/tests/strict/embed.clsp b/resources/tests/strict/embed.clsp new file mode 100644 index 000000000..72e3fcca9 --- /dev/null +++ b/resources/tests/strict/embed.clsp @@ -0,0 +1,8 @@ +(mod (Z) + + (include *standard-cl-23*) + + (embed-file hello-data bin "hello.txt") + + (sha256 hello-data Z) + ) diff --git a/resources/tests/strict/hello.txt b/resources/tests/strict/hello.txt new file mode 100644 index 000000000..ce0136250 --- /dev/null +++ b/resources/tests/strict/hello.txt @@ -0,0 +1 @@ +hello diff --git a/resources/tests/strict/includes/condition_codes.clib b/resources/tests/strict/includes/condition_codes.clib new file mode 100644 index 000000000..f8f607ccd --- /dev/null +++ b/resources/tests/strict/includes/condition_codes.clib @@ -0,0 +1,38 @@ +; See chia/types/condition_opcodes.py + +( + (defconstant AGG_SIG_UNSAFE 49) + (defconstant AGG_SIG_ME 50) + + ; the conditions below reserve coin amounts and have to be accounted for in output totals + + (defconstant CREATE_COIN 51) + (defconstant RESERVE_FEE 52) + + ; the conditions below deal with announcements, for inter-coin communication + + ; coin announcements + (defconstant CREATE_COIN_ANNOUNCEMENT 60) + (defconstant ASSERT_COIN_ANNOUNCEMENT 61) + + ; puzzle announcements + (defconstant CREATE_PUZZLE_ANNOUNCEMENT 62) + (defconstant ASSERT_PUZZLE_ANNOUNCEMENT 63) + + ; the conditions below let coins inquire about themselves + + (defconstant ASSERT_MY_COIN_ID 70) + (defconstant ASSERT_MY_PARENT_ID 71) + (defconstant ASSERT_MY_PUZZLEHASH 72) + (defconstant ASSERT_MY_AMOUNT 73) + + ; the conditions below ensure that we're "far enough" in the future + + ; wall-clock time + (defconstant ASSERT_SECONDS_RELATIVE 80) + (defconstant ASSERT_SECONDS_ABSOLUTE 81) + + ; block index + (defconstant ASSERT_HEIGHT_RELATIVE 82) + (defconstant ASSERT_HEIGHT_ABSOLUTE 83) +) diff --git a/resources/tests/strict/includes/curry-and-treehash.clib b/resources/tests/strict/includes/curry-and-treehash.clib new file mode 100644 index 000000000..8f985ffe9 --- /dev/null +++ b/resources/tests/strict/includes/curry-and-treehash.clib @@ -0,0 +1,72 @@ +( + ;; The code below is used to calculate of the tree hash of a curried function + ;; without actually doing the curry, and using other optimization tricks + ;; like unrolling `sha256tree`. + + (defconstant ONE 1) + (defconstant TWO 2) + (defconstant A_KW #a) + (defconstant Q_KW #q) + (defconstant C_KW #c) + + ;; Given the tree hash `environment-hash` of an environment tree E + ;; and the tree hash `parameter-hash` of a constant parameter P + ;; return the tree hash of the tree corresponding to + ;; `(c (q . P) E)` + ;; This is the new environment tree with the addition parameter P curried in. + ;; + ;; Note that `(c (q . P) E)` = `(c . ((q . P) . (E . 0)))` + + (defun-inline update-hash-for-parameter-hash (parameter-hash environment-hash) + (sha256 TWO (sha256 ONE C_KW) + (sha256 TWO (sha256 TWO (sha256 ONE Q_KW) parameter-hash) + (sha256 TWO environment-hash (sha256 ONE 0)))) + ) + + ;; This function recursively calls `update-hash-for-parameter-hash`, updating `environment-hash` + ;; along the way. + + (defun build-curry-list (reversed-curry-parameter-hashes environment-hash) + (if reversed-curry-parameter-hashes + (build-curry-list (r reversed-curry-parameter-hashes) + (update-hash-for-parameter-hash (f reversed-curry-parameter-hashes) environment-hash)) + environment-hash + ) + ) + + ;; Given the tree hash `environment-hash` of an environment tree E + ;; and the tree hash `function-hash` of a function tree F + ;; return the tree hash of the tree corresponding to + ;; `(a (q . F) E)` + ;; This is the hash of a new function that adopts the new environment E. + ;; This is used to build of the tree hash of a curried function. + ;; + ;; Note that `(a (q . F) E)` = `(a . ((q . F) . (E . 0)))` + + (defun-inline tree-hash-of-apply (function-hash environment-hash) + (sha256 TWO (sha256 ONE A_KW) + (sha256 TWO (sha256 TWO (sha256 ONE Q_KW) function-hash) + (sha256 TWO environment-hash (sha256 ONE 0)))) + ) + + ;; function-hash: + ;; the hash of a puzzle function, ie. a `mod` + ;; + ;; reversed-curry-parameter-hashes: + ;; a list of pre-hashed trees representing parameters to be curried into the puzzle. + ;; Note that this must be applied in REVERSED order. This may seem strange, but it greatly simplifies + ;; the underlying code, since we calculate the tree hash from the bottom nodes up, and the last + ;; parameters curried must have their hashes calculated first. + ;; + ;; we return the hash of the curried expression + ;; (a (q . function-hash) (c (cp1 (c cp2 (c ... 1)...)))) + ;; + ;; Note that from a user's perspective the hashes passed in here aren't simply + ;; the hashes of the desired parameters, but their treehash representation since + ;; that's the form we're assuming they take in the acutal curried program. + + (defun puzzle-hash-of-curried-function (function-hash . reversed-curry-parameter-hashes) + (tree-hash-of-apply function-hash + (build-curry-list reversed-curry-parameter-hashes (sha256 ONE ONE))) + ) +) diff --git a/resources/tests/strict/includes/singleton_truths.clib b/resources/tests/strict/includes/singleton_truths.clib new file mode 100644 index 000000000..fe673eedc --- /dev/null +++ b/resources/tests/strict/includes/singleton_truths.clib @@ -0,0 +1,21 @@ +( + (defun-inline truth_data_to_truth_struct (my_id full_puzhash innerpuzhash my_amount lineage_proof singleton_struct) (c (c my_id full_puzhash) (c (c innerpuzhash my_amount) (c lineage_proof singleton_struct)))) + + (defun-inline my_id_truth (Truths) (f (f Truths))) + (defun-inline my_full_puzzle_hash_truth (Truths) (r (f Truths))) + (defun-inline my_inner_puzzle_hash_truth (Truths) (f (f (r Truths)))) + (defun-inline my_amount_truth (Truths) (r (f (r Truths)))) + (defun-inline my_lineage_proof_truth (Truths) (f (r (r Truths)))) + (defun-inline singleton_struct_truth (Truths) (r (r (r Truths)))) + + (defun-inline singleton_mod_hash_truth (Truths) (f (singleton_struct_truth Truths))) + (defun-inline singleton_launcher_id_truth (Truths) (f (r (singleton_struct_truth Truths)))) + (defun-inline singleton_launcher_puzzle_hash_truth (Truths) (f (r (r (singleton_struct_truth Truths))))) + + (defun-inline parent_info_for_lineage_proof (lineage_proof) (f lineage_proof)) + (defun-inline puzzle_hash_for_lineage_proof (lineage_proof) (f (r lineage_proof))) + (defun-inline amount_for_lineage_proof (lineage_proof) (f (r (r lineage_proof)))) + (defun-inline is_not_eve_proof (lineage_proof) (r (r lineage_proof))) + (defun-inline parent_info_for_eve_proof (lineage_proof) (f lineage_proof)) + (defun-inline amount_for_eve_proof (lineage_proof) (f (r lineage_proof))) +) \ No newline at end of file diff --git a/resources/tests/strict/map-example.clsp b/resources/tests/strict/map-example.clsp new file mode 100644 index 000000000..79eb30dff --- /dev/null +++ b/resources/tests/strict/map-example.clsp @@ -0,0 +1,15 @@ +(mod (Z) + + (include *standard-cl-23*) + + (defun add-one (X) (+ X 1)) + + (defun map (F L) + (if L + (c (a F (list (f L))) (map F (r L))) + () + ) + ) + + (map add-one Z) + ) diff --git a/resources/tests/strict/partition.clinc b/resources/tests/strict/partition.clinc new file mode 100644 index 000000000..8c8c268f6 --- /dev/null +++ b/resources/tests/strict/partition.clinc @@ -0,0 +1,15 @@ +( + (defun partition_inner (matched not-matched F L) + (if L + (if (a F (list (f L))) + (partition_inner (c (f L) matched) not-matched F (r L)) + (partition_inner matched (c (f L) not-matched) F (r L)) + ) + (c matched not-matched) + ) + ) + + (defun partition (F L) + (partition_inner () () F L) + ) +) diff --git a/resources/tests/strict/rosetta_code_abc.clsp b/resources/tests/strict/rosetta_code_abc.clsp new file mode 100644 index 000000000..d460f8ea2 --- /dev/null +++ b/resources/tests/strict/rosetta_code_abc.clsp @@ -0,0 +1,76 @@ +;; Adapted from https://rosettacode.org/wiki/ABC_problem#Scheme +(mod (word) + + (include *standard-cl-23*) + + (defconst *blocks* + (list + (c "B" "O") (c "X" "K") (c "D" "Q") (c "C" "P") (c "N" "A") + (c "G" "T") (c "R" "E") (c "T" "G") (c "Q" "D") (c "F" "S") + (c "J" "W") (c "H" "U") (c "V" "I") (c "A" "N") (c "O" "B") + (c "E" "R") (c "F" "S") (c "L" "Y") (c "P" "C") (c "Z" "M"))) + + (defun-inline block-member (e s) + (logior (= e (f s)) (= e (r s))) + ) + + ;; Make short-circuiting and. + (defun and_ (CLAUSES) + (if (r CLAUSES) + (qq (if (unquote (f CLAUSES)) (unquote (and_ (r CLAUSES))) ())) + (f CLAUSES) + ) + ) + + (defmac and CLAUSES (if CLAUSES (and_ CLAUSES) 1)) + + ;; Make short-circuiting or. + (defun or_ (CLAUSES) + (if (r CLAUSES) + (qq (if (unquote (f CLAUSES)) 1 (unquote (or_ (r CLAUSES))))) + (f CLAUSES) + ) + ) + + (defmac or CLAUSES (if CLAUSES (or_ CLAUSES) ())) + + (defun exists (p? li) + (and li (or (a p? (list (f li))) (exists p? (r li)))) + ) + + (defun remove-one (x li) + (or + (not li) + (if (and (= (f (f li)) (f x)) (= (r (f li)) (r x))) + (r li) + (c (f li) (remove-one x (r li))) + ) + ) + ) + + (defun can-make-list? (li blocks) + (or + (not li) + (exists + (lambda ((& li blocks) block) + (and + (block-member (f li) block) + (can-make-list? (r li) (remove-one block blocks)) + ) + ) + blocks + ) + ) + ) + + (defun can-make-word? (word) (can-make-list? word *blocks*)) + + (defun wordify (W) + (if W + (c (substr W 0 1) (wordify (substr W 1))) + () + ) + ) + + (can-make-word? (wordify word)) + ) diff --git a/resources/tests/strict/rosetta_code_abc_preprocessed.clsp b/resources/tests/strict/rosetta_code_abc_preprocessed.clsp new file mode 100644 index 000000000..d07e850b2 --- /dev/null +++ b/resources/tests/strict/rosetta_code_abc_preprocessed.clsp @@ -0,0 +1,13 @@ +(mod (word) + (include *standard-cl-23*) + + (defconst *blocks* (4 (c "B" "O") (4 (c "X" "K") (4 (c "D" "Q") (4 (c "C" "P") (4 (c "N" "A") (4 (c "G" "T") (4 (c "R" "E") (4 (c "T" "G") (4 (c "Q" "D") (4 (c "F" "S") (4 (c "J" "W") (4 (c "H" "U") (4 (c "V" "I") (4 (c "A" "N") (4 (c "O" "B") (4 (c "E" "R") (4 (c "F" "S") (4 (c "L" "Y") (4 (c "P" "C") (4 (c "Z" "M") ()))))))))))))))))))))) + + (defun-inline block-member (e_$_420 s_$_421) (logior (= e_$_420 (f s_$_421)) (= e_$_420 (r s_$_421)))) + (defun exists (p?_$_428 li_$_429) (a (i li_$_429 (com (a (i (a p?_$_428 (4 (f li_$_429) ())) (com 1) (com (exists p?_$_428 (r li_$_429)))) @)) (com ())) @)) + (defun remove-one (x_$_430 li_$_431) (a (i (not li_$_431) (com 1) (com (a (i (a (i (= (f (f li_$_431)) (f x_$_430)) (com (= (r (f li_$_431)) (r x_$_430))) (com ())) @) (com (r li_$_431)) (com (c (f li_$_431) (remove-one x_$_430 (r li_$_431))))) @))) @)) + (defun can-make-list? (li_$_432 blocks_$_433) (a (i (not li_$_432) (com 1) (com (exists (lambda ((& li_$_432 blocks_$_433) block_$_434) (a (i (block-member (f li_$_432) block_$_434) (com (can-make-list? (r li_$_432) (remove-one block_$_434 blocks_$_433))) (com ())) @)) blocks_$_433))) @)) + (defun can-make-word? (word_$_435) (can-make-list? word_$_435 *blocks*)) (defun wordify (W_$_436) (a (i W_$_436 (com (c (substr W_$_436 () 1) (wordify (substr W_$_436 1)))) (com ())) @)) + + (can-make-word? (wordify word)) + ) diff --git a/resources/tests/strict/rosetta_code_babbage_problem.clsp b/resources/tests/strict/rosetta_code_babbage_problem.clsp new file mode 100644 index 000000000..55b00b455 --- /dev/null +++ b/resources/tests/strict/rosetta_code_babbage_problem.clsp @@ -0,0 +1,61 @@ +;; Adapted from: https://rosettacode.org/wiki/Babbage_problem#Scheme +(mod (N) + (include *standard-cl-23*) + + (defun digits_ (result n) + (assign + (d . r) (divmod n 10) + (if d + (digits_ (c r result) d) + (c r result) + ) + ) + ) + + (defun digits (n) (if n (digits_ () n) ())) + + (defun reverse_ (result lst) + (if lst + (reverse_ (c (f lst) result) (r lst)) + result + ) + ) + + (defun reverse (lst) (reverse_ () lst)) + + (defun starts-with (lst prefix) + (if prefix + (if lst + (if (= (f prefix) (f lst)) + (starts-with (r lst) (r prefix)) + () + ) + () + ) + 1 + ) + ) + + (defun ends-with (lst tail) + ;; does list end with tail? + (starts-with (reverse lst) (reverse tail)) + ) + + (defun loop (start fun) + (let ((res (a fun (list start)))) + (if res + (f res) + (loop (+ 1 start) fun) + ) + ) + ) + + (loop 1 + (lambda ((& N) idx) + (if (ends-with (digits (* idx idx)) (digits N)) + (list idx) + () + ) + ) + ) + ) diff --git a/resources/tests/strict/rps-referee-uncaptured.clsp b/resources/tests/strict/rps-referee-uncaptured.clsp new file mode 100644 index 000000000..01e90e55e --- /dev/null +++ b/resources/tests/strict/rps-referee-uncaptured.clsp @@ -0,0 +1,31 @@ +(mod ((VALIDATION_PROGRAM_HASH AMOUNT) action . args) + + (include *strict-cl-21*) + + (defconstant CREATE_COIN 51) + + (defun reduce (fun lst init) + (if lst + (reduce fun (r lst) (a fun (list (f lst) init))) + init + ) + ) + + (let + ((new_puzzle_hash 38911) + ) + (reduce + (lambda ((@ condition (condname arg1 arg2)) agg) + (if agg + 1 + (if (= condname CREATE_COIN) + (logand (= arg1 new_puzzle_hash) (= arg2 100)) + 0 + ) + ) + ) + conditions + 0 + ) + ) + ) diff --git a/resources/tests/strict/singleton_top_layer.clsp b/resources/tests/strict/singleton_top_layer.clsp new file mode 100644 index 000000000..805c0a485 --- /dev/null +++ b/resources/tests/strict/singleton_top_layer.clsp @@ -0,0 +1,168 @@ +(mod (SINGLETON_STRUCT INNER_PUZZLE lineage_proof my_amount inner_solution) + + ;; SINGLETON_STRUCT = (MOD_HASH . (LAUNCHER_ID . LAUNCHER_PUZZLE_HASH)) + + ; SINGLETON_STRUCT, INNER_PUZZLE are curried in by the wallet + + ; EXAMPLE SOLUTION '(0xfadeddab 0xdeadbeef 1 (0xdeadbeef 200) 50 ((51 0xfadeddab 100) (60 "trash") (51 deadbeef 0)))' + + + ; This puzzle is a wrapper around an inner smart puzzle which guarantees uniqueness. + ; It takes its singleton identity from a coin with a launcher puzzle which guarantees that it is unique. + (include *standard-cl-23*) + + (include condition_codes.clib) + (include curry-and-treehash.clib) + (include singleton_truths.clib) + + ; takes a lisp tree and returns the hash of it + (defun sha256tree1 (TREE) + (if (l TREE) + (sha256 2 (sha256tree1 (f TREE)) (sha256tree1 (r TREE))) + (sha256 1 TREE) + ) + ) + + (include defmac_assert.clib) + + (defun-inline mod_hash_for_singleton_struct (SINGLETON_STRUCT) (f SINGLETON_STRUCT)) + (defun-inline launcher_id_for_singleton_struct (SINGLETON_STRUCT) (f (r SINGLETON_STRUCT))) + (defun-inline launcher_puzzle_hash_for_singleton_struct (SINGLETON_STRUCT) (r (r SINGLETON_STRUCT))) + + ;; return the full puzzlehash for a singleton with the innerpuzzle curried in + ; puzzle-hash-of-curried-function is imported from curry-and-treehash.clib + (defun-inline calculate_full_puzzle_hash (SINGLETON_STRUCT inner_puzzle_hash) + (puzzle-hash-of-curried-function (mod_hash_for_singleton_struct SINGLETON_STRUCT) + inner_puzzle_hash + (sha256tree1 SINGLETON_STRUCT) + ) + ) + + ; assembles information from the solution to create our own full ID including asserting our parent is a singleton + (defun create_my_ID (SINGLETON_STRUCT full_puzzle_hash parent_parent parent_inner_puzzle_hash parent_amount my_amount) + (sha256 (sha256 parent_parent (calculate_full_puzzle_hash SINGLETON_STRUCT parent_inner_puzzle_hash) parent_amount) + full_puzzle_hash + my_amount) + ) + + ;; take a boolean and a non-empty list of conditions + ;; strip off the first condition if a boolean is set + ;; this is used to remove `(CREATE_COIN xxx -113)` + ;; pretty sneaky, eh? + (defun strip_first_condition_if (boolean condition_list) + (if boolean + (r condition_list) + condition_list + ) + ) + + (defun-inline morph_condition (condition SINGLETON_STRUCT) + (list (f condition) (calculate_full_puzzle_hash SINGLETON_STRUCT (f (r condition))) (f (r (r condition)))) + ) + + ;; return the value of the coin created if this is a `CREATE_COIN` condition, or 0 otherwise + (defun-inline created_coin_value_or_0 (condition) + (if (= (f condition) CREATE_COIN) + (f (r (r condition))) + 0 + ) + ) + + ;; Returns a (bool . bool) + (defun odd_cons_m113 (output_amount) + (c + (= (logand output_amount 1) 1) ;; is it odd? + (= output_amount -113) ;; is it the escape value? + ) + ) + + ; Assert exactly one output with odd value exists - ignore it if value is -113 + + ;; this function iterates over the output conditions from the inner puzzle & solution + ;; and both checks that exactly one unique singleton child is created (with odd valued output), + ;; and wraps the inner puzzle with this same singleton wrapper puzzle + ;; + ;; The special case where the output value is -113 means a child singleton is intentionally + ;; *NOT* being created, thus forever ending this singleton's existence + + (defun check_and_morph_conditions_for_singleton (SINGLETON_STRUCT conditions has_odd_output_been_found) + (if conditions + (morph_next_condition SINGLETON_STRUCT conditions has_odd_output_been_found (odd_cons_m113 (created_coin_value_or_0 (f conditions)))) + (if has_odd_output_been_found + 0 + (x) ;; no odd output found + ) + ) + ) + + ;; a continuation of `check_and_morph_conditions_for_singleton` with booleans `is_output_odd` and `is_output_m113` + ;; precalculated + (defun morph_next_condition (SINGLETON_STRUCT conditions has_odd_output_been_found (is_output_odd . is_output_m113)) + (assert + (not (all is_output_odd has_odd_output_been_found)) + (strip_first_condition_if + is_output_m113 + (c (if is_output_odd + (morph_condition (f conditions) SINGLETON_STRUCT) + (f conditions) + ) + (check_and_morph_conditions_for_singleton SINGLETON_STRUCT (r conditions) (any is_output_odd has_odd_output_been_found)) + ) + ) + ) + ) + + ; this final stager asserts our ID + ; it also runs the innerpuz with the innersolution with the "truths" added + ; it then passes that output conditions from the innerpuz to the morph conditions function + (defun stager_three (SINGLETON_STRUCT lineage_proof my_id full_puzhash innerpuzhash my_amount INNER_PUZZLE inner_solution) + (c (list ASSERT_MY_COIN_ID my_id) (check_and_morph_conditions_for_singleton SINGLETON_STRUCT (a INNER_PUZZLE (c (truth_data_to_truth_struct my_id full_puzhash innerpuzhash my_amount lineage_proof SINGLETON_STRUCT) inner_solution)) 0)) + ) + + ; this checks whether we are an eve spend or not and calculates our full coin ID appropriately and passes it on to the final stager + ; if we are the eve spend it also adds the additional checks that our parent's puzzle is the standard launcher format and that out parent ID is the same as our singleton ID + + (defun stager_two (SINGLETON_STRUCT lineage_proof full_puzhash innerpuzhash my_amount INNER_PUZZLE inner_solution) + (stager_three + SINGLETON_STRUCT + lineage_proof + (if (is_not_eve_proof lineage_proof) + (create_my_ID + SINGLETON_STRUCT + full_puzhash + (parent_info_for_lineage_proof lineage_proof) + (puzzle_hash_for_lineage_proof lineage_proof) + (amount_for_lineage_proof lineage_proof) + my_amount + ) + (if (= + (launcher_id_for_singleton_struct SINGLETON_STRUCT) + (sha256 (parent_info_for_eve_proof lineage_proof) (launcher_puzzle_hash_for_singleton_struct SINGLETON_STRUCT) (amount_for_eve_proof lineage_proof)) + ) + (sha256 (launcher_id_for_singleton_struct SINGLETON_STRUCT) full_puzhash my_amount) + (x) + ) + ) + full_puzhash + innerpuzhash + my_amount + INNER_PUZZLE + inner_solution + ) + ) + + ; this calculates our current full puzzle hash and passes it to stager two + (defun stager_one (SINGLETON_STRUCT lineage_proof my_innerpuzhash my_amount INNER_PUZZLE inner_solution) + (stager_two SINGLETON_STRUCT lineage_proof (calculate_full_puzzle_hash SINGLETON_STRUCT my_innerpuzhash) my_innerpuzhash my_amount INNER_PUZZLE inner_solution) + ) + + + ; main + + ; if our value is not an odd amount then we are invalid + ; this calculates my_innerpuzhash and passes all values to stager_one + (if (logand my_amount 1) + (stager_one SINGLETON_STRUCT lineage_proof (sha256tree1 INNER_PUZZLE) my_amount INNER_PUZZLE inner_solution) + (x) + ) +) diff --git a/resources/tests/strict/strict-classify-expr-if.clsp b/resources/tests/strict/strict-classify-expr-if.clsp new file mode 100644 index 000000000..03288183d --- /dev/null +++ b/resources/tests/strict/strict-classify-expr-if.clsp @@ -0,0 +1,24 @@ +(mod (X) + (include *strict-cl-21*) + ;; Ensure macros can expand inside other macros when using advanced primitives. + (defmac classify-expr (G) + (if (number? G) + 1 + (if (symbol? G) + 2 + (if (string? G) + 3 + (if (l G) + 4 + 0 + ) + ) + ) + ) + ) + + (if X + (classify-expr X) + (list (classify-expr ()) (classify-expr 33) (classify-expr test) (classify-expr "foo") (classify-expr (* 3 2)) (classify-expr (list 1 2 3))) + ) + ) diff --git a/resources/tests/strict/strict-in-place-factorial.clsp b/resources/tests/strict/strict-in-place-factorial.clsp new file mode 100644 index 000000000..6b036beac --- /dev/null +++ b/resources/tests/strict/strict-in-place-factorial.clsp @@ -0,0 +1,6 @@ +(mod (X) + (include *strict-cl-21*) + (defmac factorial (N) + (if (> 2 N) 1 (qq (* (unquote N) (factorial (- N 1)))))) + (factorial 5) + ) diff --git a/resources/tests/strict/strict-list-fail.clsp b/resources/tests/strict/strict-list-fail.clsp new file mode 100644 index 000000000..9e4e42502 --- /dev/null +++ b/resources/tests/strict/strict-list-fail.clsp @@ -0,0 +1,4 @@ +(mod (X) + (include *strict-cl-21*) + (list X (+ X 1) (+ X2)) + ) diff --git a/resources/tests/strict/strict-list-pass.clsp b/resources/tests/strict/strict-list-pass.clsp new file mode 100644 index 000000000..efbba4770 --- /dev/null +++ b/resources/tests/strict/strict-list-pass.clsp @@ -0,0 +1,4 @@ +(mod (X) + (include *strict-cl-21*) + (list X (+ X 1) (+ X 2)) + ) diff --git a/resources/tests/strict/strict-nested-list.clsp b/resources/tests/strict/strict-nested-list.clsp new file mode 100644 index 000000000..6bc4bddb4 --- /dev/null +++ b/resources/tests/strict/strict-nested-list.clsp @@ -0,0 +1,4 @@ +(mod (X) + (include *strict-cl-21*) + (list X (list X) (list (list X))) + ) diff --git a/resources/tests/strict/strict-test-fail.clsp b/resources/tests/strict/strict-test-fail.clsp new file mode 100644 index 000000000..4ca88390b --- /dev/null +++ b/resources/tests/strict/strict-test-fail.clsp @@ -0,0 +1,9 @@ +(mod (X) + (include *strict-cl-21*) + ;; This wouldn't be able to be rejected because X1 is coming from a macro + ;; expansion. This should fail in strict but succeed wrong non-strict. + (if X + (+ X1 2) + 5 + ) + ) diff --git a/resources/tests/strict/strict-test-pass.clsp b/resources/tests/strict/strict-test-pass.clsp new file mode 100644 index 000000000..6dfbc39de --- /dev/null +++ b/resources/tests/strict/strict-test-pass.clsp @@ -0,0 +1,7 @@ +(mod (X) + (include *strict-cl-21*) + (if X + (+ X 2) + 5 + ) + ) diff --git a/resources/tests/strict/test-inner-include.clinc b/resources/tests/strict/test-inner-include.clinc new file mode 100644 index 000000000..704dfcca7 --- /dev/null +++ b/resources/tests/strict/test-inner-include.clinc @@ -0,0 +1,3 @@ +( + (include defmac_simple_if.clib) +) diff --git a/resources/tests/strict/test-inner-include.clsp b/resources/tests/strict/test-inner-include.clsp new file mode 100644 index 000000000..6fc0dabf8 --- /dev/null +++ b/resources/tests/strict/test-inner-include.clsp @@ -0,0 +1,7 @@ +(mod (X) + (include *strict-cl-21*) + + (include test-inner-include.clinc) + + (if_ X (* X 2) (+ X 1)) + ) diff --git a/resources/tests/strict/test_atomsort.clsp b/resources/tests/strict/test_atomsort.clsp new file mode 100644 index 000000000..229c4275e --- /dev/null +++ b/resources/tests/strict/test_atomsort.clsp @@ -0,0 +1,5 @@ +(mod (X) + (include *standard-cl-23*) + (include atomsort.clinc) + (atomsort X) + ) diff --git a/resources/tests/strict/truncate.clinc b/resources/tests/strict/truncate.clinc new file mode 100644 index 000000000..e4557f31c --- /dev/null +++ b/resources/tests/strict/truncate.clinc @@ -0,0 +1,8 @@ +( +(defun truncate (N (@ L (LF . LR))) + (if (all N L) + (c LF (truncate (- N 1) LR)) + () + ) +) +) \ No newline at end of file diff --git a/resources/tests/strict/typesmoke-lambda-anno.clsp b/resources/tests/strict/typesmoke-lambda-anno.clsp new file mode 100644 index 000000000..150f37800 --- /dev/null +++ b/resources/tests/strict/typesmoke-lambda-anno.clsp @@ -0,0 +1,8 @@ +(mod ((X : Atom) (Y : Atom)) -> Atom + (include *standard-cl-23*) + (defun plus-n ((N : Atom)) -> (Exec ((Pair Atom Unit) -> Atom)) + (lambda ((& N) Y) (+ N Y)) + ) + + (a (plus-n X) (list Y)) + ) diff --git a/resources/tests/strict/typesmoke-lambda.clsp b/resources/tests/strict/typesmoke-lambda.clsp new file mode 100644 index 000000000..940bc7b45 --- /dev/null +++ b/resources/tests/strict/typesmoke-lambda.clsp @@ -0,0 +1,9 @@ +(mod ((X : (Pair Atom Unit))) -> (Pair Atom Any) + (include *standard-cl-23*) + (deftype T (x)) + (assign + x_of_t (get_T_x (new_T X)) + lam (a (lambda (Y) (+ Y 1)) (list x_of_t)) + (c x_of_t lam) + ) + ) diff --git a/resources/tests/strict/typesmoke.clsp b/resources/tests/strict/typesmoke.clsp new file mode 100644 index 000000000..3367c2966 --- /dev/null +++ b/resources/tests/strict/typesmoke.clsp @@ -0,0 +1,5 @@ +(mod ((X : (Pair Atom Unit))) -> Atom + (include *standard-cl-23*) + (deftype T (x)) + (get_T_x (new_T X)) + ) diff --git a/resources/tests/strict/use-w2.clsp b/resources/tests/strict/use-w2.clsp new file mode 100644 index 000000000..63da2fd7c --- /dev/null +++ b/resources/tests/strict/use-w2.clsp @@ -0,0 +1,9 @@ +(mod (items) + (include *standard-cl-23*) + + (defun assert_ (items_$_41) (letbinding_$_44 (r @*env*) (f items_$_41))) + (defun-inline letbinding_$_44 ((items_$_41) cse_$_43) + (a (com cse_$_43) @) + ) + (assert_ items) + ) diff --git a/resources/tests/strict/use-w3.clsp b/resources/tests/strict/use-w3.clsp new file mode 100644 index 000000000..742707d58 --- /dev/null +++ b/resources/tests/strict/use-w3.clsp @@ -0,0 +1,9 @@ +(mod (items) + (include *standard-cl-23*) + + (defun assert_ (items_$_41) (letbinding_$_44 (r @*env*) (f items_$_41))) + (defun letbinding_$_44 ((items_$_41) cse_$_43) + (a (com cse_$_43) @) + ) + (assert_ items) + ) diff --git a/resources/tests/test_assign_path_opt.clsp b/resources/tests/test_assign_path_opt.clsp new file mode 100644 index 000000000..81072f2ee --- /dev/null +++ b/resources/tests/test_assign_path_opt.clsp @@ -0,0 +1,8 @@ +(mod (Z) + (include *strict-cl-21*) + (defun F (X) (* X 5)) + (assign + (_0 _1 _2 _3 _4 (_50 (_51 _52 _53 Q))) Z + (F Q) + ) + ) diff --git a/resources/tests/test_clvm_step.py b/resources/tests/test_clvm_step.py index 4f4b2f9d2..850d2a44a 100644 --- a/resources/tests/test_clvm_step.py +++ b/resources/tests/test_clvm_step.py @@ -4,7 +4,10 @@ import json from clvm_tools_rs import start_clvm_program, compose_run_function -def run_until_end(p): +def do_nothing(p): + pass + +def run_until_end(p,printing=do_nothing,spam=True): last = None location = None @@ -12,9 +15,12 @@ def run_until_end(p): step_result = p.step() if step_result is not None: last = step_result + if 'Print' in last: + printing(last['Print']) if 'Operator-Location' in last: location = last['Operator-Location'] - print(json.dumps(step_result)) + if spam: + print(json.dumps(step_result)) return (last, location) @@ -43,6 +49,54 @@ def fact_base_override(env): assert int(last['Final']) == 11880 +def test_with_printing(): + mypath = Path(os.path.abspath(__file__)) + testpath = mypath.parent.joinpath('mandelbrot') + symbols = json.loads(open(str(testpath.joinpath('mandelbrot.sym'))).read()) + + p = start_clvm_program(open(str(testpath.joinpath('mandelbrot.clvm.hex'))).read(), 'ff82ff40ff8180ff82ff70ff81a0ff0880', symbols, {}) + + print_outputs = [] + def do_print(p): + print(p) + print_outputs.append(p) + + last, location = run_until_end(p,printing=do_print,spam=False) + + expected_outcome = "||567AAC|68DEEE|78EEEE|78BEEE" + want_prints = [ + "((\"escape-at\" -152 -104) 14)", + "((\"escape-at\" -160 -104) 14)", + "((\"escape-at\" -168 -104) 14)", + "((\"escape-at\" -176 -104) 11)", + "((\"escape-at\" -184 -104) 8)", + "((\"escape-at\" -192 -104) 7)", + "((\"escape-at\" -152 -112) 14)", + "((\"escape-at\" -160 -112) 14)", + "((\"escape-at\" -168 -112) 14)", + "((\"escape-at\" -176 -112) 14)", + "((\"escape-at\" -184 -112) 8)", + "((\"escape-at\" -192 -112) 7)", + "((\"escape-at\" -152 -120) 14)", + "((\"escape-at\" -160 -120) 14)", + "((\"escape-at\" -168 -120) 14)", + "((\"escape-at\" -176 -120) 13)", + "((\"escape-at\" -184 -120) 8)", + "((\"escape-at\" -192 -120) 6)", + "((\"escape-at\" -152 -128) 12)", + "((\"escape-at\" -160 -128) 10)", + "((\"escape-at\" -168 -128) 10)", + "((\"escape-at\" -176 -128) 7)", + "((\"escape-at\" -184 -128) 6)", + "((\"escape-at\" -192 -128) 5)", + f"(\"result\" \"{expected_outcome}\")" + ] + + assert print_outputs == want_prints + to_hex = hex(int(last['Final'])) + have_outcome = bytes.fromhex(to_hex[2:]).decode('utf8') + assert have_outcome == expected_outcome + def single_function_test(): mypath = Path(os.path.abspath(__file__)) testpath = mypath.parent.joinpath('steprun') @@ -60,3 +114,4 @@ def single_function_test(): simple_test() complex_test() single_function_test() + test_with_printing() diff --git a/resources/tests/test_compile_from_string.py b/resources/tests/test_compile_from_string.py new file mode 100644 index 000000000..f067b11ba --- /dev/null +++ b/resources/tests/test_compile_from_string.py @@ -0,0 +1,88 @@ +import binascii +import clvm_tools_rs +from pathlib import Path + +classic_code = """ +(mod (N X) + (defun F (N X) (if N (sha256 (F (- N 1) X)) X)) + (F N X) + ) +""" +expected_classic = "ff02ffff01ff02ff02ffff04ff02ffff04ff05ffff04ff0bff8080808080ffff04ffff01ff02ffff03ff05ffff01ff0bffff02ff02ffff04ff02ffff04ffff11ff05ffff010180ffff04ff0bff808080808080ffff010b80ff0180ff018080" + +cl23_code = """ +(mod (N X) + (include *standard-cl-23*) + (defun F (N X) (if N (sha256 (F (- N 1) X)) X)) + (F N X) + ) +""" +expected_cl23 = "ff02ffff01ff02ff02ffff04ff02ffff04ff05ffff04ff0bff8080808080ffff04ffff01ff02ffff03ff05ffff01ff0bffff02ff02ffff04ff02ffff04ffff11ff05ffff010180ffff04ff0bff808080808080ffff010b80ff0180ff018080" + +expected_deinline = "ff02ffff01ff02ff02ffff04ff02ffff04ff03ffff04ffff10ff05ffff01830f424080ff8080808080ffff04ffff01ff10ff0bff0bff0bff0bff0bff0b80ff018080" + +classic_error = "(mod (X) (xxx X))" +cl23_error = "(mod (X) (include *standard-cl-23*) (+ X X1))" + +compiled_code = clvm_tools_rs.compile( + classic_code, + ["."], + True +) +# Classic outputs symbols to the filesystem down all routes, which likely should +# be fixed. +assert compiled_code["output"] == expected_classic + +compiled_code = clvm_tools_rs.compile( + classic_code, + ["."] +) +assert compiled_code == expected_classic + +# Verify modern compilation +compiled_code = clvm_tools_rs.compile( + cl23_code, + ["."], + True +) +symbols = compiled_code["symbols"] +assert symbols["__chia__main_arguments"] == "(N X)" +assert symbols["30960d7f2ddc7188a6428a11d39a13ff70d308e6cc571ffb6ed5ec8dbe4376c0_arguments"] == "(N X)" +assert symbols["30960d7f2ddc7188a6428a11d39a13ff70d308e6cc571ffb6ed5ec8dbe4376c0"] == "F" +assert compiled_code["output"] == expected_cl23 + +# Check compilation with a path +test_path = Path(__file__).parent + +output_file = "simple_deinline_case_23.hex" +compiled_code = clvm_tools_rs.compile_clvm( + str(test_path / "simple_deinline_case_23.clsp"), + output_file, + ["."], + True +) +assert compiled_code["symbols"]["d623cecd87575189eb1518b50cecc8944a51aa6f4bb4cf6419f70e4aa34f5a20"].startswith("letbinding") +assert compiled_code["output"] == output_file +assert open(output_file).read().strip() == expected_deinline + +# Check dependency output +game_referee = Path(__file__).parent / "game-referee-in-cl23" +dependencies = clvm_tools_rs.check_dependencies( + str(game_referee / "test_reverse.clsp"), + [str(game_referee)] +) +assert len(dependencies) == 1 +assert Path(dependencies[0]) == game_referee / 'reverse.clinc' + +# Better error reporting +try: + clvm_tools_rs.compile(classic_error, []) + assert False +except Exception as e: + assert e.args[0] == "error can't compile (\"xxx\" 88), unknown operator compiling (\"xxx\" 88)" + +try: + clvm_tools_rs.compile(cl23_error, []) + assert False +except Exception as e: + assert e.args[0] == "*inline*(1):42-*inline*(1):44: Unbound use of X1 as a variable name" diff --git a/resources/tests/test_recursion_subexp.clsp b/resources/tests/test_recursion_subexp.clsp new file mode 100644 index 000000000..4fdac1fbb --- /dev/null +++ b/resources/tests/test_recursion_subexp.clsp @@ -0,0 +1,10 @@ +(mod (Q R) + (include *standard-cl-23*) + (defun G (Q R) + (if Q + (G (- Q 1) (* (+ 1 Q) R)) + (* (+ 1 Q) R) + ) + ) + (G Q R) + ) diff --git a/resources/tests/test_user_path_opt_0.clsp b/resources/tests/test_user_path_opt_0.clsp new file mode 100644 index 000000000..2a5a15c89 --- /dev/null +++ b/resources/tests/test_user_path_opt_0.clsp @@ -0,0 +1,5 @@ +(mod (Q) + (include *strict-cl-21*) + (defun F (X) (f (f (f (f (f (f (r X)))))))) + (F Q) + ) diff --git a/src/classic/bins/clisp_to_json.rs b/src/classic/bins/clisp_to_json.rs index e3b70905d..0cbf6734b 100644 --- a/src/classic/bins/clisp_to_json.rs +++ b/src/classic/bins/clisp_to_json.rs @@ -1,6 +1,5 @@ extern crate clvmr as clvm_rs; -use ::serde_json; use std::env; use std::rc::Rc; diff --git a/src/classic/bins/repl.rs b/src/classic/bins/repl.rs index 3a8fc9df7..0126ef2a4 100644 --- a/src/classic/bins/repl.rs +++ b/src/classic/bins/repl.rs @@ -8,10 +8,11 @@ use clvm_rs::allocator::Allocator; use clvm_tools_rs::compiler::compiler::DefaultCompilerOpts; use clvm_tools_rs::compiler::repl::Repl; +use clvm_tools_rs::classic::clvm_tools::log; use clvm_tools_rs::classic::clvm_tools::stages::stage_0::DefaultProgramRunner; fn main() { - env_logger::init(); + log::init(); let mut allocator = Allocator::new(); let runner = Rc::new(DefaultProgramRunner::new()); diff --git a/src/classic/bins/typetest.rs b/src/classic/bins/typetest.rs deleted file mode 100644 index edd68bd10..000000000 --- a/src/classic/bins/typetest.rs +++ /dev/null @@ -1,66 +0,0 @@ -extern crate clvmr as clvm_rs; - -use std::env; - -use clvm_tools_rs::compiler::comptypes::CompileErr; -use clvm_tools_rs::compiler::sexp::parse_sexp; -use clvm_tools_rs::compiler::srcloc::Srcloc; -use clvm_tools_rs::compiler::typecheck::{parse_expr_sexp, TheoryToSExp}; -use clvm_tools_rs::compiler::typechia::standard_type_context; -use clvm_tools_rs::compiler::types::ast::{ContextElim, Var}; -use clvm_tools_rs::compiler::types::theory::TypeTheory; - -fn main() { - let args: Vec = env::args().collect(); - if args.len() < 2 { - println!("give type theory expressions"); - return; - } - - env_logger::init(); - - let loc = Srcloc::start("*program*"); - let mut context = standard_type_context(); - - let mut takename = true; - let mut name = "".to_string(); - for arg in args.iter().take(args.len() - 1).skip(1) { - if takename { - name = arg.to_string(); - } else { - match parse_sexp(loc.clone(), arg.bytes()) - .map_err(|e| CompileErr(e.0.clone(), e.1)) - .and_then(|parsed_program| parse_expr_sexp(parsed_program[0].clone())) - .and_then(|result| context.typesynth(&result)) - { - Ok((ty, _)) => { - context = context.snoc(ContextElim::CVar(Var(name.clone(), loc.clone()), ty)); - } - Err(e) => { - println!("error in helper {name}: {e:?}"); - return; - } - } - } - - takename = !takename; - } - - println!("starting context {}", context.to_sexp()); - - parse_sexp(loc, args[args.len() - 1].bytes()) - .map_err(|e| CompileErr(e.0.clone(), e.1)) - .and_then(|parsed_program| parse_expr_sexp(parsed_program[0].clone())) - .and_then(|result| { - println!("parsed: {}", result.to_sexp()); - context.typesynth(&result) - }) - .map(|(ty, ctx)| { - println!("typed: {}", ctx.reify(&ty, None).to_sexp()); - println!("context: {}", ctx.to_sexp()); - }) - .map_err(|e| { - println!("failed: {e:?}"); - }) - .ok(); -} diff --git a/src/classic/clvm/__type_compatibility__.rs b/src/classic/clvm/__type_compatibility__.rs index 81530f3d2..98bbddbfb 100644 --- a/src/classic/clvm/__type_compatibility__.rs +++ b/src/classic/clvm/__type_compatibility__.rs @@ -4,11 +4,8 @@ use std::cmp::Ordering; use std::cmp::{max, min}; use std::collections::HashMap; use std::fmt::{Debug, Display}; -use std::option::Option; -use std::string::String; use bls12_381::G1Affine; -use hex; use sha2::Digest; use sha2::Sha256; diff --git a/src/classic/clvm/serialize.rs b/src/classic/clvm/serialize.rs index f863a42df..6deb9dd7c 100644 --- a/src/classic/clvm/serialize.rs +++ b/src/classic/clvm/serialize.rs @@ -14,7 +14,6 @@ leading bits is the count of bytes to read of size */ use std::rc::Rc; -use std::vec::Vec; use crate::classic::clvm::__type_compatibility__::{Bytes, BytesFromType, Stream}; use crate::classic::clvm::as_rust::{TToSexpF, TValStack}; diff --git a/src/classic/clvm/sexp.rs b/src/classic/clvm/sexp.rs index fd26de905..bf8b1fd30 100644 --- a/src/classic/clvm/sexp.rs +++ b/src/classic/clvm/sexp.rs @@ -1,7 +1,6 @@ use std::borrow::Borrow; use std::fmt::Debug; use std::rc::Rc; -use std::string::String; use clvm_rs::allocator::{Allocator, NodePtr, SExp}; use clvm_rs::reduction::EvalErr; diff --git a/src/classic/clvm_tools/clvmc.rs b/src/classic/clvm_tools/clvmc.rs index 0994ed1de..ce9883bfc 100644 --- a/src/classic/clvm_tools/clvmc.rs +++ b/src/classic/clvm_tools/clvmc.rs @@ -1,11 +1,7 @@ use std::collections::HashMap; use std::fs; -use std::io::Write; -use std::path::Path; use std::rc::Rc; -use tempfile::NamedTempFile; - use clvm_rs::allocator::{Allocator, NodePtr}; use clvm_rs::reduction::EvalErr; @@ -21,12 +17,58 @@ use crate::classic::platform::distutils::dep_util::newer; use crate::compiler::clvm::convert_to_clvm_rs; use crate::compiler::compiler::compile_file; -use crate::compiler::compiler::{run_optimizer, DefaultCompilerOpts}; +use crate::compiler::compiler::DefaultCompilerOpts; use crate::compiler::comptypes::{CompileErr, CompilerOpts}; use crate::compiler::dialect::detect_modern; +use crate::compiler::optimize::maybe_finalize_program_via_classic_optimizer; use crate::compiler::runtypes::RunFailure; use crate::compiler::srcloc::Srcloc; use crate::compiler::untype::untype_code; +use crate::util::gentle_overwrite; + +#[derive(Debug, Clone)] +pub enum CompileError { + Modern(Srcloc, String), + Classic(NodePtr, String), +} + +impl From for CompileError { + fn from(e: EvalErr) -> Self { + CompileError::Classic(e.0, e.1) + } +} + +impl From for CompileError { + fn from(r: CompileErr) -> Self { + CompileError::Modern(r.0, r.1) + } +} + +impl From for CompileError { + fn from(r: RunFailure) -> Self { + match r { + RunFailure::RunErr(l, x) => CompileError::Modern(l, x), + RunFailure::RunExn(l, x) => CompileError::Modern(l, x.to_string()), + } + } +} + +impl CompileError { + pub fn format(&self, allocator: &Allocator, opts: Rc) -> String { + match self { + CompileError::Classic(node, message) => { + format!( + "error {} compiling {}", + message, + disassemble(allocator, *node, opts.disassembly_ver()) + ) + } + CompileError::Modern(loc, message) => { + format!("{}: {}", loc, message) + } + } + } +} pub fn write_sym_output( compiled_lookup: &HashMap, @@ -40,14 +82,15 @@ pub fn write_sym_output( .map(|_| ()) } -pub fn compile_clvm_text( +pub fn compile_clvm_text_maybe_opt( allocator: &mut Allocator, + do_optimize: bool, opts: Rc, symbol_table: &mut HashMap, text: &str, input_path: &str, classic_with_opts: bool, -) -> Result { +) -> Result { let ir_src = read_ir(text).map_err(|s| EvalErr(allocator.null(), s.to_string()))?; let assembled_sexp = assemble_from_ir(allocator, Rc::new(ir_src))?; let untyped_sexp = untype_code(allocator, Srcloc::start(input_path), assembled_sexp)?; @@ -60,18 +103,21 @@ pub fn compile_clvm_text( // to get more members that are somewhat independent. if let Some(stepping) = dialect.stepping { let runner = Rc::new(DefaultProgramRunner::new()); - let opts = opts.set_optimize(true).set_frontend_opt(stepping > 21); - - let unopt_res = compile_file(allocator, runner.clone(), opts, text, symbol_table); - let res = unopt_res.and_then(|x| run_optimizer(allocator, runner, Rc::new(x))); - - res.and_then(|x| { - convert_to_clvm_rs(allocator, x).map_err(|r| match r { - RunFailure::RunErr(l, x) => CompileErr(l, x), - RunFailure::RunExn(l, x) => CompileErr(l, x.to_string()), - }) - }) - .map_err(|s| EvalErr(allocator.null(), s.1)) + let opts = opts + .set_dialect(dialect) + .set_optimize(do_optimize || stepping > 22) // Would apply to cl23 + .set_frontend_opt(stepping == 22); + + let unopt_res = compile_file(allocator, runner.clone(), opts.clone(), text, symbol_table)?; + let res = maybe_finalize_program_via_classic_optimizer( + allocator, + runner, + opts, + do_optimize, + &unopt_res, + )?; + + Ok(convert_to_clvm_rs(allocator, res)?) } else { let compile_invoke_code = run(allocator); let input_sexp = allocator.new_pair(untyped_sexp, allocator.null())?; @@ -85,6 +131,25 @@ pub fn compile_clvm_text( } } +pub fn compile_clvm_text( + allocator: &mut Allocator, + opts: Rc, + symbol_table: &mut HashMap, + text: &str, + input_path: &str, + classic_with_opts: bool, +) -> Result { + compile_clvm_text_maybe_opt( + allocator, + true, + opts, + symbol_table, + text, + input_path, + classic_with_opts, + ) +} + pub fn compile_clvm_inner( allocator: &mut Allocator, opts: Rc, @@ -102,13 +167,7 @@ pub fn compile_clvm_inner( filename, classic_with_opts, ) - .map_err(|x| { - format!( - "error {} compiling {}", - x.1, - disassemble(allocator, x.0, opts.disassembly_ver()) - ) - })?; + .map_err(|e| e.format(allocator, opts))?; sexp_to_stream(allocator, result, result_stream); Ok(()) } @@ -139,55 +198,12 @@ pub fn compile_clvm( false, )?; - let target_data = result_stream.get_value().hex(); - - let write_file = |output_path: &str, target_data: &str| -> Result<(), String> { - let output_path_obj = Path::new(output_path); - let output_dir = output_path_obj - .parent() - .map(Ok) - .unwrap_or_else(|| Err("could not get parent of output path"))?; - - // Make the contents appear atomically so that other test processes - // won't mistake an empty file for intended output. - let mut temp_output_file = NamedTempFile::new_in(output_dir).map_err(|e| { - format!("error creating temporary compiler output for {input_path}: {e:?}") - })?; - - let err_text = format!("failed to write to {:?}", temp_output_file.path()); - let translate_err = |_| err_text.clone(); - - temp_output_file - .write_all(target_data.as_bytes()) - .map_err(translate_err)?; - - temp_output_file.write_all(b"\n").map_err(translate_err)?; - - temp_output_file.persist(output_path).map_err(|e| { - format!("error persisting temporary compiler output {output_path}: {e:?}") - })?; - - Ok(()) - }; + let mut target_data = result_stream.get_value().hex(); + target_data += "\n"; // Try to detect whether we'd put the same output in the output file. // Don't proceed if true. - if let Ok(prev_content) = fs::read_to_string(output_path) { - let prev_trimmed = prev_content.trim(); - let trimmed = target_data.trim(); - if prev_trimmed == trimmed { - // We should try to overwrite here, but not fail if it doesn't - // work. This will accomodate both the read only scenario and - // the scenario where a target file is newer and people want the - // date to be updated. - write_file(output_path, &target_data).ok(); - - // It's the same program, bail regardless. - return Ok(output_path.to_string()); - } - } - - write_file(output_path, &target_data)?; + gentle_overwrite(input_path, output_path, &target_data)?; } Ok(output_path.to_string()) diff --git a/src/classic/clvm_tools/cmds.rs b/src/classic/clvm_tools/cmds.rs index d14304e3e..0b791f9e3 100644 --- a/src/classic/clvm_tools/cmds.rs +++ b/src/classic/clvm_tools/cmds.rs @@ -1,5 +1,6 @@ use core::cell::RefCell; +use std::borrow::Borrow; use std::collections::{BTreeMap, HashMap}; use std::fs; use std::io; @@ -35,6 +36,7 @@ use crate::classic::clvm_tools::debug::{ trace_to_text, }; use crate::classic::clvm_tools::ir::reader::read_ir; +use crate::classic::clvm_tools::log; use crate::classic::clvm_tools::sha256tree::sha256tree; use crate::classic::clvm_tools::stages; use crate::classic::clvm_tools::stages::stage_0::{ @@ -42,7 +44,6 @@ use crate::classic::clvm_tools::stages::stage_0::{ }; use crate::classic::clvm_tools::stages::stage_2::operators::run_program_for_search_paths; use crate::classic::platform::PathJoin; -use crate::compiler::dialect::detect_modern; use crate::classic::platform::argparse::{ Argument, ArgumentParser, ArgumentValue, ArgumentValueConv, IntConversion, NArgsSpec, @@ -52,10 +53,12 @@ use crate::classic::platform::argparse::{ use crate::compiler::cldb::{hex_to_modern_sexp, CldbNoOverride, CldbRun, CldbRunEnv}; use crate::compiler::cldb_hierarchy::{HierarchialRunner, HierarchialStepResult, RunPurpose}; use crate::compiler::clvm::start_step; -use crate::compiler::compiler::{compile_file, run_optimizer, DefaultCompilerOpts}; +use crate::compiler::compiler::{compile_file, DefaultCompilerOpts}; use crate::compiler::comptypes::{CompileErr, CompilerOpts}; use crate::compiler::debug::build_symbol_table_mut; +use crate::compiler::dialect::detect_modern; use crate::compiler::frontend::frontend; +use crate::compiler::optimize::maybe_finalize_program_via_classic_optimizer; use crate::compiler::preprocessor::gather_dependencies; use crate::compiler::prims; use crate::compiler::runtypes::RunFailure; @@ -190,7 +193,7 @@ pub fn call_tool( return Ok(()); } - let args_path_or_code_val = match args.get(&"path_or_code".to_string()) { + let args_path_or_code_val = match args.get("path_or_code") { None => ArgumentValue::ArgArray(vec![]), Some(v) => v.clone(), }; @@ -210,7 +213,7 @@ pub fn call_tool( let conv_result = task.conv.invoke(allocator, &s)?; let sexp = *conv_result.first(); let text = conv_result.rest(); - if args.contains_key(&"script_hash".to_string()) { + if args.contains_key("script_hash") { let data: Vec = sha256tree(allocator, sexp).hex().bytes().collect(); stream.write(Bytes::new(Some(BytesFromType::Raw(data)))); } else if !text.is_empty() { @@ -316,7 +319,7 @@ impl ArgumentValueConv for OperatorsVersion { } pub fn run(args: &[String]) { - env_logger::init(); + log::init(); let mut s = Stream::new(None); launch_tool(&mut s, args, "run", 2); @@ -500,7 +503,7 @@ pub fn cldb_hierarchy( } pub fn cldb(args: &[String]) { - env_logger::init(); + log::init(); let tool_name = "cldb".to_string(); let props = TArgumentParserProps { @@ -536,6 +539,12 @@ pub fn cldb(args: &[String]) { .set_type(Rc::new(PathOrCodeConv {})) .set_help("path to symbol file".to_string()), ); + parser.add_argument( + vec!["-p".to_string(), "--only-print".to_string()], + Argument::new() + .set_action(TArgOptionAction::StoreTrue) + .set_help("only show printing from the program".to_string()), + ); parser.add_argument( vec!["-t".to_string(), "--tree".to_string()], Argument::new() @@ -604,6 +613,8 @@ pub fn cldb(args: &[String]) { _ => None, }); + let only_print = parsed_args.get("only_print").map(|_| true).unwrap_or(false); + let do_optimize = parsed_args .get("optimize") .map(|x| matches!(x, ArgumentValue::ArgBool(true))) @@ -637,11 +648,15 @@ pub fn cldb(args: &[String]) { &input_program, &mut use_symbol_table, ); - if do_optimize { - unopt_res.and_then(|x| run_optimizer(&mut allocator, runner.clone(), Rc::new(x))) - } else { - unopt_res.map(Rc::new) - } + unopt_res.and_then(|x| { + maybe_finalize_program_via_classic_optimizer( + &mut allocator, + runner.clone(), + opts, + false, + &x, + ) + }) } }; @@ -712,7 +727,7 @@ pub fn cldb(args: &[String]) { Box::new(CldbNoOverride::new_symbols(use_symbol_table.clone())), ); - if parsed_args.get("tree").is_some() { + if parsed_args.contains_key("tree") { let result = cldb_hierarchy( runner, Rc::new(prim_map), @@ -731,6 +746,16 @@ pub fn cldb(args: &[String]) { let step = start_step(program, args); let mut cldbrun = CldbRun::new(runner, Rc::new(prim_map), Box::new(cldbenv), step); + let print_tree = |output: &mut Vec<_>, result: &BTreeMap| { + let mut cvt_subtree = BTreeMap::new(); + for (k, v) in result.iter() { + cvt_subtree.insert(k.clone(), YamlElement::String(v.clone())); + } + output.push(cvt_subtree); + }; + + cldbrun.set_print_only(only_print); + loop { if cldbrun.is_ended() { println!("{}", yamlette_string(&output)); @@ -738,11 +763,22 @@ pub fn cldb(args: &[String]) { } if let Some(result) = cldbrun.step(&mut allocator) { - let mut cvt_subtree = BTreeMap::new(); - for (k, v) in result.iter() { - cvt_subtree.insert(k.clone(), YamlElement::String(v.clone())); + if only_print { + if let Some(p) = result.get("Print") { + let mut only_print = BTreeMap::new(); + only_print.insert("Print".to_string(), YamlElement::String(p.clone())); + output.push(only_print); + } else { + let is_final = result.contains_key("Final"); + let is_throw = result.contains_key("Throw"); + let is_failure = result.contains_key("Failure"); + if is_final || is_throw || is_failure { + print_tree(&mut output, &result); + } + } + } else { + print_tree(&mut output, &result); } - output.push(cvt_subtree); } } } @@ -814,6 +850,70 @@ fn fix_log( } } +// A function which performs preprocessing on a whole program and renders the +// output to the user. +// +// This is used in the same way as cc -E in a C compiler; to see what +// preprocessing did to the source so you can debug and improve your macros. +// +// Without this, it's difficult for some to visualize how macro are functioning +// and what forms they output. +fn perform_preprocessing( + stdout: &mut Stream, + opts: Rc, + input_file: &str, + program_text: &str, +) -> Result<(), CompileErr> { + let srcloc = Srcloc::start(input_file); + // Parse the source file. + let parsed = parse_sexp(srcloc.clone(), program_text.bytes())?; + // Get the detected dialect and compose a sigil that matches. + // Classic preprocessing (also shared by standard sigil 21 and 21) does macro + // expansion during the compile process, making all macros available to all + // code regardless of its lexical order and therefore isn't rendered in a + // unified way (for example, 'com' and 'mod' forms invoke macros when + // encountered and expanded. By contrast strict mode reads the macros and + // evaluates them in that order (as in C). + // + // The result is fully rendered before the next stage of compilation so that + // it can be inspected and so that the execution environment for macros is + // fully and cleanly separated from compile time. + let stepping_form_text = match opts.dialect().stepping { + Some(21) => Some("(include *strict-cl-21*)".to_string()), + Some(n) => Some(format!("(include *standard-cl-{n}*)")), + _ => None, + }; + let frontend = frontend(opts, &parsed)?; + let fe_sexp = frontend.to_sexp(); + let with_stepping = if let Some(s) = stepping_form_text { + let parsed_stepping_form = parse_sexp(srcloc.clone(), s.bytes())?; + if let sexp::SExp::Cons(_, a, rest) = fe_sexp.borrow() { + Rc::new(sexp::SExp::Cons( + srcloc.clone(), + a.clone(), + Rc::new(sexp::SExp::Cons( + srcloc.clone(), + parsed_stepping_form[0].clone(), + rest.clone(), + )), + )) + } else { + fe_sexp + } + } else { + fe_sexp + }; + + let whole_mod = sexp::SExp::Cons( + srcloc.clone(), + Rc::new(sexp::SExp::Atom(srcloc, b"mod".to_vec())), + with_stepping, + ); + + stdout.write_str(&format!("{}", whole_mod)); + Ok(()) +} + fn get_disassembly_ver(p: &HashMap) -> Option { if let Some(ArgumentValue::ArgInt(x)) = p.get("operators_version") { return Some(*x as usize); @@ -966,6 +1066,18 @@ pub fn launch_tool(stdout: &mut Stream, args: &[String], tool_name: &str, defaul .set_type(Rc::new(PathJoin {})) .set_default(ArgumentValue::ArgString(None, "main.sym".to_string())), ); + parser.add_argument( + vec!["--strict".to_string()], + Argument::new() + .set_action(TArgOptionAction::StoreTrue) + .set_help("For modern dialects, don't treat unknown names as constants".to_string()), + ); + parser.add_argument( + vec!["-E".to_string(), "--preprocess".to_string()], + Argument::new() + .set_action(TArgOptionAction::StoreTrue) + .set_help("Perform strict mode preprocessing and show the result".to_string()), + ); parser.add_argument( vec!["--operators-version".to_string()], Argument::new() @@ -1212,7 +1324,7 @@ pub fn launch_tool(stdout: &mut Stream, args: &[String], tool_name: &str, defaul emit_symbol_output = true; } - if parsed_args.get("table").is_some() { + if parsed_args.contains_key("table") { emit_symbol_output = true; } @@ -1257,7 +1369,7 @@ pub fn launch_tool(stdout: &mut Stream, args: &[String], tool_name: &str, defaul .and_then(|pre_forms| { let context = standard_type_context(); let compileform = frontend(opts.clone(), &pre_forms)?; - let target_type = context.typecheck_chialisp_program(&compileform)?; + let target_type = context.typecheck_chialisp_program(opts, &compileform)?; Ok(context.reify(&target_type, None)) }) { @@ -1279,8 +1391,7 @@ pub fn launch_tool(stdout: &mut Stream, args: &[String], tool_name: &str, defaul .unwrap_or_else(|| "main.sym".to_string()); // In testing: short circuit for modern compilation. - // Now stepping is the optional part. - if let Some(dialect) = dialect.and_then(|d| d.stepping) { + if let Some(stepping) = dialect.as_ref().and_then(|d| d.stepping) { let do_optimize = parsed_args .get("optimize") .map(|x| matches!(x, ArgumentValue::ArgBool(true))) @@ -1288,12 +1399,21 @@ pub fn launch_tool(stdout: &mut Stream, args: &[String], tool_name: &str, defaul let runner = Rc::new(DefaultProgramRunner::new()); let use_filename = input_file.unwrap_or_else(|| "*command*".to_string()); let opts = Rc::new(DefaultCompilerOpts::new(&use_filename)) - .set_optimize(do_optimize) + .set_dialect(dialect.unwrap_or_default()) + .set_optimize(do_optimize || stepping > 22) .set_search_paths(&search_paths) - .set_frontend_opt(dialect > 21) + .set_frontend_opt(stepping == 22) .set_disassembly_ver(get_disassembly_ver(&parsed_args)); let mut symbol_table = HashMap::new(); + // Short circuit preprocessing display. + if parsed_args.contains_key("preprocess") { + if let Err(e) = perform_preprocessing(stdout, opts, &use_filename, &input_program) { + stdout.write_str(&format!("{}: {}", e.0, e.1)); + } + return; + } + let unopt_res = compile_file( &mut allocator, runner.clone(), @@ -1301,11 +1421,15 @@ pub fn launch_tool(stdout: &mut Stream, args: &[String], tool_name: &str, defaul &input_program, &mut symbol_table, ); - let res = if do_optimize { - unopt_res.and_then(|x| run_optimizer(&mut allocator, runner, Rc::new(x))) - } else { - unopt_res.map(Rc::new) - }; + let res = unopt_res.and_then(|x| { + maybe_finalize_program_via_classic_optimizer( + &mut allocator, + runner, + opts, + do_optimize, + &x, + ) + }); match res { Ok(r) => { @@ -1481,7 +1605,7 @@ pub fn launch_tool(stdout: &mut Stream, args: &[String], tool_name: &str, defaul let result = run_program_result.1; let time_done = SystemTime::now(); - if parsed_args.get("cost").is_some() { + if parsed_args.contains_key("cost") { if cost > 0 { cost += cost_offset; } @@ -1489,7 +1613,7 @@ pub fn launch_tool(stdout: &mut Stream, args: &[String], tool_name: &str, defaul }; if let Some(ArgumentValue::ArgBool(true)) = parsed_args.get("time") { - if parsed_args.get("hex").is_some() { + if parsed_args.contains_key("hex") { stdout.write_str(&format!( "read_hex: {}\n", time_read_hex @@ -1571,13 +1695,15 @@ pub fn launch_tool(stdout: &mut Stream, args: &[String], tool_name: &str, defaul .unwrap_or_else(|| false); if emit_symbol_output { - if parsed_args.get("table").is_some() { + if parsed_args.contains_key("table") { trace_to_table( &mut allocator, stdout, only_exn, &log_content, symbol_table, + // Clippy: disassemble no longer requires mutability, + // but this callback interface delivers it. &|allocator, p| disassemble(allocator, p, disassembly_ver), ); } else { @@ -1588,6 +1714,7 @@ pub fn launch_tool(stdout: &mut Stream, args: &[String], tool_name: &str, defaul only_exn, &log_content, symbol_table, + // Same as above. &|allocator, p| disassemble(allocator, p, disassembly_ver), ); } diff --git a/src/classic/clvm_tools/ir/reader.rs b/src/classic/clvm_tools/ir/reader.rs index 78667f418..0623fb805 100644 --- a/src/classic/clvm_tools/ir/reader.rs +++ b/src/classic/clvm_tools/ir/reader.rs @@ -185,7 +185,7 @@ pub fn consume_atom(s: &mut IRReader, b: &Bytes) -> Result, Synta } } -fn enlist_ir(vec: &mut Vec, tail: IRRepr) -> IRRepr { +fn enlist_ir(vec: &mut [IRRepr], tail: IRRepr) -> IRRepr { let mut result = tail; for i_reverse in 0..vec.len() { let i = vec.len() - i_reverse - 1; diff --git a/src/classic/clvm_tools/log.rs b/src/classic/clvm_tools/log.rs new file mode 100644 index 000000000..5af0327c8 --- /dev/null +++ b/src/classic/clvm_tools/log.rs @@ -0,0 +1,12 @@ +use std::sync::atomic::AtomicUsize; +use std::sync::atomic::Ordering; + +lazy_static! { + pub static ref LOG_INIT: AtomicUsize = AtomicUsize::new(0); +} + +pub fn init() { + if LOG_INIT.fetch_add(1, Ordering::SeqCst) == 0 { + env_logger::init(); + } +} diff --git a/src/classic/clvm_tools/mod.rs b/src/classic/clvm_tools/mod.rs index a5bd88464..35a18b6ab 100644 --- a/src/classic/clvm_tools/mod.rs +++ b/src/classic/clvm_tools/mod.rs @@ -4,6 +4,7 @@ pub mod cmds; pub mod curry; pub mod debug; pub mod ir; +pub mod log; pub mod node_path; pub mod pattern_match; pub mod sha256tree; diff --git a/src/classic/clvm_tools/stages/stage_0.rs b/src/classic/clvm_tools/stages/stage_0.rs index 6292411b1..df5fd9b23 100644 --- a/src/classic/clvm_tools/stages/stage_0.rs +++ b/src/classic/clvm_tools/stages/stage_0.rs @@ -1,5 +1,5 @@ use clvm_rs::allocator::{Allocator, NodePtr}; -use clvm_rs::chia_dialect::{ChiaDialect, ENABLE_BLS_OPS, ENABLE_SECP_OPS, NO_UNKNOWN_OPS}; +use clvm_rs::chia_dialect::{ChiaDialect, NO_UNKNOWN_OPS}; use clvm_rs::cost::Cost; use clvm_rs::reduction::Response; @@ -47,7 +47,7 @@ impl TRunProgram for DefaultProgramRunner { run_program_with_pre_eval( allocator, - &ChiaDialect::new(NO_UNKNOWN_OPS | ENABLE_BLS_OPS | ENABLE_SECP_OPS), + &ChiaDialect::new(NO_UNKNOWN_OPS), program, args, max_cost, diff --git a/src/classic/clvm_tools/stages/stage_2/operators.rs b/src/classic/clvm_tools/stages/stage_2/operators.rs index 2e69564d3..5b433395f 100644 --- a/src/classic/clvm_tools/stages/stage_2/operators.rs +++ b/src/classic/clvm_tools/stages/stage_2/operators.rs @@ -5,7 +5,7 @@ use std::path::PathBuf; use std::rc::Rc; use clvm_rs::allocator::{Allocator, NodePtr, SExp}; -use clvm_rs::chia_dialect::{ChiaDialect, ENABLE_BLS_OPS, ENABLE_SECP_OPS, NO_UNKNOWN_OPS}; +use clvm_rs::chia_dialect::{ChiaDialect, NO_UNKNOWN_OPS}; use clvm_rs::cost::Cost; use clvm_rs::dialect::{Dialect, OperatorSet}; use clvm_rs::reduction::{EvalErr, Reduction, Response}; @@ -122,9 +122,7 @@ impl Drop for CompilerOperators { impl CompilerOperatorsInternal { pub fn new(source_file: &str, search_paths: Vec, symbols_extra_info: bool) -> Self { - let base_dialect = Rc::new(ChiaDialect::new( - NO_UNKNOWN_OPS | ENABLE_BLS_OPS | ENABLE_SECP_OPS, - )); + let base_dialect = Rc::new(ChiaDialect::new(NO_UNKNOWN_OPS)); let base_runner = Rc::new(DefaultProgramRunner::new()); CompilerOperatorsInternal { base_dialect, diff --git a/src/classic/platform/argparse.rs b/src/classic/platform/argparse.rs index d39bb2353..916d1343f 100644 --- a/src/classic/platform/argparse.rs +++ b/src/classic/platform/argparse.rs @@ -397,7 +397,7 @@ impl ArgumentParser { } } - if params.get(&"help".to_string()).is_some() { + if params.contains_key("help") { let usage = self.compile_help_messages(); return Err(usage); } diff --git a/src/compiler/cldb.rs b/src/compiler/cldb.rs index 95df3dcd2..d8bb942cf 100644 --- a/src/compiler/cldb.rs +++ b/src/compiler/cldb.rs @@ -21,8 +21,13 @@ use crate::compiler::clvm::{convert_from_clvm_rs, run_step, RunStep}; use crate::compiler::runtypes::RunFailure; use crate::compiler::sexp::SExp; use crate::compiler::srcloc::Srcloc; +use crate::util::u8_from_number; use crate::util::Number; +fn print_atom() -> SExp { + SExp::Atom(Srcloc::start("*print*"), b"$print$".to_vec()) +} + #[derive(Clone, Debug)] pub struct PriorResult { reference: usize, @@ -103,10 +108,41 @@ pub struct CldbRun { to_print: BTreeMap, in_expr: bool, row: usize, + print_only: bool, outputs_to_step: HashMap, } +fn humanize(a: Rc) -> Rc { + match a.borrow() { + SExp::Integer(l, i) => { + // If it has a nice string representation then show that. + let bytes_of_int = u8_from_number(i.clone()); + if bytes_of_int.len() > 2 && bytes_of_int.iter().all(|b| *b >= 32 && *b < 127) { + Rc::new(SExp::QuotedString(l.clone(), b'\'', bytes_of_int)) + } else { + a.clone() + } + } + SExp::Cons(l, a, b) => { + let new_a = humanize(a.clone()); + let new_b = humanize(b.clone()); + Rc::new(SExp::Cons(l.clone(), new_a, new_b)) + } + _ => a.clone(), + } +} + +fn is_print_request(a: &SExp) -> Option<(Srcloc, Rc)> { + if let SExp::Cons(l, f, r) = a { + if &print_atom() == f.borrow() { + return Some((l.clone(), humanize(r.clone()))); + } + } + + None +} + impl CldbRun { /// Create a new CldbRun for running a program. /// Takes an CldbEnvironment and a prepared RunStep, which will be stepped @@ -129,9 +165,14 @@ impl CldbRun { in_expr: false, row: 0, outputs_to_step: HashMap::::new(), + print_only: false, } } + pub fn set_print_only(&mut self, pronly: bool) { + self.print_only = pronly; + } + pub fn is_ended(&self) -> bool { self.ended } @@ -140,6 +181,10 @@ impl CldbRun { self.final_result.clone() } + pub fn should_print_basic_output(&self) -> bool { + !self.print_only + } + pub fn step(&mut self, allocator: &mut Allocator) -> Option> { let mut produce_result = false; let mut result = BTreeMap::new(); @@ -150,6 +195,7 @@ impl CldbRun { self.runner.clone(), self.prim_map.clone(), &self.step, + None, ), }; @@ -158,23 +204,27 @@ impl CldbRun { match &new_step { Ok(RunStep::OpResult(l, x, _p)) => { if self.in_expr { - self.to_print - .insert("Result-Location".to_string(), l.to_string()); - self.to_print.insert("Value".to_string(), x.to_string()); - self.to_print - .insert("Row".to_string(), self.row.to_string()); - if let Ok(n) = x.get_number() { - self.outputs_to_step.insert( - n, - PriorResult { - reference: self.row, - // value: x.clone(), // for future - }, - ); + if self.should_print_basic_output() { + self.to_print + .insert("Result-Location".to_string(), l.to_string()); + self.to_print.insert("Value".to_string(), x.to_string()); + self.to_print + .insert("Row".to_string(), self.row.to_string()); + + if let Ok(n) = x.get_number() { + self.outputs_to_step.insert( + n, + PriorResult { + reference: self.row, + // value: x.clone(), // for future + }, + ); + } + swap(&mut self.to_print, &mut result); + produce_result = true; } + self.in_expr = false; - swap(&mut self.to_print, &mut result); - produce_result = true; } } Ok(RunStep::Done(l, x)) => { @@ -189,27 +239,43 @@ impl CldbRun { } Ok(RunStep::Step(_sexp, _c, _p)) => {} Ok(RunStep::Op(sexp, c, a, None, _p)) => { - self.to_print - .insert("Operator-Location".to_string(), a.loc().to_string()); - self.to_print - .insert("Operator".to_string(), sexp.to_string()); + let should_print_basic_output = self.should_print_basic_output(); + if should_print_basic_output { + self.to_print + .insert("Operator-Location".to_string(), a.loc().to_string()); + self.to_print + .insert("Operator".to_string(), sexp.to_string()); + } + if let Ok(v) = sexp.get_number() { - if v == 11_u32.to_bigint().unwrap() { + if v == 11_u32.to_bigint().unwrap() && should_print_basic_output { // Build source tree for hashes. let arg_associations = get_arg_associations(&self.outputs_to_step, a.clone()); let args = format_arg_inputs(&arg_associations); self.to_print.insert("Argument-Refs".to_string(), args); + } else if v == 34_u32.to_bigint().unwrap() { + // Handle diagnostic output. + if let Some((loc, outputs)) = is_print_request(a) { + self.to_print + .insert("Print-Location".to_string(), loc.to_string()); + self.to_print + .insert("Print".to_string(), outputs.to_string()); + swap(&mut self.to_print, &mut result); + produce_result = true; + } } } - self.env.add_context( - sexp.borrow(), - c.borrow(), - Some(a.clone()), - &mut self.to_print, - ); - self.env.add_function(sexp, &mut self.to_print); - self.in_expr = true; + if should_print_basic_output { + self.env.add_context( + sexp.borrow(), + c.borrow(), + Some(a.clone()), + &mut self.to_print, + ); + self.env.add_function(sexp, &mut self.to_print); + self.in_expr = true; + } } Ok(RunStep::Op(_sexp, _c, _a, Some(_v), _p)) => {} Err(RunFailure::RunExn(l, s)) => { diff --git a/src/compiler/clvm.rs b/src/compiler/clvm.rs index f0020efab..7246aae96 100644 --- a/src/compiler/clvm.rs +++ b/src/compiler/clvm.rs @@ -20,6 +20,16 @@ use crate::compiler::srcloc::Srcloc; use crate::util::{number_from_u8, u8_from_number, Number}; +/// Provide a way of intercepting and running new primitives. +pub trait PrimOverride { + fn try_handle( + &self, + head: Rc, + context: Rc, + tail: Rc, + ) -> Result>, RunFailure>; +} + /// An object which contains the state of a running CLVM program in a compact /// form. /// @@ -161,7 +171,15 @@ fn translate_head( Some(v) => Ok(Rc::new(v.with_loc(l.clone()))), }, SExp::Cons(_l, _a, nil) => match nil.borrow() { - SExp::Nil(_l1) => run(allocator, runner, prim_map, sexp.clone(), context, None), + SExp::Nil(_l1) => run( + allocator, + runner, + prim_map, + sexp.clone(), + context, + None, + None, + ), _ => Err(RunFailure::RunErr( sexp.loc(), format!("Unexpected head form in clvm {sexp}"), @@ -393,6 +411,7 @@ pub fn run_step( runner: Rc, prim_map: Rc, Rc>>, step_: &RunStep, + prim_override: Option<&dyn PrimOverride>, ) -> Result { let mut step = step_.clone(); @@ -496,7 +515,7 @@ pub fn run_step( } } } - RunStep::Op(head, _context, tail, None, parent) => { + RunStep::Op(head, context, tail, None, parent) => { let aval = atom_value(head.clone())?; let apply_atom = 2_i32.to_bigint().unwrap(); let if_atom = 3_i32.to_bigint().unwrap(); @@ -514,6 +533,12 @@ pub fn run_step( -1 }; + if let Some(ovr) = prim_override { + if let Some(res) = ovr.try_handle(head.clone(), context.clone(), tail.clone())? { + return Ok(RunStep::OpResult(res.loc(), res.clone(), parent.clone())); + } + } + let op = if aval == apply_atom { "apply".to_string() } else if aval == if_atom { @@ -629,6 +654,7 @@ pub fn run( prim_map: Rc, Rc>>, sexp_: Rc, context_: Rc, + prim_override: Option<&dyn PrimOverride>, iter_limit: Option, ) -> Result, RunFailure> { let mut step = start_step(sexp_, context_); @@ -641,7 +667,13 @@ pub fn run( } } iters += 1; - step = run_step(allocator, runner.clone(), prim_map.clone(), &step)?; + step = run_step( + allocator, + runner.clone(), + prim_map.clone(), + &step, + prim_override, + )?; if let RunStep::Done(_, x) = step { return Ok(x); } @@ -681,6 +713,7 @@ pub fn parse_and_run( prim_map, code[0].clone(), args[0].clone(), + None, step_limit, ) } diff --git a/src/compiler/codegen.rs b/src/compiler/codegen.rs index ead801b6d..eaef4fdae 100644 --- a/src/compiler/codegen.rs +++ b/src/compiler/codegen.rs @@ -8,24 +8,25 @@ use num_bigint::ToBigInt; use crate::classic::clvm::__type_compatibility__::bi_one; -use crate::compiler::clvm::run; -use crate::compiler::compiler::{is_at_capture, run_optimizer}; +use crate::compiler::clvm::{run, truthy}; +use crate::compiler::compiler::is_at_capture; use crate::compiler::comptypes::{ fold_m, join_vecs_to_string, list_to_cons, Binding, BindingPattern, BodyForm, CallSpec, Callable, CompileErr, CompileForm, CompiledCode, CompilerOpts, ConstantKind, DefunCall, DefunData, HelperForm, InlineFunction, LetData, LetFormInlineHint, LetFormKind, PrimaryCodegen, - RawCallSpec, + RawCallSpec, SyntheticType, }; use crate::compiler::debug::{build_swap_table_mut, relabel}; use crate::compiler::evaluate::{Evaluator, EVAL_STACK_LIMIT}; use crate::compiler::frontend::{compile_bodyform, make_provides_set}; use crate::compiler::gensym::gensym; use crate::compiler::inline::{replace_in_inline, synthesize_args}; -use crate::compiler::optimize::optimize_expr; +use crate::compiler::lambda::lambda_codegen; use crate::compiler::prims::{primapply, primcons, primquote}; use crate::compiler::runtypes::RunFailure; -use crate::compiler::sexp::{decode_string, SExp}; +use crate::compiler::sexp::{decode_string, printable, SExp}; use crate::compiler::srcloc::Srcloc; +use crate::compiler::StartOfCodegenOptimization; use crate::compiler::{BasicCompileContext, CompileContextWrapper}; use crate::util::{toposort, u8_from_number, TopoSortItem}; @@ -68,6 +69,33 @@ fn cons_bodyform(loc: Srcloc, left: Rc, right: Rc) -> BodyFo ) } +fn empty_left_env(env: Rc) -> Option> { + if let SExp::Cons(_, l, r) = env.borrow() { + if truthy(l.clone()) { + None + } else { + Some(r.clone()) + } + } else { + // It's an unusual env, so be conservative. + None + } +} + +fn enable_nil_env_mode_for_stepping_23_or_greater( + opts: Rc, + code_generator: &mut PrimaryCodegen, +) { + if let Some(s) = opts.dialect().stepping { + if s >= 23 && opts.optimize() { + if let Some(whole_env) = empty_left_env(code_generator.env.clone()) { + code_generator.left_env = false; + code_generator.env = whole_env; + } + } + } +} + /* * Produce a structure that mimics the expected environment if the current inline * context had been a function. @@ -181,18 +209,104 @@ fn create_name_lookup_( } } +// Tell whether there's a non-inline defun called 'name' in this program. +// If so, the reference to this name is a reference to a function, which +// will make variable references to it capture the program's function +// environment. +fn is_defun_in_codegen(compiler: &PrimaryCodegen, name: &[u8]) -> bool { + // Check for an input defun that matches the name. + for h in compiler.original_helpers.iter() { + if matches!(h, HelperForm::Defun(false, _)) && h.name() == name { + return true; + } + } + + false +} + +// At the CLVM level, given a list of clvm expressios, make an expression +// that contains that list using conses. +fn make_list(loc: Srcloc, elements: Vec>) -> Rc { + let mut res = Rc::new(SExp::Nil(loc.clone())); + for e in elements.iter().rev() { + res = Rc::new(primcons(loc.clone(), e.clone(), res)); + } + res +} + +// +// Get the clvm expression that represents the indicated function as a +// callable value using the CLVM a operator. This value can be returned +// and even passed to another program because it carries the required +// environment to call functions it depends on from the call site. +// +// To do this, it writes an expression that conses the left env. +// +// (list (q . 2) (c (q . 1) n) (list (q . 4) (c (q . 1) 2) (q . 1))) +// +// Something like: +// (apply (quoted (expanded n)) (cons (quoted (expanded 2)) given-args)) +// +fn lambda_for_defun(loc: Srcloc, lookup: Rc) -> Rc { + let one_atom = Rc::new(SExp::Atom(loc.clone(), vec![1])); + let two_atom = Rc::new(SExp::Atom(loc.clone(), vec![2])); + let apply_atom = two_atom.clone(); + let cons_atom = Rc::new(SExp::Atom(loc.clone(), vec![4])); + make_list( + loc.clone(), + vec![ + Rc::new(primquote(loc.clone(), apply_atom)), + Rc::new(primcons( + loc.clone(), + Rc::new(primquote(loc.clone(), one_atom.clone())), + lookup, + )), + make_list( + loc.clone(), + vec![ + Rc::new(primquote(loc.clone(), cons_atom)), + Rc::new(primcons( + loc.clone(), + Rc::new(primquote(loc.clone(), one_atom.clone())), + two_atom, + )), + Rc::new(primquote(loc, one_atom)), + ], + ), + ], + ) +} + fn create_name_lookup( compiler: &PrimaryCodegen, l: Srcloc, name: &[u8], + // If the lookup is in head position, then it is a lookup as a callable, + // otherwise it's a lookup as a variable, which means that if a function + // is named, it will be built into an expression that allows it to be + // called by a CLVM 'a' operator as one would expect, regardless of how + // it integrates with the rest of the program it lives in. + as_variable: bool, ) -> Result, CompileErr> { compiler .constants .get(name) .map(|x| Ok(x.clone())) .unwrap_or_else(|| { - create_name_lookup_(l.clone(), name, compiler.env.clone(), compiler.env.clone()) - .map(|i| Rc::new(SExp::Integer(l.clone(), i.to_bigint().unwrap()))) + create_name_lookup_(l.clone(), name, compiler.env.clone(), compiler.env.clone()).map( + |i| { + // Determine if it's a defun. If so we can ensure that it's + // callable like a lambda by repeating the left env into it. + let find_program = Rc::new(SExp::Integer(l.clone(), i.to_bigint().unwrap())); + if as_variable && is_defun_in_codegen(compiler, name) { + // It's a defun. Harden the result so it is callable + // directly by the CLVM 'a' operator. + lambda_for_defun(l.clone(), find_program) + } else { + find_program + } + }, + ) }) } @@ -220,10 +334,13 @@ pub fn get_callable( SExp::Atom(l, name) => { let macro_def = compiler.macros.get(name); let inline = compiler.inlines.get(name); - let defun = create_name_lookup(compiler, l.clone(), name); + // We're getting a callable, so the access requested is not as + // a variable. + let defun = create_name_lookup(compiler, l.clone(), name, false); let prim = get_prim(l.clone(), compiler.prims.clone(), name); let atom_is_com = *name == "com".as_bytes().to_vec(); - let atom_is_at = *name == "@".as_bytes().to_vec(); + let atom_is_at = + *name == "@".as_bytes().to_vec() || *name == "@*env*".as_bytes().to_vec(); match (macro_def, inline, defun, prim, atom_is_com, atom_is_at) { (Some(macro_def), _, _, _, _, _) => { let macro_def_clone: &SExp = macro_def.borrow(); @@ -273,6 +390,7 @@ pub fn process_macro_call( opts.prim_map(), code, Rc::new(args_to_macro), + None, Some(MACRO_TIME_LIMIT), ) .map_err(|e| match e { @@ -446,6 +564,10 @@ fn compile_call( l.clone(), Rc::new(SExp::Integer(l.clone(), i.clone())), )), + BodyForm::Quoted(SExp::Integer(l, i)) => Ok(CompiledCode( + l.clone(), + Rc::new(SExp::Integer(l.clone(), i.clone())), + )), _ => Err(CompileErr( al.clone(), "@ form only accepts integers at present".to_string(), @@ -522,8 +644,13 @@ pub fn do_mod_codegen( let without_env = opts.set_start_env(None).set_in_defun(false); let mut throwaway_symbols = HashMap::new(); let runner = context.runner(); - let mut context_wrapper = - CompileContextWrapper::new(context.allocator(), runner.clone(), &mut throwaway_symbols); + let optimizer = context.optimizer.duplicate(); + let mut context_wrapper = CompileContextWrapper::new( + context.allocator(), + runner.clone(), + &mut throwaway_symbols, + optimizer, + ); let code = codegen(&mut context_wrapper.context, without_env, program)?; Ok(CompiledCode( program.loc.clone(), @@ -535,6 +662,30 @@ pub fn do_mod_codegen( )) } +fn is_cons(bf: &BodyForm) -> bool { + if let BodyForm::Value(v) = bf { + if let SExp::Atom(_, vec) = v.atomize() { + return vec == [4] || vec == b"r"; + } + } + + false +} + +fn is_at_env(bf: &BodyForm) -> bool { + if let BodyForm::Value(v) = bf { + if let SExp::Atom(_, vec) = v.atomize() { + return vec == b"@*env*"; + } + } + + false +} + +fn addresses_user_env(call: &[Rc]) -> bool { + call.len() == 2 && is_cons(call[0].borrow()) && is_at_env(call[1].borrow()) +} + pub fn generate_expr_code( context: &mut BasicCompileContext, opts: Rc, @@ -557,15 +708,46 @@ pub fn generate_expr_code( BodyForm::Value(v) => { match v { SExp::Atom(l, atom) => { - if *atom == "@".as_bytes().to_vec() { + if *atom == "@".as_bytes().to_vec() || *atom == "@*env*".as_bytes().to_vec() { Ok(CompiledCode( l.clone(), Rc::new(SExp::Integer(l.clone(), bi_one())), )) + } else if atom.is_empty() { + // Ensure that we handle empty atoms as nils. + generate_expr_code( + context, + opts, + compiler, + Rc::new(BodyForm::Value(SExp::Nil(l.clone()))), + ) } else { - create_name_lookup(compiler, l.clone(), atom) + // This is as a variable access, given that we've got + // a Value bodyform containing an Atom, so if a defun + // is returned, it should be a packaged callable. + create_name_lookup(compiler, l.clone(), atom, true) .map(|f| Ok(CompiledCode(l.clone(), f))) .unwrap_or_else(|_| { + if opts.dialect().strict && printable(atom, false) { + // Finally enable strictness for variable names. + // This is possible because the modern macro system + // takes great care to preserve as much information + // from the source code as possible. + // + // When we come here in strict mode, we have + // a string, integer or atom depending on the + // user's desire and the explicitly generated + // result from the macro, therefore we can return + // an error if this atom didn't have a binding. + return Err(CompileErr( + l.clone(), + format!( + "Unbound use of {} as a variable name", + decode_string(atom) + ), + )); + } + // Pass through atoms that don't look up on behalf of // macros, as it's possible that a macro returned // something that's canonically a name in number form. @@ -578,19 +760,26 @@ pub fn generate_expr_code( }) } } - // Since macros are in this language and the runtime has - // a very narrow data representation, we'll need to - // accomodate bare numbers coming back in place of identifiers. - // I'm considering ways to make this better. - SExp::Integer(l, i) => generate_expr_code( - context, - opts, - compiler, - Rc::new(BodyForm::Value(SExp::Atom( - l.clone(), - u8_from_number(i.clone()), - ))), - ), + SExp::Integer(l, i) => { + // This code can assume that an integer is an integer because + // strict mode closes the necessary loophole below. Values + // intended as variable names are never crushed into integer + // like values from modern macros. + let ambiguous_int_value = if opts.dialect().strict { + Rc::new(BodyForm::Quoted(SExp::Integer(l.clone(), i.clone()))) + } else { + // Since macros are in this language and the runtime has + // a very narrow data representation, we'll need to + // accomodate bare numbers coming back in place of identifiers, + // but only in legacy non-strict mode. + Rc::new(BodyForm::Value(SExp::Atom( + l.clone(), + u8_from_number(i.clone()), + ))) + }; + + generate_expr_code(context, opts, compiler, ambiguous_int_value) + } _ => Ok(CompiledCode( v.loc(), Rc::new(primquote(v.loc(), Rc::new(v.clone()))), @@ -598,6 +787,13 @@ pub fn generate_expr_code( } } BodyForm::Call(l, list, tail) => { + // Recognize attempts to get the input arguments. They're paired with + // a left env in the usual case, but it can be omitted if there are no + // freestanding functions. In that case, the user args are just the + // whole env. + if !compiler.left_env && addresses_user_env(list) { + return generate_expr_code(context, opts, compiler, list[1].clone()); + } if list.is_empty() { Err(CompileErr( l.clone(), @@ -656,7 +852,7 @@ fn codegen_( compiler: &PrimaryCodegen, h: &HelperForm, ) -> Result { - match &h { + match h { HelperForm::Defun(inline, defun) => { if *inline { // Note: this just replaces a dummy function inserted earlier. @@ -679,21 +875,7 @@ fn codegen_( defun.args.clone(), ))); - let runner = context.runner(); - let opt = if opts.optimize() { - // Run optimizer on frontend style forms. - optimize_expr( - context.allocator(), - opts.clone(), - runner, - compiler, - defun.body.clone(), - ) - .map(|x| x.1) - .unwrap_or_else(|| defun.body.clone()) - } else { - defun.body.clone() - }; + let opt = context.pre_codegen_function_optimize(opts.clone(), compiler, defun)?; let tocompile = SExp::Cons( defun.loc.clone(), @@ -719,11 +901,7 @@ fn codegen_( &mut unused_symbol_table, ) .and_then(|code| { - if opts.optimize() { - run_optimizer(context.allocator(), runner, Rc::new(code)) - } else { - Ok(Rc::new(code)) - } + context.post_codegen_function_optimize(opts.clone(), Some(h), Rc::new(code)) }) .and_then(|code| { fail_if_present(defun.loc.clone(), &compiler.inlines, &defun.name, code) @@ -748,8 +926,12 @@ fn codegen_( } } -fn is_defun(b: &HelperForm) -> bool { - matches!(b, HelperForm::Defun(false, _)) +fn is_defun_or_tabled_constant(b: &HelperForm) -> bool { + match b { + HelperForm::Defun(false, _) => true, + HelperForm::Defconstant(cdata) => cdata.tabled, + _ => false, + } } pub fn empty_compiler(prim_map: Rc, Rc>>, l: Srcloc) -> PrimaryCodegen { @@ -759,6 +941,7 @@ pub fn empty_compiler(prim_map: Rc, Rc>>, l: Srcloc) -> Pr PrimaryCodegen { prims: prim_map, constants: HashMap::new(), + tabled_constants: HashMap::new(), inlines: HashMap::new(), macros: HashMap::new(), defuns: HashMap::new(), @@ -769,6 +952,7 @@ pub fn empty_compiler(prim_map: Rc, Rc>>, l: Srcloc) -> Pr final_expr: Rc::new(BodyForm::Quoted(nil)), final_code: None, function_symbols: HashMap::new(), + left_env: true, } } @@ -813,7 +997,7 @@ fn generate_let_defun( // binary size, when permitted. Sometimes the user will signal a // preference. should_inline_let(inline_hint), - DefunData { + Box::new(DefunData { loc: l.clone(), nl: l, kw: kwl, @@ -821,8 +1005,9 @@ fn generate_let_defun( orig_args: inner_function_args.clone(), args: inner_function_args, body, + synthetic: Some(SyntheticType::NoInlinePreference), ty: None, - }, + }), ) } @@ -1056,7 +1241,7 @@ pub fn hoist_body_let_binding( ))), Rc::new(BodyForm::Value(SExp::Atom( letdata.loc.clone(), - "@".as_bytes().to_vec(), + "@*env*".as_bytes().to_vec(), ))), ], None, @@ -1101,6 +1286,49 @@ pub fn hoist_body_let_binding( Rc::new(BodyForm::Call(l.clone(), new_call_list, new_tail)), )) } + BodyForm::Lambda(letdata) => { + // A lambda is exactly the same as + // 1) A function whose argument list is the captures plus the + // non-capture arguments. + // 2) A call site which includes a reference to the function + // surrounded with a structure that curries on the capture + // arguments. + + // Compose the function and return it as a desugared function. + // The functions desugared here also come from let bindings. + let new_function_args = Rc::new(SExp::Cons( + letdata.loc.clone(), + letdata.capture_args.clone(), + letdata.args.clone(), + )); + let new_function_name = gensym(b"lambda".to_vec()); + let (mut new_helpers_from_body, new_body) = hoist_body_let_binding( + Some(new_function_args.clone()), + new_function_args.clone(), + letdata.body.clone(), + )?; + let function = HelperForm::Defun( + false, + Box::new(DefunData { + loc: letdata.loc.clone(), + name: new_function_name.clone(), + kw: letdata.kw.clone(), + nl: letdata.args.loc(), + orig_args: new_function_args.clone(), + args: new_function_args, + body: new_body, + synthetic: Some(SyntheticType::WantNonInline), + ty: None, + }), + ); + new_helpers_from_body.push(function); + + // new_expr is the generated code at the call site. The reference + // to the actual function additionally is enriched by a left-env + // reference that gives it access to the program. + let new_expr = lambda_codegen(&new_function_name, letdata)?; + Ok((new_helpers_from_body, Rc::new(new_expr))) + } _ => Ok((Vec::new(), body.clone())), } } @@ -1128,16 +1356,11 @@ pub fn process_helper_let_bindings(helpers: &[HelperForm]) -> Result { @@ -1228,14 +1456,13 @@ fn start_codegen( Some(EVAL_STACK_LIMIT), )?; if let BodyForm::Quoted(q) = constant_result.borrow() { - code_generator.add_constant( - &defc.name, - Rc::new(SExp::Cons( - defc.loc.clone(), - Rc::new(SExp::Atom(defc.loc.clone(), vec![1])), - Rc::new(q.clone()), - )), - ) + let res = Rc::new(q.clone()); + if defc.tabled { + code_generator.add_tabled_constant(&defc.name, res) + } else { + let quoted = primquote(defc.loc.clone(), res); + code_generator.add_constant(&defc.name, Rc::new(quoted)) + } } else { return Err(CompileErr( defc.loc.clone(), @@ -1259,24 +1486,21 @@ fn start_codegen( .set_code_generator(code_generator.clone()) .set_in_defun(false) .set_stdenv(false) + .set_start_env(None) .set_frontend_opt(false); let runner = context.runner(); - updated_opts - .compile_program( - context.allocator(), - runner.clone(), - macro_program, - &mut HashMap::new(), - ) - .and_then(|code| { - if opts.optimize() { - run_optimizer(context.allocator(), runner, Rc::new(code)) - } else { - Ok(Rc::new(code)) - } - }) - .map(|code| code_generator.add_macro(&mac.name, code))? + let code = updated_opts.compile_program( + context.allocator(), + runner.clone(), + macro_program, + &mut HashMap::new(), + )?; + + let optimized_code = + context.macro_optimization(opts.clone(), Rc::new(code.clone()))?; + + code_generator.add_macro(&mac.name, optimized_code) } _ => code_generator, }; @@ -1285,7 +1509,7 @@ fn start_codegen( let only_defuns: Vec = program .helpers .iter() - .filter(|x| is_defun(x)) + .filter(|x| is_defun_or_tabled_constant(x)) .cloned() .collect(); @@ -1299,7 +1523,11 @@ fn start_codegen( }; code_generator.to_process = program.helpers.clone(); - code_generator.original_helpers = program.helpers.clone(); + // Ensure that we have the synthesis of the previous codegen's helpers and + // The ones provided with the new form if any. + let mut combined_helpers_for_codegen = program.helpers.clone(); + combined_helpers_for_codegen.append(&mut code_generator.original_helpers); + code_generator.original_helpers = combined_helpers_for_codegen; code_generator.final_expr = program.exp; Ok(code_generator) @@ -1310,25 +1538,15 @@ fn final_codegen( opts: Rc, compiler: &PrimaryCodegen, ) -> Result { - let runner = context.runner(); - let opt_final_expr = if opts.optimize() { - optimize_expr( - context.allocator(), - opts.clone(), - runner, - compiler, - compiler.final_expr.clone(), - ) - .map(|x| x.1) - .unwrap_or_else(|| compiler.final_expr.clone()) - } else { - compiler.final_expr.clone() - }; + let opt_final_expr = context.pre_final_codegen_optimize(opts.clone(), compiler)?; - generate_expr_code(context, opts, compiler, opt_final_expr).map(|code| { + let optimizer_opts = opts.clone(); + generate_expr_code(context, opts, compiler, opt_final_expr).and_then(|code| { let mut final_comp = compiler.clone(); - final_comp.final_code = Some(CompiledCode(code.0, code.1)); - final_comp + let optimized_code = + context.post_codegen_function_optimize(optimizer_opts.clone(), None, code.1.clone())?; + final_comp.final_code = Some(CompiledCode(code.0, optimized_code)); + Ok(final_comp) }) } @@ -1341,40 +1559,40 @@ fn finalize_env_( ) -> Result, CompileErr> { match env.borrow() { SExp::Atom(l, v) => { - match c.defuns.get(v) { - Some(res) => Ok(res.code.clone()), - None => { - match c.inlines.get(v) { - Some(res) => { - let (arg_list, arg_tail) = synthesize_args(res.args.clone()); - replace_in_inline( - context, - opts.clone(), - c, - l.clone(), - res, - res.args.loc(), - &arg_list, - arg_tail, - ) - .map(|x| x.1) - } - None => { - /* Parentfns are functions in progress in the parent */ - if c.parentfns.get(v).is_some() { - Ok(Rc::new(SExp::Nil(l.clone()))) - } else { - Err(CompileErr( - l.clone(), - format!( - "A defun was referenced in the defun env but not found {}", - decode_string(v) - ), - )) - } - } - } - } + if let Some(res) = c.defuns.get(v) { + return Ok(res.code.clone()); + } + + if let Some(res) = c.tabled_constants.get(v) { + return Ok(res.clone()); + } + + if let Some(res) = c.inlines.get(v) { + let (arg_list, arg_tail) = synthesize_args(res.args.clone()); + return replace_in_inline( + context, + opts.clone(), + c, + l.clone(), + res, + res.args.loc(), + &arg_list, + arg_tail, + ) + .map(|x| x.1); + } + + /* Parentfns are functions in progress in the parent */ + if c.parentfns.contains(v) { + Ok(Rc::new(SExp::Nil(l.clone()))) + } else { + Err(CompileErr( + l.clone(), + format!( + "A defun was referenced in the defun env but not found {}", + decode_string(v) + ), + )) } } @@ -1394,7 +1612,13 @@ fn finalize_env( c: &PrimaryCodegen, ) -> Result, CompileErr> { match c.env.borrow() { - SExp::Cons(l, h, _) => finalize_env_(context, opts.clone(), c, l.clone(), h.clone()), + SExp::Cons(l, h, _) => { + if c.left_env { + finalize_env_(context, opts.clone(), c, l.clone(), h.clone()) + } else { + Ok(c.env.clone()) + } + } _ => Ok(c.env.clone()), } } @@ -1424,6 +1648,15 @@ fn dummy_functions(compiler: &PrimaryCodegen) -> Result { + if cdata.tabled { + let mut c_copy = compiler.clone(); + c_copy.parentfns.insert(cdata.name.clone()); + Ok(c_copy) + } else { + Ok(compiler.clone()) + } + } _ => Ok(compiler.clone()), }, compiler.clone(), @@ -1436,7 +1669,45 @@ pub fn codegen( opts: Rc, cmod: &CompileForm, ) -> Result { - let mut code_generator = dummy_functions(&start_codegen(context, opts.clone(), cmod.clone())?)?; + let mut start_of_codegen_optimization = StartOfCodegenOptimization { + program: cmod.clone(), + code_generator: dummy_functions(&start_codegen(context, opts.clone(), cmod.clone())?)?, + }; + + // This is a tree-shaking loop. It results in the minimum number of emitted + // helpers in the environment by taking only those still alive after each + // optimization pass. If a function is constant at all call sites, then + // then the function will be constant reduced and won't appear when we do + // the live calculation again, which can also remove the last reference to + // other helpers. + loop { + // We should not modify the environment if we're here on behalf of a + // function in a program, only the toplevel program itself. + if opts.in_defun() { + break; + } + + let newly_optimized_start = context + .start_of_codegen_optimization(opts.clone(), start_of_codegen_optimization.clone())?; + + // We got back the same program, so nothing will change anymore. + if newly_optimized_start.program.to_sexp() + == start_of_codegen_optimization.program.to_sexp() + { + break; + } + // Reset the optimization struct so we can go again. + // The maximum number of iterations should be about (N+1) * M where N is + // the number of functions and M is the largest number of parameters in + // any called function or operator. + let program = newly_optimized_start.program; + start_of_codegen_optimization = StartOfCodegenOptimization { + program: program.clone(), + code_generator: dummy_functions(&start_codegen(context, opts.clone(), program)?)?, + }; + } + + let mut code_generator = start_of_codegen_optimization.code_generator; let to_process = code_generator.to_process.clone(); @@ -1444,6 +1715,9 @@ pub fn codegen( code_generator = codegen_(context, opts.clone(), &code_generator, &f)?; } + // If stepping 23 or greater, we support no-env mode. + enable_nil_env_mode_for_stepping_23_or_greater(opts.clone(), &mut code_generator); + *context.symbols() = code_generator.function_symbols.clone(); context .symbols() @@ -1471,7 +1745,7 @@ pub fn codegen( ); Ok(final_code) - } else { + } else if code_generator.left_env { let final_code = primapply( code.0.clone(), Rc::new(primquote(code.0.clone(), code.1)), @@ -1483,6 +1757,9 @@ pub fn codegen( ); Ok(final_code) + } else { + let code_borrowed: &SExp = code.1.borrow(); + Ok(code_borrowed.clone()) } } } diff --git a/src/compiler/compiler.rs b/src/compiler/compiler.rs index ac834591d..b16c8d588 100644 --- a/src/compiler/compiler.rs +++ b/src/compiler/compiler.rs @@ -9,42 +9,20 @@ use clvm_rs::allocator::Allocator; use crate::classic::clvm::__type_compatibility__::{bi_one, bi_zero}; use crate::classic::clvm_tools::stages::stage_0::TRunProgram; -use crate::classic::clvm_tools::stages::stage_2::optimize::optimize_sexp; -use crate::compiler::clvm::{convert_from_clvm_rs, convert_to_clvm_rs, sha256tree}; +use crate::compiler::clvm::sha256tree; use crate::compiler::codegen::{codegen, hoist_body_let_binding, process_helper_let_bindings}; -use crate::compiler::comptypes::{ - CompileErr, CompileForm, CompilerOpts, DefunData, HelperForm, PrimaryCodegen, -}; -use crate::compiler::dialect::AcceptedDialect; -use crate::compiler::evaluate::{build_reflex_captures, Evaluator, EVAL_STACK_LIMIT}; +use crate::compiler::comptypes::{CompileErr, CompileForm, CompilerOpts, PrimaryCodegen}; +use crate::compiler::dialect::{AcceptedDialect, KNOWN_DIALECTS}; use crate::compiler::frontend::frontend; +use crate::compiler::optimize::get_optimizer; use crate::compiler::prims; -use crate::compiler::runtypes::RunFailure; use crate::compiler::sexp::{parse_sexp, SExp}; use crate::compiler::srcloc::Srcloc; use crate::compiler::{BasicCompileContext, CompileContextWrapper}; use crate::util::Number; lazy_static! { - pub static ref KNOWN_DIALECTS: HashMap = { - let mut known_dialects: HashMap = HashMap::new(); - known_dialects.insert( - "*standard-cl-21*".to_string(), - indoc! {"( - (defconstant *chialisp-version* 21) - )"} - .to_string(), - ); - known_dialects.insert( - "*standard-cl-22*".to_string(), - indoc! {"( - (defconstant *chialisp-version* 22) - )"} - .to_string(), - ); - known_dialects - }; pub static ref STANDARD_MACROS: String = { indoc! {"( (defmacro if (A B C) (qq (a (i (unquote A) (com (unquote B)) (com (unquote C))) @))) @@ -69,6 +47,42 @@ lazy_static! { "} .to_string() }; + pub static ref ADVANCED_MACROS: String = { + indoc! {"( + (defmac __chia__primitive__if (A B C) + (qq (a (i (unquote A) (com (unquote B)) (com (unquote C))) @)) + ) + + (defun __chia__if (ARGS) + (__chia__primitive__if (r (r (r ARGS))) + (qq (a (i (unquote (f ARGS)) (com (unquote (f (r ARGS)))) (com (unquote (__chia__if (r (r ARGS)))))) @)) + (qq (a (i (unquote (f ARGS)) (com (unquote (f (r ARGS)))) (com (unquote (f (r (r ARGS)))))) @)) + ) + ) + + (defmac if ARGS (__chia__if ARGS)) + + (defun __chia__compile-list (args) + (if args + (c 4 (c (f args) (c (__chia__compile-list (r args)) ()))) + () + ) + ) + + (defmac list ARGS (__chia__compile-list ARGS)) + + (defun-inline / (A B) (f (divmod A B))) + (defun-inline c* (A B) (c A B)) + (defun-inline a* (A B) (a A B)) + (defun-inline coerce (X) : (Any -> Any) X) + (defun-inline explode (X) : (forall a ((Exec a) -> a)) X) + (defun-inline bless (X) : (forall a ((Pair a Unit) -> (Exec a))) (coerce X)) + (defun-inline lift (X V) : (forall a (forall b ((Pair (Exec a) (Pair b Unit)) -> (Exec (Pair a b))))) (coerce X)) + (defun-inline unlift (X) : (forall a (forall b ((Pair (Exec (Pair a b)) Unit) -> (Exec b)))) (coerce X)) + ) + "} + .to_string() + }; } #[derive(Clone, Debug)] @@ -85,8 +99,6 @@ pub struct DefaultCompilerOpts { pub disassembly_ver: Option, pub prim_map: Rc, Rc>>, pub dialect: AcceptedDialect, - - known_dialects: Rc>, } pub fn create_prim_map() -> Rc, Rc>> { @@ -99,104 +111,60 @@ pub fn create_prim_map() -> Rc, Rc>> { Rc::new(prim_map) } -fn fe_opt( - context: &mut BasicCompileContext, - opts: Rc, - compileform: CompileForm, -) -> Result { - let runner = context.runner(); - let evaluator = Evaluator::new(opts.clone(), runner.clone(), compileform.helpers.clone()); - let mut optimized_helpers: Vec = Vec::new(); - for h in compileform.helpers.iter() { - match h { - HelperForm::Defun(inline, defun) => { - let mut env = HashMap::new(); - build_reflex_captures(&mut env, defun.args.clone()); - let body_rc = evaluator.shrink_bodyform( - context.allocator(), - defun.args.clone(), - &env, - defun.body.clone(), - true, - Some(EVAL_STACK_LIMIT), - )?; - let new_helper = HelperForm::Defun( - *inline, - DefunData { - loc: defun.loc.clone(), - nl: defun.nl.clone(), - kw: defun.kw.clone(), - name: defun.name.clone(), - args: defun.args.clone(), - orig_args: defun.orig_args.clone(), - body: body_rc.clone(), - ty: defun.ty.clone(), - }, - ); - optimized_helpers.push(new_helper); - } - obj => { - optimized_helpers.push(obj.clone()); - } - } - } - let new_evaluator = Evaluator::new(opts.clone(), runner.clone(), optimized_helpers.clone()); +fn do_desugar(program: &CompileForm) -> Result { + // Transform let bindings, merging nested let scopes with the top namespace + let hoisted_bindings = hoist_body_let_binding(None, program.args.clone(), program.exp.clone())?; + let mut new_helpers = hoisted_bindings.0; + let expr = hoisted_bindings.1; // expr is the let-hoisted program - let shrunk = new_evaluator.shrink_bodyform( - context.allocator(), - Rc::new(SExp::Nil(compileform.args.loc())), - &HashMap::new(), - compileform.exp.clone(), - true, - Some(EVAL_STACK_LIMIT), - )?; + // TODO: Distinguish the frontend_helpers and the hoisted_let helpers for later stages + let mut combined_helpers = program.helpers.clone(); + combined_helpers.append(&mut new_helpers); + let combined_helpers = process_helper_let_bindings(&combined_helpers)?; Ok(CompileForm { - loc: compileform.loc.clone(), - include_forms: compileform.include_forms.clone(), - args: compileform.args, - helpers: optimized_helpers.clone(), - exp: shrunk, - ty: None, + helpers: combined_helpers, + exp: expr, + ..program.clone() }) } -pub fn compile_pre_forms( +pub fn desugar_pre_forms( context: &mut BasicCompileContext, opts: Rc, pre_forms: &[Rc], -) -> Result { - // Resolve includes, convert program source to lexemes +) -> Result { let p0 = frontend(opts.clone(), pre_forms)?; - let p1 = if opts.frontend_opt() { - // Front end optimization - fe_opt(context, opts.clone(), p0)? - } else { - p0 - }; - - // Transform let bindings, merging nested let scopes with the top namespace - let hoisted_bindings = hoist_body_let_binding(None, p1.args.clone(), p1.exp.clone())?; - let mut new_helpers = hoisted_bindings.0; - let expr = hoisted_bindings.1; // expr is the let-hoisted program + let p1 = context.frontend_optimization(opts.clone(), p0)?; - // TODO: Distinguish the frontend_helpers and the hoisted_let helpers for later stages - let mut combined_helpers = p1.helpers.clone(); - combined_helpers.append(&mut new_helpers); - let combined_helpers = process_helper_let_bindings(&combined_helpers)?; + do_desugar(&p1) +} - let p2 = CompileForm { - loc: p1.loc.clone(), - include_forms: p1.include_forms.clone(), - args: p1.args, - helpers: combined_helpers, - exp: expr, - ty: p1.ty, - }; +pub fn compile_from_compileform( + context: &mut BasicCompileContext, + opts: Rc, + p2: CompileForm, +) -> Result { + let p3 = context.post_desugar_optimization(opts.clone(), p2)?; // generate code from AST, optionally with optimization - codegen(context, opts, &p2) + let generated = codegen(context, opts.clone(), &p3)?; + + let g2 = context.post_codegen_output_optimize(opts, generated)?; + + Ok(g2) +} + +pub fn compile_pre_forms( + context: &mut BasicCompileContext, + opts: Rc, + pre_forms: &[Rc], +) -> Result { + // Resolve includes, convert program source to lexemes + let p2 = desugar_pre_forms(context, opts.clone(), pre_forms)?; + + compile_from_compileform(context, opts, p2) } pub fn compile_file( @@ -206,33 +174,17 @@ pub fn compile_file( content: &str, symbol_table: &mut HashMap, ) -> Result { - let pre_forms = parse_sexp(Srcloc::start(&opts.filename()), content.bytes())?; - let mut context_wrapper = CompileContextWrapper::new(allocator, runner, symbol_table); + let srcloc = Srcloc::start(&opts.filename()); + let pre_forms = parse_sexp(srcloc.clone(), content.bytes())?; + let mut context_wrapper = CompileContextWrapper::new( + allocator, + runner, + symbol_table, + get_optimizer(&srcloc, opts.clone())?, + ); compile_pre_forms(&mut context_wrapper.context, opts, &pre_forms) } -pub fn run_optimizer( - allocator: &mut Allocator, - runner: Rc, - r: Rc, -) -> Result, CompileErr> { - let to_clvm_rs = convert_to_clvm_rs(allocator, r.clone()) - .map(|x| (r.loc(), x)) - .map_err(|e| match e { - RunFailure::RunErr(l, e) => CompileErr(l, e), - RunFailure::RunExn(s, e) => CompileErr(s, format!("exception {e}\n")), - })?; - - let optimized = optimize_sexp(allocator, to_clvm_rs.1, runner) - .map_err(|e| CompileErr(to_clvm_rs.0.clone(), e.1)) - .map(|x| (to_clvm_rs.0, x))?; - - convert_from_clvm_rs(allocator, optimized.0, optimized.1).map_err(|e| match e { - RunFailure::RunErr(l, e) => CompileErr(l, e), - RunFailure::RunExn(s, e) => CompileErr(s, format!("exception {e}\n")), - }) -} - impl CompilerOpts for DefaultCompilerOpts { fn filename(&self) -> String { self.filename.clone() @@ -321,6 +273,11 @@ impl CompilerOpts for DefaultCompilerOpts { copy.start_env = start_env; Rc::new(copy) } + fn set_prim_map(&self, prims: Rc, Rc>>) -> Rc { + let mut copy = self.clone(); + copy.prim_map = prims; + Rc::new(copy) + } fn read_new_file( &self, @@ -328,9 +285,13 @@ impl CompilerOpts for DefaultCompilerOpts { filename: String, ) -> Result<(String, Vec), CompileErr> { if filename == "*macros*" { - return Ok((filename, STANDARD_MACROS.clone().as_bytes().to_vec())); - } else if let Some(content) = self.known_dialects.get(&filename) { - return Ok((filename, content.as_bytes().to_vec())); + if self.dialect().strict { + return Ok((filename, ADVANCED_MACROS.bytes().collect())); + } else { + return Ok((filename, STANDARD_MACROS.bytes().collect())); + } + } else if let Some(dialect) = KNOWN_DIALECTS.get(&filename) { + return Ok((filename, dialect.content.bytes().collect())); } for dir in self.include_dirs.iter() { @@ -361,7 +322,9 @@ impl CompilerOpts for DefaultCompilerOpts { symbol_table: &mut HashMap, ) -> Result { let me = Rc::new(self.clone()); - let mut context_wrapper = CompileContextWrapper::new(allocator, runner, symbol_table); + let optimizer = get_optimizer(&sexp.loc(), me.clone())?; + let mut context_wrapper = + CompileContextWrapper::new(allocator, runner, symbol_table, optimizer); compile_pre_forms(&mut context_wrapper.context, me, &[sexp]) } } @@ -381,7 +344,6 @@ impl DefaultCompilerOpts { dialect: AcceptedDialect::default(), prim_map: create_prim_map(), disassembly_ver: None, - known_dialects: Rc::new(KNOWN_DIALECTS.clone()), } } } diff --git a/src/compiler/comptypes.rs b/src/compiler/comptypes.rs index 35e763d90..10cb4e327 100644 --- a/src/compiler/comptypes.rs +++ b/src/compiler/comptypes.rs @@ -9,7 +9,7 @@ use clvm_rs::allocator::Allocator; use crate::classic::clvm::__type_compatibility__::{Bytes, BytesFromType}; use crate::classic::clvm_tools::stages::stage_0::TRunProgram; -use crate::compiler::clvm::sha256tree; +use crate::compiler::clvm::{sha256tree, truthy}; use crate::compiler::dialect::AcceptedDialect; use crate::compiler::sexp::{decode_string, enlist, SExp}; use crate::compiler::srcloc::Srcloc; @@ -17,6 +17,14 @@ use crate::compiler::typecheck::TheoryToSExp; use crate::compiler::types::ast::{Polytype, TypeVar}; use crate::util::Number; +// Note: only used in tests, not normally dependencies. +#[cfg(test)] +use crate::compiler::compiler::DefaultCompilerOpts; +#[cfg(test)] +use crate::compiler::frontend::compile_bodyform; +#[cfg(test)] +use crate::compiler::sexp::parse_sexp; + /// The basic error type. It contains a Srcloc identifying coordinates of the /// error in the source file and a message. It probably should be made even better /// but this works ok. @@ -148,6 +156,17 @@ pub struct LetData { pub body: Rc, } +/// Describes a lambda used in an expression. +#[derive(Clone, Debug, Serialize)] +pub struct LambdaData { + pub loc: Srcloc, + pub kw: Option, + pub capture_args: Rc, + pub captures: Rc, + pub args: Rc, + pub body: Rc, +} + #[derive(Clone, Debug, Serialize)] pub enum BodyForm { /// A let or let* form (depending on LetFormKind). @@ -175,6 +194,25 @@ pub enum BodyForm { /// the compiled code. Here, it contains a CompileForm, which represents /// the full significant input of a program (yielded by frontend()). Mod(Srcloc, CompileForm), + /// A lambda form (lambda (...) ...) + /// + /// The lambda arguments are in two parts: + /// + /// (lambda ((& captures) real args) ...) + /// + /// Where the parts in captures are captured from the hosting environment. + /// Captures are optional. + /// The real args are given in the indicated shape when the lambda is applied + /// with the 'a' operator. + Lambda(Box), +} + +#[derive(Clone, Debug, Serialize)] +pub enum SyntheticType { + NoInlinePreference, + MaybeRecursive, + WantInline, + WantNonInline, } /// The information needed to know about a defun. Whether it's inline is left in @@ -195,6 +233,9 @@ pub struct DefunData { pub args: Rc, /// The body expression of the defun. pub body: Rc, + /// Whether this defun was created during desugaring. + pub synthetic: Option, + /// Type annotation if given. pub ty: Option, } @@ -214,6 +255,8 @@ pub struct DefmacData { pub args: Rc, /// The program appearing in the macro definition. pub program: Rc, + /// Whether this is an an advanced macro. + pub advanced: bool, } /// Information from a constant definition. @@ -233,6 +276,9 @@ pub struct DefconstData { pub nl: Srcloc, /// The location of the body expression, whatever it is. pub body: Rc, + /// This constant should exist in the left env rather than be inlined. + pub tabled: bool, + /// Type annotation if given. pub ty: Option, } @@ -297,7 +343,7 @@ pub enum HelperForm { /// A macro definition (see DefmacData). Defmacro(DefmacData), /// A function definition (see DefunData). - Defun(bool, DefunData), + Defun(bool, Box), } /// To what purpose is the file included. @@ -354,6 +400,7 @@ pub struct CompileForm { pub helpers: Vec, /// The expression the program evaluates, using the declared helpers. pub exp: Rc, + /// Type if specified. pub ty: Option, } @@ -370,6 +417,7 @@ pub struct DefunCall { pub struct PrimaryCodegen { pub prims: Rc, Rc>>, pub constants: HashMap, Rc>, + pub tabled_constants: HashMap, Rc>, pub macros: HashMap, Rc>, pub inlines: HashMap, InlineFunction>, pub defuns: HashMap, DefunCall>, @@ -380,6 +428,7 @@ pub struct PrimaryCodegen { pub final_expr: Rc, pub final_code: Option, pub function_symbols: HashMap, + pub left_env: bool, } /// The CompilerOpts specifies global options used during compilation. @@ -443,6 +492,8 @@ pub trait CompilerOpts { fn set_code_generator(&self, new_compiler: PrimaryCodegen) -> Rc; /// Set the environment shape to assume. fn set_start_env(&self, start_env: Option>) -> Rc; + /// Set the primitive map in use so we can add custom primitives. + fn set_prim_map(&self, new_map: Rc, Rc>>) -> Rc; /// Using the search paths list we have, try to read a file by name, /// Returning the expanded path to the file and its content. @@ -469,6 +520,7 @@ pub struct ModAccum { pub loc: Srcloc, pub includes: Vec, pub helpers: Vec, + pub left_capture: bool, pub exp_form: Option, } @@ -505,6 +557,7 @@ impl ModAccum { loc: self.loc.clone(), includes: self.includes.clone(), helpers: self.helpers.clone(), + left_capture: self.left_capture, exp_form: Some(c.clone()), } } @@ -516,6 +569,7 @@ impl ModAccum { loc: self.loc.clone(), includes: new_includes, helpers: self.helpers.clone(), + left_capture: self.left_capture, exp_form: self.exp_form.clone(), } } @@ -528,15 +582,17 @@ impl ModAccum { loc: self.loc.clone(), includes: self.includes.clone(), helpers: hs, + left_capture: self.left_capture, exp_form: self.exp_form.clone(), } } - pub fn new(loc: Srcloc) -> ModAccum { + pub fn new(loc: Srcloc, left_capture: bool) -> ModAccum { ModAccum { loc, includes: Vec::new(), helpers: Vec::new(), + left_capture, exp_form: None, } } @@ -605,6 +661,38 @@ impl CompileForm { } } +pub fn generate_defmacro_sexp(mac: &DefmacData) -> Rc { + if mac.advanced { + Rc::new(SExp::Cons( + mac.loc.clone(), + Rc::new(SExp::atom_from_string(mac.loc.clone(), "defmac")), + Rc::new(SExp::Cons( + mac.loc.clone(), + Rc::new(SExp::atom_from_vec(mac.nl.clone(), &mac.name)), + Rc::new(SExp::Cons( + mac.loc.clone(), + mac.args.clone(), + Rc::new(SExp::Cons( + mac.loc.clone(), + mac.program.exp.to_sexp(), + Rc::new(SExp::Nil(mac.loc.clone())), + )), + )), + )), + )) + } else { + Rc::new(SExp::Cons( + mac.loc.clone(), + Rc::new(SExp::atom_from_string(mac.loc.clone(), "defmacro")), + Rc::new(SExp::Cons( + mac.loc.clone(), + Rc::new(SExp::atom_from_vec(mac.nl.clone(), &mac.name)), + mac.program.to_sexp(), + )), + )) + } +} + impl HelperForm { /// Get a reference to the HelperForm's name. pub fn name(&self) -> &Vec { @@ -674,15 +762,7 @@ impl HelperForm { ], )), }, - HelperForm::Defmacro(mac) => Rc::new(SExp::Cons( - mac.loc.clone(), - Rc::new(SExp::atom_from_string(mac.loc.clone(), "defmacro")), - Rc::new(SExp::Cons( - mac.loc.clone(), - Rc::new(SExp::atom_from_vec(mac.nl.clone(), &mac.name)), - mac.program.to_sexp(), - )), - )), + HelperForm::Defmacro(mac) => generate_defmacro_sexp(mac), HelperForm::Defun(inline, defun) => { let di_string = "defun-inline".to_string(); let d_string = "defun".to_string(); @@ -703,6 +783,35 @@ impl HelperForm { } } +fn compose_lambda_serialized_form(ldata: &LambdaData) -> Rc { + let lambda_kw = Rc::new(SExp::Atom(ldata.loc.clone(), b"lambda".to_vec())); + let amp_kw = Rc::new(SExp::Atom(ldata.loc.clone(), b"&".to_vec())); + let arguments = if truthy(ldata.capture_args.clone()) { + Rc::new(SExp::Cons( + ldata.loc.clone(), + Rc::new(SExp::Cons( + ldata.loc.clone(), + amp_kw, + ldata.capture_args.clone(), + )), + ldata.args.clone(), + )) + } else { + ldata.args.clone() + }; + let rest_of_body = Rc::new(SExp::Cons( + ldata.loc.clone(), + ldata.body.to_sexp(), + Rc::new(SExp::Nil(ldata.loc.clone())), + )); + + Rc::new(SExp::Cons( + ldata.loc.clone(), + lambda_kw, + Rc::new(SExp::Cons(ldata.loc.clone(), arguments, rest_of_body)), + )) +} + fn compose_let(marker: &[u8], letdata: &LetData) -> Rc { let translated_bindings: Vec> = letdata.bindings.iter().map(|x| x.to_sexp()).collect(); let bindings_cons = list_to_cons(letdata.loc.clone(), &translated_bindings); @@ -765,6 +874,7 @@ impl BodyForm { BodyForm::Call(loc, _, _) => loc.clone(), BodyForm::Value(a) => a.loc(), BodyForm::Mod(kl, program) => kl.ext(&program.loc), + BodyForm::Lambda(ldata) => ldata.loc.ext(&ldata.body.loc()), } } @@ -797,10 +907,35 @@ impl BodyForm { Rc::new(SExp::Atom(loc.clone(), b"mod".to_vec())), program.to_sexp(), )), + BodyForm::Lambda(ldata) => compose_lambda_serialized_form(ldata), } } } +// Note: in cfg(test), this will not be part of the finished binary. +// Also: not a test in itself, just named test so for at least some readers, +// its association with test infrastructure will be apparent. +#[cfg(test)] +fn test_parse_bodyform_to_frontend(bf: &str) { + let name = "*test*"; + let loc = Srcloc::start(name); + let opts = Rc::new(DefaultCompilerOpts::new(name)); + let parsed = parse_sexp(loc, bf.bytes()).expect("should parse"); + let bodyform = compile_bodyform(opts, parsed[0].clone()).expect("should compile"); + assert_eq!(bodyform.to_sexp(), parsed[0]); +} + +// Inline unit tests for sexp serialization. +#[test] +fn test_mod_serialize_regular_mod() { + test_parse_bodyform_to_frontend("(mod (X) (+ X 1))"); +} + +#[test] +fn test_mod_serialize_simple_lambda() { + test_parse_bodyform_to_frontend("(lambda (X) (+ X 1))"); +} + impl Binding { /// Express the binding as it would be used in a let form. pub fn to_sexp(&self) -> Rc { @@ -839,6 +974,12 @@ impl PrimaryCodegen { codegen_copy } + pub fn add_tabled_constant(&self, name: &[u8], value: Rc) -> Self { + let mut codegen_copy = self.clone(); + codegen_copy.tabled_constants.insert(name.to_owned(), value); + codegen_copy + } + pub fn add_macro(&self, name: &[u8], value: Rc) -> Self { let mut codegen_copy = self.clone(); codegen_copy.macros.insert(name.to_owned(), value); diff --git a/src/compiler/dialect.rs b/src/compiler/dialect.rs index 305a0048c..e3f876e93 100644 --- a/src/compiler/dialect.rs +++ b/src/compiler/dialect.rs @@ -10,6 +10,7 @@ use crate::compiler::sexp::decode_string; #[derive(Clone, Debug, Default)] pub struct AcceptedDialect { pub stepping: Option, + pub strict: bool, } /// A package containing the content we should insert when a dialect include is @@ -27,23 +28,55 @@ lazy_static! { ( "*standard-cl-21*", DialectDescription { - accepted: AcceptedDialect { stepping: Some(21) }, + accepted: AcceptedDialect { + stepping: Some(21), + ..AcceptedDialect::default() + }, content: indoc! {"( (defconstant *chialisp-version* 21) )"} .to_string(), }, ), + ( + "*strict-cl-21*", + DialectDescription { + accepted: AcceptedDialect { + stepping: Some(21), + strict: true, + }, + content: indoc! {"( + (defconstant *chialisp-version* 22) + )"} + .to_string(), + }, + ), ( "*standard-cl-22*", DialectDescription { - accepted: AcceptedDialect { stepping: Some(22) }, + accepted: AcceptedDialect { + stepping: Some(22), + strict: false, + }, content: indoc! {"( (defconstant *chialisp-version* 22) )"} .to_string(), }, ), + ( + "*standard-cl-23*", + DialectDescription { + accepted: AcceptedDialect { + stepping: Some(23), + strict: true, + }, + content: indoc! {"( + (defconstant *chialisp-version* 23) + )"} + .to_string(), + }, + ), ]; for (n, v) in dialect_list.iter() { dialects.insert(n.to_string(), v.clone()); diff --git a/src/compiler/evaluate.rs b/src/compiler/evaluate.rs index fd046d5c5..64b0ecedc 100644 --- a/src/compiler/evaluate.rs +++ b/src/compiler/evaluate.rs @@ -8,23 +8,24 @@ use num_bigint::ToBigInt; use crate::classic::clvm::__type_compatibility__::{bi_one, bi_zero}; use crate::classic::clvm_tools::stages::stage_0::TRunProgram; -use crate::compiler::clvm::run; +use crate::compiler::clvm::{run, truthy}; use crate::compiler::codegen::{codegen, hoist_assign_form}; use crate::compiler::compiler::is_at_capture; use crate::compiler::comptypes::{ - Binding, BindingPattern, BodyForm, CallSpec, CompileErr, CompileForm, CompilerOpts, HelperForm, - LetData, LetFormInlineHint, LetFormKind, + Binding, BindingPattern, BodyForm, CallSpec, CompileErr, CompileForm, CompilerOpts, DefunData, + HelperForm, LambdaData, LetData, LetFormInlineHint, LetFormKind, }; use crate::compiler::frontend::frontend; +use crate::compiler::optimize::get_optimizer; use crate::compiler::runtypes::RunFailure; -use crate::compiler::sexp::SExp; +use crate::compiler::sexp::{enlist, SExp}; use crate::compiler::srcloc::Srcloc; use crate::compiler::stackvisit::{HasDepthLimit, VisitedMarker}; use crate::compiler::CompileContextWrapper; use crate::util::{number_from_u8, u8_from_number, Number}; const PRIM_RUN_LIMIT: usize = 1000000; -pub const EVAL_STACK_LIMIT: usize = 100; +pub const EVAL_STACK_LIMIT: usize = 200; // Stack depth checker. #[derive(Clone, Debug, Default)] @@ -49,7 +50,7 @@ trait VisitedInfoAccess { impl<'info> VisitedInfoAccess for VisitedMarker<'info, VisitedInfo> { fn get_function(&mut self, name: &[u8]) -> Option> { - if let Some(ref mut info) = self.info { + if let Some(info) = self.info.as_ref() { info.functions.get(name).cloned() } else { None @@ -59,12 +60,21 @@ impl<'info> VisitedInfoAccess for VisitedMarker<'info, VisitedInfo> { fn insert_function(&mut self, name: Vec, body: Rc) { if let Some(ref mut info) = self.info { info.functions.insert(name, body); + } else { + todo!(); } } } +pub struct LambdaApply { + lambda: LambdaData, + body: Rc, + env: Rc, +} + // Frontend evaluator based on my fuzzer representation and direct interpreter of // that. + #[derive(Debug)] pub enum ArgInputs { Whole(Rc), @@ -87,6 +97,7 @@ pub enum ArgInputs { /// whether input parameters to the program as a whole are used in the program's /// eventual results. The simplification it does is general eta conversion with /// some other local transformations thrown in. +#[derive(Clone)] pub struct Evaluator { opts: Rc, runner: Rc, @@ -190,7 +201,7 @@ pub fn is_primitive(expr: &BodyForm) -> bool { ) } -fn make_operator1(l: &Srcloc, op: String, arg: Rc) -> BodyForm { +pub fn make_operator1(l: &Srcloc, op: String, arg: Rc) -> BodyForm { BodyForm::Call( l.clone(), vec![ @@ -201,7 +212,7 @@ fn make_operator1(l: &Srcloc, op: String, arg: Rc) -> BodyForm { ) } -fn make_operator2(l: &Srcloc, op: String, arg1: Rc, arg2: Rc) -> BodyForm { +pub fn make_operator2(l: &Srcloc, op: String, arg1: Rc, arg2: Rc) -> BodyForm { BodyForm::Call( l.clone(), vec![ @@ -232,7 +243,7 @@ fn get_bodyform_from_arginput(l: &Srcloc, arginput: &ArgInputs) -> Rc // // It's possible this will result in irreducible (unknown at compile time) // argument expressions. -fn create_argument_captures( +pub fn create_argument_captures( argument_captures: &mut HashMap, Rc>, formed_arguments: &ArgInputs, function_arg_spec: Rc, @@ -329,6 +340,16 @@ fn arg_inputs_primitive(arginputs: Rc) -> bool { } } +fn decons_args(formed_tail: Rc) -> ArgInputs { + if let Some((head, tail)) = match_cons(formed_tail.clone()) { + let arg_head = decons_args(head.clone()); + let arg_tail = decons_args(tail.clone()); + ArgInputs::Pair(Rc::new(arg_head), Rc::new(arg_tail)) + } else { + ArgInputs::Whole(formed_tail) + } +} + pub fn build_argument_captures( l: &Srcloc, arguments_to_convert: &[Rc], @@ -336,7 +357,7 @@ pub fn build_argument_captures( args: Rc, ) -> Result, Rc>, CompileErr> { let formed_tail = tail.unwrap_or_else(|| Rc::new(BodyForm::Quoted(SExp::Nil(l.clone())))); - let mut formed_arguments = ArgInputs::Whole(formed_tail); + let mut formed_arguments = decons_args(formed_tail); for i_reverse in 0..arguments_to_convert.len() { let i = arguments_to_convert.len() - i_reverse - 1; @@ -473,14 +494,18 @@ fn is_quote_atom(h: Rc) -> bool { match_atom_to_prim(vec![b'q'], 1, h) } -fn is_apply_atom(h: Rc) -> bool { +pub fn is_apply_atom(h: Rc) -> bool { match_atom_to_prim(vec![b'a'], 2, h) } -fn is_i_atom(h: Rc) -> bool { +pub fn is_i_atom(h: Rc) -> bool { match_atom_to_prim(vec![b'i'], 3, h) } +pub fn is_not_atom(h: Rc) -> bool { + match_atom_to_prim(b"not".to_vec(), 32, h) +} + fn is_cons_atom(h: Rc) -> bool { match_atom_to_prim(vec![b'c'], 4, h) } @@ -652,6 +677,27 @@ pub fn eval_dont_expand_let(inline_hint: &Option) -> bool { matches!(inline_hint, Some(LetFormInlineHint::NonInline(_))) } +pub fn filter_capture_args(args: Rc, name_map: &HashMap, Rc>) -> Rc { + match args.borrow() { + SExp::Cons(l, a, b) => { + let a_filtered = filter_capture_args(a.clone(), name_map); + let b_filtered = filter_capture_args(b.clone(), name_map); + if !truthy(a_filtered.clone()) && !truthy(b_filtered.clone()) { + return Rc::new(SExp::Nil(l.clone())); + } + Rc::new(SExp::Cons(l.clone(), a_filtered, b_filtered)) + } + SExp::Atom(l, n) => { + if name_map.contains_key(n) { + Rc::new(SExp::Nil(l.clone())) + } else { + args + } + } + _ => Rc::new(SExp::Nil(args.loc())), + } +} + impl<'info> Evaluator { pub fn new( opts: Rc, @@ -669,39 +715,30 @@ impl<'info> Evaluator { } } - pub fn disable_calls(&self) -> Self { + pub fn mash_conditions(&self) -> Self { Evaluator { - opts: self.opts.clone(), - runner: self.runner.clone(), - prims: self.prims.clone(), - helpers: self.helpers.clone(), - mash_conditions: false, + mash_conditions: true, ignore_exn: true, - disable_calls: true, + disable_calls: false, + ..self.clone() } } - pub fn enable_calls_for_macro(&self) -> Self { + pub fn disable_calls(&self) -> Self { Evaluator { - opts: self.opts.clone(), - runner: self.runner.clone(), - prims: self.prims.clone(), - helpers: self.helpers.clone(), mash_conditions: false, ignore_exn: true, - disable_calls: false, + disable_calls: true, + ..self.clone() } } - pub fn mash_conditions(&self) -> Self { + pub fn enable_calls_for_macro(&self) -> Self { Evaluator { - opts: self.opts.clone(), - runner: self.runner.clone(), - prims: self.prims.clone(), - helpers: self.helpers.clone(), - mash_conditions: true, + mash_conditions: false, ignore_exn: true, disable_calls: false, + ..self.clone() } } @@ -739,16 +776,8 @@ impl<'info> Evaluator { )), )); - frontend(self.opts.clone(), &[frontend_macro_input]).and_then(|program| { - self.shrink_bodyform_visited( - allocator, - visited, - prog_args.clone(), - env, - program.exp, - false, - ) - }) + let program = frontend(self.opts.clone(), &[frontend_macro_input])?; + self.shrink_bodyform_visited(allocator, visited, prog_args, env, program.exp, false) } else { promote_program_to_bodyform( macro_expansion.to_sexp(), @@ -760,11 +789,125 @@ impl<'info> Evaluator { } } + fn is_lambda_apply( + &self, + allocator: &mut Allocator, + visited_: &'info mut VisitedMarker<'_, VisitedInfo>, + prog_args: Rc, + env: &HashMap, Rc>, + parts: &[Rc], + only_inline: bool, + ) -> Result, CompileErr> { + if parts.len() == 3 && is_apply_atom(parts[0].to_sexp()) { + let mut visited = VisitedMarker::again(parts[0].loc(), visited_)?; + let evaluated_prog = self.shrink_bodyform_visited( + allocator, + &mut visited, + prog_args.clone(), + env, + parts[1].clone(), + only_inline, + )?; + let evaluated_env = self.shrink_bodyform_visited( + allocator, + &mut visited, + prog_args, + env, + parts[2].clone(), + only_inline, + )?; + if let BodyForm::Lambda(ldata) = evaluated_prog.borrow() { + return Ok(Some(LambdaApply { + lambda: *ldata.clone(), + body: ldata.body.clone(), + env: evaluated_env, + })); + } + } + + Ok(None) + } + + fn do_lambda_apply( + &self, + allocator: &mut Allocator, + visited: &mut VisitedMarker<'info, VisitedInfo>, + prog_args: Rc, + env: &HashMap, Rc>, + lapply: &LambdaApply, + only_inline: bool, + ) -> Result, CompileErr> { + let mut lambda_env = env.clone(); + // Finish eta-expansion. + + // We're carrying an enriched environment which we can use to enrich + // the env map at this time. Once we do that we can expand the body + // fully because we're carring the info that goes with the primary + // arguments. + // + // Generate the enriched environment. + let reified_captures = self.shrink_bodyform_visited( + allocator, + visited, + prog_args, + env, + lapply.lambda.captures.clone(), + only_inline, + )?; + let formed_caps = ArgInputs::Whole(reified_captures); + create_argument_captures( + &mut lambda_env, + &formed_caps, + lapply.lambda.capture_args.clone(), + )?; + + // Create captures with the actual parameters. + let formed_args = ArgInputs::Whole(lapply.env.clone()); + create_argument_captures(&mut lambda_env, &formed_args, lapply.lambda.args.clone())?; + + self.shrink_bodyform_visited( + allocator, + visited, + lapply.lambda.args.clone(), + &lambda_env, + lapply.body.clone(), + only_inline, + ) + } + + fn defmac_ordering(&self) -> bool { + let dialect = self.opts.dialect(); + dialect.strict || dialect.stepping.unwrap_or(21) > 22 + } + + fn make_com_module(&self, l: &Srcloc, prog_args: Rc, body: Rc) -> Rc { + let end_of_list = if self.defmac_ordering() { + let mut mod_list: Vec> = self.helpers.iter().map(|h| h.to_sexp()).collect(); + mod_list.push(body); + Rc::new(enlist(l.clone(), &mod_list)) + } else { + let mut end_of_list = + Rc::new(SExp::Cons(l.clone(), body, Rc::new(SExp::Nil(l.clone())))); + + for h in self.helpers.iter() { + end_of_list = Rc::new(SExp::Cons(l.clone(), h.to_sexp(), end_of_list)); + } + + end_of_list + }; + + Rc::new(SExp::Cons( + l.clone(), + Rc::new(SExp::Atom(l.clone(), "mod".as_bytes().to_vec())), + Rc::new(SExp::Cons(l.clone(), prog_args, end_of_list)), + )) + } + #[allow(clippy::too_many_arguments)] fn invoke_primitive( &self, allocator: &mut Allocator, - visited: &mut VisitedMarker<'info, VisitedInfo>, + visited_: &'info mut VisitedMarker<'_, VisitedInfo>, call: &CallSpec, prog_args: Rc, arguments_to_convert: &[Rc], @@ -773,133 +916,131 @@ impl<'info> Evaluator { ) -> Result, CompileErr> { let mut all_primitive = true; let mut target_vec: Vec> = call.args.to_owned(); + let mut visited = VisitedMarker::again(call.original.loc(), visited_)?; - if call.name == "@".as_bytes() { + if call.name == b"@" || call.name == b"@*env*" { // Synthesize the environment for this function Ok(Rc::new(BodyForm::Quoted(SExp::Cons( call.loc.clone(), Rc::new(SExp::Nil(call.loc.clone())), prog_args, )))) - } else if call.name == "com".as_bytes() { - let mut end_of_list = Rc::new(SExp::Cons( - call.loc.clone(), - arguments_to_convert[0].to_sexp(), - Rc::new(SExp::Nil(call.loc.clone())), - )); - - for h in self.helpers.iter() { - end_of_list = Rc::new(SExp::Cons(call.loc.clone(), h.to_sexp(), end_of_list)) - } - - let use_body = SExp::Cons( - call.loc.clone(), - Rc::new(SExp::Atom(call.loc.clone(), "mod".as_bytes().to_vec())), - Rc::new(SExp::Cons(call.loc.clone(), prog_args, end_of_list)), - ); - - let compiled = self.compile_code(allocator, false, Rc::new(use_body))?; + } else if call.name == b"com" { + let use_body = + self.make_com_module(&call.loc, prog_args, arguments_to_convert[0].to_sexp()); + let compiled = self.compile_code(allocator, false, use_body)?; let compiled_borrowed: &SExp = compiled.borrow(); Ok(Rc::new(BodyForm::Quoted(compiled_borrowed.clone()))) - } else { - let pres = self - .lookup_prim(call.loc.clone(), call.name) - .map(|prim| { - // Reduce all arguments. - let mut converted_args = SExp::Nil(call.loc.clone()); - - for i_reverse in 0..arguments_to_convert.len() { - let i = arguments_to_convert.len() - i_reverse - 1; - let shrunk = self.shrink_bodyform_visited( - allocator, - visited, - prog_args.clone(), - env, - arguments_to_convert[i].clone(), - only_inline, - )?; + } else if let Some(prim) = self.lookup_prim(call.loc.clone(), call.name) { + // Reduce all arguments. + let mut converted_args = SExp::Nil(call.loc.clone()); + + for i_reverse in 0..arguments_to_convert.len() { + let i = arguments_to_convert.len() - i_reverse - 1; + let shrunk = self.shrink_bodyform_visited( + allocator, + &mut visited, + prog_args.clone(), + env, + arguments_to_convert[i].clone(), + only_inline, + )?; - target_vec[i + 1] = shrunk.clone(); + target_vec[i + 1] = shrunk.clone(); - if !arg_inputs_primitive(Rc::new(ArgInputs::Whole(shrunk.clone()))) { - all_primitive = false; - } + if !arg_inputs_primitive(Rc::new(ArgInputs::Whole(shrunk.clone()))) { + all_primitive = false; + } - converted_args = - SExp::Cons(call.loc.clone(), shrunk.to_sexp(), Rc::new(converted_args)); - } + converted_args = + SExp::Cons(call.loc.clone(), shrunk.to_sexp(), Rc::new(converted_args)); + } - if all_primitive { - match self.run_prim( - allocator, - call.loc.clone(), - make_prim_call(call.loc.clone(), prim, Rc::new(converted_args)), - Rc::new(SExp::Nil(call.loc.clone())), - ) { - Ok(res) => Ok(res), - Err(e) => { - if only_inline || self.ignore_exn { - Ok(Rc::new(BodyForm::Call( - call.loc.clone(), - target_vec.clone(), - None, - ))) - } else { - Err(e) - } - } + if all_primitive { + match self.run_prim( + allocator, + call.loc.clone(), + make_prim_call(call.loc.clone(), prim, Rc::new(converted_args)), + Rc::new(SExp::Nil(call.loc.clone())), + ) { + Ok(res) => Ok(res), + Err(e) => { + if only_inline || self.ignore_exn { + Ok(Rc::new(BodyForm::Call( + call.loc.clone(), + target_vec.clone(), + None, + ))) + } else { + Err(e) } - } else { - // Since this is a primitive, there's no tail transform. - let reformed = - BodyForm::Call(call.loc.clone(), target_vec.clone(), call.tail.clone()); - self.chase_apply(allocator, visited, Rc::new(reformed)) } - }) - .unwrap_or_else(|| { - // Build SExp arguments for external call or - // return the unevaluated chunk with minimized - // arguments. - Err(CompileErr( - call.loc.clone(), - format!( - "Don't yet support this call type {} {:?}", - call.original.to_sexp(), - call.original - ), - )) - })?; - Ok(pres) + } + } else if let Some(applied_lambda) = self.is_lambda_apply( + allocator, + &mut visited, + prog_args.clone(), + env, + &target_vec, + only_inline, + )? { + self.do_lambda_apply( + allocator, + &mut visited, + prog_args, + env, + &applied_lambda, + only_inline, + ) + } else { + let reformed = + BodyForm::Call(call.loc.clone(), target_vec.clone(), call.tail.clone()); + self.chase_apply(allocator, &mut visited, Rc::new(reformed)) + } + } else { + // Build SExp arguments for external call or + // return the unevaluated chunk with minimized + // arguments. + Err(CompileErr( + call.loc.clone(), + format!( + "Don't yet support this call type {} {:?}", + call.original.to_sexp(), + call.original + ), + )) } } fn continue_apply( &self, allocator: &mut Allocator, - visited: &'_ mut VisitedMarker<'info, VisitedInfo>, + visited_: &'_ mut VisitedMarker<'info, VisitedInfo>, env: Rc, run_program: Rc, ) -> Result, CompileErr> { + let mut visited = VisitedMarker::again(run_program.loc(), visited_)?; let bindings = HashMap::new(); let program = promote_program_to_bodyform(run_program.clone(), env)?; let apply_result = self.shrink_bodyform_visited( allocator, - visited, + &mut visited, Rc::new(SExp::Nil(run_program.loc())), &bindings, program, false, )?; - self.chase_apply(allocator, visited, apply_result) + self.chase_apply(allocator, &mut visited, apply_result) } fn do_mash_condition( &self, allocator: &mut Allocator, - visited: &'_ mut VisitedMarker<'info, VisitedInfo>, + visited_: &'_ mut VisitedMarker<'info, VisitedInfo>, maybe_condition: Rc, env: Rc, ) -> Result, CompileErr> { + let mut visited = VisitedMarker::again(maybe_condition.loc(), visited_)?; // The inner part could be an 'i' which we know passes on // one of the two conditional arguments. This was an apply so // we can distribute over the conditional arguments. @@ -924,7 +1065,7 @@ impl<'info> Evaluator { let surrogate_apply_true = self.chase_apply( allocator, - visited, + &mut visited, Rc::new(BodyForm::Call( iftrue.loc(), vec![apply_head.clone(), iftrue.clone(), env.clone()], @@ -934,7 +1075,7 @@ impl<'info> Evaluator { let surrogate_apply_false = self.chase_apply( allocator, - visited, + &mut visited, Rc::new(BodyForm::Call( iffalse.loc(), vec![apply_head, iffalse.clone(), env], @@ -966,19 +1107,29 @@ impl<'info> Evaluator { fn chase_apply( &self, allocator: &mut Allocator, - visited: &'_ mut VisitedMarker<'info, VisitedInfo>, + visited_: &'_ mut VisitedMarker<'info, VisitedInfo>, body: Rc, ) -> Result, CompileErr> { + let mut visited = VisitedMarker::again(body.loc(), visited_)?; + // Matching a primitive so no tail argument. if let BodyForm::Call(l, vec, None) = body.borrow() { if is_apply_atom(vec[0].to_sexp()) { if let Ok(run_program) = dequote(l.clone(), vec[1].clone()) { - return self.continue_apply(allocator, visited, vec[2].clone(), run_program); + return self.continue_apply( + allocator, + &mut visited, + vec[2].clone(), + run_program, + ); } if self.mash_conditions { - if let Ok(mashed) = - self.do_mash_condition(allocator, visited, vec[1].clone(), vec[2].clone()) - { + if let Ok(mashed) = self.do_mash_condition( + allocator, + &mut visited, + vec[1].clone(), + vec[2].clone(), + ) { return Ok(mashed); } } @@ -1058,10 +1209,22 @@ impl<'info> Evaluator { ))); } + let translated_tail = if let Some(t) = call.tail.as_ref() { + Some(self.shrink_bodyform_visited( + allocator, + visited, + prog_args.clone(), + env, + t.clone(), + only_inline, + )?) + } else { + None + }; let argument_captures_untranslated = build_argument_captures( - &call.loc.clone(), + &call.loc, arguments_to_convert, - call.tail.clone(), + translated_tail, defun.args.clone(), )?; @@ -1090,8 +1253,8 @@ impl<'info> Evaluator { only_inline, ) } - _ => self - .invoke_primitive( + _ => { + let invoked = self.invoke_primitive( allocator, visited, call, @@ -1099,9 +1262,108 @@ impl<'info> Evaluator { arguments_to_convert, env, only_inline, - ) - .and_then(|res| self.chase_apply(allocator, visited, res)), + )?; + self.chase_apply(allocator, visited, invoked) + } + } + } + + fn enrich_lambda_site_info( + &self, + allocator: &mut Allocator, + visited: &'info mut VisitedMarker<'_, VisitedInfo>, + prog_args: Rc, + env: &HashMap, Rc>, + ldata: &LambdaData, + only_inline: bool, + ) -> Result, CompileErr> { + if !truthy(ldata.capture_args.clone()) { + return Ok(Rc::new(BodyForm::Lambda(Box::new(ldata.clone())))); } + + // Rewrite the captures based on what we know at the call site. + let new_captures = self.shrink_bodyform_visited( + allocator, + visited, + prog_args.clone(), + env, + ldata.captures.clone(), + only_inline, + )?; + + // Break up and make binding map. + let deconsed_args = decons_args(new_captures.clone()); + let mut arg_captures = HashMap::new(); + create_argument_captures( + &mut arg_captures, + &deconsed_args, + ldata.capture_args.clone(), + )?; + + // Filter out elements that are not interpretable yet. + let mut interpretable_captures = HashMap::new(); + for (n, v) in arg_captures.iter() { + if dequote(v.loc(), v.clone()).is_ok() { + // This capture has already been made into a literal. + // We will substitute it in the lambda body and remove it + // from the capture set. + interpretable_captures.insert(n.clone(), v.clone()); + } + } + + let combined_args = Rc::new(SExp::Cons( + ldata.loc.clone(), + ldata.capture_args.clone(), + ldata.args.clone(), + )); + + // Eliminate the captures via beta substituion. + let simplified_body = self.shrink_bodyform_visited( + allocator, + visited, + combined_args.clone(), + &interpretable_captures, + ldata.body.clone(), + only_inline, + )?; + + let new_capture_args = + filter_capture_args(ldata.capture_args.clone(), &interpretable_captures); + + // This is the first part of eta-conversion. + Ok(Rc::new(BodyForm::Lambda(Box::new(LambdaData { + args: ldata.args.clone(), + capture_args: new_capture_args, + captures: new_captures, + body: simplified_body, + ..ldata.clone() + })))) + } + + fn get_function(&self, name: &[u8]) -> Option> { + for h in self.helpers.iter() { + if let HelperForm::Defun(false, dd) = &h { + if name == h.name() { + return Some(dd.clone()); + } + } + } + + None + } + + fn create_mod_for_fun(&self, l: &Srcloc, function: &DefunData) -> Rc { + Rc::new(BodyForm::Mod( + l.clone(), + CompileForm { + loc: l.clone(), + include_forms: Vec::new(), + args: function.args.clone(), + helpers: self.helpers.clone(), + exp: function.body.clone(), + ty: function.ty.clone(), + }, + )) } // A frontend language evaluator and minifier @@ -1184,7 +1446,7 @@ impl<'info> Evaluator { } BodyForm::Quoted(_) => Ok(body.clone()), BodyForm::Value(SExp::Atom(l, name)) => { - if name == &"@".as_bytes().to_vec() { + if name == &"@".as_bytes().to_vec() || name == &"@*env*".as_bytes().to_vec() { let literal_args = synthesize_args(prog_args.clone(), env)?; self.shrink_bodyform_visited( allocator, @@ -1194,41 +1456,42 @@ impl<'info> Evaluator { literal_args, only_inline, ) + } else if let Some(function) = self.get_function(name) { + self.shrink_bodyform_visited( + allocator, + &mut visited, + prog_args, + env, + self.create_mod_for_fun(l, function.borrow()), + only_inline, + ) + } else if let Some(x) = env.get(name) { + if reflex_capture(name, x.clone()) { + Ok(x.clone()) + } else { + self.shrink_bodyform_visited( + allocator, + &mut visited, + prog_args, + env, + x.clone(), + only_inline, + ) + } + } else if let Some(x) = self.get_constant(name) { + self.shrink_bodyform_visited( + allocator, + &mut visited, + prog_args, + env, + x, + only_inline, + ) } else { - env.get(name) - .map(|x| { - if reflex_capture(name, x.clone()) { - Ok(x.clone()) - } else { - self.shrink_bodyform_visited( - allocator, - &mut visited, - prog_args.clone(), - env, - x.clone(), - only_inline, - ) - } - }) - .unwrap_or_else(|| { - self.get_constant(name) - .map(|x| { - self.shrink_bodyform_visited( - allocator, - &mut visited, - prog_args.clone(), - env, - x, - only_inline, - ) - }) - .unwrap_or_else(|| { - Ok(Rc::new(BodyForm::Value(SExp::Atom( - l.clone(), - name.clone(), - )))) - }) - }) + Ok(Rc::new(BodyForm::Value(SExp::Atom( + l.clone(), + name.clone(), + )))) } } BodyForm::Value(v) => Ok(Rc::new(BodyForm::Quoted(v.clone()))), @@ -1288,11 +1551,24 @@ impl<'info> Evaluator { BodyForm::Mod(_, program) => { // A mod form yields the compiled code. let mut symbols = HashMap::new(); - let mut context_wrapper = - CompileContextWrapper::new(allocator, self.runner.clone(), &mut symbols); + let optimizer = get_optimizer(&program.loc(), self.opts.clone())?; + let mut context_wrapper = CompileContextWrapper::new( + allocator, + self.runner.clone(), + &mut symbols, + optimizer, + ); let code = codegen(&mut context_wrapper.context, self.opts.clone(), program)?; Ok(Rc::new(BodyForm::Quoted(code))) } + BodyForm::Lambda(ldata) => self.enrich_lambda_site_info( + allocator, + &mut visited, + prog_args, + env, + ldata, + only_inline, + ), } } @@ -1406,6 +1682,7 @@ impl<'info> Evaluator { self.prims.clone(), prim, args, + None, Some(PRIM_RUN_LIMIT), ) .map_err(|e| match e { @@ -1429,7 +1706,7 @@ impl<'info> Evaluator { // primitive. let updated_opts = self .opts - .set_stdenv(!in_defun) + .set_stdenv(!in_defun && !self.opts.dialect().strict) .set_in_defun(in_defun) .set_frontend_opt(false); diff --git a/src/compiler/frontend.rs b/src/compiler/frontend.rs index 186fb0e97..4c5115ea1 100644 --- a/src/compiler/frontend.rs +++ b/src/compiler/frontend.rs @@ -4,7 +4,6 @@ use std::collections::HashSet; use std::rc::Rc; use log::debug; - use num_bigint::ToBigInt; use crate::classic::clvm::__type_compatibility__::{bi_one, bi_zero}; @@ -12,8 +11,9 @@ use crate::compiler::comptypes::{ list_to_cons, ArgsAndTail, Binding, BindingPattern, BodyForm, ChiaType, CompileErr, CompileForm, CompilerOpts, ConstantKind, DefconstData, DefmacData, DeftypeData, DefunData, HelperForm, IncludeDesc, LetData, LetFormInlineHint, LetFormKind, ModAccum, StructDef, - StructMember, TypeAnnoKind, + StructMember, SyntheticType, TypeAnnoKind, }; +use crate::compiler::lambda::handle_lambda; use crate::compiler::preprocessor::preprocess; use crate::compiler::rename::{rename_assign_bindings, rename_children_compileform}; use crate::compiler::sexp::{decode_string, enlist, SExp}; @@ -76,6 +76,11 @@ fn collect_used_names_bodyform(body: &BodyForm) -> Vec> { result } BodyForm::Mod(_, _) => vec![], + BodyForm::Lambda(ldata) => { + let mut capture_names = collect_used_names_bodyform(ldata.captures.borrow()); + capture_names.append(&mut collect_used_names_bodyform(ldata.body.borrow())); + capture_names + } } } @@ -257,16 +262,13 @@ fn make_let_bindings( opts: Rc, body: Rc, ) -> Result>, CompileErr> { - let err = Err(CompileErr( - body.loc(), - "Bad binding tail ".to_string() + &body.to_string(), - )); + let err = Err(CompileErr(body.loc(), format!("Bad binding tail {body:?}"))); match body.borrow() { SExp::Nil(_) => Ok(vec![]), SExp::Cons(_, head, tl) => head .proper_list() .filter(|x| x.len() == 2) - .map(|x| match (x[0].atomize(), &x[1]) { + .map(|x| match (x[0].clone(), &x[1]) { (SExp::Atom(l, name), expr) => { let compiled_body = compile_bodyform(opts.clone(), Rc::new(expr.clone()))?; let mut result = Vec::new(); @@ -324,7 +326,6 @@ fn handle_assign_form( for idx in (0..(v.len() - 1) / 2).map(|idx| idx * 2) { let destructure_pattern = Rc::new(v[idx].clone()); let binding_body = compile_bodyform(opts.clone(), Rc::new(v[idx + 1].clone()))?; - // Ensure bindings aren't duplicated as we won't be able to // guarantee their order during toposort. let mut this_provides = HashSet::new(); @@ -354,7 +355,7 @@ fn handle_assign_form( return Ok(compiled_body); } - if at_or_above_23(opts.clone()) { + if at_or_above_23(opts) { let (new_compiled_body, new_bindings) = rename_assign_bindings(&l, &bindings, Rc::new(compiled_body))?; compiled_body = new_compiled_body; @@ -409,9 +410,7 @@ pub fn compile_bodyform( match op.borrow() { SExp::Atom(l, atom_name) => { - if *atom_name == "q".as_bytes().to_vec() - || (atom_name.len() == 1 && atom_name[0] == 1) - { + if *atom_name == b"q" || (atom_name.len() == 1 && atom_name[0] == 1) { let tail_copy: &SExp = tail.borrow(); return Ok(BodyForm::Quoted(tail_copy.clone())); } @@ -421,14 +420,12 @@ pub fn compile_bodyform( match tail.proper_list() { Some(v) => { - if *atom_name == "let".as_bytes().to_vec() - || *atom_name == "let*".as_bytes().to_vec() - { + if *atom_name == b"let" || *atom_name == b"let*" { if v.len() != 2 { return finish_err("let"); } - let kind = if *atom_name == "let".as_bytes().to_vec() { + let kind = if *atom_name == b"let" { LetFormKind::Parallel } else { LetFormKind::Sequential @@ -466,7 +463,7 @@ pub fn compile_bodyform( Some(LetFormInlineHint::NoChoice) }, ) - } else if *atom_name == "quote".as_bytes().to_vec() { + } else if *atom_name == b"quote" { if v.len() != 1 { return finish_err("quote"); } @@ -474,7 +471,7 @@ pub fn compile_bodyform( let quote_body = v[0].clone(); Ok(BodyForm::Quoted(quote_body)) - } else if *atom_name == "qq".as_bytes().to_vec() { + } else if *atom_name == b"qq" { if v.len() != 1 { return finish_err("qq"); } @@ -482,9 +479,11 @@ pub fn compile_bodyform( let quote_body = v[0].clone(); qq_to_expression(opts, Rc::new(quote_body)) - } else if *atom_name == "mod".as_bytes().to_vec() { + } else if *atom_name == b"mod" { let subparse = frontend(opts, &[body.clone()])?; Ok(BodyForm::Mod(op.loc(), subparse)) + } else if *atom_name == b"lambda" { + handle_lambda(opts, Some(l.clone()), &v) } else { application() } @@ -527,7 +526,7 @@ fn compile_defconst( name: Vec, body: Rc, ) -> Result { - let bf = compile_bodyform(opts, body)?; + let bf = compile_bodyform(opts.clone(), body)?; Ok(HelperForm::Defconstant(DefconstData { kw: kl, nl, @@ -535,6 +534,7 @@ fn compile_defconst( kind: ConstantKind::Complex, name: name.to_vec(), body: Rc::new(bf), + tabled: opts.frontend_opt() || opts.dialect().stepping.unwrap_or(0) > 22, ty: None, })) } @@ -557,6 +557,7 @@ fn compile_defconstant( kind: ConstantKind::Simple, name: name.to_vec(), body: Rc::new(BodyForm::Value(body_borrowed.clone())), + tabled: false, ty, })) } else { @@ -568,6 +569,7 @@ fn compile_defconstant( kind: ConstantKind::Simple, name: name.to_vec(), body: Rc::new(bf), + tabled: false, ty, }) }) @@ -607,7 +609,7 @@ fn compile_defun( compile_bodyform(opts, take_form).map(|bf| { HelperForm::Defun( data.inline, - DefunData { + Box::new(DefunData { loc: data.l, nl: data.nl, kw: data.kwl, @@ -615,8 +617,9 @@ fn compile_defun( args: data.args.clone(), orig_args: data.args, body: Rc::new(bf), + synthetic: None, ty, - }, + }), ) }) } @@ -644,6 +647,7 @@ fn compile_defmacro( name, args: args.clone(), program: Rc::new(p), + advanced: false, }) }) } @@ -991,7 +995,7 @@ fn create_constructor(sdef: &StructDef) -> HelperForm { HelperForm::Defun( true, - DefunData { + Box::new(DefunData { kw: None, nl: sdef.loc.clone(), loc: sdef.loc.clone(), @@ -999,8 +1003,9 @@ fn create_constructor(sdef: &StructDef) -> HelperForm { orig_args: arguments.clone(), args: arguments, body: Rc::new(construction), + synthetic: Some(SyntheticType::NoInlinePreference), ty: Some(funty), - }, + }), ) } @@ -1043,7 +1048,7 @@ pub fn generate_type_helpers(ty: &ChiaType) -> Vec { HelperForm::Defun( true, - DefunData { + Box::new(DefunData { kw: None, nl: m.loc.clone(), loc: m.loc.clone(), @@ -1065,8 +1070,9 @@ pub fn generate_type_helpers(ty: &ChiaType) -> Vec { ], None, )), + synthetic: Some(SyntheticType::NoInlinePreference), ty: Some(funty), - }, + }), ) }) .collect(); @@ -1136,6 +1142,7 @@ fn parse_chia_type(v: Vec) -> Result { )) } +#[derive(Debug, Clone)] pub struct HelperFormResult { pub chia_type: Option, pub new_helpers: Vec, @@ -1150,6 +1157,7 @@ pub fn compile_helperform( if let Some(matched) = plist.and_then(|pl| match_op_name_4(&pl)) { let inline = matched.op_name == "defun-inline".as_bytes().to_vec(); + let is_defmac = matched.op_name == "defmac".as_bytes().to_vec(); if matched.op_name == "defconstant".as_bytes().to_vec() { let definition = compile_defconstant( opts, @@ -1177,7 +1185,14 @@ pub fn compile_helperform( chia_type: None, new_helpers: vec![definition], })) - } else if matched.op_name == "defmacro".as_bytes().to_vec() { + } else if matched.op_name == b"defmacro" || is_defmac { + if is_defmac { + return Ok(Some(HelperFormResult { + chia_type: None, + new_helpers: vec![], + })); + } + let definition = compile_defmacro( opts, l, @@ -1373,11 +1388,15 @@ fn frontend_start( )); } - if *mod_atom == "mod".as_bytes().to_vec() { + if *mod_atom == b"mod" { let args = Rc::new(x[1].atomize()); let mut skip_idx = 2; let mut ty: Option = None; + if x.len() < 3 { + return Err(CompileErr(x[0].loc(), "incomplete mod form".to_string())); + } + if let SExp::Atom(_, colon) = &x[2].atomize() { if *colon == vec![b':'] && x.len() > 3 { let use_ty = parse_type_sexp(Rc::new(x[3].atomize()))?; @@ -1399,7 +1418,7 @@ fn frontend_start( let body = Rc::new(enlist(pre_forms[0].loc(), &body_vec)); let ls = preprocess(opts.clone(), includes, body)?; - let mut ma = ModAccum::new(l.clone()); + let mut ma = ModAccum::new(l.clone(), false); for form in ls.iter().take(ls.len() - 1) { ma = ma.compile_mod_helper( opts.clone(), @@ -1425,6 +1444,37 @@ fn frontend_start( } } +/// Given the available helper list and the main expression, compute the list of +/// reachable helpers. +pub fn compute_live_helpers( + opts: Rc, + helper_list: &[HelperForm], + main_exp: Rc, +) -> Vec { + let expr_names: HashSet> = collect_used_names_bodyform(main_exp.borrow()) + .iter() + .map(|x| x.to_vec()) + .collect(); + + let mut helper_map = HashMap::new(); + + for h in helper_list.iter() { + helper_map.insert(h.name().clone(), h.clone()); + } + + let helper_names = calculate_live_helpers(&HashSet::new(), &expr_names, &helper_map); + + helper_list + .iter() + .filter(|h| { + matches!(h, HelperForm::Deftype(_)) + || !opts.frontend_check_live() + || helper_names.contains(h.name()) + }) + .cloned() + .collect() +} + /// Entrypoint for compilation. This yields a CompileForm which represents a full /// program. /// @@ -1462,37 +1512,12 @@ pub fn frontend( let our_mod = rename_children_compileform(&compiled?)?; - let expr_names: HashSet> = collect_used_names_bodyform(our_mod.exp.borrow()) - .iter() - .map(|x| x.to_vec()) - .collect(); - - let helper_list = our_mod.helpers.iter().map(|h| (h.name(), h)); - let mut helper_map = HashMap::new(); - - for hpair in helper_list { - helper_map.insert(hpair.0.clone(), hpair.1.clone()); - } - - let helper_names = calculate_live_helpers(&HashSet::new(), &expr_names, &helper_map); - - let mut live_helpers = Vec::new(); - for h in our_mod.helpers { - if matches!(h, HelperForm::Deftype(_)) - || !opts.frontend_check_live() - || helper_names.contains(h.name()) - { - live_helpers.push(h); - } - } + let live_helpers = compute_live_helpers(opts.clone(), &our_mod.helpers, our_mod.exp.clone()); Ok(CompileForm { - loc: our_mod.loc.clone(), include_forms: includes.to_vec(), - args: our_mod.args.clone(), helpers: live_helpers, - exp: our_mod.exp.clone(), - ty: our_mod.ty.clone(), + ..our_mod }) } diff --git a/src/compiler/frontend2.rs b/src/compiler/frontend2.rs deleted file mode 100644 index a564bc86e..000000000 --- a/src/compiler/frontend2.rs +++ /dev/null @@ -1,1265 +0,0 @@ -use std::borrow::Borrow; -use std::collections::HashMap; -use std::collections::HashSet; -use std::rc::Rc; - -use log::debug; - -use num_bigint::ToBigInt; - - -use crate::classic::clvm::__type_compatibility__::{bi_one, bi_zero}; -use crate::compiler::comptypes::{ - list_to_cons, Binding, BodyForm, ChiaType, CompileErr, CompileForm, CompilerOpts, DefconstData, - DefmacData, DefunData, HelperForm, LetData, LetFormKind, ModAccum, StructDef, StructMember, TypeAnnoKind -}; -use crate::compiler::preprocessor::preprocess; -use crate::compiler::rename::rename_children_compileform; -use crate::compiler::sexp::{decode_string, enlist, SExp}; -use crate::compiler::srcloc::{HasLoc, Srcloc}; -use crate::compiler::typecheck::{parse_type_sexp, parse_type_var}; -use crate::compiler::types::ast::{Polytype, Type, TypeVar}; -use crate::util::{u8_from_number, Number}; - -fn collect_used_names_sexp(body: Rc) -> Vec> { - match body.borrow() { - SExp::Atom(_, name) => vec![name.to_vec()], - SExp::Cons(_, head, tail) => { - let mut head_collected = collect_used_names_sexp(head.clone()); - let mut tail_collected = collect_used_names_sexp(tail.clone()); - head_collected.append(&mut tail_collected); - head_collected - } - _ => vec![], - } -} - -fn collect_used_names_binding(body: &Binding) -> Vec> { - collect_used_names_bodyform(body.body.borrow()) -} - -fn collect_used_names_bodyform(body: &BodyForm) -> Vec> { - match body { - BodyForm::Let(_, letdata) => { - let mut result = Vec::new(); - for b in letdata.bindings.iter() { - let mut new_binding_names = collect_used_names_binding(b); - result.append(&mut new_binding_names); - } - - let mut body_names = collect_used_names_bodyform(letdata.body.borrow()); - result.append(&mut body_names); - result - } - BodyForm::Quoted(_) => vec![], - BodyForm::Value(atom) => match atom.borrow() { - SExp::Atom(_l, v) => vec![v.to_vec()], - SExp::Cons(_l, f, r) => { - let mut first_names = collect_used_names_sexp(f.clone()); - let mut rest_names = collect_used_names_sexp(r.clone()); - first_names.append(&mut rest_names); - first_names - } - _ => Vec::new(), - }, - BodyForm::Call(_l, vs) => { - let mut result = Vec::new(); - for a in vs { - let mut argnames = collect_used_names_bodyform(a); - result.append(&mut argnames); - } - result - } - BodyForm::Mod(_, _) => vec![], - } -} - -fn collect_used_names_helperform(body: &HelperForm) -> Vec> { - match body { - HelperForm::Deftype(_) => Vec::new(), - HelperForm::Defconstant(defc) => collect_used_names_bodyform(defc.body.borrow()), - HelperForm::Defmacro(mac) => collect_used_names_compileform(mac.program.borrow()), - HelperForm::Defun(_, defun) => collect_used_names_bodyform(&defun.body), - } -} - -fn collect_used_names_compileform(body: &CompileForm) -> Vec> { - let mut result = Vec::new(); - for h in body.helpers.iter() { - let mut helper_list = collect_used_names_helperform(h.borrow()); - result.append(&mut helper_list); - } - - let mut ex_list = collect_used_names_bodyform(body.exp.borrow()); - result.append(&mut ex_list); - result -} - -fn calculate_live_helpers( - last_names: &HashSet>, - names: &HashSet>, - helper_map: &HashMap, HelperForm>, -) -> HashSet> { - if last_names.len() == names.len() { - names.clone() - } else { - let new_names: HashSet> = - names.difference(last_names).map(|x| x.to_vec()).collect(); - let mut needed_helpers: HashSet> = names.clone(); - - for name in new_names { - if let Some(new_helper) = helper_map.get(&name) { - let even_newer_names: HashSet> = collect_used_names_helperform(new_helper) - .iter() - .map(|x| x.to_vec()) - .collect(); - needed_helpers = needed_helpers - .union(&even_newer_names) - .into_iter() - .map(|x| x.to_vec()) - .collect(); - } - } - - calculate_live_helpers(names, &needed_helpers, helper_map) - } -} - -fn qq_to_expression(opts: Rc, body: Rc) -> Result { - let body_copy: &SExp = body.borrow(); - - match body.borrow() { - SExp::Cons(l, f, r) => { - let op = match f.borrow() { - SExp::Atom(_, o) => o.clone(), - SExp::QuotedString(_, _, s) => s.clone(), - SExp::Integer(_, i) => u8_from_number(i.clone()), - _ => Vec::new(), - }; - - if op.len() == 1 && (op[0] == b'q' || op[0] == 1) { - return Ok(BodyForm::Quoted(body_copy.clone())); - } else if let Some(list) = r.proper_list() { - if op == b"quote" { - if list.len() != 1 { - return Err(CompileErr(l.clone(), format!("bad form {}", body))); - } - - return Ok(BodyForm::Quoted(list[0].clone())); - } else if op == b"unquote" { - if list.len() != 1 { - return Err(CompileErr(l.clone(), format!("bad form {}", body))); - } - - return compile_bodyform(opts.clone(), Rc::new(list[0].clone())); - } - } - - qq_to_expression_list(opts, body.clone()) - } - _ => Ok(BodyForm::Quoted(body_copy.clone())), - } -} - -fn qq_to_expression_list( - opts: Rc, - body: Rc, -) -> Result { - match body.borrow() { - SExp::Cons(l, f, r) => { - m! { - f_qq <- qq_to_expression(opts.clone(), f.clone()); - r_qq <- qq_to_expression_list(opts, r.clone()); - Ok(BodyForm::Call(l.clone(), vec!( - Rc::new(BodyForm::Value( - SExp::Atom(l.clone(), "c".as_bytes().to_vec()) - )), - Rc::new(f_qq), - Rc::new(r_qq) - ))) - } - } - SExp::Nil(l) => Ok(BodyForm::Quoted(SExp::Nil(l.clone()))), - _ => Err(CompileErr( - body.loc(), - format!("Bad list tail in qq {}", body), - )), - } -} - -fn args_to_expression_list( - opts: Rc, - body: Rc, -) -> Result>, CompileErr> { - if body.nilp() { - Ok(vec![]) - } else { - match body.borrow() { - SExp::Cons(_l, first, rest) => { - let mut result_list = Vec::new(); - let f_compiled = compile_bodyform(opts.clone(), first.clone())?; - result_list.push(Rc::new(f_compiled)); - let mut args = args_to_expression_list(opts, rest.clone())?; - result_list.append(&mut args); - Ok(result_list) - } - _ => Err(CompileErr( - body.loc(), - "Bad arg list tail ".to_string() + &body.to_string(), - )), - } - } -} - -fn make_let_bindings( - opts: Rc, - body: Rc, -) -> Result>, CompileErr> { - let err = Err(CompileErr( - body.loc(), - "Bad binding tail ".to_string() + &body.to_string(), - )); - match body.borrow() { - SExp::Nil(_) => Ok(vec![]), - SExp::Cons(_, head, tl) => head - .proper_list() - .map(|x| match &x[..] { - [SExp::Atom(l, name), expr] => { - let compiled_body = compile_bodyform(opts.clone(), Rc::new(expr.clone()))?; - let mut result = Vec::new(); - let mut rest_bindings = make_let_bindings(opts, tl.clone())?; - result.push(Rc::new(Binding { - loc: l.clone(), - nl: l.clone(), - name: name.to_vec(), - body: Rc::new(compiled_body), - })); - result.append(&mut rest_bindings); - Ok(result) - } - _ => err.clone(), - }) - .unwrap_or_else(|| err.clone()), - _ => err, - } -} - -pub fn compile_bodyform( - opts: Rc, - body: Rc, -) -> Result { - match body.borrow() { - SExp::Cons(l, op, tail) => { - let application = || { - args_to_expression_list(opts.clone(), tail.clone()).and_then(|args| { - compile_bodyform(opts.clone(), op.clone()).map(|func| { - let mut result_call = vec![Rc::new(func)]; - let mut args_clone = args.to_vec(); - let ending = if args.is_empty() { - l.ending() - } else { - args[args.len() - 1].loc().ending() - }; - result_call.append(&mut args_clone); - BodyForm::Call(l.ext(&ending), result_call) - }) - }) - }; - - let finish_err = |site| { - Err(CompileErr( - l.clone(), - format!("{}: bad argument list for form {}", site, body), - )) - }; - - match op.borrow() { - SExp::Atom(l, atom_name) => { - if *atom_name == "q".as_bytes().to_vec() - || (atom_name.len() == 1 && atom_name[0] == 1) - { - let tail_copy: &SExp = tail.borrow(); - return Ok(BodyForm::Quoted(tail_copy.clone())); - } - - match tail.proper_list() { - Some(v) => { - if *atom_name == "let".as_bytes().to_vec() - || *atom_name == "let*".as_bytes().to_vec() - { - if v.len() != 2 { - return finish_err("let"); - } - - let kind = if *atom_name == "let".as_bytes().to_vec() { - LetFormKind::Parallel - } else { - LetFormKind::Sequential - }; - - let bindings = v[0].clone(); - let body = v[1].clone(); - - let let_bindings = - make_let_bindings(opts.clone(), Rc::new(bindings))?; - let compiled_body = compile_bodyform(opts, Rc::new(body))?; - Ok(BodyForm::Let( - kind, - LetData { - loc: l.clone(), - kw: Some(l.clone()), - bindings: let_bindings, - body: Rc::new(compiled_body), - }, - )) - } else if *atom_name == "quote".as_bytes().to_vec() { - if v.len() != 1 { - return finish_err("quote"); - } - - let quote_body = v[0].clone(); - - Ok(BodyForm::Quoted(quote_body)) - } else if *atom_name == "qq".as_bytes().to_vec() { - if v.len() != 1 { - return finish_err("qq"); - } - - let quote_body = v[0].clone(); - - qq_to_expression(opts, Rc::new(quote_body)) - } else if *atom_name == "mod".as_bytes().to_vec() { - let subparse = frontend(opts, &[body.clone()])?; - Ok(BodyForm::Mod(op.loc(), subparse)) - } else { - application() - } - } - None => finish_err("tail_proper"), - } - } - SExp::Integer(il, i) => compile_bodyform( - opts, - Rc::new(SExp::Cons( - il.clone(), - Rc::new(SExp::Atom(il.clone(), u8_from_number(i.clone()))), - tail.clone(), - )), - ), - SExp::QuotedString(_, _, _) => { - let body_copy: &SExp = body.borrow(); - Ok(BodyForm::Value(body_copy.clone())) - } - SExp::Nil(_l) => { - let body_copy: &SExp = body.borrow(); - Ok(BodyForm::Quoted(body_copy.clone())) - } - SExp::Cons(_, _, _) => finish_err("bad cons"), - } - } - _ => { - let body_copy: &SExp = body.borrow(); - Ok(BodyForm::Value(body_copy.clone())) - } - } -} - -fn compile_defconstant( - opts: Rc, - l: Srcloc, - nl: Srcloc, - kwl: Option, - name: Vec, - body: Rc, - ty: Option, -) -> Result { - compile_bodyform(opts, body).map(|bf| { - HelperForm::Defconstant(DefconstData { - loc: l, - nl, - kw: kwl, - name: name.to_vec(), - body: Rc::new(bf), - ty - }) - }) -} - -fn location_span(l_: Srcloc, lst_: Rc) -> Srcloc { - let mut l = l_; - let mut lst = lst_; - while let SExp::Cons(_, a, b) = lst.borrow() { - l = location_span(l.clone(), a.clone()).ext(&b.loc()); - lst = b.clone(); - } - l -} - -pub struct CompileDefun { - pub l: Srcloc, - pub nl: Srcloc, - pub kwl: Option, - pub inline: bool, - pub name: Vec, - pub args: Rc, - pub body: Rc, -} - -fn compile_defun(opts: Rc, data: CompileDefun, ty: Option) -> Result { - let mut take_form = data.body.clone(); - - if let SExp::Cons(_, f, _r) = data.body.borrow() { - take_form = f.clone(); - } - compile_bodyform(opts, take_form).map(|bf| { - HelperForm::Defun( - data.inline, - DefunData { - loc: data.l, - nl: data.nl, - kw: data.kwl, - name: data.name, - args: data.args, - body: Rc::new(bf), - ty - }, - ) - }) -} - -fn compile_defmacro( - opts: Rc, - l: Srcloc, - nl: Srcloc, - kwl: Option, - name: Vec, - args: Rc, - body: Rc, -) -> Result { - let program = SExp::Cons( - l.clone(), - Rc::new(SExp::Atom(l.clone(), b"mod".to_vec())), - Rc::new(SExp::Cons(l.clone(), args.clone(), body)), - ); - let new_opts = opts.set_stdenv(false); - frontend(new_opts, &[Rc::new(program)]).map(|p| { - HelperForm::Defmacro(DefmacData { - loc: l, - nl, - kw: kwl, - name, - args: args.clone(), - program: Rc::new(p), - }) - }) -} - -struct OpName4Match { - opl: Srcloc, - op_name: Vec, - nl: Srcloc, - name: Vec, - args: Rc, - body: Rc, -} - -enum TypeKind { - Arrow, - Colon, -} - -struct Opname4Match { - op_name: Vec, - name: Vec, - args: Rc, - body: Rc, - orig: Vec, - ty: Option<(TypeKind, Rc)>, -} - -fn match_op_name_4(pl: &[SExp]) -> Option { - if pl.is_empty() { - return None; - } - - match &pl[0] { - SExp::Atom(l, op_name) => { - if pl.len() < 3 { - return Some(OpName4Match { - opl: l.clone(), - op_name: op_name.clone(), - nl: l.clone(), - name: Vec::new(), - args: Rc::new(SExp::Nil(l.clone())), - body: Rc::new(SExp::Nil(l.clone())), - ty: None, - }); - } - - match &pl[1] { - SExp::Atom(ll, name) => { - let mut tail_list = Vec::new(); - let mut type_anno = None; - if pl.len() > 3 { - if let SExp::Atom(_, colon) = &pl[3] { - if *colon == vec![b':'] { - // Type annotation - tail_idx += 2; - type_anno = Some((TypeKind::Colon, Rc::new(pl[4].clone()))); - } else if *colon == vec![b'-', b'>'] { - // Type annotation - tail_idx += 2; - type_anno = Some((TypeKind::Arrow, Rc::new(pl[4].clone()))); - } - } - } - for elt in pl.iter().skip(tail_idx) { - tail_list.push(Rc::new(elt.clone())); - } - Some(Opname4Match { - op_name: op_name.clone(), - name: name.clone(), - args: Rc::new(pl[2].clone()), - body: Rc::new(enlist(l, tail_list)), - orig: pl.to_owned(), - ty: type_anno, - }) - } - _ => Some(Opname4Match { - op_name: op_name.clone(), - name: Vec::new(), - args: Rc::new(SExp::Nil(l.clone())), - body: Rc::new(SExp::Nil(l)), - orig: pl.to_owned(), - ty: None, - }), - } - } - _ => None, - } -} - -fn extract_type_variables_from_forall_stack(tvars: &mut Vec, t: &Polytype) -> Polytype { - if let Type::TForall(v, t1) = t { - tvars.push(v.clone()); - extract_type_variables_from_forall_stack(tvars, t1.borrow()) - } else { - t.clone() - } -} - -pub struct ArgTypeResult { - pub stripped_args: Rc, - pub arg_names: Vec>, - pub individual_types: HashMap, Polytype>, - pub individual_paths: HashMap, Number>, - pub individual_locs: HashMap, Srcloc>, - pub whole_args: Polytype, -} - -#[allow(clippy::too_many_arguments)] -fn recover_arg_type_inner( - arg_names: &mut Vec>, - individual_types: &mut HashMap, Polytype>, - individual_paths: &mut HashMap, Number>, - individual_locs: &mut HashMap, Srcloc>, - depth: Number, - path: Number, - args: Rc, - have_anno: bool, -) -> Result<(bool, Rc, Polytype), CompileErr> { - match &args.atomize() { - SExp::Nil(l) => Ok((have_anno, args.clone(), Type::TUnit(l.clone()))), - SExp::Atom(l, n) => { - arg_names.push(n.clone()); - individual_types.insert(n.clone(), Type::TAny(l.clone())); - individual_paths.insert(n.clone(), depth + path); - individual_locs.insert(n.clone(), l.clone()); - Ok((false, args.clone(), Type::TAny(l.clone()))) - } - SExp::Cons(l, a, b) => { - // There are a few cases: - // (normal destructuring) - // (@ name sub) - // (@ name sub : ty) - // (X : ty) - // We want to catch the final case and pass through its unannotated - // counterpart. - let next_depth = depth.clone() * 2_u32.to_bigint().unwrap(); - if let Some(lst) = args.proper_list() { - // Dive in - if lst.len() == 5 { - if let (SExp::Atom(l, n), SExp::Atom(_l2, n2)) = - (&lst[0].atomize(), &lst[3].atomize()) - { - if n == &vec![b'@'] && n2 == &vec![b':'] { - // At capture with annotation - return Err(CompileErr(l.clone(), "An at-capture with a type alias is currently unsupported. A struct can be used instead.".to_string())); - }; - }; - } else if lst.len() == 3 { - if let (SExp::Atom(l0, n0), SExp::Atom(_l1, n1)) = - (&lst[0].atomize(), &lst[1].atomize()) - { - if n1 == &vec![b':'] { - // Name with annotation - let ty = parse_type_sexp(Rc::new(lst[2].clone()))?; - arg_names.push(n0.clone()); - individual_types.insert(n0.clone(), ty.clone()); - individual_paths.insert(n0.clone(), depth + path); - individual_locs.insert(n0.clone(), l0.clone()); - return Ok((true, Rc::new(lst[0].clone()), ty)); - }; - }; - } - } - - let (got_ty_a, stripped_a, ty_a) = recover_arg_type_inner( - arg_names, - individual_types, - individual_paths, - individual_locs, - next_depth.clone(), - path.clone(), - a.clone(), - have_anno, - )?; - let (got_ty_b, stripped_b, ty_b) = recover_arg_type_inner( - arg_names, - individual_types, - individual_paths, - individual_locs, - next_depth, - path + depth, - b.clone(), - have_anno, - )?; - Ok(( - got_ty_a || got_ty_b, - Rc::new(SExp::Cons(l.clone(), stripped_a, stripped_b)), - Type::TPair(Rc::new(ty_a), Rc::new(ty_b)), - )) - } - _ => Err(CompileErr( - args.loc(), - "unrecognized argument form".to_string(), - )), - } -} - -pub fn recover_arg_type(args: Rc, always: bool) -> Result, CompileErr> { - let mut arg_names = Vec::new(); - let mut individual_types = HashMap::new(); - let mut individual_paths = HashMap::new(); - let mut individual_locs = HashMap::new(); - let (got_any, stripped, ty) = recover_arg_type_inner( - &mut arg_names, - &mut individual_types, - &mut individual_paths, - &mut individual_locs, - bi_one(), - bi_zero(), - args, - false, - )?; - if got_any || always { - Ok(Some(ArgTypeResult { - arg_names, - stripped_args: stripped, - individual_types, - individual_paths, - individual_locs, - whole_args: ty, - })) - } else { - Ok(None) - } -} - -// Given type recovered argument type and a candidate return type (possibly with -// a forall stack), construct the user's expected function type. If no arg types -// were given, the arg type is Any. If the bottom of the stack is a function -// type, its left hand type is replaced with the given arg type or Any. If it -// isn't a function type, it's promoted to be a function taking the given arg -// type or Any. -fn promote_with_arg_type(argty: &Polytype, funty: &Polytype) -> Polytype { - match funty { - Type::TForall(v, t) => { - Type::TForall(v.clone(), Rc::new(promote_with_arg_type(argty, t.borrow()))) - } - Type::TFun(_t1, t2) => Type::TFun(Rc::new(argty.clone()), t2.clone()), - _ => Type::TFun(Rc::new(argty.clone()), Rc::new(funty.clone())), - } -} - -// Returns None if result_ty is None and there are no type signatures recovered -// from the args. -// -// If the function's type signature is given with a TForall, the type variables -// given will be in scope for the arguments. -// If type arguments are given, the function's type signature must not be given -// as a function type (since all functions are arity-1 in chialisp). The final -// result type will be enriched to include the argument types. -fn augment_fun_type_with_args( - args: Rc, - result_ty: Option, -) -> Result<(Rc, Option), CompileErr> { - if let Some(atr) = recover_arg_type(args.clone(), false)? { - let mut tvars = Vec::new(); - - let actual_result_ty = if let Some(TypeAnnoKind::Arrow(rty)) = result_ty { - extract_type_variables_from_forall_stack(&mut tvars, &rty) - } else if let Some(TypeAnnoKind::Colon(rty)) = result_ty { - let want_rty = extract_type_variables_from_forall_stack(&mut tvars, &rty); - // If it's a function type, we have to give it as "args" - if let Type::TFun(t1, t2) = want_rty { - let t1_borrowed: &Polytype = t1.borrow(); - if t1_borrowed != &Type::TVar(TypeVar("args".to_string(), t1.loc())) { - return Err(CompileErr(t1.loc(), "When arguments are annotated, if the full function type is given, it must be given as (args -> ...). The 'args' type variable will contain the type implied by the individual argument annotations.".to_string())); - } - - let t2_borrowed: &Polytype = t2.borrow(); - t2_borrowed.clone() - } else { - want_rty - } - } else { - Type::TAny(args.loc()) - }; - - Ok(( - atr.stripped_args.clone(), - Some(promote_with_arg_type(&atr.whole_args, &actual_result_ty)), - )) - } else { - // No arg types were given. If a type was given for the result (non-fun) - // use Any -> Any - // else use the whole thing. - Ok(result_ty - .map(|rty| match rty { - TypeAnnoKind::Colon(t) => (args.clone(), Some(t)), - TypeAnnoKind::Arrow(t) => ( - args.clone(), - Some(Type::TFun(Rc::new(Type::TAny(args.loc())), Rc::new(t))), - ), - }) - .unwrap_or_else(|| (args.clone(), None))) - } -} - -fn create_constructor_code(sdef: &StructDef, proto: Rc) -> BodyForm { - match proto.atomize() { - SExp::Atom(l, n) => BodyForm::Value(SExp::Atom(l, n)), - SExp::Cons(l, a, b) => BodyForm::Call( - l.clone(), - vec![ - Rc::new(BodyForm::Value(SExp::Atom(l, b"c*".to_vec()))), - Rc::new(create_constructor_code(sdef, a)), - Rc::new(create_constructor_code(sdef, b)), - ], - ), - _ => BodyForm::Quoted(SExp::Nil(sdef.loc.clone())), - } -} - -fn create_constructor(sdef: &StructDef) -> HelperForm { - let mut access_name = "new_".as_bytes().to_vec(); - access_name.append(&mut sdef.name.clone()); - - // Iterate through the arguments in reverse to build up a linear argument - // list. - // Build up the type list in the same way. - let mut arguments = SExp::Nil(sdef.loc.clone()); - let mut argtype = Type::TUnit(sdef.loc.clone()); - - for m in sdef.members.iter().rev() { - argtype = Type::TPair(Rc::new(m.ty.clone()), Rc::new(argtype)); - arguments = SExp::Cons( - m.loc.clone(), - Rc::new(SExp::Atom(m.loc.clone(), m.name.clone())), - Rc::new(arguments), - ); - } - - let construction = create_constructor_code(sdef, sdef.proto.clone()); - let mut target_ty = Type::TVar(TypeVar(decode_string(&sdef.name), sdef.loc.clone())); - - for a in sdef.vars.iter().rev() { - target_ty = Type::TApp(Rc::new(target_ty), Rc::new(Type::TVar(a.clone()))); - } - - let mut funty = Type::TFun(Rc::new(argtype), Rc::new(target_ty)); - - for a in sdef.vars.iter().rev() { - funty = Type::TForall(a.clone(), Rc::new(funty)); - } - - HelperForm::Defun( - sdef.loc.clone(), - access_name, - true, - Rc::new(arguments), - Rc::new(construction), - Some(funty), - ) -} - -pub fn generate_type_helpers(ty: &ChiaType) -> Vec { - match ty { - ChiaType::Abstract(_, _) => vec![], - ChiaType::Struct(sdef) => { - // Construct ((S : )) - let struct_argument = Rc::new(SExp::Cons( - sdef.loc.clone(), - Rc::new(SExp::Atom(sdef.loc.clone(), vec![b'S'])), - Rc::new(SExp::Nil(sdef.loc.clone())), - )); - let mut members: Vec = sdef - .members - .iter() - .map(|m| { - let mut access_name = "get_".as_bytes().to_vec(); - access_name.append(&mut sdef.name.clone()); - access_name.push(b'_'); - access_name.append(&mut m.name.clone()); - - let mut argty = Type::TVar(TypeVar(decode_string(&sdef.name), m.loc.clone())); - - for a in sdef.vars.iter().rev() { - argty = Type::TApp(Rc::new(argty), Rc::new(Type::TVar(a.clone()))); - } - - let mut funty = Type::TFun( - Rc::new(Type::TPair( - Rc::new(argty), - Rc::new(Type::TUnit(m.loc.clone())), - )), - Rc::new(m.ty.clone()), - ); - - for a in sdef.vars.iter().rev() { - funty = Type::TForall(a.clone(), Rc::new(funty)); - } - - HelperForm::Defun( - m.loc.clone(), - access_name, - true, - struct_argument.clone(), - Rc::new(BodyForm::Call( - m.loc.clone(), - vec![ - Rc::new(BodyForm::Value(SExp::Atom( - m.loc.clone(), - vec![b'a', b'*'], - ))), - Rc::new(BodyForm::Quoted(SExp::Integer( - m.loc.clone(), - m.path.clone(), - ))), - Rc::new(BodyForm::Value(SExp::Atom(m.loc.clone(), vec![b'S']))), - ], - )), - Some(funty), - ) - }) - .collect(); - - let ctor = create_constructor(sdef); - members.push(ctor); - members - } - } -} - -fn parse_chia_type(v: Vec) -> Result { - // (deftype name args... (def)) - if let SExp::Atom(l, n) = &v[1].atomize() { - // Name - if v.len() == 2 { - // An abstract type - return Ok(ChiaType::Abstract(v[1].loc(), n.clone())); - } - - let vars: Vec = v.iter().skip(2).take(v.len() - 3).cloned().collect(); - let expr = Rc::new(v[v.len() - 1].clone()); - - let mut var_vec = Vec::new(); - for var in vars.iter() { - var_vec.push(parse_type_var(Rc::new(var.clone()))?); - } - - let type_of_body = recover_arg_type(expr, true)?.unwrap(); - let mut member_vec = Vec::new(); - for k in type_of_body.arg_names.iter() { - let arg_path = type_of_body - .individual_paths - .get(k) - .cloned() - .unwrap_or_else(bi_one); - let arg_loc = type_of_body - .individual_locs - .get(k) - .cloned() - .unwrap_or_else(|| l.clone()); - let arg_type = type_of_body - .individual_types - .get(k) - .cloned() - .unwrap_or_else(|| Type::TAny(arg_loc.clone())); - member_vec.push(StructMember { - loc: arg_loc, - name: k.clone(), - path: arg_path, - ty: arg_type, - }); - } - return Ok(ChiaType::Struct(StructDef { - loc: l.clone(), - name: n.clone(), - vars: var_vec, - members: member_vec, - proto: type_of_body.stripped_args, - ty: type_of_body.whole_args, - })); - } - - Err(CompileErr( - v[0].loc(), - "Don't know how to interpret as type definition".to_string(), - )) -} - -pub struct HelperFormResult { - pub chia_type: Option, - pub new_helpers: Vec, -} - -pub fn compile_helperform( - opts: Rc, - body: Rc, -) -> Result, CompileErr> { - let l = location_span(body.loc(), body.clone()); - - if let Some(matched) = body.proper_list().and_then(|pl| match_op_name_4(&pl)) { - if matched.op_name == b"defconstant" { - compile_defconstant( - opts, - l, - matched.nl, - Some(matched.opl), - matched.name.to_vec(), - matched.args, - ) - .map(Some) - } else if matched.op_name == b"defmacro" { - compile_defmacro( - opts, - l, - matched.nl, - Some(matched.opl), - matched.name.to_vec(), - matched.args, - matched.body, - ) - .map(Some) - } else if matched.op_name == b"defun" { - compile_defun( - opts, - CompileDefun { - l, - nl: matched.nl, - kwl: Some(matched.opl), - inline: false, - name: matched.name.to_vec(), - args: matched.args, - body: matched.body, - }, - ) - .map(Some) - } else if matched.op_name == b"defun-inline" { - compile_defun( - opts, - CompileDefun { - l, - nl: matched.nl, - kwl: Some(matched.opl), - inline: true, - name: matched.name.to_vec(), - args: matched.args, - body: matched.body, - }, - ) - .map(Some) - } else { - Err(CompileErr( - matched.body.loc(), - "unknown keyword in helper".to_string(), - )) - } - } else { - Err(CompileErr( - body.loc(), - "Helper wasn't in the proper form".to_string(), - )) - } -} - -fn compile_mod_( - mc: &ModAccum, - opts: Rc, - args: Rc, - content: Rc, -) -> Result { - match content.borrow() { - SExp::Nil(l) => Err(CompileErr( - l.clone(), - "no expression at end of mod".to_string(), - )), - SExp::Cons(l, body, tail) => match tail.borrow() { - SExp::Nil(_) => match mc.exp_form { - Some(_) => Err(CompileErr(l.clone(), "too many expressions".to_string())), - _ => Ok(mc.set_final(&CompileForm { - loc: mc.loc.clone(), - args, - helpers: mc.helpers.clone(), - exp: Rc::new(compile_bodyform(opts.clone(), body.clone())?), - })), - }, - _ => { - let helper = compile_helperform(opts.clone(), body.clone())?; - match helper { - None => Err(CompileErr( - l.clone(), - "only the last form can be an exprssion in mod".to_string(), - )), - Some(form) => match mc.exp_form { - None => compile_mod_(&mc.add_helper(form), opts, args, tail.clone()), - Some(_) => Err(CompileErr(l.clone(), "too many expressions".to_string())), - }, - } - } - Ok(mc) - } else { - Err(CompileErr( - body.loc(), - "only the last form can be an exprssion in mod".to_string(), - )) - } - } -} - -fn frontend_start( - opts: Rc, - pre_forms: &[Rc], -) -> Result { - if pre_forms.is_empty() { - Err(CompileErr( - Srcloc::start(&opts.filename()), - "empty source file not allowed".to_string(), - )) - } else { - let finish = || { - let loc = pre_forms[0].loc(); - frontend_start( - opts.clone(), - &[Rc::new(SExp::Cons( - loc.clone(), - Rc::new(SExp::Atom(loc.clone(), "mod".as_bytes().to_vec())), - Rc::new(SExp::Cons( - loc.clone(), - Rc::new(SExp::Nil(loc.clone())), - Rc::new(list_to_cons(loc, pre_forms)), - )), - ))], - ) - }; - let l = pre_forms[0].loc(); - pre_forms[0] - .proper_list() - .map(|x| { - if x.len() < 3 { - return finish(); - } - - if let SExp::Atom(_, mod_atom) = &x[0] { - if pre_forms.len() > 1 { - return Err(CompileErr( - pre_forms[0].loc(), - "one toplevel mod form allowed".to_string(), - )); - } - - if *mod_atom == "mod".as_bytes().to_vec() { - let args = Rc::new(x[1].atomize()); - let mut skip_idx = 2; - let mut ty: Option = None; - - if let SExp::Atom(_, colon) = &x[2].atomize() { - if *colon == vec![b':'] && x.len() > 3 { - let use_ty = parse_type_sexp(Rc::new(x[3].atomize()))?; - ty = Some(TypeAnnoKind::Colon(use_ty)); - skip_idx += 2; - } else if *colon == vec![b'-', b'>'] && x.len() > 3 { - let use_ty = parse_type_sexp(Rc::new(x[3].atomize()))?; - ty = Some(TypeAnnoKind::Arrow(use_ty)); - skip_idx += 2; - } - } - let (stripped_args, parsed_type) = augment_fun_type_with_args(args, ty)?; - - let body_vec = x - .iter() - .skip(skip_idx) - .map(|s| Rc::new(s.clone())) - .collect(); - let body = Rc::new(enlist(pre_forms[0].loc(), body_vec)); - - let ls = preprocess(opts.clone(), body)?; - let mut ma = ModAccum::new(l.clone()); - for form in ls.iter().take(ls.len() - 1) { - ma = ma.compile_mod_helper( - opts.clone(), - stripped_args.clone(), - form.clone(), - parsed_type.clone(), - )?; - } - - return ma.compile_mod_body( - opts.clone(), - stripped_args, - ls[ls.len() - 1].clone(), - parsed_type, - ); - } - } - - finish() - }) - .unwrap_or_else(finish) - } -} - -pub fn frontend( - opts: Rc, - pre_forms: &[Rc], -) -> Result { - let started = frontend_start(opts.clone(), pre_forms)?; - - let compiled: Result = match started.exp_form { - None => Err(CompileErr( - started.loc, - "mod must end on an expression".to_string(), - )), - Some(v) => { - let compiled_val: &CompileForm = v.borrow(); - Ok(compiled_val.clone()) - } - }; - - let our_mod = rename_children_compileform(&compiled?); - - let expr_names: HashSet> = collect_used_names_bodyform(our_mod.exp.borrow()) - .iter() - .map(|x| x.to_vec()) - .collect(); - - let helper_list = our_mod.helpers.iter().map(|h| (h.name(), h)); - let mut helper_map = HashMap::new(); - - for hpair in helper_list { - helper_map.insert(hpair.0.clone(), hpair.1.clone()); - } - - let helper_names = calculate_live_helpers(&HashSet::new(), &expr_names, &helper_map); - - let mut live_helpers = Vec::new(); - for h in our_mod.helpers { - if matches!(h, HelperForm::Deftype(_, _, _, _)) || helper_names.contains(h.name()) { - live_helpers.push(h); - } - } - - Ok(CompileForm { - loc: our_mod.loc.clone(), - args: our_mod.args.clone(), - helpers: live_helpers, - exp: our_mod.exp.clone(), - ty: our_mod.ty.clone(), - }) -} - -fn is_quote_op(sexp: Rc) -> bool { - match sexp.borrow() { - SExp::Atom(_, name) => name.len() == 1 && name[0] as char == 'q', - SExp::Integer(_, v) => v == &bi_one(), - _ => false, - } -} - -fn from_clvm_args(args: Rc) -> Rc { - match args.borrow() { - SExp::Cons(l, arg, rest) => { - let new_arg = from_clvm(arg.clone()); - let new_rest = from_clvm_args(rest.clone()); - Rc::new(SExp::Cons(l.clone(), new_arg, new_rest)) - } - _ => { - // Treat tail of proper application list as expression. - from_clvm(args.clone()) - } - } -} - -// Form proper frontend code from CLVM. -// The languages are related but not identical: -// - Left env references refer to functions from the env. -// - Right env references refer to user arguments. -// We can introduce defconstant helpers that allow us to keep track of what's -// being called via 'a' and use that information. -// Bare numbers in operator position are only prims. -// Bare numbers in argument position are references, rewrite as (@ ..) -pub fn from_clvm(sexp: Rc) -> Rc { - match sexp.borrow() { - SExp::Atom(l, _name) => { - // An atom encountered as an expression is treated as a path. - from_clvm(Rc::new(SExp::Integer(l.clone(), sexp.to_bigint().unwrap()))) - } - SExp::QuotedString(l, _, _v) => { - // A string is treated as a number. - // An atom encountered as an expression is treated as a path. - from_clvm(Rc::new(SExp::Integer(l.clone(), sexp.to_bigint().unwrap()))) - } - SExp::Integer(l, _n) => { - // A number is treated as a reference in expression position. - // Results in (@ n). - Rc::new(SExp::Cons( - l.clone(), - Rc::new(SExp::atom_from_string(l.clone(), "@")), - Rc::new(SExp::Cons( - l.clone(), - sexp.clone(), - Rc::new(SExp::Nil(l.clone())), - )), - )) - } - SExp::Nil(_l) => { - // Nil represents nil in both systems. - sexp.clone() - } - SExp::Cons(l, op, args) => { - // This expression represents applying some primitive. - if is_quote_op(op.clone()) { - Rc::new(SExp::Cons( - l.clone(), - Rc::new(SExp::atom_from_string(l.clone(), "q")), - args.clone(), - )) - } else { - let new_args = from_clvm_args(args.clone()); - Rc::new(SExp::Cons(l.clone(), op.clone(), new_args)) - } - } - } -} diff --git a/src/compiler/inline.rs b/src/compiler/inline.rs index c60a6e511..5111ddd41 100644 --- a/src/compiler/inline.rs +++ b/src/compiler/inline.rs @@ -1,6 +1,6 @@ use num_bigint::ToBigInt; use std::borrow::Borrow; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::rc::Rc; use crate::classic::clvm::__type_compatibility__::bi_one; @@ -10,11 +10,12 @@ use crate::compiler::codegen::{generate_expr_code, get_call_name, get_callable}; use crate::compiler::compiler::is_at_capture; use crate::compiler::comptypes::{ ArgsAndTail, BodyForm, CallSpec, Callable, CompileErr, CompiledCode, CompilerOpts, - InlineFunction, PrimaryCodegen, + InlineFunction, LambdaData, PrimaryCodegen, }; +use crate::compiler::lambda::make_cons; use crate::compiler::sexp::{decode_string, SExp}; use crate::compiler::srcloc::Srcloc; -use crate::compiler::BasicCompileContext; +use crate::compiler::{BasicCompileContext, CompileContextWrapper}; use crate::util::Number; @@ -440,11 +441,56 @@ fn replace_inline_body( } } } - BodyForm::Value(SExp::Atom(_, a)) => { + BodyForm::Value(SExp::Atom(l, a)) => { + if a == b"@*env*" { + // Reify the environment as it looks from here. + let left_env = Rc::new(BodyForm::Call( + l.clone(), + vec![ + Rc::new(BodyForm::Value(SExp::Atom(l.clone(), b"@".to_vec()))), + Rc::new(BodyForm::Value(SExp::Integer( + l.clone(), + 2_u32.to_bigint().unwrap(), + ))), + ], + // Builtin + None, + )); + let mut env = Rc::new(BodyForm::Quoted(SExp::Nil(l.clone()))); + for arg in args.iter().rev() { + env = Rc::new(make_cons(l.clone(), arg.clone(), env)); + } + env = Rc::new(make_cons(l.clone(), left_env, env)); + return Ok(env); + } else if a == b"@" { + return Ok(Rc::new(BodyForm::Value(SExp::Atom( + l.clone(), + b"@".to_vec(), + )))); + } + let alookup = arg_lookup(callsite, inline.args.clone(), args, tail, a.clone())? .unwrap_or_else(|| expr.clone()); Ok(alookup) } + BodyForm::Lambda(ldata) => { + let rewritten_captures = replace_inline_body( + visited_inlines, + runner, + opts, + compiler, + loc, + inline, + args, + tail, + callsite, + ldata.captures.clone(), + )?; + Ok(Rc::new(BodyForm::Lambda(Box::new(LambdaData { + captures: rewritten_captures, + ..*ldata.clone() + })))) + } _ => Ok(expr.clone()), } } @@ -491,5 +537,12 @@ pub fn replace_in_inline( callsite, inline.body.clone(), ) - .and_then(|x| generate_expr_code(context, opts, compiler, x)) + .and_then(|x| { + let mut symbols = HashMap::new(); + let runner = context.runner(); + let optimizer = context.optimizer.duplicate(); + let mut context_wrapper = + CompileContextWrapper::new(context.allocator(), runner, &mut symbols, optimizer); + generate_expr_code(&mut context_wrapper.context, opts, compiler, x) + }) } diff --git a/src/compiler/lambda.rs b/src/compiler/lambda.rs new file mode 100644 index 000000000..aeb08297e --- /dev/null +++ b/src/compiler/lambda.rs @@ -0,0 +1,244 @@ +use std::borrow::Borrow; +use std::rc::Rc; + +use num_bigint::ToBigInt; + +use crate::classic::clvm::__type_compatibility__::{bi_one, bi_zero}; + +use crate::compiler::clvm::truthy; +use crate::compiler::compiler::is_at_capture; +use crate::compiler::comptypes::{ + Binding, BindingPattern, BodyForm, CompileErr, CompilerOpts, LambdaData, +}; +use crate::compiler::evaluate::make_operator2; +use crate::compiler::frontend::compile_bodyform; +use crate::compiler::sexp::SExp; +use crate::compiler::srcloc::Srcloc; +use crate::util::Number; + +fn make_captures(opts: Rc, sexp: Rc) -> Result, CompileErr> { + if let SExp::Cons(l, f, r) = sexp.borrow() { + Ok(Rc::new(make_operator2( + l, + "c".to_string(), + make_captures(opts.clone(), f.clone())?, + make_captures(opts, r.clone())?, + ))) + } else if !truthy(sexp.clone()) { + Ok(Rc::new(BodyForm::Quoted(SExp::Nil(sexp.loc())))) + } else { + Ok(Rc::new(compile_bodyform(opts, sexp)?)) + } +} + +struct FoundLambdaCaptures { + args: Rc, + capture_args: Rc, + captures: Rc, +} + +fn find_and_compose_captures( + opts: Rc, + sexp: &SExp, +) -> Result { + let mut found = FoundLambdaCaptures { + args: Rc::new(sexp.clone()), + capture_args: Rc::new(SExp::Nil(sexp.loc())), + captures: Rc::new(BodyForm::Quoted(SExp::Nil(sexp.loc()))), + }; + if let SExp::Cons(_, l, r) = sexp { + if let SExp::Cons(_, head, rest) = l.borrow() { + if let SExp::Atom(_, name) = head.borrow() { + if name == b"&" { + found.args = r.clone(); + found.capture_args = rest.clone(); + found.captures = make_captures(opts, rest.clone())?; + } + } + } + } + + Ok(found) +} + +fn make_operator(loc: Srcloc, op: u8, arg1: Rc, arg2: Rc) -> BodyForm { + BodyForm::Call( + loc.clone(), + vec![ + Rc::new(BodyForm::Value(SExp::Integer(loc, op.to_bigint().unwrap()))), + arg1, + arg2, + ], + // Tail safe: creates a primitive. + None, + ) +} + +pub fn make_cons(loc: Srcloc, arg1: Rc, arg2: Rc) -> BodyForm { + make_operator(loc, 4, arg1, arg2) +} + +fn make_list(loc: Srcloc, args: &[BodyForm]) -> BodyForm { + let mut res = BodyForm::Quoted(SExp::Nil(loc.clone())); + let cons_atom = BodyForm::Value(SExp::Atom(loc.clone(), vec![4])); + for a in args.iter().rev() { + res = BodyForm::Call( + loc.clone(), + vec![Rc::new(cons_atom.clone()), Rc::new(a.clone()), Rc::new(res)], + // Tail safe: creating a list with primitives. + None, + ); + } + res +} + +// +// Lambda +// +// (lambda ((& captures) arguments) +// (body) +// ) +// +// Yields: +// +// (list 2 +// (c 1 ) +// (list 4 (list 4 (c 1 compose_captures) @)) +// ) +// +pub fn lambda_codegen(name: &[u8], ldata: &LambdaData) -> Result { + // Code to retrieve and quote the captures. + let quote_atom = BodyForm::Value(SExp::Integer(ldata.loc.clone(), bi_one())); + let apply_atom = BodyForm::Value(SExp::Integer(ldata.loc.clone(), 2_u32.to_bigint().unwrap())); + let cons_atom = BodyForm::Value(SExp::Integer(ldata.loc.clone(), 4_u32.to_bigint().unwrap())); + let whole_env = quote_atom.clone(); + + let compose_captures = make_cons( + ldata.loc.clone(), + Rc::new(quote_atom.clone()), + ldata.captures.clone(), + ); + + let lambda_output = make_list( + ldata.loc.clone(), + &[ + apply_atom, + make_cons( + ldata.loc.clone(), + Rc::new(quote_atom), + Rc::new(BodyForm::Value(SExp::Atom( + ldata.loc.clone(), + name.to_vec(), + ))), + ), + make_list(ldata.loc.clone(), &[cons_atom, compose_captures, whole_env]), + ], + ); + Ok(lambda_output) +} + +pub fn handle_lambda( + opts: Rc, + kw_loc: Option, + v: &[SExp], +) -> Result { + if v.len() < 2 { + return Err(CompileErr( + v[0].loc(), + "Must provide at least arguments and body to lambda".to_string(), + )); + } + + let found = find_and_compose_captures(opts.clone(), &v[0])?; + + // Requires captures + let subparse = compile_bodyform(opts, Rc::new(v[1].clone()))?; + + Ok(BodyForm::Lambda(Box::new(LambdaData { + loc: v[0].loc(), + kw: kw_loc, + args: found.args.clone(), + capture_args: found.capture_args.clone(), + captures: found.captures, + body: Rc::new(subparse), + }))) +} + +// Used during type elaboration. This generates a path of f and r operators into +// the single unary argument of the lambda to extract a specific binding. +fn generate_get_from_var(mask: Number, target_path: Number, arg: Rc) -> Rc { + let two = 2_u32.to_bigint().unwrap(); + if mask.clone() * two.clone() > target_path { + // Found where we're going + return arg; + } + let is_right = mask.clone() & target_path.clone() != bi_zero(); + let new_op = if is_right { b"r" } else { b"f" }; + let new_body = Rc::new(BodyForm::Call( + arg.loc(), + vec![ + Rc::new(BodyForm::Value(SExp::Atom(arg.loc(), new_op.to_vec()))), + arg.clone(), + ], + // Tail safe: generating a primitive. + None, + )); + generate_get_from_var(mask * two, target_path, new_body) +} + +// Recurse over the argument bindings of a lambda and generate Binding objects +// for a let form which binds the multiple destructured arguments (virtually) +// from the literal unary argument. +fn form_lambda_bindings_inner( + bindings: &mut Vec>, + arg: Rc, + mask: Number, + path: Number, + args: Rc, +) { + match args.borrow() { + SExp::Cons(_, l, r) => { + if let Some((name, farther)) = is_at_capture(l.clone(), r.clone()) { + form_lambda_bindings_inner( + bindings, + arg.clone(), + mask.clone(), + path.clone(), + Rc::new(SExp::Atom(args.loc(), name.to_vec())), + ); + form_lambda_bindings_inner(bindings, arg, mask, path, farther); + return; + } + let right_path = path.clone() | mask.clone(); + let new_mask = mask * 2_u32.to_bigint().unwrap(); + form_lambda_bindings_inner(bindings, arg.clone(), new_mask.clone(), path, l.clone()); + form_lambda_bindings_inner(bindings, arg, new_mask, right_path, r.clone()); + } + SExp::Atom(l, _a) => { + let target_path = path | mask; + let arg_borrowed: &SExp = arg.borrow(); + let body = generate_get_from_var( + bi_one(), + target_path, + Rc::new(BodyForm::Value(arg_borrowed.clone())), + ); + bindings.push(Rc::new(Binding { + nl: l.clone(), + loc: l.clone(), + pattern: BindingPattern::Complex(args), + body, + })); + } + _ => {} + } +} + +/// For typing: let the argument be a single argument. +/// for each argument in the environment, add a binding to a let that retrieves +/// it from the argument type. +pub fn form_lambda_bindings(arg_name: &[u8], args: Rc) -> Vec> { + let mut bindings = Vec::new(); + let arg = Rc::new(SExp::Atom(args.loc(), arg_name.to_vec())); + form_lambda_bindings_inner(&mut bindings, arg, bi_one(), bi_zero(), args); + bindings +} diff --git a/src/compiler/mod.rs b/src/compiler/mod.rs index 605c645ef..8595462a9 100644 --- a/src/compiler/mod.rs +++ b/src/compiler/mod.rs @@ -20,6 +20,7 @@ pub mod evaluate; pub mod frontend; pub mod gensym; mod inline; +mod lambda; pub mod optimize; pub mod preprocessor; pub mod prims; @@ -41,6 +42,11 @@ use std::mem::swap; use std::rc::Rc; use crate::classic::clvm_tools::stages::stage_0::TRunProgram; +use crate::compiler::comptypes::{ + BodyForm, CompileErr, CompileForm, CompilerOpts, DefunData, HelperForm, PrimaryCodegen, +}; +use crate::compiler::optimize::Optimization; +use crate::compiler::sexp::SExp; /// An object which represents the standard set of mutable items passed down the /// stack when compiling chialisp. @@ -48,6 +54,7 @@ pub struct BasicCompileContext { pub allocator: Allocator, pub runner: Rc, pub symbols: HashMap, + pub optimizer: Box, } impl BasicCompileContext { @@ -77,6 +84,109 @@ impl BasicCompileContext { &mut self.symbols } + /// Called after frontend parsing and preprocessing when we have a complete + /// picture of the user's intended semantics. + fn frontend_optimization( + &mut self, + opts: Rc, + cf: CompileForm, + ) -> Result { + let runner = self.runner.clone(); + self.optimizer + .frontend_optimization(&mut self.allocator, runner, opts, cf) + } + + fn post_desugar_optimization( + &mut self, + opts: Rc, + cf: CompileForm, + ) -> Result { + let runner = self.runner.clone(); + self.optimizer + .post_desugar_optimization(&mut self.allocator, runner, opts, cf) + } + + /// Shrink the program prior to generating the final environment map and + /// doing other codegen tasks. This also serves as a tree-shaking pass. + fn start_of_codegen_optimization( + &mut self, + opts: Rc, + to_optimize: StartOfCodegenOptimization, + ) -> Result { + let runner = self.runner.clone(); + self.optimizer + .start_of_codegen_optimization(&mut self.allocator, runner, opts, to_optimize) + } + + /// Note: must take measures to ensure that the symbols are changed along + /// with any code that's changed. It's likely better to do optimizations + /// at other stages, such as post_codegen_function_optimize. + fn post_codegen_output_optimize( + &mut self, + opts: Rc, + generated: SExp, + ) -> Result { + self.optimizer.post_codegen_output_optimize(opts, generated) + } + + /// Called when a full macro program optimization is used. + fn macro_optimization( + &mut self, + opts: Rc, + code: Rc, + ) -> Result, CompileErr> { + self.optimizer + .macro_optimization(&mut self.allocator, self.runner.clone(), opts, code) + } + + /// Called to transform a defun before generating code from it. + /// Returns a new bodyform. + fn pre_codegen_function_optimize( + &mut self, + opts: Rc, + codegen: &PrimaryCodegen, + defun: &DefunData, + ) -> Result, CompileErr> { + self.optimizer.defun_body_optimization( + &mut self.allocator, + self.runner.clone(), + opts, + codegen, + defun, + ) + } + + /// Called to transform the function body after code generation. + fn post_codegen_function_optimize( + &mut self, + opts: Rc, + helper: Option<&HelperForm>, + code: Rc, + ) -> Result, CompileErr> { + self.optimizer.post_codegen_function_optimize( + &mut self.allocator, + self.runner.clone(), + opts, + helper, + code, + ) + } + + /// Call in final_codegen to get the final main bodyform to generate + /// code from. + fn pre_final_codegen_optimize( + &mut self, + opts: Rc, + codegen: &PrimaryCodegen, + ) -> Result, CompileErr> { + self.optimizer.pre_final_codegen_optimize( + &mut self.allocator, + self.runner.clone(), + opts, + codegen, + ) + } + /// Given allocator, runner and symbols, move the mutable objects into this /// BasicCompileContext so it can own them and pass a single mutable /// reference to itself down the stack. This allows these objects to be @@ -85,11 +195,13 @@ impl BasicCompileContext { allocator: Allocator, runner: Rc, symbols: HashMap, + optimizer: Box, ) -> Self { BasicCompileContext { allocator, runner, symbols, + optimizer, } } } @@ -127,11 +239,13 @@ impl<'a> CompileContextWrapper<'a> { allocator: &'a mut Allocator, runner: Rc, symbols: &'a mut HashMap, + optimizer: Box, ) -> Self { let bcc = BasicCompileContext { allocator: Allocator::new(), runner, symbols: HashMap::new(), + optimizer, }; let mut wrapper = CompileContextWrapper { allocator, @@ -160,3 +274,11 @@ impl<'a> Drop for CompileContextWrapper<'a> { self.switch(); } } + +/// Describes the unique inputs and outputs available at the start of code +/// generation. +#[derive(Debug, Clone)] +pub struct StartOfCodegenOptimization { + program: CompileForm, + code_generator: PrimaryCodegen, +} diff --git a/src/compiler/optimize.rs b/src/compiler/optimize.rs deleted file mode 100644 index 84a262042..000000000 --- a/src/compiler/optimize.rs +++ /dev/null @@ -1,125 +0,0 @@ -use std::borrow::Borrow; -use std::rc::Rc; - -use clvm_rs::allocator::Allocator; - -use crate::classic::clvm_tools::stages::stage_0::TRunProgram; - -use crate::compiler::clvm::run; -use crate::compiler::codegen::get_callable; -use crate::compiler::comptypes::{BodyForm, Callable, CompilerOpts, PrimaryCodegen}; -use crate::compiler::sexp::SExp; -use crate::compiler::srcloc::Srcloc; -use crate::util::u8_from_number; - -const CONST_FOLD_LIMIT: usize = 10000000; - -fn is_at_form(head: Rc) -> bool { - match head.borrow() { - BodyForm::Value(SExp::Atom(_, a)) => a.len() == 1 && a[0] == b'@', - _ => false, - } -} - -/// At this point, very rudimentary constant folding on body expressions. -pub fn optimize_expr( - allocator: &mut Allocator, - opts: Rc, - runner: Rc, - compiler: &PrimaryCodegen, - body: Rc, -) -> Option<(bool, Rc)> { - match body.borrow() { - BodyForm::Quoted(_) => Some((true, body)), - BodyForm::Call(l, forms, None) => { - // () evaluates to () - if forms.is_empty() { - return Some((true, body)); - } else if is_at_form(forms[0].clone()) { - return None; - } - - let mut examine_call = |al: Srcloc, an: &Vec| { - get_callable( - opts.clone(), - compiler, - l.clone(), - Rc::new(SExp::Atom(al, an.to_vec())), - ) - .map(|calltype| match calltype { - // A macro invocation emits a bodyform, which we - // run back through the frontend and check. - Callable::CallMacro(_l, _) => None, - // A function is constant if its body is a constant - // expression or all its arguments are constant and - // its body doesn't include an environment reference. - Callable::CallDefun(_l, _target) => None, - // A primcall is constant if its arguments are constant - Callable::CallPrim(l, _) => { - let mut constant = true; - let optimized_args: Vec<(bool, Rc)> = forms - .iter() - .skip(1) - .map(|a| { - let optimized = optimize_expr( - allocator, - opts.clone(), - runner.clone(), - compiler, - a.clone(), - ); - constant = constant - && optimized.as_ref().map(|x| x.0).unwrap_or_else(|| false); - optimized - .map(|x| (x.0, x.1)) - .unwrap_or_else(|| (false, a.clone())) - }) - .collect(); - - let mut result_list = vec![forms[0].clone()]; - let mut replaced_args = - optimized_args.iter().map(|x| x.1.clone()).collect(); - result_list.append(&mut replaced_args); - // Calling a primitive. - let code = BodyForm::Call(l.clone(), result_list, None); - - if constant { - run( - allocator, - runner.clone(), - opts.prim_map(), - code.to_sexp(), - Rc::new(SExp::Nil(l)), - Some(CONST_FOLD_LIMIT), - ) - .map(|x| { - let x_borrow: &SExp = x.borrow(); - Some((true, Rc::new(BodyForm::Quoted(x_borrow.clone())))) - }) - .unwrap_or_else(|_| Some((false, Rc::new(code)))) - } else { - Some((false, Rc::new(code))) - } - } - _ => None, - }) - .unwrap_or_else(|_| None) - }; - - match forms[0].borrow() { - BodyForm::Value(SExp::Integer(al, an)) => { - examine_call(al.clone(), &u8_from_number(an.clone())) - } - BodyForm::Value(SExp::QuotedString(al, _, an)) => examine_call(al.clone(), an), - BodyForm::Value(SExp::Atom(al, an)) => examine_call(al.clone(), an), - _ => None, - } - } - BodyForm::Call(_l, _forms, Some(_)) => None, - BodyForm::Value(SExp::Integer(l, i)) => Some(( - true, - Rc::new(BodyForm::Quoted(SExp::Integer(l.clone(), i.clone()))), - )), - _ => None, - } -} diff --git a/src/compiler/optimize/above22.rs b/src/compiler/optimize/above22.rs new file mode 100644 index 000000000..7cf01aab2 --- /dev/null +++ b/src/compiler/optimize/above22.rs @@ -0,0 +1,240 @@ +use std::borrow::Borrow; +use std::collections::HashMap; +use std::rc::Rc; + +use clvmr::allocator::Allocator; + +use crate::classic::clvm_tools::stages::stage_0::TRunProgram; + +use crate::compiler::comptypes::{ + BodyForm, CompileErr, CompileForm, CompilerOpts, DefunData, HelperForm, PrimaryCodegen, +}; +use crate::compiler::frontend::compute_live_helpers; +use crate::compiler::optimize::brief::brief_path_selection; +use crate::compiler::optimize::cse::cse_optimize_bodyform; +use crate::compiler::optimize::deinline::deinline_opt; +use crate::compiler::optimize::double_apply::remove_double_apply; +use crate::compiler::optimize::{ + null_optimization, optimize_expr, run_optimizer, CompileContextWrapper, Optimization, +}; +use crate::compiler::sexp::SExp; +use crate::compiler::StartOfCodegenOptimization; + +/// Captures the strategy for cl23 and above. +/// Until formally released, we can take action in here. +#[derive(Default, Clone)] +pub struct Strategy23 {} + +impl Strategy23 { + pub fn new() -> Self { + Strategy23 {} + } +} + +impl Optimization for Strategy23 { + fn frontend_optimization( + &mut self, + _allocator: &mut Allocator, + _runner: Rc, + _opts: Rc, + mut p0: CompileForm, + ) -> Result { + let mut rebuilt_helpers = Vec::new(); + for h in p0.helpers.iter() { + if let HelperForm::Defun(inline, d) = h { + let function_body = cse_optimize_bodyform(&h.loc(), h.name(), d.body.borrow())?; + // Ok we've got a body that is now a let stack. + let new_helper = HelperForm::Defun( + *inline, + Box::new(DefunData { + body: Rc::new(function_body), + ..*d.clone() + }), + ); + + rebuilt_helpers.push(new_helper); + } else { + rebuilt_helpers.push(h.clone()); + } + } + + p0.helpers = rebuilt_helpers; + Ok(p0) + } + + fn post_desugar_optimization( + &mut self, + allocator: &mut Allocator, + runner: Rc, + opts: Rc, + cf: CompileForm, + ) -> Result { + let mut symbols = HashMap::new(); + let mut wrapper = + CompileContextWrapper::new(allocator, runner, &mut symbols, self.duplicate()); + deinline_opt(&mut wrapper.context, opts.clone(), cf) + } + + fn start_of_codegen_optimization( + &mut self, + allocator: &mut Allocator, + runner: Rc, + opts: Rc, + mut to_optimize: StartOfCodegenOptimization, + ) -> Result { + let new_helpers: Vec = to_optimize + .program + .helpers + .iter() + .map(|h| { + if let HelperForm::Defun(inline, defun) = h { + let new_body = optimize_expr( + allocator, + opts.clone(), + runner.clone(), + &to_optimize.code_generator, + defun.body.clone(), + ) + .map(|x| x.1) + .unwrap_or_else(|| defun.body.clone()); + HelperForm::Defun( + *inline, + Box::new(DefunData { + body: new_body, + ..*defun.clone() + }), + ) + } else { + h.clone() + } + }) + .collect(); + + to_optimize.program.helpers = new_helpers; + to_optimize.program.exp = optimize_expr( + allocator, + opts.clone(), + runner.clone(), + &to_optimize.code_generator, + to_optimize.program.exp.clone(), + ) + .map(|x| x.1) + .unwrap_or_else(|| to_optimize.program.exp.clone()); + + let used_helpers = compute_live_helpers( + opts, + &to_optimize.program.helpers, + to_optimize.program.exp.clone(), + ); + + to_optimize.program.helpers = used_helpers; + + Ok(to_optimize) + } + + fn macro_optimization( + &mut self, + allocator: &mut Allocator, + runner: Rc, + _opts: Rc, + code: Rc, + ) -> Result, CompileErr> { + run_optimizer(allocator, runner, code) + } + + fn defun_body_optimization( + &mut self, + allocator: &mut Allocator, + runner: Rc, + opts: Rc, + codegen: &PrimaryCodegen, + defun: &DefunData, + ) -> Result, CompileErr> { + // Run optimizer on frontend style forms. + let mut changed = true; + let mut new_body = defun.body.clone(); + + while changed { + if let Some((did_optimize, optimized_form)) = optimize_expr( + allocator, + opts.clone(), + runner.clone(), + codegen, + new_body.clone(), + ) { + changed = did_optimize && optimized_form.to_sexp() != new_body.to_sexp(); + new_body = optimized_form; + } else { + changed = false; + } + } + + Ok(new_body) + } + + fn post_codegen_function_optimize( + &mut self, + _allocator: &mut Allocator, + _runner: Rc, + _opts: Rc, + _helper: Option<&HelperForm>, + code: Rc, + ) -> Result, CompileErr> { + let (null_worked, result) = null_optimization(code.clone(), true); + let (double_worked, dbl_result) = remove_double_apply(result, true); + let (brief_worked, brief_result) = brief_path_selection(dbl_result); + if null_worked || double_worked || brief_worked { + Ok(brief_result) + } else { + Ok(code) + } + } + + fn pre_final_codegen_optimize( + &mut self, + allocator: &mut Allocator, + runner: Rc, + opts: Rc, + codegen: &PrimaryCodegen, + ) -> Result, CompileErr> { + let mut changed = true; + let mut new_body = codegen.final_expr.clone(); + + while changed { + if let Some((did_optimize, optimized_form)) = optimize_expr( + allocator, + opts.clone(), + runner.clone(), + codegen, + new_body.clone(), + ) { + changed = did_optimize && optimized_form.to_sexp() != new_body.to_sexp(); + new_body = optimized_form; + } else { + changed = false; + } + } + + Ok(new_body) + } + + fn post_codegen_output_optimize( + &mut self, + _opts: Rc, + generated: SExp, + ) -> Result { + let (null_worked, result) = null_optimization(Rc::new(generated.clone()), true); + let (double_worked, dbl_result) = remove_double_apply(result, true); + let (brief_worked, brief_result) = brief_path_selection(dbl_result); + if null_worked || double_worked || brief_worked { + let borrowed: &SExp = brief_result.borrow(); + Ok(borrowed.clone()) + } else { + Ok(generated) + } + } + + fn duplicate(&self) -> Box { + Box::new(self.clone()) + } +} diff --git a/src/compiler/optimize/bodyform.rs b/src/compiler/optimize/bodyform.rs new file mode 100644 index 000000000..73109bb8d --- /dev/null +++ b/src/compiler/optimize/bodyform.rs @@ -0,0 +1,430 @@ +use std::borrow::Borrow; +use std::cmp::{min, Ordering}; +use std::rc::Rc; + +use crate::compiler::comptypes::{Binding, BodyForm, CompileForm, LambdaData, LetData}; + +// Rewriting and matching on bodyforms. +// Allows a convenient bodyform path description. + +/// A path in a bodyform. Allows us to find and potentially replace the bodyform +/// in a larger expression. +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum BodyformPathArc { + LetBinding(usize), // In (let ((a 1) (b 2)) LetBinding(1) points to 2 + CallArgument(usize), // in (x0 x1 x2 x3 x4 x5) CallArgument(3) points to x3 + BodyOf, // In the body of a lambda, mod or let. +} + +/// True if b is contained in a. +pub fn path_overlap_one_way(a: &[BodyformPathArc], b: &[BodyformPathArc]) -> bool { + let a_len = a.len(); + let b_len = b.len(); + + // a is longer than b, so b can't be in a. + if a_len > b_len { + return false; + } + + let iter_until = min(a.len(), b.len()); + for idx in 0..iter_until { + if a[idx] != b[idx] { + // They diverged. + return false; + } + } + + true +} + +/// Determines whether a and b conflict (a is a superset of b or vice versa). +pub fn path_overlap(a: &[BodyformPathArc], b: &[BodyformPathArc]) -> bool { + path_overlap_one_way(a, b) || path_overlap_one_way(b, a) +} + +/// A single valid result from visit_detect_in_bodyform noting the path to the +/// bodyform, the form itself and the returned context from the visitor function. +#[derive(Clone)] +pub struct PathDetectVisitorResult { + pub path: Vec, + pub subexp: BodyForm, + pub context: R, +} + +/// Visit over a bodyform offering the path, original and current bodyforms to the +/// visitor. The vistor returns Ok(None) to just go on, Ok(Some(R)) to accept and +/// record the path and can return error to abort. +fn visit_detect_in_bodyform_inner( + path: &mut Vec, + res: &mut Vec>, + f: &F, + original: &BodyForm, + bf: &BodyForm, +) -> Result<(), E> +where + F: Fn(&[BodyformPathArc], &BodyForm, &BodyForm) -> Result, E>, +{ + let path_idx = path.len(); + match bf { + BodyForm::Call(_l, args, tail) => { + for (i, a) in args.iter().enumerate() { + path.push(BodyformPathArc::CallArgument(i)); + visit_detect_in_bodyform_inner(path, res, f, original, a)?; + path.truncate(path_idx); + } + if let Some(t) = tail.as_ref() { + path.push(BodyformPathArc::CallArgument(args.len())); + visit_detect_in_bodyform_inner(path, res, f, original, t)?; + path.truncate(path_idx); + } + } + BodyForm::Let(_k, b) => { + for (i, a) in b.bindings.iter().enumerate() { + path.push(BodyformPathArc::LetBinding(i)); + visit_detect_in_bodyform_inner(path, res, f, original, a.body.borrow())?; + path.truncate(path_idx); + } + path.push(BodyformPathArc::BodyOf); + visit_detect_in_bodyform_inner(path, res, f, original, b.body.borrow())?; + path.truncate(path_idx); + } + BodyForm::Lambda(ldata) => { + path.push(BodyformPathArc::BodyOf); + visit_detect_in_bodyform_inner(path, res, f, original, ldata.body.borrow())?; + path.truncate(path_idx); + } + BodyForm::Mod(_, form) => { + path.push(BodyformPathArc::BodyOf); + visit_detect_in_bodyform_inner(path, res, f, original, form.exp.borrow())?; + path.truncate(path_idx); + } + _ => {} + } + + // And for this node, call the visitor. + if let Some(r) = f(path, original, bf)? { + res.push(PathDetectVisitorResult { + path: path.clone(), + subexp: bf.clone(), + context: r, + }); + } + + Ok(()) +} + +pub fn visit_detect_in_bodyform( + f: &F, + bf: &BodyForm, +) -> Result>, E> +where + F: Fn(&[BodyformPathArc], &BodyForm, &BodyForm) -> Result, E>, +{ + let mut path = vec![]; + let mut res = vec![]; + visit_detect_in_bodyform_inner(&mut path, &mut res, f, bf, bf)?; + Ok(res) +} + +#[allow(clippy::too_many_arguments)] +fn replace_in_bodyform_inner_list<'a, L, P, F, F1, G, H, R>( + current_path: &mut Vec, + replacements: &[PathDetectVisitorResult], + list_of: &'a [L], + tail_of: &'a Option, + make_path_comp: &P, + extract_body: &G, + compose_wrap: &H, + make_f: &F1, + f: &F, +) -> BodyForm +where + R: Clone, + L: Clone + 'a, + P: Fn(usize) -> BodyformPathArc, + F1: Fn(Vec, Option) -> BodyForm, + G: Fn(&'a L) -> &'a BodyForm, + H: Fn(&'a L, BodyForm) -> L, + F: Fn(&PathDetectVisitorResult, &BodyForm) -> BodyForm, +{ + let mut collection = vec![]; + let path_idx = current_path.len(); + let list_len = list_of.len(); + let mut replacement_list: Vec<(usize, &L)> = list_of.iter().enumerate().collect(); + let mut maybe_tail: Option = None; + if let Some(t) = tail_of.as_ref() { + replacement_list.push((list_len, t)); + } + for (i, a) in replacement_list.into_iter() { + current_path.push(make_path_comp(i)); + + // Continue only with potentially matching replacements. + let pass_on_replacements: Vec> = replacements + .iter() + .filter(|r| path_overlap(current_path, &r.path)) + .cloned() + .collect(); + + // No replacements down this argument. + if pass_on_replacements.is_empty() { + if i == list_len { + maybe_tail = Some(a.clone()); + } else { + collection.push(a.clone()); + } + current_path.truncate(path_idx); + continue; + } + + let wrapper = compose_wrap( + a, + replace_in_bodyform_subset(current_path, &pass_on_replacements, extract_body(a), f), + ); + if i == list_of.len() { + maybe_tail = Some(wrapper); + } else { + collection.push(wrapper); + } + + current_path.truncate(path_idx); + } + + make_f(collection, maybe_tail) +} + +fn replace_in_bodyform_inner_body( + current_path: &mut Vec, + replacements: &[PathDetectVisitorResult], + new_path_elt: BodyformPathArc, + outer_body: &BodyForm, + inner_body: &BodyForm, + make_f: &F1, + f: &F, +) -> BodyForm +where + R: Clone, + F1: Fn(BodyForm) -> BodyForm, + F: Fn(&PathDetectVisitorResult, &BodyForm) -> BodyForm, +{ + let path_idx = current_path.len(); + current_path.push(new_path_elt); + let pass_on_replacements: Vec> = replacements + .iter() + .filter(|r| path_overlap(current_path, &r.path)) + .cloned() + .collect(); + + if pass_on_replacements.is_empty() { + current_path.truncate(path_idx); + return outer_body.clone(); + } + + let new_binding_body = + replace_in_bodyform_subset(current_path, &pass_on_replacements, inner_body, f); + current_path.truncate(path_idx); + make_f(new_binding_body) +} + +/// For some partially matched subset of the replacement set at index idx in their +/// paths, do the child replacements. +fn replace_in_bodyform_subset( + current_path: &mut Vec, + replacements: &[PathDetectVisitorResult], + bf: &BodyForm, + f: &F, +) -> BodyForm +where + R: Clone, + F: Fn(&PathDetectVisitorResult, &BodyForm) -> BodyForm, +{ + // We already checked for overlaps, so there'll be only one if any. + let exact_match_replacements: Vec> = replacements + .iter() + .filter(|r| &r.path == current_path) + .cloned() + .collect(); + + if !exact_match_replacements.is_empty() { + // Return the object + return f(&exact_match_replacements[0], bf); + } + + match bf { + BodyForm::Call(l, args, tail) => replace_in_bodyform_inner_list( + current_path, + replacements, + args, + tail, + &BodyformPathArc::CallArgument, + &|e: &Rc| e.borrow(), + &|_w, b| Rc::new(b), + &|args, tail| BodyForm::Call(l.clone(), args, tail), + f, + ), + BodyForm::Let(k, b) => { + let path_idx = current_path.len(); + current_path.push(BodyformPathArc::BodyOf); + let pass_on_replacements: Vec> = replacements + .iter() + .filter(|r| path_overlap(current_path, &r.path)) + .cloned() + .collect(); + + let new_lambda_body = + replace_in_bodyform_subset(current_path, &pass_on_replacements, b.body.borrow(), f); + + current_path.truncate(path_idx); + + replace_in_bodyform_inner_list( + current_path, + replacements, + &b.bindings, + &None, + &BodyformPathArc::LetBinding, + &|e: &Rc| &e.body, + &|w: &Rc, b: BodyForm| { + let wb: &Binding = w.borrow(); + Rc::new(Binding { + body: Rc::new(b), + ..wb.clone() + }) + }, + &|bindings, _| { + BodyForm::Let( + k.clone(), + Box::new(LetData { + bindings, + body: Rc::new(new_lambda_body.clone()), + ..*b.clone() + }), + ) + }, + f, + ) + } + BodyForm::Lambda(l) => replace_in_bodyform_inner_body( + current_path, + replacements, + BodyformPathArc::BodyOf, + bf, + &l.body, + &|b| { + BodyForm::Lambda(Box::new(LambdaData { + body: Rc::new(b), + ..*l.clone() + })) + }, + f, + ), + BodyForm::Mod(l, m) => replace_in_bodyform_inner_body( + current_path, + replacements, + BodyformPathArc::BodyOf, + bf, + &m.exp, + &|b| { + BodyForm::Mod( + l.clone(), + CompileForm { + exp: Rc::new(b), + ..m.clone() + }, + ) + }, + f, + ), + _ => bf.clone(), + } +} + +/// Replace subexpressions in a bodyform given a set of PathDetectVisitorResult<_>. +pub fn replace_in_bodyform( + replacements: &[PathDetectVisitorResult], + bf: &BodyForm, + f: &F, +) -> Option +where + R: Clone, + F: Fn(&PathDetectVisitorResult, &BodyForm) -> BodyForm, +{ + if replacements.is_empty() { + return Some(bf.clone()); + } + + // We should not have any overlapping paths... if we do, that seems like a + // failure since a replacement would be lost. + for (i, p) in replacements.iter().enumerate() { + for q in replacements.iter().skip(i + 1) { + if path_overlap(&p.path, &q.path) { + return None; // An overlap + } + } + } + + let mut current_path = vec![]; + // There are no overlaps, start replacing + Some(replace_in_bodyform_subset( + &mut current_path, + replacements, + bf, + f, + )) +} + +/// Retrieve bodyform by path +pub fn retrieve_bodyform(path: &[BodyformPathArc], mut found: &BodyForm, f: &F) -> Option +where + F: Fn(&BodyForm) -> R, +{ + for p in path.iter() { + match p { + BodyformPathArc::LetBinding(n) => { + if let BodyForm::Let(_, l) = found { + if *n >= l.bindings.len() { + return None; + } + found = l.bindings[*n].body.borrow(); + } else { + return None; + } + } + BodyformPathArc::CallArgument(n) => { + if let BodyForm::Call(_, a, tail) = found { + match n.cmp(&a.len()) { + Ordering::Greater => { + return None; + } + Ordering::Equal => { + if let Some(t) = tail { + found = t.borrow(); + } else { + return None; + } + } + _ => { + found = a[*n].borrow(); + } + } + } else { + return None; + } + } + BodyformPathArc::BodyOf => match found { + BodyForm::Let(_, b) => { + found = b.body.borrow(); + } + BodyForm::Lambda(l) => { + found = l.body.borrow(); + } + BodyForm::Mod(_, m) => { + found = m.exp.borrow(); + } + _ => { + return None; + } + }, + } + } + + Some(f(found)) +} diff --git a/src/compiler/optimize/brief.rs b/src/compiler/optimize/brief.rs new file mode 100644 index 000000000..f8cac9a9d --- /dev/null +++ b/src/compiler/optimize/brief.rs @@ -0,0 +1,180 @@ +use num_bigint::ToBigInt; +use std::borrow::Borrow; +use std::rc::Rc; + +use crate::classic::clvm::__type_compatibility__::bi_one; +use crate::classic::clvm_tools::node_path::compose_paths; + +#[cfg(test)] +use crate::compiler::sexp::parse_sexp; +use crate::compiler::sexp::SExp; + +#[cfg(test)] +use crate::compiler::srcloc::Srcloc; + +fn is_quote_atom(a: &SExp) -> bool { + if let SExp::Atom(_, n) = a.atomize() { + return n.len() == 1 && n[0] == 1; + } + + false +} + +fn is_first_atom(a: &SExp) -> bool { + if let SExp::Atom(_, n) = a.atomize() { + return n.len() == 1 && n[0] == 5; + } + + false +} + +fn is_rest_atom(a: &SExp) -> bool { + if let SExp::Atom(_, n) = a.atomize() { + return n.len() == 1 && n[0] == 6; + } + + false +} + +// Collapse sequences of (f (r (f ... X))) representing (a P1 X) +// into (a P1 X) if X is not a path +// or P1 || X if X is a path +fn brief_path_selection_single(mut body: Rc) -> (bool, Rc) { + let orig_body = body.clone(); + let mut found_stack = 0; + let mut target_path = bi_one(); + + while let Some(lst) = body.proper_list() { + if let [cmd, arg] = &lst[..] { + if is_quote_atom(cmd) { + break; + } + + let is_first = is_first_atom(cmd); + if is_first || is_rest_atom(cmd) { + found_stack += 1; + target_path *= 2_u32.to_bigint().unwrap(); + if !is_first { + target_path += bi_one(); + } + body = Rc::new(arg.clone()); + continue; + } + } + + break; + } + + if found_stack > 0 { + let intval = if let SExp::Integer(_l, i) = body.borrow() { + Some(i.clone()) + } else { + None + }; + + if let Some(i) = intval { + // The number to the left is "closer to the root". + // These bits are selected first. + let final_path = compose_paths(&i, &target_path); + return (true, Rc::new(SExp::Integer(body.loc(), final_path))); + } + + /* + if found_stack > 2 { + let apply_atom = Rc::new(SExp::Atom(body.loc(), vec![2])); + let at_atom = Rc::new(SExp::Atom(body.loc(), vec![1])); + + return (true, Rc::new(SExp::Cons( + body.loc(), + apply_atom.clone(), + Rc::new(SExp::Cons( + body.loc(), + Rc::new(SExp::Cons( + body.loc(), + at_atom.clone(), + Rc::new(SExp::Integer(body.loc(), target_path)) + )), + Rc::new(SExp::Cons( + body.loc(), + Rc::new(SExp::Cons( + body.loc(), + apply_atom, + Rc::new(SExp::Cons( + body.loc(), + body.clone(), + Rc::new(SExp::Cons( + body.loc(), + at_atom.clone(), + Rc::new(SExp::Nil(body.loc())) + )) + )) + )), + Rc::new(SExp::Nil(body.loc())) + )) + )) + ))); + } + */ + } + + (false, orig_body) +} + +pub fn brief_path_selection(body: Rc) -> (bool, Rc) { + let (changed, new_body) = brief_path_selection_single(body.clone()); + if changed { + return (true, new_body); + } + + if let Some(lst) = body.proper_list() { + if lst.len() < 2 || is_quote_atom(&lst[0]) { + return (false, body); + } + + let mut end = Rc::new(SExp::Nil(body.loc())); + let mut updated = false; + for f in lst.iter().rev() { + let (mod_a, a) = brief_path_selection(Rc::new(f.clone())); + updated = updated || mod_a; + end = Rc::new(SExp::Cons(body.loc(), a, end)); + } + return (updated, end); + } + + (false, body) +} + +#[test] +fn test_brief_path_selection_none() { + let filename = "*test*"; + let loc = Srcloc::start(filename); + let parsed = parse_sexp(loc.clone(), "(2 (1 (1) (1) (1)) (3))".bytes()).expect("should parse"); + let (did_work, optimized) = brief_path_selection(parsed[0].clone()); + assert!(!did_work); + assert_eq!(optimized.to_string(), "(2 (1 (1) (1) (1)) (3))"); +} + +/* +#[test] +fn test_brief_path_selection_one_first_unknown_body() { + let filename = "*test*"; + let loc = Srcloc::start(filename); + let parsed = parse_sexp(loc.clone(), "(5 (5 (5 (+ 3 2))))".bytes()).expect("should parse"); + let (did_work, optimized) = brief_path_selection(parsed[0].clone()); + assert!(did_work); + assert_eq!(optimized.to_string(), "(2 8 (2 (+ 3 2) 1))"); +} +*/ + +#[test] +fn test_brief_path_selection_one_first_path_body_1() { + let filename = "*test*"; + let loc = Srcloc::start(filename); + let parsed = parse_sexp(loc.clone(), "(5 (5 (6 (5 11))))".bytes()).expect("should parse"); + let (did_work, optimized) = brief_path_selection(parsed[0].clone()); + assert!(did_work); + // f f r f -> path 18 (0100[1]) + // 11 -> (110[1]) + // Joined so that 11's path occupies the inner (low) bits: 1100100[1] + assert_eq!(optimized.to_string(), "147"); +} diff --git a/src/compiler/optimize/cse.rs b/src/compiler/optimize/cse.rs new file mode 100644 index 000000000..116dc1775 --- /dev/null +++ b/src/compiler/optimize/cse.rs @@ -0,0 +1,742 @@ +use std::borrow::Borrow; +use std::cmp::min; +use std::collections::{BTreeMap, HashSet}; +use std::rc::Rc; + +use crate::compiler::clvm::sha256tree; +use crate::compiler::comptypes::{ + Binding, BindingPattern, BodyForm, CompileErr, LambdaData, LetData, LetFormInlineHint, + LetFormKind, +}; +use crate::compiler::evaluate::{is_apply_atom, is_i_atom}; +use crate::compiler::gensym::gensym; +use crate::compiler::lambda::make_cons; +use crate::compiler::optimize::bodyform::{ + path_overlap_one_way, replace_in_bodyform, retrieve_bodyform, visit_detect_in_bodyform, + BodyformPathArc, PathDetectVisitorResult, +}; +use crate::compiler::sexp::{decode_string, SExp}; +use crate::compiler::srcloc::Srcloc; + +// Common subexpression elimintation. +// catalog subexpressions of the given bodyform and +#[derive(Debug, Clone)] +pub struct CSEInstance { + pub path: Vec, +} + +#[derive(Debug, Clone)] +pub struct CSEDetectionWithoutConditions { + pub hash: Vec, + pub subexp: BodyForm, + pub instances: Vec, +} + +#[derive(Debug, Clone)] +pub struct CSEDetection { + pub hash: Vec, + pub root: Vec, + pub saturated: bool, + pub subexp: BodyForm, + pub instances: Vec, +} + +#[derive(Debug, Clone)] +pub struct CSECondition { + pub path: Vec, + pub canonical: bool, +} + +// in a chain of conditions: +// +// (if a *b *c) // Can precompute. +// +// (if a *b (if c (if d *e *f) h)) // Can't precompute; might not be safe in h. +// +// The question we have to ask for each condition is: +// does every branch use the cse? +// +// If it is used in every branch of a condition, then it dominates that condition +// and it can be computed definitely above the condition. +// +// If it is missing from some downstream elements of a condition, then we must +// pass it on as a lambda that can be applied. +// +fn is_constant(bf: &BodyForm) -> bool { + matches!( + bf, + BodyForm::Value(SExp::Nil(_)) + | BodyForm::Value(SExp::Integer(_, _)) + | BodyForm::Value(SExp::QuotedString(_, _, _)) + | BodyForm::Quoted(_) + ) +} + +// A detection is fully dominated if every instance of it is used in the same +// other detection. +fn is_fully_dominated( + cse: &CSEDetectionWithoutConditions, + detections: &[CSEDetectionWithoutConditions], +) -> bool { + let mut host_set = HashSet::new(); + + for i in cse.instances.iter() { + for d in detections.iter() { + if d.hash == cse.hash { + continue; + } + for d_i in d.instances.iter() { + if path_overlap_one_way(&d_i.path, &i.path) { + host_set.insert(d.hash.clone()); + } + } + } + } + + // No overlaps means all uses are unique, otherwise it is fully dominated if + // if all uses are in the same host. If there are multiple hosts then it is + // not fully dominated since we can still deduplicate it among other hosts + // which are themselves going to be deduplicated. + host_set.len() == 1 +} + +pub fn cse_detect(fe: &BodyForm) -> Result, CompileErr> { + let found_exprs = visit_detect_in_bodyform( + &|path, _original, form| { + // The whole expression isn't a repeat. + if path.is_empty() { + return Ok(None); + } + + // Skip the function name of a call. + if path[path.len() - 1] == BodyformPathArc::CallArgument(0) { + return Ok(None); + } + + // Skip individual variable references. + if matches!(form, BodyForm::Value(SExp::Atom(_, _))) { + return Ok(None); + } + + // We can't take a com directly, but we can take parents or children. + if get_com_body(form).is_some() { + return Ok(None); + } + + // Skip cheap constants. + if is_constant(form) { + return Ok(None); + } + + let hash_of = sha256tree(form.to_sexp()); + let res: Result>, CompileErr> = Ok(Some(hash_of)); + res + }, + fe, + )?; + + // Group them by hash since we've renamed variables. + let mut by_hash: BTreeMap, Vec>>> = BTreeMap::new(); + for expr in found_exprs.iter() { + if let Some(lst) = by_hash.get_mut(&expr.context) { + lst.push(expr.clone()); + } else { + by_hash.insert(expr.context.clone(), vec![expr.clone()]); + } + } + + let detections: Vec = by_hash + .into_iter() + .filter_map(|(k, v)| { + if v.len() < 2 { + return None; + } + + let subexp = v[0].subexp.clone(); + + let instances = v + .into_iter() + .map(|item| CSEInstance { path: item.path }) + .collect(); + + Some(CSEDetectionWithoutConditions { + hash: k, + subexp, + instances, + }) + }) + .collect(); + + let useful_detections = detections + .iter() + .filter(|d| !is_fully_dominated(d, &detections)) + .cloned() + .collect(); + + Ok(useful_detections) +} + +// Number of other CSE detections this one depends on. +// We can't apply it until the ones it depends on are applied. +fn number_of_overlaps(detections: &[CSEDetection], cse: &CSEDetection) -> usize { + cse.instances + .iter() + .map(|i: &CSEInstance| { + detections + .iter() + .filter(|d| d.hash != cse.hash) + .map(|d| { + d.instances + .iter() + .filter(|j: &&CSEInstance| path_overlap_one_way(&i.path, &j.path)) + .count() + }) + .sum::() + }) + .sum() +} + +fn sorted_cse_detections_by_applicability( + cse_detections: &[CSEDetection], +) -> Vec<(usize, CSEDetection)> { + let mut detections_with_dependencies: Vec<(usize, CSEDetection)> = cse_detections + .iter() + .map(|a| (number_of_overlaps(cse_detections, a), a.clone())) + .collect(); + detections_with_dependencies.sort_by(|(a, _), (b, _)| a.cmp(b)); + detections_with_dependencies +} + +fn is_one_env_ref(bf: &BodyForm) -> bool { + bf.to_sexp() == Rc::new(SExp::Atom(bf.loc(), vec![1])) + || bf.to_sexp() == Rc::new(SExp::Atom(bf.loc(), vec![b'@'])) + || bf.to_sexp() == Rc::new(SExp::Atom(bf.loc(), b"@*env*".to_vec())) +} + +pub fn is_canonical_apply_parent( + p: &[BodyformPathArc], + root: &BodyForm, +) -> Result { + if p.is_empty() { + return Ok(false); + } + + let last_idx = p.len() - 1; + if p[last_idx] != BodyformPathArc::CallArgument(1) { + return Ok(false); // Not the right position in the parent. + } + + let path_to_parent: Vec = p.iter().take(last_idx).cloned().collect(); + let parent_exp = + if let Some(parent) = retrieve_bodyform(&path_to_parent, root, &|bf| bf.clone()) { + parent + } else { + return Err(CompileErr( + root.loc(), + format!( + "Impossible: could not retrieve parent of existing expression (root {})", + root.to_sexp() + ), + )); + }; + + // Checking for a primitive, so no tail. + if let BodyForm::Call(_, parts, None) = &parent_exp { + if parts.len() != 3 { + return Ok(false); + } + + if !is_apply_atom(parts[0].to_sexp()) { + return Ok(false); + } + + Ok(is_one_env_ref(&parts[2])) + } else { + Ok(false) + } +} + +fn get_com_body(bf: &BodyForm) -> Option<&BodyForm> { + // Checking for com so no tail. + if let BodyForm::Call(_, parts, None) = bf { + if parts.len() != 2 { + return None; + } + + if parts[0].to_sexp() != Rc::new(SExp::Atom(bf.loc(), b"com".to_vec())) { + return None; + } + + return Some(&parts[1]); + } + + None +} + +// Detect uses of the 'i' operator in chialisp code. +// When written (a (i x (com A) (com B)) 1) +// it is canonical. +pub fn detect_conditions(bf: &BodyForm) -> Result, CompileErr> { + let found_conditions = visit_detect_in_bodyform( + &|path, root, form| -> Result, CompileErr> { + // Must have (a ... 1) surrounding it to be canonical. + if !is_canonical_apply_parent(path, root)? { + return Ok(None); + } + + // Checking for a primitive so no tail. + if let BodyForm::Call(_, parts, None) = form { + if parts.len() != 4 { + return Ok(None); + } + + if !is_i_atom(parts[0].to_sexp()) { + return Ok(None); + } + + // We're expecting (com A) and (com B) for the last two + // arguments. + // XXX also recognize a tree of (i ...) forms whose leaves + // are all (com X). + let a_body = get_com_body(parts[2].borrow()); + let b_body = get_com_body(parts[3].borrow()); + if let (Some(_), Some(_)) = (a_body, b_body) { + return Ok(Some(true)); + } + + // It is a proper conditional expression, but not in the + // canonical form. + return Ok(Some(false)); + } + + Ok(None) + }, + bf, + )?; + + let results = found_conditions + .into_iter() + .map(|f| CSECondition { + path: f.path, + canonical: f.context, + }) + .collect(); + + Ok(results) +} + +// True if for some condition path c_path there are matching instance paths +// for either c_path + [CallArgument(1)] or both +// c_path + [CallArgument(2)] and c_path + [CallArgument(3)] +fn cse_is_covering(c_path: &[BodyformPathArc], instances: &[CSEInstance]) -> bool { + let mut target_paths = [c_path.to_vec(), c_path.to_vec(), c_path.to_vec()]; + target_paths[0].push(BodyformPathArc::CallArgument(1)); + target_paths[1].push(BodyformPathArc::CallArgument(2)); + target_paths[2].push(BodyformPathArc::CallArgument(3)); + + let have_targets: Vec = target_paths + .iter() + .map(|t| instances.iter().any(|i| path_overlap_one_way(t, &i.path))) + .collect(); + + have_targets[0] || (have_targets[1] && have_targets[2]) +} + +pub fn cse_classify_by_conditions( + conditions: &[CSECondition], + detections: &[CSEDetectionWithoutConditions], +) -> Vec { + detections + .iter() + .filter_map(|d| { + // Detect the common root of all instances. + if d.instances.is_empty() { + return None; + } + + let mut path_limit = 0; + let possible_root = d.instances[0].path.clone(); + for i in d.instances.iter().skip(1) { + path_limit = min(path_limit, i.path.len()); + for (idx, item) in possible_root.iter().take(path_limit).enumerate() { + if &i.path[idx] != item { + path_limit = idx; + break; + } + } + } + + // path_limit points to the common root of all instances of this + // cse detection. + // + // now find conditions that are downstream of the cse root. + let applicable_conditions: Vec = conditions + .iter() + .filter(|c| path_overlap_one_way(&c.path, &possible_root)) + .cloned() + .collect(); + + // We don't need to delay the CSE if 1) all conditions below it + // are canonical and 2) it appears downstream of all conditions + // it encloses. + let fully_canonical = applicable_conditions + .iter() + .all(|c| c.canonical && cse_is_covering(&c.path, &d.instances)); + + Some(CSEDetection { + hash: d.hash.clone(), + subexp: d.subexp.clone(), + instances: d.instances.clone(), + saturated: fully_canonical, + root: possible_root, + }) + }) + .collect() +} + +fn detect_common_cse_root(instances: &[CSEInstance]) -> Vec { + // No instances, we can choose the root. + let min_size = if let Some(m) = instances.iter().map(|i| i.path.len()).min() { + m + } else { + return Vec::new(); + }; + + let mut target_path = instances[0].path.clone(); + let mut last_match = min_size; + for idx in 0..min_size { + for i in instances.iter() { + if i.path[idx] != instances[0].path[idx] { + // If we don't match here, then the common root is up to here. + last_match = last_match.min(idx); + target_path = instances[0].path.iter().take(last_match).cloned().collect(); + break; + } + } + } + + // Back it up to the body of a let binding. + for (idx, f) in target_path.iter().enumerate().rev() { + if f == &BodyformPathArc::BodyOf { + return target_path.iter().take(idx + 1).cloned().collect(); + } + } + + // No internal root if there was no let traversal. + Vec::new() +} + +// Finds lambdas that contain CSE detection instances from the provided list. +fn find_affected_lambdas( + instances: &[CSEInstance], + common_root: &[BodyformPathArc], + bf: &BodyForm, +) -> Result>, CompileErr> { + visit_detect_in_bodyform( + &|path, _root, form| -> Result, CompileErr> { + // The common root is inside this lambda. + if path_overlap_one_way(path, common_root) { + return Ok(None); + } + if let BodyForm::Lambda(_) = form { + if instances + .iter() + .any(|i| path_overlap_one_way(path, &i.path)) + { + return Ok(Some(())); + } + } + + Ok(None) + }, + bf, + ) +} + +// Adds a new variable on the left of the lambda captures. +// "x" + (lambda ((& a b) z) ...) -> (lambda ((& x a b) z) ...) +fn add_variable_to_lambda_capture(vn: &[u8], bf: &BodyForm) -> BodyForm { + let new_var_sexp = SExp::Atom(bf.loc(), vn.to_vec()); + if let BodyForm::Lambda(ldata) = bf { + let ldata_borrowed: &LambdaData = ldata.borrow(); + let new_captures = Rc::new(make_cons( + bf.loc(), + Rc::new(BodyForm::Value(new_var_sexp.clone())), + ldata.captures.clone(), + )); + BodyForm::Lambda(Box::new(LambdaData { + capture_args: Rc::new(SExp::Cons( + bf.loc(), + Rc::new(new_var_sexp), + ldata.capture_args.clone(), + )), + captures: new_captures, + ..ldata_borrowed.clone() + })) + } else { + bf.clone() + } +} + +#[derive(Clone, Debug)] +struct CSEBindingSite { + target_path: Vec, + binding: Binding, +} + +#[derive(Default, Debug)] +struct CSEBindingInfo { + info: BTreeMap, Vec>, +} + +impl CSEBindingInfo { + fn push(&mut self, site: CSEBindingSite) { + if let Some(reference) = self.info.get_mut(&site.target_path) { + reference.push(site.clone()); + } else { + self.info.insert(site.target_path.clone(), vec![site]); + } + } +} + +type CSEReplacementTargetAndBindings<'a> = Vec<&'a (Vec, Vec>)>; + +pub fn cse_optimize_bodyform( + loc: &Srcloc, + name: &[u8], + b: &BodyForm, +) -> Result { + let conditions = detect_conditions(b)?; + let cse_raw_detections = cse_detect(b)?; + + let cse_detections = cse_classify_by_conditions(&conditions, &cse_raw_detections); + + // While we have them, apply any detections that overlap no others. + let mut detections_with_dependencies: Vec<(usize, CSEDetection)> = + sorted_cse_detections_by_applicability(&cse_detections); + + let mut function_body = b.clone(); + let mut new_binding_stack: Vec<(Vec, Vec>)> = Vec::new(); + + while !detections_with_dependencies.is_empty() { + let detections_to_apply: Vec = detections_with_dependencies + .iter() + .take_while(|(c, _d)| *c == 0) + .map(|(_c, d)| d.clone()) + .collect(); + let keep_detections: Vec = detections_with_dependencies + .iter() + .skip_while(|(c, _d)| *c == 0) + .map(|(_c, d)| d.clone()) + .collect(); + + // It's an error if applications are deadlocked. + // I don't think it's possible but this will prevent infinite + // looping. + if detections_to_apply.is_empty() && !keep_detections.is_empty() { + return Err(CompileErr( + loc.clone(), + format!("CSE optimization failed in helper {}", decode_string(name)), + )); + } + + let mut binding_set: CSEBindingInfo = Default::default(); + + for d in detections_to_apply.iter() { + // If for some reason there are none to apply, we can + // skip it. That should not be possible. + if d.instances.is_empty() { + break; + } + + // Skip unsaturated conditional CSE clauses at the moment. + // This is improvable in the future. + if !d.saturated { + continue; + } + + // All detections should have been transformed equally. + // Therefore, we can pick one out and use its form. + // + // These might have changed from when they were detected + // because other common subexpressions were substuted. + let prototype_instance = if let Some(r) = + retrieve_bodyform(&d.instances[0].path, &function_body, &|b: &BodyForm| { + b.clone() + }) { + r + } else { + return Err(CompileErr( + loc.clone(), + format!( + "CSE Error in {}: could not find form to replace for path {:?}", + decode_string(name), + d.instances[0].path + ), + )); + }; + + // We'll assign a fresh variable for each of the detections + // that are applicable now. + let new_variable_name = gensym(b"cse".to_vec()); + let new_variable_bf_alone = BodyForm::Value(SExp::Atom( + prototype_instance.loc(), + new_variable_name.clone(), + )); + + let new_variable_bf = new_variable_bf_alone; + + let replacement_spec: Vec> = d + .instances + .iter() + .map(|i| PathDetectVisitorResult { + path: i.path.clone(), + subexp: new_variable_bf.clone(), + context: (), + }) + .collect(); + + // Detect the root of the CSE as the innermost expression that covers + // all uses. + let replace_path = detect_common_cse_root(&d.instances); + + // Route the captured repeated subexpression into intervening lambdas. + // This means that the lambdas will gain a capture on the left side of + // their captures. + // + // Ensure that lambdas above replace_path aren't targeted. + let affected_lambdas = find_affected_lambdas(&d.instances, &replace_path, b)?; + if let Some(res) = replace_in_bodyform( + &affected_lambdas, + &function_body, + &|_v: &PathDetectVisitorResult<()>, b| { + add_variable_to_lambda_capture(&new_variable_name, b) + }, + ) { + function_body = res; + } else { + return Err(CompileErr( + loc.clone(), + "error forwarding cse capture into lambda, which should work".to_string(), + )); + } + + if let Some(res) = replace_in_bodyform( + &replacement_spec, + &function_body, + &|v: &PathDetectVisitorResult<()>, _b| v.subexp.clone(), + ) { + function_body = res; + } else { + return Err(CompileErr( + loc.clone(), + format!( + "cse replacement failed in helper {}, which shouldn't be possible", + decode_string(name) + ), + )); + } + + // Put aside the definition in this binding set. + let name_atom = SExp::Atom(prototype_instance.loc(), new_variable_name.clone()); + binding_set.push(CSEBindingSite { + target_path: replace_path, + binding: Binding { + loc: prototype_instance.loc(), + nl: prototype_instance.loc(), + pattern: BindingPattern::Complex(Rc::new(name_atom)), + body: Rc::new(prototype_instance), + }, + }); + } + + detections_with_dependencies = sorted_cse_detections_by_applicability(&keep_detections); + + new_binding_stack.append( + &mut binding_set + .info + .iter() + .rev() + .map(|(target_path, sites)| { + let bindings: Vec> = sites + .iter() + .map(|site| Rc::new(site.binding.clone())) + .collect(); + (target_path.clone(), bindings) + }) + .collect(), + ); + } + + // We might not have completely sorted sites anymore due to joining up each + // site set under a common target path (which themselves need sorting). + if new_binding_stack.is_empty() { + return Ok(function_body); + } + + // We need to topologically sort the CSE insertions by dominance otherwise + // The inserted let bindings farther up the tree will disrupt lower down + // replacements. + // + // Sort the target paths so we put in deeper paths before outer ones. + let mut sorted_bindings: Vec<(Vec, Vec>)> = Vec::new(); + + // We'll do this by finding bindings that are not dominated and processing + // them last. + while !new_binding_stack.is_empty() { + let (still_dominated, not_dominated): ( + CSEReplacementTargetAndBindings<'_>, + CSEReplacementTargetAndBindings<'_>, + ) = new_binding_stack.iter().partition(|(t, _)| { + new_binding_stack.iter().any(|(t_other, _)| { + // t is dominated if t_other contains it. + t_other != t && path_overlap_one_way(t_other, t) + }) + }); + let mut not_dominated_vec: Vec<(Vec, Vec>)> = + not_dominated.into_iter().cloned().collect(); + sorted_bindings.append(&mut not_dominated_vec); + let still_dominated_vec: Vec<(Vec, Vec>)> = + still_dominated.into_iter().cloned().collect(); + new_binding_stack = still_dominated_vec; + } + + // All CSE replacements are done. We unwind the new bindings + // into a stack of parallel let forms. + for (target_path, binding_list) in sorted_bindings.into_iter().rev() { + let replacement_spec = &[PathDetectVisitorResult { + path: target_path.clone(), + subexp: function_body.clone(), + context: (), + }]; + if let Some(res) = replace_in_bodyform( + replacement_spec, + &function_body, + &|_v: &PathDetectVisitorResult<()>, b| { + BodyForm::Let( + LetFormKind::Parallel, + Box::new(LetData { + loc: function_body.loc(), + kw: None, + inline_hint: Some(LetFormInlineHint::NonInline(loc.clone())), + bindings: binding_list.clone(), + body: Rc::new(b.clone()), + }), + ) + }, + ) { + assert!(res.to_sexp() != function_body.to_sexp()); + function_body = res; + } else { + return Err(CompileErr( + function_body.loc(), + format!( + "Could not find the target to replace for path {target_path:?} in {}", + b.to_sexp() + ), + )); + } + } + + Ok(function_body) +} diff --git a/src/compiler/optimize/deinline.rs b/src/compiler/optimize/deinline.rs new file mode 100644 index 000000000..5b1b9b86c --- /dev/null +++ b/src/compiler/optimize/deinline.rs @@ -0,0 +1,225 @@ +use std::collections::{BTreeSet, HashMap, HashSet}; +use std::rc::Rc; + +use crate::compiler::codegen::codegen; +use crate::compiler::optimize::depgraph::{DepgraphKind, FunctionDependencyGraph}; +use crate::compiler::optimize::{sexp_scale, SyntheticType}; +use crate::compiler::{BasicCompileContext, CompileErr, CompileForm, CompilerOpts, HelperForm}; + +// Find the roots for the given function. +fn find_roots( + visited: &mut HashSet>, + root_set: &mut BTreeSet>, + depgraph: &FunctionDependencyGraph, + function: &[u8], +) { + if visited.contains(function) { + return; + } + + visited.insert(function.to_vec()); + + // If it's non-inline, it's a root. + if let Some(f) = depgraph.helpers.get(function) { + if matches!(f.status, DepgraphKind::UserNonInline) { + root_set.insert(function.to_vec()); + return; + } + } + + if let Some(parents) = depgraph.parents(function) { + for p in parents.iter() { + find_roots(visited, root_set, depgraph, p); + } + } +} + +// Should take a desugared program. +pub fn deinline_opt( + context: &mut BasicCompileContext, + opts: Rc, + mut compileform: CompileForm, +) -> Result { + // Short circuit return: no helpers. + if compileform.helpers.is_empty() { + return Ok(compileform); + } + + let depgraph = FunctionDependencyGraph::new(&compileform); + + let mut best_compileform = compileform.clone(); + let generated_program = codegen(context, opts.clone(), &best_compileform)?; + let mut metric = sexp_scale(&generated_program); + let flip_helper = |h: &mut HelperForm| { + if let HelperForm::Defun(inline, defun) = h { + if matches!(&defun.synthetic, Some(SyntheticType::NoInlinePreference)) { + *h = HelperForm::Defun(!*inline, defun.clone()); + return true; + } + } + + false + }; + + let helper_to_index: HashMap, usize> = compileform + .helpers + .iter() + .enumerate() + .map(|(i, h)| (h.name().to_vec(), i)) + .collect(); + + // defun F -> Synthetic letbinding_$_1 + // Synthetic letbinding_$_2 -> Synthetic letbinding_$_3 + // + // defun H_inline -> + // Synthetic letbinding_$_4 -> Synthetic letbinding_$_5 + // Synthetic letbinding_$_6 + // + // defun G -> Synthetic letbinding_$_7 -> H_inline + // + // - Synthetic Roots - + // + // letbinding_$_1, letbinding_$_2, letbinding_$_7 + // letbinding_$_4 is not a root, because it's in H_inline, called from G. + // + // So for each synthetic function, we traverse functions that depend on + // it as long as it's a synthetic function or a non-synthetic inline. + // The functions we reach are the roots. + // + // If any two roots share dependencies, they must be merged. + // + // So we take the set of each root and every synthetic function reachable + // from it and for each of those sets, we do the normal optimizataion loop. + + // Find leaf synthetic functions by first finding leaf functions, then + // until we find a synthetic function, go up to each depended_on_by function + // until we reach a root. + // + // Remember the root this function belongs to. + let leaves: Vec> = depgraph + .leaves() + .iter() + .filter(|l| { + depgraph + .helpers + .get(&l.to_vec()) + .map(|l| !matches!(l.status, DepgraphKind::UserNonInline)) + .unwrap_or(false) + }) + .cloned() + .collect(); + + let mut roots: HashMap, BTreeSet>> = HashMap::new(); + + // For each leaf, find roots. + for l in leaves.iter() { + let mut visited = HashSet::new(); + let mut leaf_roots = BTreeSet::new(); + find_roots(&mut visited, &mut leaf_roots, &depgraph, l); + if leaf_roots.is_empty() { + leaf_roots.insert(l.to_vec()); + } + roots.insert(l.to_vec(), leaf_roots); + } + + // Make a set of root sets to coalesce them. + let mut roots_set: HashSet>> = HashSet::new(); + for (_, common_roots) in roots.iter() { + roots_set.insert(common_roots.clone()); + } + + // roots is a map from leaf inline to root container. We can use the roots_set + // with this collection to make a set of leaves reachable from each root set. + // Each root set is a set of functions that will change representation when + // inlining is changed so we have to handle each root set as a unit. + let mut root_set_to_leaf: HashMap>, BTreeSet>> = roots_set + .iter() + .map(|root_set| (root_set.clone(), BTreeSet::new())) + .collect(); + + for l in leaves.iter() { + let root = if let Some(root) = roots.get(l) { + root.clone() + } else { + return Err(CompileErr( + compileform.loc.clone(), + "Error in deinline, depgraph gave a leaf that didn't yield a root".to_string(), + )); + }; + + let from_root_set: Vec>> = roots_set + .iter() + .filter(|r| { + let intersection_of_roots: HashSet> = + r.intersection(&root).cloned().collect(); + !intersection_of_roots.is_empty() + }) + .cloned() + .collect(); + + for root_set in from_root_set.iter() { + if let Some(leaf_set) = root_set_to_leaf.get_mut(root_set) { + leaf_set.insert(l.to_vec()); + } + } + } + + // Now collect the tree of synthetic functions rooted at any of the roots in + // each root set. + let root_set_to_inline_tree: HashMap>, HashSet>> = root_set_to_leaf + .iter() + .map(|(root_set, leaves)| { + let mut full_tree_set = HashSet::new(); + for root in root_set.iter() { + let mut full_tree = HashSet::new(); + depgraph.get_full_depends_on(&mut full_tree, root); + full_tree_set = full_tree.union(&full_tree_set).cloned().collect(); + } + if full_tree_set.is_empty() { + full_tree_set = leaves.iter().cloned().collect(); + } + (root_set.clone(), full_tree_set) + }) + .collect(); + + for (_, function_set) in root_set_to_inline_tree.iter() { + loop { + let start_metric = metric; + + for f in function_set.iter() { + // Get index of helper identified by this leaf name. + let i = if let Some(i) = helper_to_index.get(f) { + *i + } else { + return Err(CompileErr( + compileform.loc.clone(), + "We have a helper name that has no index?".to_string(), + )); + }; + + // Try flipped. + let old_helper = compileform.helpers[i].clone(); + if !flip_helper(&mut compileform.helpers[i]) { + continue; + } + + let maybe_smaller_program = codegen(context, opts.clone(), &compileform)?; + let new_metric = sexp_scale(&maybe_smaller_program); + + // Don't keep this change if it made things worse. + if new_metric >= metric { + compileform.helpers[i] = old_helper; + } else { + metric = new_metric; + best_compileform = compileform.clone(); + } + } + + if start_metric == metric { + break; + } + } + } + + Ok(best_compileform) +} diff --git a/src/compiler/optimize/depgraph.rs b/src/compiler/optimize/depgraph.rs new file mode 100644 index 000000000..b99256849 --- /dev/null +++ b/src/compiler/optimize/depgraph.rs @@ -0,0 +1,212 @@ +use std::borrow::Borrow; +use std::collections::{HashMap, HashSet}; +use std::rc::Rc; + +use crate::compiler::optimize::SyntheticType; +use crate::compiler::sexp::enlist; +use crate::compiler::srcloc::Srcloc; +use crate::compiler::{BodyForm, CompileForm, DefunData, HelperForm, SExp}; + +#[derive(Debug)] +pub enum DepgraphKind { + UserNonInline, + UserInline, + Synthetic(SyntheticType), +} + +pub struct FunctionDependencyEntry { + pub loc: Srcloc, + pub name: Vec, + pub status: DepgraphKind, + pub depends_on: HashSet>, + pub is_depended_on_by: HashSet>, +} + +impl FunctionDependencyEntry { + pub fn to_sexp(&self) -> Rc { + let depends_on: Vec> = self + .depends_on + .iter() + .map(|x| Rc::new(SExp::Atom(self.loc.clone(), x.clone()))) + .collect(); + + let is_depended_on_by: Vec> = self + .is_depended_on_by + .iter() + .map(|x| Rc::new(SExp::Atom(self.loc.clone(), x.clone()))) + .collect(); + + Rc::new(enlist( + self.loc.clone(), + &[ + Rc::new(SExp::Atom(self.loc.clone(), self.name.clone())), + Rc::new(SExp::Atom( + self.loc.clone(), + format!("{:?}", self.status).as_bytes().to_vec(), + )), + Rc::new(SExp::Atom( + self.loc.clone(), + "depends_on".as_bytes().to_vec(), + )), + Rc::new(enlist(self.loc.clone(), &depends_on)), + Rc::new(SExp::Atom( + self.loc.clone(), + "is_depended_on_by".as_bytes().to_vec(), + )), + Rc::new(enlist(self.loc.clone(), &is_depended_on_by)), + ], + )) + } + + pub fn new(name: &[u8], loc: Srcloc, status: DepgraphKind) -> Self { + FunctionDependencyEntry { + loc, + name: name.to_vec(), + status, + depends_on: HashSet::default(), + is_depended_on_by: HashSet::default(), + } + } +} + +pub struct FunctionDependencyGraph { + pub loc: Srcloc, + pub helpers: HashMap, FunctionDependencyEntry>, +} + +fn status_from_defun(inline: bool, defun: &DefunData) -> DepgraphKind { + match (inline, defun.synthetic.as_ref()) { + (true, None) => DepgraphKind::UserInline, + (false, None) => DepgraphKind::UserNonInline, + (_, Some(st)) => DepgraphKind::Synthetic(st.clone()), + } +} + +impl FunctionDependencyGraph { + /// Find leaf functions. + pub fn leaves(&self) -> HashSet> { + self.helpers + .iter() + .filter(|(_k, h)| h.depends_on.is_empty()) + .map(|(k, _h)| k.clone()) + .collect() + } + + pub fn parents(&self, helper: &[u8]) -> Option>> { + self.helpers.get(helper).map(|h| { + let mut result_set = h.is_depended_on_by.clone(); + result_set.remove(helper); + result_set + }) + } + + pub fn get_full_depended_on_by( + &self, + depended_on_by: &mut HashSet>, + helper_name: &[u8], + ) { + if let Some(helper) = self.helpers.get(helper_name) { + for d in helper.is_depended_on_by.iter() { + if !depended_on_by.contains(d) { + depended_on_by.insert(d.to_vec()); + self.get_full_depended_on_by(depended_on_by, d); + } + } + } + } + + pub fn get_full_depends_on(&self, depends_on_fun: &mut HashSet>, helper_name: &[u8]) { + if let Some(helper) = self.helpers.get(helper_name) { + for d in helper.depends_on.iter() { + if !depends_on_fun.contains(d) { + depends_on_fun.insert(d.clone()); + self.get_full_depends_on(depends_on_fun, d); + } + } + } + } + + fn add_depends_on_relationship(&mut self, helper_name: &[u8], name: &[u8]) { + if !self.helpers.contains_key(helper_name) || !self.helpers.contains_key(name) { + return; + } + + if let Some(function_entry) = self.helpers.get_mut(helper_name) { + function_entry.depends_on.insert(name.to_vec()); + } + + if let Some(function_entry) = self.helpers.get_mut(name) { + function_entry + .is_depended_on_by + .insert(helper_name.to_vec()); + } + } + + fn process_expr(&mut self, helper_name: &[u8], expr: Rc) { + match expr.borrow() { + BodyForm::Value(SExp::Atom(_, name)) => { + // This introduces a function dependency. + self.add_depends_on_relationship(helper_name, name); + } + BodyForm::Value(_) => {} + BodyForm::Let(_, letdata) => { + for b in letdata.bindings.iter() { + self.process_expr(helper_name, b.body.clone()); + } + + self.process_expr(helper_name, letdata.body.clone()); + } + BodyForm::Call(_, args, tail) => { + if let Some(t) = tail.as_ref() { + self.process_expr(helper_name, t.clone()); + } + + for a in args.iter() { + self.process_expr(helper_name, a.clone()); + } + } + BodyForm::Lambda(ldata) => { + self.process_expr(helper_name, ldata.captures.clone()); + self.process_expr(helper_name, ldata.body.clone()); + } + BodyForm::Quoted(_) => {} + BodyForm::Mod(_, _) => {} + } + } + + fn process_helper(&mut self, h: &HelperForm) { + if let HelperForm::Defun(_, defun) = h { + self.process_expr(&defun.name, defun.body.clone()); + } + } + + pub fn new(program: &CompileForm) -> Self { + let mut helpers: HashMap, FunctionDependencyEntry> = HashMap::new(); + + for h in program.helpers.iter() { + if let HelperForm::Defun(inline, d) = h { + helpers.insert( + h.name().to_vec(), + FunctionDependencyEntry::new(h.name(), h.loc(), status_from_defun(*inline, d)), + ); + } + } + + let mut graph = FunctionDependencyGraph { + loc: program.loc.clone(), + helpers, + }; + + for h in program.helpers.iter() { + graph.process_helper(h); + } + + graph + } + + pub fn to_sexp(&self) -> Rc { + let helpers: Vec> = self.helpers.values().map(|v| v.to_sexp()).collect(); + + Rc::new(enlist(self.loc.clone(), &helpers)) + } +} diff --git a/src/compiler/optimize/double_apply.rs b/src/compiler/optimize/double_apply.rs new file mode 100644 index 000000000..9beb70942 --- /dev/null +++ b/src/compiler/optimize/double_apply.rs @@ -0,0 +1,158 @@ +use crate::compiler::clvm::truthy; +use crate::compiler::prims::primquote; +use crate::compiler::sexp::{AtomValue, NodeSel, SExp, SelectNode, ThisNode}; +use std::borrow::Borrow; +use std::rc::Rc; + +// Turn: +// +// (a (q any) 1) +// +// into +// +// any +// +// I now realize this is exactly cons_q_a_optimizer from classic :-) +pub fn change_double_to_single_apply(sexp: Rc) -> (bool, Rc) { + if let Ok(NodeSel::Cons( + _, + NodeSel::Cons( + NodeSel::Cons( + // quoted program + _, + inner_program, + ), + NodeSel::Cons(_, _), + ), + )) = NodeSel::Cons( + AtomValue::Here(&[2]), + NodeSel::Cons( + NodeSel::Cons( + // quoted program + AtomValue::Here(&[1]), + ThisNode, + ), + NodeSel::Cons(AtomValue::Here(&[1]), ThisNode), + ), + ) + .select_nodes(sexp.clone()) + { + return (true, inner_program); + } + + (false, sexp) +} + +fn change_apply_double_quote(sexp: Rc) -> (bool, Rc) { + if let Ok(NodeSel::Cons( + _, // apply + NodeSel::Cons( + NodeSel::Cons( + _, // q + NodeSel::Cons( + _, // 1 + body, + ), + ), + _, + ), + )) = NodeSel::Cons( + AtomValue::Here(&[2]), + NodeSel::Cons( + NodeSel::Cons( + AtomValue::Here(&[1]), + NodeSel::Cons(AtomValue::Here(&[1]), ThisNode), + ), + ThisNode, + ), + ) + .select_nodes(sexp.clone()) + { + return (true, Rc::new(primquote(body.loc(), body.clone()))); + } + + (false, sexp) +} + +fn collapse_constant_condition(sexp: Rc) -> (bool, Rc) { + if let Ok(NodeSel::Cons( + _, // i + NodeSel::Cons(cond, NodeSel::Cons(a, NodeSel::Cons(b, _))), + )) = NodeSel::Cons( + AtomValue::Here(&[3]), + NodeSel::Cons( + ThisNode, + NodeSel::Cons(ThisNode, NodeSel::Cons(ThisNode, ThisNode)), + ), + ) + .select_nodes(sexp.clone()) + { + // There are two cases here we care about: + // Either cond is () or it's (1 . something) + // The following filters away a non-const condition and leaves + // the remaining as either Some(true) or Some(false), then + // chooses a wing based on that. + return NodeSel::Cons(AtomValue::Here(&[1]), ThisNode) + .select_nodes(cond.clone()) + .ok() + .map(|NodeSel::Cons(_, cond_quoted)| Some(truthy(cond_quoted))) + .unwrap_or_else(|| if !truthy(cond) { Some(false) } else { None }) + .map(|use_cond| if use_cond { (true, a) } else { (true, b) }) + .unwrap_or_else(|| (false, sexp)); + } + + (false, sexp) +} + +// Recognize some optimizations: +// +// specific: (a (q 1 . x) _) => (q . x) +// classic optimizer: (a (op SEXP) ENV) => (op (a SEXP ENV)) <- wip +// classic optimizer: (a (q SEXP) 1) => SEXP +pub fn remove_double_apply(mut sexp: Rc, spine: bool) -> (bool, Rc) { + // Don't descend into quoted expressions. + if spine { + if let Ok(NodeSel::Cons(_, _)) = + NodeSel::Cons(AtomValue::Here(&[1]), ThisNode).select_nodes(sexp.clone()) + { + return (false, sexp); + } + } + + let mut any_transformation = true; + let mut was_transformed = false; + + while any_transformation { + if let SExp::Cons(l, a, b) = sexp.borrow() { + // These transformations play on each other but finalize together. + let (a_changed, new_a) = remove_double_apply(a.clone(), true); + let (b_changed, new_b) = remove_double_apply(b.clone(), false); + + let result = Rc::new(SExp::Cons(l.clone(), new_a, new_b)); + if spine { + let (root_transformed_dq, result_dq) = change_apply_double_quote(result); + let (root_transformed_unapply, result_single_apply) = + change_double_to_single_apply(result_dq); + + let (constant_collapse, result_end) = + collapse_constant_condition(result_single_apply); + + any_transformation = a_changed + || b_changed + || root_transformed_dq + || root_transformed_unapply + || constant_collapse; + was_transformed |= any_transformation; + sexp = result_end; + } else { + any_transformation = a_changed || b_changed; + was_transformed |= any_transformation; + sexp = result; + } + } else { + break; + } + } + + (was_transformed, sexp) +} diff --git a/src/compiler/optimize/mod.rs b/src/compiler/optimize/mod.rs new file mode 100644 index 000000000..b50bdcb12 --- /dev/null +++ b/src/compiler/optimize/mod.rs @@ -0,0 +1,731 @@ +pub mod above22; +pub mod bodyform; +pub mod brief; +pub mod cse; +pub mod deinline; +pub mod depgraph; +pub mod double_apply; +pub mod strategy; + +#[cfg(test)] +use num_bigint::ToBigInt; + +use std::borrow::Borrow; +use std::collections::HashMap; +use std::rc::Rc; + +use clvm_rs::allocator::Allocator; + +#[cfg(test)] +use crate::classic::clvm::__type_compatibility__::bi_one; +use crate::classic::clvm::__type_compatibility__::bi_zero; + +use crate::classic::clvm_tools::stages::stage_0::TRunProgram; +use crate::classic::clvm_tools::stages::stage_2::optimize::optimize_sexp; + +use crate::compiler::clvm::{convert_from_clvm_rs, convert_to_clvm_rs, run}; +use crate::compiler::codegen::{codegen, do_mod_codegen, get_callable}; +use crate::compiler::comptypes::{ + BodyForm, CallSpec, Callable, CompileErr, CompileForm, CompilerOpts, DefunData, HelperForm, + PrimaryCodegen, SyntheticType, +}; +use crate::compiler::evaluate::{ + build_reflex_captures, dequote, is_i_atom, is_not_atom, Evaluator, EVAL_STACK_LIMIT, +}; +use crate::compiler::optimize::above22::Strategy23; +use crate::compiler::optimize::strategy::ExistingStrategy; +use crate::compiler::runtypes::RunFailure; +#[cfg(test)] +use crate::compiler::sexp::parse_sexp; +use crate::compiler::sexp::{AtomValue, NodeSel, SExp, SelectNode, ThisNode}; +use crate::compiler::srcloc::Srcloc; +use crate::compiler::CompileContextWrapper; +use crate::compiler::StartOfCodegenOptimization; +use crate::util::u8_from_number; + +const CONST_FOLD_LIMIT: usize = 10000000; + +/// Represents a code generator level optimization result. +/// If revised_definition is different from the one we already have, the compiler +/// must re-generate at least functions that depend on this one. +#[derive(Default, Debug, Clone)] +pub struct CodegenOptimizationResult { + /// Revised code generator object, if given. + pub revised_code_generator: Option, + /// If present, the definition of the helperform, if provided, was changed. + pub revised_definition: Option, + /// If present, each key represents the shatree of an environment part that + /// was rewriten along with its new definition. + pub revised_environment: Option, Rc>>, + /// Final generated code if different. + pub code: Option>, +} + +/// Make a formal interface that represents all kinds of optimization we can do. +/// This includes these possible things: +/// +/// - Frontend: +/// - Simplification +/// - Constant folding +/// - Inlining and deinlining +/// - SSA optimizations +/// - Deduplication +/// - Constant term propogation +/// - ... etc +/// - Argument list changes which simplify code +/// - Capture removal +/// - Pattern based inlining in loops +/// +/// - Start of codegen +/// - Environment layout optimization +/// - Dead code/constant elimination +/// - Leaf function optimization +/// - Leaf main optimization +/// +/// - During codegen +/// - Function level code optimizations +/// - Constant compression +/// - Nil and quote simplification +/// - Constant folding +/// - Path folding for (r and (f and composed paths +/// - Cons simplification +/// - Apply elision +/// +/// Global optimization must be performed when the code generator is requesting +/// optimizations on the main expression, therefore there is no post-code generator +/// optimization in this scheme. +/// +pub trait Optimization { + /// Represents frontend optimizations + fn frontend_optimization( + &mut self, + allocator: &mut Allocator, + runner: Rc, + opts: Rc, + cf: CompileForm, + ) -> Result; + + /// Represents optimization we should do after desugaring, such as deinlining + fn post_desugar_optimization( + &mut self, + allocator: &mut Allocator, + runner: Rc, + opts: Rc, + cf: CompileForm, + ) -> Result; + + /// Represents start of codegen optimizations + /// PrimaryCodegen has computed the environment it wants to use but hasn't + /// generated any code that depends on it yet. + fn start_of_codegen_optimization( + &mut self, + allocator: &mut Allocator, + runner: Rc, + opts: Rc, + to_optimize: StartOfCodegenOptimization, + ) -> Result; + + /// Optimize macro bodies. + fn macro_optimization( + &mut self, + allocator: &mut Allocator, + runner: Rc, + opts: Rc, + code: Rc, + ) -> Result, CompileErr>; + + fn defun_body_optimization( + &mut self, + allocator: &mut Allocator, + runner: Rc, + opts: Rc, + codegen: &PrimaryCodegen, + defun: &DefunData, + ) -> Result, CompileErr>; + + fn post_codegen_function_optimize( + &mut self, + allocator: &mut Allocator, + runner: Rc, + opts: Rc, + helper: Option<&HelperForm>, + code: Rc, + ) -> Result, CompileErr>; + + fn pre_final_codegen_optimize( + &mut self, + allocator: &mut Allocator, + runner: Rc, + opts: Rc, + codegen: &PrimaryCodegen, + ) -> Result, CompileErr>; + + fn post_codegen_output_optimize( + &mut self, + opts: Rc, + generated: SExp, + ) -> Result; + + fn duplicate(&self) -> Box; +} + +fn is_at_form(head: Rc) -> bool { + match head.borrow() { + BodyForm::Value(SExp::Atom(_, a)) => a.len() == 1 && a[0] == b'@', + _ => false, + } +} + +// Return a score for sexp size. +pub fn sexp_scale(sexp: &SExp) -> u64 { + match sexp { + SExp::Cons(_, a, b) => { + let a_scale = sexp_scale(a.borrow()); + let b_scale = sexp_scale(b.borrow()); + 1_u64 + a_scale + b_scale + } + SExp::Nil(_) => 1, + SExp::QuotedString(_, _, s) => 1_u64 + s.len() as u64, + SExp::Atom(_, n) => 1_u64 + n.len() as u64, + SExp::Integer(_, i) => { + let raw_bits = i.bits(); + let use_bits = if raw_bits > 0 { raw_bits - 1 } else { 0 }; + let bytes = use_bits / 8; + 1_u64 + bytes + } + } +} + +#[test] +fn test_sexp_scale_increases_with_atom_size() { + let l = Srcloc::start("*test*"); + assert!( + sexp_scale(&SExp::Integer(l.clone(), bi_one())) + < sexp_scale(&SExp::Integer(l, 1000000_u32.to_bigint().unwrap())) + ); +} + +fn is_not_condition(bf: &BodyForm) -> Option> { + // Checking for a primitive so no tail. + if let BodyForm::Call(_, parts, None) = bf { + if parts.len() != 2 { + return None; + } + + if is_not_atom(parts[0].to_sexp()) { + return Some(parts[1].clone()); + } + } + + None +} + +/// Changes (i (not c) a b) into (i c b a) +fn condition_invert_optimize( + opts: Rc, + loc: &Srcloc, + forms: &[Rc], +) -> Option { + if let Some(res) = opts.dialect().stepping { + // Only perform on chialisp above the appropriate stepping. + if res >= 23 { + if forms.len() != 4 { + return None; + } + + if !is_i_atom(forms[0].to_sexp()) { + return None; + } + + // We have a (not cond) + if let Some(condition) = is_not_condition(forms[1].borrow()) { + return Some(BodyForm::Call( + loc.clone(), + vec![ + forms[0].clone(), + condition, + forms[3].clone(), + forms[2].clone(), + ], + None, + )); + } + } + } + + None +} + +/// If a function is called with all constant arguments, we compose the program +/// that runs that function and run it. +/// +/// The result is the constant result of invoking the function. +fn constant_fun_result( + allocator: &mut Allocator, + opts: Rc, + runner: Rc, + compiler: &PrimaryCodegen, + call_spec: &CallSpec, +) -> Option> { + if let Some(res) = opts.dialect().stepping { + if res >= 23 { + let mut constant = true; + let optimized_args: Vec<(bool, Rc)> = call_spec + .args + .iter() + .skip(1) + .map(|a| { + let optimized = + optimize_expr(allocator, opts.clone(), runner.clone(), compiler, a.clone()); + constant = constant && optimized.as_ref().map(|x| x.0).unwrap_or_else(|| false); + optimized + .map(|x| (x.0, x.1)) + .unwrap_or_else(|| (false, a.clone())) + }) + .collect(); + + let optimized_tail: Option<(bool, Rc)> = call_spec.tail.as_ref().map(|t| { + let optimized = + optimize_expr(allocator, opts.clone(), runner.clone(), compiler, t.clone()); + constant = constant && optimized.as_ref().map(|x| x.0).unwrap_or_else(|| false); + optimized + .map(|x| (x.0, x.1)) + .unwrap_or_else(|| (false, t.clone())) + }); + + if !constant { + return None; + } + + let compiled_body = { + let to_compile = CompileForm { + loc: call_spec.loc.clone(), + include_forms: Vec::new(), + helpers: compiler.original_helpers.clone(), + args: Rc::new(SExp::Atom(call_spec.loc.clone(), b"__ARGS__".to_vec())), + exp: Rc::new(BodyForm::Call( + call_spec.loc.clone(), + vec![ + Rc::new(BodyForm::Value(SExp::Atom(call_spec.loc.clone(), vec![2]))), + Rc::new(BodyForm::Value(SExp::Atom( + call_spec.loc.clone(), + call_spec.name.to_vec(), + ))), + Rc::new(BodyForm::Value(SExp::Atom( + call_spec.loc.clone(), + b"__ARGS__".to_vec(), + ))), + ], + // Proper call: we're calling 'a' on behalf of our + // single capture argument. + None, + )), + ty: None, + }; + let optimizer = if let Ok(res) = get_optimizer(&call_spec.loc, opts.clone()) { + res + } else { + return None; + }; + + let mut symbols = HashMap::new(); + let mut wrapper = + CompileContextWrapper::new(allocator, runner.clone(), &mut symbols, optimizer); + + if let Ok(code) = codegen(&mut wrapper.context, opts.clone(), &to_compile) { + code + } else { + return None; + } + }; + + // Reified args reflect the actual ABI shape with a tail if any. + let mut reified_args = if let Some((_, t)) = optimized_tail { + if let Ok(res) = dequote(call_spec.loc.clone(), t) { + res + } else { + return None; + } + } else { + Rc::new(SExp::Nil(call_spec.loc.clone())) + }; + for (_, v) in optimized_args.iter().rev() { + let unquoted = if let Ok(res) = dequote(call_spec.loc.clone(), v.clone()) { + res + } else { + return None; + }; + reified_args = Rc::new(SExp::Cons(call_spec.loc.clone(), unquoted, reified_args)); + } + let borrowed_args: &SExp = reified_args.borrow(); + let new_body = BodyForm::Call( + call_spec.loc.clone(), + vec![ + Rc::new(BodyForm::Value(SExp::Atom(call_spec.loc.clone(), vec![2]))), + Rc::new(BodyForm::Quoted(compiled_body)), + Rc::new(BodyForm::Quoted(borrowed_args.clone())), + ], + // The constructed call is proper because we're feeding something + // we constructed above. + None, + ); + + return Some(Rc::new(new_body)); + } + } + + None +} + +/// At this point, very rudimentary constant folding on body expressions. +pub fn optimize_expr( + allocator: &mut Allocator, + opts: Rc, + runner: Rc, + compiler: &PrimaryCodegen, + body: Rc, +) -> Option<(bool, Rc)> { + match body.borrow() { + BodyForm::Quoted(_) => Some((true, body)), + BodyForm::Call(l, forms, tail) => { + // () evaluates to () + if forms.is_empty() { + return Some((true, body)); + } else if is_at_form(forms[0].clone()) { + return None; + } + + let examine_call = |al: Srcloc, an: &Vec| { + get_callable( + opts.clone(), + compiler, + l.clone(), + Rc::new(SExp::Atom(al, an.to_vec())), + ) + .map(|calltype| match calltype { + // A macro invocation emits a bodyform, which we + // run back through the frontend and check. + Callable::CallMacro(_l, _) => None, + // A function is constant if its body is a constant + // expression or all its arguments are constant and + // its body doesn't include an environment reference. + Callable::CallDefun(l, _target) => { + if let Some(constant_invocation) = constant_fun_result( + allocator, + opts.clone(), + runner.clone(), + compiler, + &CallSpec { + loc: l, + name: an, + args: forms, + tail: tail.clone(), + original: body.clone(), + }, + ) { + return Some( + optimize_expr( + allocator, + opts.clone(), + runner, + compiler, + constant_invocation.clone(), + ) + .map(|(_, optimize)| (true, optimize)) + .unwrap_or_else(|| (true, constant_invocation)), + ); + } + + None + } + // A primcall is constant if its arguments are constant + Callable::CallPrim(l, _) => { + let mut constant = true; + + if let Some(not_invert) = condition_invert_optimize(opts.clone(), &l, forms) + { + return Some( + optimize_expr( + allocator, + opts.clone(), + runner.clone(), + compiler, + Rc::new(not_invert.clone()), + ) + .map(|(_, optimize)| (true, optimize)) + .unwrap_or_else(|| (true, Rc::new(not_invert))), + ); + } + + let optimized_args: Vec<(bool, Rc)> = forms + .iter() + .skip(1) + .map(|a| { + let optimized = optimize_expr( + allocator, + opts.clone(), + runner.clone(), + compiler, + a.clone(), + ); + constant = constant + && optimized.as_ref().map(|x| x.0).unwrap_or_else(|| false); + optimized + .map(|x| (x.0, x.1)) + .unwrap_or_else(|| (false, a.clone())) + }) + .collect(); + + let mut result_list = vec![forms[0].clone()]; + let mut replaced_args = + optimized_args.iter().map(|x| x.1.clone()).collect(); + result_list.append(&mut replaced_args); + // Primitive call: no tail. + let code = BodyForm::Call(l.clone(), result_list, None); + + if constant { + run( + allocator, + runner.clone(), + opts.prim_map(), + code.to_sexp(), + Rc::new(SExp::Nil(l)), + None, + Some(CONST_FOLD_LIMIT), + ) + .map(|x| { + let x_borrow: &SExp = x.borrow(); + Some((true, Rc::new(BodyForm::Quoted(x_borrow.clone())))) + }) + .unwrap_or_else(|_| Some((false, Rc::new(code)))) + } else { + Some((false, Rc::new(code))) + } + } + _ => None, + }) + .unwrap_or_else(|_| None) + }; + + match forms[0].borrow() { + BodyForm::Value(SExp::Integer(al, an)) => { + examine_call(al.clone(), &u8_from_number(an.clone())) + } + BodyForm::Value(SExp::QuotedString(al, _, an)) => examine_call(al.clone(), an), + BodyForm::Value(SExp::Atom(al, an)) => examine_call(al.clone(), an), + _ => None, + } + } + BodyForm::Value(SExp::Integer(l, i)) => Some(( + true, + Rc::new(BodyForm::Quoted(SExp::Integer(l.clone(), i.clone()))), + )), + BodyForm::Mod(l, cf) => { + if let Some(stepping) = opts.dialect().stepping { + if stepping >= 23 { + let mut throwaway_symbols = HashMap::new(); + if let Ok(optimizer) = get_optimizer(l, opts.clone()) { + let mut wrapper = CompileContextWrapper::new( + allocator, + runner, + &mut throwaway_symbols, + optimizer, + ); + if let Ok(compiled) = do_mod_codegen(&mut wrapper.context, opts.clone(), cf) + { + if let Ok(NodeSel::Cons(_, body)) = + NodeSel::Cons(AtomValue::Here(&[1]), ThisNode) + .select_nodes(compiled.1) + { + let borrowed_body: &SExp = body.borrow(); + return Some(( + true, + Rc::new(BodyForm::Quoted(borrowed_body.clone())), + )); + } + } + } + } + } + + None + } + _ => None, + } +} + +// If (1) appears anywhere outside of a quoted expression, it can be replaced with +// () since nil yields itself. +fn null_optimization(sexp: Rc, spine: bool) -> (bool, Rc) { + if let SExp::Cons(l, a, b) = sexp.borrow() { + if let SExp::Atom(_, name) = a.atomize() { + if (name == vec![1] || name == b"q") && !spine { + let b_empty = match b.borrow() { + SExp::Atom(_, tail) => tail.is_empty(), + SExp::QuotedString(_, _, q) => q.is_empty(), + SExp::Integer(_, i) => *i == bi_zero(), + SExp::Nil(_) => true, + _ => false, + }; + + if b_empty { + return (true, b.clone()); + } else { + return (false, sexp); + } + } + } + + let (oa, opt_a) = null_optimization(a.clone(), false); + let (ob, opt_b) = null_optimization(b.clone(), true); + + if oa || ob { + return (true, Rc::new(SExp::Cons(l.clone(), opt_a, opt_b))); + } + } + + (false, sexp) +} + +#[test] +fn test_null_optimization_basic() { + let loc = Srcloc::start("*test*"); + let parsed = parse_sexp(loc.clone(), "(2 (1 1) (4 (1) 1))".bytes()).expect("should parse"); + let (did_work, optimized) = null_optimization(parsed[0].clone(), true); + assert!(did_work); + assert_eq!(optimized.to_string(), "(2 (1 1) (4 () 1))"); +} + +#[test] +fn test_null_optimization_skips_quoted() { + let loc = Srcloc::start("*test*"); + let parsed = parse_sexp(loc.clone(), "(2 (1 (1) (1) (1)) (1))".bytes()).expect("should parse"); + let (did_work, optimized) = null_optimization(parsed[0].clone(), true); + assert!(did_work); + assert_eq!(optimized.to_string(), "(2 (1 (1) (1) (1)) ())"); +} + +#[test] +fn test_null_optimization_ok_not_doing_anything() { + let loc = Srcloc::start("*test*"); + let parsed = parse_sexp(loc.clone(), "(2 (1 (1) (1) (1)) (3))".bytes()).expect("should parse"); + let (did_work, optimized) = null_optimization(parsed[0].clone(), true); + assert!(!did_work); + assert_eq!(optimized.to_string(), "(2 (1 (1) (1) (1)) (3))"); +} + +fn fe_opt( + allocator: &mut Allocator, + runner: Rc, + opts: Rc, + compileform: CompileForm, +) -> Result { + let evaluator = Evaluator::new(opts.clone(), runner.clone(), compileform.helpers.clone()); + let mut optimized_helpers: Vec = Vec::new(); + for h in compileform.helpers.iter() { + match h { + HelperForm::Defun(inline, defun) => { + let mut env = HashMap::new(); + build_reflex_captures(&mut env, defun.args.clone()); + let body_rc = evaluator.shrink_bodyform( + allocator, + defun.args.clone(), + &env, + defun.body.clone(), + true, + Some(EVAL_STACK_LIMIT), + )?; + let new_helper = HelperForm::Defun( + *inline, + Box::new(DefunData { + body: body_rc.clone(), + ..*defun.clone() + }), + ); + optimized_helpers.push(new_helper); + } + obj => { + optimized_helpers.push(obj.clone()); + } + } + } + let new_evaluator = Evaluator::new(opts.clone(), runner.clone(), optimized_helpers.clone()); + + let shrunk = new_evaluator.shrink_bodyform( + allocator, + Rc::new(SExp::Nil(compileform.args.loc())), + &HashMap::new(), + compileform.exp.clone(), + true, + Some(EVAL_STACK_LIMIT), + )?; + + Ok(CompileForm { + helpers: optimized_helpers.clone(), + exp: shrunk, + ..compileform + }) +} + +pub fn run_optimizer( + allocator: &mut Allocator, + runner: Rc, + r: Rc, +) -> Result, CompileErr> { + let to_clvm_rs = convert_to_clvm_rs(allocator, r.clone()) + .map(|x| (r.loc(), x)) + .map_err(|e| match e { + RunFailure::RunErr(l, e) => CompileErr(l, e), + RunFailure::RunExn(s, e) => CompileErr(s, format!("exception {e}\n")), + })?; + + let optimized = optimize_sexp(allocator, to_clvm_rs.1, runner) + .map_err(|e| CompileErr(to_clvm_rs.0.clone(), e.1)) + .map(|x| (to_clvm_rs.0, x))?; + + convert_from_clvm_rs(allocator, optimized.0, optimized.1).map_err(|e| match e { + RunFailure::RunErr(l, e) => CompileErr(l, e), + RunFailure::RunExn(s, e) => CompileErr(s, format!("exception {e}\n")), + }) +} + +/// Produce the optimization strategy specified by the compiler opts we're given. +pub fn get_optimizer( + loc: &Srcloc, + opts: Rc, +) -> Result, CompileErr> { + if let Some(s) = opts.dialect().stepping { + if s < 21 { + return Err(CompileErr( + loc.clone(), + format!("minimum language stepping is 21, {s} specified"), + )); + } else if s > 23 { + return Err(CompileErr( + loc.clone(), + format!("maximum language stepping is 23 at this time, {s} specified"), + )); + } else if s == 23 && opts.optimize() { + return Ok(Box::new(Strategy23::new())); + } + } + + Ok(Box::new(ExistingStrategy::new())) +} + +/// This small interface takes care of various scenarios that have existed +/// regarding mixing modern chialisp output with classic's optimizer. +pub fn maybe_finalize_program_via_classic_optimizer( + allocator: &mut Allocator, + runner: Rc, + _opts: Rc, // Currently unused but I want this interface + // to consider opts in the future when required. + opt_flag: bool, // Command line flag and other features control this in oldest- // versions + unopt_res: &SExp, +) -> Result, CompileErr> { + if opt_flag { + run_optimizer(allocator, runner, Rc::new(unopt_res.clone())) + } else { + Ok(Rc::new(unopt_res.clone())) + } +} diff --git a/src/compiler/optimize/strategy.rs b/src/compiler/optimize/strategy.rs new file mode 100644 index 000000000..7ea7ef668 --- /dev/null +++ b/src/compiler/optimize/strategy.rs @@ -0,0 +1,170 @@ +use std::borrow::Borrow; +use std::collections::HashMap; +use std::rc::Rc; + +use clvmr::allocator::Allocator; + +use crate::classic::clvm_tools::stages::stage_0::TRunProgram; + +use crate::compiler::comptypes::{ + BodyForm, CompileErr, CompileForm, CompilerOpts, DefunData, HelperForm, PrimaryCodegen, +}; +use crate::compiler::optimize::deinline::deinline_opt; +use crate::compiler::optimize::{ + fe_opt, null_optimization, optimize_expr, run_optimizer, CompileContextWrapper, Optimization, +}; +use crate::compiler::sexp::SExp; +use crate::compiler::StartOfCodegenOptimization; + +/// Captures the existing strategy set for cl22 and below. +#[derive(Default, Clone)] +pub struct ExistingStrategy {} + +impl ExistingStrategy { + pub fn new() -> Self { + ExistingStrategy {} + } +} + +impl Optimization for ExistingStrategy { + fn frontend_optimization( + &mut self, + allocator: &mut Allocator, + runner: Rc, + opts: Rc, + p0: CompileForm, + ) -> Result { + // Not yet turned on for >22 + if opts.frontend_opt() && !(opts.dialect().stepping.map(|d| d > 22).unwrap_or(false)) { + // Front end optimization + fe_opt(allocator, runner, opts.clone(), p0) + } else { + Ok(p0) + } + } + + fn post_desugar_optimization( + &mut self, + allocator: &mut Allocator, + runner: Rc, + opts: Rc, + cf: CompileForm, + ) -> Result { + if opts.frontend_opt() && opts.dialect().stepping.map(|s| s > 22).unwrap_or(false) { + let mut symbols = HashMap::new(); + let mut wrapper = + CompileContextWrapper::new(allocator, runner, &mut symbols, self.duplicate()); + deinline_opt(&mut wrapper.context, opts.clone(), cf) + } else { + Ok(cf) + } + } + + fn start_of_codegen_optimization( + &mut self, + _allocator: &mut Allocator, + _runner: Rc, + _opts: Rc, + to_optimize: StartOfCodegenOptimization, + ) -> Result { + Ok(to_optimize) + } + + fn macro_optimization( + &mut self, + allocator: &mut Allocator, + runner: Rc, + opts: Rc, + code: Rc, + ) -> Result, CompileErr> { + if opts.optimize() { + run_optimizer(allocator, runner, code) + } else { + Ok(code) + } + } + + fn defun_body_optimization( + &mut self, + allocator: &mut Allocator, + runner: Rc, + opts: Rc, + codegen: &PrimaryCodegen, + defun: &DefunData, + ) -> Result, CompileErr> { + let res = if opts.optimize() { + // Run optimizer on frontend style forms. + optimize_expr( + allocator, + opts.clone(), + runner.clone(), + codegen, + defun.body.clone(), + ) + .map(|x| x.1) + .unwrap_or_else(|| defun.body.clone()) + } else { + defun.body.clone() + }; + Ok(res) + } + + fn post_codegen_function_optimize( + &mut self, + allocator: &mut Allocator, + runner: Rc, + opts: Rc, + helper: Option<&HelperForm>, + code: Rc, + ) -> Result, CompileErr> { + if opts.optimize() && helper.is_some() { + run_optimizer(allocator, runner, code) + } else { + Ok(code) + } + } + + fn pre_final_codegen_optimize( + &mut self, + allocator: &mut Allocator, + runner: Rc, + opts: Rc, + codegen: &PrimaryCodegen, + ) -> Result, CompileErr> { + let res = if opts.optimize() { + optimize_expr( + allocator, + opts.clone(), + runner, + codegen, + codegen.final_expr.clone(), + ) + .map(|x| x.1) + .unwrap_or_else(|| codegen.final_expr.clone()) + } else { + codegen.final_expr.clone() + }; + + Ok(res) + } + + fn post_codegen_output_optimize( + &mut self, + opts: Rc, + generated: SExp, + ) -> Result { + if opts.frontend_opt() && opts.dialect().stepping.map(|s| s > 22).unwrap_or(false) { + let (did_work, optimized) = null_optimization(Rc::new(generated.clone()), false); + if did_work { + let o_borrowed: &SExp = optimized.borrow(); + return Ok(o_borrowed.clone()); + } + } + + Ok(generated) + } + + fn duplicate(&self) -> Box { + Box::new(self.clone()) + } +} diff --git a/src/compiler/preprocessor.rs b/src/compiler/preprocessor.rs deleted file mode 100644 index 640f90b4b..000000000 --- a/src/compiler/preprocessor.rs +++ /dev/null @@ -1,344 +0,0 @@ -use std::borrow::Borrow; -use std::collections::HashMap; -use std::rc::Rc; - -use clvmr::allocator::Allocator; - -use crate::classic::clvm::__type_compatibility__::{Bytes, BytesFromType}; - -use crate::compiler::cldb::hex_to_modern_sexp; -use crate::compiler::compiler::KNOWN_DIALECTS; -use crate::compiler::comptypes::{CompileErr, CompilerOpts, IncludeDesc, IncludeProcessType}; -use crate::compiler::runtypes::RunFailure; -use crate::compiler::sexp::{decode_string, enlist, parse_sexp, SExp}; -use crate::compiler::srcloc::Srcloc; -use crate::util::ErrInto; - -/// Determines how an included file is used. -/// -/// Basic means that the file contains helper forms to include in the program. -/// Processed means that some kind of processing is done and the result is a named -/// constant. -#[derive(Clone, Debug)] -enum IncludeType { - /// Normal include in chialisp. The code in the target file will join the - /// program being compiled. - Basic(IncludeDesc), - /// The data in the file will be processed in some way and the result will - /// live in a named constant. - Processed(IncludeDesc, IncludeProcessType, Vec), -} - -/// Given a specification of an include file, load up the forms inside it and -/// return them (or an error if the file couldn't be read or wasn't a list). -pub fn process_include( - opts: Rc, - include: IncludeDesc, -) -> Result>, CompileErr> { - let filename_and_content = opts.read_new_file(opts.filename(), decode_string(&include.name))?; - let content = filename_and_content.1; - let start_of_file = Srcloc::start(&decode_string(&include.name)); - - // Because we're also subsequently returning CompileErr later in the pipe, - // this needs an explicit err map. - parse_sexp(start_of_file.clone(), content.iter().copied()) - .err_into() - .and_then(|x| match x[0].proper_list() { - None => Err(CompileErr( - start_of_file, - "Includes should contain a list of forms".to_string(), - )), - Some(v) => Ok(v.iter().map(|x| Rc::new(x.clone())).collect()), - }) -} - -fn compose_defconst(loc: Srcloc, name: &[u8], sexp: Rc) -> Rc { - Rc::new(enlist( - loc.clone(), - &[ - Rc::new(SExp::Atom(loc.clone(), b"defconst".to_vec())), - Rc::new(SExp::Atom(loc.clone(), name.to_vec())), - Rc::new(SExp::Cons( - loc.clone(), - Rc::new(SExp::Atom(loc, vec![1])), - sexp, - )), - ], - )) -} - -fn process_embed( - loc: Srcloc, - opts: Rc, - fname: &str, - kind: IncludeProcessType, - constant_name: &[u8], -) -> Result>, CompileErr> { - let mut allocator = Allocator::new(); - let run_to_compile_err = |e| match e { - RunFailure::RunExn(l, x) => CompileErr( - l, - format!("failed to convert compiled clvm to expression: throw ({x})"), - ), - RunFailure::RunErr(l, e) => CompileErr( - l, - format!("failed to convert compiled clvm to expression: {e}"), - ), - }; - - let (full_name, content) = opts.read_new_file(opts.filename(), fname.to_string())?; - let content = match kind { - IncludeProcessType::Bin => Rc::new(SExp::Atom(loc.clone(), content)), - IncludeProcessType::Hex => hex_to_modern_sexp( - &mut allocator, - &HashMap::new(), - loc.clone(), - &decode_string(&content), - ) - .map_err(run_to_compile_err)?, - IncludeProcessType::SExpression => { - let parsed = parse_sexp(Srcloc::start(&full_name), content.iter().copied()) - .map_err(|e| CompileErr(e.0, e.1))?; - if parsed.len() != 1 { - return Err(CompileErr( - loc, - format!("More than one form (or empty data) in {fname}"), - )); - } - - parsed[0].clone() - } - }; - - Ok(vec![compose_defconst(loc, constant_name, content)]) -} - -/* Expand include inline in forms */ -fn process_pp_form( - opts: Rc, - includes: &mut Vec, - body: Rc, -) -> Result>, CompileErr> { - // Support using the preprocessor to collect dependencies recursively. - let recurse_dependencies = |opts: Rc, - includes: &mut Vec, - desc: IncludeDesc| - -> Result<(), CompileErr> { - let name_string = decode_string(&desc.name); - if KNOWN_DIALECTS.contains_key(&name_string) { - return Ok(()); - } - - let (full_name, content) = opts.read_new_file(opts.filename(), name_string)?; - includes.push(IncludeDesc { - name: full_name.as_bytes().to_vec(), - ..desc - }); - - let parsed = parse_sexp(Srcloc::start(&full_name), content.iter().copied()) - .map_err(|e| CompileErr(e.0, e.1))?; - if parsed.is_empty() { - return Ok(()); - } - - let program_form = parsed[0].clone(); - if let Some(l) = program_form.proper_list() { - for elt in l.iter() { - process_pp_form(opts.clone(), includes, Rc::new(elt.clone()))?; - } - } - - Ok(()) - }; - - let include_type: Option = body - .proper_list() - .map(|x| x.iter().map(|elt| elt.atomize()).collect()) - .map(|x: Vec| { - match &x[..] { - [SExp::Atom(kw, inc), SExp::Atom(nl, fname)] => { - if inc == b"include" { - return Ok(Some(IncludeType::Basic(IncludeDesc { - kw: kw.clone(), - nl: nl.clone(), - kind: None, - name: fname.clone(), - }))); - } - } - - // Accepted forms: - // (embed-file varname bin file.dat) - // (embed-file varname sexp file.clvm) - // (embed-file varname hex file.hex) - [SExp::Atom(kl, embed_file), SExp::Atom(_, name), SExp::Atom(_, kind), SExp::Atom(nl, fname)] => { - if embed_file == b"embed-file" { - if kind == b"hex" { - return Ok(Some(IncludeType::Processed( - IncludeDesc { - kw: kl.clone(), - nl: nl.clone(), - kind: Some(IncludeProcessType::Hex), - name: fname.clone(), - }, - IncludeProcessType::Hex, - name.clone() - ))); - } else if kind == b"bin" { - return Ok(Some(IncludeType::Processed( - IncludeDesc { - kw: kl.clone(), - nl: nl.clone(), - kind: Some(IncludeProcessType::Bin), - name: fname.clone(), - }, - IncludeProcessType::Bin, - name.clone(), - ))); - } else if kind == b"sexp" { - return Ok(Some(IncludeType::Processed( - IncludeDesc { - kw: kl.clone(), - nl: nl.clone(), - kind: Some(IncludeProcessType::SExpression), - name: fname.clone(), - }, - IncludeProcessType::SExpression, - name.clone(), - ))); - } else { - return Err(CompileErr( - body.loc(), - format!("bad include kind in embed-file {body}") - )); - } - } - } - - [] => {} - - // Ensure that legal empty or atom expressions don't try include - _ => { - // Include is only allowed as a proper form. It's a keyword in - // this language. - if let SExp::Atom(_, inc) = &x[0] { - if inc == b"include" { - return Err(CompileErr( - body.loc(), - format!("bad tail in include {body}"), - )); - } - } - } - } - - Ok(None) - }) - .unwrap_or_else(|| Ok(None))?; - - match include_type { - Some(IncludeType::Basic(f)) => { - recurse_dependencies(opts.clone(), includes, f.clone())?; - process_include(opts, f) - } - Some(IncludeType::Processed(f, kind, name)) => process_embed( - body.loc(), - opts, - &Bytes::new(Some(BytesFromType::Raw(f.name.to_vec()))).decode(), - kind, - &name, - ), - _ => Ok(vec![body]), - } -} - -fn preprocess_( - opts: Rc, - includes: &mut Vec, - body: Rc, -) -> Result>, CompileErr> { - match body.borrow() { - SExp::Cons(_, head, rest) => match rest.borrow() { - SExp::Nil(_nl) => process_pp_form(opts, includes, head.clone()), - _ => { - let lst = process_pp_form(opts.clone(), includes, head.clone())?; - let mut rs = preprocess_(opts, includes, rest.clone())?; - let mut result = lst; - result.append(&mut rs); - Ok(result) - } - }, - _ => Ok(vec![body]), - } -} - -fn inject_std_macros(body: Rc) -> SExp { - match body.proper_list() { - Some(v) => { - let include_form = Rc::new(SExp::Cons( - body.loc(), - Rc::new(SExp::atom_from_string(body.loc(), "include")), - Rc::new(SExp::Cons( - body.loc(), - Rc::new(SExp::quoted_from_string(body.loc(), "*macros*")), - Rc::new(SExp::Nil(body.loc())), - )), - )); - let mut v_clone: Vec> = v.iter().map(|x| Rc::new(x.clone())).collect(); - let include_copy: &SExp = include_form.borrow(); - v_clone.insert(0, Rc::new(include_copy.clone())); - enlist(body.loc(), &v_clone) - } - _ => { - let body_clone: &SExp = body.borrow(); - body_clone.clone() - } - } -} - -/// Run the preprocessor over this code, which at present just finds (include ...) -/// forms in the source and includes the content of in a combined list. If a file -/// can't be found via the directory list in CompilerOrs. -pub fn preprocess( - opts: Rc, - includes: &mut Vec, - cmod: Rc, -) -> Result>, CompileErr> { - let tocompile = if opts.stdenv() { - let injected = inject_std_macros(cmod); - Rc::new(injected) - } else { - cmod - }; - - preprocess_(opts, includes, tocompile) -} - -/// Visit all files used during compilation. -/// This reports a list of all files used while compiling the input file, via any -/// form that causes compilation to include another file. The file names are path -/// expanded based on the include path they were found in (from opts). -pub fn gather_dependencies( - opts: Rc, - real_input_path: &str, - file_content: &str, -) -> Result, CompileErr> { - let mut includes = Vec::new(); - let loc = Srcloc::start(real_input_path); - - let parsed = parse_sexp(loc.clone(), file_content.bytes())?; - - if parsed.is_empty() { - return Ok(vec![]); - } - - if let Some(l) = parsed[0].proper_list() { - for elt in l.iter() { - process_pp_form(opts.clone(), &mut includes, Rc::new(elt.clone()))?; - } - } else { - return Err(CompileErr(loc, "malformed list body".to_string())); - }; - - Ok(includes) -} diff --git a/src/compiler/preprocessor/macros.rs b/src/compiler/preprocessor/macros.rs new file mode 100644 index 000000000..f4f673374 --- /dev/null +++ b/src/compiler/preprocessor/macros.rs @@ -0,0 +1,397 @@ +use std::borrow::Borrow; +use std::collections::HashMap; +use std::rc::Rc; + +use num_bigint::ToBigInt; +use num_traits::ToPrimitive; + +use crate::classic::clvm::__type_compatibility__::{bi_one, bi_zero}; + +use crate::compiler::clvm::PrimOverride; +use crate::compiler::comptypes::{CompileErr, CompilerOpts}; +use crate::compiler::runtypes::RunFailure; +use crate::compiler::sexp::{decode_string, printable, SExp}; +use crate::compiler::srcloc::Srcloc; +use crate::util::{number_from_u8, Number}; + +// If the bodyform represents a constant, only match a quoted string. +fn match_quoted_string(body: Rc) -> Result<(Srcloc, Vec), CompileErr> { + match body.borrow() { + SExp::QuotedString(_, b'x', _) => {} + SExp::QuotedString(al, _, an) => return Ok((al.clone(), an.clone())), + _ => {} + } + + Err(CompileErr(body.loc(), "string required".to_string())) +} + +fn match_atom(body: Rc) -> Result<(Srcloc, Vec), CompileErr> { + if let SExp::Atom(al, an) = body.borrow() { + return Ok((al.clone(), an.clone())); + } + Err(CompileErr(body.loc(), "atom required".to_string())) +} + +enum MatchedNumber { + MatchedInt(Srcloc, Number), + MatchedHex(Srcloc, Vec), +} + +fn match_number(body: Rc) -> Result { + match body.borrow() { + SExp::Integer(il, n) => { + return Ok(MatchedNumber::MatchedInt(il.clone(), n.clone())); + } + SExp::QuotedString(ql, b'x', b) => { + return Ok(MatchedNumber::MatchedHex(ql.clone(), b.clone())); + } + SExp::Atom(al, b) => { + // An atom with unprintable characters is rendered as an integer. + if !printable(b, false) { + let to_integer = number_from_u8(b); + return Ok(MatchedNumber::MatchedInt(al.clone(), to_integer)); + } + } + SExp::Nil(il) => { + return Ok(MatchedNumber::MatchedInt(il.clone(), bi_zero())); + } + _ => {} + } + + Err(CompileErr(body.loc(), "Not a number".to_string())) +} + +fn numeric_value(body: Rc) -> Result { + match match_number(body.clone())? { + MatchedNumber::MatchedInt(_, n) => Ok(n), + MatchedNumber::MatchedHex(_, h) => Ok(number_from_u8(&h)), + } +} + +fn usize_value(body: Rc) -> Result { + let n = numeric_value(body.clone())?; + if let Some(res) = n.to_usize() { + Ok(res) + } else { + Err(CompileErr(body.loc(), "Value out of range".to_string())) + } +} + +/// A container for a function to evaluate in advanced preprocessor macros. +/// We use this trait (which is very similar to the extension trait in Evaluator) +/// as a definite handler for a specific named form, so optional returns aren't +/// needed. These are held in a collection and looked up. To be maximally +/// conservative with typing and lifetime, we hold these via Rc. +pub trait ExtensionFunction { + fn try_eval(&self, loc: &Srcloc, args: &[Rc]) -> Result, CompileErr>; +} + +struct StringQ; + +impl StringQ { + fn create() -> Rc { + Rc::new(StringQ) + } +} + +impl ExtensionFunction for StringQ { + fn try_eval(&self, loc: &Srcloc, args: &[Rc]) -> Result, CompileErr> { + let res = match match_quoted_string(args[0].clone()) { + Ok(_) => SExp::Integer(loc.clone(), bi_one()), + _ => SExp::Nil(loc.clone()), + }; + + Ok(Rc::new(res)) + } +} + +struct NumberQ; + +impl NumberQ { + fn create() -> Rc { + Rc::new(NumberQ) + } +} + +impl ExtensionFunction for NumberQ { + fn try_eval(&self, loc: &Srcloc, args: &[Rc]) -> Result, CompileErr> { + let res = match match_number(args[0].clone()) { + Ok(_) => SExp::Integer(loc.clone(), bi_one()), + _ => SExp::Nil(loc.clone()), + }; + + Ok(Rc::new(res)) + } +} + +struct SymbolQ; + +impl SymbolQ { + fn create() -> Rc { + Rc::new(SymbolQ) + } +} + +impl ExtensionFunction for SymbolQ { + fn try_eval(&self, loc: &Srcloc, args: &[Rc]) -> Result, CompileErr> { + let res = match match_atom(args[0].clone()) { + Ok(_) => SExp::Integer(loc.clone(), bi_one()), + _ => SExp::Nil(loc.clone()), + }; + + Ok(Rc::new(res)) + } +} + +struct SymbolToString; + +impl SymbolToString { + fn create() -> Rc { + Rc::new(SymbolToString) + } +} + +impl ExtensionFunction for SymbolToString { + fn try_eval(&self, _loc: &Srcloc, args: &[Rc]) -> Result, CompileErr> { + let (loc, value) = match_atom(args[0].clone())?; + Ok(Rc::new(SExp::QuotedString(loc, b'\"', value))) + } +} + +struct StringToSymbol; + +impl StringToSymbol { + fn create() -> Rc { + Rc::new(StringToSymbol) + } +} + +impl ExtensionFunction for StringToSymbol { + fn try_eval(&self, _loc: &Srcloc, args: &[Rc]) -> Result, CompileErr> { + let (loc, value) = match_quoted_string(args[0].clone())?; + Ok(Rc::new(SExp::Atom(loc, value))) + } +} + +struct StringAppend; + +impl StringAppend { + fn create() -> Rc { + Rc::new(StringAppend) + } +} + +impl ExtensionFunction for StringAppend { + fn try_eval(&self, loc: &Srcloc, args: &[Rc]) -> Result, CompileErr> { + let mut out_vec = Vec::new(); + let mut out_loc = None; + for a in args.iter() { + let (loc, mut value) = match_quoted_string(a.clone())?; + if out_loc.is_none() { + out_loc = Some(loc); + } + out_vec.append(&mut value); + } + Ok(Rc::new(SExp::QuotedString( + out_loc.unwrap_or_else(|| loc.clone()), + b'\"', + out_vec, + ))) + } +} + +struct NumberToString; + +impl NumberToString { + fn create() -> Rc { + Rc::new(NumberToString) + } +} + +impl ExtensionFunction for NumberToString { + fn try_eval(&self, _loc: &Srcloc, args: &[Rc]) -> Result, CompileErr> { + let match_res = match_number(args[0].clone())?; + let (use_loc, int_val) = match &match_res { + MatchedNumber::MatchedInt(l, i) => (l.clone(), i.clone()), + MatchedNumber::MatchedHex(l, h) => (l.clone(), number_from_u8(h)), + }; + Ok(Rc::new(SExp::QuotedString( + use_loc, + b'\"', + int_val.to_string().as_bytes().to_vec(), + ))) + } +} + +struct StringToNumber; + +impl StringToNumber { + fn create() -> Rc { + Rc::new(StringToNumber) + } +} + +impl ExtensionFunction for StringToNumber { + fn try_eval(&self, _loc: &Srcloc, args: &[Rc]) -> Result, CompileErr> { + let (loc, value) = match_quoted_string(args[0].clone())?; + if let Ok(cvt_bi) = decode_string(&value).parse::() { + Ok(Rc::new(SExp::Integer(loc, cvt_bi))) + } else { + Err(CompileErr(loc, "bad number".to_string())) + } + } +} + +struct StringLength; + +impl StringLength { + fn create() -> Rc { + Rc::new(StringLength) + } +} + +impl ExtensionFunction for StringLength { + fn try_eval(&self, _loc: &Srcloc, args: &[Rc]) -> Result, CompileErr> { + let (loc, value) = match_quoted_string(args[0].clone())?; + if let Some(len_bi) = value.len().to_bigint() { + return Ok(Rc::new(SExp::Integer(loc, len_bi))); + } + Err(CompileErr( + args[0].loc(), + "Error getting string length".to_string(), + )) + } +} + +struct Substring; + +impl Substring { + fn create() -> Rc { + Rc::new(Substring) + } +} + +impl ExtensionFunction for Substring { + fn try_eval(&self, _loc: &Srcloc, args: &[Rc]) -> Result, CompileErr> { + let start_element = usize_value(args[1].clone())?; + let end_element = usize_value(args[2].clone())?; + + match args[0].borrow() { + SExp::QuotedString(l, ch, s) => { + if start_element > end_element || start_element > s.len() || end_element > s.len() { + return Err(CompileErr( + l.clone(), + "start greater than end in substring".to_string(), + )); + } + let result_value: Vec = s + .iter() + .take(end_element) + .skip(start_element) + .copied() + .collect(); + Ok(Rc::new(SExp::QuotedString(l.clone(), *ch, result_value))) + } + _ => Err(CompileErr(args[0].loc(), "Not a string".to_string())), + } + } +} + +/// An evaluator extension for the preprocessor. +/// +/// Implements scheme like conversion functions for handling chialisp programs and +/// bits of them. +/// +/// These functions are provided: +/// +/// Enhanced versions of builtin macros: +/// +/// if -- first class short circuiting, no round trip to CLVM space +/// list -- simple own implementation +/// c -- cons preserving exact input values +/// f -- first and rest exactly preserving part of cons. +/// r -- +/// +/// Queries +/// +/// string? +/// number? +/// symbol? +/// +/// Basic conversion +/// +/// string->symbol +/// symbol->string +/// string->number +/// number->string +/// +/// Working with values +/// +/// string-append s0 s1 ... +/// string-length +/// substring s start end +/// +pub struct PreprocessorExtension { + extfuns: HashMap, Rc>, +} + +impl PrimOverride for PreprocessorExtension { + fn try_handle( + &self, + head: Rc, + _context: Rc, + tail: Rc, + ) -> Result>, RunFailure> { + if let SExp::Atom(hl, head_atom) = head.borrow() { + let have_args: Vec> = if let Some(args_list) = tail.proper_list() { + args_list.into_iter().map(Rc::new).collect() + } else { + return Ok(None); + }; + + if let Some(extension) = self.extfuns.get(head_atom) { + let res = extension.try_eval(hl, &have_args)?; + return Ok(Some(res)); + } + } + + Ok(None) + } +} + +impl PreprocessorExtension { + pub fn new() -> Self { + let extfuns = [ + (b"string?".to_vec(), StringQ::create()), + (b"number?".to_vec(), NumberQ::create()), + (b"symbol?".to_vec(), SymbolQ::create()), + (b"string->symbol".to_vec(), StringToSymbol::create()), + (b"symbol->string".to_vec(), SymbolToString::create()), + (b"string->number".to_vec(), StringToNumber::create()), + (b"number->string".to_vec(), NumberToString::create()), + (b"string-append".to_vec(), StringAppend::create()), + (b"string-length".to_vec(), StringLength::create()), + (b"substring".to_vec(), Substring::create()), + ]; + PreprocessorExtension { + extfuns: HashMap::from(extfuns), + } + } + + /// Introduce new primitive names for the operators we use to bootstrap macros. + pub fn enrich_prims(&self, opts: Rc) -> Rc { + let old_prim_map = opts.prim_map(); + let old_prim_map_borrowed: &HashMap, Rc> = old_prim_map.borrow(); + let mut new_prim_map_cloned = old_prim_map_borrowed.clone(); + let srcloc = Srcloc::start("*defmac*"); + + for (f, _) in self.extfuns.iter() { + if !new_prim_map_cloned.contains_key(f) { + new_prim_map_cloned + .insert(f.clone(), Rc::new(SExp::Atom(srcloc.clone(), f.clone()))); + } + } + + opts.set_prim_map(Rc::new(new_prim_map_cloned)) + } +} diff --git a/src/compiler/preprocessor/mod.rs b/src/compiler/preprocessor/mod.rs new file mode 100644 index 000000000..77266b00b --- /dev/null +++ b/src/compiler/preprocessor/mod.rs @@ -0,0 +1,605 @@ +mod macros; + +use std::borrow::Borrow; +use std::collections::HashMap; +use std::rc::Rc; + +use clvmr::allocator::Allocator; + +use crate::classic::clvm_tools::binutils::assemble; +use crate::classic::clvm_tools::stages::stage_0::{DefaultProgramRunner, TRunProgram}; + +use crate::compiler::cldb::hex_to_modern_sexp; +use crate::compiler::clvm; +use crate::compiler::clvm::truthy; +use crate::compiler::comptypes::{ + BodyForm, CompileErr, CompileForm, CompilerOpts, HelperForm, IncludeDesc, IncludeProcessType, +}; +use crate::compiler::dialect::{detect_modern, KNOWN_DIALECTS}; +use crate::compiler::evaluate::{create_argument_captures, ArgInputs}; +use crate::compiler::frontend::{compile_helperform, frontend}; +use crate::compiler::preprocessor::macros::PreprocessorExtension; +use crate::compiler::rename::rename_args_helperform; +use crate::compiler::runtypes::RunFailure; +use crate::compiler::sexp::{ + decode_string, enlist, parse_sexp, Atom, NodeSel, SExp, SelectNode, ThisNode, +}; +use crate::compiler::srcloc::Srcloc; +use crate::util::ErrInto; + +/// Determines how an included file is used. +/// +/// Basic means that the file contains helper forms to include in the program. +/// Processed means that some kind of processing is done and the result is a named +/// constant. +#[derive(Clone, Debug)] +enum IncludeType { + /// Normal include in chialisp. The code in the target file will join the + /// program being compiled. + Basic(IncludeDesc), + /// The data in the file will be processed in some way and the result will + /// live in a named constant. + Processed(IncludeDesc, IncludeProcessType, Vec), +} + +struct Preprocessor { + opts: Rc, + ppext: Rc, + runner: Rc, + helpers: Vec, + strict: bool, + stored_macros: HashMap, Rc>, +} + +fn compose_defconst(loc: Srcloc, name: &[u8], sexp: Rc) -> Rc { + Rc::new(enlist( + loc.clone(), + &[ + Rc::new(SExp::Atom(loc.clone(), b"defconst".to_vec())), + Rc::new(SExp::Atom(loc.clone(), name.to_vec())), + Rc::new(SExp::Cons( + loc.clone(), + Rc::new(SExp::Atom(loc, vec![1])), + sexp, + )), + ], + )) +} + +fn make_defmac_name(name: &[u8]) -> Vec { + let mut res = b"__chia__defmac__".to_vec(); + res.append(&mut name.to_vec()); + res +} + +fn nilize(v: Rc) -> Rc { + if let SExp::Cons(l, a, b) = v.borrow() { + let a_conv = nilize(a.clone()); + let b_conv = nilize(b.clone()); + if Rc::as_ptr(&a_conv) == Rc::as_ptr(a) && Rc::as_ptr(&b_conv) == Rc::as_ptr(b) { + v.clone() + } else { + Rc::new(SExp::Cons(l.clone(), a_conv, b_conv)) + } + } else if !truthy(v.clone()) { + Rc::new(SExp::Nil(v.loc())) + } else { + v + } +} + +impl Preprocessor { + pub fn new(opts: Rc) -> Self { + let runner = Rc::new(DefaultProgramRunner::new()); + let ppext = Rc::new(PreprocessorExtension::new()); + let opts_prims = ppext.enrich_prims(opts.clone()); + Preprocessor { + opts: opts_prims, + ppext, + runner, + helpers: Vec::new(), + strict: opts.dialect().strict, + stored_macros: HashMap::default(), + } + } + + /// Given a specification of an include file, load up the forms inside it and + /// return them (or an error if the file couldn't be read or wasn't a list). + pub fn process_include( + &mut self, + includes: &mut Vec, + include: &IncludeDesc, + ) -> Result>, CompileErr> { + let filename_and_content = self + .opts + .read_new_file(self.opts.filename(), decode_string(&include.name))?; + let content = filename_and_content.1; + let start_of_file = Srcloc::start(&decode_string(&include.name)); + + // Because we're also subsequently returning CompileErr later in the pipe, + // this needs an explicit err map. + let parsed: Vec> = parse_sexp(start_of_file.clone(), content.iter().copied()) + .err_into() + .and_then(|x| match x[0].proper_list() { + None => Err(CompileErr( + start_of_file, + "Includes should contain a list of forms".to_string(), + )), + Some(v) => Ok(v.iter().map(|x| Rc::new(x.clone())).collect()), + })?; + + if self.strict { + let mut result = Vec::new(); + for p in parsed.into_iter() { + let mut new_forms = self.process_pp_form(includes, p.clone())?; + result.append(&mut new_forms); + } + + Ok(result) + } else { + Ok(parsed) + } + } + + fn process_embed( + &mut self, + loc: Srcloc, + fname: &str, + kind: &IncludeProcessType, + constant_name: &[u8], + ) -> Result>, CompileErr> { + let mut allocator = Allocator::new(); + let run_to_compile_err = |e| match e { + RunFailure::RunExn(l, x) => CompileErr( + l, + format!("failed to convert compiled clvm to expression: throw ({x})"), + ), + RunFailure::RunErr(l, e) => CompileErr( + l, + format!("failed to convert compiled clvm to expression: {e}"), + ), + }; + + let (full_name, content) = self + .opts + .read_new_file(self.opts.filename(), fname.to_string())?; + let content = match kind { + IncludeProcessType::Bin => Rc::new(SExp::Atom(loc.clone(), content)), + IncludeProcessType::Hex => hex_to_modern_sexp( + &mut allocator, + &HashMap::new(), + loc.clone(), + &decode_string(&content), + ) + .map_err(run_to_compile_err)?, + IncludeProcessType::SExpression => { + let parsed = parse_sexp(Srcloc::start(&full_name), content.iter().copied()) + .map_err(|e| CompileErr(e.0, e.1))?; + if parsed.len() != 1 { + return Err(CompileErr(loc, format!("More than one form in {fname}"))); + } + + parsed[0].clone() + } + }; + + Ok(vec![compose_defconst(loc, constant_name, content)]) + } + + // Support using the preprocessor to collect dependencies recursively. + fn recurse_dependencies( + &mut self, + includes: &mut Vec, + desc: IncludeDesc, + ) -> Result<(), CompileErr> { + let name_string = decode_string(&desc.name); + if KNOWN_DIALECTS.contains_key(&name_string) { + return Ok(()); + } + + let (full_name, content) = self.opts.read_new_file(self.opts.filename(), name_string)?; + includes.push(IncludeDesc { + name: full_name.as_bytes().to_vec(), + ..desc + }); + + let parsed = parse_sexp(Srcloc::start(&full_name), content.iter().copied()) + .map_err(|e| CompileErr(e.0, e.1))?; + if parsed.is_empty() { + return Ok(()); + } + + let program_form = parsed[0].clone(); + if let Some(l) = program_form.proper_list() { + for elt in l.iter() { + self.process_pp_form(includes, Rc::new(elt.clone()))?; + } + } + + Ok(()) + } + + fn add_helper(&mut self, h: HelperForm) { + for i in 0..=self.helpers.len() { + if i == self.helpers.len() { + self.helpers.push(h); + break; + } else if self.helpers[i].name() == h.name() { + self.helpers[i] = h; + break; + } + } + } + + // Check for and apply preprocessor level macros. + // This is maximally permissive. + fn expand_macros( + &mut self, + body: Rc, + start: bool, + ) -> Result>, CompileErr> { + if let SExp::Cons(l, f, r) = body.borrow() { + // First expand inner macros. + let first_expanded = self.expand_macros(f.clone(), true)?; + let rest_expanded = self.expand_macros(r.clone(), false)?; + let new_self = match (first_expanded, rest_expanded) { + (None, None) => Some(body.clone()), + (Some(f), None) => Some(Rc::new(SExp::Cons(l.clone(), f, r.clone()))), + (None, Some(r)) => Some(Rc::new(SExp::Cons(l.clone(), f.clone(), r))), + (Some(f), Some(r)) => Some(Rc::new(SExp::Cons(l.clone(), f, r))), + }; + + if !start { + return Ok(new_self); + } + + if let Ok(NodeSel::Cons((_, name), args)) = NodeSel::Cons(Atom::Here(()), ThisNode) + .select_nodes(new_self.clone().unwrap_or_else(|| body.clone())) + { + let defmac_name = make_defmac_name(&name); + + // See if it's a form that calls one of our macros. + for m in self.helpers.iter() { + if let HelperForm::Defun(_, mdata) = &m { + // We record upfront macros + if mdata.name != defmac_name { + continue; + } + + // The name matched, try calling it. + + // Form argument env. + let mut macro_arg_env = HashMap::new(); + let args_borrowed: &SExp = args.borrow(); + create_argument_captures( + &mut macro_arg_env, + &ArgInputs::Whole(Rc::new(BodyForm::Quoted(args_borrowed.clone()))), + mdata.args.clone(), + )?; + + let mut allocator = Allocator::new(); + let compiled_program = if let Some(compiled_program) = + self.stored_macros.get(&mdata.name) + { + compiled_program.clone() + } else { + // as inline defuns because they're closest to that + // semantically. + let mut symbol_table = HashMap::new(); + let new_program = CompileForm { + loc: body.loc(), + args: mdata.args.clone(), + include_forms: vec![], + helpers: self.helpers.clone(), + exp: mdata.body.clone(), + ty: None, + }; + + let program_sexp = Rc::new(SExp::Cons( + body.loc(), + Rc::new(SExp::Atom(body.loc(), b"mod".to_vec())), + new_program.to_sexp(), + )); + + let compiled_program = self.opts.set_stdenv(false).compile_program( + &mut allocator, + self.runner.clone(), + program_sexp, + &mut symbol_table, + )?; + self.stored_macros + .insert(mdata.name.clone(), Rc::new(compiled_program.clone())); + Rc::new(compiled_program) + }; + + let ppext: &PreprocessorExtension = self.ppext.borrow(); + let res = clvm::run( + &mut allocator, + self.runner.clone(), + self.opts.prim_map(), + compiled_program, + args.clone(), + Some(ppext), + None, + ) + .map(nilize) + .map_err(CompileErr::from)?; + + if let Some(final_result) = self.expand_macros(res.clone(), true)? { + return Ok(Some(final_result)); + } else { + return Ok(Some(res)); + } + } + } + } + + return Ok(new_self); + } + + Ok(None) + } + + // If it's a defmac (preprocessor level macro), add it to the evaulator. + fn decode_macro(&mut self, definition: Rc) -> Result, CompileErr> { + if let Ok(NodeSel::Cons( + (defmac_loc, kw), + NodeSel::Cons((nl, name), NodeSel::Cons(args, body)), + )) = NodeSel::Cons( + Atom::Here(()), + NodeSel::Cons(Atom::Here(()), NodeSel::Cons(ThisNode, ThisNode)), + ) + .select_nodes(definition.clone()) + { + let is_defmac = kw == b"defmac"; + if is_defmac + || kw == b"defmacro" + || kw == b"defun" + || kw == b"defun-inline" + || kw == b"defconst" + || kw == b"defconstant" + { + if is_defmac { + let target_defun = Rc::new(SExp::Cons( + defmac_loc.clone(), + Rc::new(SExp::atom_from_string(defmac_loc, "defun")), + Rc::new(SExp::Cons( + nl.clone(), + Rc::new(SExp::Atom(nl, make_defmac_name(&name))), + Rc::new(SExp::Cons(args.loc(), args.clone(), body)), + )), + )); + if let Some(helpers) = compile_helperform(self.opts.clone(), target_defun)? { + for helper in helpers.new_helpers.iter() { + self.add_helper(rename_args_helperform(helper)?); + } + } else { + return Err(CompileErr( + definition.loc(), + "defmac found but couldn't be converted to function".to_string(), + )); + } + } else if let Some(helpers) = compile_helperform(self.opts.clone(), definition)? { + for helper in helpers.new_helpers.iter() { + self.add_helper(rename_args_helperform(helper)?); + } + } + } + } + + Ok(None) + } + + /* Expand include inline in forms */ + fn process_pp_form( + &mut self, + includes: &mut Vec, + unexpanded_body: Rc, + ) -> Result>, CompileErr> { + let body = self + .expand_macros(unexpanded_body.clone(), true)? + .unwrap_or_else(|| unexpanded_body.clone()); + // Support using the preprocessor to collect dependencies recursively. + let included: Option = body + .proper_list() + .map(|x| x.iter().map(|elt| elt.atomize()).collect()) + .map(|x: Vec| { + match &x[..] { + [SExp::Atom(kw, inc), SExp::Atom(nl, fname)] => { + if "include".as_bytes().to_vec() == *inc { + return Ok(Some(IncludeType::Basic( + IncludeDesc { + kw: kw.clone(), + nl: nl.clone(), + name: fname.clone(), + kind: None, + } + ))); + } + } + [SExp::Atom(kw, inc), SExp::QuotedString(nl, _, fname)] => { + if "include".as_bytes().to_vec() == *inc { + return Ok(Some(IncludeType::Basic( + IncludeDesc { + kw: kw.clone(), + nl: nl.clone(), + name: fname.clone(), + kind: None, + } + ))); + } + } + + [SExp::Atom(kl, embed_file), SExp::Atom(_, name), SExp::Atom(_, kind), SExp::Atom(nl, fname)] => { + if embed_file == b"embed-file" { + if kind == b"hex" { + return Ok(Some(IncludeType::Processed( + IncludeDesc { + kw: kl.clone(), + nl: nl.clone(), + kind: Some(IncludeProcessType::Hex), + name: fname.clone(), + }, + IncludeProcessType::Hex, + name.clone() + ))); + } else if kind == b"bin" { + return Ok(Some(IncludeType::Processed( + IncludeDesc { + kw: kl.clone(), + nl: nl.clone(), + kind: Some(IncludeProcessType::Bin), + name: fname.clone(), + }, + IncludeProcessType::Bin, + name.clone(), + ))); + } else if kind == b"sexp" { + return Ok(Some(IncludeType::Processed( + IncludeDesc { + kw: kl.clone(), + nl: nl.clone(), + kind: Some(IncludeProcessType::SExpression), + name: fname.clone(), + }, + IncludeProcessType::SExpression, + name.clone(), + ))); + } else { + return Err(CompileErr( + body.loc(), + format!("bad include kind in embed-file {body}") + )); + } + } + } + + [] => {} + + // Ensure that legal empty or atom expressions don't try include + _ => { + // Include is only allowed as a proper form. It's a keyword in + // this language. + if let SExp::Atom(_, inc) = &x[0] { + if "include".as_bytes().to_vec() == *inc { + return Err(CompileErr( + body.loc(), + format!("bad tail in include {body}"), + )); + } else { + // Try to pick up helperforms. + if let Some(()) = self.decode_macro(body.clone())? { + return Ok(None); + } + } + } + } + } + + Ok(None) + }) + .unwrap_or_else(|| Ok(None))?; + + if let Some(()) = self.decode_macro(body.clone())? { + Ok(vec![]) + } else if let Some(IncludeType::Basic(i)) = &included { + self.recurse_dependencies(includes, i.clone())?; + self.process_include(includes, i) + } else if let Some(IncludeType::Processed(f, kind, name)) = &included { + self.recurse_dependencies(includes, f.clone())?; + self.process_embed(body.loc(), &decode_string(&f.name), kind, name) + } else { + Ok(vec![body]) + } + } + + fn inject_std_macros(&mut self, body: Rc) -> SExp { + match body.proper_list() { + Some(v) => { + let include_form = Rc::new(SExp::Cons( + body.loc(), + Rc::new(SExp::atom_from_string(body.loc(), "include")), + Rc::new(SExp::Cons( + body.loc(), + Rc::new(SExp::quoted_from_string(body.loc(), "*macros*")), + Rc::new(SExp::Nil(body.loc())), + )), + )); + let mut v_clone: Vec> = v.iter().map(|x| Rc::new(x.clone())).collect(); + let include_copy: &SExp = include_form.borrow(); + v_clone.insert(0, Rc::new(include_copy.clone())); + enlist(body.loc(), &v_clone) + } + _ => { + let body_clone: &SExp = body.borrow(); + body_clone.clone() + } + } + } + + pub fn run( + &mut self, + includes: &mut Vec, + cmod: Rc, + ) -> Result>, CompileErr> { + let mut result = Vec::new(); + let mut tocompile = if self.opts.stdenv() { + let injected = self.inject_std_macros(cmod); + Rc::new(injected) + } else { + cmod + }; + + while let SExp::Cons(_, f, r) = tocompile.borrow() { + let mut lst = self.process_pp_form(includes, f.clone())?; + result.append(&mut lst); + tocompile = r.clone(); + } + + Ok(result) + } +} + +/// Run the preprocessor over this code, which at present just finds (include ...) +/// forms in the source and includes the content of in a combined list. If a file +/// can't be found via the directory list in CompilerOrs. +pub fn preprocess( + opts: Rc, + includes: &mut Vec, + cmod: Rc, +) -> Result>, CompileErr> { + let mut p = Preprocessor::new(opts); + p.run(includes, cmod) +} + +/// Visit all files used during compilation. +/// This reports a list of all files used while compiling the input file, via any +/// form that causes compilation to include another file. The file names are path +/// expanded based on the include path they were found in (from opts). +pub fn gather_dependencies( + mut opts: Rc, + real_input_path: &str, + file_content: &str, +) -> Result, CompileErr> { + let mut allocator = Allocator::new(); + + let assembled_input = assemble(&mut allocator, file_content) + .map_err(|e| CompileErr(Srcloc::start(real_input_path), e.1))?; + let dialect = detect_modern(&mut allocator, assembled_input); + opts = opts.set_stdenv(dialect.strict).set_dialect(dialect.clone()); + if let Some(stepping) = dialect.stepping { + opts = opts + .set_optimize(stepping > 22) + .set_frontend_opt(stepping > 21); + } + + let parsed = parse_sexp(Srcloc::start(real_input_path), file_content.bytes())?; + let program = frontend(opts, &parsed)?; + + let filtered_results: Vec = program + .include_forms + .into_iter() + .filter(|f| !f.name.starts_with(b"*")) + .collect(); + Ok(filtered_results) +} diff --git a/src/compiler/rename.rs b/src/compiler/rename.rs index aab5cf9ec..25435799d 100644 --- a/src/compiler/rename.rs +++ b/src/compiler/rename.rs @@ -5,7 +5,7 @@ use std::rc::Rc; use crate::compiler::codegen::toposort_assign_bindings; use crate::compiler::comptypes::{ map_m, map_m_reverse, Binding, BindingPattern, BodyForm, CompileErr, CompileForm, DefconstData, - DefmacData, DefunData, HelperForm, LetData, LetFormKind, + DefmacData, DefunData, HelperForm, LambdaData, LetData, LetFormKind, }; use crate::compiler::gensym::gensym; use crate::compiler::sexp::SExp; @@ -128,10 +128,8 @@ fn make_binding_unique(b: &Binding) -> InnerRenameList { InnerRenameList { bindings: single_name_map, from_wing: Binding { - loc: b.loc.clone(), - nl: b.nl.clone(), pattern: BindingPattern::Name(new_name), - body: b.body.clone(), + ..b.clone() }, } } @@ -147,10 +145,8 @@ fn make_binding_unique(b: &Binding) -> InnerRenameList { InnerRenameList { bindings: new_names, from_wing: Binding { - loc: b.loc.clone(), - nl: b.nl.clone(), pattern: BindingPattern::Complex(renamed_pattern), - body: b.body.clone(), + ..b.clone() }, } } @@ -164,7 +160,7 @@ pub fn rename_assign_bindings( ) -> Result<(BodyForm, Vec>), CompileErr> { // Order the bindings. let sorted_bindings = toposort_assign_bindings(l, bindings)?; - let mut renames = HashMap::new(); + let mut renames: HashMap, Vec> = HashMap::new(); // Process in reverse order so we rename from inner to outer. let bindings_to_rename: Vec> = sorted_bindings.to_vec(); let renamed_bindings = map_m_reverse( @@ -175,9 +171,11 @@ pub fn rename_assign_bindings( for (name, renamed) in new_names.iter() { renames.insert(name.clone(), renamed.clone()); } + + let renamed_in_body = Rc::new(rename_args_bodyform(b.body.borrow())?); Ok(Rc::new(Binding { pattern: BindingPattern::Complex(rename_in_cons(&renames, p.clone(), false)), - body: Rc::new(rename_in_bodyform(&renames, b.body.clone())?), + body: Rc::new(rename_in_bodyform(&renames, renamed_in_body)?), ..b.clone() })) } else { @@ -186,7 +184,8 @@ pub fn rename_assign_bindings( }, &bindings_to_rename, )?; - Ok((rename_in_bodyform(&renames, body)?, renamed_bindings)) + let new_body = Rc::new(rename_args_bodyform(body.borrow())?); + Ok((rename_in_bodyform(&renames, new_body)?, renamed_bindings)) } fn rename_in_bodyform( @@ -197,11 +196,10 @@ fn rename_in_bodyform( BodyForm::Let(kind, letdata) => { let new_bindings = map_m( &|b: &Rc| -> Result, CompileErr> { + let b_borrowed: &Binding = b.borrow(); Ok(Rc::new(Binding { - loc: b.loc(), - nl: b.nl.clone(), - pattern: b.pattern.clone(), body: Rc::new(rename_in_bodyform(namemap, b.body.clone())?), + ..b_borrowed.clone() })) }, &letdata.bindings, @@ -255,9 +253,26 @@ fn rename_in_bodyform( } BodyForm::Mod(l, prog) => Ok(BodyForm::Mod(l.clone(), prog.clone())), + // Rename lambda arguments down the lexical scope. + BodyForm::Lambda(ldata) => { + let renamed_capture_inputs = + Rc::new(rename_in_bodyform(namemap, ldata.captures.clone())?); + let renamed_capture_outputs = + rename_in_cons(namemap, ldata.capture_args.clone(), false); + let renamed_body = Rc::new(rename_args_bodyform(ldata.body.borrow())?); + let outer_renamed_body = rename_in_bodyform(namemap, renamed_body)?; + Ok(BodyForm::Lambda(Box::new(LambdaData { + captures: renamed_capture_inputs, + capture_args: renamed_capture_outputs, + body: Rc::new(outer_renamed_body), + ..*ldata.clone() + }))) + } } } +/// Given a set of sequential bindings, create a stack of let forms that have +/// the same meaning. This is used to propogate renaming. pub fn desugar_sequential_let_bindings( bindings: &[Rc], body: &BodyForm, @@ -368,6 +383,20 @@ fn rename_args_bodyform(b: &BodyForm) -> Result { Ok(BodyForm::Call(l.clone(), new_vs, new_tail)) } BodyForm::Mod(l, program) => Ok(BodyForm::Mod(l.clone(), program.clone())), + BodyForm::Lambda(ldata) => { + let mut own_args = HashMap::new(); + for (n, v) in invent_new_names_sexp(ldata.args.clone()).iter() { + own_args.insert(n.clone(), v.clone()); + } + let new_args = rename_in_cons(&own_args, ldata.args.clone(), false); + let new_body = rename_args_bodyform(ldata.body.borrow())?; + let renamed_with_own_args = rename_in_bodyform(&own_args, Rc::new(new_body))?; + Ok(BodyForm::Lambda(Box::new(LambdaData { + args: new_args, + body: Rc::new(renamed_with_own_args), + ..*ldata.clone() + }))) + } } } @@ -378,49 +407,29 @@ fn rename_in_helperform( match h { HelperForm::Deftype(_) => Ok(h.clone()), HelperForm::Defconstant(defc) => Ok(HelperForm::Defconstant(DefconstData { - loc: defc.loc.clone(), - kind: defc.kind.clone(), - name: defc.name.to_vec(), - nl: defc.nl.clone(), - kw: defc.kw.clone(), body: Rc::new(rename_in_bodyform(namemap, defc.body.clone())?), - ty: defc.ty.clone(), + ..defc.clone() })), HelperForm::Defmacro(mac) => Ok(HelperForm::Defmacro(DefmacData { - loc: mac.loc.clone(), - kw: mac.kw.clone(), - nl: mac.nl.clone(), - name: mac.name.to_vec(), - args: mac.args.clone(), program: Rc::new(rename_in_compileform(namemap, mac.program.clone())?), + ..mac.clone() })), HelperForm::Defun(inline, defun) => Ok(HelperForm::Defun( *inline, - DefunData { - loc: defun.loc.clone(), - kw: defun.kw.clone(), - nl: defun.nl.clone(), - name: defun.name.to_vec(), - orig_args: defun.orig_args.clone(), - args: defun.args.clone(), + Box::new(DefunData { body: Rc::new(rename_in_bodyform(namemap, defun.body.clone())?), - ty: defun.ty.clone(), - }, + ..*defun.clone() + }), )), } } -fn rename_args_helperform(h: &HelperForm) -> Result { +pub fn rename_args_helperform(h: &HelperForm) -> Result { match h { HelperForm::Deftype(_) => Ok(h.clone()), HelperForm::Defconstant(defc) => Ok(HelperForm::Defconstant(DefconstData { - loc: defc.loc.clone(), - kind: defc.kind.clone(), - nl: defc.nl.clone(), - kw: defc.kw.clone(), - name: defc.name.clone(), body: Rc::new(rename_args_bodyform(defc.body.borrow())?), - ty: defc.ty.clone(), + ..defc.clone() })), HelperForm::Defmacro(mac) => { let mut new_names: HashMap, Vec> = HashMap::new(); @@ -434,15 +443,12 @@ fn rename_args_helperform(h: &HelperForm) -> Result { let local_renamed_arg = rename_in_cons(&local_namemap, mac.args.clone(), true); let local_renamed_body = rename_args_compileform(mac.program.borrow())?; Ok(HelperForm::Defmacro(DefmacData { - loc: mac.loc.clone(), - kw: mac.kw.clone(), - nl: mac.nl.clone(), - name: mac.name.clone(), args: local_renamed_arg, program: Rc::new(rename_in_compileform( &local_namemap, Rc::new(local_renamed_body), )?), + ..mac.clone() })) } HelperForm::Defun(inline, defun) => { @@ -455,19 +461,14 @@ fn rename_args_helperform(h: &HelperForm) -> Result { let local_renamed_body = rename_args_bodyform(defun.body.borrow())?; Ok(HelperForm::Defun( *inline, - DefunData { - loc: defun.loc.clone(), - nl: defun.nl.clone(), - kw: defun.kw.clone(), - name: defun.name.clone(), - orig_args: defun.orig_args.clone(), + Box::new(DefunData { args: local_renamed_arg, body: Rc::new(rename_in_bodyform( &local_namemap, Rc::new(local_renamed_body), )?), - ty: defun.ty.clone(), - }, + ..*defun.clone() + }), )) } } @@ -477,29 +478,32 @@ fn rename_in_compileform( namemap: &HashMap, Vec>, c: Rc, ) -> Result { + let c_ref: &CompileForm = c.borrow(); Ok(CompileForm { - loc: c.loc.clone(), - args: c.args.clone(), - include_forms: c.include_forms.clone(), helpers: map_m(|x| rename_in_helperform(namemap, x), &c.helpers)?, exp: Rc::new(rename_in_bodyform(namemap, c.exp.clone())?), - ty: c.ty.clone(), + ..c_ref.clone() }) } +/// For all the HelperForms in a CompileForm, do renaming in them so that all +/// unique variable bindings in the program have unique names. pub fn rename_children_compileform(c: &CompileForm) -> Result { let local_renamed_helpers = map_m(&rename_args_helperform, &c.helpers)?; let local_renamed_body = rename_args_bodyform(c.exp.borrow())?; Ok(CompileForm { - loc: c.loc.clone(), - args: c.args.clone(), - include_forms: c.include_forms.clone(), helpers: local_renamed_helpers, exp: Rc::new(local_renamed_body), - ty: c.ty.clone(), + ..c.clone() }) } +/// Given a compileform, perform renaming in descendants so that every variable +/// name that lives in a different scope has a unique name. This allows +/// compilation to treat identical forms as equivalent and ensures that forms +/// that look the same but refer to different variables are different. It also +/// ensures that future tricky variable name uses decide on one binding from their +/// lexical scope. pub fn rename_args_compileform(c: &CompileForm) -> Result { let new_names = invent_new_names_sexp(c.args.clone()); let mut local_namemap = HashMap::new(); diff --git a/src/compiler/repl.rs b/src/compiler/repl.rs index 29f90d898..e8c228311 100644 --- a/src/compiler/repl.rs +++ b/src/compiler/repl.rs @@ -9,8 +9,8 @@ use clvm_rs::allocator::Allocator; use crate::classic::clvm_tools::stages::stage_0::TRunProgram; use crate::compiler::comptypes::{BodyForm, CompileErr, CompilerOpts}; -use crate::compiler::evaluate::{Evaluator, EVAL_STACK_LIMIT}; -use crate::compiler::frontend::{compile_helperform, frontend}; +use crate::compiler::evaluate::{first_of_alist, second_of_alist, Evaluator, EVAL_STACK_LIMIT}; +use crate::compiler::frontend::frontend; use crate::compiler::sexp::{parse_sexp, SExp}; use crate::compiler::srcloc::Srcloc; use crate::util::ErrInto; @@ -30,6 +30,8 @@ pub struct Repl { depth: i32, input_exp: String, + toplevel_forms: HashSet, + opts: Rc, evaluator: Evaluator, @@ -90,15 +92,7 @@ impl Repl { let loc = Srcloc::start(&opts.filename()); let mut toplevel_forms = HashSet::new(); - for w in [ - "defun", - "defun-inline", - "defconstant", - "defmacro", - "deftype", - ] - .iter() - { + for w in ["defun", "defun-inline", "defconstant", "defmacro"].iter() { toplevel_forms.insert(w.to_string()); } @@ -107,13 +101,6 @@ impl Repl { vec![ Rc::new(SExp::atom_from_string(loc.clone(), "if")), Rc::new(SExp::atom_from_string(loc.clone(), "list")), - Rc::new(SExp::atom_from_string(loc.clone(), "c*")), - Rc::new(SExp::atom_from_string(loc.clone(), "a*")), - Rc::new(SExp::atom_from_string(loc.clone(), "coerce")), - Rc::new(SExp::atom_from_string(loc.clone(), "explode")), - Rc::new(SExp::atom_from_string(loc.clone(), "bless")), - Rc::new(SExp::atom_from_string(loc.clone(), "lift")), - Rc::new(SExp::atom_from_string(loc.clone(), "unlift")), ], Rc::new(SExp::Cons( loc.clone(), @@ -138,6 +125,7 @@ impl Repl { Repl { depth: 0, input_exp: "".to_string(), + toplevel_forms, evaluator, opts, loc, @@ -195,14 +183,18 @@ impl Repl { if parsed_program.is_empty() { return Ok(None); } - - if let Ok(Some(hresult)) = - compile_helperform(self.opts.clone(), parsed_program[0].clone()) - { - for h in hresult.new_helpers.iter() { - self.evaluator.add_helper(h); - } - + let fa = first_of_alist(parsed_program[0].clone()); + let is_helper = fa + .map(|fa| self.toplevel_forms.contains(&fa.to_string())) + .unwrap_or_else(|_| false); + + if is_helper { + let prog0 = parsed_program[0].clone(); + let name = second_of_alist(prog0.clone())?; + let built_program = program_with_helper(vec![name], prog0); + let program = frontend(self.opts.clone(), &[built_program])?; + self.evaluator + .add_helper(&program.helpers[program.helpers.len() - 1]); Ok(Some(Rc::new(BodyForm::Quoted(SExp::Nil(self.loc.clone()))))) } else { frontend(self.opts.clone(), &parsed_program) diff --git a/src/compiler/runtypes.rs b/src/compiler/runtypes.rs index 720822337..526f9afef 100644 --- a/src/compiler/runtypes.rs +++ b/src/compiler/runtypes.rs @@ -1,6 +1,7 @@ use std::fmt::Display; use std::rc::Rc; +use crate::compiler::comptypes::CompileErr; use crate::compiler::sexp::SExp; use crate::compiler::srcloc::Srcloc; @@ -27,3 +28,20 @@ impl Display for RunFailure { Ok(()) } } + +impl From for CompileErr { + fn from(item: RunFailure) -> Self { + match item { + RunFailure::RunExn(l, s) => CompileErr(l.clone(), format!("Runtime exception: {s}")), + RunFailure::RunErr(l, s) => CompileErr(l.clone(), format!("Runtime error: {s}")), + } + } +} + +impl From for RunFailure { + fn from(e: CompileErr) -> Self { + match e { + CompileErr(l, e) => RunFailure::RunErr(l, e), + } + } +} diff --git a/src/compiler/sexp.rs b/src/compiler/sexp.rs index 81fb01e39..0edea62dc 100644 --- a/src/compiler/sexp.rs +++ b/src/compiler/sexp.rs @@ -9,7 +9,6 @@ use std::borrow::Borrow; use std::fmt::Display; use std::hash::{Hash, Hasher}; use std::rc::Rc; -use std::string::String; use binascii::{bin2hex, hex2bin}; use num_traits::{zero, Num}; @@ -41,9 +40,11 @@ pub enum SExp { /// content of the list, but may not depending on the construction of the /// list. Cons(Srcloc, Rc, Rc), - /// + /// Contains an integer which is presented normalized. Integer(Srcloc, Number), + /// Contains a quoted string or hex constant to reproduce exactly. QuotedString(Srcloc, u8, Vec), + /// Contains an identifier like atom. Atom(Srcloc, Vec), } @@ -136,7 +137,7 @@ impl Display for SExp { formatter.write_str(&v.to_string())?; } SExp::QuotedString(_, q, s) => { - if printable(s) { + if printable(s, true) { formatter.write_str("\"")?; formatter.write_str(&escape_quote(*q, s))?; formatter.write_str("\"")?; @@ -153,7 +154,7 @@ impl Display for SExp { SExp::Atom(l, a) => { if a.is_empty() { formatter.write_str("()")?; - } else if printable(a) { + } else if printable(a, false) { formatter.write_str(&decode_string(a))?; } else { formatter @@ -204,14 +205,15 @@ enum SExpParseState { Bareword(Srcloc, Vec), //srcloc contains the file, line, column and length for the captured form QuotedText(Srcloc, u8, Vec), QuotedEscaped(Srcloc, u8, Vec), - OpenList(Srcloc), - ParsingList(Srcloc, Rc, Vec>), + OpenList(Srcloc, bool), + ParsingList(Srcloc, Rc, Vec>, bool), // Rc is for the inner state of the list, bool is is_structured TermList( Srcloc, Option>, // this is the second value in the dot expression Rc, // used for inner parsing Vec>, // list content ), + StartStructuredList(Srcloc), } #[derive(Debug, PartialEq, Eq)] @@ -272,10 +274,10 @@ fn normalize_int(v: Vec, base: u32) -> Number { fn from_hex(l: Srcloc, v: &[u8]) -> SExp { let mut result = vec![0; (v.len() - 2) / 2]; hex2bin(&v[2..], &mut result).expect("should convert from hex"); - SExp::QuotedString(l, b'"', result) + SExp::QuotedString(l, b'x', result) } -pub fn make_atom(l: Srcloc, v: Vec) -> SExp { +fn make_atom(l: Srcloc, v: Vec) -> SExp { let alen = v.len(); if alen > 1 && v[0] == b'#' { // Search prims for appropriate primitive @@ -356,14 +358,12 @@ pub fn decode_string(v: &[u8]) -> String { return String::from_utf8_lossy(v).as_ref().to_string(); } -fn printable(a: &[u8]) -> bool { - for ch in a.iter() { - if (*ch as char).is_control() || !(*ch as char).is_ascii() { - return false; - } - } - - true +pub fn printable(a: &[u8], quoted: bool) -> bool { + !a.iter().any(|ch| { + (*ch as char).is_control() + || !(*ch as char).is_ascii() + || (!quoted && ch.is_ascii_whitespace()) + }) } impl SExp { @@ -490,7 +490,7 @@ impl SExp { (SExp::Cons(_, r, s), SExp::Cons(_, t, u)) => r.equal_to(t) && s.equal_to(u), (SExp::Cons(_, _, _), _) => false, (_, SExp::Cons(_, _, _)) => false, - (SExp::Integer(_, _), b) => self.atomize() == *b, + (SExp::Integer(l, a), b) => SExp::Atom(l.clone(), u8_from_number(a.clone())) == *b, (SExp::QuotedString(l, _, a), b) => SExp::Atom(l.clone(), a.clone()) == *b, (SExp::Nil(l), b) => SExp::Atom(l.clone(), Vec::new()) == *b, (SExp::Atom(_, _), SExp::Integer(_, _)) => other == self, @@ -535,17 +535,34 @@ impl SExp { } } +fn restructure_list(mut this_list: Vec>, srcloc: Srcloc) -> Rc { + // Check if the vector is empty + if this_list.len() == 1 { + return Rc::clone(&this_list[0]); + } + if this_list.is_empty() { + return Rc::new(SExp::Nil(srcloc.clone())); + } + // Remove and get the middle element as the root + let mid_index = this_list.len() / 2; + let left_subtree = restructure_list(this_list.drain(..mid_index).collect(), srcloc.clone()); + let right_subtree = restructure_list(this_list, srcloc.clone()); + + Rc::new(make_cons(left_subtree, right_subtree)) +} + fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) -> SExpParseResult { // switch on our state match current_state { SExpParseState::Empty => match this_char as char { // we are not currently in a list - '(' => resume(SExpParseState::OpenList(loc)), // move to OpenList state - '\n' => resume(SExpParseState::Empty), // new line, same state + '(' => resume(SExpParseState::OpenList(loc, false)), // move to OpenList state + '\n' => resume(SExpParseState::Empty), // new line, same state ';' => resume(SExpParseState::CommentText), ')' => error(loc, "Too many close parens"), '"' => resume(SExpParseState::QuotedText(loc, b'"', Vec::new())), // match on " '\'' => resume(SExpParseState::QuotedText(loc, b'\'', Vec::new())), // match on ' + '#' => resume(SExpParseState::StartStructuredList(loc)), // initiating a structured list ch => { if char::is_whitespace(ch) { resume(SExpParseState::Empty) @@ -601,7 +618,7 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - tcopy.push(this_char); resume(SExpParseState::QuotedText(srcloc.clone(), *term, tcopy)) } - SExpParseState::OpenList(srcloc) => match this_char as char { + SExpParseState::OpenList(srcloc, is_structured) => match this_char as char { // we are beginning a new list ')' => emit(Rc::new(SExp::Nil(srcloc.ext(&loc))), SExpParseState::Empty), // create a Nil object '.' => error(loc, "Dot can't appear directly after begin paren"), @@ -612,44 +629,69 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - srcloc.ext(&loc), Rc::new(current_state), // captured state from our pretend empty state vec![o], + *is_structured, )), SExpParseResult::Resume(current_state) => resume(SExpParseState::ParsingList( // we're still reading the object, resume processing srcloc.ext(&loc), Rc::new(current_state), // captured state from our pretend empty state Vec::new(), + *is_structured, )), SExpParseResult::Error(l, e) => SExpParseResult::Error(l, e), // propagate error }, }, // We are in the middle of a list currently - SExpParseState::ParsingList(srcloc, pp, list_content) => { + SExpParseState::ParsingList(srcloc, pp, list_content, is_structured) => { // pp is the captured inside-list state we received from OpenList - match (this_char as char, pp.borrow()) { - ('.', SExpParseState::Empty) => resume(SExpParseState::TermList( + match (this_char as char, pp.borrow(), is_structured) { + ('.', SExpParseState::Empty, false) => resume(SExpParseState::TermList( // dot notation showing cons cell srcloc.ext(&loc), None, Rc::new(SExpParseState::Empty), // nested state is empty list_content.to_vec(), )), - (')', SExpParseState::Empty) => emit( - // close list and emit it upwards as a complete entity - Rc::new(enlist(srcloc.clone(), list_content)), - SExpParseState::Empty, - ), - (')', SExpParseState::Bareword(l, t)) => { + ('.', SExpParseState::Empty, true) => { + error(loc, "Dot expressions disallowed in structured lists") + } + (')', SExpParseState::Empty, _) => { + if *is_structured { + emit( + // close list and emit it upwards as a complete entity + restructure_list(list_content.to_vec(), srcloc.clone()), + SExpParseState::Empty, + ) + } else { + emit( + // close list and emit it upwards as a complete entity + Rc::new(enlist(srcloc.clone(), list_content)), + SExpParseState::Empty, + ) + } + } + (')', SExpParseState::Bareword(l, t), _) => { // you've reached the end of the word AND the end of the list, close list and emit upwards + // TODO: check bool and rearrange here let parsed_atom = make_atom(l.clone(), t.to_vec()); let mut updated_list = list_content.to_vec(); updated_list.push(Rc::new(parsed_atom)); - emit( - Rc::new(enlist(srcloc.clone(), &updated_list)), - SExpParseState::Empty, - ) + if *is_structured { + emit( + // close list and emit it upwards as a complete entity + restructure_list(updated_list, srcloc.clone()), + SExpParseState::Empty, + ) + } else { + emit( + // close list and emit it upwards as a complete entity + Rc::new(enlist(srcloc.clone(), &updated_list)), + SExpParseState::Empty, + ) + } } // analyze this character using the mock "inner state" stored in pp - (_, _) => match parse_sexp_step(loc.clone(), pp.borrow(), this_char) { + (_, _, _) => match parse_sexp_step(loc.clone(), pp.borrow(), this_char) { // SExpParseResult::Emit(o, current_state) => { // add result of parse_sexp_step to our list @@ -659,6 +701,7 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - srcloc.ext(&loc), Rc::new(current_state), list_copy, + *is_structured, ); resume(result) } @@ -667,6 +710,7 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - srcloc.ext(&loc), Rc::new(rp), // store the returned state from parse_sexp_step in pp list_content.to_vec(), + *is_structured, )), SExpParseResult::Error(l, e) => SExpParseResult::Error(l, e), // propagate error upwards }, @@ -779,6 +823,24 @@ fn parse_sexp_step(loc: Srcloc, current_state: &SExpParseState, this_char: u8) - }, } } + SExpParseState::StartStructuredList(l) => { + let new_srcloc = l.ext(&loc); + match this_char as char { + '(' => resume(SExpParseState::ParsingList( + // go into a ParsingList + new_srcloc, + Rc::new(SExpParseState::Empty), // we have no inner state + Vec::new(), + true, // note that this is a special StructuredList to be processed later + )), + _ => parse_sexp_step( + // if we don't see a '(' then process it as if the preceding '#' was part of a bareword + loc.clone(), + &SExpParseState::Bareword(loc, vec![b'#']), + this_char, + ), + } + } // SExpParseState::StartStructuredList(_) => error(loc, "Missing srcloc"), } } @@ -837,9 +899,14 @@ impl ParsePartialResult { SExpParseState::QuotedEscaped(l, _, _) => { Err((l, "unterminated quoted string with escape".to_string())) } - SExpParseState::OpenList(l) => Err((l, "Unterminated list (empty)".to_string())), - SExpParseState::ParsingList(l, _, _) => Err((l, "Unterminated mid list".to_string())), + SExpParseState::OpenList(l, _) => Err((l, "Unterminated list (empty)".to_string())), + SExpParseState::ParsingList(l, _, _, _) => { + Err((l, "Unterminated mid list".to_string())) + } SExpParseState::TermList(l, _, _, _) => Err((l, "Unterminated tail list".to_string())), + SExpParseState::StartStructuredList(l) => { + Err((l, "Unclosed structured list".to_string())) + } } } } @@ -980,3 +1047,175 @@ fn test_tricky_parser_tail_03() { ))]) ); } + +// This is a trait that generates a haskell-like ad-hoc type from the user's +// construction of NodeSel and ThisNode. +// the result is transformed into a NodeSel tree of NodePtr if it can be. +// The type of the result is an ad-hoc shape derived from the shape of the +// original request. +// +// This mirrors code in src/classic/clvm/sexp.rs +// +// It's a nicer way of modelling matches that will overtake bespoke code for a lot +// of things. +#[derive(Debug, Clone)] +pub enum NodeSel { + Cons(T, U), +} + +#[derive(Debug, Clone)] +pub enum First { + Here(T), +} + +#[derive(Debug, Clone)] +pub enum Rest { + Here(T), +} + +#[derive(Debug, Clone)] +pub struct ThisNode; + +pub enum Atom { + Here(T), +} + +pub enum AtomValue { + Here(T), +} + +pub trait SelectNode { + fn select_nodes(&self, s: Rc) -> Result; +} + +impl SelectNode, E> for ThisNode { + fn select_nodes(&self, s: Rc) -> Result, E> { + Ok(s) + } +} + +impl SelectNode<(Srcloc, Vec), (Srcloc, String)> for Atom<()> { + fn select_nodes(&self, s: Rc) -> Result<(Srcloc, Vec), (Srcloc, String)> { + if let SExp::Atom(loc, name) = s.borrow() { + return Ok((loc.clone(), name.clone())); + } + + Err((s.loc(), "Not an atom".to_string())) + } +} + +impl SelectNode for Atom<&str> { + fn select_nodes(&self, s: Rc) -> Result { + let Atom::Here(name) = self; + if let Ok((l, n)) = Atom::Here(()).select_nodes(s.clone()) { + if n == name.as_bytes() { + return Ok(l); + } + } + + Err((s.loc(), format!("Not an atom named {name}"))) + } +} + +impl SelectNode for AtomValue<&[u8; N]> { + fn select_nodes(&self, s: Rc) -> Result { + let AtomValue::Here(name) = self; + match s.borrow() { + SExp::Nil(l) => { + if name.is_empty() { + return Ok(l.clone()); + } + } + SExp::Atom(l, n) => { + if n == name { + return Ok(l.clone()); + } + } + SExp::QuotedString(l, _, n) => { + if n == name { + return Ok(l.clone()); + } + } + SExp::Integer(l, i) => { + if &u8_from_number(i.clone()) == name { + return Ok(l.clone()); + } + } + _ => {} + } + + Err((s.loc(), format!("Not an atom with content {name:?}"))) + } +} + +impl SelectNode<(Srcloc, Vec), (Srcloc, String)> for AtomValue<()> { + fn select_nodes(&self, s: Rc) -> Result<(Srcloc, Vec), (Srcloc, String)> { + let AtomValue::Here(name) = self; + match s.borrow() { + SExp::Nil(l) => { + return Ok((l.clone(), vec![])); + } + SExp::Atom(l, n) => { + return Ok((l.clone(), n.clone())); + } + SExp::QuotedString(l, _, n) => { + return Ok((l.clone(), n.clone())); + } + SExp::Integer(l, i) => { + let u8_vec = u8_from_number(i.clone()); + return Ok((l.clone(), u8_vec)); + } + _ => {} + } + + Err((s.loc(), format!("Not an atom with content {name:?}"))) + } +} + +impl SelectNode<(), E> for () { + fn select_nodes(&self, _n: Rc) -> Result<(), E> { + Ok(()) + } +} + +impl SelectNode, E> for First +where + R: SelectNode + Clone, + E: From<(Srcloc, String)>, +{ + fn select_nodes(&self, s: Rc) -> Result, E> { + let First::Here(f) = &self; + let NodeSel::Cons(first, ()) = NodeSel::Cons(f.clone(), ()).select_nodes(s)?; + Ok(First::Here(first)) + } +} + +impl SelectNode, E> for Rest +where + R: SelectNode + Clone, + E: From<(Srcloc, String)>, +{ + fn select_nodes(&self, s: Rc) -> Result, E> { + let Rest::Here(f) = &self; + let NodeSel::Cons((), rest) = NodeSel::Cons((), f.clone()).select_nodes(s)?; + Ok(Rest::Here(rest)) + } +} + +impl SelectNode, E> for NodeSel +where + R: SelectNode, + S: SelectNode, + E: From<(Srcloc, String)>, +{ + fn select_nodes(&self, s: Rc) -> Result, E> { + let NodeSel::Cons(my_left, my_right) = &self; + if let SExp::Cons(_, l, r) = s.borrow() { + let first = my_left.select_nodes(l.clone())?; + let rest = my_right.select_nodes(r.clone())?; + Ok(NodeSel::Cons(first, rest)) + } else { + Err(E::from((s.loc(), "not a cons".to_string()))) + } + } +} diff --git a/src/compiler/typechia.rs b/src/compiler/typechia.rs index a9be70095..0ca45741e 100644 --- a/src/compiler/typechia.rs +++ b/src/compiler/typechia.rs @@ -12,9 +12,13 @@ use crate::classic::clvm::__type_compatibility__::{bi_one, bi_zero}; use crate::classic::clvm_tools::stages::stage_0::DefaultProgramRunner; use crate::compiler::compiler::{is_at_capture, DefaultCompilerOpts}; -use crate::compiler::comptypes::{BodyForm, CompileErr, CompileForm, HelperForm}; +use crate::compiler::comptypes::{ + BodyForm, CompileErr, CompileForm, CompilerOpts, HelperForm, LetData, LetFormKind, +}; use crate::compiler::evaluate::{build_argument_captures, dequote, Evaluator, EVAL_STACK_LIMIT}; use crate::compiler::frontend::frontend; +use crate::compiler::gensym::gensym; +use crate::compiler::lambda::form_lambda_bindings; use crate::compiler::sexp::{decode_string, SExp}; use crate::compiler::srcloc::{HasLoc, Srcloc}; use crate::compiler::typecheck::TheoryToSExp; @@ -526,6 +530,7 @@ fn handle_macro( form: Rc, loc: Srcloc, provided_args: &[Rc], + tail: Option>, ) -> Result { // It is a macro, we need to interpret it in our way: // We'll compile and run the code itself on a @@ -558,7 +563,7 @@ fn handle_macro( ev.add_helper(h); } let mut allocator = Allocator::new(); - let arg_env = build_argument_captures(&loc, &call_args, None, form.args.clone())?; + let arg_env = build_argument_captures(&loc, &call_args, tail, form.args.clone())?; let result = ev.shrink_bodyform( &mut allocator, Rc::new(SExp::Nil(loc.clone())), @@ -578,8 +583,8 @@ fn handle_macro( )?; match dequote(loc.clone(), exp_result) { Ok(dequoted) => { - let last_reparse = frontend(opts, &[dequoted])?; - let final_res = chialisp_to_expr(program, form_args, last_reparse.exp)?; + let last_reparse = frontend(opts.clone(), &[dequoted])?; + let final_res = chialisp_to_expr(opts, program, form_args, last_reparse.exp)?; Ok(final_res) } Err(_) => { @@ -593,6 +598,7 @@ fn handle_macro( } fn chialisp_to_expr( + opts: Rc, program: &CompileForm, form_args: Rc, body: Rc, @@ -613,12 +619,14 @@ fn chialisp_to_expr( Rc::new(Expr::EApp( Rc::new(Expr::EVar(Var("c^".to_string(), l.clone()))), Rc::new(chialisp_to_expr( + opts.clone(), program, form_args.clone(), Rc::new(BodyForm::Quoted(a_borrowed.clone())), )?), )), Rc::new(chialisp_to_expr( + opts.clone(), program, form_args, Rc::new(BodyForm::Quoted(b_borrowed.clone())), @@ -637,7 +645,8 @@ fn chialisp_to_expr( let file_borrowed: &String = letdata.loc.file.borrow(); let opts = Rc::new(DefaultCompilerOpts::new(file_borrowed)); let runner = Rc::new(DefaultProgramRunner::new()); - let evaluator = Evaluator::new(opts, runner, program.helpers.clone()).disable_calls(); + let evaluator = + Evaluator::new(opts.clone(), runner, program.helpers.clone()).disable_calls(); let beta_reduced = evaluator.shrink_bodyform( &mut allocator, Rc::new(SExp::Nil(letdata.loc.clone())), @@ -646,18 +655,19 @@ fn chialisp_to_expr( false, Some(EVAL_STACK_LIMIT), )?; - chialisp_to_expr(program, form_args, beta_reduced) + chialisp_to_expr(opts, program, form_args, beta_reduced) } BodyForm::Call(l, lst, tail) => { let mut arg_expr = if let Some(t) = tail.as_ref() { - chialisp_to_expr(program, form_args.clone(), t.clone())? + chialisp_to_expr(opts.clone(), program, form_args.clone(), t.clone())? } else { Expr::EUnit(l.clone()) }; - for i_rev in 0..lst.len() - 1 { - let i = lst.len() - i_rev - 1; - let new_expr = chialisp_to_expr(program, form_args.clone(), lst[i].clone())?; + for (_i, e) in lst.iter().enumerate().rev().take(lst.len() - 1) { + let new_expr = + chialisp_to_expr(opts.clone(), program, form_args.clone(), e.clone())?; + arg_expr = Expr::EApp( Rc::new(Expr::EApp( Rc::new(Expr::EVar(Var("c^".to_string(), l.clone()))), @@ -678,6 +688,7 @@ fn chialisp_to_expr( defm.program.clone(), body.loc(), lst, + tail.clone(), ); } } @@ -686,7 +697,7 @@ fn chialisp_to_expr( if n1 == &vec![b'c', b'o', b'm'] { // Handle com // Rewrite (com X) as (com^ (lambda x X)) - let inner = chialisp_to_expr(program, form_args, lst[1].clone())?; + let inner = chialisp_to_expr(opts, program, form_args, lst[1].clone())?; let var = fresh_var(l.clone()); return Ok(Expr::EApp( Rc::new(Expr::EVar(Var("com^".to_string(), l.clone()))), @@ -695,13 +706,63 @@ fn chialisp_to_expr( } } + // Recognize an operator expressed as a numeric atom or integer. + if let BodyForm::Value(v) = &lst[0].borrow() { + for (op_name, op_value) in opts.prim_map().iter() { + let op_borrowed: &SExp = op_value.borrow(); + if op_borrowed == v { + return Ok(Expr::EApp( + Rc::new(Expr::EVar(Var(decode_string(op_name), v.loc()))), + Rc::new(arg_expr), + )); + } + } + } + // Just treat it as an expression... If it's a function we defined, // then it's in the environment. Ok(Expr::EApp( - Rc::new(chialisp_to_expr(program, form_args, lst[0].clone())?), + Rc::new(chialisp_to_expr(opts, program, form_args, lst[0].clone())?), Rc::new(arg_expr), )) } + BodyForm::Lambda(l) => { + let lambda_arg_name = gensym(b"lambda_arg".to_vec()); + let lambda_evar = Var(decode_string(&lambda_arg_name), l.loc.clone()); + let lambda_bindings = form_lambda_bindings(&lambda_arg_name, l.args.clone()); + let lambda_body_let = BodyForm::Let( + LetFormKind::Parallel, + Box::new(LetData { + loc: l.loc.clone(), + kw: None, + bindings: lambda_bindings, + body: l.body.clone(), + inline_hint: None, + }), + ); + + // Produce a type side lambda with a single argument (all clvm + // functions are typewise unary) and a let form inside it which + // destructures the argument. Closures are assumed so it should + // be fine not to repeat bindings for the other variables in scope. + // + // We can use com^ to transform it into an Exec, which is the + // right type for apply. Do that by constructing an invocation. + let lambda_expr = Expr::EApp( + Rc::new(Expr::EVar(Var("com^".to_string(), l.loc.clone()))), + Rc::new(Expr::EAbs( + lambda_evar, + Rc::new(chialisp_to_expr( + opts, + program, + form_args, + Rc::new(lambda_body_let), + )?), + )), + ); + + Ok(lambda_expr) + } _ => Err(CompileErr( body.loc(), format!("not sure how to handle {body:?} yet"), @@ -743,7 +804,11 @@ fn handle_function_type( // Given a compileform, typecheck impl Context { - pub fn typecheck_chialisp_program(&self, comp: &CompileForm) -> Result { + pub fn typecheck_chialisp_program( + &self, + opts: Rc, + comp: &CompileForm, + ) -> Result { let mut context = self.clone(); // Extract type definitions @@ -805,6 +870,7 @@ impl Context { &context_with_args, &Expr::EAnno( Rc::new(chialisp_to_expr( + opts.clone(), comp, defun.args.clone(), defun.body.clone(), @@ -819,7 +885,7 @@ impl Context { let ty = type_of_defun(comp.exp.loc(), &comp.ty); let (context_with_args, result_ty) = handle_function_type(&context, comp.exp.loc(), comp.args.clone(), &ty)?; - let clexpr = chialisp_to_expr(comp, comp.args.clone(), comp.exp.clone())?; + let clexpr = chialisp_to_expr(opts, comp, comp.args.clone(), comp.exp.clone())?; typecheck_chialisp_body_with_context( &context_with_args, &Expr::EAnno(Rc::new(clexpr), result_ty), diff --git a/src/py/api.rs b/src/py/api.rs index d2c4900e1..d3202f1d1 100644 --- a/src/py/api.rs +++ b/src/py/api.rs @@ -4,8 +4,9 @@ // re: https://github.com/rust-lang/rust-clippy/issues/8971 use pyo3::exceptions::PyException; use pyo3::prelude::*; -use pyo3::types::{PyDict, PyString, PyTuple}; +use pyo3::types::{PyBool, PyDict, PyString, PyTuple}; +use std::cmp::Ordering; use std::collections::{BTreeMap, HashMap}; use std::fs; use std::rc::Rc; @@ -14,11 +15,15 @@ use std::sync::mpsc::{Receiver, Sender}; use std::thread; use clvm_rs::allocator::Allocator; +use clvm_rs::serde::node_to_bytes; -use crate::classic::clvm::__type_compatibility__::{Bytes, Stream, UnvalidatedBytesFromType}; +use crate::classic::clvm::__type_compatibility__::{ + Bytes, BytesFromType, Stream, UnvalidatedBytesFromType, +}; use crate::classic::clvm::serialize::sexp_to_stream; use crate::classic::clvm_tools::clvmc; use crate::classic::clvm_tools::cmds; +use crate::classic::clvm_tools::log; use crate::classic::clvm_tools::stages::stage_0::DefaultProgramRunner; use crate::compiler::cldb::{ hex_to_modern_sexp, CldbOverrideBespokeCode, CldbRun, CldbRunEnv, CldbSingleBespokeOverride, @@ -34,7 +39,7 @@ use crate::compiler::runtypes::RunFailure; use crate::compiler::sexp::{decode_string, SExp}; use crate::compiler::srcloc::Srcloc; -use crate::util::version; +use crate::util::{gentle_overwrite, version}; use crate::py::pyval::{clvm_value_to_python, python_value_to_clvm}; @@ -49,79 +54,159 @@ fn get_version() -> PyResult { Ok(version()) } -#[pyfunction(arg3 = "[]", arg4 = "None")] +enum CompileClvmSource<'a> { + SourcePath(&'a PyAny), + SourceCode(String, String), +} + +enum CompileClvmAction { + CheckDependencies, + CompileCode(Option), +} + +fn get_source_from_input(input_code: CompileClvmSource) -> PyResult<(String, String)> { + match input_code { + CompileClvmSource::SourcePath(input_path) => { + let has_atom = input_path.hasattr("atom")?; + let has_pair = input_path.hasattr("pair")?; + + let real_input_path = if has_atom { + input_path.getattr("atom").and_then(|x| x.str()) + } else if has_pair { + input_path + .getattr("pair") + .and_then(|x| x.get_item(0)) + .and_then(|x| x.str()) + } else { + input_path.extract() + }?; + + let mut path_string = real_input_path.to_string(); + + if !std::path::Path::new(&path_string).exists() && !path_string.ends_with(".clvm") { + path_string += ".clvm"; + } + + let file_data = fs::read_to_string(&path_string) + .map_err(|e| PyException::new_err(format!("error reading {path_string}: {e:?}")))?; + Ok((path_string, file_data)) + } + CompileClvmSource::SourceCode(name, code) => Ok((name.clone(), code.clone())), + } +} + +fn run_clvm_compilation( + input_code: CompileClvmSource, + action: CompileClvmAction, + search_paths: Vec, + export_symbols: Option, +) -> PyResult { + // Resolve the input, get the indicated path and content. + let (path_string, file_content) = get_source_from_input(input_code)?; + + // Load up our compiler opts. + let def_opts: Rc = Rc::new(DefaultCompilerOpts::new(&path_string)); + let opts = def_opts.set_search_paths(&search_paths); + + match action { + CompileClvmAction::CompileCode(output) => { + let mut allocator = Allocator::new(); + let mut symbols = HashMap::new(); + + // Output is a program represented as clvm data in allocator. + let clvm_result = clvmc::compile_clvm_text( + &mut allocator, + opts.clone(), + &mut symbols, + &file_content, + &path_string, + true, + ) + .map_err(|e| CompError::new_err(e.format(&allocator, opts)))?; + + // Get the text representation, which will go either to the output file + // or result. + let mut hex_text = Bytes::new(Some(BytesFromType::Raw(node_to_bytes( + &allocator, + clvm_result, + )?))) + .hex(); + let compiled = if let Some(output_file) = output { + // Write output with eol. + hex_text += "\n"; + gentle_overwrite(&path_string, &output_file, &hex_text) + .map_err(PyException::new_err)?; + output_file.to_string() + } else { + hex_text + }; + + // Produce compiled output according to whether output with symbols + // or just the standard result is required. + Python::with_gil(|py| { + if export_symbols == Some(true) { + let mut result_dict = HashMap::new(); + result_dict.insert("output".to_string(), compiled.into_py(py)); + result_dict.insert("symbols".to_string(), symbols.into_py(py)); + Ok(result_dict.into_py(py)) + } else { + Ok(compiled.into_py(py)) + } + }) + } + CompileClvmAction::CheckDependencies => { + // Produce dependency results. + let result_deps: Vec = + gather_dependencies(opts, &path_string.to_string(), &file_content) + .map_err(|e| CompError::new_err(format!("{}: {}", e.0, e.1))) + .map(|rlist| rlist.iter().map(|i| decode_string(&i.name)).collect())?; + + // Return all visited files. + Python::with_gil(|py| Ok(result_deps.into_py(py))) + } + } +} + +#[pyfunction] +#[pyo3(signature = (input_path, output_path, search_paths = Vec::new(), export_symbols = None))] fn compile_clvm( input_path: &PyAny, output_path: String, search_paths: Vec, export_symbols: Option, ) -> PyResult { - let has_atom = input_path.hasattr("atom")?; - let has_pair = input_path.hasattr("pair")?; - - let real_input_path = if has_atom { - input_path.getattr("atom").and_then(|x| x.str()) - } else if has_pair { - input_path - .getattr("pair") - .and_then(|x| x.get_item(0)) - .and_then(|x| x.str()) - } else { - input_path.extract() - }?; - - let mut path_string = real_input_path.to_string(); - - if !std::path::Path::new(&path_string).exists() && !path_string.ends_with(".clvm") { - path_string += ".clvm"; - }; + run_clvm_compilation( + CompileClvmSource::SourcePath(input_path), + CompileClvmAction::CompileCode(Some(output_path)), + search_paths, + export_symbols, + ) +} - let mut symbols = HashMap::new(); - let compiled = clvmc::compile_clvm(&path_string, &output_path, &search_paths, &mut symbols) - .map_err(PyException::new_err)?; - - Python::with_gil(|py| { - if export_symbols == Some(true) { - let mut result_dict = HashMap::new(); - result_dict.insert("output".to_string(), compiled.into_py(py)); - result_dict.insert("symbols".to_string(), symbols.into_py(py)); - Ok(result_dict.into_py(py)) - } else { - Ok(compiled.into_py(py)) - } - }) +#[pyfunction] +#[pyo3(signature = (source, search_paths = Vec::new(), export_symbols = None))] +fn compile( + source: String, + search_paths: Vec, + export_symbols: Option, +) -> PyResult { + run_clvm_compilation( + CompileClvmSource::SourceCode("*inline*".to_string(), source), + CompileClvmAction::CompileCode(None), + search_paths, + export_symbols, + ) } -#[pyfunction(arg2 = "[]")] +#[pyfunction] +#[pyo3(signature = (input_path, search_paths=Vec::new()))] fn check_dependencies(input_path: &PyAny, search_paths: Vec) -> PyResult { - let has_atom = input_path.hasattr("atom")?; - let has_pair = input_path.hasattr("pair")?; - - let real_input_path = if has_atom { - input_path.getattr("atom").and_then(|x| x.str()) - } else if has_pair { - input_path - .getattr("pair") - .and_then(|x| x.get_item(0)) - .and_then(|x| x.str()) - } else { - input_path.extract() - }?; - - let file_content = fs::read_to_string(&real_input_path.to_string()) - .map_err(|_| CompError::new_err("failed to read file"))?; - - let def_opts: Rc = - Rc::new(DefaultCompilerOpts::new(&real_input_path.to_string())); - let opts = def_opts.set_search_paths(&search_paths); - - let result_deps: Vec = - gather_dependencies(opts, &real_input_path.to_string(), &file_content) - .map_err(|e| CompError::new_err(format!("{}: {}", e.0, e.1))) - .map(|rlist| rlist.iter().map(|i| decode_string(&i.name)).collect())?; - - // Return all visited files. - Python::with_gil(|py| Ok(result_deps.into_py(py))) + run_clvm_compilation( + CompileClvmSource::SourcePath(input_path), + CompileClvmAction::CheckDependencies, + search_paths, + None, + ) } #[pyclass] @@ -201,21 +286,37 @@ impl CldbSingleBespokeOverride for CldbSinglePythonOverride { .pycode .call1(py, PyTuple::new(py, &vec![arg_value])) .map_err(|e| RunFailure::RunErr(env.loc(), format!("{}", e)))?; - python_value_to_clvm(py, res) + let res_ref: &PyAny = res.as_ref(py); + python_value_to_clvm(res_ref) }) } } -#[pyfunction(arg4 = "None")] +#[pyfunction] +#[pyo3(signature = (hex_prog, hex_args, symbol_table, overrides=None, run_options=None))] fn start_clvm_program( hex_prog: String, hex_args: String, symbol_table: Option>, overrides: Option>>, + run_options: Option>>, ) -> PyResult { let (command_tx, command_rx) = mpsc::channel(); let (result_tx, result_rx) = mpsc::channel(); + let print_only_value = Python::with_gil(|py| { + let print_only_option = run_options + .and_then(|h| h.get("print").map(|p| p.clone())) + .unwrap_or_else(|| { + let any: Py = PyBool::new(py, false).into(); + any + }); + + PyBool::new(py, true).compare(print_only_option) + })?; + + let print_only = print_only_value == Ordering::Equal; + thread::spawn(move || { let mut allocator = Allocator::new(); let runner = Rc::new(DefaultProgramRunner::new()); @@ -258,6 +359,8 @@ fn start_clvm_program( let step = start_step(program, args); let cldbenv = CldbRunEnv::new(None, Rc::new(vec![]), Box::new(override_runnable)); let mut cldbrun = CldbRun::new(runner, Rc::new(prim_map), Box::new(cldbenv), step); + cldbrun.set_print_only(print_only); + loop { match cmd_input.recv() { Ok(end_run) => { @@ -290,7 +393,8 @@ fn start_clvm_program( }) } -#[pyfunction(arg3 = 2)] +#[pyfunction] +#[pyo3(signature = (tool_name, args, default_stage=2))] fn launch_tool(tool_name: String, args: Vec, default_stage: u32) -> Vec { let mut stdout = Stream::new(None); cmds::launch_tool(&mut stdout, &args, &tool_name, default_stage); @@ -391,12 +495,15 @@ pub fn compose_run_function( #[pymodule] fn clvm_tools_rs(py: Python, m: &PyModule) -> PyResult<()> { + log::init(); + m.add_submodule(create_cmds_module(py)?)?; m.add("CldbError", py.get_type::())?; m.add("CompError", py.get_type::())?; m.add_function(wrap_pyfunction!(compile_clvm, m)?)?; + m.add_function(wrap_pyfunction!(compile, m)?)?; m.add_function(wrap_pyfunction!(get_version, m)?)?; m.add_function(wrap_pyfunction!(start_clvm_program, m)?)?; m.add_function(wrap_pyfunction!(launch_tool, m)?)?; diff --git a/src/py/pyval.rs b/src/py/pyval.rs index 117bd67ad..546342a9c 100644 --- a/src/py/pyval.rs +++ b/src/py/pyval.rs @@ -11,14 +11,13 @@ use crate::compiler::runtypes::RunFailure; use crate::compiler::sexp::SExp; use crate::compiler::srcloc::Srcloc; -pub fn map_err_to_pyerr(srcloc: Srcloc, r: PyResult>) -> Result, RunFailure> { +pub fn map_err_to_pyerr(srcloc: Srcloc, r: PyResult) -> Result { r.map_err(|e| RunFailure::RunErr(srcloc, format!("{e}"))) } -pub fn python_value_to_clvm(py: Python, val: Py) -> Result, RunFailure> { +pub fn python_value_to_clvm(val: &PyAny) -> Result, RunFailure> { let srcloc = Srcloc::start("*python*"); - val.as_ref(py) - .downcast::() + val.downcast::() .ok() .map(|l| { if l.is_empty() { @@ -27,11 +26,10 @@ pub fn python_value_to_clvm(py: Python, val: Py) -> Result, RunF let mut result = SExp::Nil(srcloc.clone()); for i_rev in 0..l.len() { let i = l.len() - i_rev - 1; - let item = l.get_item(i as isize).extract(); - let any_of_elt = map_err_to_pyerr(srcloc.clone(), item)?; + let any_of_elt = map_err_to_pyerr(srcloc.clone(), l.get_item(i))?; result = SExp::Cons( srcloc.clone(), - python_value_to_clvm(py, any_of_elt)?, + python_value_to_clvm(any_of_elt)?, Rc::new(result), ); } @@ -40,8 +38,7 @@ pub fn python_value_to_clvm(py: Python, val: Py) -> Result, RunF }) .map(Some) .unwrap_or_else(|| { - val.as_ref(py) - .downcast::() + val.downcast::() .map(|t| { if t.len() != 2 { Err(RunFailure::RunErr( @@ -49,12 +46,12 @@ pub fn python_value_to_clvm(py: Python, val: Py) -> Result, RunF "tuple must have len 2".to_string(), )) } else { - let any_of_e0 = map_err_to_pyerr(srcloc.clone(), t.get_item(0).extract())?; - let any_of_e1 = map_err_to_pyerr(srcloc.clone(), t.get_item(1).extract())?; + let any_of_e0 = map_err_to_pyerr(srcloc.clone(), t.get_item(0))?; + let any_of_e1 = map_err_to_pyerr(srcloc.clone(), t.get_item(1))?; Ok(Rc::new(SExp::Cons( srcloc.clone(), - python_value_to_clvm(py, any_of_e0)?, - python_value_to_clvm(py, any_of_e1)?, + python_value_to_clvm(any_of_e0)?, + python_value_to_clvm(any_of_e1)?, ))) } }) @@ -62,8 +59,7 @@ pub fn python_value_to_clvm(py: Python, val: Py) -> Result, RunF }) .map(Some) .unwrap_or_else(|| { - val.as_ref(py) - .downcast::() + val.downcast::() .map(|b| Ok(Rc::new(SExp::Atom(srcloc.clone(), b.as_bytes().to_vec())))) .ok() }) diff --git a/src/tests/classic/clvmc.rs b/src/tests/classic/clvmc.rs index c62dc1a51..4f2d7aef7 100644 --- a/src/tests/classic/clvmc.rs +++ b/src/tests/classic/clvmc.rs @@ -1,7 +1,12 @@ use std::collections::HashMap; use std::fs; +use std::rc::Rc; -use crate::classic::clvm_tools::clvmc::compile_clvm; +use clvmr::Allocator; + +use crate::classic::clvm_tools::clvmc::{compile_clvm, compile_clvm_text}; +use crate::compiler::compiler::DefaultCompilerOpts; +use crate::compiler::comptypes::CompilerOpts; use crate::tests::classic::run::read_json_from_file; #[test] @@ -50,3 +55,54 @@ fn test_compile_clvm_with_previous_data() { .expect("should compile"); fs::remove_file(bridge_hex_file).expect("should have existed"); } + +#[test] +fn test_classic_compile_error_output() { + let mut allocator = Allocator::new(); + let mut symbols = HashMap::new(); + let path = "*test*"; + let content = "(mod (X) (xxx X))"; + let opts: Rc = Rc::new(DefaultCompilerOpts::new(path)); + let res = compile_clvm_text( + &mut allocator, + opts.clone(), + &mut symbols, + &content, + &path, + true, + ) + .map_err(|e| e.format(&allocator, opts)); + assert_eq!( + Err( + "error can't compile (\"xxx\" 88), unknown operator compiling (\"xxx\" 88)".to_string() + ), + res + ); +} + +#[test] +fn test_modern_compile_error_output() { + let mut allocator = Allocator::new(); + let mut symbols = HashMap::new(); + let path = "*test*"; + let content = indoc! { + "(mod (X) + (include *standard-cl-23*) + (+ X1 X) + ) + "}; + let opts: Rc = Rc::new(DefaultCompilerOpts::new(path)); + let res = compile_clvm_text( + &mut allocator, + opts.clone(), + &mut symbols, + &content, + &path, + true, + ) + .map_err(|e| e.format(&allocator, opts)); + assert_eq!( + Err("*test*(3):4-*test*(3):6: Unbound use of X1 as a variable name".to_string()), + res + ); +} diff --git a/src/tests/classic/embed.rs b/src/tests/classic/embed.rs index 45691e57d..d74796ad6 100644 --- a/src/tests/classic/embed.rs +++ b/src/tests/classic/embed.rs @@ -60,9 +60,11 @@ fn test_embed_exhaustive() { for order in 0..=1 { for exists in 0..=1 { for (include_kind, include_file, want_hash) in include_list.iter() { - for modern in 0..=1 { - let modern_sigil = if modern > 0 { + for modern in 0..=2 { + let modern_sigil = if modern == 1 { "(include *standard-cl-21*)" + } else if modern == 2 { + "(include *strict-cl-21*)" } else { "" }; diff --git a/src/tests/classic/run.rs b/src/tests/classic/run.rs index 9180fc717..458ee30ee 100644 --- a/src/tests/classic/run.rs +++ b/src/tests/classic/run.rs @@ -5,8 +5,6 @@ use rand::distributions::Standard; #[cfg(test)] use rand::prelude::*; #[cfg(test)] -use rand::Rng; -#[cfg(test)] use rand_chacha::ChaChaRng; use std::borrow::Borrow; @@ -572,7 +570,7 @@ fn test_treehash_constant_embedded_modern_loop() { .trim() .to_string(); eprintln!("{result_text}"); - assert!(result_text.starts_with("*command*")); + // Asserting where the stack overflows isn't necessary. assert!(result_text.contains("stack limit exceeded")); } @@ -1016,6 +1014,71 @@ fn test_modern_sets_source_file_in_symbols() { ); } +// Test that leaving off the lambda captures causes bare words for the +// requested values to find their way into the output and that having +// the capture catches it. This shows that uses of uncaptured words +// are unencumbered. +#[test] +fn test_lambda_without_capture_reproduces_bare_word_in_output() { + let compiled = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + "resources/tests/rps-referee-uncaptured.clsp".to_string(), + ]) + .trim() + .to_string(); + assert!(compiled.contains("AMOUNT")); + assert!(compiled.contains("new_puzzle_hash")); +} + +// Test that strict cl21 throws an error rather than compiling the above. +#[test] +fn test_lambda_without_capture_strict() { + let compiler_result = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + "resources/tests/strict/rps-referee-uncaptured.clsp".to_string(), + ]) + .trim() + .to_string(); + assert!(compiler_result.contains("Unbound")); + assert!(compiler_result.contains("new_puzzle_hash")); +} + +// Test that having a lambda capture captures all the associated words. +#[test] +fn test_lambda_with_capture_defines_word() { + let compiled = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + "resources/tests/rps-referee.clsp".to_string(), + ]) + .trim() + .to_string(); + assert!(!compiled.contains("AMOUNT")); + assert!(!compiled.contains("new_puzzle_hash")); +} + +#[test] +fn test_cost_reporting_0() { + let program = "(2 (1 2 6 (4 2 (4 (1 . 1) ()))) (4 (1 (2 (1 2 (3 (7 5) (1 2 (1 11 (1 . 2) (2 4 (4 2 (4 (5 5) ()))) (2 4 (4 2 (4 (6 5) ())))) 1) (1 2 (1 11 (1 . 1) 5) 1)) 1) 1) 2 (1 16 5 (1 . 50565442356047746631413349885570059132562040184787699607120092457326103992436)) 1) 1))"; + let result = do_basic_brun(&vec![ + "brun".to_string(), + "-c".to_string(), + program.to_string(), + "()".to_string(), + ]) + .trim() + .to_string(); + assert_eq!( + result, + "cost = 1978\n0x6fcb06b1fe29d132bb37f3a21b86d7cf03d636bf6230aa206486bef5e68f9875" + ); +} + #[test] fn test_assign_lambda_code_generation() { let tname = "test_assign_lambda_code_generation.sym".to_string(); @@ -1070,23 +1133,6 @@ fn test_assign_lambda_code_generation_normally_inlines() { .contains(&"ccd5be506752cebf01f9930b4c108fe18058c65e1ab57a72ca0a00d9788c7ca6".to_string())); } -#[test] -fn test_cost_reporting_0() { - let program = "(2 (1 2 6 (4 2 (4 (1 . 1) ()))) (4 (1 (2 (1 2 (3 (7 5) (1 2 (1 11 (1 . 2) (2 4 (4 2 (4 (5 5) ()))) (2 4 (4 2 (4 (6 5) ())))) 1) (1 2 (1 11 (1 . 1) 5) 1)) 1) 1) 2 (1 16 5 (1 . 50565442356047746631413349885570059132562040184787699607120092457326103992436)) 1) 1))"; - let result = do_basic_brun(&vec![ - "brun".to_string(), - "-c".to_string(), - program.to_string(), - "()".to_string(), - ]) - .trim() - .to_string(); - assert_eq!( - result, - "cost = 1978\n0x6fcb06b1fe29d132bb37f3a21b86d7cf03d636bf6230aa206486bef5e68f9875" - ); -} - #[test] fn test_assign_fancy_final_dot_rest() { let result_prog = do_basic_run(&vec![ @@ -1102,117 +1148,1115 @@ fn test_assign_fancy_final_dot_rest() { } #[test] -fn test_g1_map_op_modern() { - let program = "(mod (S) (include *standard-cl-21*) (g1_map S \"BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_AUG_\"))"; - let compiled = do_basic_run(&vec!["run".to_string(), program.to_string()]); - let output = do_basic_brun(&vec![ +fn test_strict_smoke_0() { + let result = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + "resources/tests/strict/strict-test-fail.clsp".to_string(), + ]); + assert!(result.contains("Unbound")); + assert!(result.contains("X1")); +} + +#[test] +fn test_strict_smoke_1() { + let result_prog = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + "resources/tests/strict/strict-test-pass.clsp".to_string(), + ]); + let result = do_basic_brun(&vec!["brun".to_string(), result_prog, "(13)".to_string()]) + .trim() + .to_string(); + assert_eq!(result, "15"); +} + +#[test] +fn test_strict_list_fail() { + let result = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + "resources/tests/strict/strict-list-fail.clsp".to_string(), + ]); + assert!(result.contains("Unbound")); + assert!(result.contains("X2")); +} + +#[test] +fn test_strict_list_pass() { + let result_prog = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + "resources/tests/strict/strict-list-pass.clsp".to_string(), + ]); + let result = do_basic_brun(&vec!["brun".to_string(), result_prog, "(13)".to_string()]) + .trim() + .to_string(); + assert_eq!(result, "(strlen 14 15)"); +} + +#[test] +fn test_strict_nested_list_pass() { + let result_prog = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + "resources/tests/strict/strict-nested-list.clsp".to_string(), + ]); + let result = do_basic_brun(&vec!["brun".to_string(), result_prog, "(13)".to_string()]) + .trim() + .to_string(); + assert_eq!(result, "(strlen (strlen) ((strlen)))"); +} + +#[test] +fn test_double_constant_pass() { + let result_prog = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + "resources/tests/strict/double-constant-pass.clsp".to_string(), + ]); + let result = do_basic_brun(&vec!["brun".to_string(), result_prog, "()".to_string()]) + .trim() + .to_string(); + assert_eq!(result, "198"); +} + +#[test] +fn test_double_constant_fail() { + let result = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + "resources/tests/strict/double-constant-fail.clsp".to_string(), + ]); + assert!(result.contains("not a number given to only-integers")); + assert!(result.contains("\"hithere\"")); +} + +#[test] +fn test_double_constant_pass_in_function() { + let result_prog = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + "resources/tests/strict/double-constant-pass-in-function.clsp".to_string(), + ]); + let result = do_basic_brun(&vec!["brun".to_string(), result_prog, "(13)".to_string()]) + .trim() + .to_string(); + assert_eq!(result, "211"); +} + +#[test] +fn test_check_symbol_kinds_nested_if() { + let result_prog = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + "resources/tests/strict/strict-classify-expr-if.clsp".to_string(), + ]); + let result_1 = do_basic_brun(&vec![ "brun".to_string(), - compiled, - "(abcdef0123456789)".to_string(), + result_prog.clone(), + "(1)".to_string(), ]) .trim() .to_string(); + assert_eq!(result_1, "2"); + let result_0 = do_basic_brun(&vec!["brun".to_string(), result_prog, "(0)".to_string()]) + .trim() + .to_string(); + assert_eq!(result_0, "(q 1 2 3 4 4)"); +} + +// Check for successful deinlining of a large constant. +// The result program tables the constant. +#[test] +fn test_basic_deinlining_smoke_0() { + let fname = "resources/tests/simple_deinline_case_23.clsp"; + let file_content = fs::read_to_string(fname).expect("should exist"); + let result_prog = do_basic_run(&vec!["run".to_string(), fname.to_string()]); + eprintln!("result_prog 23 {result_prog}"); + assert_eq!(result_prog.matches("1000000").count(), 1); + let old_prog = file_content.to_string().replace("23", "21"); + let result_prog_21 = do_basic_run(&vec!["run".to_string(), old_prog]); + eprintln!("result_prog 21 {result_prog_21}"); + assert_eq!(result_prog_21.matches("1000000").count(), 6); + assert!(result_prog.len() < result_prog_21.len()); +} + +// Check for the optimizer to reduce a fully constant program to a constant. +#[test] +fn test_optimizer_fully_reduces_constant_outcome_0() { + let res = do_basic_run(&vec![ + "run".to_string(), + "(mod () (include *standard-cl-23*) (defun F (X) (+ X 1)) (F 3))".to_string(), + ]); + assert_eq!(res, "(1 . 4)"); +} + +// Check for the optimizer to reduce a fully constant program to a constant. +#[test] +fn test_optimizer_fully_reduces_constant_outcome_sha256tree() { + let res = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + "(mod () (include *standard-cl-23*) (include sha256tree.clib) (defun F (X) (sha256tree (+ X 1))) (F 3))".to_string(), + ]); assert_eq!( - output, - "0x88e7302bf1fa8fcdecfb96f6b81475c3564d3bcaf552ccb338b1c48b9ba18ab7195c5067fe94fb216478188c0a3bef4a" + res, + "(1 . -39425664269051251592384450451821132878837081010681666327853404714379049572411)" ); } +// Check for the optimizer to reduce a fully constant function call to a constant +// and propogate through another expression. #[test] -fn test_g1_map_op_classic() { - let program = "(mod (S) (g1_map S \"BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_AUG_\"))"; - let compiled = do_basic_run(&vec!["run".to_string(), program.to_string()]); - let output = do_basic_brun(&vec![ - "brun".to_string(), - compiled, - "(abcdef0123456789)".to_string(), - ]) - .trim() - .to_string(); +fn test_optimizer_fully_reduces_constant_outcome_sha256tree_1() { + let res = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + "(mod () (include *standard-cl-23*) (include sha256tree.clib) (defun F (X) (sha256tree (+ X 1))) (+ (F 3) 1))".to_string(), + ]); assert_eq!( - output, - "0x88e7302bf1fa8fcdecfb96f6b81475c3564d3bcaf552ccb338b1c48b9ba18ab7195c5067fe94fb216478188c0a3bef4a" + res, + "(1 . -39425664269051251592384450451821132878837081010681666327853404714379049572410)" ); } #[test] -fn test_g2_map_op_modern() { - let program = "(mod (S) (include *standard-cl-21*) (g2_map S \"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_\"))"; +fn test_g1_map_op_modern() { + let program = "(mod (S) (include *standard-cl-21*) (g1_map S \"BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_AUG_\"))"; let compiled = do_basic_run(&vec!["run".to_string(), program.to_string()]); let output = do_basic_brun(&vec![ "brun".to_string(), compiled, - "(0x21473dab7ad0136f7488128d44247b04fa58a9c6b4fab6ef4d)".to_string(), + "(abcdef0123456789)".to_string(), ]) .trim() .to_string(); assert_eq!( output, - "0x879584f6c205b4492abca2be331fc2875596b08c7fbd958fb8d5e725a479d1794b85add1266fb5d410de5c416ce12305166b1c3e2e5d5ae2720a058169b057520d8f2a315f6097c774f659ce5619a070e1cbc8212fb460758e459498d0e598d6" + "0x88e7302bf1fa8fcdecfb96f6b81475c3564d3bcaf552ccb338b1c48b9ba18ab7195c5067fe94fb216478188c0a3bef4a" ); } #[test] -fn test_g2_map_op_classic() { - let program = "(mod (S) (g2_map S \"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_\"))"; - let compiled = do_basic_run(&vec!["run".to_string(), program.to_string()]); - let output = do_basic_brun(&vec![ - "brun".to_string(), - compiled, - "(0x21473dab7ad0136f7488128d44247b04fa58a9c6b4fab6ef4d)".to_string(), - ]) - .trim() - .to_string(); +fn test_optimizer_fully_reduces_constant_outcome_let_0() { + let res = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + "(mod (A) (include *standard-cl-23*) (include sha256tree.clib) (defun F (X) (sha256tree (+ X 1))) (defun G (Q) (let ((R (F Q))) (+ R 1))) (+ A (G 3)))".to_string(), + ]); + // Tree shaking will remove the functions that became unused due to constant + // reduction. We now support suppressing the left env in stepping 23 and + // above. assert_eq!( - output, - "0x879584f6c205b4492abca2be331fc2875596b08c7fbd958fb8d5e725a479d1794b85add1266fb5d410de5c416ce12305166b1c3e2e5d5ae2720a058169b057520d8f2a315f6097c774f659ce5619a070e1cbc8212fb460758e459498d0e598d6" + res, + "(16 2 (1 . -39425664269051251592384450451821132878837081010681666327853404714379049572410))" ); } +// Test that the optimizer inverts (i (not x) a b) to (i x b a) #[test] -fn test_secp256k1_verify_modern_succeed() { - let program = "(mod (S) (include *standard-cl-21*) (secp256k1_verify S 0x85932e4d075615be881398cc765f9f78204033f0ef5f832ac37e732f5f0cbda2 0x481477e62a1d02268127ae89cc58929e09ad5d30229721965ae35965d098a5f630205a7e69f4cb8084f16c7407ed7312994ffbf87ba5eb1aee16682dd324943e))"; - let compiled = do_basic_run(&vec!["run".to_string(), program.to_string()]); - let output = do_basic_brun(&vec![ - "brun".to_string(), - compiled, - "(0x02390b19842e100324163334b16947f66125b76d4fa4a11b9ccdde9b7398e64076)".to_string(), - ]) - .trim() - .to_string(); - assert_eq!(output, "()"); +fn test_not_inversion_body() { + let res = do_basic_run(&vec![ + "run".to_string(), + "(mod (X) (include *standard-cl-23*) (if (not X) (+ X 1) (* X 2)))".to_string(), + ]); + assert_eq!(res, "(2 (3 2 (1 18 2 (1 . 2)) (1 16 2 (1 . 1))) 1)"); } +// Test that we can test chialisp outcomes in chialisp. #[test] -fn test_secp256k1_verify_modern_fail() { - let program = "(mod (S) (include *standard-cl-21*) (secp256k1_verify S 0x935d863e2d28d8e5d399ea8af7393ef11fdffc7d862dcc6b5217a8ef15fb5442 0xbbf0712cc0a283a842011c19682629a5381c5f7ead576defcf12a9a19378e23b087cd0be730dbe78722dcfc81543fca17a30e41070ca2e5b3ae77ccec2cca935))"; - let compiled = do_basic_run(&vec!["run".to_string(), program.to_string()]); - let output = do_basic_brun(&vec![ +fn test_chialisp_in_chialisp_test_pos() { + let compiled = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + "(mod (X) (include *standard-cl-23*) (if (= (f (mod () (include *standard-cl-23*) (include sha256tree.clib) (defun F (X) (sha256tree (+ X 1))) (+ (F 3) 1))) 1) \"worked\" \"didnt work\"))".to_string(), + ]); + assert_eq!(compiled, "(1 . \"worked\")"); +} + +// Test that we can test chialisp outcomes in chialisp. +#[test] +fn test_chialisp_in_chialisp_test_neg() { + let compiled = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + "(mod (X) (include *standard-cl-23*) (if (= (f (mod () (include *standard-cl-23*) (include sha256tree.clib) (defun F (X) (sha256tree (+ (list X) 1))) (+ (F 3) 1))) 1) \"worked\" \"didnt work\"))".to_string(), + ]); + assert_eq!(compiled, "(1 . \"didnt work\")"); +} + +// Test CSE when detections are inside a lambda. It's necessary to add a capture for +// the replaced expression. +#[test] +fn test_cse_replacement_inside_lambda_23_0() { + let program = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + "resources/tests/more_exhaustive/lambda_cse_1.clsp".to_string(), + ]); + let res = do_basic_brun(&vec![ "brun".to_string(), - compiled, - "(0x0215043e969dcf616fabe8e8d6b61ddcf6e274c5b04fce957b086dbeb7e899ac63)".to_string(), + program.clone(), + "(17 17)".to_string(), ]) .trim() .to_string(); - assert!(output.starts_with("FAIL: secp256k1_verify failed")); -} - -#[test] -fn test_secp256k1_verify_classic_succeed() { - let program = "(mod (S) (secp256k1_verify S 0x85932e4d075615be881398cc765f9f78204033f0ef5f832ac37e732f5f0cbda2 0x481477e62a1d02268127ae89cc58929e09ad5d30229721965ae35965d098a5f630205a7e69f4cb8084f16c7407ed7312994ffbf87ba5eb1aee16682dd324943e))"; - let compiled = do_basic_run(&vec!["run".to_string(), program.to_string()]); - let output = do_basic_brun(&vec![ + assert_eq!(res, "0x15aa51"); + let res = do_basic_brun(&vec![ "brun".to_string(), - compiled, - "(0x02390b19842e100324163334b16947f66125b76d4fa4a11b9ccdde9b7398e64076)".to_string(), + program.clone(), + "(17 19)".to_string(), ]) .trim() .to_string(); - assert_eq!(output, "()"); + assert_eq!(res, "0x1b1019"); + let res = do_basic_brun(&vec!["brun".to_string(), program, "(19 17)".to_string()]) + .trim() + .to_string(); + assert_eq!(res, "0x1e3f2b"); } #[test] -fn test_secp256k1_verify_classic_fail() { +fn test_cse_replacement_inside_lambda_test_desugared_form_23() { + let program = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests".to_string(), + "resources/tests/more_exhaustive/lambda_cse_1_desugared_form.clsp".to_string(), + ]); + let res = do_basic_brun(&vec!["brun".to_string(), program, "(17 17)".to_string()]) + .trim() + .to_string(); + assert_eq!(res, "0x15aa51"); +} + +// Note: this program is intentionally made to properly preprocess but trigger +// an error in strict compilation as a demonstration and test that the preprocessor +// is a mechanically separate step from compilation. Separating them like this +// has the advantage that you can emit preprocessed compiler input on its own +// and also that it internally untangles the stages and makes compilation simpler. +#[test] +fn test_defmac_if_smoke_preprocess() { + let result_prog = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + "-E".to_string(), + "resources/tests/strict/defmac_if_smoke.clsp".to_string(), + ]); + assert_eq!( + result_prog, + "(mod () (include *strict-cl-21*) (a (i t1 (com t2) (com t3)) @))" + ); + let result2 = do_basic_run(&vec!["run".to_string(), result_prog]); + assert!(result2.contains("Unbound use")); + // Ensure that we're identifying one of the actually misused variables, but + // do not make a claim about which one is identified first. + assert!(result2.contains("of t1") || result2.contains("of t2") || result2.contains("of t3")); +} + +#[test] +fn test_defmac_assert_smoke_preprocess() { + let result_prog = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + "-E".to_string(), + "resources/tests/strict/assert.clsp".to_string(), + ]); + assert_eq!( + result_prog, + "(mod (A) (include *strict-cl-21*) (a (i 1 (com (a (i A (com 13) (com (x))) @)) (com (x))) @))" + ); + let result_after_preproc = do_basic_run(&vec!["run".to_string(), result_prog]); + let result_with_preproc = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + "resources/tests/strict/assert.clsp".to_string(), + ]); + assert_eq!(result_after_preproc, result_with_preproc); + let run_result_true = do_basic_brun(&vec![ + "brun".to_string(), + result_with_preproc.clone(), + "(15)".to_string(), + ]); + assert_eq!(run_result_true.trim(), "13"); + let run_result_false = do_basic_brun(&vec![ + "brun".to_string(), + result_with_preproc.clone(), + "(0)".to_string(), + ]); + assert_eq!(run_result_false.trim(), "FAIL: clvm raise ()"); +} + +#[test] +fn test_defmac_assert_smoke_preprocess_23() { + let result_prog = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + "-E".to_string(), + "resources/tests/strict/assert23.clsp".to_string(), + ]); + assert_eq!( + result_prog, + "(mod (A) (include *standard-cl-23*) (a (i 1 (com (a (i A (com 13) (com (x))) @)) (com (x))) @))" + ); + let result_after_preproc = do_basic_run(&vec!["run".to_string(), result_prog]); + let result_with_preproc = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + "resources/tests/strict/assert23.clsp".to_string(), + ]); + assert_eq!(result_after_preproc, result_with_preproc); + let run_result_true = do_basic_brun(&vec![ + "brun".to_string(), + result_with_preproc.clone(), + "(15)".to_string(), + ]); + assert_eq!(run_result_true.trim(), "13"); + let run_result_false = do_basic_brun(&vec![ + "brun".to_string(), + result_with_preproc.clone(), + "(0)".to_string(), + ]); + assert_eq!(run_result_false.trim(), "FAIL: clvm raise ()"); +} + +#[test] +fn test_smoke_inline_at_expansion_23_0() { + let prog = do_basic_run(&vec![ + "run".to_string(), + indoc! {" + (mod (Y) + (include *standard-cl-23*) + (defun A (X) (r @*env*)) ;; X = ((3)), returns (((3))) + (defun B (X) (A (r @*env*))) ;; X = (3) + (defun C (X) (B (r @*env*))) ;; X = 3 + (C Y) ;; Y = 3 + ) + "} + .to_string(), + ]); + let run_result = do_basic_brun(&vec!["brun".to_string(), prog, "(3)".to_string()]); + assert_eq!(run_result.trim(), "(((i)))"); +} + +#[test] +fn test_smoke_inline_at_expansion_23_1() { + let prog = do_basic_run(&vec![ + "run".to_string(), + indoc! {" + (mod (Y) + (include *standard-cl-23*) + (defun-inline A (X) (r @*env*)) + (defun B (X) (A (r @*env*))) + (defun C (X) (B (r @*env*))) + (C Y) + ) + "} + .to_string(), + ]); + let run_result = do_basic_brun(&vec!["brun".to_string(), prog, "(3)".to_string()]); + assert_eq!(run_result.trim(), "(((i)))"); +} + +#[test] +fn test_smoke_inline_at_expansion_23_2() { + let prog = do_basic_run(&vec![ + "run".to_string(), + indoc! {" + (mod (Y) + (include *standard-cl-23*) + (defun A (X) (r @*env*)) + (defun-inline B (X) (A (r @*env*))) + (defun C (X) (B (r @*env*))) + (C Y) + ) + "} + .to_string(), + ]); + let run_result = do_basic_brun(&vec!["brun".to_string(), prog, "(3)".to_string()]); + assert_eq!(run_result.trim(), "(((i)))"); +} + +#[test] +fn test_smoke_inline_at_expansion_23_3() { + let prog = do_basic_run(&vec![ + "run".to_string(), + indoc! {" + (mod (Y) + (include *standard-cl-23*) + (defun-inline A (X) (r @*env*)) + (defun-inline B (X) (A (r @*env*))) + (defun C (X) (B (r @*env*))) + (C Y) + ) + "} + .to_string(), + ]); + let run_result = do_basic_brun(&vec!["brun".to_string(), prog, "(3)".to_string()]); + assert_eq!(run_result.trim(), "(((i)))"); +} + +#[test] +fn test_smoke_inline_at_expansion_23_4() { + let prog = do_basic_run(&vec![ + "run".to_string(), + indoc! {" + (mod (Y) + (include *standard-cl-23*) + (defun A (X) (r @*env*)) + (defun B (X) (A (r @*env*))) + (defun-inline C (X) (B (r @*env*))) + (C Y) + ) + "} + .to_string(), + ]); + let run_result = do_basic_brun(&vec!["brun".to_string(), prog, "(3)".to_string()]); + assert_eq!(run_result.trim(), "(((i)))"); +} + +#[test] +fn test_smoke_inline_at_expansion_23_5() { + let prog = do_basic_run(&vec![ + "run".to_string(), + indoc! {" + (mod (Y) + (include *standard-cl-23*) + (defun-inline A (X) (r @*env*)) + (defun B (X) (A (r @*env*))) + (defun-inline C (X) (B (r @*env*))) + (C Y) + ) + "} + .to_string(), + ]); + let run_result = do_basic_brun(&vec!["brun".to_string(), prog, "(3)".to_string()]); + assert_eq!(run_result.trim(), "(((i)))"); +} + +#[test] +fn test_smoke_inline_at_expansion_23_6() { + let prog = do_basic_run(&vec![ + "run".to_string(), + indoc! {" + (mod (Y) + (include *standard-cl-23*) + (defun A (X) (r @*env*)) + (defun-inline B (X) (A (r @*env*))) + (defun-inline C (X) (B (r @*env*))) + (C Y) + ) + "} + .to_string(), + ]); + let run_result = do_basic_brun(&vec!["brun".to_string(), prog, "(3)".to_string()]); + assert_eq!(run_result.trim(), "(((i)))"); +} + +#[test] +fn test_smoke_inline_at_expansion_23_7() { + let prog = do_basic_run(&vec![ + "run".to_string(), + indoc! {" + (mod (Y) + (include *standard-cl-23*) + (defun-inline A (X) (r @*env*)) + (defun-inline B (X) (A (r @*env*))) + (defun-inline C (X) (B (r @*env*))) + (C Y) + ) + "} + .to_string(), + ]); + let run_result = do_basic_brun(&vec!["brun".to_string(), prog, "(3)".to_string()]); + assert_eq!(run_result.trim(), "(((i)))"); +} + +#[test] +fn test_smoke_inline_at_expansion_var_23_0() { + let prog = do_basic_run(&vec![ + "run".to_string(), + indoc! {" + (mod (Y) + (include *standard-cl-23*) + (defun A (((PPX) PX) X) (list PPX PX X)) + (defun B ((PX) X) (A (r @*env*) (+ X 1))) + (defun C (X) (B (r @*env*) (+ X 1))) + (C Y) + ) + "} + .to_string(), + ]); + let run_result = do_basic_brun(&vec!["brun".to_string(), prog, "(3)".to_string()]); + assert_eq!(run_result.trim(), "(i 4 5)"); +} + +#[test] +fn test_smoke_inline_at_expansion_var_23_1() { + let prog = do_basic_run(&vec![ + "run".to_string(), + indoc! {" + (mod (Y) + (include *standard-cl-23*) + (defun-inline A (((PPX) PX) X) (list PPX PX X)) + (defun B ((PX) X) (A (r @*env*) (+ X 1))) + (defun C (X) (B (r @*env*) (+ X 1))) + (C Y) + ) + "} + .to_string(), + ]); + let run_result = do_basic_brun(&vec!["brun".to_string(), prog, "(3)".to_string()]); + assert_eq!(run_result.trim(), "(i 4 5)"); +} + +#[test] +fn test_smoke_inline_at_expansion_var_23_2() { + let prog = do_basic_run(&vec![ + "run".to_string(), + indoc! {" + (mod (Y) + (include *standard-cl-23*) + (defun A (((PPX) PX) X) (list PPX PX X)) + (defun-inline B ((PX) X) (A (r @*env*) (+ X 1))) + (defun C (X) (B (r @*env*) (+ X 1))) + (C Y) + ) + "} + .to_string(), + ]); + let run_result = do_basic_brun(&vec!["brun".to_string(), prog, "(3)".to_string()]); + assert_eq!(run_result.trim(), "(i 4 5)"); +} + +#[test] +fn test_smoke_inline_at_expansion_var_23_3() { + let prog = do_basic_run(&vec![ + "run".to_string(), + indoc! {" + (mod (Y) + (include *standard-cl-23*) + (defun-inline A (((PPX) PX) X) (list PPX PX X)) + (defun-inline B ((PX) X) (A (r @*env*) (+ X 1))) + (defun C (X) (B (r @*env*) (+ X 1))) + (C Y) + ) + "} + .to_string(), + ]); + let run_result = do_basic_brun(&vec!["brun".to_string(), prog, "(3)".to_string()]); + assert_eq!(run_result.trim(), "(i 4 5)"); +} + +#[test] +fn test_smoke_inline_at_expansion_var_23_4() { + let prog = do_basic_run(&vec![ + "run".to_string(), + indoc! {" + (mod (Y) + (include *standard-cl-23*) + (defun A (((PPX) PX) X) (list PPX PX X)) + (defun B ((PX) X) (A (r @*env*) (+ X 1))) + (defun-inline C (X) (B (r @*env*) (+ X 1))) + (C Y) + ) + "} + .to_string(), + ]); + let run_result = do_basic_brun(&vec!["brun".to_string(), prog, "(3)".to_string()]); + assert_eq!(run_result.trim(), "(i 4 5)"); +} + +#[test] +fn test_smoke_inline_at_expansion_var_23_5() { + let prog = do_basic_run(&vec![ + "run".to_string(), + indoc! {" + (mod (Y) + (include *standard-cl-23*) + (defun-inline A (((PPX) PX) X) (list PPX PX X)) + (defun B ((PX) X) (A (r @*env*) (+ X 1))) + (defun-inline C (X) (B (r @*env*) (+ X 1))) + (C Y) + ) + "} + .to_string(), + ]); + let run_result = do_basic_brun(&vec!["brun".to_string(), prog, "(3)".to_string()]); + assert_eq!(run_result.trim(), "(i 4 5)"); +} + +#[test] +fn test_smoke_inline_at_expansion_var_23_6() { + let prog = do_basic_run(&vec![ + "run".to_string(), + indoc! {" + (mod (Y) + (include *standard-cl-23*) + (defun A (((PPX) PX) X) (list PPX PX X)) + (defun-inline B ((PX) X) (A (r @*env*) (+ X 1))) + (defun-inline C (X) (B (r @*env*) (+ X 1))) + (C Y) + ) + "} + .to_string(), + ]); + let run_result = do_basic_brun(&vec!["brun".to_string(), prog, "(3)".to_string()]); + assert_eq!(run_result.trim(), "(i 4 5)"); +} + +#[test] +fn test_smoke_inline_at_expansion_var_23_7() { + let prog = do_basic_run(&vec![ + "run".to_string(), + indoc! {" + (mod (Y) + (include *standard-cl-23*) + (defun-inline A (((PPX) PX) X) (list PPX PX X)) + (defun-inline B ((PX) X) (A (r @*env*) (+ X 1))) + (defun-inline C (X) (B (r @*env*) (+ X 1))) + (C Y) + ) + "} + .to_string(), + ]); + let run_result = do_basic_brun(&vec!["brun".to_string(), prog, "(3)".to_string()]); + assert_eq!(run_result.trim(), "(i 4 5)"); +} + +// +// Inside assert_ (items): +// items @ 5 +// +// Inside letbinding_$_44 ((items) cse_$_43_$_24) +// +// items @ 9 +// cse_$_43_$_24 @ 11 +// +#[test] +fn test_inline_vs_deinline_23() { + eprintln!("=== W2 ==="); + let compiled_2 = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/use-w2.clsp".to_string(), + ]); + eprintln!("=== W3 ==="); + let compiled_3 = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/use-w3.clsp".to_string(), + ]); + eprintln!("=== RUN W2 ==="); + let result_2 = do_basic_brun(&vec![ + "brun".to_string(), + compiled_2, + "((1 2 3))".to_string(), + ]); + eprintln!("=== RUN W3 ==="); + let result_3 = do_basic_brun(&vec![ + "brun".to_string(), + compiled_3, + "((1 2 3))".to_string(), + ]); + assert_eq!(result_2, result_3); +} + +#[test] +fn test_rosetta_code_abc_example() { + let test_words = &[ + ("A", true), + ("BARK", true), + ("TREAT", true), + ("BOOK", false), + ("COMMON", false), + ("SQUAD", true), + ("CONFUSE", true), + ]; + let prog_pp = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/rosetta_code_abc.clsp".to_string(), + ]); + let prog_np = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/rosetta_code_abc_preprocessed.clsp".to_string(), + ]); + eprintln!("{prog_pp}"); + assert_eq!(prog_pp, prog_np); + for (w, success) in test_words.iter() { + eprintln!("{} {}", w, success); + let result = do_basic_brun(&vec![ + "brun".to_string(), + prog_pp.clone(), + format!("({})", w), + ]) + .trim() + .to_string(); + if *success { + assert_eq!(result, "1"); + } else { + assert_eq!(result, "()"); + } + } +} + +#[test] +fn test_rosetta_code_babbage_problem() { + let preprocessed = do_basic_run(&vec![ + "run".to_string(), + "-E".to_string(), + "resources/tests/strict/rosetta_code_babbage_problem.clsp".to_string(), + ]); + assert!(!preprocessed.contains("*macros*")); + assert!(!preprocessed.contains("(defmacro list")); + let compiled = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/rosetta_code_babbage_problem.clsp".to_string(), + ]); + let output = do_basic_brun(&vec!["brun".to_string(), compiled, "(269696)".to_string()]) + .trim() + .to_string(); + assert_eq!(output, "25264"); +} + +#[test] +fn test_cse_when_not_dominating_conditions() { + let program = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/cse_doesnt_dominate.clsp".to_string(), + ]); + let outcome = do_basic_brun(&vec!["brun".to_string(), program, "(33)".to_string()]) + .trim() + .to_string(); + assert_eq!(outcome, "0x009988"); // 34 * 34 * 34 +} + +#[test] +fn test_cse_not_dominating_conditions_with_superior_let() { + let program = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/cse_doesnt_dominate_superior_let.clsp".to_string(), + ]); + let outcome = do_basic_brun(&vec!["brun".to_string(), program, "(33)".to_string()]) + .trim() + .to_string(); + assert_eq!(outcome, "0x009988"); // 34 * 34 * 34 +} + +#[test] +fn test_cse_not_dominating_conditions_with_superior_let_outside() { + let program = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/cse_doesnt_dominate_superior_let_outside.clsp".to_string(), + ]); + let outcome = do_basic_brun(&vec!["brun".to_string(), program, "(33)".to_string()]) + .trim() + .to_string(); + assert_eq!(outcome, "0x5c13d840"); // 34 * 34 * 34 * 34 * 34 * 34 +} + +#[test] +fn test_cse_not_dominating_conditions_with_superior_let_outside_in_inline() { + let program = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/cse_doesnt_dominate_superior_let_outside_in_inline.clsp" + .to_string(), + ]); + let outcome = do_basic_brun(&vec!["brun".to_string(), program, "(33)".to_string()]) + .trim() + .to_string(); + assert_eq!(outcome, "0x5c13d840"); // 34 * 34 * 34 * 34 * 34 * 34 +} + +#[test] +fn test_cse_not_dominating_conditions_with_superior_let_outside_in_defun() { + let program = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/cse_doesnt_dominate_superior_let_outside_in_defun.clsp".to_string(), + ]); + let outcome = do_basic_brun(&vec!["brun".to_string(), program, "(33)".to_string()]) + .trim() + .to_string(); + assert_eq!(outcome, "0x5c13d840"); // 34 * 34 * 34 * 34 * 34 * 34 +} + +#[test] +fn test_cse_not_dominating_conditions_with_superior_let_odi() { + let program = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/cse_doesnt_dominate_superior_let_odi.clsp".to_string(), + ]); + let outcome = do_basic_brun(&vec!["brun".to_string(), program, "(33)".to_string()]) + .trim() + .to_string(); + assert_eq!(outcome, "0x5c13d840"); // 34 * 34 * 34 * 34 * 34 * 34 +} + +#[test] +fn test_cse_not_dominating_conditions_with_superior_let_iodi() { + let program = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/cse_doesnt_dominate_superior_let_iodi.clsp".to_string(), + ]); + let outcome = do_basic_brun(&vec!["brun".to_string(), program, "(33)".to_string()]) + .trim() + .to_string(); + assert_eq!(outcome, "0x5c13d840"); // 34 * 34 * 34 * 34 * 34 * 34 +} + +#[test] +fn test_chialisp_web_example() { + let program = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/chialisp-web-example.clsp".to_string(), + ]); + let outcome = do_basic_brun(&vec!["brun".to_string(), program, "(100)".to_string()]) + .trim() + .to_string(); + assert_eq!(outcome, "(306 (101 103))"); +} + +#[test] +fn test_chialisp_web_example_defconst() { + let program = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/defconst.clsp".to_string(), + ]); + let outcome = do_basic_brun(&vec!["brun".to_string(), program, "(3)".to_string()]) + .trim() + .to_string(); + assert_eq!( + outcome, + "0xf60efb25b9e6e3587acd9cf01c332707bb771801bdb5e4f50ea957a29c8dde89" + ); +} + +#[test] +fn test_chialisp_web_example_big_maybe() { + let program = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/big-maybe.clsp".to_string(), + ]); + let outcome = do_basic_brun(&vec!["brun".to_string(), program, "(((3 5)))".to_string()]) + .trim() + .to_string(); + assert_eq!(outcome, "8"); +} + +#[test] +fn test_chialisp_web_example_map() { + let program = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/map-example.clsp".to_string(), + ]); + let outcome = do_basic_brun(&vec!["brun".to_string(), program, "((1 2 3))".to_string()]) + .trim() + .to_string(); + assert_eq!(outcome, "(a 3 4)"); +} + +#[test] +fn test_chialisp_web_example_map_lambda() { + let program = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/map-example.clsp".to_string(), + ]); + let outcome = do_basic_brun(&vec![ + "brun".to_string(), + program, + "((100 101 102))".to_string(), + ]) + .trim() + .to_string(); + assert_eq!(outcome, "(101 102 103)"); +} + +#[test] +fn test_chialisp_web_example_embed() { + let program = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + "resources/tests/strict/embed.clsp".to_string(), + ]); + let outcome = do_basic_brun(&vec!["brun".to_string(), program, "(world)".to_string()]) + .trim() + .to_string(); + assert_eq!( + outcome, + "0x26c60a61d01db5836ca70fefd44a6a016620413c8ef5f259a6c5612d4f79d3b8" + ); +} + +#[test] +fn test_chialisp_types_23() { + let program = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/typesmoke.clsp".to_string(), + ]) + .trim() + .to_string(); + let program2 = do_basic_run(&vec![ + "run".to_string(), + "--typecheck".to_string(), + "resources/tests/strict/typesmoke.clsp".to_string(), + ]) + .trim() + .to_string(); + assert_eq!(program, program2); + assert_eq!(program, "(2 (1 . 2) (4 2 ()))"); +} + +#[test] +fn test_chialisp_type_lambda_23() { + let program = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/typesmoke-lambda.clsp".to_string(), + ]) + .trim() + .to_string(); + let program2 = do_basic_run(&vec![ + "run".to_string(), + "--typecheck".to_string(), + "resources/tests/strict/typesmoke-lambda.clsp".to_string(), + ]) + .trim() + .to_string(); + assert_eq!(program, program2); +} + +#[test] +fn test_chialisp_type_lambda_23_anno() { + let program = do_basic_run(&vec![ + "run".to_string(), + "resources/tests/strict/typesmoke-lambda-anno.clsp".to_string(), + ]) + .trim() + .to_string(); + let program2 = do_basic_run(&vec![ + "run".to_string(), + "--typecheck".to_string(), + "resources/tests/strict/typesmoke-lambda-anno.clsp".to_string(), + ]) + .trim() + .to_string(); + assert_eq!(program, program2); +} + +#[test] +fn test_g1_map_op_classic() { + let program = "(mod (S) (g1_map S \"BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_AUG_\"))"; + let compiled = do_basic_run(&vec!["run".to_string(), program.to_string()]); + let output = do_basic_brun(&vec![ + "brun".to_string(), + compiled, + "(abcdef0123456789)".to_string(), + ]) + .trim() + .to_string(); + assert_eq!( + output, + "0x88e7302bf1fa8fcdecfb96f6b81475c3564d3bcaf552ccb338b1c48b9ba18ab7195c5067fe94fb216478188c0a3bef4a" + ); +} + +#[test] +fn test_g2_map_op_modern() { + let program = "(mod (S) (include *standard-cl-21*) (g2_map S \"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_\"))"; + let compiled = do_basic_run(&vec!["run".to_string(), program.to_string()]); + let output = do_basic_brun(&vec![ + "brun".to_string(), + compiled, + "(0x21473dab7ad0136f7488128d44247b04fa58a9c6b4fab6ef4d)".to_string(), + ]) + .trim() + .to_string(); + assert_eq!( + output, + "0x879584f6c205b4492abca2be331fc2875596b08c7fbd958fb8d5e725a479d1794b85add1266fb5d410de5c416ce12305166b1c3e2e5d5ae2720a058169b057520d8f2a315f6097c774f659ce5619a070e1cbc8212fb460758e459498d0e598d6" + ); +} + +#[test] +fn test_g2_map_op_classic() { + let program = "(mod (S) (g2_map S \"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_\"))"; + let compiled = do_basic_run(&vec!["run".to_string(), program.to_string()]); + let output = do_basic_brun(&vec![ + "brun".to_string(), + compiled, + "(0x21473dab7ad0136f7488128d44247b04fa58a9c6b4fab6ef4d)".to_string(), + ]) + .trim() + .to_string(); + assert_eq!( + output, + "0x879584f6c205b4492abca2be331fc2875596b08c7fbd958fb8d5e725a479d1794b85add1266fb5d410de5c416ce12305166b1c3e2e5d5ae2720a058169b057520d8f2a315f6097c774f659ce5619a070e1cbc8212fb460758e459498d0e598d6" + ); +} + +#[test] +fn test_secp256k1_verify_modern_succeed() { + let program = "(mod (S) (include *standard-cl-21*) (secp256k1_verify S 0x85932e4d075615be881398cc765f9f78204033f0ef5f832ac37e732f5f0cbda2 0x481477e62a1d02268127ae89cc58929e09ad5d30229721965ae35965d098a5f630205a7e69f4cb8084f16c7407ed7312994ffbf87ba5eb1aee16682dd324943e))"; + let compiled = do_basic_run(&vec!["run".to_string(), program.to_string()]); + let output = do_basic_brun(&vec![ + "brun".to_string(), + compiled, + "(0x02390b19842e100324163334b16947f66125b76d4fa4a11b9ccdde9b7398e64076)".to_string(), + ]) + .trim() + .to_string(); + assert_eq!(output, "()"); +} + +#[test] +fn test_secp256k1_verify_modern_fail() { + let program = "(mod (S) (include *standard-cl-21*) (secp256k1_verify S 0x935d863e2d28d8e5d399ea8af7393ef11fdffc7d862dcc6b5217a8ef15fb5442 0xbbf0712cc0a283a842011c19682629a5381c5f7ead576defcf12a9a19378e23b087cd0be730dbe78722dcfc81543fca17a30e41070ca2e5b3ae77ccec2cca935))"; + let compiled = do_basic_run(&vec!["run".to_string(), program.to_string()]); + let output = do_basic_brun(&vec![ + "brun".to_string(), + compiled, + "(0x0215043e969dcf616fabe8e8d6b61ddcf6e274c5b04fce957b086dbeb7e899ac63)".to_string(), + ]) + .trim() + .to_string(); + assert!(output.starts_with("FAIL: secp256k1_verify failed")); +} + +#[test] +fn test_secp256k1_verify_classic_succeed() { + let program = "(mod (S) (secp256k1_verify S 0x85932e4d075615be881398cc765f9f78204033f0ef5f832ac37e732f5f0cbda2 0x481477e62a1d02268127ae89cc58929e09ad5d30229721965ae35965d098a5f630205a7e69f4cb8084f16c7407ed7312994ffbf87ba5eb1aee16682dd324943e))"; + let compiled = do_basic_run(&vec!["run".to_string(), program.to_string()]); + let output = do_basic_brun(&vec![ + "brun".to_string(), + compiled, + "(0x02390b19842e100324163334b16947f66125b76d4fa4a11b9ccdde9b7398e64076)".to_string(), + ]) + .trim() + .to_string(); + assert_eq!(output, "()"); +} + +#[test] +fn test_secp256k1_verify_classic_fail() { let program = "(mod (S) (secp256k1_verify S 0x935d863e2d28d8e5d399ea8af7393ef11fdffc7d862dcc6b5217a8ef15fb5442 0xbbf0712cc0a283a842011c19682629a5381c5f7ead576defcf12a9a19378e23b087cd0be730dbe78722dcfc81543fca17a30e41070ca2e5b3ae77ccec2cca935))"; let compiled = do_basic_run(&vec!["run".to_string(), program.to_string()]); let output = do_basic_brun(&vec![ @@ -1352,3 +2396,72 @@ fn test_classic_obeys_operator_choice_at_compile_time_version_0() { .to_string(); assert_eq!(compiled, "FAIL: unimplemented operator 48"); } + +#[test] +fn test_continued_if() { + let prog = indoc! {" +(mod X + (include *strict-cl-21*) + + (defun bigatom (Xs Ys) + (if + Xs (concat (f Xs) (bigatom (r Xs) Ys)) + Ys (concat (f Ys) (bigatom (r Ys) ())) + () + ) + ) + + (bigatom (q . (3 4 5)) X) + )"} + .to_string(); + let compiled = do_basic_run(&vec!["run".to_string(), prog]) + .trim() + .to_string(); + let res = do_basic_brun(&vec![ + "brun".to_string(), + compiled, + "(13 99 144)".to_string(), + ]) + .trim() + .to_string(); + assert_eq!(res.to_string(), "0x0304050d630090"); +} + +#[test] +fn test_preprocess_can_recurse() { + let prog = "resources/tests/strict/test-inner-include.clsp".to_string(); + let res = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + prog.clone(), + ]) + .trim() + .to_string(); + assert_eq!( + res, + "(2 (1 2 (3 5 (1 2 (1 18 5 (1 . 2)) 1) (1 2 (1 16 5 (1 . 1)) 1)) 1) (4 (1) 1))" + ); +} + +#[test] +fn test_assign_rename_tricky() { + let filename = "resources/tests/cse-complex-21.clsp"; + let program = do_basic_run(&vec!["run".to_string(), filename.to_string()]) + .trim() + .to_string(); + + let run_result_11 = do_basic_brun(&vec![ + "brun".to_string(), + program.clone(), + "(11)".to_string(), + ]) + .trim() + .to_string(); + assert_eq!(run_result_11, "506"); + + let run_result_41 = do_basic_brun(&vec!["brun".to_string(), program, "(41)".to_string()]) + .trim() + .to_string(); + assert_eq!(run_result_41, "15375"); +} diff --git a/src/tests/classic/stage_2.rs b/src/tests/classic/stage_2.rs index 8bf43064f..9ac9aecf6 100644 --- a/src/tests/classic/stage_2.rs +++ b/src/tests/classic/stage_2.rs @@ -377,6 +377,9 @@ impl CompilerOpts for TestCompilerOptsPresentsOwnFiles { fn set_start_env(&self, _start_env: Option>) -> Rc { Rc::new(self.clone()) } + fn set_prim_map(&self, _prims: Rc, Rc>>) -> Rc { + Rc::new(self.clone()) + } fn set_disassembly_ver(&self, _ver: Option) -> Rc { Rc::new(self.clone()) } diff --git a/src/tests/compiler/clvm.rs b/src/tests/compiler/clvm.rs index 1354c27c9..f71c1536e 100644 --- a/src/tests/compiler/clvm.rs +++ b/src/tests/compiler/clvm.rs @@ -1,8 +1,6 @@ #[cfg(test)] use rand::prelude::*; #[cfg(test)] -use rand::Rng; -#[cfg(test)] use rand_chacha::ChaChaRng; use num_bigint::ToBigInt; @@ -25,7 +23,7 @@ use crate::tests::classic::run::RandomClvmNumber; use crate::util::Number; -const TEST_TIMEOUT: usize = 1000000; +pub const TEST_TIMEOUT: usize = 1000000; fn test_compiler_clvm(to_run: &String, args: &String) -> Result, RunFailure> { let mut allocator = Allocator::new(); diff --git a/src/tests/compiler/compiler.rs b/src/tests/compiler/compiler.rs index ea916eb48..5554aa602 100644 --- a/src/tests/compiler/compiler.rs +++ b/src/tests/compiler/compiler.rs @@ -3,14 +3,16 @@ use std::rc::Rc; use clvm_rs::allocator::Allocator; +use crate::classic::clvm::__type_compatibility__::bi_one; use crate::classic::clvm_tools::stages::stage_0::DefaultProgramRunner; use crate::compiler::clvm::run; use crate::compiler::compiler::{compile_file, DefaultCompilerOpts}; use crate::compiler::comptypes::{CompileErr, CompilerOpts}; +use crate::compiler::dialect::AcceptedDialect; use crate::compiler::frontend::{collect_used_names_sexp, frontend}; use crate::compiler::rename::rename_in_cons; use crate::compiler::runtypes::RunFailure; -use crate::compiler::sexp::{decode_string, parse_sexp, SExp}; +use crate::compiler::sexp::{decode_string, enlist, parse_sexp, SExp}; use crate::compiler::srcloc::Srcloc; const TEST_TIMEOUT: usize = 1000000; @@ -27,14 +29,23 @@ fn run_string_maybe_opt( content: &String, args: &String, fe_opt: bool, + strict: bool, ) -> Result, CompileErr> { let mut allocator = Allocator::new(); let runner = Rc::new(DefaultProgramRunner::new()); let mut opts: Rc = Rc::new(DefaultCompilerOpts::new(&"*test*".to_string())); let srcloc = Srcloc::start(&"*test*".to_string()); opts = opts - .set_frontend_opt(fe_opt) + .set_frontend_opt(fe_opt && !strict) .set_search_paths(&vec!["resources/tests".to_string()]); + + if strict { + opts = opts.set_dialect(AcceptedDialect { + stepping: Some(21), + strict: true, + }); + } + let sexp_args = parse_sexp(srcloc.clone(), args.bytes())?[0].clone(); compile_file( @@ -51,6 +62,7 @@ fn run_string_maybe_opt( Rc::new(HashMap::new()), Rc::new(x), sexp_args, + None, Some(TEST_TIMEOUT), ) .map_err(|e| match e { @@ -61,7 +73,11 @@ fn run_string_maybe_opt( } pub fn run_string(content: &String, args: &String) -> Result, CompileErr> { - run_string_maybe_opt(content, args, false) + run_string_maybe_opt(content, args, false, false) +} + +pub fn run_string_strict(content: &String, args: &String) -> Result, CompileErr> { + run_string_maybe_opt(content, args, false, true) } // Given some renaming that leaves behind gensym style names with _$_ in them, @@ -157,11 +173,95 @@ fn compile_test_6() { ); } +// odd numbered list +#[test] +fn compile_test_8() { + let result = + compile_string(&"(mod (S) (c S (q . #(2000 3000 4000 5000 6000 7000 8000))))".to_string()) + .unwrap(); + assert_eq!( + result, + "(2 (1 4 5 (1 (2000 3000 . 4000) (5000 . 6000) 7000 . 8000)) (4 (1) 1))".to_string() + ); +} + +// even numbered list +#[test] +fn compile_test_9() { + let result = compile_string(&"(mod (S) (c S (q . #(a b c d))))".to_string()).unwrap(); + assert_eq!( + result, + "(2 (1 4 5 (1 (a . b) c . d)) (4 (1) 1))".to_string() + ); +} + +// word +#[test] +fn compile_test_10() { + let result = compile_string(&"(mod (S) (c S #fake))".to_string()).unwrap(); + assert_eq!(result, "(2 (1 4 5 (1 . fake)) (4 (1) 1))".to_string()); +} + +// op letter +#[test] +fn compile_test_11() { + let result = compile_string(&"(mod (S) (c S #a))".to_string()).unwrap(); + assert_eq!(result, "(2 (1 4 5 (1 . 2)) (4 (1) 1))".to_string()); +} + +// length 1 list +#[test] +fn compile_test_12() { + let result = compile_string(&"(mod (S) (c S (q . #(100))))".to_string()).unwrap(); + assert_eq!(result, "(2 (1 4 5 (1 . 100)) (4 (1) 1))".to_string()); +} + +// length 0 list +#[test] +fn compile_test_13() { + let result = compile_string(&"(mod (S) (c S (q . #())))".to_string()).unwrap(); + assert_eq!(result, "(2 (1 4 5 (1)) (4 (1) 1))".to_string()); +} + +// length 2 list +#[test] +fn compile_test_14() { + let result = compile_string(&"(mod (S) (c S (q . #(a b))))".to_string()).unwrap(); + assert_eq!(result, "(2 (1 4 5 (1 a . b)) (4 (1) 1))".to_string()); +} + +// use structured list in solution +#[test] +fn compile_test_15() { + let result = run_string_maybe_opt( + &"(mod #(a b c) (- (+ a c) b))".to_string(), + &"(100 20 . 10)".to_string(), + true, + false, + ) + .unwrap(); + assert_eq!(result.to_string(), "90".to_string()); +} + +// use structured list in solution +#[test] +fn compile_test_16() { + let result = run_string_maybe_opt( + &"(mod #(a b c) (- (+ a c) b))".to_string(), + &"#(100 20 10)".to_string(), + true, + false, + ) + .unwrap(); + assert_eq!(result.to_string(), "90".to_string()); +} + fn run_test_1_maybe_opt(opt: bool) { let result = run_string_maybe_opt( &"(mod () (defun f (a b) (+ (* a a) b)) (f 3 1))".to_string(), &"()".to_string(), opt, + false, ) .unwrap(); assert_eq!(result.to_string(), "10".to_string()); @@ -189,6 +289,7 @@ fn run_test_2_maybe_opt(opt: bool) { &"(mod (c) (defun f (a b) (+ (* a a) b)) (f 3 c))".to_string(), &"(4)".to_string(), opt, + false, ) .unwrap(); assert_eq!(result.to_string(), "13".to_string()); @@ -209,7 +310,8 @@ fn run_test_3_maybe_opt(opt: bool) { run_string_maybe_opt( &"(mod (arg_one) (defun factorial (input) (if (= input 1) 1 (* (factorial (- input 1)) input))) (factorial arg_one))".to_string(), &"(5)".to_string(), - opt + opt, + false, ).unwrap(); assert_eq!(result.to_string(), "120".to_string()); } @@ -229,7 +331,8 @@ fn run_test_4_maybe_opt(opt: bool) { run_string_maybe_opt( &"(mod () (defun makelist (a) (if a (c (q . 4) (c (f a) (c (makelist (r a)) (q . ())))) (q . ()))) (makelist (q . (1 2 3))))".to_string(), &"()".to_string(), - opt + opt, + false, ).unwrap(); assert_eq!(result.to_string(), "(4 1 (4 2 (4 3 ())))".to_string()); } @@ -245,8 +348,13 @@ fn run_test_4_opt() { } fn run_test_5_maybe_opt(opt: bool) { - let result = - run_string_maybe_opt(&"(mod (a) (list 1 2))".to_string(), &"()".to_string(), opt).unwrap(); + let result = run_string_maybe_opt( + &"(mod (a) (list 1 2))".to_string(), + &"()".to_string(), + opt, + false, + ) + .unwrap(); assert_eq!(result.to_string(), "(1 2)".to_string()); } @@ -265,7 +373,8 @@ fn run_test_6_maybe_opt(opt: bool) { run_string_maybe_opt( &"(mod args (defmacro square (input) (qq (* (unquote input) (unquote input)))) (defun sqre_list (my_list) (if my_list (c (square (f my_list)) (sqre_list (r my_list))) my_list)) (sqre_list args))".to_string(), &"(10 9 8 7)".to_string(), - opt + opt, + false, ).unwrap(); assert_eq!(result.to_string(), "(100 81 64 49)".to_string()); } @@ -285,7 +394,8 @@ fn run_test_7_maybe_opt(opt: bool) { run_string_maybe_opt( &"(mod (PASSWORD_HASH password new_puzhash amount) (defconstant CREATE_COIN 51) (defun check_password (PASSWORD_HASH password new_puzhash amount) (if (= (sha256 password) PASSWORD_HASH) (list (list CREATE_COIN new_puzhash amount)) (x))) (check_password PASSWORD_HASH password new_puzhash amount))".to_string(), &"(0x2ac6aecf15ac3042db34af4863da46111da7e1bf238fc13da1094f7edc8972a1 \"sha256ftw\" 0x12345678 1000000000)".to_string(), - opt + opt, + false, ).unwrap(); assert_eq!( result.to_string(), @@ -308,6 +418,7 @@ fn run_test_8_maybe_opt(opt: bool) { &"(mod (a b) (let ((x (+ a 1)) (y (+ b 1))) (+ x y)))".to_string(), &"(5 8)".to_string(), opt, + false, ) .unwrap(); assert_eq!(result.to_string(), "15".to_string()); @@ -528,6 +639,7 @@ fn run_test_9_maybe_opt(opt: bool) { &"(mod (a) (defun f (i) (let ((x (not i)) (y (* i 2))) (+ x y))) (f a))".to_string(), &"(0)".to_string(), opt, + false, ) .unwrap(); assert_eq!(result.to_string(), "1".to_string()); @@ -548,6 +660,7 @@ fn run_test_10_maybe_opt(opt: bool) { &"(mod (a) (defun f (i) (let ((x (not i)) (y (* i 2))) (+ x y))) (f a))".to_string(), &"(3)".to_string(), opt, + false, ) .unwrap(); assert_eq!(result.to_string(), "6".to_string()); @@ -753,6 +866,7 @@ fn test_collatz_maybe_opt(opt: bool) { .to_string(), &"(4)".to_string(), opt, + false, ) .unwrap(); assert_eq!(result.to_string(), "2"); @@ -792,6 +906,7 @@ fn fancy_nested_let_bindings_should_work() { .to_string(), &"(1 2 3 100 99)".to_string(), false, + false, ) .unwrap(); assert_eq!(result.to_string(), "8"); @@ -810,6 +925,7 @@ fn let_as_argument() { .to_string(), &"(5)".to_string(), false, + false, ) .unwrap(); assert_eq!(result.to_string(), "13"); @@ -829,6 +945,7 @@ fn recursive_let_complicated_arguments() { .to_string(), &"(7 13)".to_string(), false, + false, ) .unwrap(); assert_eq!(result.to_string(), "32"); @@ -862,6 +979,7 @@ fn test_let_structure_access_1() { .to_string(), &"(7 13)".to_string(), false, + false, ) .unwrap(); // a = 1 @@ -906,6 +1024,7 @@ fn test_let_structure_access_2() { .to_string(), &"(7 13)".to_string(), false, + false, ) .unwrap(); // a = 1 @@ -935,6 +1054,7 @@ fn test_let_inline_1() { .to_string(), &"(5)".to_string(), false, + false, ) .unwrap(); assert_eq!(result.to_string(), "11"); @@ -1471,6 +1591,393 @@ fn test_inline_out_of_bounds_diagnostic() { } } +#[test] +fn test_lambda_without_capture_from_function() { + let prog = indoc! {" +(mod (A B) + (include *standard-cl-21*) + (defun FOO () (lambda (X Y) (+ X Y))) + (a (FOO) (list A B)) + )"} + .to_string(); + let res = run_string(&prog, &"(3 4)".to_string()).unwrap(); + assert_eq!(res.to_string(), "7"); +} + +#[test] +fn test_lambda_without_capture() { + let prog = indoc! {" +(mod (A B) + (include *standard-cl-21*) + (a (lambda (X Y) (+ X Y)) (list A B)) + )"} + .to_string(); + let res = run_string(&prog, &"(3 4)".to_string()).unwrap(); + assert_eq!(res.to_string(), "7"); +} + +#[test] +fn test_lambda_with_capture_from_function() { + let prog = indoc! {" +(mod (A B) + (include *standard-cl-21*) + (defun FOO (Z) (lambda ((& Z) X) (- X Z))) + (a (FOO A) (list B)) + )"} + .to_string(); + let res = run_string(&prog, &"(5 19)".to_string()).unwrap(); + assert_eq!(res.to_string(), "14"); +} + +#[test] +fn test_lambda_with_capture() { + let prog = indoc! {" +(mod (A B) + (include *standard-cl-21*) + (a (lambda ((& A) Y) (- Y A)) (list B)) + )"} + .to_string(); + let res = run_string(&prog, &"(5 19)".to_string()).unwrap(); + assert_eq!(res.to_string(), "14"); +} + +#[test] +fn test_lambda_in_let_0() { + let prog = indoc! {" +(mod (A) + (include *standard-cl-21*) + (defun FOO (Z) + (let ((Q (* 2 Z))) + (lambda ((& Q)) (- 100 Q)) + ) + ) + (a (FOO A) ()) + )"} + .to_string(); + let res = run_string(&prog, &"(5)".to_string()).unwrap(); + assert_eq!(res.to_string(), "90"); +} + +#[test] +fn test_lambda_in_let_1() { + let prog = indoc! {" +(mod (A B) + (include *standard-cl-21*) + (defun FOO (Z) + (let ((Q (* 2 Z))) + (lambda ((& Q) X) (- X Q)) + ) + ) + (a (FOO A) (list B)) + )"} + .to_string(); + let res = run_string(&prog, &"(5 19)".to_string()).unwrap(); + assert_eq!(res.to_string(), "9"); +} + +#[test] +fn test_lambda_in_map() { + let prog = indoc! {" +(mod (add-number L) + + (include *standard-cl-21*) + + (defun map (F L) + (if L + (c (a F (list (f L))) (map F (r L))) + () + ) + ) + + (map + (lambda ((& add-number) number) (+ add-number number)) + L + ) + ) +"} + .to_string(); + let res = run_string(&prog, &"(5 (1 2 3 4))".to_string()).unwrap(); + assert_eq!(res.to_string(), "(6 7 8 9)"); +} + +#[test] +fn test_lambda_in_map_with_let_surrounding() { + let prog = indoc! {" +(mod (add-number L) + + (include *standard-cl-21*) + + (defun map (F L) + (if L + (c (a F (list (f L))) (map F (r L))) + () + ) + ) + + (map + (let ((A (* add-number 2))) + (lambda ((& A) number) (+ A number)) + ) + L + ) + ) +"} + .to_string(); + let res = run_string(&prog, &"(5 (1 2 3 4))".to_string()).unwrap(); + assert_eq!(res.to_string(), "(11 12 13 14)"); +} + +#[test] +fn test_map_with_lambda_function_from_env_and_bindings() { + let prog = indoc! {" + (mod (add-number L) + + (include *standard-cl-21*) + + (defun map (F L) + (if L + (c (a F (list (f L))) (map F (r L))) + () + ) + ) + + (defun add-twice (X Y) (+ (* 2 X) Y)) + + (map + (lambda ((& add-number) number) (add-twice add-number number)) + L + ) + )"} + .to_string(); + let res = run_string(&prog, &"(5 (1 2 3 4))".to_string()).unwrap(); + assert_eq!(res.to_string(), "(11 12 13 14)"); +} + +#[test] +fn test_map_with_lambda_function_from_env_no_bindings() { + let prog = indoc! {" + (mod (L) + + (include *standard-cl-21*) + + (defun map (F L) + (if L + (c (a F (list (f L))) (map F (r L))) + () + ) + ) + + (defun sum-list (L) + (if L + (+ (f L) (sum-list (r L))) + () + ) + ) + + (map + (lambda (lst) (sum-list lst)) + L + ) + )"} + .to_string(); + let res = run_string(&prog, &"(((5 10 15) (2 4 8) (3 6 9)))".to_string()).unwrap(); + assert_eq!(res.to_string(), "(30 14 18)"); +} + +#[test] +fn test_lambda_using_let() { + let prog = indoc! {" + (mod (P L) + + (include *standard-cl-21*) + + (defun map (F L) + (if L + (c (a F (list (f L))) (map F (r L))) + () + ) + ) + + (map + (lambda ((& P) item) (let ((composed (c P item))) composed)) + L + ) + )"} + .to_string(); + let res = run_string(&prog, &"(1 (10 20 30))".to_string()).unwrap(); + assert_eq!(res.to_string(), "((1 . 10) (1 . 20) (1 . 30))"); +} + +#[test] +fn test_lambda_using_macro() { + let prog = indoc! {" + (mod (P L) + + (include *standard-cl-21*) + + (defun map (F L) + (if L + (c (a F (list (f L))) (map F (r L))) + () + ) + ) + + (map + (lambda ((& P) item) (list P item)) + L + ) + )"} + .to_string(); + let res = run_string(&prog, &"(1 (10 20 30))".to_string()).unwrap(); + assert_eq!(res.to_string(), "((1 10) (1 20) (1 30))"); +} + +#[test] +fn test_lambda_reduce() { + let prog = indoc! {" + (mod (LST) + (include *standard-cl-21*) + (defun reduce (fun lst init) + (if lst + (reduce fun (r lst) (a fun (list (f lst) init))) + init + ) + ) + + (let + ((capture 100)) + (reduce (lambda ((& capture) (X Y) ACC) (+ (* X Y) ACC capture)) LST 0) + ) + ) + "} + .to_string(); + let res = run_string(&prog, &"(((2 3) (4 9)))".to_string()).unwrap(); + assert_eq!(res.to_string(), "242"); +} + +#[test] +fn test_lambda_as_let_binding() { + let prog = indoc! {" + (mod (P L) + (defun map (F L) + (if L (c (a F (list (f L))) (map F (r L))) ()) + ) + (defun x2 (N) (* 2 N)) + (defun x3p1 (N) (+ 1 (* 3 N))) + (let* ((H (lambda (N) (x2 N))) + (G (lambda (N) (x3p1 N))) + (F (if P G H))) + (map F L) + ) + ) + "} + .to_string(); + let res0 = run_string(&prog, &"(0 (1 2 3))".to_string()).unwrap(); + assert_eq!(res0.to_string(), "(2 4 6)"); + let res1 = run_string(&prog, &"(1 (1 2 3))".to_string()).unwrap(); + assert_eq!(res1.to_string(), "(4 7 10)"); +} + +#[test] +fn test_lambda_mixed_let_binding() { + let prog = indoc! {" + (mod (P L) + (defun map (F L) + (if L (c (a F (list (f L))) (map F (r L))) ()) + ) + (defun x2 (N) (* 2 N)) + (defun x3p1 (N) (+ 1 (* 3 N))) + (let* ((G (lambda (N) (x3p1 N))) + (F (if P G (lambda (N) (x2 N))))) + (map F L) + ) + ) + "} + .to_string(); + let res0 = run_string(&prog, &"(0 (1 2 3))".to_string()).unwrap(); + assert_eq!(res0.to_string(), "(2 4 6)"); + let res1 = run_string(&prog, &"(1 (1 2 3))".to_string()).unwrap(); + assert_eq!(res1.to_string(), "(4 7 10)"); +} + +#[test] +fn test_lambda_hof_1() { + let prog = indoc! {" + (mod (P) + (a (a (lambda ((& P) X) (lambda ((& P X)) (+ P X))) (list 3)) ()) + ) + "} + .to_string(); + let res = run_string(&prog, &"(1)".to_string()).unwrap(); + assert_eq!(res.to_string(), "4"); +} + +#[test] +fn test_lambda_as_argument_to_macro() { + let prog = indoc! {" + (mod (P) + (defun map-f (A L) + (if L (c (a (f L) A) (map-f A (r L))) ()) + ) + (let ((Fs (list (lambda (X) (- X 1)) (lambda (X) (+ X 1)) (lambda (X) (* 2 X)))) + (args (list P))) + (map-f args Fs) + ) + ) + "} + .to_string(); + let res = run_string(&prog, &"(10)".to_string()).unwrap(); + assert_eq!(res.to_string(), "(9 11 20)"); +} + +#[test] +fn test_lambda_as_argument_to_macro_with_inner_let() { + let prog = indoc! {" + (mod (P) + (defun map-f (A L) + (if L (c (a (f L) A) (map-f A (r L))) ()) + ) + (let ((Fs (list (lambda (X) (let ((N (* X 3))) N)) (lambda (X) (+ X 1)) (lambda (X) (* 2 X)))) + (args (list P))) + (map-f args Fs) + ) + ) + "} + .to_string(); + let res = run_string(&prog, &"(10)".to_string()).unwrap(); + assert_eq!(res.to_string(), "(30 11 20)"); +} + +#[test] +fn test_treat_function_name_as_value() { + let prog = indoc! {" +(mod (X) + (include *standard-cl-21*) + (defun G (X) (* 2 X)) + (defun F (X) (G (+ 1 X))) + (a F (list X)) +) + "} + .to_string(); + let res = run_string(&prog, &"(99)".to_string()).expect("should compile"); + assert_eq!(res.to_string(), "200"); +} + +#[test] +fn test_treat_function_name_as_value_filter() { + let prog = indoc! {" + (mod L + (include *standard-cl-21*) + (defun greater-than-3 (X) (> X 3)) + (defun filter (F L) (let ((rest (filter F (r L)))) (if L (if (a F (list (f L))) (c (f L) rest) rest) ()))) + (filter greater-than-3 L) + ) + "} + .to_string(); + let res = run_string(&prog, &"(1 2 3 4 5)".to_string()).expect("should compile"); + assert_eq!(res.to_string(), "(4 5)"); +} + #[test] fn test_inline_in_assign_not_actually_recursive() { let prog = indoc! {" @@ -1526,6 +2033,36 @@ fn test_simple_rest_call_inline() { assert_eq!(res.to_string(), "768"); } +#[test] +fn test_simple_rest_lambda() { + let prog = indoc! {" +(mod (Z X) + (include *standard-cl-21*) + + (defun silly-lambda-consumer (Q F) (a F (list Q))) + + (silly-lambda-consumer &rest (list X (lambda ((& Z) X) (* Z X)))) + )"} + .to_string(); + let res = run_string(&prog, &"(13 51)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "663"); +} + +#[test] +fn test_lambda_in_lambda() { + let prog = indoc! {" +(mod (Z X) + (include *standard-cl-21*) + + (defun silly-lambda-consumer (Q F) (a F (list Q))) + + (a (silly-lambda-consumer X (lambda ((& Z) X) (lambda ((& Z X)) (* Z X)))) ()) + )"} + .to_string(); + let res = run_string(&prog, &"(13 51)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "663"); +} + #[test] fn test_let_in_rest_0() { let prog = indoc! {" @@ -1556,6 +2093,243 @@ fn test_let_in_rest_1() { assert_eq!(res.to_string(), "108"); } +#[test] +fn test_lambda_override_name_arg_let_capture() { + let prog = indoc! {" +(mod (X) + (include *standard-cl-21*) + + (defun F (overridden) + (let ((overridden (* 3 overridden))) + (lambda ((& overridden) z) (+ overridden z)) + ) + ) + + (a (F X) (list 17)) + )"} + .to_string(); + let res = run_string(&prog, &"(11)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "50"); +} + +#[test] +fn test_lambda_override_name_arg_let_with_let_in_lambda_1() { + let prog = indoc! {" +(mod (X) + (include *standard-cl-21*) + + (defun F (overridden) + (let ((overridden (* 3 overridden))) + (lambda ((& overridden) z) + (let + ((z (+ 123 z))) + (+ overridden z) + ) + ) + ) + ) + + (a (F X) (list 17)) + )"} + .to_string(); + let res = run_string(&prog, &"(11)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "173"); +} + +#[test] +fn test_lambda_override_name_arg_let_with_let_in_lambda_2() { + let prog = indoc! {" +(mod (X) + (include *standard-cl-21*) + + (defun F (overridden) + (let ((overridden (* 3 overridden))) + (lambda ((& overridden) z) + (let + ((overridden (+ 123 overridden))) + (+ overridden z) + ) + ) + ) + ) + + (a (F X) (list 17)) + )"} + .to_string(); + let res = run_string(&prog, &"(11)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "173"); +} + +#[test] +fn test_lambda_override_name_arg_assign_with_assign_in_lambda_1() { + let prog = indoc! {" +(mod (X) + (include *standard-cl-21*) + + (defun F (Z) + (assign overridden (* 3 Z) + (lambda ((& overridden) z) + (let + ((z (+ 123 z))) + (+ overridden z) + ) + ) + ) + ) + + (a (F X) (list 17)) + )"} + .to_string(); + let res = run_string(&prog, &"(11)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "173"); +} + +#[test] +fn test_lambda_override_name_arg_let_with_assign_in_lambda_1() { + let prog = indoc! {" +(mod (X) + (include *standard-cl-21*) + + (defun F (overridden) + (let ((overridden (* 3 overridden))) ;; overridden = 33 + (lambda ((& overridden) z) ;; overridden = 33 + (assign overridden (+ 123 z) ;; overridden = 17 + 123 = 140 + (+ overridden z) ;; 157 + ) + ) + ) + ) + + (a (F X) (list 17)) + )"} + .to_string(); + let res = run_string(&prog, &"(11)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "157"); +} + +#[test] +fn test_lambda_override_name_arg_let_with_let_in_lambda_3() { + let prog = indoc! {" +(mod (X) + (include *standard-cl-21*) + + (defun F (overridden) + (let ((overridden (* 3 overridden))) ;; overridden = 33 + (lambda ((& overridden) z) ;; overridden = 33 + (let ((overridden (+ 123 z))) ;; overridden = 17 + 123 = 140 + (+ overridden z) ;; 157 + ) + ) + ) + ) + + (a (F X) (list 17)) + )"} + .to_string(); + let res = run_string(&prog, &"(11)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "157"); +} + +#[test] +fn test_lambda_override_name_arg_let_with_assign_twice_in_lambda() { + let prog = indoc! {" +(mod (X) + (include *standard-cl-21*) + + (defun F (overridden) + (let ((overridden (* 3 overridden))) ;; overridden = 33 + (lambda ((& overridden) y z) ;; overridden = 33 + (assign + overridden (+ 123 z) ;; overridden = 123 + 17 = 140 + y (+ 191 z overridden) ;; y = 191 + 17 + 140 = 348 + (+ overridden z y) ;; 505 + ) + ) + ) + ) + + (a (F X) (list 13 17)) + )"} + .to_string(); + let res = run_string(&prog, &"(11)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "505"); +} + +#[test] +fn test_lambda_override_name_arg_let_with_let_twice_in_lambda() { + let prog = indoc! {" +(mod (X) + (include *standard-cl-21*) + + (defun F (overridden) + (let ((overridden (* 3 overridden))) ;; overridden = 33 + (lambda ((& overridden) y z) ;; overridden = 33 + (let + ((overridden (+ 123 z))) ;; overridden = 123 + 17 = 140 + (let ((y (+ 191 z overridden))) ;; y = 191 + 17 + 140 = 348 + (+ overridden z y) ;; 505 + ) + ) + ) + ) + ) + + (a (F X) (list 13 17)) + )"} + .to_string(); + let res = run_string(&prog, &"(11)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "505"); +} + +#[test] +fn test_lambda_override_name_arg_let_with_let_star_twice_in_lambda() { + let prog = indoc! {" +(mod (X) + (include *standard-cl-21*) + + (defun F (overridden) + (let ((overridden (* 3 overridden))) ;; overridden = 33 + (lambda ((& overridden) y z) ;; overridden = 33 + (let* + ((overridden (+ 123 z)) ;; overridden = 123 + 17 = 140 + (y (+ 191 z overridden))) ;; y = 191 + 17 + 140 = 348 + (+ overridden z y) ;; 505 + ) + ) + ) + ) + + (a (F X) (list 13 17)) + )"} + .to_string(); + let res = run_string(&prog, &"(11)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "505"); +} + +#[test] +fn test_lambda_let_override_in_binding() { + let prog = indoc! {" +(mod (X) + (include *standard-cl-21*) + + (defun F (overridden) + (let ((overridden (* 3 overridden))) ;; overridden = 33 + (lambda ((& overridden) y z) ;; overridden = 33 + (let + ((y (+ 191 z (let ((overridden (+ 123 z))) overridden)))) ;; overridden = 123 + 17 = 140, y = 191 + 17 + 140 = 348 + (+ overridden z y) ;; 33 + 17 + 348 = 398 + ) + ) + ) + ) + + (a (F X) (list 13 17)) + )"} + .to_string(); + let res = run_string(&prog, &"(11)".to_string()).expect("should compile and run"); + assert_eq!(res.to_string(), "398"); +} + #[test] fn test_rename_in_compileform_run() { let prog = indoc! {" @@ -1614,3 +2388,48 @@ fn test_rename_in_compileform_simple() { let renamed_helperform = squash_name_differences(helper_f[0].to_sexp()).expect("should rename"); assert_eq!(renamed_helperform.to_string(), desired_outcome); } + +#[test] +fn test_handle_explicit_empty_atom() { + let filename = "*empty-atom-test*"; + let srcloc = Srcloc::start(filename); + let opts = Rc::new(DefaultCompilerOpts::new(filename)).set_dialect(AcceptedDialect { + stepping: Some(21), + strict: true, + }); + + let atom = |s: &str| Rc::new(SExp::Atom(srcloc.clone(), s.as_bytes().to_vec())); + + let sublist = |l: &[Rc]| Rc::new(enlist(srcloc.clone(), l)); + + let nil = Rc::new(SExp::Nil(srcloc.clone())); + + let program = sublist(&[ + atom("mod"), + nil.clone(), + sublist(&[atom("include"), atom("*strict-cl-21*")]), + sublist(&[ + atom("+"), + atom(""), + Rc::new(SExp::Integer(srcloc.clone(), bi_one())), + ]), + ]); + let mut allocator = Allocator::new(); + let mut symbols = HashMap::new(); + let runner = Rc::new(DefaultProgramRunner::new()); + + let compiled = opts + .compile_program(&mut allocator, runner.clone(), program, &mut symbols) + .expect("should compile"); + let outcome = run( + &mut allocator, + runner, + opts.prim_map(), + Rc::new(compiled), + nil, + None, + None, + ) + .expect("should run"); + assert_eq!(outcome.to_string(), "1"); +} diff --git a/src/tests/compiler/evaluate.rs b/src/tests/compiler/evaluate.rs index a76033657..df42a5fa0 100644 --- a/src/tests/compiler/evaluate.rs +++ b/src/tests/compiler/evaluate.rs @@ -14,12 +14,14 @@ use crate::compiler::srcloc::Srcloc; use crate::classic::clvm_tools::stages::stage_0::DefaultProgramRunner; use crate::util::ErrInto; +use crate::tests::compiler::compiler::squash_name_differences; + fn shrink_expr_from_string(s: String) -> Result { let mut allocator = Allocator::new(); let runner = Rc::new(DefaultProgramRunner::new()); let opts = Rc::new(DefaultCompilerOpts::new(&"*program*".to_string())); let loc = Srcloc::start(&"*program*".to_string()); - parse_sexp(loc.clone(), s.bytes()) + let result = parse_sexp(loc.clone(), s.bytes()) .err_into() .and_then(|parsed_program| { return frontend(opts.clone(), &parsed_program); @@ -34,8 +36,11 @@ fn shrink_expr_from_string(s: String) -> Result { false, Some(EVAL_STACK_LIMIT), ); - }) - .map(|result| result.to_sexp().to_string()) + })?; + + let result_sexp = + squash_name_differences(result.to_sexp()).map_err(|e| CompileErr(loc.clone(), e))?; + Ok(result_sexp.to_string()) } #[test] @@ -119,6 +124,14 @@ fn test_simple_fe_opt_compile_1() { ); } +#[test] +fn test_lambda_eval_1() { + assert_eq!( + shrink_expr_from_string("(lambda (X) (+ X 1))".to_string()).unwrap(), + "(lambda (X_$_A) (+ X_$_A 1))".to_string() + ); +} + #[test] fn test_assign_simple_form_0() { assert_eq!( @@ -127,6 +140,14 @@ fn test_assign_simple_form_0() { ); } +#[test] +fn test_lambda_eval_2() { + assert_eq!( + shrink_expr_from_string("(a (lambda (X) (+ X 1)) (list 3))".to_string()).unwrap(), + "(q . 4)".to_string() + ); +} + #[test] fn test_assign_simple_form_1() { assert_eq!( @@ -135,6 +156,28 @@ fn test_assign_simple_form_1() { ); } +#[test] +fn test_lambda_eval_3() { + assert_eq!( + shrink_expr_from_string( + "(let ((L 10)) (a (lambda ((& L) X) (+ X L)) (list 3)))".to_string() + ) + .unwrap(), + "(q . 13)".to_string() + ); +} + +#[test] +fn test_lambda_eval_4() { + assert_eq!( + shrink_expr_from_string( + "(a (let ((L 10)) (lambda ((& L) X) (+ X L))) (list 3))".to_string() + ) + .unwrap(), + "(q . 13)".to_string() + ); +} + #[test] fn test_assign_simple_form_2() { assert_eq!( diff --git a/src/tests/compiler/mod.rs b/src/tests/compiler/mod.rs index 5f691cbe0..c5f3e205e 100644 --- a/src/tests/compiler/mod.rs +++ b/src/tests/compiler/mod.rs @@ -9,9 +9,12 @@ mod cldb; mod clvm; mod compiler; mod evaluate; +mod optimizer; +mod preprocessor; mod repl; mod restargs; mod runtypes; +mod singleton; mod srcloc; mod types; mod usecheck; diff --git a/src/tests/compiler/optimizer/bodyform.rs b/src/tests/compiler/optimizer/bodyform.rs new file mode 100644 index 000000000..bb09b500d --- /dev/null +++ b/src/tests/compiler/optimizer/bodyform.rs @@ -0,0 +1,316 @@ +use std::borrow::Borrow; +use std::rc::Rc; + +use regex::Regex; + +use crate::compiler::compiler::DefaultCompilerOpts; +use crate::compiler::comptypes::{BodyForm, CompileForm, CompilerOpts}; +use crate::compiler::frontend::{compile_bodyform, frontend}; +use crate::compiler::optimize::bodyform::{ + replace_in_bodyform, retrieve_bodyform, visit_detect_in_bodyform, BodyformPathArc, + PathDetectVisitorResult, +}; +use crate::compiler::sexp::parse_sexp; +use crate::compiler::srcloc::Srcloc; + +#[test] +fn test_bodyform_simple_traversal_0() { + let progfile = "*test*"; + let srcloc = Srcloc::start(progfile); + let parsed = parse_sexp( + srcloc, + indoc! {" +(mod () + (call1 + (let ((A 99) (B test)) (+ A B)) + (call2 + (mod () z) + (lambda () r) + ) + (call3 9) + ) + )"} + .bytes(), + ) + .expect("should parse"); + let opts: Rc = Rc::new(DefaultCompilerOpts::new(progfile)); + let compiled = frontend(opts.clone(), &parsed).expect("should fe"); + + let tests: &[(Vec, Option<&str>)] = &[ + ( + vec![ + BodyformPathArc::CallArgument(1), + BodyformPathArc::LetBinding(0), + ], + Some(r"99"), + ), + ( + vec![ + BodyformPathArc::CallArgument(2), + BodyformPathArc::CallArgument(1), + ], + Some(r"\(mod \(\) z\)"), + ), + ( + vec![BodyformPathArc::CallArgument(1), BodyformPathArc::BodyOf], + Some(r"\([+] A_[$]_[0-9]+ B_[$]_[0-9]+\)"), + ), + ( + vec![ + BodyformPathArc::CallArgument(1), + BodyformPathArc::LetBinding(10), + ], + None, + ), + ( + vec![ + BodyformPathArc::CallArgument(1), + BodyformPathArc::BodyOf, + BodyformPathArc::BodyOf, + ], + None, + ), + ]; + for (traversal1, want) in tests.iter() { + let retrieved1 = retrieve_bodyform(&traversal1, compiled.exp.borrow(), &|b| b.clone()); + if let Some(r) = want { + let re = Regex::new(r).unwrap(); + assert!(re.is_match(&retrieved1.unwrap().to_sexp().to_string())); + } else { + assert!(retrieved1.is_none()); + } + } +} + +#[test] +fn test_replace_in_bodyform() { + let progfile = "*test*"; + let srcloc = Srcloc::start(progfile); + let parsed = parse_sexp( + srcloc.clone(), + indoc! {" +(mod () + (call1 + (let ((A 99) (B test)) (+ A B)) + (call2 + (mod () z) + (lambda () r) + ) + (call3 9) + ) + )"} + .bytes(), + ) + .expect("should parse"); + let opts: Rc = Rc::new(DefaultCompilerOpts::new(progfile)); + let compiled = frontend(opts.clone(), &parsed).expect("should fe"); + let compile_body = |b: &str| { + let new_parsed = parse_sexp(srcloc.clone(), b.bytes()).unwrap(); + compile_bodyform(opts.clone(), new_parsed[0].clone()).unwrap() + }; + + // replacement-list, replace_with, expect + let tests: &[(Vec, &str, Option<&str>)] = &[ + ( + vec![ + BodyformPathArc::CallArgument(1), + BodyformPathArc::BodyOf, + BodyformPathArc::CallArgument(2), + ], + "()", + Some( + r"(call1 (let ((A_[$]_[0-9]+ 99) (B_[$]_[0-9]+ test)) ([+] A_[$]_[0-9]+ ())) (call2 (mod () z) (lambda () r)) (call3 9))", + ), + ), + ( + vec![ + BodyformPathArc::CallArgument(1), + BodyformPathArc::LetBinding(1), + ], + "()", + Some( + r"(call1 (let ((A_[$]_[0-9]+ 99) (B_[$]_[0-9]+ ())) ([+] A_[$]_[0-9]+ B_[$]_[0-9]+)) (call2 (mod () z) (lambda () r)) (call3 9))", + ), + ), + ( + vec![ + BodyformPathArc::CallArgument(2), + BodyformPathArc::CallArgument(1), + BodyformPathArc::BodyOf, + ], + "()", + Some( + r"(call1 (let ((A_[$]_[0-9]+ 99) (B_[$]_[0-9]+ test)) ([+] A_[$]_[0-9]+ B_[$]_[0-9]+)) (call2 (mod () ()) (lambda () r)) (call3 9))", + ), + ), + ( + vec![ + BodyformPathArc::CallArgument(2), + BodyformPathArc::CallArgument(2), + BodyformPathArc::BodyOf, + ], + "()", + Some( + r"(call1 (let ((A_[$]_[0-9]+ 99) (B_[$]_[0-9]+ test)) ([+] A_[$]_[0-9]+ B_[$]_[0-9]+)) (call2 (mod () z) (lambda () ())) (call3 9))", + ), + ), + ]; + + for (path, replacement, expect) in tests.iter() { + eprintln!("replacement {replacement}"); + let replace_spec = vec![PathDetectVisitorResult { + path: path.clone(), + subexp: compile_body(*replacement), + context: (), + }]; + let replaced = replace_in_bodyform( + &replace_spec, + compiled.exp.borrow(), + &|spec: &PathDetectVisitorResult<()>, _old: &BodyForm| spec.subexp.clone(), + ); + if let Some(r) = expect { + let got = replaced.unwrap().to_sexp().to_string(); + eprintln!("got {got}"); + eprintln!("want {r}"); + let escaped_re = r.replace("(", r"\(").replace(")", r"\)"); + let re = Regex::new(&escaped_re).unwrap(); + assert!(re.is_match(&got)); + } else { + assert!(replaced.is_none()); + } + } +} + +fn make_test_case_for_visitor(program: &str) -> CompileForm { + let progfile = "*test*"; + let srcloc = Srcloc::start(progfile); + let parsed = parse_sexp(srcloc.clone(), program.bytes()).expect("should parse"); + let opts: Rc = Rc::new(DefaultCompilerOpts::new(progfile)); + frontend(opts.clone(), &parsed).expect("should fe") +} + +#[test] +fn test_visitor_0() { + let compiled = make_test_case_for_visitor(indoc! {" +(mod () + (call1 + (let ((A 99) (B test)) (+ A B)) + (call2 + (mod () z) + (lambda () r) + ) + (call3 9) + ) + )"}); + let res = visit_detect_in_bodyform( + &|_path, _orig, _here| { + let e: Result, ()> = Err(()); + e + }, + compiled.exp.borrow(), + ); + assert!(res.is_err()); + let res = visit_detect_in_bodyform( + &|_path, _orig, here| { + if here.to_sexp().to_string() == "z" { + let res: Result, ()> = Ok(Some(())); + return res; + } + Ok(None) + }, + compiled.exp.borrow(), + ) + .unwrap(); + assert_eq!(res.len(), 1); + assert_eq!(res[0].subexp.to_sexp().to_string(), "z"); + assert_eq!( + res[0].path, + vec![ + BodyformPathArc::CallArgument(2), + BodyformPathArc::CallArgument(1), + BodyformPathArc::BodyOf + ] + ); + let res = visit_detect_in_bodyform( + &|_path, _orig, here| { + if here.to_sexp().to_string() == "r" || here.to_sexp().to_string() == "99" { + let res: Result, ()> = Ok(Some(())); + return res; + } + Ok(None) + }, + compiled.exp.borrow(), + ) + .unwrap(); + assert_eq!(res.len(), 2); + assert_eq!(res[0].subexp.to_sexp().to_string(), "99"); + assert_eq!( + res[0].path, + vec![ + BodyformPathArc::CallArgument(1), + BodyformPathArc::LetBinding(0) + ] + ); + assert_eq!(res[1].subexp.to_sexp().to_string(), "r"); + assert_eq!( + res[1].path, + vec![ + BodyformPathArc::CallArgument(2), + BodyformPathArc::CallArgument(2), + BodyformPathArc::BodyOf + ] + ); +} + +#[test] +fn test_visitor_rest_alone() { + let compiled = make_test_case_for_visitor(indoc! {" + (mod (X) + (F &rest X) + ) + "}); + let res = visit_detect_in_bodyform( + &|_path, _orig, here| { + if here.to_sexp().to_string() == "X" { + let res: Result, ()> = Ok(Some(())); + return res; + } + + Ok(None) + }, + compiled.exp.borrow(), + ) + .unwrap(); + assert_eq!(res.len(), 1); + assert_eq!(res[0].path, vec![BodyformPathArc::CallArgument(1)]); +} + +#[test] +fn test_visitor_rest_with_list() { + let compiled = make_test_case_for_visitor(indoc! {" + (mod (X) + (F X &rest (F &rest X)) + ) + "}); + let res = visit_detect_in_bodyform( + &|_path, _orig, here| { + if here.to_sexp().to_string() == "X" { + let res: Result, ()> = Ok(Some(())); + return res; + } + + Ok(None) + }, + compiled.exp.borrow(), + ) + .unwrap(); + assert_eq!(res.len(), 2); + assert_eq!(res[0].path, vec![BodyformPathArc::CallArgument(1)]); + assert_eq!( + res[1].path, + vec![ + BodyformPathArc::CallArgument(2), + BodyformPathArc::CallArgument(1) + ] + ); +} diff --git a/src/tests/compiler/optimizer/cse.rs b/src/tests/compiler/optimizer/cse.rs new file mode 100644 index 000000000..b4cfd1ad8 --- /dev/null +++ b/src/tests/compiler/optimizer/cse.rs @@ -0,0 +1,957 @@ +use num_bigint::ToBigInt; +use rand::prelude::*; +use regex::Regex; + +use std::borrow::Borrow; +use std::collections::{BTreeMap, BTreeSet, HashMap}; +use std::rc::Rc; + +use clvmr::allocator::Allocator; + +use crate::classic::clvm::__type_compatibility__::bi_one; +use crate::classic::clvm_tools::stages::stage_0::DefaultProgramRunner; + +use crate::compiler::clvm::run; +use crate::compiler::compiler::{compile_from_compileform, DefaultCompilerOpts}; +use crate::compiler::comptypes::{BodyForm, CompileForm, CompilerOpts, DefunData, HelperForm}; +use crate::compiler::dialect::AcceptedDialect; +use crate::compiler::frontend::compile_bodyform; +use crate::compiler::optimize::cse::cse_optimize_bodyform; +use crate::compiler::optimize::get_optimizer; +use crate::compiler::sexp::{enlist, parse_sexp, SExp}; +use crate::compiler::srcloc::Srcloc; +use crate::compiler::CompileContextWrapper; + +use crate::tests::classic::run::{do_basic_brun, do_basic_run}; +use crate::tests::compiler::clvm::TEST_TIMEOUT; +use crate::tests::util::RngLFSR; + +#[test] +fn smoke_test_cse_optimization() { + let filename = "*test*"; + let source = indoc! {" + (a (i Q + (com (G (- Q 1) (* (+ 1 Q) R))) + (com (* (+ 1 Q) R)) + ) 1)"} + .to_string(); + let srcloc = Srcloc::start(filename); + let opts: Rc = Rc::new(DefaultCompilerOpts::new(filename)); + let parsed = parse_sexp(srcloc.clone(), source.bytes()).expect("should parse"); + let bodyform = compile_bodyform(opts.clone(), parsed[0].clone()).expect("should compile"); + let cse_transformed = + cse_optimize_bodyform(&srcloc, b"test", &bodyform).expect("should cse optimize"); + let re_def = r"(let ((cse_[$]_[0-9]+ ([*] ([+] 1 Q) R))) (a (i Q (com (G (- Q 1) cse_[$]_[0-9]+)) (com cse_[$]_[0-9]+)) 1))".replace("(", r"\(").replace(")",r"\)"); + let re = Regex::new(&re_def).expect("should become a regex"); + assert!(re.is_match(&cse_transformed.to_sexp().to_string())); +} + +#[test] +fn test_cse_tricky() { + let filename = "resources/tests/strict/cse-complex-1.clsp"; + let program = do_basic_run(&vec!["run".to_string(), filename.to_string()]) + .trim() + .to_string(); + + let run_result_11 = do_basic_brun(&vec![ + "brun".to_string(), + program.clone(), + "(11)".to_string(), + ]) + .trim() + .to_string(); + assert_eq!(run_result_11, "506"); + + let run_result_41 = do_basic_brun(&vec!["brun".to_string(), program, "(41)".to_string()]) + .trim() + .to_string(); + assert_eq!(run_result_41, "15375"); +} + +#[test] +fn test_cse_tricky_lambda() { + let filename = "resources/tests/strict/cse-complex-1-lambda.clsp"; + let program = do_basic_run(&vec!["run".to_string(), filename.to_string()]) + .trim() + .to_string(); + + let run_result_11 = do_basic_brun(&vec![ + "brun".to_string(), + program.clone(), + "(11)".to_string(), + ]) + .trim() + .to_string(); + assert_eq!(run_result_11, "5566"); + + let run_result_41 = do_basic_brun(&vec![ + "brun".to_string(), + program.clone(), + "(41)".to_string(), + ]) + .trim() + .to_string(); + assert_eq!(run_result_41, "0x099e67"); + + let run_result_5 = do_basic_brun(&vec!["brun".to_string(), program, "(5)".to_string()]) + .trim() + .to_string(); + assert_eq!(run_result_5, "240"); +} + +// Ensure that we're sorting CSE rounds to apply by dominance so we do inner +// replacements before outer ones. Any that aren't dominated don't have an +// order that matters. +#[test] +fn test_cse_dominance_sorting() { + let filename = "resources/tests/strict/cse-test-no-dom.clsp"; + let program = do_basic_run(&vec!["run".to_string(), filename.to_string()]) + .trim() + .to_string(); + let run_result = do_basic_brun(&vec![ + "brun".to_string(), + "-n".to_string(), + program, + "(((3 3) (2 1 13 19) (5 5) (7 7)))".to_string(), + ]) + .trim() + .to_string(); + assert_eq!(run_result, "(13 19)"); +} + +// Test out atomsort from bram's chialisp +#[test] +fn test_atomsort_bad_ref_simplified() { + let filename = "resources/tests/strict/csecond.clsp"; + + let program = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + filename.to_string(), + ]) + .trim() + .to_string(); + + let run_result = do_basic_brun(&vec![ + "brun".to_string(), + "-n".to_string(), + program, + "((99 101 103))".to_string(), + ]) + .trim() + .to_string(); + + // Expect test5 + assert_eq!(run_result, "\"test5\""); +} + +#[test] +fn test_atomsort_bad_ref() { + let filename = "resources/tests/strict/test_atomsort.clsp"; + + let program = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + filename.to_string(), + ]) + .trim() + .to_string(); + + let run_result_empty = do_basic_brun(&vec![ + "brun".to_string(), + "-n".to_string(), + program.clone(), + "(())".to_string(), + ]) + .trim() + .to_string(); + + // Expect a sorted list, descending order. + assert_eq!(run_result_empty, "()"); + + let run_result_one_item = do_basic_brun(&vec![ + "brun".to_string(), + "-n".to_string(), + program.clone(), + "((0x100001))".to_string(), + ]) + .trim() + .to_string(); + + assert_eq!(run_result_one_item, "(0x100001)"); + + let run_result_two_items = do_basic_brun(&vec![ + "brun".to_string(), + "-n".to_string(), + program.clone(), + "((0x100001 0x100002))".to_string(), + ]) + .trim() + .to_string(); + + assert_eq!(run_result_two_items, "(0x100002 0x100001)"); + + let run_result_three_items = do_basic_brun(&vec![ + "brun".to_string(), + "-n".to_string(), + program, + "((0x100001 0x100003 0x100002))".to_string(), + ]) + .trim() + .to_string(); + + assert_eq!(run_result_three_items, "(0x100003 0x100002 0x100001)"); +} + +#[test] +fn test_tricky_handcalc_example() { + let filename = "resources/tests/strict/cse_tricky_assign.clsp"; + + let program = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/game-referee-after-cl21".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), + filename.to_string(), + ]) + .trim() + .to_string(); + + eprintln!("{program}"); + assert!(!program.contains(":")); + + let run_result = do_basic_brun(&vec![ + "brun".to_string(), + "-n".to_string(), + program, + "((13 . 1) (12 . 1) (10 . 1) (6 . 2) (5 . 2))".to_string(), + ]) + .trim() + .to_string(); + + assert_eq!(run_result, "31"); +} + +// Produce trees of CSE eligible forms and challenge the CSE optimizer. +// +// Things that might trip up CSE: +// +// A cse occurrence is in a lambda +// A cse occurrence is in an assign or let binding +// A cse occurrence is in an assign or let body +// A cse occurrence is in an if condition +// A cse occurrence is in a conditional branch of an if +// A cse occurrence dominates another +// apply is weird + +// Generate expressions of the form +// +// Imagining a random tree structure, we'll generate a program that retrieves +// a few particular values in the tree based on the presence or absence of other +// values. +// +// If we evaluate it in the wrong order, it'll fail, because we'll ensure that +// earlier checks gate later checks at runtime. +// +// Imagine +// +// 50 +// 25 75 +// 12 37 62 87 +// 6 18 31 43 56 68 81 93 +// +// Each tree node is (v l . r) +// +// So we can write a function like: +// +// (if (select-tree tree "") +// (if (select-tree tree "l") +// (if (all (select-tree tree "ll") (select-tree "llr") (select-tree tree "r") (select-tree tree "rl")) +// (select-tree tree "llrl") +// (select-tree tree "ll") +// ) +// ... +// +// Choose a few nodes from the tree along with nodes to return when those nodes are +// present. +// +// ((37 . 18) (75 . 56) (87 . 18) (56 . 68)) +// +// We choose points along the paths to each node to insert checks +// +// paths: +// +// -- checks +// (50 25 37 31 . 50) +// (50 25 37 . 18) +// (50 75 . 56) +// (50 75 62 56 . 68) +// (50 75 87 . 18) +// -- returns +// (50) +// (50 25 12 18) +// (50 75 62 56) +// (50 75 62 68) +// -- set +// (12 18 25 37 50 56 62 68 75 87) +// -- choose gates (not leaves) +// ((12) 18 25 37 50 56 62 68 (75) 87) +// +// Then organize them by their relationships to the gates +// +// ((12 18) (75 56 62 68 87) 25 37 50) +// +// Find out which rows are gated by which gates: +// +// Must be sorted by dominance +// (50 25 37 31 . 50) -- not gated +// (50 25 37 . 18) -- gated by 12 +// (50 75 62 56 . 68) -- gated by 75 +// (50 75 87 . 18) -- gated by 12 and 75 +// (50 75 . 56) -- gated by 75 +// +// First write out a skeleton that mirrors these choices: +// (if +// (all +// ;; path to check +// (select-tree tree "") (select-tree tree "l") (select-tree tree "lr") (select-tree tree "lrl") +// ;; path to target (if not subsumed) +// ;; checks here if needed. +// ) +// +// (select-tree tree "") +// +// Next paths (gated by 12) +// (if +// (all (select-tree tree "") (select-tree tree "l") (select-tree tree "ll")) +// ;; Expressions gated by 12 +// (if (all (select-tree tree "") (select-tree tree "l") (select-tree tree "lr") (select-tree tree "lllr")) +// (select-tree tree "lllr") +// ;; also gated by 75 +// (if (all (select-tree tree "") (select-tree tree "r")) +// (if (all (select-tree tree "") (select-tree tree "r") (select-tree tree "rl") (select-tree tree "rll") (select-tree tree "rlr")) +// (select-tree tree "rlr") +// ;; Others downstream (50 75 . 56) is after gated by 12 and 75 +// (if (all (select-tree tree "") (select-tree tree "r") (select-tree tree "rl") (select-tree tree "rll")) +// (select-tree tree "rll") +// ... + +struct GenerateTrickyCSE { + pub numbers: BTreeSet, + pub tree: TreeNode, + pub choices: Vec, +} + +#[derive(Default, Clone, Debug)] +struct TreeNode { + pub number: u16, + pub left: Option>, + pub right: Option>, +} + +fn generate_option(srcloc: Srcloc, opt: Option<&Rc>, filter: &F) -> SExp +where + F: Fn(&TreeNode) -> bool, +{ + if let Some(r) = opt { + if filter(r) { + return r.generate(srcloc, filter); + } + } + + SExp::Nil(srcloc) +} + +impl TreeNode { + fn generate(&self, srcloc: Srcloc, filter: &F) -> SExp + where + F: Fn(&TreeNode) -> bool, + { + let n = SExp::Integer(srcloc.clone(), self.number.to_bigint().unwrap()); + if self.left.is_none() && self.right.is_none() { + n + } else { + let a = generate_option(srcloc.clone(), self.left.as_ref(), filter); + let b = generate_option(srcloc.clone(), self.right.as_ref(), filter); + enlist(srcloc, &[Rc::new(a), Rc::new(b), Rc::new(n)]) + } + } +} + +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug)] +enum Direction { + L, + R, +} + +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug)] +struct TreeChoice { + pub path: Vec, +} + +impl TreeChoice { + pub fn prerequisites(&self) -> BTreeSet { + self.path + .iter() + .enumerate() + .map(|(i, _)| TreeChoice { + path: self.path.iter().take(i).cloned().collect(), + }) + .collect() + } + + pub fn contains(&self, other: &TreeChoice) -> bool { + self.prerequisites().contains(other) + } + + pub fn condition(&self) -> Rc { + let srcloc = Srcloc::start("*tree-choice-condition*"); + let mut condition = Rc::new(BodyForm::Value(SExp::Atom(srcloc.clone(), b"arg".to_vec()))); + for p in self.path.iter() { + let op = match p { + Direction::L => b"f", + Direction::R => b"r", + }; + condition = Rc::new(BodyForm::Call( + srcloc.clone(), + vec![ + Rc::new(BodyForm::Value(SExp::Atom(srcloc.clone(), op.to_vec()))), + condition, + ], + None, + )); + } + condition + } + + pub fn conditions(&self, myself: bool, prev: Option>) -> Vec> { + let mut condition_vec = prev.map(|b| vec![b.clone()]).unwrap_or_else(|| vec![]); + let mut prerequisite_conditions = + self.prerequisites().iter().map(|p| p.condition()).collect(); + condition_vec.append(&mut prerequisite_conditions); + if myself { + condition_vec.push(self.condition()); + } + condition_vec + } +} + +fn all_conditions(c: &[Rc]) -> Rc { + if c.is_empty() { + return Rc::new(BodyForm::Quoted(SExp::Integer( + Srcloc::start("*all-conditions-empty*"), + bi_one(), + ))); + } + let mut copy_vec = c.to_vec(); + copy_vec.insert( + 0, + Rc::new(BodyForm::Value(SExp::Atom(c[0].loc(), b"all".to_vec()))), + ); + Rc::new(BodyForm::Call(c[0].loc(), copy_vec, None)) +} + +fn if_expr( + cond: Rc, + then_clause: Rc, + else_clause: Rc, +) -> Rc { + Rc::new(BodyForm::Call( + cond.loc(), + vec![ + Rc::new(BodyForm::Value(SExp::Atom(cond.loc(), b"a".to_vec()))), + Rc::new(BodyForm::Call( + cond.loc(), + vec![ + Rc::new(BodyForm::Value(SExp::Atom(cond.loc(), b"i".to_vec()))), + cond.clone(), + Rc::new(BodyForm::Call( + cond.loc(), + vec![ + Rc::new(BodyForm::Value(SExp::Atom(cond.loc(), b"com".to_vec()))), + then_clause, + ], + None, + )), + Rc::new(BodyForm::Call( + cond.loc(), + vec![ + Rc::new(BodyForm::Value(SExp::Atom(cond.loc(), b"com".to_vec()))), + else_clause, + ], + None, + )), + ], + None, + )), + Rc::new(BodyForm::Value(SExp::Atom(cond.loc(), b"@".to_vec()))), + ], + None, + )) +} + +#[test] +fn test_tree_choice_conditions() { + let tree = TreeChoice { + path: vec![Direction::L, Direction::L, Direction::R], + }; + let conditions_of = all_conditions(&tree.conditions(false, None)); + assert_eq!( + conditions_of.to_sexp().to_string(), + "(all arg (f arg) (f (f arg)))" + ); +} + +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug)] +struct CheckAndRetrieve { + pub gate: Option, + pub retrieve: TreeChoice, + pub checks: Vec, +} + +impl CheckAndRetrieve { + // generate an if of the native checks and the check of the retrievable + // itself for this object, otherwise doing the else clause. + pub fn generate_body_if(&self, else_clause: Rc) -> Rc { + let check_conditions: Vec> = self + .checks + .iter() + .map(|c| all_conditions(&c.conditions(true, None))) + .collect(); + let retrieve_condition = all_conditions( + &self + .retrieve + .conditions(false, Some(all_conditions(&check_conditions))), + ); + let what_to_do = self.retrieve.condition(); + + if_expr(retrieve_condition, what_to_do, else_clause) + } +} + +#[test] +fn test_check_and_retrieve_1() { + let car = CheckAndRetrieve { + gate: None, + retrieve: TreeChoice { + path: vec![Direction::L, Direction::R], + }, + checks: vec![], + }; + let else_clause = Rc::new(BodyForm::Value(SExp::Nil(Srcloc::start("*test*")))); + assert_eq!( + car.generate_body_if(else_clause).to_sexp().to_string(), + "(a (i (all (q . 1) arg (f arg)) (com (r (f arg))) (com ())) @)" + ); +} + +#[test] +fn test_check_and_retrieve_2() { + let car = CheckAndRetrieve { + gate: None, + retrieve: TreeChoice { + path: vec![Direction::L, Direction::R], + }, + checks: vec![TreeChoice { + path: vec![Direction::R], + }], + }; + let else_clause = Rc::new(BodyForm::Value(SExp::Nil(Srcloc::start("*test*")))); + assert_eq!( + car.generate_body_if(else_clause).to_sexp().to_string(), + "(a (i (all (all (all arg (r arg))) arg (f arg)) (com (r (f arg))) (com ())) @)" + ); +} + +fn create_number_tree(tree: &mut TreeNode, numbers: &[u16]) { + assert!(!numbers.is_empty()); + let len = numbers.len(); + if len == 1 { + tree.number = numbers[0]; + return; + } + + let mid = len / 2; + tree.number = numbers[mid]; + if mid > 0 { + let left_slice = &numbers[0..mid]; + let mut left_node = TreeNode::default(); + create_number_tree(&mut left_node, left_slice); + tree.left = Some(Rc::new(left_node)); + } + if len > mid + 1 { + let right_slice = &numbers[mid + 1..len]; + let mut right_node = TreeNode::default(); + create_number_tree(&mut right_node, right_slice); + tree.right = Some(Rc::new(right_node)); + } +} + +fn choose_in_tree(tree: &TreeNode, number: u16) -> TreeChoice { + let mut path: Vec = Vec::new(); + let mut tn: &TreeNode = tree; + while tn.number != number { + if number < tn.number { + path.push(Direction::L); + if let Some(t) = tn.left.as_ref().borrow() { + tn = t; + } else { + panic!("should have existed"); + } + } else { + path.push(Direction::R); + if let Some(t) = tn.right.as_ref().borrow() { + tn = t; + } else { + panic!("should have existed"); + } + } + } + TreeChoice { path } +} + +#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug)] +struct IfWithGate { + gate: TreeChoice, + in_gate: BTreeSet, + otherwise_reachable: BTreeSet, +} + +impl IfWithGate { + fn generate(&self) -> Rc { + let srcloc = Srcloc::start("*if-with-gate*"); + let gate_conditions = all_conditions(&self.gate.conditions(false, None)); + let mut maybe_also_these = Rc::new(BodyForm::Quoted(SExp::Nil(srcloc.clone()))); + for reachable in self.otherwise_reachable.iter().rev() { + maybe_also_these = reachable.generate_body_if(maybe_also_these); + } + + let mut gated = maybe_also_these.clone(); + for new_gated in self.in_gate.iter().rev() { + gated = new_gated.generate_body_if(gated); + } + + if_expr(gate_conditions, gated, maybe_also_these) + } +} + +#[test] +fn test_if_with_gate_generate_0() { + let mut in_gate_set = BTreeSet::new(); + in_gate_set.insert(CheckAndRetrieve { + gate: Some(TreeChoice { + path: vec![Direction::R, Direction::L, Direction::R, Direction::L], + }), + retrieve: TreeChoice { + path: vec![ + Direction::R, + Direction::R, + Direction::R, + Direction::R, + Direction::L, + Direction::L, + ], + }, + checks: vec![], + }); + let mut otherwise_set = BTreeSet::new(); + otherwise_set.insert(CheckAndRetrieve { + gate: None, + retrieve: TreeChoice { + path: vec![ + Direction::R, + Direction::R, + Direction::R, + Direction::R, + Direction::L, + Direction::R, + ], + }, + checks: vec![], + }); + let iwg = IfWithGate { + gate: TreeChoice { + path: vec![Direction::R, Direction::R, Direction::R], + }, + in_gate: in_gate_set, + otherwise_reachable: otherwise_set, + }; + assert_eq!(iwg.generate().to_sexp().to_string(), "(a (i (all arg (r arg) (r (r arg))) (com (a (i (all (q . 1) arg (r arg) (r (r arg)) (r (r (r arg))) (r (r (r (r arg)))) (f (r (r (r (r arg)))))) (com (f (f (r (r (r (r arg))))))) (com (a (i (all (q . 1) arg (r arg) (r (r arg)) (r (r (r arg))) (r (r (r (r arg)))) (f (r (r (r (r arg)))))) (com (r (f (r (r (r (r arg))))))) (com (q))) @))) @)) (com (a (i (all (q . 1) arg (r arg) (r (r arg)) (r (r (r arg))) (r (r (r (r arg)))) (f (r (r (r (r arg)))))) (com (r (f (r (r (r (r arg))))))) (com (q))) @))) @)"); +} + +impl GenerateTrickyCSE { + fn new(rng: &mut R) -> Self { + // Generate number tree. + let number_of_numbers = 5 + rng.gen::() % 11; + let numbers_set: BTreeSet = (0..number_of_numbers).map(|_| rng.gen()).collect(); + let numbers: Vec = numbers_set.iter().copied().collect(); + let mut number_tree = TreeNode::default(); + create_number_tree(&mut number_tree, &numbers); + + // Now we have a number tree. Choose some random values and find their + // paths in the tree. + let num_choices = 3 + (rng.gen::() % 7); + let mut choices: Vec = (0..num_choices) + .map(|_| { + let retrieve = choose_in_tree( + &number_tree, + numbers[rng.gen::() % number_of_numbers], + ); + let gate = if rng.gen() { + Some(choose_in_tree( + &number_tree, + numbers[rng.gen::() % number_of_numbers], + )) + } else { + None + }; + let num_checks = rng.gen::() % 3; + let checks: Vec = (0..num_checks) + .map(|_| { + choose_in_tree( + &number_tree, + numbers[rng.gen::() % number_of_numbers], + ) + }) + .collect(); + CheckAndRetrieve { + gate, + retrieve, + checks, + } + }) + .collect(); + + // Actually, we can just sort the choices since ones that dominate will + // come before ones that are dominated (longer path with same prefix). + choices.sort(); + + eprintln!("choices {choices:?}"); + GenerateTrickyCSE { + choices, + tree: number_tree.clone(), + numbers: numbers_set, + } + } + + fn generate_expr(&self) -> Rc { + let srcloc = Srcloc::start("*tree-generate*"); + + // Generate if statements for each tier of gate + let mut choice_by_gate: BTreeMap = BTreeMap::new(); + + // Make a list of distinct gates and the directly gated choices. + for choice in self.choices.iter() { + if let Some(choice_gate) = choice.gate.as_ref() { + if let Some(gated_by_choice) = choice_by_gate.get_mut(choice_gate) { + gated_by_choice.in_gate.insert(choice.clone()); + } else { + let mut in_gate = BTreeSet::new(); + in_gate.insert(choice.clone()); + choice_by_gate.insert( + choice_gate.clone(), + IfWithGate { + gate: choice_gate.clone(), + in_gate, + otherwise_reachable: BTreeSet::default(), + }, + ); + } + } + } + + // For each gate, filter all the remaining checks into in_gate or + // otherwise_reachable. + for (gate, ifwith) in choice_by_gate.iter_mut() { + let (in_gate, otherwise_reachable) = self + .choices + .iter() + .cloned() + .partition::, _>(|choice| { + choice + .gate + .as_ref() + .map(|g| gate.contains(g)) + .unwrap_or(false) + }); + for g in in_gate.iter() { + ifwith.in_gate.insert(g.clone()); + } + for g in otherwise_reachable.iter() { + ifwith.otherwise_reachable.insert(g.clone()); + } + } + + // Generate the full expression. + let mut final_value = Rc::new(BodyForm::Quoted(SExp::Nil(srcloc.clone()))); + for (gate, ifwith) in choice_by_gate.iter().rev() { + let this_gate = ifwith.generate(); + let gate_conditions = all_conditions(&gate.conditions(true, None)); + final_value = if_expr(gate_conditions, this_gate, final_value); + } + + final_value + } + + fn generate_helper(&self) -> HelperForm { + let srcloc = Srcloc::start("*helper*"); + let args = Rc::new(SExp::Cons( + srcloc.clone(), + Rc::new(SExp::Atom(srcloc.clone(), b"arg".to_vec())), + Rc::new(SExp::Nil(srcloc.clone())), + )); + HelperForm::Defun( + false, + Box::new(DefunData { + nl: srcloc.clone(), + loc: srcloc.clone(), + name: b"tricky-cse".to_vec(), + args: args.clone(), + orig_args: args.clone(), + body: self.generate_expr(), + kw: None, + synthetic: None, + ty: None, + }), + ) + } + + fn generate_program(&self) -> CompileForm { + let helper = self.generate_helper(); + let args = Rc::new(SExp::Atom(helper.loc(), b"arg".to_vec())); + CompileForm { + loc: helper.loc(), + include_forms: vec![], + args, + exp: Rc::new(BodyForm::Call( + helper.loc(), + vec![ + Rc::new(BodyForm::Value(SExp::Atom( + helper.loc(), + helper.name().to_vec(), + ))), + Rc::new(BodyForm::Value(SExp::Atom(helper.loc(), b"arg".to_vec()))), + ], + None, + )), + helpers: vec![helper], + ty: None, + } + } +} + +fn test_generated_cse(n: u32) { + eprintln!("=== SEED {n} ==="); + let mut rng = RngLFSR::new(n); + let tcse = GenerateTrickyCSE::new(&mut rng); + let generated = tcse.generate_program(); + eprintln!("{}", generated.to_sexp()); + let runner = Rc::new(DefaultProgramRunner::new()); + let opts: Rc = Rc::new(DefaultCompilerOpts::new("*tricky-cse*")); + let opts21 = opts.set_dialect(AcceptedDialect { + stepping: Some(21), + strict: true, + }); + let opts23 = opts + .set_dialect(AcceptedDialect { + stepping: Some(23), + strict: true, + }) + .set_optimize(true); + let mut allocator = Allocator::new(); + let mut symbols = HashMap::new(); + let compiled21; + let compiled23; + + // Get strict cl21 compile + { + let mut wrapper21 = CompileContextWrapper::new( + &mut allocator, + runner.clone(), + &mut symbols, + get_optimizer(&generated.loc(), opts21.clone()).expect("should be ok dialect"), + ); + eprintln!("21 compile"); + compiled21 = Rc::new( + compile_from_compileform(&mut wrapper21.context, opts21, generated.clone()) + .expect("compiled"), + ) + } + + // Get cl23 compile + { + let mut wrapper23 = CompileContextWrapper::new( + &mut allocator, + runner.clone(), + &mut symbols, + get_optimizer(&generated.loc(), opts23.clone()).expect("should be ok dialect"), + ); + eprintln!("23 compile"); + compiled23 = Rc::new( + compile_from_compileform(&mut wrapper23.context, opts23, generated.clone()) + .expect("compiled"), + ) + } + + eprintln!("generate tree numbers"); + let check_numbers: BTreeSet = tcse + .numbers + .iter() + .filter(|_| { + let check: u8 = rng.gen(); + check & 15 >= 1 + }) + .copied() + .collect(); + eprintln!("generate tree"); + let tree = Rc::new(tcse.tree.generate(generated.loc(), &move |tn| { + check_numbers.contains(&tn.number) + })); + + eprintln!("compiled21 {compiled21}"); + eprintln!("compiled23 {compiled23}"); + eprintln!("tree {tree}"); + + let mut allocator = Allocator::new(); + let clvm21 = run( + &mut allocator, + runner.clone(), + opts.prim_map(), + compiled21.clone(), + tree.clone(), + None, + Some(TEST_TIMEOUT), + ); + let clvm23 = run( + &mut allocator, + runner, + opts.prim_map(), + compiled23.clone(), + tree.clone(), + None, + Some(TEST_TIMEOUT), + ); + if let Ok(res21) = clvm21.as_ref() { + eprintln!("cl21 {res21}"); + } + if let Ok(res23) = clvm23.as_ref() { + eprintln!("cl23 {res23}"); + } + if clvm21.is_err() || clvm23.is_err() { + // Precise errors might change due to differences in ordering and + // locations and such. + assert_eq!(clvm21.is_err(), clvm23.is_err()); + return; + } + assert_eq!(clvm21, clvm23); +} + +#[test] +fn test_generate_tricky_cse() { + for i in 0..16 { + test_generated_cse(10000 + i); + } +} diff --git a/src/tests/compiler/optimizer/depgraph.rs b/src/tests/compiler/optimizer/depgraph.rs new file mode 100644 index 000000000..977762caa --- /dev/null +++ b/src/tests/compiler/optimizer/depgraph.rs @@ -0,0 +1,68 @@ +use std::collections::HashSet; + +use crate::compiler::compiler::DefaultCompilerOpts; +use crate::compiler::comptypes::CompilerOpts; +use crate::compiler::dialect::AcceptedDialect; +use crate::compiler::frontend::frontend; +use crate::compiler::optimize::depgraph::FunctionDependencyGraph; +use crate::compiler::sexp::parse_sexp; +use crate::compiler::srcloc::Srcloc; + +fn get_depgraph_for_program(prog: &str) -> FunctionDependencyGraph { + let filename = "*test*"; + let forms = parse_sexp(Srcloc::start(filename), prog.bytes()).expect("should parse"); + let opts = DefaultCompilerOpts::new(filename).set_dialect(AcceptedDialect { + stepping: Some(21), + strict: true, + }); + let compileform = frontend(opts.clone(), &forms).expect("should frontend"); + + FunctionDependencyGraph::new(&compileform) +} + +#[test] +fn test_dependency_graph_smoke() { + let depgraph = get_depgraph_for_program(indoc! {" + (mod (X) + (include *strict-cl-21*) + + (defun DependedOnByFGAndH (X) (+ 1 X)) + + (defun F (X) (DependedOnByFGAndH X)) + + (defun H (X) (+ (G X) (* X 2))) + + (defun G (X) (DependedOnByFGAndH X)) + + (+ (F X) (G X) (H X)) + ) + "}); + + let mut depended_on_by = HashSet::default(); + depgraph.get_full_depended_on_by(&mut depended_on_by, b"DependedOnByFGAndH"); + + let want_depended_on_by_set: HashSet> = [b"F".to_vec(), b"G".to_vec(), b"H".to_vec()] + .iter() + .cloned() + .collect(); + assert_eq!(want_depended_on_by_set, depended_on_by); + + let mut g_depended_on_by = HashSet::default(); + depgraph.get_full_depended_on_by(&mut g_depended_on_by, b"G"); + let want_g_depended_on_by_set = [b"H".to_vec()].iter().cloned().collect(); + assert_eq!(g_depended_on_by, want_g_depended_on_by_set); + + let mut f_depends_on = HashSet::default(); + depgraph.get_full_depends_on(&mut f_depends_on, b"F"); + let want_f_depends_on_set = [b"DependedOnByFGAndH".to_vec()].iter().cloned().collect(); + assert_eq!(f_depends_on, want_f_depends_on_set); + + let mut h_depends_on = HashSet::default(); + depgraph.get_full_depends_on(&mut h_depends_on, b"H"); + + let want_h_depends_on_set = [b"DependedOnByFGAndH".to_vec(), b"G".to_vec()] + .iter() + .cloned() + .collect(); + assert_eq!(h_depends_on, want_h_depends_on_set); +} diff --git a/src/tests/compiler/optimizer/mod.rs b/src/tests/compiler/optimizer/mod.rs new file mode 100644 index 000000000..5b41e594b --- /dev/null +++ b/src/tests/compiler/optimizer/mod.rs @@ -0,0 +1,4 @@ +mod bodyform; +mod cse; +mod depgraph; +mod output; diff --git a/src/tests/compiler/optimizer/output.rs b/src/tests/compiler/optimizer/output.rs new file mode 100644 index 000000000..0c2b1ba78 --- /dev/null +++ b/src/tests/compiler/optimizer/output.rs @@ -0,0 +1,381 @@ +use std::collections::HashMap; +use std::fs; +use std::rc::Rc; + +use clvm_rs::allocator::Allocator; + +use crate::classic::clvm::sexp::sexp_as_bin; +use crate::classic::clvm_tools::stages::stage_0::{ + DefaultProgramRunner, RunProgramOption, TRunProgram, +}; +use crate::compiler::clvm::{convert_from_clvm_rs, convert_to_clvm_rs}; +use crate::compiler::compiler::{compile_file, DefaultCompilerOpts}; +use crate::compiler::comptypes::{CompileErr, CompilerOpts}; +use crate::compiler::dialect::AcceptedDialect; +use crate::compiler::runtypes::RunFailure; +use crate::compiler::sexp::{parse_sexp, SExp}; +use crate::compiler::srcloc::Srcloc; + +const MAX_RUN_COST: u64 = 1000000; + +#[derive(Debug)] +struct CompileRunResult { + pub compiled: Rc, + pub compiled_hex: String, + pub run_result: Rc, +} + +#[derive(Debug)] +struct OptRunResult { + unopt: CompileRunResult, + opt: CompileRunResult, +} + +fn run_with_cost( + allocator: &mut Allocator, + runner: Rc, + sexp: Rc, + env: Rc, +) -> Result { + let as_classic_program = convert_to_clvm_rs(allocator, sexp.clone())?; + let as_classic_env = convert_to_clvm_rs(allocator, env.clone())?; + let compiled_hex = sexp_as_bin(allocator, as_classic_program).hex(); + runner + .run_program( + allocator, + as_classic_program, + as_classic_env, + Some(RunProgramOption { + max_cost: Some(MAX_RUN_COST), + pre_eval_f: None, + strict: false, + }), + ) + .map_err(|e| RunFailure::RunErr(sexp.loc(), format!("{} in {} {}", e.1, sexp, env))) + .and_then(|reduction| { + Ok(CompileRunResult { + compiled: sexp.clone(), + compiled_hex, + run_result: convert_from_clvm_rs(allocator, sexp.loc(), reduction.1)?, + }) + }) +} + +#[derive(Clone, Debug)] +struct OptimizationRunSpec { + dialect: AcceptedDialect, + optimize: bool, + fe_opt: bool, +} + +fn run_string_get_program_and_output_dialect( + content: &str, + args: &str, + include_dirs: &[String], + spec: OptimizationRunSpec, +) -> Result { + let mut allocator = Allocator::new(); + let runner = Rc::new(DefaultProgramRunner::new()); + let mut opts: Rc = Rc::new(DefaultCompilerOpts::new(&"*test*".to_string())); + let srcloc = Srcloc::start(&"*test*".to_string()); + opts = opts + .set_optimize(spec.optimize) + .set_frontend_opt(spec.fe_opt) + .set_dialect(spec.dialect) + .set_search_paths(include_dirs); + let sexp_args = + parse_sexp(srcloc.clone(), args.bytes()).map_err(|e| CompileErr(e.0, e.1))?[0].clone(); + + compile_file( + &mut allocator, + runner.clone(), + opts, + &content, + &mut HashMap::new(), + ) + .and_then(|program| { + run_with_cost(&mut allocator, runner, Rc::new(program), sexp_args).map_err(|e| match e { + RunFailure::RunErr(l, s) => CompileErr(l, s), + RunFailure::RunExn(l, s) => CompileErr(l, s.to_string()), + }) + }) +} + +fn run_string_get_program_and_output_with_includes( + content: &str, + args: &str, + include_dirs: &[String], + fe_opt: bool, +) -> Result { + run_string_get_program_and_output_dialect( + content, + args, + include_dirs, + OptimizationRunSpec { + dialect: AcceptedDialect { + stepping: Some(23), + strict: false, + }, + optimize: false, + fe_opt, + }, + ) +} + +fn do_compile_and_run_opt_size_test_with_includes( + prog: &str, + env: &str, + includes: &[String], +) -> Result { + let unopt_run = run_string_get_program_and_output_with_includes(prog, env, includes, false)?; + let opt_run = run_string_get_program_and_output_with_includes(prog, env, includes, true)?; + + // Ensure the runs had the same output. + assert_eq!(unopt_run.run_result, opt_run.run_result); + + Ok(OptRunResult { + unopt: unopt_run, + opt: opt_run, + }) +} + +fn do_compile_and_run_opt_size_test_dialect( + prog: &str, + env: &str, + includes: &[String], + mut dialect: OptimizationRunSpec, +) -> Result { + let opt_run = run_string_get_program_and_output_dialect(prog, env, includes, dialect.clone())?; + dialect.optimize = false; + dialect.fe_opt = false; + let unopt_run = run_string_get_program_and_output_dialect(prog, env, includes, dialect)?; + + // Ensure the runs had the same output. + assert_eq!(unopt_run.run_result, opt_run.run_result); + + Ok(OptRunResult { + unopt: unopt_run, + opt: opt_run, + }) +} + +fn do_compile_and_run_opt_size_test(prog: &str, env: &str) -> Result { + do_compile_and_run_opt_size_test_with_includes(prog, env, &["resources/tests".to_string()]) +} + +#[test] +fn test_optimizer_tables_big_constants() { + let res = do_compile_and_run_opt_size_test( + indoc! {" + (mod (A) + (include *standard-cl-22*) + (defconstant X \"hi there this is a test\") + (c X (c X A)) + ) + "}, + "(test)", + ) + .expect("should compile and run"); + assert!(res.opt.compiled_hex.len() < res.unopt.compiled_hex.len()); +} + +#[test] +fn smoke_test_optimizer() { + let res = do_compile_and_run_opt_size_test( + indoc! {" + (mod () + (include *standard-cl-22*) + (defun-inline F (X Y) (+ X Y)) + (let ((A 2) (B 4)) (F A B)) + ) + "}, + "()", + ) + .expect("should compile and run"); + eprintln!("opt {}", res.opt.compiled); + eprintln!("unopt {}", res.unopt.compiled); + assert!(res.opt.compiled_hex.len() < res.unopt.compiled_hex.len()); +} + +#[test] +fn test_optimizer_shrinks_inlines() { + let res = do_compile_and_run_opt_size_test( + indoc! {" + (mod (A) + (include *standard-cl-22*) + (defun-inline F (N) (* 3 (+ 1 N))) + (let* ((FN (F A))) + (let ((FA (+ FN 1)) (FB (- FN 1)) (FC (* FN 2))) + (+ FA FB FC) + ) + ) + ) + "}, + "(3)", + ) + .expect("should compile and run"); + assert!(res.opt.compiled_hex.len() < res.unopt.compiled_hex.len()); +} + +#[test] +fn test_optimizer_shrinks_repeated_lets() { + let res = do_compile_and_run_opt_size_test( + indoc! {" + (mod (X) + (include *standard-cl-22*) + (defconstant Z 1000000) + (let + ((X1 (+ X Z))) + (+ X1 X1 X1 X1 X1 X1) + ) + )"}, + "(3)", + ) + .expect("should compile and run"); + assert!(res.opt.compiled_hex.len() < res.unopt.compiled_hex.len()); +} + +#[test] +fn test_optimizer_shrinks_q_test_1() { + let program = fs::read_to_string("resources/tests/optimization/merkle_tree_a2c.clsp") + .expect("test file should exist"); + let res = do_compile_and_run_opt_size_test_with_includes( + &program, + "(0x79539b34c33bc90bdaa6f9a28d3993a1e34025e5f2061fc57f8ff3edb9fb3b85 0x47194347579b7aa1ede51c52ddfd4200d8b560828051608ce599c763fd99291a (() 0xfb3b5605bc59e423b7df9c3bcfa7f559d6cdfcb9a49645dd801b3b24d6e9c439 0xe925a16b925dc355611f46c900ff0c182a3ed29a32d76394ea85b14d760d91c6))", + &["resources/tests/bridge-includes".to_string()] + ).expect("should compile and run"); + assert!(res.opt.compiled_hex.len() <= res.unopt.compiled_hex.len()); +} + +#[test] +fn test_optimizer_shrinks_q_test_2() { + let program = fs::read_to_string("resources/tests/optimization/validation_taproot.clsp") + .expect("test file should exist"); + let res = do_compile_and_run_opt_size_test_with_includes( + &program, + indoc!{"( + ;; Curried + ( + 0x7faa3253bfddd1e0decb0906b2dc6247bbc4cf608f58345d173adb63e8b47c9f + 0x0303030303030303030303030303030303030303030303030303030303030303 . + 0xeff07522495060c066f66f32acc2a77e3a3e737aca8baea4d1a64ea4cdc13da9 + ) + 0xa04d9f57764f54a43e4030befb4d80026e870519aaa66334aef8304f5d0393c2 + 0xb521509a3e089e25b66b3e272aa88b19851778eefebbea13e6be63a471ebf12a + ;; Args + () 0x78305c9b8b52ec71ebdd6db292fd106dbfdee8c061314658e13bf2436fa66a71 0x9dcf97a184f32623d11a73124ceb99a5709b083721e878a16d78f596718ba7b2 1 (((1 . 0x0000000000000000000000000000000000000000000000000000000000000000) 2 . 0x0101010101010101010101010101010101010101010101010101010101010101) . 0x15966a8a80f66c1eb2547b2dcc42b1fccdb7d6c1c787a888b9fdc19bf72ac58b) + )"}, + &["resources/tests/bridge-includes".to_string()] + ).expect("should compile and run"); + assert!(res.opt.compiled_hex.len() <= res.unopt.compiled_hex.len()); +} + +// Tests from program builder. +#[test] +fn test_optimizer_stack_overflow_1() { + let program = indoc! {" + (mod C + (include *standard-cl-21*) + (defun helper_0 E (helper_0 (q))) + (if (helper_0 (q)) (helper_0 (q)) (helper_0 (q)))) + "} + .to_string(); + let res = do_compile_and_run_opt_size_test_with_includes(&program, "33", &[]); + if let Err(e) = &res { + assert!(e.1.starts_with("cost exceeded")); + } else { + assert!(false); + } +} + +#[test] +fn test_optimizer_stack_overflow_2() { + let program = indoc! {" + (mod C + (include *standard-cl-21*) + (defun helper_0 E (helper_0 (17 (q) (q)))) + (if (q) + (helper_0 (17 (q) (q))) + (helper_0 (17 (q) (q))) + ) + ) + "} + .to_string(); + let res = do_compile_and_run_opt_size_test_with_includes(&program, "33", &[]); + if let Err(e) = &res { + assert!(e.1.starts_with("cost exceeded")); + } else { + assert!(false); + } +} + +const SPEC_23: OptimizationRunSpec = OptimizationRunSpec { + dialect: AcceptedDialect { + stepping: Some(23), + strict: true, + }, + optimize: true, + fe_opt: true, +}; + +#[test] +fn test_optimizer_shrinks_repeated_lets_23() { + let res = do_compile_and_run_opt_size_test_dialect( + indoc! {" + (mod (X) + (include *standard-cl-22*) + (defconstant Z 1000000) + (let + ((X1 (+ X Z))) + (+ X1 X1 X1 X1 X1 X1) + ) + )"}, + "(3)", + &[], + SPEC_23.clone(), + ) + .expect("should compile and run"); + assert!(res.opt.compiled_hex.len() < res.unopt.compiled_hex.len()); +} + +#[test] +fn test_brief_path_optimization() { + let program = + fs::read_to_string("resources/tests/test_user_path_opt_0.clsp").expect("should exist"); + let res = do_compile_and_run_opt_size_test_dialect( + &program, + "((1111111 ((((((987))))))))", + &[], + SPEC_23.clone(), + ) + .expect("should compile and run"); + assert!(res.opt.compiled_hex.len() < res.unopt.compiled_hex.len()); +} + +// Tests the path optimizer on a tricky assign extraction. +#[test] +fn test_brief_path_optimization_assign() { + let program = + fs::read_to_string("resources/tests/test_assign_path_opt.clsp").expect("should exist"); + let res = do_compile_and_run_opt_size_test_dialect( + &program, + "((_0 _1 _2 _3 _4 (_50 (_51 _52 _53 99))))", + &[], + SPEC_23.clone(), + ) + .expect("should compile and run"); + eprintln!("res.opt.compiled {}", res.opt.compiled); + eprintln!("res.unopt.compiled {}", res.unopt.compiled); + assert!(res.opt.compiled_hex.len() < res.unopt.compiled_hex.len()); +} + +#[test] +fn test_subexp_elimination_smoke_0() { + let program = + fs::read_to_string("resources/tests/test_recursion_subexp.clsp").expect("should exist"); + let res = do_compile_and_run_opt_size_test_dialect(&program, "(13 15)", &[], SPEC_23.clone()) + .expect("should compile and run"); + eprintln!("res.opt.compiled {}", res.opt.compiled); + eprintln!("res.unopt.compiled {}", res.unopt.compiled); + assert!(res.opt.compiled_hex.len() < res.unopt.compiled_hex.len()); +} diff --git a/src/tests/compiler/preprocessor.rs b/src/tests/compiler/preprocessor.rs new file mode 100644 index 000000000..39c1bebaf --- /dev/null +++ b/src/tests/compiler/preprocessor.rs @@ -0,0 +1,617 @@ +use crate::compiler::compiler::DefaultCompilerOpts; +use crate::compiler::comptypes::CompilerOpts; +use crate::compiler::dialect::AcceptedDialect; +use crate::compiler::preprocessor::preprocess; +use crate::compiler::sexp::parse_sexp; +use crate::compiler::srcloc::Srcloc; +use std::rc::Rc; + +use crate::tests::compiler::compiler::run_string_strict; + +#[test] +fn test_defmac_basic_0() { + let prog = indoc! {" + (mod (X) + (defmac double-arg (A) (list (string->symbol (string-append (symbol->string A) \"1\")) (string->symbol (string-append (symbol->string A) \"2\")))) + (defun strange (double-arg X) (+ X1 X2)) + (strange X (* 2 X)) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(3)".to_string()).unwrap(); + assert_eq!(res.to_string(), "9"); +} + +#[test] +fn test_defmac_basic_shared_constant() { + let prog = indoc! {" + (mod (X) + (defconstant twostring \"2\") + (defmac double-arg (A) (list (string->symbol (string-append (symbol->string A) \"1\")) (string->symbol (string-append (symbol->string A) twostring)))) + (defun strange (double-arg X) (+ X1 X2)) + (c twostring (strange X (* 2 X))) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(3)".to_string()).unwrap(); + assert_eq!(res.to_string(), "(\"2\" . 9)"); +} + +#[test] +fn test_defmac_basic_shared_constant_not_string_with_string_operator() { + let prog = indoc! {" + (mod (X) + (defconstant twostring 2) + (defmac double-arg (A) (list (string->symbol (string-append (symbol->string A) \"1\")) (string->symbol (string-append (symbol->string A) twostring)))) + (defun strange (double-arg X) (+ X1 X2)) + (c twostring (strange X (* 2 X))) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(3)".to_string()); + assert!(res.is_err()); +} + +#[test] +fn test_defmac_basic_shared_constant_not_string_with_string_operator_fun() { + let prog = indoc! {" + (mod (X) + (defconstant twostring \"2\") + (defun make-arg-list (A) (list (string->symbol (string-append (symbol->string A) \"1\")) (string->symbol (string-append (symbol->string A) twostring)))) + (defmac double-arg (A) (make-arg-list A)) + (defun strange (double-arg X) (+ X1 X2)) + (c twostring (strange X (* 2 X))) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(3)".to_string()).unwrap(); + assert_eq!(res.to_string(), "(\"2\" . 9)"); +} + +#[test] +fn test_defmac_basic_test_is_string_pos() { + let prog = indoc! {" + (mod (X) + (defmac classify (S) + (if (string? S) + (qq (c 1 (unquote S))) + (qq (c 2 (unquote S))) + ) + ) + (c X (classify \"test\")) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(3)".to_string()).unwrap(); + assert_eq!(res.to_string(), "(3 1 . \"test\")"); +} + +#[test] +fn test_defmac_basic_test_is_string_neg() { + let prog = indoc! {" + (mod (X) + (defmac classify (S) + (if (string? S) + (qq (c 1 (unquote S))) + (qq (c 2 (unquote S))) + ) + ) + (c X (classify 99)) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(3)".to_string()).unwrap(); + assert_eq!(res.to_string(), "(3 2 . 99)"); +} + +#[test] +fn test_defmac_basic_test_is_symbol_pos() { + let prog = indoc! {" + (mod (X) + (defmac classify (S) + (if (symbol? S) + (qq (c 1 (unquote (symbol->string S)))) + (qq (c 2 (unquote S))) + ) + ) + (c X (classify test)) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(3)".to_string()).unwrap(); + assert_eq!(res.to_string(), "(3 1 . \"test\")"); +} + +#[test] +fn test_defmac_basic_test_is_symbol_neg() { + let prog = indoc! {" + (mod (X) + (defmac classify (S) + (if (symbol? S) + (qq (c 1 (unquote S))) + (qq (c 2 (unquote S))) + ) + ) + (c X (classify \"test\")) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(3)".to_string()).unwrap(); + assert_eq!(res.to_string(), "(3 2 . \"test\")"); +} + +#[test] +fn test_defmac_basic_test_is_number_pos() { + let prog = indoc! {" + (mod (X) + (defmac classify (S) + (if (number? S) + (qq (c 1 (unquote S))) + (qq (c 2 (unquote S))) + ) + ) + (c X (classify 7)) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(3)".to_string()).unwrap(); + assert_eq!(res.to_string(), "(3 1 . 7)"); +} + +#[test] +fn test_defmac_basic_test_is_number_neg() { + let prog = indoc! {" + (mod (X) + (defmac classify (S) + (if (number? S) + (qq (c 1 (unquote S))) + (qq (c 2 (unquote S))) + ) + ) + (c X (classify \"test\")) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(3)".to_string()).unwrap(); + assert_eq!(res.to_string(), "(3 2 . \"test\")"); +} + +#[test] +fn test_defmac_extension_from_function() { + let prog = indoc! {" + (mod (X) + (defun FX (X) (symbol->string X)) + (defmac F (X) (FX X)) + (c 3 (F X)) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(3)".to_string()).unwrap(); + assert_eq!(res.to_string(), "(3 . \"X\")"); +} + +#[test] +fn test_defmac_if_extension() { + let prog = indoc! {" + (mod (X) + (defun FX (X) (if X (number->string 1) 2)) + (defmac F (X) (c 1 (FX X))) + (F X) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(9)".to_string()).unwrap(); + assert_eq!(res.to_string(), "\"1\""); +} + +#[test] +fn test_defmac_create_match_form() { + let prog = indoc! {" + ;; Make a simple list match ala ocaml/elm/haskell. + ;; + ;; The real version will be more elaborate. This is a test case and a demo. + (mod X + (include *standard-cl-21*) + (defun list-nth (L N) + (if N + (list-nth (r L) (- N 1)) + (f L) + ) + ) + + (defun list-len (L N) + (if L + (list-len (r L) (+ N 1)) + N + ) + ) + + (defun funcall (name args) (c (string->symbol name) args)) + (defun quoted (X) (c 1 X)) + (defun equals (A B) (funcall \"=\" (list A B))) + (defun emit-list-nth (L N) (funcall \"list-nth\" (list L N))) + (defun emit-list-len (L N) (funcall \"list-len\" (list L N))) + (defun emit-if (C T E) (funcall \"if\" (list C T E))) + (defun emit-let (bindings body) (funcall \"let\" (list bindings body))) + + ;; Determine the size of each list as well as the constants and bindings + ;; Return either a list of (number-of-elts matches bindings) or symbol. + (defun build-matches-and-bindings (n pattern matches bindings) + (if (not pattern) + (list n matches bindings) + (if (l pattern) + (if (symbol? (f pattern)) + (build-matches-and-bindings (+ n 1) (r pattern) matches (c (c n (f pattern)) bindings)) + (build-matches-and-bindings (+ n 1) (r pattern) (c (c n (f pattern)) matches) bindings) + ) + pattern + ) + ) + ) + + ;; Emit code that matches each match list for length and constants. + (defun write-match-code (expr matches) + (if (not matches) + (quoted 1) + (if (l (f matches)) + (let* + ( + (offset (f (f matches))) + (desire (r (f matches))) + (this-match (equals (quoted desire) (emit-list-nth expr (quoted offset)))) + ) + (if (not (r matches)) + (list this-match) + (c this-match (write-match-code expr (r matches))) + ) + ) + (quoted 1) + ) + ) + ) + + ;; Generate let bindings for the bindings indicated in the match. + (defun let-bindings (expr bindings) + (if (not bindings) + () + (let + ((n (f (f bindings))) + (binding (r (f bindings))) + ) + (c (list binding (emit-list-nth expr n)) (let-bindings expr (r bindings))) + ) + ) + ) + + ;; Generate if expressions that match the indicates matches and return + ;; the indicated code with bindings installed. + (defun match-if (expr clauses) + (if (not clauses) + (list 8) + (let + ((extracted-clause-data (build-matches-and-bindings 0 (f (f clauses)) () ())) + (code (f (r (f clauses)))) + ) + (if (l extracted-clause-data) + (let + ( + (number-of-elts (f extracted-clause-data)) + (matches (list-nth extracted-clause-data 1)) + (bindings (list-nth extracted-clause-data 2)) + ) + (emit-if + (emit-if + (equals (emit-list-len expr 0) (quoted number-of-elts)) + ;; then + (c (string->symbol \"logand\") (write-match-code expr matches)) + ;; else + () + ) + ;; then + (emit-let (let-bindings expr bindings) code) + ;; else + (match-if expr (r clauses)) + ) + ) + (emit-let (list (list extracted-clause-data expr)) code) + ) + ) + ) + ) + + ;; match as below. + (defmac match (expr . matches) (match-if expr matches)) + + (match X + ((16 x y) (c 1 (+ x y))) + ((3 () b c) c) + ((3 1 b c) b) + (x x) + ) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(3 () 1001 1002)".to_string()).unwrap(); + assert_eq!(res.to_string(), "1002"); +} + +#[test] +fn test_defmac_stringq() { + let prog = indoc! {" + (mod () + (defmac is-string (X) (string? X)) + (list (is-string X) (is-string \"X\") (is-string 3)) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"()".to_string()).unwrap(); + assert_eq!(res.to_string(), "(() 1 ())"); +} + +#[test] +fn test_defmac_numberq() { + let prog = indoc! {" + (mod () + (defmac is-number (X) (number? X)) + (list (is-number X) (is-number \"X\") (is-number 3)) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"()".to_string()).unwrap(); + assert_eq!(res.to_string(), "(() () 1)"); +} + +#[test] +fn test_defmac_symbolq() { + let prog = indoc! {" + (mod () + (defmac is-symbol (X) (symbol? X)) + (list (is-symbol X) (is-symbol \"X\") (is-symbol 3)) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"()".to_string()).unwrap(); + assert_eq!(res.to_string(), "(1 () ())"); +} + +#[test] +fn test_defmac_string_to_symbol() { + let prog = indoc! {" + (mod () + (defmac is-symbol (X) (symbol? X)) + (list (is-symbol X) (is-symbol \"X\") (is-symbol 3)) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"()".to_string()).unwrap(); + assert_eq!(res.to_string(), "(1 () ())"); +} + +#[test] +fn test_defmac_string_to_symbol_converts() { + let prog = indoc! {" + (mod (X) + (defmac let_pi (code) (qq (let (((unquote (string->symbol \"pi\")) 31415)) (unquote code)))) + (let_pi (+ pi X)) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(5)".to_string()).unwrap(); + assert_eq!(res.to_string(), "31420"); +} + +#[test] +fn test_defmac_string_needs_conversion() { + let prog = indoc! {" + (mod (X) + (defmac let_pi (code) (qq (let ((\"pi\" 31415)) (unquote code)))) + (let_pi (+ pi X)) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(5)".to_string()); + eprintln!("res {res:?}"); + assert!(res.is_err()); +} + +#[test] +fn test_defmac_string_substr_0() { + let prog = indoc! {" + (mod (X) + (defmac first-letter-of (Q) + (let ((first-character (substring (symbol->string Q) 0 1))) + (qq (c (unquote first-character) (unquote (string->symbol first-character)))) + ) + ) + (first-letter-of Xanadu) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(5999)".to_string()).unwrap(); + assert_eq!(res.to_string(), "(\"X\" . 5999)"); +} + +#[test] +fn test_defmac_string_substr_bad() { + let prog = indoc! {" + (mod (test_variable_name) + (defmac bind-tail-of-symbol (N Q CODE) + (let* + ((stringified (symbol->string Q)) + (slen (string-length stringified)) + (suffix (string->symbol (substring stringified N slen)))) + (qq (let (((unquote suffix) (r (unquote Q)))) (unquote CODE))) + ) + ) + (bind-tail-of-symbol 100 test_variable_name (c 9999 variable_name)) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"((87 89 91))".to_string()); + assert!(res.is_err()); +} + +#[test] +fn test_defmac_string_to_number_0() { + let prog = indoc! {" + (mod (X_7) + (defmac add-n-to (X) + (let* + ((stringified (symbol->string X)) + (slen (string-length stringified)) + (number-part (substring stringified (- slen 1) slen)) + (numeric-value (string->number number-part))) + (qq (+ (unquote numeric-value) (unquote X))) + ) + ) + (add-n-to X_7) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(31)".to_string()).unwrap(); + assert_eq!(res.to_string(), "38"); +} + +#[test] +fn test_defmac_string_to_number_bad() { + let prog = indoc! {" + (mod (X_A) + (defmac add-n-to (X) + (let* + ((stringified (symbol->string X)) + (slen (string-length stringified)) + (number-part (substring stringified (- slen 1) slen)) + (numeric-value (string->number number-part))) + (qq (+ (unquote numeric-value) (unquote X))) + ) + ) + (add-n-to X_A) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(31)".to_string()); + assert!(res.is_err()); +} + +#[test] +fn test_defmac_number_to_string() { + let prog = indoc! {" + (mod (Q) + (defmac with-my-length (X) + (let* + ((stringified (symbol->string X)) + (slen (string-length stringified))) + (string->symbol (string-append stringified \"-\" (number->string slen))) + ) + ) + (defun F (Xanadu-6) (+ (with-my-length Xanadu) 99)) + (F Q) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"(37)".to_string()).unwrap(); + assert_eq!(res.to_string(), "136"); +} + +#[test] +fn test_preprocess_basic_list() { + let file = "*test*"; + let input_form_set = indoc! {"( + (include *strict-cl-21*) + (list 1 2 3) + )"}; + let parsed_forms = + parse_sexp(Srcloc::start(file), input_form_set.bytes()).expect("should parse"); + let opts: Rc = + Rc::new(DefaultCompilerOpts::new(file)).set_dialect(AcceptedDialect { + stepping: Some(21), + strict: true, + }); + let mut includes = Vec::new(); + let pp = preprocess(opts.clone(), &mut includes, parsed_forms[0].clone()) + .expect("should preprocess"); + assert_eq!(pp[pp.len() - 1].to_string(), "(4 1 (4 2 (4 3 ())))"); +} + +#[test] +fn test_preprocess_expansion_makes_numeric_operators() { + let prog = indoc! {" + (mod () + (include *strict-cl-21*) + (defmac G () (com (4 \"test\" ()))) + (G) + ) + "} + .to_string(); + let res = run_string_strict(&prog, &"()".to_string()).unwrap(); + assert_eq!(res.to_string(), "(\"test\")"); +} + +#[test] +fn test_preprocessor_tours_includes_properly() { + let prog = indoc! {" + ( ;; Note: preprocessing is run in the list of the body forms. + (include *strict-cl-21*) + (include condition_codes.clvm) + (include curry-and-treehash.clinc) + () + ) + "} + .to_string(); + let pname = "*test*"; + let opts: Rc = Rc::new(DefaultCompilerOpts::new(pname)) + .set_search_paths(&["resources/tests".to_string()]) + .set_dialect(AcceptedDialect { + stepping: Some(21), + strict: true, + }); + let parsed = parse_sexp(Srcloc::start(pname), prog.bytes()).expect("should parse"); + let mut includes = Vec::new(); + let res = preprocess(opts, &mut includes, parsed[0].clone()).expect("should preprocess"); + let expected_lines = &[ + "(defmac __chia__primitive__if (A B C) (qq (a (i (unquote A) (com (unquote B)) (com (unquote C))) @)))", + "(defun __chia__if (ARGS) (a (i (r (r (r ARGS))) (com (qq (a (i (unquote (f ARGS)) (com (unquote (f (r ARGS)))) (com (unquote (__chia__if (r (r ARGS)))))) @))) (com (qq (a (i (unquote (f ARGS)) (com (unquote (f (r ARGS)))) (com (unquote (f (r (r ARGS)))))) @)))) @))", + "(defmac if ARGS (__chia__if ARGS))", + "(defun __chia__compile-list (args) (a (i args (com (c 4 (c (f args) (c (__chia__compile-list (r args)) ())))) (com ())) @))", + "(defmac list ARGS (__chia__compile-list ARGS))", + "(defun-inline / (A B) (f (divmod A B)))", + "(defun-inline c* (A B) (c A B))", + "(defun-inline a* (A B) (a A B))", + "(defun-inline coerce (X) : (Any -> Any) X)", + "(defun-inline explode (X) : (forall a ((Exec a) -> a)) X)", + "(defun-inline bless (X) : (forall a ((Pair a Unit) -> (Exec a))) (coerce X))", + "(defun-inline lift (X V) : (forall a (forall b ((Pair (Exec a) (Pair b Unit)) -> (Exec (Pair a b))))) (coerce X))", + "(defun-inline unlift (X) : (forall a (forall b ((Pair (Exec (Pair a b)) Unit) -> (Exec b)))) (coerce X))", + "(defconstant *chialisp-version* 22)", + "(defconstant AGG_SIG_UNSAFE 49)", + "(defconstant AGG_SIG_ME 50)", + "(defconstant CREATE_COIN 51)", + "(defconstant RESERVE_FEE 52)", + "(defconstant CREATE_COIN_ANNOUNCEMENT 60)", + "(defconstant ASSERT_COIN_ANNOUNCEMENT 61)", + "(defconstant CREATE_PUZZLE_ANNOUNCEMENT 62)", + "(defconstant ASSERT_PUZZLE_ANNOUNCEMENT 63)", + "(defconstant ASSERT_MY_COIN_ID 70)", + "(defconstant ASSERT_MY_PARENT_ID 71)", + "(defconstant ASSERT_MY_PUZZLEHASH 72)", + "(defconstant ASSERT_MY_AMOUNT 73)", + "(defconstant ASSERT_SECONDS_RELATIVE 80)", + "(defconstant ASSERT_SECONDS_ABSOLUTE 81)", + "(defconstant ASSERT_HEIGHT_RELATIVE 82)", + "(defconstant ASSERT_HEIGHT_ABSOLUTE 83)", + "(defconstant ONE 1)", + "(defconstant TWO 2)", + "(defconstant A_KW 2)", + "(defconstant Q_KW 1)", + "(defconstant C_KW 4)", + "(defun-inline update-hash-for-parameter-hash (parameter-hash environment-hash) (sha256 TWO (sha256 ONE C_KW) (sha256 TWO (sha256 TWO (sha256 ONE Q_KW) parameter-hash) (sha256 TWO environment-hash (sha256 ONE ())))))", + "(defun build-curry-list (reversed-curry-parameter-hashes environment-hash) (a (i reversed-curry-parameter-hashes (com (build-curry-list (r reversed-curry-parameter-hashes) (update-hash-for-parameter-hash (f reversed-curry-parameter-hashes) environment-hash))) (com environment-hash)) @))", + "(defun-inline tree-hash-of-apply (function-hash environment-hash) (sha256 TWO (sha256 ONE A_KW) (sha256 TWO (sha256 TWO (sha256 ONE Q_KW) function-hash) (sha256 TWO environment-hash (sha256 ONE ())))))", + "(defun puzzle-hash-of-curried-function (function-hash . reversed-curry-parameter-hashes) (tree-hash-of-apply function-hash (build-curry-list reversed-curry-parameter-hashes (sha256 ONE ONE))))", + "()", + ]; + for (i, r) in res.iter().enumerate() { + assert_eq!(r.to_string(), expected_lines[i]); + } + assert_eq!(res.len(), expected_lines.len()); +} diff --git a/src/tests/compiler/repl.rs b/src/tests/compiler/repl.rs index a392c77b8..d5c0977ca 100644 --- a/src/tests/compiler/repl.rs +++ b/src/tests/compiler/repl.rs @@ -302,6 +302,95 @@ fn test_eval_list_partially_evaluated_xyz() { ); } +#[test] +fn test_defun_value_in_repl_0() { + assert_eq!( + test_repl_outcome(vec![ + "(defun greater-than-3 (X) (> X 3))", + "(a greater-than-3 (list 5))" + ]) + .unwrap() + .unwrap(), + "(q . 1)" + ); +} + +#[test] +fn test_defun_value_repl_map() { + assert_eq!( + test_repl_outcome(vec![ + "(defun greater-than-3 (X) (> X 3))", + "(defun map (F L) (if L (c (a F (list (f L))) (map F (r L))) ()))", + "(map greater-than-3 (list 1 2 3 4 5))" + ]) + .unwrap() + .unwrap(), + "(q () () () 1 1)" + ); +} + +#[test] +fn test_lambda_eval_5() { + assert_eq!( + test_repl_outcome_with_stack_limit( + vec![ + "(defun GetFun (L) (lambda ((& L) X) (+ X L)))", + "(a (GetFun 10) (list 3))" + ], + None + ) + .unwrap() + .unwrap(), + "(q . 13)" + ); +} + +#[test] +fn test_lambda_eval_6() { + assert_eq!( + test_repl_outcome(vec![ + indoc! {" +(defun visit-atoms (fn acc mask path pattern) + (if (l pattern) + (visit-atoms + fn + (visit-atoms fn acc (* 2 mask) path (f pattern)) + (* 2 mask) + (logior mask path) + (r pattern) + ) + + (a fn (list acc (logior path mask) pattern)) + ) + ) +"}, + indoc! {" + (defun if-match (match) + (c 1 + (visit-atoms + (lambda (cb path pat) + (if (l pat) + (list cb \"A\") ;; Unbound use of cb + (list cb \"B\") + ) + ) + () + 1 + 0 + match + ) + ) + ) + +"}, + "(if-match (q test \"test\" t1 (t2 . t3)))" + ]) + .unwrap() + .unwrap(), + "(q 1 (((((() B) B) B) B) B) B)" + ); +} + #[test] fn test_eval_new_bls_operator() { assert_eq!( @@ -315,3 +404,68 @@ fn test_eval_new_bls_operator() { "(q)" ); } + +#[test] +fn test_repl_base_lambda_case() { + assert_eq!( + test_repl_outcome_with_stack_limit( + vec![ + "(defun F (X F) (a F (list X)))".to_string(), + "(F 3 (lambda (Y) (+ Y 9)))".to_string(), + ], + None + ) + .unwrap() + .unwrap(), + "(q . 12)" + ); +} + +#[test] +fn test_repl_rest_lambda_case() { + assert_eq!( + test_repl_outcome_with_stack_limit( + vec![ + "(defun F (X F) (a F (list X)))".to_string(), + "(F &rest (list 3 (lambda (Y) (+ Y 9))))".to_string() + ], + None + ) + .unwrap() + .unwrap(), + "(q . 12)" + ); +} + +#[test] +fn test_repl_lambda_with_captures_rest() { + assert_eq!( + test_repl_outcome_with_stack_limit( + vec![ + "(defun map (F L) (if L (c (a F (list (f L))) (map F (r L))) ()))".to_string(), + "(defun F (X L) (map &rest (list (lambda ((& X) Y) (+ X Y)) L)))".to_string(), + "(F 3 (list 99 101 103))".to_string() + ], + None + ) + .unwrap() + .unwrap(), + "(q 102 104 106)" + ); +} + +#[test] +fn test_repl_lambda_with_captures_out_of_own_function() { + assert_eq!( + test_repl_outcome_with_stack_limit( + vec![ + "(defun F (X) (lambda ((& X) Y) (+ X Y)))".to_string(), + "(a (F 3) (list 4))".to_string(), + ], + None + ) + .unwrap() + .unwrap(), + "(q . 7)" + ); +} diff --git a/src/tests/compiler/restargs.rs b/src/tests/compiler/restargs.rs index bed669f47..e04f674ab 100644 --- a/src/tests/compiler/restargs.rs +++ b/src/tests/compiler/restargs.rs @@ -907,8 +907,10 @@ fn test_repl_10() { fn test_rest_type_good() { let prog_good = indoc! {" (mod (X) - (include *standard-cl-21*) + (include *standard-cl-23*) + (defun F (A B . C) : ((Pair Atom (Pair Atom (List Atom))) -> Atom) (* A B (f C))) + (F 5 7 &rest (list 9)) )"} .to_string(); @@ -923,9 +925,12 @@ fn test_rest_type_good() { fn test_rest_type_bad() { let prog_bad = indoc! {" (mod (X) - (include *standard-cl-21*) + (include *standard-cl-23*) + (deftype Foo ()) + (defun F (A B . C) : ((Pair Atom (Pair Atom (List Foo))) -> Atom) (* A B (f C))) + (F 5 7 &rest (list 9)) )"} .to_string(); diff --git a/src/tests/compiler/singleton.rs b/src/tests/compiler/singleton.rs new file mode 100644 index 000000000..68aaedacf --- /dev/null +++ b/src/tests/compiler/singleton.rs @@ -0,0 +1,314 @@ +use sha2::{Digest, Sha256}; +use std::rc::Rc; + +use clvmr::allocator::Allocator; + +use num_bigint::ToBigInt; + +use crate::classic::clvm::__type_compatibility__::{bi_one, Bytes, BytesFromType, Stream}; +use crate::classic::clvm::serialize::{sexp_from_stream, SimpleCreateCLVMObject}; +use crate::classic::clvm_tools::binutils::disassemble; +use crate::compiler::clvm::sha256tree; +use crate::compiler::prims::{primapply, primcons, primquote}; +use crate::compiler::sexp::{enlist, parse_sexp, SExp}; +use crate::compiler::srcloc::Srcloc; +use crate::tests::classic::run::{do_basic_brun, do_basic_run}; +use crate::util::u8_from_number; + +// Tests of a strict compile of singleton_top_layer.clsp +// +// Includes ported code from singleton_top_layer.py and +// my test-singleton.py +// const SINGLETON_MOD_HASH: &[u8] = &[ +// 0x24, 0xe0, 0x44, 0x10, 0x1e, 0x57, 0xb3, 0xd8, 0xc9, 0x08, 0xb8, 0xa3, 0x8a, 0xd5, 0x78, 0x48, 0xaf, 0xd2, 0x9d, 0x3e, 0xec, 0xc4, 0x39, 0xdb, 0xa4, 0x5f, 0x44, 0x12, 0xdf, 0x49, 0x54, 0xfd +// ]; +const SINGLETON_LAUNCHER_BYTES: &[u8] = &[ + 0xff, 0x02, 0xff, 0xff, 0x01, 0xff, 0x04, 0xff, 0xff, 0x04, 0xff, 0x04, 0xff, 0xff, 0x04, 0xff, + 0x05, 0xff, 0xff, 0x04, 0xff, 0x0b, 0xff, 0x80, 0x80, 0x80, 0x80, 0xff, 0xff, 0x04, 0xff, 0xff, + 0x04, 0xff, 0x0a, 0xff, 0xff, 0x04, 0xff, 0xff, 0x02, 0xff, 0x0e, 0xff, 0xff, 0x04, 0xff, 0x02, + 0xff, 0xff, 0x04, 0xff, 0xff, 0x04, 0xff, 0x05, 0xff, 0xff, 0x04, 0xff, 0x0b, 0xff, 0xff, 0x04, + 0xff, 0x17, 0xff, 0x80, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, + 0xff, 0x80, 0x80, 0x80, 0xff, 0xff, 0x04, 0xff, 0xff, 0x01, 0xff, 0x33, 0xff, 0x3c, 0xff, 0x02, + 0xff, 0xff, 0x03, 0xff, 0xff, 0x07, 0xff, 0x05, 0x80, 0xff, 0xff, 0x01, 0xff, 0x0b, 0xff, 0xff, + 0x01, 0x02, 0xff, 0xff, 0x02, 0xff, 0x0e, 0xff, 0xff, 0x04, 0xff, 0x02, 0xff, 0xff, 0x04, 0xff, + 0x09, 0xff, 0x80, 0x80, 0x80, 0x80, 0xff, 0xff, 0x02, 0xff, 0x0e, 0xff, 0xff, 0x04, 0xff, 0x02, + 0xff, 0xff, 0x04, 0xff, 0x0d, 0xff, 0x80, 0x80, 0x80, 0x80, 0x80, 0xff, 0xff, 0x01, 0xff, 0x0b, + 0xff, 0xff, 0x01, 0x01, 0xff, 0x05, 0x80, 0x80, 0xff, 0x01, 0x80, 0xff, 0x01, 0x80, 0x80, +]; + +lazy_static! { + pub static ref SINGLETON_LAUNCHER: String = { + let mut stream = Stream::new(Some(Bytes::new(Some(BytesFromType::Raw( + SINGLETON_LAUNCHER_BYTES.to_vec(), + ))))); + let mut allocator = Allocator::new(); + let code = sexp_from_stream( + &mut allocator, + &mut stream, + Box::new(SimpleCreateCLVMObject {}), + ) + .expect("should be able to parse binary"); + disassemble(&mut allocator, code.1, Some(0)) + }; +} + +const SINGLETON_LAUNCHER_HASH: &[u8] = &[ + 0xef, 0xf0, 0x75, 0x22, 0x49, 0x50, 0x60, 0xc0, 0x66, 0xf6, 0x6f, 0x32, 0xac, 0xc2, 0xa7, 0x7e, + 0x3a, 0x3e, 0x73, 0x7a, 0xca, 0x8b, 0xae, 0xa4, 0xd1, 0xa6, 0x4e, 0xa4, 0xcd, 0xc1, 0x3d, 0xa9, +]; +const FIRST_COIN_PARENT: &[u8] = &[ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, +]; +const CREATE_COIN: usize = 51; + +#[derive(Clone, Debug)] +struct Coin { + parent_coin_id: Vec, + puzzle_hash: Vec, + amount: u64, +} + +fn std_hash(form: &[u8]) -> Vec { + let mut hasher = Sha256::new(); + hasher.update(&form); + hasher.finalize().to_vec() +} + +// Ported code from singleton_top_layer.py +fn generate_launcher_coin(parent_hash: &[u8], amount: u64) -> Coin { + Coin { + parent_coin_id: parent_hash.to_vec(), + puzzle_hash: SINGLETON_LAUNCHER_HASH.to_vec(), + amount, + } +} + +impl Coin { + fn name(&self) -> Vec { + let mut form = self.parent_coin_id.clone(); + form.append(&mut self.puzzle_hash.clone()); + let mut size_atom_bytes = u8_from_number(self.amount.to_bigint().unwrap()); + form.append(&mut size_atom_bytes); + std_hash(&form) + } +} + +fn curry(the_mod: Rc, new_args: &[Rc]) -> Rc { + let mut fixed_args = SExp::Integer(the_mod.loc(), bi_one()); + for arg in new_args.iter().rev() { + fixed_args = primcons( + the_mod.loc(), + Rc::new(primquote(the_mod.loc(), arg.clone())), + Rc::new(fixed_args), + ); + } + Rc::new(primapply( + the_mod.loc(), + Rc::new(primquote(the_mod.loc(), the_mod)), + Rc::new(fixed_args), + )) +} + +struct LineageProof { + parent_name: Vec, + inner_puzzle_hash: Option>, + amount: u64, +} + +struct SingletonLaunch { + inner_puzzle: Rc, + inner_puzzle_hash: Vec, + inner_puzzle_hash_atom: Rc, + curried_singleton: Rc, + curried_singleton_hash_atom: Rc, + amount: u64, + amount_atom: Rc, +} + +impl SingletonLaunch { + fn new(launcher_coin: Coin, program_file: &str, inner_puzzle: Rc, amount: u64) -> Self { + let compiled = do_basic_run(&vec![ + "run".to_string(), + "-i".to_string(), + "resources/tests/strict/includes".to_string(), + "-i".to_string(), + "resources/tests/strict".to_string(), // defmac_assert.clib + program_file.to_string(), + ]); + let amount_atom = Rc::new(SExp::Integer(inner_puzzle.loc(), bi_one())); + let parsed_compiled = + parse_sexp(inner_puzzle.loc(), compiled.bytes()).expect("should parse")[0].clone(); + let singleton_mod_hash = sha256tree(parsed_compiled.clone()); + let curried_singleton = curry( + parsed_compiled.clone(), + &[ + Rc::new(SExp::Cons( + inner_puzzle.loc(), + Rc::new(SExp::Atom(inner_puzzle.loc(), singleton_mod_hash.clone())), + Rc::new(SExp::Cons( + inner_puzzle.loc(), + Rc::new(SExp::Atom(inner_puzzle.loc(), launcher_coin.name())), + Rc::new(SExp::Atom( + inner_puzzle.loc(), + SINGLETON_LAUNCHER_HASH.to_vec(), + )), + )), + )), + inner_puzzle.clone(), + ], + ); + let inner_puzzle_hash = sha256tree(inner_puzzle.clone()); + let inner_puzzle_hash_atom = + Rc::new(SExp::Atom(inner_puzzle.loc(), inner_puzzle_hash.clone())); + let curried_singleton_hash = sha256tree(curried_singleton.clone()); + SingletonLaunch { + inner_puzzle_hash, + inner_puzzle_hash_atom, + curried_singleton_hash_atom: Rc::new(SExp::Atom( + inner_puzzle.loc(), + curried_singleton_hash.clone(), + )), + curried_singleton, + amount, + amount_atom, + inner_puzzle, + } + } + + fn loc(&self) -> Srcloc { + self.inner_puzzle.loc() + } + + fn launcher_solution(&self) -> Rc { + Rc::new(enlist( + self.loc(), + &[ + self.curried_singleton_hash_atom.clone(), + self.amount_atom.clone(), + Rc::new(SExp::Nil(self.loc())), + ], + )) + } + + fn lineage_proof(&self, parent_coin: &Coin) -> LineageProof { + let inner_puzzle_hash = if parent_coin.puzzle_hash == SINGLETON_LAUNCHER_HASH { + None + } else { + Some(self.inner_puzzle_hash.clone()) + }; + LineageProof { + parent_name: parent_coin.parent_coin_id.clone(), + inner_puzzle_hash, + amount: parent_coin.amount, + } + } + + fn solution_for_singleton( + &self, + lineage_proof: &LineageProof, + inner_solution: Rc, + ) -> Rc { + let parent_name = Rc::new(SExp::Atom(self.loc(), lineage_proof.parent_name.clone())); + let amount_atom = Rc::new(SExp::Integer( + self.loc(), + lineage_proof.amount.to_bigint().unwrap(), + )); + + let parent_info = if let Some(_inner_puzzle_hash) = &lineage_proof.inner_puzzle_hash { + enlist( + self.loc(), + &[ + parent_name, + self.inner_puzzle_hash_atom.clone(), + amount_atom.clone(), + ], + ) + } else { + enlist(self.loc(), &[parent_name, amount_atom.clone()]) + }; + Rc::new(enlist( + self.loc(), + &[Rc::new(parent_info), amount_atom, inner_solution], + )) + } + + fn get_next_coin(&self, parent: &Coin) -> Coin { + Coin { + parent_coin_id: parent.name(), + puzzle_hash: sha256tree(self.curried_singleton.clone()), + amount: self.amount, + } + } +} + +// singleton_top_layer in cl23 (just replacing the assert macro). +#[test] +fn test_singleton_top_layer_23() { + let program_file = "resources/tests/strict/singleton_top_layer.clsp"; + let loc = Srcloc::start(program_file); + let inner_puzzle = Rc::new(SExp::Integer(loc.clone(), 5_u32.to_bigint().unwrap())); + let launcher_coin = generate_launcher_coin(FIRST_COIN_PARENT, 1); + let launch = SingletonLaunch::new(launcher_coin.clone(), program_file, inner_puzzle, 1); + + let launcher_solution = launch.launcher_solution(); + let bootstrap_singleton = do_basic_brun(&vec![ + "brun".to_string(), + "--operators-version".to_string(), + "0".to_string(), + SINGLETON_LAUNCHER.to_string(), + launcher_solution.to_string(), + ]) + .trim() + .to_string(); + + assert_eq!(bootstrap_singleton, "((51 0xe435c0e8158464c825adb748900108adba4877bcd960c485f3effd3b8438f7e9 1) (60 0x8117fb4c6939a70936ab1d4f6ffe1daf24333978f0302c0464cbdd98fc346f65))"); + + // (((51 0xZZZZ... 1))) + let inner_solution = Rc::new(enlist( + launch.loc(), + &[Rc::new(enlist( + launch.loc(), + &[Rc::new(enlist( + launch.loc(), + &[ + Rc::new(SExp::Integer( + launch.loc(), + CREATE_COIN.to_bigint().unwrap(), + )), + launch.inner_puzzle_hash_atom.clone(), + launch.amount_atom.clone(), + ], + ))], + ))], + )); + let lineage_proof = launch.lineage_proof(&launcher_coin); + let solution_for_singleton = + launch.solution_for_singleton(&lineage_proof, inner_solution.clone()); + let singleton_eve_run = do_basic_brun(&vec![ + "brun".to_string(), + "--operators-version".to_string(), + "0".to_string(), + launch.curried_singleton.to_string(), + solution_for_singleton.to_string(), + ]) + .trim() + .to_string(); + + assert_eq!(singleton_eve_run, "((70 0xf5ab253587c5eee301cfe877321e662612f85f993a31616df45ef0f80a686fe8) (51 0xe435c0e8158464c825adb748900108adba4877bcd960c485f3effd3b8438f7e9 1))"); + let parent_of_eve_spend_coin = launch.get_next_coin(&launcher_coin); + let next_lineage_proof = launch.lineage_proof(&parent_of_eve_spend_coin); + let solution_for_next_singleton = + launch.solution_for_singleton(&next_lineage_proof, inner_solution.clone()); + let singleton_next_run = do_basic_brun(&vec![ + "brun".to_string(), + "--operators-version".to_string(), + "0".to_string(), + launch.curried_singleton.to_string(), + solution_for_next_singleton.to_string(), + ]) + .trim() + .to_string(); + + assert_eq!(singleton_next_run, "((70 0xff1dd6715c5de8101added4088b446308432f6f96f7ad95add6ec884834d7206) (51 0xe435c0e8158464c825adb748900108adba4877bcd960c485f3effd3b8438f7e9 1))"); +} diff --git a/src/tests/compiler/srcloc.rs b/src/tests/compiler/srcloc.rs index cbaa42594..040a6fd31 100644 --- a/src/tests/compiler/srcloc.rs +++ b/src/tests/compiler/srcloc.rs @@ -3,6 +3,7 @@ use crate::compiler::srcloc::Srcloc; // _ is the start to end range. // . is the target range. // X is an overlap. + // no _. #[test] fn test_overlap_1() { diff --git a/src/tests/compiler/types/chialisp.rs b/src/tests/compiler/types/chialisp.rs index d2b5f419f..ae6dcc36a 100644 --- a/src/tests/compiler/types/chialisp.rs +++ b/src/tests/compiler/types/chialisp.rs @@ -4,7 +4,8 @@ use std::rc::Rc; use crate::classic::clvm::__type_compatibility__::{bi_one, bi_zero}; use crate::compiler::compiler::DefaultCompilerOpts; -use crate::compiler::comptypes::CompileErr; +use crate::compiler::comptypes::{CompileErr, CompilerOpts}; +use crate::compiler::dialect::AcceptedDialect; use crate::compiler::frontend::frontend; use crate::compiler::sexp::{parse_sexp, SExp}; use crate::compiler::srcloc::{HasLoc, Srcloc}; @@ -121,12 +122,19 @@ pub fn test_chialisp_program_typecheck(s: &str, flatten: bool) -> Result, @@ -94,3 +97,55 @@ fn test_topo_sort_1() { assert!(result.is_err()); } + +// A simple pseudo RNG based on an lfsr. Good enough to generate interesting +// deterministic patterns. +pub struct RngLFSR { + generator: u32, +} + +impl RngLFSR { + pub fn new(state: u32) -> Self { + RngLFSR { generator: state } + } + fn next(&mut self) -> u32 { + self.generator = lfsr::galois::Galois16::up(self.generator); + self.generator + } +} + +impl RngCore for RngLFSR { + fn next_u32(&mut self) -> u32 { + let a = self.next(); + let b = self.next(); + (a << 16) | b + } + + fn next_u64(&mut self) -> u64 { + let a = self.next_u32() as u64; + let b = self.next_u32() as u64; + (a << 32) | b + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + if dest.is_empty() { + return; + } + + for i in 0..(dest.len() / 2) { + let a = self.next(); + dest[i * 2] = (a & 0xff) as u8; + dest[i * 2 + 1] = ((a >> 8) & 0xff) as u8; + } + + if (dest.len() & 1) != 0 { + let a = self.next(); + dest[dest.len() - 1] = (a & 0xff) as u8; + } + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + self.fill_bytes(dest); + Ok(()) + } +} diff --git a/src/util/mod.rs b/src/util/mod.rs index 51943649f..d075b9aba 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,6 +1,10 @@ use num_bigint::BigInt; use std::collections::HashSet; +use std::fs; +use std::io::Write; use std::mem::swap; +use std::path::Path; +use tempfile::NamedTempFile; use unicode_segmentation::UnicodeSegmentation; pub type Number = BigInt; @@ -81,7 +85,7 @@ where let mut finished_idx = 0; // Determine what's defined in these bindings. - for (_, item) in items.iter().enumerate() { + for item in items.iter() { for new_item in item.has.iter() { possible.insert(new_item.clone()); } @@ -145,3 +149,56 @@ where self.map_err(|e| e.into()) } } + +pub fn atomic_write_file( + input_path: &str, + output_path: &str, + target_data: &str, +) -> Result<(), String> { + let output_path_obj = Path::new(output_path); + let output_dir = output_path_obj + .parent() + .map(Ok) + .unwrap_or_else(|| Err("could not get parent of output path"))?; + + // Make the contents appear atomically so that other test processes + // won't mistake an empty file for intended output. + let mut temp_output_file = NamedTempFile::new_in(output_dir) + .map_err(|e| format!("error creating temporary compiler output for {input_path}: {e:?}"))?; + + let err_text = format!("failed to write to {:?}", temp_output_file.path()); + let translate_err = |_| err_text.clone(); + + temp_output_file + .write_all(target_data.as_bytes()) + .map_err(translate_err)?; + + temp_output_file + .persist(output_path) + .map_err(|e| format!("error persisting temporary compiler output {output_path}: {e:?}"))?; + + Ok(()) +} + +pub fn gentle_overwrite( + input_path: &str, + output_path: &str, + target_data: &str, +) -> Result<(), String> { + if let Ok(prev_content) = fs::read_to_string(output_path) { + let prev_trimmed = prev_content.trim(); + let trimmed = target_data.trim(); + if prev_trimmed == trimmed { + // We should try to overwrite here, but not fail if it doesn't + // work. This will accomodate both the read only scenario and + // the scenario where a target file is newer and people want the + // date to be updated. + atomic_write_file(input_path, output_path, target_data).ok(); + + // It's the same program, bail regardless. + return Ok(()); + } + } + + atomic_write_file(input_path, output_path, target_data) +} diff --git a/support/test-game-referee.sh b/support/test-game-referee.sh new file mode 100755 index 000000000..31e28a93a --- /dev/null +++ b/support/test-game-referee.sh @@ -0,0 +1,16 @@ +#!/bin/bash -x + +if [ "x$1" = x ] ; then + echo "usage: test-game-referee.sh [game-referee-version]" + exit 1 +fi + +REF_SUBDIR="$1" + +python -m pip install --upgrade pip +python -m pip install chia_rs==0.2.5 +python -m pip install clvm_tools +python -m pip install pytest + +export PYTHONPATH=$PWD/resources/tests:.:$PYTHONPATH +(cd "${REF_SUBDIR}" && pytest -s .) diff --git a/support/wheelname.py b/support/wheelname.py deleted file mode 100644 index 5b3cd7e4c..000000000 --- a/support/wheelname.py +++ /dev/null @@ -1,8 +0,0 @@ -import os -import subprocess - -wheels_files = os.listdir('target/wheels') -wheelname = list(filter(lambda x: x.endswith('whl') and 'musl' not in x, wheels_files))[0] -filename = "target/wheels/%s" % wheelname -print(filename) -subprocess.check_call(["pip", "install", filename]) diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 188b9174f..e775616a4 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -4,20 +4,32 @@ version = 3 [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] +[[package]] +name = "anyhow" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" + +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" + [[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -48,15 +60,9 @@ checksum = "383d29d513d8764dcdc42ea295d979eb99c3c9f00607b3692cf68a431f7dca72" [[package]] name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.3.3" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "bitvec" @@ -102,6 +108,18 @@ dependencies = [ "subtle", ] +[[package]] +name = "blst" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c94087b935a822949d3291a9989ad2b2051ea141eda0fd4e478a75f6aa3e604b" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + [[package]] name = "bumpalo" version = "3.13.0" @@ -125,12 +143,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.81" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c6b2562119bf28c3439f7f02db99faf0aa1a8cdfe5772a2ee155d32227239f0" -dependencies = [ - "libc", -] +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cfg-if" @@ -138,9 +153,60 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chia-bls" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba003303bda3019f2fe94e5478555a96addff1d6a1ea84bfe207b3f075cd8420" +dependencies = [ + "anyhow", + "arbitrary", + "blst", + "chia-traits", + "hex", + "hkdf", + "sha2 0.10.8", + "thiserror", + "tiny-bip39", +] + +[[package]] +name = "chia-traits" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe532ed59df94db00cc1fb85edc3c4dd7287d0590eefb356d960671b93081334" +dependencies = [ + "chia_streamable_macro", + "hex", + "sha2 0.10.8", + "thiserror", +] + +[[package]] +name = "chia_streamable_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "342cdb29dd8c1214d60fac24100ab1567756270710e93336db910a531fe8a264" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "clvm-traits" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5548b7de9921c68b2ca1101c08dd416bfa9afdf319f5b45183ecb3574ee177a3" +dependencies = [ + "num-bigint", + "thiserror", +] + [[package]] name = "clvm_tools_rs" -version = "0.1.35" +version = "0.1.40" dependencies = [ "binascii", "bls12_381", @@ -161,6 +227,7 @@ dependencies = [ "num-bigint", "num-traits", "pyo3-build-config", + "regex", "serde", "serde_json", "sha2 0.9.9", @@ -173,7 +240,7 @@ dependencies = [ [[package]] name = "clvm_tools_wasm" -version = "0.1.35" +version = "0.1.40" dependencies = [ "clvm_tools_rs", "clvmr", @@ -186,13 +253,12 @@ dependencies = [ [[package]] name = "clvmr" -version = "0.2.7" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2890f01537f1be43d2767ae71bbba0d0b3543dbb1ee892092d0ed4d913227fc" +checksum = "deabd4e4163efb64486937a7c80996e5bdfb88d21a6baa9c0f802e6b45906109" dependencies = [ - "bls12_381", - "getrandom", - "group", + "chia-bls", + "clvm-traits", "hex", "k256", "lazy_static", @@ -200,7 +266,7 @@ dependencies = [ "num-integer", "num-traits", "p256", - "sha2 0.9.9", + "sha2 0.10.8", ] [[package]] @@ -353,31 +419,26 @@ dependencies = [ ] [[package]] -name = "errno" -version = "0.3.2" +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys", -] +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "errno" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "cc", "libc", + "windows-sys", ] [[package]] name = "fastrand" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "ff" @@ -420,6 +481,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "group" version = "0.13.0" @@ -431,6 +498,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -440,12 +513,27 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" + [[package]] name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + [[package]] name = "hmac" version = "0.12.1" @@ -461,6 +549,16 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "indoc" version = "1.0.9" @@ -492,7 +590,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "once_cell", - "sha2 0.10.7", + "sha2 0.10.8", "signature", ] @@ -504,9 +602,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "linked-hash-map" @@ -516,9 +614,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.5" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "log" @@ -528,9 +626,9 @@ checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "num" @@ -609,6 +707,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi 0.3.4", + "libc", +] + [[package]] name = "once_cell" version = "1.18.0" @@ -630,7 +738,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "primeorder", - "sha2 0.10.7", + "sha2 0.10.8", ] [[package]] @@ -642,6 +750,15 @@ dependencies = [ "group", ] +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -661,6 +778,12 @@ dependencies = [ "spki", ] +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "primeorder" version = "0.13.2" @@ -670,6 +793,16 @@ dependencies = [ "elliptic-curve", ] +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + [[package]] name = "proc-macro2" version = "1.0.66" @@ -704,28 +837,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] -name = "rand_core" -version = "0.6.4" +name = "rand" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "getrandom", + "libc", + "rand_chacha", + "rand_core", ] [[package]] -name = "redox_syscall" -version = "0.3.5" +name = "rand_chacha" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ - "bitflags 1.3.2", + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", ] [[package]] name = "regex" -version = "1.9.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", @@ -735,9 +880,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7b6d6190b7594385f61bd3911cd1be99dfddcfc365a4160cc2ab5bff4aed294" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", @@ -746,9 +891,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "rfc6979" @@ -760,13 +905,19 @@ dependencies = [ "subtle", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustix" -version = "0.38.6" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee020b1716f0a80e2ace9b03441a749e402e86712f15f16fe8a8f75afac732f" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.3.3", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -845,9 +996,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -910,26 +1061,105 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.7.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", "rustix", "windows-sys", ] [[package]] name = "termcolor" -version = "1.2.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] +[[package]] +name = "thiserror" +version = "1.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e3de26b0965292219b4287ff031fcba86837900fe9cd2b34ea8ad893c0953d2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "268026685b2be38d7103e9e507c938a1fcb3d7e6eb15e87870b617bf37b6d581" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "tiny-bip39" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62cc94d358b5a1e84a5cb9109f559aa3c4d634d2b1b4de3d0fa4adc7c78e2861" +dependencies = [ + "anyhow", + "hmac", + "once_cell", + "pbkdf2", + "rand", + "rustc-hash", + "sha2 0.10.8", + "thiserror", + "unicode-normalization", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + [[package]] name = "typenum" version = "1.16.0" @@ -942,6 +1172,15 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-segmentation" version = "1.10.1" @@ -1080,9 +1319,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -1095,18 +1334,18 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -1119,45 +1358,54 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + +[[package]] +name = "winnow" +version = "0.5.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16" +dependencies = [ + "memchr", +] [[package]] name = "wyz" @@ -1182,3 +1430,17 @@ name = "zeroize" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml index fda4860f0..568a15a9d 100644 --- a/wasm/Cargo.toml +++ b/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clvm_tools_wasm" -version = "0.1.35" +version = "0.1.40" edition = "2018" authors = ["Art Yerkes "] description = "tools for working with chialisp language; compiler, repl, python and wasm bindings" @@ -23,4 +23,4 @@ wasm-bindgen = "=0.2.83" wasm-bindgen-test = "=0.3.25" js-sys = "0.3.60" num-bigint = "0.4.0" -num-traits = "0.2.15" \ No newline at end of file +num-traits = "0.2.15" diff --git a/wasm/src/api.rs b/wasm/src/api.rs index 333057018..ddbc8af3e 100644 --- a/wasm/src/api.rs +++ b/wasm/src/api.rs @@ -12,7 +12,14 @@ use wasm_bindgen::JsCast; use clvmr::allocator::Allocator; -use clvm_tools_rs::classic::clvm::__type_compatibility__::{Bytes, Stream, UnvalidatedBytesFromType}; +use crate::jsval::{ + btreemap_to_object, get_property, js_object_from_sexp, js_pair, object_to_value, + read_string_to_string_map, sexp_from_js_object, +}; +use crate::objects::Program; +use clvm_tools_rs::classic::clvm::__type_compatibility__::{ + Bytes, Stream, UnvalidatedBytesFromType, +}; use clvm_tools_rs::classic::clvm::serialize::sexp_to_stream; use clvm_tools_rs::classic::clvm_tools::clvmc::compile_clvm_inner; use clvm_tools_rs::classic::clvm_tools::stages::stage_0::DefaultProgramRunner; @@ -30,11 +37,6 @@ use clvm_tools_rs::compiler::repl::Repl; use clvm_tools_rs::compiler::runtypes::RunFailure; use clvm_tools_rs::compiler::sexp::SExp; use clvm_tools_rs::compiler::srcloc::Srcloc; -use crate::jsval::{ - btreemap_to_object, get_property, js_object_from_sexp, js_pair, object_to_value, - read_string_to_string_map, sexp_from_js_object, -}; -use crate::objects::Program; #[cfg(feature = "wee_alloc")] #[global_allocator] @@ -117,20 +119,14 @@ pub fn create_clvm_runner_err(error: String) -> JsValue { fn create_clvm_runner_run_failure(err: &RunFailure) -> JsValue { match err { - RunFailure::RunErr(l, e) => { - create_clvm_runner_err(format!("{}: Error {}", l, e)) - } - RunFailure::RunExn(l, e) => { - create_clvm_runner_err(format!("{}: Exn {}", l, e)) - } + RunFailure::RunErr(l, e) => create_clvm_runner_err(format!("{}: Error {}", l, e)), + RunFailure::RunExn(l, e) => create_clvm_runner_err(format!("{}: Exn {}", l, e)), } } fn create_clvm_compile_failure(err: &CompileErr) -> JsValue { match err { - CompileErr(l, e) => { - create_clvm_runner_err(format!("{}: Error {}", l, e)) - } + CompileErr(l, e) => create_clvm_runner_err(format!("{}: Error {}", l, e)), } } @@ -144,7 +140,12 @@ impl CldbSingleBespokeOverride for JsBespokeOverride { // When the user returns, try to convert the result back to sexp. fn get_override(&self, env: Rc) -> Result, RunFailure> { let args = js_sys::Array::new(); - args.set(0, js_object_from_sexp(env.clone()).map_err(|_| RunFailure::RunErr(env.loc(), "error converting override value".to_string()))?); + args.set( + 0, + js_object_from_sexp(env.clone()).map_err(|_| { + RunFailure::RunErr(env.loc(), "error converting override value".to_string()) + })?, + ); self.fun .apply(&JsValue::null(), &args) .map_err(|e| { @@ -247,7 +248,9 @@ pub fn create_clvm_runner( #[wasm_bindgen] pub fn final_value(runner: i32) -> JsValue { with_runner(runner, |r| { - r.cldbrun.final_result().map(|v| js_object_from_sexp(v).unwrap_or_else(|e| e)) + r.cldbrun + .final_result() + .map(|v| js_object_from_sexp(v).unwrap_or_else(|e| e)) }) .unwrap_or_else(JsValue::null) } @@ -280,7 +283,10 @@ fn make_compile_output(result_stream: &Stream, symbol_table: &HashMap { - return create_clvm_compile_failure(&CompileErr( - program.loc(), - e.to_string(), - )); - }, - Ok(x) => x, - }; + let hash_bytes = + match Bytes::new_validated(Some(UnvalidatedBytesFromType::Hex(function_hash.clone()))) { + Err(e) => { + return create_clvm_compile_failure(&CompileErr(program.loc(), e.to_string())); + } + Ok(x) => x, + }; let function_path = match path_to_function(main_env.1.clone(), &hash_bytes.data().clone()) { Some(p) => p, @@ -489,11 +492,14 @@ pub fn sexp_to_string(v: &JsValue) -> JsValue { #[wasm_bindgen] pub fn h(v: String) -> Result, JsValue> { - let hex_data = Bytes::new_validated(Some(UnvalidatedBytesFromType::Hex(v))).map_err(|_| js_sys::JsString::from("bad hex input"))?; + let hex_data = Bytes::new_validated(Some(UnvalidatedBytesFromType::Hex(v))) + .map_err(|_| js_sys::JsString::from("bad hex input"))?; Ok(hex_data.data().clone()) } #[wasm_bindgen] pub fn t(a: &JsValue, b: &JsValue) -> Result { - Program::as_pair_internal(&Program::cons_internal(&Program::to(a)?, &Program::to(b)?)?) + Program::as_pair_internal( + &Program::cons_internal(&Program::to_internal(a)?, &Program::to_internal(b)?)?.into(), + ) } diff --git a/wasm/src/jsval.rs b/wasm/src/jsval.rs index 0b9a65e13..170199836 100644 --- a/wasm/src/jsval.rs +++ b/wasm/src/jsval.rs @@ -1,6 +1,5 @@ -use js_sys; use js_sys::JSON::stringify; -use js_sys::{Array, BigInt, Object, Reflect}; +use js_sys::{Array, BigInt, Object, Reflect, Uint8Array}; use wasm_bindgen::JsCast; use num_bigint::ToBigInt; @@ -42,21 +41,27 @@ pub fn js_object_from_sexp(v: Rc) -> Result { match v.borrow() { SExp::Nil(_) => Ok(JsValue::null()), SExp::Integer(_, i) => Ok(JsValue::bigint_from_str(&i.to_string())), - SExp::QuotedString(_, _, q) => { - Ok(JsValue::from_str(&Bytes::new(Some(BytesFromType::Raw(q.clone()))).decode())) - } - SExp::Atom(_, q) => { - Ok(JsValue::from_str(&Bytes::new(Some(BytesFromType::Raw(q.clone()))).decode())) - } + SExp::QuotedString(_, _, q) => Ok(JsValue::from_str( + &Bytes::new(Some(BytesFromType::Raw(q.clone()))).decode(), + )), + SExp::Atom(_, q) => Ok(JsValue::from_str( + &Bytes::new(Some(BytesFromType::Raw(q.clone()))).decode(), + )), SExp::Cons(_, a, b) => { if let Some(lst) = v.proper_list() { let array = Array::new(); - for i in 0..lst.len() { - array.set(i as u32, js_object_from_sexp(Rc::new(lst[i].clone())).unwrap_or_else(|e| e)); + for (i, _) in lst.iter().enumerate() { + array.set( + i as u32, + js_object_from_sexp(Rc::new(lst[i].clone())).unwrap_or_else(|e| e), + ); } Ok(array_to_value(array)) } else { - t(&js_object_from_sexp(a.clone())?, &js_object_from_sexp(b.clone())?) + t( + &js_object_from_sexp(a.clone())?, + &js_object_from_sexp(b.clone())?, + ) } } } @@ -103,7 +108,7 @@ fn location(o: &Object) -> Option { line: l, col: c, until: get_property(o, "until") - .and_then(|lo| Object::try_from(&lo).map(|o| o.clone())) + .and_then(|lo| Object::try_from(&lo).cloned()) .and_then(|lo| location_lc_pair(&lo)) .map(|(ll, lc)| Until { line: ll, col: lc }), }) @@ -111,25 +116,29 @@ fn location(o: &Object) -> Option { pub fn detect_serializable(loc: &Srcloc, v: &JsValue) -> Option> { let serialize_key = JsValue::from_str("serialize"); - js_sys::Reflect::get(v, &serialize_key).ok().and_then(|serialize| { - Reflect::apply(serialize.unchecked_ref(), v, &js_sys::Array::new()).ok().and_then(|array| { - Array::try_from(array).ok().and_then(|array| { - let mut bytes_array: Vec = vec![]; - for item in array.iter() { - if let Some(n) = item.as_f64() { - if n < 0.0 || n > 255.0 { - return None; + js_sys::Reflect::get(v, &serialize_key) + .ok() + .and_then(|serialize| { + Reflect::apply(serialize.unchecked_ref(), v, &js_sys::Array::new()) + .ok() + .and_then(|array| { + Array::try_from(array).ok().and_then(|array| { + let mut bytes_array: Vec = vec![]; + for item in array.iter() { + if let Some(n) = item.as_f64() { + if !(0.0..=255.0).contains(&n) { + return None; + } + bytes_array.push(n as u8); + } else { + return None; + } } - bytes_array.push(n as u8); - } else { - return None; - } - } - return Some(Rc::new(SExp::QuotedString(loc.clone(), b'x', bytes_array))); - }) + Some(Rc::new(SExp::QuotedString(loc.clone(), b'x', bytes_array))) + }) + }) }) - }) } pub fn detect_convertible(v: &JsValue) -> Result, JsValue> { @@ -146,9 +155,9 @@ pub fn detect_convertible(v: &JsValue) -> Result, JsValue> { pub fn sexp_from_js_object(sstart: Srcloc, v: &JsValue) -> Option> { // Already converted value. if let Ok(res) = js_cache_value_from_js(v) { - find_cached_sexp(res.entry, &res.content).map(|result| { - result.modern.clone() - }).ok() + find_cached_sexp(res.entry, &res.content) + .map(|result| result.modern.clone()) + .ok() } else if v.is_bigint() { BigInt::new(v) .ok() @@ -157,22 +166,20 @@ pub fn sexp_from_js_object(sstart: Srcloc, v: &JsValue) -> Option> { .and_then(|v| v.parse::().ok()) .map(|x| Rc::new(SExp::Integer(sstart.clone(), x))) } else if let Some(fval) = v.as_f64() { - (fval as i64).to_bigint() + (fval as i64) + .to_bigint() .map(|x| Rc::new(SExp::Integer(sstart.clone(), x))) } else if let Some(g1_bytes) = detect_serializable(&sstart, v) { Some(g1_bytes) - } else if let Some(converted) = detect_convertible(v).ok() { + } else if let Ok(converted) = detect_convertible(v) { Some(converted) } else if Array::is_array(v) { let a = Array::from(v); - let mut result_value = Rc::new(SExp::Nil(Srcloc::start(&"*js*".to_string()))); + let mut result_value = Rc::new(SExp::Nil(Srcloc::start("*js*"))); for i_rev in 0..a.length() { let i = a.length() - i_rev - 1; - match sexp_from_js_object(sstart.clone(), &a.get(i)) { - Some(nv) => { - result_value = Rc::new(SExp::Cons(nv.loc(), nv, result_value)); - } - _ => {} + if let Some(nv) = sexp_from_js_object(sstart.clone(), &a.get(i)) { + result_value = Rc::new(SExp::Cons(nv.loc(), nv, result_value)); } } Some(result_value) @@ -180,9 +187,14 @@ pub fn sexp_from_js_object(sstart: Srcloc, v: &JsValue) -> Option> { Object::try_from(v) .map(|o| { let loc = get_property(o, "location") - .and_then(|o| Object::try_from(&o).map(|o| o.clone())) + .and_then(|o| Object::try_from(&o).cloned()) .and_then(|o| location(&o)) .unwrap_or_else(|| sstart.clone()); + if Uint8Array::instanceof(v) { + // Explicitly handle uint8array conversion. + let as_uint8array = Uint8Array::unchecked_from_js(v.clone()); + return Some(Rc::new(SExp::Atom(loc, as_uint8array.to_vec()))); + } get_property(o, "pair") .and_then(|p| { let pa = Array::from(&p); @@ -211,21 +223,21 @@ pub fn btreemap_to_object<'a>(iter: impl Iterator Result, String> { let mut result = HashMap::new(); - for ent in js_sys::Object::keys(&symbols).values() { + for ent in js_sys::Object::keys(symbols).values() { let key = ent.unwrap().as_string().unwrap(); - match get_property(&symbols, &key).unwrap().as_string() { + match get_property(symbols, &key).unwrap().as_string() { Some(val) => { result.insert(key, val); } diff --git a/wasm/src/objects.rs b/wasm/src/objects.rs index 3e13b3421..2188ce313 100644 --- a/wasm/src/objects.rs +++ b/wasm/src/objects.rs @@ -6,15 +6,20 @@ use std::cell::{RefCell, RefMut}; use std::collections::HashMap; use std::rc::Rc; use wasm_bindgen::prelude::*; - -use clvmr::Allocator; -use clvm_tools_rs::classic::clvm::__type_compatibility__::{Bytes, Stream, UnvalidatedBytesFromType, bi_one}; -use clvm_tools_rs::classic::clvm::serialize::{SimpleCreateCLVMObject, sexp_to_stream, sexp_from_stream}; +use wasm_bindgen::JsCast; + +use clvm_tools_rs::classic::clvm::__type_compatibility__::{ + bi_one, Bytes, Stream, UnvalidatedBytesFromType, +}; +use clvm_tools_rs::classic::clvm::serialize::{ + sexp_from_stream, sexp_to_stream, SimpleCreateCLVMObject, +}; use clvm_tools_rs::classic::clvm_tools::stages::stage_0::{DefaultProgramRunner, TRunProgram}; use clvm_tools_rs::compiler::clvm::{convert_from_clvm_rs, convert_to_clvm_rs, sha256tree, truthy}; use clvm_tools_rs::compiler::prims::{primapply, primcons, primquote}; use clvm_tools_rs::compiler::sexp::SExp; use clvm_tools_rs::compiler::srcloc::Srcloc; +use clvmr::Allocator; use crate::api::{create_clvm_runner_err, get_next_id}; use crate::jsval::{js_object_from_sexp, sexp_from_js_object}; @@ -40,20 +45,21 @@ struct ObjectCache { pub struct JsCacheValue { pub entry: i32, - pub content: String + pub content: String, } pub fn js_cache_value_from_js(jsval: &JsValue) -> Result { - let entry = js_sys::Reflect::get( - jsval, - &JsString::from("id") - )?.as_f64().ok_or(JsString::from("id was not a number"))?; - let content = js_sys::Reflect::get( - jsval, - &JsString::from("content") - )?.as_string().ok_or(JsString::from("content was not a string"))?; - - Ok(JsCacheValue { entry: entry as i32, content }) + let entry = js_sys::Reflect::get(jsval, &JsString::from("id"))? + .as_f64() + .ok_or(JsString::from("id was not a number"))?; + let content = js_sys::Reflect::get(jsval, &JsString::from("content"))? + .as_string() + .ok_or(JsString::from("content was not a string"))?; + + Ok(JsCacheValue { + entry: entry as i32, + content, + }) } impl Default for ObjectCache { @@ -84,45 +90,47 @@ impl ObjectCache { fn create_entry_from_sexp(&mut self, id: i32, sexp: Rc) -> Result { let mut allocator = Allocator::new(); - let node = convert_to_clvm_rs( - &mut allocator, - sexp.clone() - ).map_err(|_| js_sys::JsString::from("could not convert to clvm"))?; + let node = convert_to_clvm_rs(&mut allocator, sexp.clone()) + .map_err(|_| js_sys::JsString::from("could not convert to clvm"))?; let mut stream = Stream::new(None); sexp_to_stream(&mut allocator, node, &mut stream); - self.create_or_update_cache_entry(id, ObjectCacheMember { - modern: sexp.clone(), - }); + self.create_or_update_cache_entry( + id, + ObjectCacheMember { + modern: sexp.clone(), + }, + ); Ok(stream.get_value().hex()) } - fn find_or_create_entry_from_hex(&mut self, entry: i32, content: &str) -> Result { + fn find_or_create_entry_from_hex( + &mut self, + entry: i32, + content: &str, + ) -> Result { if let Some(res) = self.cache_data.get(&entry) { return Ok(res.clone()); } let mut allocator = Allocator::new(); - let bytes_from_hex = Bytes::new_validated(Some(UnvalidatedBytesFromType::Hex(content.to_string()))).map_err(|_| JsString::from("could not parse hex"))?; + let bytes_from_hex = + Bytes::new_validated(Some(UnvalidatedBytesFromType::Hex(content.to_string()))) + .map_err(|_| JsString::from("could not parse hex"))?; let mut stream = Stream::new(Some(bytes_from_hex)); let parsed = sexp_from_stream( &mut allocator, &mut stream, - Box::new(SimpleCreateCLVMObject {}) + Box::new(SimpleCreateCLVMObject {}), ) - .map(|x| x.1) - .map_err(|_| JsString::from("could not parse sexp from hex"))?; + .map(|x| x.1) + .map_err(|_| JsString::from("could not parse sexp from hex"))?; let srcloc = Srcloc::start("*var*"); - let modern = convert_from_clvm_rs( - &mut allocator, - srcloc, - parsed - ).map_err(|_| JsString::from("could not realize parsed sexp"))?; + let modern = convert_from_clvm_rs(&mut allocator, srcloc, parsed) + .map_err(|_| JsString::from("could not realize parsed sexp"))?; - let cache_entry = ObjectCacheMember { - modern - }; + let cache_entry = ObjectCacheMember { modern }; self.create_or_update_cache_entry(entry, cache_entry.clone()); Ok(cache_entry) @@ -222,13 +230,11 @@ static PROGRAM_FUNCTIONS: &[FunctionWrapperDesc] = &[ }, ]; -static TUPLE_FUNCTIONS: &[FunctionWrapperDesc] = &[ - FunctionWrapperDesc { - export_name: "to_program", - member_name: "tuple_to_program_internal", - varargs: false - }, -]; +static TUPLE_FUNCTIONS: &[FunctionWrapperDesc] = &[FunctionWrapperDesc { + export_name: "to_program", + member_name: "tuple_to_program_internal", + varargs: false, +}]; thread_local! { static OBJECT_CACHE: RefCell = { @@ -256,7 +262,7 @@ fn get_srcloc() -> Srcloc { pub fn find_cached_sexp(entry: i32, content: &str) -> Result { if content == "80" { return Ok(ObjectCacheMember { - modern: Rc::new(SExp::Nil(get_srcloc())) + modern: Rc::new(SExp::Nil(get_srcloc())), }); } @@ -266,6 +272,40 @@ pub fn find_cached_sexp(entry: i32, content: &str) -> Result]; + uncurry(): [IProgram, Array|null]; +} +"#; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "IProgram")] + pub type IProgram; +} + // Strategy for Program objects. // We'll provide a Program object that allows users to have something that // acts js-y but conserves compute time when possible. @@ -284,7 +324,7 @@ pub fn find_cached_sexp(entry: i32, content: &str) -> Result Result { @@ -297,12 +337,11 @@ fn get_program_prototype() -> Result { let program_self = js_sys::eval("Program")?; for func_wrapper_desc in PROGRAM_FUNCTIONS.iter() { - let pass_on_args = - if func_wrapper_desc.varargs { - "[args]" - } else { - "args" - }; + let pass_on_args = if func_wrapper_desc.varargs { + "[args]" + } else { + "args" + }; let to_string_fun = js_sys::Function::new_with_args( "", &format!("const t = this; return function() {{ let args = Array.prototype.slice.call(arguments); let apply_args = {pass_on_args}; apply_args.unshift(this); return t.{}.apply(null, apply_args); }}", func_wrapper_desc.member_name) @@ -356,10 +395,7 @@ pub fn finish_new_object(id: i32, encoded_hex: &str) -> Result let prototype = get_program_prototype()?; let new_object = js_sys::Object::new(); - js_sys::Reflect::set_prototype_of( - &new_object, - &prototype - )?; + js_sys::Reflect::set_prototype_of(&new_object, &prototype)?; js_sys::Reflect::set( &new_object, @@ -377,18 +413,38 @@ pub fn finish_new_object(id: i32, encoded_hex: &str) -> Result // Return a vector of arguments if the given SExp is the expected operator // and has the required number of arguments. -fn match_op(opcode: u8, expected_args: usize, opname: &str, program: Rc) -> Result>, JsValue> { - let plist = - if let Some(plist) = program.proper_list() { - plist +fn match_op( + opcode: u8, + mut expected_args: usize, + opname: &str, + program: Rc, +) -> Result>, JsValue> { + let plist = if expected_args == 0 { + if let SExp::Cons(_, a, b) = program.borrow() { + let a_borrowed: &SExp = a.borrow(); + let b_borrowed: &SExp = b.borrow(); + expected_args = 1; + vec![a_borrowed.clone(), b_borrowed.clone()] } else { - // Not a list so can't be an apply. - return Err(JsValue::from_str(&format!("program wasn't a list representing an {opname} op: {program}"))); - }; + return Err(JsValue::from_str(&format!( + "program was expected to be a cons, but wasn't: {program}" + ))); + } + } else if let Some(plist) = program.proper_list() { + plist + } else { + // Not a list so can't be an apply. + return Err(JsValue::from_str(&format!( + "program wasn't a list representing an {opname} op: {program}" + ))); + }; // Not the right length if plist.len() != expected_args + 1 { - return Err(JsValue::from_str(&format!("program list wasn't a list of {} representing an {opname} op: {program}", expected_args + 1))); + return Err(JsValue::from_str(&format!( + "program list wasn't a list of {} representing an {opname} op: {program}", + expected_args + 1 + ))); } // Not an apply @@ -409,12 +465,19 @@ fn cache_and_accumulate_arg(array: &Array, prog: Rc) -> Result<(), JsValue Ok(()) } +fn to_iprogram(v: JsValue) -> IProgram { + v.unchecked_into::() +} + #[wasm_bindgen] impl Program { - #[wasm_bindgen] - pub fn to(input: &JsValue) -> Result { + pub fn to_internal(input: &JsValue) -> Result { let loc = get_srcloc(); - let sexp = sexp_from_js_object(loc, input).map(Ok).unwrap_or_else(|| Err(create_clvm_runner_err(format!("unable to convert to value"))))?; + let sexp = sexp_from_js_object(loc, input).map(Ok).unwrap_or_else(|| { + Err(create_clvm_runner_err(format!( + "unable to convert to value" + ))) + })?; let new_id = get_next_id(); @@ -425,18 +488,23 @@ impl Program { } #[wasm_bindgen] - pub fn from_hex(input: &str) -> Result { + pub fn to(input: &JsValue) -> Result { + Program::to_internal(input).map(to_iprogram) + } + + #[wasm_bindgen] + pub fn from_hex(input: &str) -> Result { let new_id = get_next_id(); let obj = finish_new_object(new_id, input)?; - Program::to(&obj) + Program::to_internal(&obj).map(to_iprogram) } #[wasm_bindgen] - pub fn null() -> Result { + pub fn null() -> Result { let new_id = get_next_id(); let encoded = create_cached_sexp(new_id, Rc::new(SExp::Nil(get_srcloc())))?; - finish_new_object(new_id, &encoded) + finish_new_object(new_id, &encoded).map(to_iprogram) } #[wasm_bindgen] @@ -448,10 +516,7 @@ impl Program { #[wasm_bindgen] pub fn to_string_internal(obj: &JsValue) -> Result { - js_sys::Reflect::get( - obj, - &js_sys::JsString::from("content"), - ) + js_sys::Reflect::get(obj, &js_sys::JsString::from("content")) } #[wasm_bindgen] @@ -472,15 +537,8 @@ impl Program { result_value.set(0, object_a); result_value.set(1, object_b); // Support reading as a classic clvm input. - Reflect::set( - &result_value, - &JsString::from("pair"), - &result_value, - )?; - Reflect::set_prototype_of( - &result_value, - &prototype - )?; + Reflect::set(&result_value, &JsString::from("pair"), &result_value)?; + Reflect::set_prototype_of(&result_value, &prototype)?; return Ok(result_value.into()); } @@ -503,7 +561,10 @@ impl Program { pub fn as_int_internal(obj: &JsValue) -> Result { let cacheval = js_cache_value_from_js(obj)?; let cached = find_cached_sexp(cacheval.entry, &cacheval.content)?; - let number = cached.modern.get_number().map_err(|_| JsString::from("not a number"))?; + let number = cached + .modern + .get_number() + .map_err(|_| JsString::from("not a number"))?; (number.to_i32()).ok_or(JsString::from("number out of range").into()) } @@ -511,40 +572,44 @@ impl Program { pub fn as_bigint_internal(obj: &JsValue) -> Result { let cacheval = js_cache_value_from_js(obj)?; let cached = find_cached_sexp(cacheval.entry, &cacheval.content)?; - let number = cached.modern.get_number().map_err(|_| JsString::from("not a number"))?; + let number = cached + .modern + .get_number() + .map_err(|_| JsString::from("not a number"))?; let num_string = number.to_string(); let num_str: &str = &num_string; - js_sys::BigInt::new(&JsString::from(num_str)).map_err(|_| JsString::from("couldn't construct bigint").into()) + js_sys::BigInt::new(&JsString::from(num_str)) + .map_err(|_| JsString::from("couldn't construct bigint").into()) } #[wasm_bindgen] - pub fn first_internal(obj: &JsValue) -> Result { + pub fn first_internal(obj: &JsValue) -> Result { let cacheval = js_cache_value_from_js(obj)?; let cached = find_cached_sexp(cacheval.entry, &cacheval.content)?; if let SExp::Cons(_, a, _) = cached.modern.borrow() { let id_a = get_next_id(); let new_cached_a = create_cached_sexp(id_a, a.clone())?; - return finish_new_object(id_a, &new_cached_a); + return finish_new_object(id_a, &new_cached_a).map(to_iprogram); } Err(JsString::from("not a cons").into()) } #[wasm_bindgen] - pub fn rest_internal(obj: &JsValue) -> Result { + pub fn rest_internal(obj: &JsValue) -> Result { let cacheval = js_cache_value_from_js(obj)?; let cached = find_cached_sexp(cacheval.entry, &cacheval.content)?; if let SExp::Cons(_, _, a) = cached.modern.borrow() { let id_a = get_next_id(); let new_cached_a = create_cached_sexp(id_a, a.clone())?; - return finish_new_object(id_a, &new_cached_a); + return finish_new_object(id_a, &new_cached_a).map(to_iprogram); } Err(JsString::from("not a cons").into()) } #[wasm_bindgen] - pub fn cons_internal(obj: &JsValue, other: &JsValue) -> Result { + pub fn cons_internal(obj: &JsValue, other: &JsValue) -> Result { let cacheval = js_cache_value_from_js(obj)?; let cached = find_cached_sexp(cacheval.entry, &cacheval.content)?; @@ -552,9 +617,13 @@ impl Program { let other_cache = find_cached_sexp(other_val.entry, &other_val.content)?; let new_id = get_next_id(); - let new_sexp = Rc::new(SExp::Cons(get_srcloc(), cached.modern.clone(), other_cache.modern.clone())); + let new_sexp = Rc::new(SExp::Cons( + get_srcloc(), + cached.modern.clone(), + other_cache.modern.clone(), + )); let new_cached = create_cached_sexp(new_id, new_sexp)?; - finish_new_object(new_id, &new_cached) + finish_new_object(new_id, &new_cached).map(to_iprogram) } #[wasm_bindgen] @@ -566,41 +635,30 @@ impl Program { let arg_cache = find_cached_sexp(argval.entry, &argval.content)?; let mut allocator = Allocator::new(); - let prog_classic = convert_to_clvm_rs( - &mut allocator, - prog_cache.modern.clone() - ).map_err(|_| { - let err: JsValue = JsString::from("error converting program").into(); - err - })?; - let arg_classic = convert_to_clvm_rs( - &mut allocator, - arg_cache.modern.clone() - ).map_err(|_| { - let err: JsValue = JsString::from("error converting args").into(); - err - })?; + let prog_classic = + convert_to_clvm_rs(&mut allocator, prog_cache.modern.clone()).map_err(|_| { + let err: JsValue = JsString::from("error converting program").into(); + err + })?; + let arg_classic = + convert_to_clvm_rs(&mut allocator, arg_cache.modern.clone()).map_err(|_| { + let err: JsValue = JsString::from("error converting args").into(); + err + })?; let runner = DefaultProgramRunner::default(); - let run_result = - runner.run_program( - &mut allocator, - prog_classic, - arg_classic, - None - ).map_err(|e| { + let run_result = runner + .run_program(&mut allocator, prog_classic, arg_classic, None) + .map_err(|e| { let err_str: &str = &e.1; let err: JsValue = JsString::from(err_str).into(); err })?; - let modern_result = convert_from_clvm_rs( - &mut allocator, - get_srcloc(), - run_result.1 - ).map_err(|_| { - let err: JsValue = JsString::from("error converting result").into(); - err - })?; + let modern_result = convert_from_clvm_rs(&mut allocator, get_srcloc(), run_result.1) + .map_err(|_| { + let err: JsValue = JsString::from("error converting result").into(); + err + })?; let result_id = get_next_id(); let new_cached_result = create_cached_sexp(result_id, modern_result)?; let result_object = finish_new_object(result_id, &new_cached_result)?; @@ -611,25 +669,19 @@ impl Program { } #[wasm_bindgen] - pub fn tuple_to_program_internal(obj: &JsValue) -> Result { - let a = js_sys::Reflect::get( - obj, - &JsString::from("0"), - )?; - let b = js_sys::Reflect::get( - obj, - &JsString::from("1"), - )?; + pub fn tuple_to_program_internal(obj: &JsValue) -> Result { + let a = js_sys::Reflect::get(obj, &JsString::from("0"))?; + let b = js_sys::Reflect::get(obj, &JsString::from("1"))?; Program::cons_internal(&a, &b) } #[wasm_bindgen] pub fn as_bin_internal(obj: &JsValue) -> Result, JsValue> { - let convert = Reflect::get( - obj, - &JsString::from("content"), - )?.as_string().ok_or(JsString::from("content wasn't a hex string"))?; - let bytes = Bytes::new_validated(Some(UnvalidatedBytesFromType::Hex(convert))).map_err(|_| JsString::from("could not convert to binary data"))?; + let convert = Reflect::get(obj, &JsString::from("content"))? + .as_string() + .ok_or(JsString::from("content wasn't a hex string"))?; + let bytes = Bytes::new_validated(Some(UnvalidatedBytesFromType::Hex(convert))) + .map_err(|_| JsString::from("could not convert to binary data"))?; Ok(bytes.data().clone()) } @@ -687,7 +739,7 @@ impl Program { // Resulting in a function which places its own arguments after those // curried in in the form of a proper list. #[wasm_bindgen] - pub fn curry_internal(obj: &JsValue, args: Vec) -> Result { + pub fn curry_internal(obj: &JsValue, args: Vec) -> Result { let program_val = Program::to(obj)?; let cacheval = js_cache_value_from_js(&program_val)?; let program = find_cached_sexp(cacheval.entry, &cacheval.content)?; @@ -700,41 +752,51 @@ impl Program { fixed_args = Rc::new(primcons( get_srcloc(), Rc::new(primquote(get_srcloc(), a_cached.modern.clone())), - fixed_args + fixed_args, )); } let result = Rc::new(primapply( get_srcloc(), Rc::new(primquote(get_srcloc(), program.modern.clone())), - fixed_args + fixed_args, )); let new_id = get_next_id(); let new_cached = create_cached_sexp(new_id, result)?; - finish_new_object(new_id, &new_cached) + finish_new_object(new_id, &new_cached).map(to_iprogram) } #[wasm_bindgen] - pub fn uncurry_error_internal(obj: &JsValue) -> Result { + pub fn uncurry_error_internal(obj: &JsValue) -> Result, JsValue> { let program_val = Program::to(obj)?; let cacheval = js_cache_value_from_js(&program_val)?; let program = find_cached_sexp(cacheval.entry, &cacheval.content)?; let apply_args = match_op(2, 2, "apply", program.modern.clone())?; + // Not used in code, but detects a quoted program. - let quoted_prog = match_op(1, 1, "quote", apply_args[0].clone())?; + let quoted_prog = match_op(1, 0, "quote", apply_args[0].clone())?; let retrieved_args = Array::new(); let mut cons_expr = match_op(4, 2, "cons", apply_args[1].clone())?; - cache_and_accumulate_arg(&retrieved_args, cons_expr[0].clone())?; + + let decons_and_unquote = |expr: Rc| { + if let Ok(unquoted_curry_argument) = match_op(1, 0, "quote", expr.clone()) { + unquoted_curry_argument[0].clone() + } else { + expr + } + }; + + cache_and_accumulate_arg(&retrieved_args, decons_and_unquote(cons_expr[0].clone()))?; let mut next_cons = cons_expr[1].clone(); while matches!(next_cons.borrow(), SExp::Cons(_, _, _)) { cons_expr = match_op(4, 2, "cons", next_cons)?; // Convert to the external js form and insert into cache so we can // forego conversion if still cached. - cache_and_accumulate_arg(&retrieved_args, cons_expr[0].clone())?; + cache_and_accumulate_arg(&retrieved_args, decons_and_unquote(cons_expr[0].clone()))?; // Move on to the tail that's being built. next_cons = cons_expr[1].clone(); @@ -751,21 +813,21 @@ impl Program { let new_cached_mod = create_cached_sexp(mod_id, quoted_prog[0].clone())?; let mod_js = finish_new_object(mod_id, &new_cached_mod)?; - let res = Array::new(); - res.push(&mod_js); - res.push(&retrieved_args); - Ok(res.into()) + Ok(vec![ + mod_js.into(), + retrieved_args.unchecked_into::(), + ]) } #[wasm_bindgen] - pub fn uncurry_internal(obj: &JsValue) -> JsValue { + pub fn uncurry_internal(obj: &JsValue) -> Result, JsValue> { if let Ok(res) = Program::uncurry_error_internal(obj) { - res + Ok(res) } else { - let res = Array::new(); - res.push(obj); - res.push(&JsValue::null()); - res.into() + Ok(vec![ + obj.clone().unchecked_into::(), + JsValue::null().unchecked_into::(), + ]) } } } diff --git a/wasm/tests/clvm-tools-interface/content/test_cat2_program.hex b/wasm/tests/clvm-tools-interface/content/test_cat2_program.hex new file mode 100644 index 000000000..1fc0fa674 --- /dev/null +++ b/wasm/tests/clvm-tools-interface/content/test_cat2_program.hex @@ -0,0 +1 @@ +ff02ffff01ff02ffff01ff02ff5effff04ff02ffff04ffff04ff05ffff04ffff0bff2cff0580ffff04ff0bff80808080ffff04ffff02ff17ff2f80ffff04ff5fffff04ffff02ff2effff04ff02ffff04ff17ff80808080ffff04ffff0bff82027fff82057fff820b7f80ffff04ff81bfffff04ff82017fffff04ff8202ffffff04ff8205ffffff04ff820bffff80808080808080808080808080ffff04ffff01ffffffff81ca3dff46ff0233ffff3c04ff01ff0181cbffffff02ff02ffff03ff05ffff01ff02ff32ffff04ff02ffff04ff0dffff04ffff0bff22ffff0bff2cff3480ffff0bff22ffff0bff22ffff0bff2cff5c80ff0980ffff0bff22ff0bffff0bff2cff8080808080ff8080808080ffff010b80ff0180ffff02ffff03ff0bffff01ff02ffff03ffff09ffff02ff2effff04ff02ffff04ff13ff80808080ff820b9f80ffff01ff02ff26ffff04ff02ffff04ffff02ff13ffff04ff5fffff04ff17ffff04ff2fffff04ff81bfffff04ff82017fffff04ff1bff8080808080808080ffff04ff82017fff8080808080ffff01ff088080ff0180ffff01ff02ffff03ff17ffff01ff02ffff03ffff20ff81bf80ffff0182017fffff01ff088080ff0180ffff01ff088080ff018080ff0180ffff04ffff04ff05ff2780ffff04ffff10ff0bff5780ff778080ff02ffff03ff05ffff01ff02ffff03ffff09ffff02ffff03ffff09ff11ff7880ffff0159ff8080ff0180ffff01818f80ffff01ff02ff7affff04ff02ffff04ff0dffff04ff0bffff04ffff04ff81b9ff82017980ff808080808080ffff01ff02ff5affff04ff02ffff04ffff02ffff03ffff09ff11ff7880ffff01ff04ff78ffff04ffff02ff36ffff04ff02ffff04ff13ffff04ff29ffff04ffff0bff2cff5b80ffff04ff2bff80808080808080ff398080ffff01ff02ffff03ffff09ff11ff2480ffff01ff04ff24ffff04ffff0bff20ff2980ff398080ffff010980ff018080ff0180ffff04ffff02ffff03ffff09ff11ff7880ffff0159ff8080ff0180ffff04ffff02ff7affff04ff02ffff04ff0dffff04ff0bffff04ff17ff808080808080ff80808080808080ff0180ffff01ff04ff80ffff04ff80ff17808080ff0180ffffff02ffff03ff05ffff01ff04ff09ffff02ff26ffff04ff02ffff04ff0dffff04ff0bff808080808080ffff010b80ff0180ff0bff22ffff0bff2cff5880ffff0bff22ffff0bff22ffff0bff2cff5c80ff0580ffff0bff22ffff02ff32ffff04ff02ffff04ff07ffff04ffff0bff2cff2c80ff8080808080ffff0bff2cff8080808080ffff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff2effff04ff02ffff04ff09ff80808080ffff02ff2effff04ff02ffff04ff0dff8080808080ffff01ff0bff2cff058080ff0180ffff04ffff04ff28ffff04ff5fff808080ffff02ff7effff04ff02ffff04ffff04ffff04ff2fff0580ffff04ff5fff82017f8080ffff04ffff02ff7affff04ff02ffff04ff0bffff04ff05ffff01ff808080808080ffff04ff17ffff04ff81bfffff04ff82017fffff04ffff0bff8204ffffff02ff36ffff04ff02ffff04ff09ffff04ff820affffff04ffff0bff2cff2d80ffff04ff15ff80808080808080ff8216ff80ffff04ff8205ffffff04ff820bffff808080808080808080808080ff02ff2affff04ff02ffff04ff5fffff04ff3bffff04ffff02ffff03ff17ffff01ff09ff2dffff0bff27ffff02ff36ffff04ff02ffff04ff29ffff04ff57ffff04ffff0bff2cff81b980ffff04ff59ff80808080808080ff81b78080ff8080ff0180ffff04ff17ffff04ff05ffff04ff8202ffffff04ffff04ffff04ff24ffff04ffff0bff7cff2fff82017f80ff808080ffff04ffff04ff30ffff04ffff0bff81bfffff0bff7cff15ffff10ff82017fffff11ff8202dfff2b80ff8202ff808080ff808080ff138080ff80808080808080808080ff018080ffff04ffff01a072dec062874cd4d3aab892a0906688a1ae412b0109982e1797a170add88bdcdcffff04ffff01a06d95dae356e32a71db5ddcb42224754a02524c615c5fc35f568c2af04774e589ffff04ffff01ff02ffff01ff02ffff01ff02ffff03ff0bffff01ff02ffff03ffff09ff05ffff1dff0bffff1effff0bff0bffff02ff06ffff04ff02ffff04ff17ff8080808080808080ffff01ff02ff17ff2f80ffff01ff088080ff0180ffff01ff04ffff04ff04ffff04ff05ffff04ffff02ff06ffff04ff02ffff04ff17ff80808080ff80808080ffff02ff17ff2f808080ff0180ffff04ffff01ff32ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff06ffff04ff02ffff04ff09ff80808080ffff02ff06ffff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080ffff04ffff01b0a7ca4bce10200d073ef10c46e9d27c3b4e31263d4c07fbec447650fcc1b286300e8ecf25c0560f9cb5aa673247fb6a6fff018080ff0180808080 \ No newline at end of file diff --git a/wasm/tests/clvm-tools-interface/package.json b/wasm/tests/clvm-tools-interface/package.json index 3fc737a5f..a63cc6cdc 100644 --- a/wasm/tests/clvm-tools-interface/package.json +++ b/wasm/tests/clvm-tools-interface/package.json @@ -8,7 +8,7 @@ "start": "webpack serve --config webpack.config.demo.js", "build": "webpack && tsc", "build:demo": "webpack --config webpack.config.demo.js", - "test": "jest", + "test": "tsc -p tstestconfig.json --noEmit && jest", "coverage": "npm run test -- --coverage", "prepare": "npm run build", "trypublish": "npm publish || true" diff --git a/wasm/tests/clvm-tools-interface/src/lib/tests/index.test.ts b/wasm/tests/clvm-tools-interface/src/lib/tests/index.test.ts index 626d11b41..96863fd66 100644 --- a/wasm/tests/clvm-tools-interface/src/lib/tests/index.test.ts +++ b/wasm/tests/clvm-tools-interface/src/lib/tests/index.test.ts @@ -1,35 +1,60 @@ +import type { IProgram, ITuple } from '../../../../../pkg/clvm_tools_wasm.js'; +import type { G1Element } from 'bls-signatures'; + import * as fs from 'fs'; import { resolve } from 'path'; import * as assert from 'assert'; import * as bls_loader from 'bls-signatures'; -const {h, t, Program} = require('../../../../../pkg/clvm_tools_wasm'); +const {h, t, Program} = require('../../../../../pkg/clvm_tools_wasm.js'); it('Has BLS signatures support', async () => { - let bls = await bls_loader.default(); - let g1element = new bls.G1Element(); - let converted_g1_element = Program.to(g1element); + const bls = await bls_loader.default(); + const g1element = new bls.G1Element(); + const converted_g1_element = Program.to(g1element); assert.equal('b0c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', converted_g1_element.toString()); }); it('Has the "h" function', async () => { - let unhexed = h('21203031'); + const unhexed = h('21203031'); assert.equal([0x21, 0x20, 0x30, 0x31].toString(), unhexed.toString()); }); +it('Converts uint8arrays', async () => { + let ua = new Uint8Array(3); + ua[0] = 0x30; + ua[1] = 0x81; + ua[2] = 0xff; + let p = Program.to(ua); + assert.equal([0x30, 0x81, 0xff].toString(), ua.toString()); +}); + +it('Converts uint8arrays from the "h" function', async () => { + let unhexed = h('8b5fd961cb1a826823c45a796b350d0d6ba2398829f249b1e535fd76f6d150b1'); + let p = Program.to([unhexed]); + assert.equal("ffa08b5fd961cb1a826823c45a796b350d0d6ba2398829f249b1e535fd76f6d150b180", p.toString()); +}); + +it('Converts a buffer', async () => { + let unhexed = h('8b5fd961cb1a826823c45a796b350d0d6ba2398829f249b1e535fd76f6d150b1'); + let b = Buffer.from(unhexed); + let p = Program.to([b]); + assert.equal("ffa08b5fd961cb1a826823c45a796b350d0d6ba2398829f249b1e535fd76f6d150b180", p.toString()); +}); + it('Converts to string', async () => { - let converted_sexp = Program.to([1, 2, 3]); + const converted_sexp = Program.to([1, 2, 3]); assert.equal("ff01ff02ff0380", converted_sexp.toString()); }); it('Accepts already converted objects', async () => { - let converted_sexp = Program.to([1, 2, 3]); - let twice_converted = Program.to(converted_sexp); + const converted_sexp = Program.to([1, 2, 3]); + const twice_converted = Program.to(converted_sexp); assert.equal("ff01ff02ff0380", twice_converted.toString()); }); it('Has as_pair', async () => { - let converted_sexp = Program.to([1, 2, 3]); - let as_pair = converted_sexp.as_pair(); + const converted_sexp = Program.to([1, 2, 3]); + const as_pair = converted_sexp.as_pair(); assert.equal("01", as_pair[0].toString()); assert.equal("ff02ff0380", as_pair[1].toString()); }); @@ -39,17 +64,17 @@ it('Has null', async () => { }); it('Has listp', async () => { - let is_list = Program.to([1,2,3]); - let isnt_list = Program.to(456); + const is_list: IProgram = Program.to([1,2,3]); + const isnt_list: IProgram = Program.to(456); assert.equal(is_list.listp(), true); assert.equal(isnt_list.listp(), false); }); it('Has nullp', async () => { - let is_null = Program.to([]); - let is_also_null = Program.to(0); - let isnt_null = Program.to(7); - let isnt_also_null = Program.to([99,101]); + const is_null = Program.to([]); + const is_also_null = Program.to(0); + const isnt_null = Program.to(7); + const isnt_also_null = Program.to([99,101]); assert.equal(is_null.nullp(), true); assert.equal(is_also_null.nullp(), true); assert.equal(isnt_null.nullp(), false); @@ -57,130 +82,149 @@ it('Has nullp', async () => { }); it('Has as_int', async () => { - let int_value = Program.to(7).as_int(); + const int_value = Program.to(7).as_int(); assert.equal(int_value, 7); try { - non_int_value = Program.to([7,13]).as_int(); - assert.fail(true); - } catch (e) { + /*const non_int_value =*/ Program.to([7,13]).as_int(); + assert.fail('was an int but should not be'); + } catch (e: any) { assert.equal(e.toString(), "not a number"); } }); it('Has as_bigint', async () => { - let int_value = Program.to(10000000000000000000000n).as_bigint(); + const int_value = Program.to(10000000000000000000000n).as_bigint(); assert.equal(int_value, 10000000000000000000000n); try { - non_int_value = Program.to([7,13]).as_bigint(); - assert.fail(true); - } catch (e) { + /*const non_int_value =*/ Program.to([7,13]).as_bigint(); + assert.fail(''); + } catch (e: any) { assert.equal(e.toString(), "not a number"); } }); it('Has first and rest', async () => { - let test_list = Program.to([7,13,17,23]); + const test_list = Program.to([7,13,17,23]); assert.equal(test_list.first().toString(), '07'); assert.equal(test_list.rest().toString(), 'ff0dff11ff1780'); try { Program.to([]).first(); - assert.fail(true); - } catch (e) { + assert.fail("empty list had first"); + } catch (e: any) { assert.equal(e.toString(), "not a cons"); } try { Program.to([]).rest(); - assert.fail(true); - } catch (e) { + assert.fail("empty list had rest"); + } catch (e: any) { assert.equal(e.toString(), "not a cons"); } }); it('Has cons', async () => { - let test_1 = Program.to(7); - let test_2 = Program.to([8,9,10]); - let consed = test_1.cons(test_2); - let test_3 = Program.to([7,8,9,10]); + const test_1 = Program.to(7); + const test_2 = Program.to([8,9,10]); + const consed = test_1.cons(test_2); + const test_3 = Program.to([7,8,9,10]); assert.equal(consed.toString(), test_3.toString()); }); it('Has the t function', async () => { - let p1 = Program.to(7); - let p2 = Program.to(9); - let tuple = t(p1, p2); - let consed = p1.cons(p2); + const p1 = Program.to(7); + const p2 = Program.to(9); + const tuple: ITuple = t(p1, p2); + const consed = p1.cons(p2); assert.equal(Program.to(tuple).toString(), consed.toString()); }); it('Has as_bin', async () => { - let test_data = Program.to([7,8,9,10]); - let as_bin = test_data.as_bin(); + const test_data = Program.to([7,8,9,10]); + const as_bin: Uint8Array = test_data.as_bin(); assert.equal([255,7,255,8,255,9,255,10,128].toString(), as_bin.toString()); }); it('Has list_len', async () => { - let list_data = Program.to([7,8,9,10]); - let list_len = list_data.list_len(); + const list_data = Program.to([7,8,9,10]); + const list_len = list_data.list_len(); assert.equal(list_len, 4); - let not_list = Program.to(16); - let not_list_len = not_list.list_len(); + const not_list = Program.to(16); + const not_list_len = not_list.list_len(); assert.equal(not_list_len, 0); }); it('Has equal_to', async () => { - let p1 = Program.to([7,8,[9,10],11]); - let p2 = Program.from_hex('ff07ff08ffff09ff0a80ff0b80'); - let p3 = Program.to([7,8,[9,11],11]); + const p1 = Program.to([7,8,[9,10],11]); + const p2 = Program.from_hex('ff07ff08ffff09ff0a80ff0b80'); + const p3 = Program.to([7,8,[9,11],11]); assert.ok(p1.equal_to(p2)); assert.ok(!p1.equal_to(p3)); assert.ok(!p2.equal_to(p3)); }); it('Has as_javascript', async () => { - let tuple = t(9,(t(10,11))); - let original = [7,8,tuple,12]; - let p1 = Program.to(original); - let p1_as_js = p1.as_javascript(); + const tuple = t(9,(t(10,11))); + const original = [7,8,tuple,12]; + const p1 = Program.to(original); + const p1_as_js = p1.as_javascript(); assert.equal(original.toString(), p1_as_js.toString()); }); it('Has run', async () => { - let program = Program.from_hex('ff12ffff10ff02ffff010180ffff11ff02ffff01018080'); - let args = Program.to([13]); + const program = Program.from_hex('ff12ffff10ff02ffff010180ffff11ff02ffff01018080'); + const args = Program.to([13]); const [cost, run_result] = program.run(args); assert.equal(run_result.toString(), '8200a8'); assert.equal(cost, 2658); }); it('Has curry', async () => { - let program = Program.from_hex('ff12ffff10ff02ffff010180ffff11ff02ffff01018080'); - let program_with_arg = program.curry(Program.to(13)); + const program = Program.from_hex('ff12ffff10ff02ffff010180ffff11ff02ffff01018080'); + const program_with_arg = program.curry(Program.to(13)); const [cost, run_result] = program_with_arg.run(Program.to([])); assert.equal(run_result.toString(), '8200a8'); assert.equal(cost, 2884); }); export class ChiaExample { - constructor(MOD) { + private MOD: IProgram; + + constructor(MOD: IProgram) { this.MOD = MOD; } - public puzzle_for_synthetic_public_key(synthetic_public_key: G1Element): Program { - return this.MOD.curry(synthetic_public_key); + public puzzle_for_synthetic_public_key(synthetic_public_key: G1Element): IProgram { + return this.MOD.curry(Program.to(synthetic_public_key)); } } it('works as expected in context', async () => { - let bls = await bls_loader.default(); + const bls = await bls_loader.default(); const program_text = fs.readFileSync(resolve(__dirname, '../../../content/p2_delegated_puzzle_or_hidden_puzzle.clvm.hex'),'utf-8'); - const MOD: Program = Program.from_hex(program_text); - let ce = new ChiaExample(MOD); - let sk = bls.AugSchemeMPL.key_gen([ + const MOD: IProgram = Program.from_hex(program_text); + const ce = new ChiaExample(MOD); + const sk = bls.AugSchemeMPL.key_gen(new Uint8Array([ 0, 50, 6, 244, 24, 199, 1, 25, 52, 88, 192, 19, 18, 12, 89, 6, 220, 18, 102, 58, 209, 82, 12, 62, 89, 110, 182, 9, 44, 20, 254, 22 - ]); - let pk = bls.AugSchemeMPL.sk_to_g1(sk); + ])); + const pk = bls.AugSchemeMPL.sk_to_g1(sk); // pk bytes 86243290bbcbfd9ae75bdece7981965350208eb5e99b04d5cd24e955ada961f8c0a162dee740be7bdc6c3c0613ba2eb1 // Expected puzzle hash = 30cdae3d54778db5eba21584c452cfb1a278136b2ec352ba44a52078efea7507 - let target_puzzle = ce.puzzle_for_synthetic_public_key(pk); - assert.equal(target_puzzle.sha256tree().toString(), h('30cdae3d54778db5eba21584c452cfb1a278136b2ec352ba44a52078efea7507').toString()); + const target_puzzle = ce.puzzle_for_synthetic_public_key(pk); + const shatree_result: Uint8Array = target_puzzle.sha256tree(); + assert.equal(shatree_result.toString(), h('30cdae3d54778db5eba21584c452cfb1a278136b2ec352ba44a52078efea7507').toString()); +}); + +const cat2_puzzle = 'ff02ffff01ff02ff5effff04ff02ffff04ffff04ff05ffff04ffff0bff2cff0580ffff04ff0bff80808080ffff04ffff02ff17ff2f80ffff04ff5fffff04ffff02ff2effff04ff02ffff04ff17ff80808080ffff04ffff0bff82027fff82057fff820b7f80ffff04ff81bfffff04ff82017fffff04ff8202ffffff04ff8205ffffff04ff820bffff80808080808080808080808080ffff04ffff01ffffffff81ca3dff46ff0233ffff3c04ff01ff0181cbffffff02ff02ffff03ff05ffff01ff02ff32ffff04ff02ffff04ff0dffff04ffff0bff22ffff0bff2cff3480ffff0bff22ffff0bff22ffff0bff2cff5c80ff0980ffff0bff22ff0bffff0bff2cff8080808080ff8080808080ffff010b80ff0180ffff02ffff03ff0bffff01ff02ffff03ffff09ffff02ff2effff04ff02ffff04ff13ff80808080ff820b9f80ffff01ff02ff26ffff04ff02ffff04ffff02ff13ffff04ff5fffff04ff17ffff04ff2fffff04ff81bfffff04ff82017fffff04ff1bff8080808080808080ffff04ff82017fff8080808080ffff01ff088080ff0180ffff01ff02ffff03ff17ffff01ff02ffff03ffff20ff81bf80ffff0182017fffff01ff088080ff0180ffff01ff088080ff018080ff0180ffff04ffff04ff05ff2780ffff04ffff10ff0bff5780ff778080ff02ffff03ff05ffff01ff02ffff03ffff09ffff02ffff03ffff09ff11ff7880ffff0159ff8080ff0180ffff01818f80ffff01ff02ff7affff04ff02ffff04ff0dffff04ff0bffff04ffff04ff81b9ff82017980ff808080808080ffff01ff02ff5affff04ff02ffff04ffff02ffff03ffff09ff11ff7880ffff01ff04ff78ffff04ffff02ff36ffff04ff02ffff04ff13ffff04ff29ffff04ffff0bff2cff5b80ffff04ff2bff80808080808080ff398080ffff01ff02ffff03ffff09ff11ff2480ffff01ff04ff24ffff04ffff0bff20ff2980ff398080ffff010980ff018080ff0180ffff04ffff02ffff03ffff09ff11ff7880ffff0159ff8080ff0180ffff04ffff02ff7affff04ff02ffff04ff0dffff04ff0bffff04ff17ff808080808080ff80808080808080ff0180ffff01ff04ff80ffff04ff80ff17808080ff0180ffffff02ffff03ff05ffff01ff04ff09ffff02ff26ffff04ff02ffff04ff0dffff04ff0bff808080808080ffff010b80ff0180ff0bff22ffff0bff2cff5880ffff0bff22ffff0bff22ffff0bff2cff5c80ff0580ffff0bff22ffff02ff32ffff04ff02ffff04ff07ffff04ffff0bff2cff2c80ff8080808080ffff0bff2cff8080808080ffff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff2effff04ff02ffff04ff09ff80808080ffff02ff2effff04ff02ffff04ff0dff8080808080ffff01ff0bff2cff058080ff0180ffff04ffff04ff28ffff04ff5fff808080ffff02ff7effff04ff02ffff04ffff04ffff04ff2fff0580ffff04ff5fff82017f8080ffff04ffff02ff7affff04ff02ffff04ff0bffff04ff05ffff01ff808080808080ffff04ff17ffff04ff81bfffff04ff82017fffff04ffff0bff8204ffffff02ff36ffff04ff02ffff04ff09ffff04ff820affffff04ffff0bff2cff2d80ffff04ff15ff80808080808080ff8216ff80ffff04ff8205ffffff04ff820bffff808080808080808080808080ff02ff2affff04ff02ffff04ff5fffff04ff3bffff04ffff02ffff03ff17ffff01ff09ff2dffff0bff27ffff02ff36ffff04ff02ffff04ff29ffff04ff57ffff04ffff0bff2cff81b980ffff04ff59ff80808080808080ff81b78080ff8080ff0180ffff04ff17ffff04ff05ffff04ff8202ffffff04ffff04ffff04ff24ffff04ffff0bff7cff2fff82017f80ff808080ffff04ffff04ff30ffff04ffff0bff81bfffff0bff7cff15ffff10ff82017fffff11ff8202dfff2b80ff8202ff808080ff808080ff138080ff80808080808080808080ff018080'; + +const cat2_curried_program = 'ff02ffff01ff02ffff01ff02ffff03ff0bffff01ff02ffff03ffff09ff05ffff1dff0bffff1effff0bff0bffff02ff06ffff04ff02ffff04ff17ff8080808080808080ffff01ff02ff17ff2f80ffff01ff088080ff0180ffff01ff04ffff04ff04ffff04ff05ffff04ffff02ff06ffff04ff02ffff04ff17ff80808080ff80808080ffff02ff17ff2f808080ff0180ffff04ffff01ff32ff02ffff03ffff07ff0580ffff01ff0bffff0102ffff02ff06ffff04ff02ffff04ff09ff80808080ffff02ff06ffff04ff02ffff04ff0dff8080808080ffff01ff0bffff0101ff058080ff0180ff018080ffff04ffff01b0a7ca4bce10200d073ef10c46e9d27c3b4e31263d4c07fbec447650fcc1b286300e8ecf25c0560f9cb5aa673247fb6a6fff018080'; + +it('can uncurry an example program', async () => { + const to_uncurry_text = fs.readFileSync(resolve(__dirname, '../../../content/test_cat2_program.hex'),'utf-8'); + const program = Program.from_hex(to_uncurry_text); + const uncurried = program.uncurry_error(); + assert.equal(uncurried.length, 2); + assert.equal(uncurried[1].length, 3); + assert.equal(uncurried[0].toString(), cat2_puzzle); + assert.equal(uncurried[1][0].toString(), 'a072dec062874cd4d3aab892a0906688a1ae412b0109982e1797a170add88bdcdc'); + assert.equal(uncurried[1][1].toString(), 'a06d95dae356e32a71db5ddcb42224754a02524c615c5fc35f568c2af04774e589'); + assert.equal(uncurried[1][2].toString(), cat2_curried_program); }); diff --git a/wasm/tests/clvm-tools-interface/tsconfig.json b/wasm/tests/clvm-tools-interface/tsconfig.json index 9ea99e98e..655a5b6d6 100644 --- a/wasm/tests/clvm-tools-interface/tsconfig.json +++ b/wasm/tests/clvm-tools-interface/tsconfig.json @@ -12,6 +12,7 @@ "suppressImplicitAnyIndexErrors": true, "lib": ["es2018", "dom"], "moduleResolution": "node", + "target": "es2020" }, "include": ["src/lib"], "exclude": ["src/lib/**/tests"], diff --git a/wasm/tests/clvm-tools-interface/tstestconfig.json b/wasm/tests/clvm-tools-interface/tstestconfig.json new file mode 100644 index 000000000..b47c040da --- /dev/null +++ b/wasm/tests/clvm-tools-interface/tstestconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "emitDeclarationOnly": false, + "noEmitOnError": true, + "strict": true, + }, + "include": ["src/lib/**/tests"], + "exclude": [] +} diff --git a/wasm/tests/clvm-tools-interface/yarn.lock b/wasm/tests/clvm-tools-interface/yarn.lock index 162a52399..51008bc77 100644 --- a/wasm/tests/clvm-tools-interface/yarn.lock +++ b/wasm/tests/clvm-tools-interface/yarn.lock @@ -3,58 +3,58 @@ "@aashutoshrathi/word-wrap@^1.2.3": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" - integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + "integrity" "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==" + "resolved" "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz" + "version" "1.2.6" "@ampproject/remapping@^2.2.0": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" - integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== + "integrity" "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==" + "resolved" "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz" + "version" "2.2.1" dependencies: "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" "@babel/cli@^7.22.9": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.22.10.tgz#25e4bbd8d0a0d8b4b389e1b5e2d7a238bd4c1b75" - integrity sha512-rM9ZMmaII630zGvtMtQ3P4GyHs28CHLYE9apLG7L8TgaSqcfoIGrlLSLsh4Q8kDTdZQQEXZm1M0nQtOvU/2heg== + "integrity" "sha512-rM9ZMmaII630zGvtMtQ3P4GyHs28CHLYE9apLG7L8TgaSqcfoIGrlLSLsh4Q8kDTdZQQEXZm1M0nQtOvU/2heg==" + "resolved" "https://registry.npmjs.org/@babel/cli/-/cli-7.22.10.tgz" + "version" "7.22.10" dependencies: "@jridgewell/trace-mapping" "^0.3.17" - commander "^4.0.1" - convert-source-map "^1.1.0" - fs-readdir-recursive "^1.1.0" - glob "^7.2.0" - make-dir "^2.1.0" - slash "^2.0.0" + "commander" "^4.0.1" + "convert-source-map" "^1.1.0" + "fs-readdir-recursive" "^1.1.0" + "glob" "^7.2.0" + "make-dir" "^2.1.0" + "slash" "^2.0.0" optionalDependencies: "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents.3" - chokidar "^3.4.0" - -"@babel/code-frame@7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" - integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== - dependencies: - "@babel/highlight" "^7.10.4" + "chokidar" "^3.4.0" "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.10", "@babel/code-frame@^7.22.5": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.10.tgz#1c20e612b768fefa75f6e90d6ecb86329247f0a3" - integrity sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA== + "integrity" "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==" + "resolved" "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz" + "version" "7.22.10" dependencies: "@babel/highlight" "^7.22.10" - chalk "^2.4.2" + "chalk" "^2.4.2" + +"@babel/code-frame@7.12.11": + "integrity" "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==" + "resolved" "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz" + "version" "7.12.11" + dependencies: + "@babel/highlight" "^7.10.4" "@babel/compat-data@^7.22.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.22.9": - version "7.22.9" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.9.tgz#71cdb00a1ce3a329ce4cbec3a44f9fef35669730" - integrity sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ== + "integrity" "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==" + "resolved" "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz" + "version" "7.22.9" -"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.22.10": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.10.tgz#aad442c7bcd1582252cb4576747ace35bc122f35" - integrity sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw== +"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.0.0-0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.11.6", "@babel/core@^7.12.0", "@babel/core@^7.12.3", "@babel/core@^7.13.0", "@babel/core@^7.22.10", "@babel/core@^7.4.0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.8.0": + "integrity" "sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==" + "resolved" "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz" + "version" "7.22.10" dependencies: "@ampproject/remapping" "^2.2.0" "@babel/code-frame" "^7.22.10" @@ -66,51 +66,51 @@ "@babel/template" "^7.22.5" "@babel/traverse" "^7.22.10" "@babel/types" "^7.22.10" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.2" - semver "^6.3.1" + "convert-source-map" "^1.7.0" + "debug" "^4.1.0" + "gensync" "^1.0.0-beta.2" + "json5" "^2.2.2" + "semver" "^6.3.1" "@babel/generator@^7.22.10", "@babel/generator@^7.7.2": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.10.tgz#c92254361f398e160645ac58831069707382b722" - integrity sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A== + "integrity" "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==" + "resolved" "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz" + "version" "7.22.10" dependencies: "@babel/types" "^7.22.10" "@jridgewell/gen-mapping" "^0.3.2" "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" + "jsesc" "^2.5.1" "@babel/helper-annotate-as-pure@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" - integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== + "integrity" "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==" + "resolved" "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/types" "^7.22.5" "@babel/helper-builder-binary-assignment-operator-visitor@^7.22.5": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.10.tgz#573e735937e99ea75ea30788b57eb52fab7468c9" - integrity sha512-Av0qubwDQxC56DoUReVDeLfMEjYYSN1nZrTUrWkXd7hpU73ymRANkbuDm3yni9npkn+RXy9nNbEJZEzXr7xrfQ== + "integrity" "sha512-Av0qubwDQxC56DoUReVDeLfMEjYYSN1nZrTUrWkXd7hpU73ymRANkbuDm3yni9npkn+RXy9nNbEJZEzXr7xrfQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.10.tgz" + "version" "7.22.10" dependencies: "@babel/types" "^7.22.10" "@babel/helper-compilation-targets@^7.22.10", "@babel/helper-compilation-targets@^7.22.5", "@babel/helper-compilation-targets@^7.22.6": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz#01d648bbc25dd88f513d862ee0df27b7d4e67024" - integrity sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q== + "integrity" "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==" + "resolved" "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz" + "version" "7.22.10" dependencies: "@babel/compat-data" "^7.22.9" "@babel/helper-validator-option" "^7.22.5" - browserslist "^4.21.9" - lru-cache "^5.1.1" - semver "^6.3.1" + "browserslist" "^4.21.9" + "lru-cache" "^5.1.1" + "semver" "^6.3.1" "@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.22.10", "@babel/helper-create-class-features-plugin@^7.22.5": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.10.tgz#dd2612d59eac45588021ac3d6fa976d08f4e95a3" - integrity sha512-5IBb77txKYQPpOEdUdIhBx8VrZyDCQ+H82H0+5dX1TmuscP5vJKEE3cKurjtIw/vFwzbVH48VweE78kVDBrqjA== + "integrity" "sha512-5IBb77txKYQPpOEdUdIhBx8VrZyDCQ+H82H0+5dX1TmuscP5vJKEE3cKurjtIw/vFwzbVH48VweE78kVDBrqjA==" + "resolved" "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.10.tgz" + "version" "7.22.10" dependencies: "@babel/helper-annotate-as-pure" "^7.22.5" "@babel/helper-environment-visitor" "^7.22.5" @@ -120,66 +120,66 @@ "@babel/helper-replace-supers" "^7.22.9" "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" "@babel/helper-split-export-declaration" "^7.22.6" - semver "^6.3.1" + "semver" "^6.3.1" "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.5": - version "7.22.9" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.9.tgz#9d8e61a8d9366fe66198f57c40565663de0825f6" - integrity sha512-+svjVa/tFwsNSG4NEy1h85+HQ5imbT92Q5/bgtS7P0GTQlP8WuFdqsiABmQouhiFGyV66oGxZFpeYHza1rNsKw== + "integrity" "sha512-+svjVa/tFwsNSG4NEy1h85+HQ5imbT92Q5/bgtS7P0GTQlP8WuFdqsiABmQouhiFGyV66oGxZFpeYHza1rNsKw==" + "resolved" "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.9.tgz" + "version" "7.22.9" dependencies: "@babel/helper-annotate-as-pure" "^7.22.5" - regexpu-core "^5.3.1" - semver "^6.3.1" + "regexpu-core" "^5.3.1" + "semver" "^6.3.1" "@babel/helper-define-polyfill-provider@^0.4.2": - version "0.4.2" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz#82c825cadeeeee7aad237618ebbe8fa1710015d7" - integrity sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw== + "integrity" "sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw==" + "resolved" "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz" + "version" "0.4.2" dependencies: "@babel/helper-compilation-targets" "^7.22.6" "@babel/helper-plugin-utils" "^7.22.5" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" + "debug" "^4.1.1" + "lodash.debounce" "^4.0.8" + "resolve" "^1.14.2" "@babel/helper-environment-visitor@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98" - integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q== + "integrity" "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==" + "resolved" "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz" + "version" "7.22.5" "@babel/helper-function-name@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be" - integrity sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ== + "integrity" "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/template" "^7.22.5" "@babel/types" "^7.22.5" "@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== + "integrity" "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==" + "resolved" "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/types" "^7.22.5" "@babel/helper-member-expression-to-functions@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz#0a7c56117cad3372fbf8d2fb4bf8f8d64a1e76b2" - integrity sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ== + "integrity" "sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/types" "^7.22.5" "@babel/helper-module-imports@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz#1a8f4c9f4027d23f520bd76b364d44434a72660c" - integrity sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg== + "integrity" "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==" + "resolved" "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/types" "^7.22.5" "@babel/helper-module-transforms@^7.22.5", "@babel/helper-module-transforms@^7.22.9": - version "7.22.9" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz#92dfcb1fbbb2bc62529024f72d942a8c97142129" - integrity sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ== + "integrity" "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz" + "version" "7.22.9" dependencies: "@babel/helper-environment-visitor" "^7.22.5" "@babel/helper-module-imports" "^7.22.5" @@ -188,291 +188,291 @@ "@babel/helper-validator-identifier" "^7.22.5" "@babel/helper-optimise-call-expression@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" - integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw== + "integrity" "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==" + "resolved" "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/types" "^7.22.5" "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" - integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== + "integrity" "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==" + "resolved" "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz" + "version" "7.22.5" "@babel/helper-remap-async-to-generator@^7.22.5", "@babel/helper-remap-async-to-generator@^7.22.9": - version "7.22.9" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz#53a25b7484e722d7efb9c350c75c032d4628de82" - integrity sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ== + "integrity" "sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz" + "version" "7.22.9" dependencies: "@babel/helper-annotate-as-pure" "^7.22.5" "@babel/helper-environment-visitor" "^7.22.5" "@babel/helper-wrap-function" "^7.22.9" "@babel/helper-replace-supers@^7.22.5", "@babel/helper-replace-supers@^7.22.9": - version "7.22.9" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz#cbdc27d6d8d18cd22c81ae4293765a5d9afd0779" - integrity sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg== + "integrity" "sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==" + "resolved" "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz" + "version" "7.22.9" dependencies: "@babel/helper-environment-visitor" "^7.22.5" "@babel/helper-member-expression-to-functions" "^7.22.5" "@babel/helper-optimise-call-expression" "^7.22.5" "@babel/helper-simple-access@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" - integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== + "integrity" "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==" + "resolved" "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/types" "^7.22.5" "@babel/helper-skip-transparent-expression-wrappers@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" - integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== + "integrity" "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==" + "resolved" "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/types" "^7.22.5" "@babel/helper-split-export-declaration@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" - integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + "integrity" "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==" + "resolved" "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz" + "version" "7.22.6" dependencies: "@babel/types" "^7.22.5" "@babel/helper-string-parser@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" - integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== + "integrity" "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==" + "resolved" "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz" + "version" "7.22.5" "@babel/helper-validator-identifier@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" - integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== + "integrity" "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz" + "version" "7.22.5" "@babel/helper-validator-option@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz#de52000a15a177413c8234fa3a8af4ee8102d0ac" - integrity sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw== + "integrity" "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==" + "resolved" "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz" + "version" "7.22.5" "@babel/helper-wrap-function@^7.22.9": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz#d845e043880ed0b8c18bd194a12005cb16d2f614" - integrity sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ== + "integrity" "sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ==" + "resolved" "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz" + "version" "7.22.10" dependencies: "@babel/helper-function-name" "^7.22.5" "@babel/template" "^7.22.5" "@babel/types" "^7.22.10" "@babel/helpers@^7.22.10": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.10.tgz#ae6005c539dfbcb5cd71fb51bfc8a52ba63bc37a" - integrity sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw== + "integrity" "sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==" + "resolved" "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.10.tgz" + "version" "7.22.10" dependencies: "@babel/template" "^7.22.5" "@babel/traverse" "^7.22.10" "@babel/types" "^7.22.10" "@babel/highlight@^7.10.4", "@babel/highlight@^7.22.10": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.10.tgz#02a3f6d8c1cb4521b2fd0ab0da8f4739936137d7" - integrity sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ== + "integrity" "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==" + "resolved" "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz" + "version" "7.22.10" dependencies: "@babel/helper-validator-identifier" "^7.22.5" - chalk "^2.4.2" - js-tokens "^4.0.0" + "chalk" "^2.4.2" + "js-tokens" "^4.0.0" "@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.10", "@babel/parser@^7.22.5", "@babel/parser@^7.7.0": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.10.tgz#e37634f9a12a1716136c44624ef54283cabd3f55" - integrity sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ== + "integrity" "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==" + "resolved" "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz" + "version" "7.22.10" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz#87245a21cd69a73b0b81bcda98d443d6df08f05e" - integrity sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ== + "integrity" "sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.5.tgz#fef09f9499b1f1c930da8a0c419db42167d792ca" - integrity sha512-31Bb65aZaUwqCbWMnZPduIZxCBngHFlzyN6Dq6KAJjtx+lx6ohKHubc61OomYi7XwVD4Ol0XCVz4h+pYFR048g== + "integrity" "sha512-31Bb65aZaUwqCbWMnZPduIZxCBngHFlzyN6Dq6KAJjtx+lx6ohKHubc61OomYi7XwVD4Ol0XCVz4h+pYFR048g==" + "resolved" "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" "@babel/plugin-transform-optional-chaining" "^7.22.5" "@babel/plugin-proposal-class-properties@^7.16.0": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" - integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== + "integrity" "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz" + "version" "7.18.6" dependencies: "@babel/helper-create-class-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": - version "7.21.0-placeholder-for-preset-env.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" - integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== + "integrity" "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==" + "resolved" "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz" + "version" "7.21.0-placeholder-for-preset-env.2" "@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + "integrity" "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" + "version" "7.8.4" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-bigint@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" - integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + "integrity" "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + "integrity" "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" + "version" "7.12.13" dependencies: "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-class-static-block@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" - integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + "integrity" "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz" + "version" "7.14.5" dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" - integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + "integrity" "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-export-namespace-from@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" - integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + "integrity" "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-import-assertions@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz#07d252e2aa0bc6125567f742cd58619cb14dce98" - integrity sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg== + "integrity" "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-import-attributes@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz#ab840248d834410b829f569f5262b9e517555ecb" - integrity sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg== + "integrity" "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-import-meta@^7.10.4", "@babel/plugin-syntax-import-meta@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + "integrity" "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz" + "version" "7.10.4" dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + "integrity" "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-jsx@^7.7.2": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz#a6b68e84fb76e759fc3b93e901876ffabbe1d918" - integrity sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg== + "integrity" "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + "integrity" "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" + "version" "7.10.4" dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + "integrity" "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + "integrity" "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" + "version" "7.10.4" dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + "integrity" "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + "integrity" "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + "integrity" "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" + "version" "7.8.3" dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-private-property-in-object@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" - integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + "integrity" "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz" + "version" "7.14.5" dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-top-level-await@^7.14.5", "@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + "integrity" "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" + "version" "7.14.5" dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.22.5", "@babel/plugin-syntax-typescript@^7.7.2": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz#aac8d383b062c5072c647a31ef990c1d0af90272" - integrity sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ== + "integrity" "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-unicode-sets-regex@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" - integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== + "integrity" "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz" + "version" "7.18.6" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-arrow-functions@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz#e5ba566d0c58a5b2ba2a8b795450641950b71958" - integrity sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw== + "integrity" "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-async-generator-functions@^7.22.10": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.10.tgz#45946cd17f915b10e65c29b8ed18a0a50fc648c8" - integrity sha512-eueE8lvKVzq5wIObKK/7dvoeKJ+xc6TvRn6aysIjS6pSCeLy7S/eVi7pEQknZqyqvzaNKdDtem8nUNTBgDVR2g== + "integrity" "sha512-eueE8lvKVzq5wIObKK/7dvoeKJ+xc6TvRn6aysIjS6pSCeLy7S/eVi7pEQknZqyqvzaNKdDtem8nUNTBgDVR2g==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.10.tgz" + "version" "7.22.10" dependencies: "@babel/helper-environment-visitor" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" @@ -480,49 +480,49 @@ "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-transform-async-to-generator@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz#c7a85f44e46f8952f6d27fe57c2ed3cc084c3775" - integrity sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ== + "integrity" "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-module-imports" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-remap-async-to-generator" "^7.22.5" "@babel/plugin-transform-block-scoped-functions@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz#27978075bfaeb9fa586d3cb63a3d30c1de580024" - integrity sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA== + "integrity" "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-block-scoping@^7.22.10": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.10.tgz#88a1dccc3383899eb5e660534a76a22ecee64faa" - integrity sha512-1+kVpGAOOI1Albt6Vse7c8pHzcZQdQKW+wJH+g8mCaszOdDVwRXa/slHPqIw+oJAJANTKDMuM2cBdV0Dg618Vg== + "integrity" "sha512-1+kVpGAOOI1Albt6Vse7c8pHzcZQdQKW+wJH+g8mCaszOdDVwRXa/slHPqIw+oJAJANTKDMuM2cBdV0Dg618Vg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.10.tgz" + "version" "7.22.10" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-class-properties@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz#97a56e31ad8c9dc06a0b3710ce7803d5a48cca77" - integrity sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ== + "integrity" "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-create-class-features-plugin" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-class-static-block@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.5.tgz#3e40c46f048403472d6f4183116d5e46b1bff5ba" - integrity sha512-SPToJ5eYZLxlnp1UzdARpOGeC2GbHvr9d/UV0EukuVx8atktg194oe+C5BqQ8jRTkgLRVOPYeXRSBg1IlMoVRA== + "integrity" "sha512-SPToJ5eYZLxlnp1UzdARpOGeC2GbHvr9d/UV0EukuVx8atktg194oe+C5BqQ8jRTkgLRVOPYeXRSBg1IlMoVRA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-create-class-features-plugin" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-transform-classes@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.6.tgz#e04d7d804ed5b8501311293d1a0e6d43e94c3363" - integrity sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ== + "integrity" "sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.6.tgz" + "version" "7.22.6" dependencies: "@babel/helper-annotate-as-pure" "^7.22.5" "@babel/helper-compilation-targets" "^7.22.6" @@ -532,129 +532,129 @@ "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-replace-supers" "^7.22.5" "@babel/helper-split-export-declaration" "^7.22.6" - globals "^11.1.0" + "globals" "^11.1.0" "@babel/plugin-transform-computed-properties@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz#cd1e994bf9f316bd1c2dafcd02063ec261bb3869" - integrity sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg== + "integrity" "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/template" "^7.22.5" "@babel/plugin-transform-destructuring@^7.22.10": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.10.tgz#38e2273814a58c810b6c34ea293be4973c4eb5e2" - integrity sha512-dPJrL0VOyxqLM9sritNbMSGx/teueHF/htMKrPT7DNxccXxRDPYqlgPFFdr8u+F+qUZOkZoXue/6rL5O5GduEw== + "integrity" "sha512-dPJrL0VOyxqLM9sritNbMSGx/teueHF/htMKrPT7DNxccXxRDPYqlgPFFdr8u+F+qUZOkZoXue/6rL5O5GduEw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.10.tgz" + "version" "7.22.10" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-dotall-regex@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz#dbb4f0e45766eb544e193fb00e65a1dd3b2a4165" - integrity sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw== + "integrity" "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-duplicate-keys@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz#b6e6428d9416f5f0bba19c70d1e6e7e0b88ab285" - integrity sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw== + "integrity" "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-dynamic-import@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.5.tgz#d6908a8916a810468c4edff73b5b75bda6ad393e" - integrity sha512-0MC3ppTB1AMxd8fXjSrbPa7LT9hrImt+/fcj+Pg5YMD7UQyWp/02+JWpdnCymmsXwIx5Z+sYn1bwCn4ZJNvhqQ== + "integrity" "sha512-0MC3ppTB1AMxd8fXjSrbPa7LT9hrImt+/fcj+Pg5YMD7UQyWp/02+JWpdnCymmsXwIx5Z+sYn1bwCn4ZJNvhqQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-transform-exponentiation-operator@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz#402432ad544a1f9a480da865fda26be653e48f6a" - integrity sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g== + "integrity" "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-export-namespace-from@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.5.tgz#57c41cb1d0613d22f548fddd8b288eedb9973a5b" - integrity sha512-X4hhm7FRnPgd4nDA4b/5V280xCx6oL7Oob5+9qVS5C13Zq4bh1qq7LU0GgRU6b5dBWBvhGaXYVB4AcN6+ol6vg== + "integrity" "sha512-X4hhm7FRnPgd4nDA4b/5V280xCx6oL7Oob5+9qVS5C13Zq4bh1qq7LU0GgRU6b5dBWBvhGaXYVB4AcN6+ol6vg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" "@babel/plugin-transform-for-of@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.5.tgz#ab1b8a200a8f990137aff9a084f8de4099ab173f" - integrity sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A== + "integrity" "sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-function-name@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz#935189af68b01898e0d6d99658db6b164205c143" - integrity sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg== + "integrity" "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-compilation-targets" "^7.22.5" "@babel/helper-function-name" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-json-strings@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.5.tgz#14b64352fdf7e1f737eed68de1a1468bd2a77ec0" - integrity sha512-DuCRB7fu8MyTLbEQd1ew3R85nx/88yMoqo2uPSjevMj3yoN7CDM8jkgrY0wmVxfJZyJ/B9fE1iq7EQppWQmR5A== + "integrity" "sha512-DuCRB7fu8MyTLbEQd1ew3R85nx/88yMoqo2uPSjevMj3yoN7CDM8jkgrY0wmVxfJZyJ/B9fE1iq7EQppWQmR5A==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-transform-literals@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz#e9341f4b5a167952576e23db8d435849b1dd7920" - integrity sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g== + "integrity" "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-logical-assignment-operators@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.5.tgz#66ae5f068fd5a9a5dc570df16f56c2a8462a9d6c" - integrity sha512-MQQOUW1KL8X0cDWfbwYP+TbVbZm16QmQXJQ+vndPtH/BoO0lOKpVoEDMI7+PskYxH+IiE0tS8xZye0qr1lGzSA== + "integrity" "sha512-MQQOUW1KL8X0cDWfbwYP+TbVbZm16QmQXJQ+vndPtH/BoO0lOKpVoEDMI7+PskYxH+IiE0tS8xZye0qr1lGzSA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-transform-member-expression-literals@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz#4fcc9050eded981a468347dd374539ed3e058def" - integrity sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew== + "integrity" "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-modules-amd@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz#4e045f55dcf98afd00f85691a68fc0780704f526" - integrity sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ== + "integrity" "sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-module-transforms" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-modules-commonjs@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz#7d9875908d19b8c0536085af7b053fd5bd651bfa" - integrity sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA== + "integrity" "sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-module-transforms" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-simple-access" "^7.22.5" "@babel/plugin-transform-modules-systemjs@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.5.tgz#18c31410b5e579a0092638f95c896c2a98a5d496" - integrity sha512-emtEpoaTMsOs6Tzz+nbmcePl6AKVtS1yC4YNAeMun9U8YCsgadPNxnOPQ8GhHFB2qdx+LZu9LgoC0Lthuu05DQ== + "integrity" "sha512-emtEpoaTMsOs6Tzz+nbmcePl6AKVtS1yC4YNAeMun9U8YCsgadPNxnOPQ8GhHFB2qdx+LZu9LgoC0Lthuu05DQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-hoist-variables" "^7.22.5" "@babel/helper-module-transforms" "^7.22.5" @@ -662,48 +662,48 @@ "@babel/helper-validator-identifier" "^7.22.5" "@babel/plugin-transform-modules-umd@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz#4694ae40a87b1745e3775b6a7fe96400315d4f98" - integrity sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ== + "integrity" "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-module-transforms" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-named-capturing-groups-regex@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz#67fe18ee8ce02d57c855185e27e3dc959b2e991f" - integrity sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ== + "integrity" "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-new-target@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz#1b248acea54ce44ea06dfd37247ba089fcf9758d" - integrity sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw== + "integrity" "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-nullish-coalescing-operator@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.5.tgz#f8872c65776e0b552e0849d7596cddd416c3e381" - integrity sha512-6CF8g6z1dNYZ/VXok5uYkkBBICHZPiGEl7oDnAx2Mt1hlHVHOSIKWJaXHjQJA5VB43KZnXZDIexMchY4y2PGdA== + "integrity" "sha512-6CF8g6z1dNYZ/VXok5uYkkBBICHZPiGEl7oDnAx2Mt1hlHVHOSIKWJaXHjQJA5VB43KZnXZDIexMchY4y2PGdA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" "@babel/plugin-transform-numeric-separator@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.5.tgz#57226a2ed9e512b9b446517ab6fa2d17abb83f58" - integrity sha512-NbslED1/6M+sXiwwtcAB/nieypGw02Ejf4KtDeMkCEpP6gWFMX1wI9WKYua+4oBneCCEmulOkRpwywypVZzs/g== + "integrity" "sha512-NbslED1/6M+sXiwwtcAB/nieypGw02Ejf4KtDeMkCEpP6gWFMX1wI9WKYua+4oBneCCEmulOkRpwywypVZzs/g==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-transform-object-rest-spread@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.5.tgz#9686dc3447df4753b0b2a2fae7e8bc33cdc1f2e1" - integrity sha512-Kk3lyDmEslH9DnvCDA1s1kkd3YWQITiBOHngOtDL9Pt6BZjzqb6hiOlb8VfjiiQJ2unmegBqZu0rx5RxJb5vmQ== + "integrity" "sha512-Kk3lyDmEslH9DnvCDA1s1kkd3YWQITiBOHngOtDL9Pt6BZjzqb6hiOlb8VfjiiQJ2unmegBqZu0rx5RxJb5vmQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/compat-data" "^7.22.5" "@babel/helper-compilation-targets" "^7.22.5" @@ -712,49 +712,49 @@ "@babel/plugin-transform-parameters" "^7.22.5" "@babel/plugin-transform-object-super@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz#794a8d2fcb5d0835af722173c1a9d704f44e218c" - integrity sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw== + "integrity" "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-replace-supers" "^7.22.5" "@babel/plugin-transform-optional-catch-binding@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.5.tgz#842080be3076703be0eaf32ead6ac8174edee333" - integrity sha512-pH8orJahy+hzZje5b8e2QIlBWQvGpelS76C63Z+jhZKsmzfNaPQ+LaW6dcJ9bxTpo1mtXbgHwy765Ro3jftmUg== + "integrity" "sha512-pH8orJahy+hzZje5b8e2QIlBWQvGpelS76C63Z+jhZKsmzfNaPQ+LaW6dcJ9bxTpo1mtXbgHwy765Ro3jftmUg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-transform-optional-chaining@^7.22.10", "@babel/plugin-transform-optional-chaining@^7.22.5": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.10.tgz#076d28a7e074392e840d4ae587d83445bac0372a" - integrity sha512-MMkQqZAZ+MGj+jGTG3OTuhKeBpNcO+0oCEbrGNEaOmiEn+1MzRyQlYsruGiU8RTK3zV6XwrVJTmwiDOyYK6J9g== + "integrity" "sha512-MMkQqZAZ+MGj+jGTG3OTuhKeBpNcO+0oCEbrGNEaOmiEn+1MzRyQlYsruGiU8RTK3zV6XwrVJTmwiDOyYK6J9g==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.10.tgz" + "version" "7.22.10" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-transform-parameters@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.5.tgz#c3542dd3c39b42c8069936e48717a8d179d63a18" - integrity sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg== + "integrity" "sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-private-methods@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz#21c8af791f76674420a147ae62e9935d790f8722" - integrity sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA== + "integrity" "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-create-class-features-plugin" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-private-property-in-object@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.5.tgz#07a77f28cbb251546a43d175a1dda4cf3ef83e32" - integrity sha512-/9xnaTTJcVoBtSSmrVyhtSvO3kbqS2ODoh2juEU72c3aYonNF0OMGiaz2gjukyKM2wBBYJP38S4JiE0Wfb5VMQ== + "integrity" "sha512-/9xnaTTJcVoBtSSmrVyhtSvO3kbqS2ODoh2juEU72c3aYonNF0OMGiaz2gjukyKM2wBBYJP38S4JiE0Wfb5VMQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-annotate-as-pure" "^7.22.5" "@babel/helper-create-class-features-plugin" "^7.22.5" @@ -762,67 +762,67 @@ "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-transform-property-literals@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz#b5ddabd73a4f7f26cd0e20f5db48290b88732766" - integrity sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ== + "integrity" "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-regenerator@^7.22.10": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz#8ceef3bd7375c4db7652878b0241b2be5d0c3cca" - integrity sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw== + "integrity" "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz" + "version" "7.22.10" dependencies: "@babel/helper-plugin-utils" "^7.22.5" - regenerator-transform "^0.15.2" + "regenerator-transform" "^0.15.2" "@babel/plugin-transform-reserved-words@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz#832cd35b81c287c4bcd09ce03e22199641f964fb" - integrity sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA== + "integrity" "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-shorthand-properties@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz#6e277654be82b5559fc4b9f58088507c24f0c624" - integrity sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA== + "integrity" "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-spread@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz#6487fd29f229c95e284ba6c98d65eafb893fea6b" - integrity sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg== + "integrity" "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" "@babel/plugin-transform-sticky-regex@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz#295aba1595bfc8197abd02eae5fc288c0deb26aa" - integrity sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw== + "integrity" "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-template-literals@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz#8f38cf291e5f7a8e60e9f733193f0bcc10909bff" - integrity sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA== + "integrity" "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-typeof-symbol@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz#5e2ba478da4b603af8673ff7c54f75a97b716b34" - integrity sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA== + "integrity" "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-typescript@^7.22.10": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.10.tgz#aadd98fab871f0bb5717bcc24c31aaaa455af923" - integrity sha512-7++c8I/ymsDo4QQBAgbraXLzIM6jmfao11KgIBEYZRReWzNWH9NtNgJcyrZiXsOPh523FQm6LfpLyy/U5fn46A== + "integrity" "sha512-7++c8I/ymsDo4QQBAgbraXLzIM6jmfao11KgIBEYZRReWzNWH9NtNgJcyrZiXsOPh523FQm6LfpLyy/U5fn46A==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.10.tgz" + "version" "7.22.10" dependencies: "@babel/helper-annotate-as-pure" "^7.22.5" "@babel/helper-create-class-features-plugin" "^7.22.10" @@ -830,48 +830,48 @@ "@babel/plugin-syntax-typescript" "^7.22.5" "@babel/plugin-transform-unicode-escapes@^7.22.10": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz#c723f380f40a2b2f57a62df24c9005834c8616d9" - integrity sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg== + "integrity" "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz" + "version" "7.22.10" dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-unicode-property-regex@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz#098898f74d5c1e86660dc112057b2d11227f1c81" - integrity sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A== + "integrity" "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-unicode-regex@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz#ce7e7bb3ef208c4ff67e02a22816656256d7a183" - integrity sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg== + "integrity" "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-transform-unicode-sets-regex@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz#77788060e511b708ffc7d42fdfbc5b37c3004e91" - integrity sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg== + "integrity" "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==" + "resolved" "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/helper-create-regexp-features-plugin" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" "@babel/polyfill@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.12.1.tgz#1f2d6371d1261bbd961f3c5d5909150e12d0bd96" - integrity sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g== + "integrity" "sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==" + "resolved" "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.12.1.tgz" + "version" "7.12.1" dependencies: - core-js "^2.6.5" - regenerator-runtime "^0.13.4" + "core-js" "^2.6.5" + "regenerator-runtime" "^0.13.4" "@babel/preset-env@^7.22.10": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.22.10.tgz#3263b9fe2c8823d191d28e61eac60a79f9ce8a0f" - integrity sha512-riHpLb1drNkpLlocmSyEg4oYJIQFeXAK/d7rI6mbD0XsvoTOOweXDmQPG/ErxsEhWk3rl3Q/3F6RFQlVFS8m0A== + "integrity" "sha512-riHpLb1drNkpLlocmSyEg4oYJIQFeXAK/d7rI6mbD0XsvoTOOweXDmQPG/ErxsEhWk3rl3Q/3F6RFQlVFS8m0A==" + "resolved" "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.10.tgz" + "version" "7.22.10" dependencies: "@babel/compat-data" "^7.22.9" "@babel/helper-compilation-targets" "^7.22.10" @@ -948,46 +948,46 @@ "@babel/plugin-transform-unicode-sets-regex" "^7.22.5" "@babel/preset-modules" "0.1.6-no-external-plugins" "@babel/types" "^7.22.10" - babel-plugin-polyfill-corejs2 "^0.4.5" - babel-plugin-polyfill-corejs3 "^0.8.3" - babel-plugin-polyfill-regenerator "^0.5.2" - core-js-compat "^3.31.0" - semver "^6.3.1" + "babel-plugin-polyfill-corejs2" "^0.4.5" + "babel-plugin-polyfill-corejs3" "^0.8.3" + "babel-plugin-polyfill-regenerator" "^0.5.2" + "core-js-compat" "^3.31.0" + "semver" "^6.3.1" "@babel/preset-modules@0.1.6-no-external-plugins": - version "0.1.6-no-external-plugins" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" - integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== + "integrity" "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==" + "resolved" "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz" + "version" "0.1.6-no-external-plugins" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/types" "^7.4.4" - esutils "^2.0.2" + "esutils" "^2.0.2" "@babel/regjsgen@^0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" - integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== + "integrity" "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" + "resolved" "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz" + "version" "0.8.0" "@babel/runtime@^7.8.4": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.10.tgz#ae3e9631fd947cb7e3610d3e9d8fef5f76696682" - integrity sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ== + "integrity" "sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==" + "resolved" "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.10.tgz" + "version" "7.22.10" dependencies: - regenerator-runtime "^0.14.0" + "regenerator-runtime" "^0.14.0" "@babel/template@^7.22.5", "@babel/template@^7.3.3": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" - integrity sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw== + "integrity" "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==" + "resolved" "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz" + "version" "7.22.5" dependencies: "@babel/code-frame" "^7.22.5" "@babel/parser" "^7.22.5" "@babel/types" "^7.22.5" "@babel/traverse@^7.22.10", "@babel/traverse@^7.7.0": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.10.tgz#20252acb240e746d27c2e82b4484f199cf8141aa" - integrity sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig== + "integrity" "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==" + "resolved" "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz" + "version" "7.22.10" dependencies: "@babel/code-frame" "^7.22.10" "@babel/generator" "^7.22.10" @@ -997,89 +997,89 @@ "@babel/helper-split-export-declaration" "^7.22.6" "@babel/parser" "^7.22.10" "@babel/types" "^7.22.10" - debug "^4.1.0" - globals "^11.1.0" + "debug" "^4.1.0" + "globals" "^11.1.0" "@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.10", "@babel/types@^7.22.5", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": - version "7.22.10" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.10.tgz#4a9e76446048f2c66982d1a989dd12b8a2d2dc03" - integrity sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg== + "integrity" "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==" + "resolved" "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz" + "version" "7.22.10" dependencies: "@babel/helper-string-parser" "^7.22.5" "@babel/helper-validator-identifier" "^7.22.5" - to-fast-properties "^2.0.0" + "to-fast-properties" "^2.0.0" "@bcoe/v8-coverage@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" - integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + "integrity" "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" + "resolved" "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz" + "version" "0.2.3" "@discoveryjs/json-ext@^0.5.0": - version "0.5.7" - resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" - integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== + "integrity" "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==" + "resolved" "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz" + "version" "0.5.7" "@eslint/eslintrc@^0.4.3": - version "0.4.3" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" - integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== - 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" + "integrity" "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==" + "resolved" "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz" + "version" "0.4.3" + 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" "@humanwhocodes/config-array@^0.5.0": - version "0.5.0" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" - integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== + "integrity" "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==" + "resolved" "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz" + "version" "0.5.0" dependencies: "@humanwhocodes/object-schema" "^1.2.0" - debug "^4.1.1" - minimatch "^3.0.4" + "debug" "^4.1.1" + "minimatch" "^3.0.4" "@humanwhocodes/object-schema@^1.2.0": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + "integrity" "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + "resolved" "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz" + "version" "1.2.1" "@istanbuljs/load-nyc-config@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" - integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + "integrity" "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==" + "resolved" "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz" + "version" "1.1.0" dependencies: - camelcase "^5.3.1" - find-up "^4.1.0" - get-package-type "^0.1.0" - js-yaml "^3.13.1" - resolve-from "^5.0.0" + "camelcase" "^5.3.1" + "find-up" "^4.1.0" + "get-package-type" "^0.1.0" + "js-yaml" "^3.13.1" + "resolve-from" "^5.0.0" "@istanbuljs/schema@^0.1.2": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" - integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + "integrity" "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==" + "resolved" "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz" + "version" "0.1.3" "@jest/console@^29.6.2": - version "29.6.2" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.6.2.tgz#bf1d4101347c23e07c029a1b1ae07d550f5cc541" - integrity sha512-0N0yZof5hi44HAR2pPS+ikJ3nzKNoZdVu8FffRf3wy47I7Dm7etk/3KetMdRUqzVd16V4O2m2ISpNTbnIuqy1w== + "integrity" "sha512-0N0yZof5hi44HAR2pPS+ikJ3nzKNoZdVu8FffRf3wy47I7Dm7etk/3KetMdRUqzVd16V4O2m2ISpNTbnIuqy1w==" + "resolved" "https://registry.npmjs.org/@jest/console/-/console-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/types" "^29.6.1" "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^29.6.2" - jest-util "^29.6.2" - slash "^3.0.0" + "chalk" "^4.0.0" + "jest-message-util" "^29.6.2" + "jest-util" "^29.6.2" + "slash" "^3.0.0" "@jest/core@^29.6.2": - version "29.6.2" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.6.2.tgz#6f2d1dbe8aa0265fcd4fb8082ae1952f148209c8" - integrity sha512-Oj+5B+sDMiMWLhPFF+4/DvHOf+U10rgvCLGPHP8Xlsy/7QxS51aU/eBngudHlJXnaWD5EohAgJ4js+T6pa+zOg== + "integrity" "sha512-Oj+5B+sDMiMWLhPFF+4/DvHOf+U10rgvCLGPHP8Xlsy/7QxS51aU/eBngudHlJXnaWD5EohAgJ4js+T6pa+zOg==" + "resolved" "https://registry.npmjs.org/@jest/core/-/core-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/console" "^29.6.2" "@jest/reporters" "^29.6.2" @@ -1087,80 +1087,80 @@ "@jest/transform" "^29.6.2" "@jest/types" "^29.6.1" "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - ci-info "^3.2.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^29.5.0" - jest-config "^29.6.2" - jest-haste-map "^29.6.2" - jest-message-util "^29.6.2" - jest-regex-util "^29.4.3" - jest-resolve "^29.6.2" - jest-resolve-dependencies "^29.6.2" - jest-runner "^29.6.2" - jest-runtime "^29.6.2" - jest-snapshot "^29.6.2" - jest-util "^29.6.2" - jest-validate "^29.6.2" - jest-watcher "^29.6.2" - micromatch "^4.0.4" - pretty-format "^29.6.2" - slash "^3.0.0" - strip-ansi "^6.0.0" + "ansi-escapes" "^4.2.1" + "chalk" "^4.0.0" + "ci-info" "^3.2.0" + "exit" "^0.1.2" + "graceful-fs" "^4.2.9" + "jest-changed-files" "^29.5.0" + "jest-config" "^29.6.2" + "jest-haste-map" "^29.6.2" + "jest-message-util" "^29.6.2" + "jest-regex-util" "^29.4.3" + "jest-resolve" "^29.6.2" + "jest-resolve-dependencies" "^29.6.2" + "jest-runner" "^29.6.2" + "jest-runtime" "^29.6.2" + "jest-snapshot" "^29.6.2" + "jest-util" "^29.6.2" + "jest-validate" "^29.6.2" + "jest-watcher" "^29.6.2" + "micromatch" "^4.0.4" + "pretty-format" "^29.6.2" + "slash" "^3.0.0" + "strip-ansi" "^6.0.0" "@jest/environment@^29.6.2": - version "29.6.2" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.6.2.tgz#794c0f769d85e7553439d107d3f43186dc6874a9" - integrity sha512-AEcW43C7huGd/vogTddNNTDRpO6vQ2zaQNrttvWV18ArBx9Z56h7BIsXkNFJVOO4/kblWEQz30ckw0+L3izc+Q== + "integrity" "sha512-AEcW43C7huGd/vogTddNNTDRpO6vQ2zaQNrttvWV18ArBx9Z56h7BIsXkNFJVOO4/kblWEQz30ckw0+L3izc+Q==" + "resolved" "https://registry.npmjs.org/@jest/environment/-/environment-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/fake-timers" "^29.6.2" "@jest/types" "^29.6.1" "@types/node" "*" - jest-mock "^29.6.2" + "jest-mock" "^29.6.2" "@jest/expect-utils@^29.6.2": - version "29.6.2" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.6.2.tgz#1b97f290d0185d264dd9fdec7567a14a38a90534" - integrity sha512-6zIhM8go3RV2IG4aIZaZbxwpOzz3ZiM23oxAlkquOIole+G6TrbeXnykxWYlqF7kz2HlBjdKtca20x9atkEQYg== + "integrity" "sha512-6zIhM8go3RV2IG4aIZaZbxwpOzz3ZiM23oxAlkquOIole+G6TrbeXnykxWYlqF7kz2HlBjdKtca20x9atkEQYg==" + "resolved" "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.2.tgz" + "version" "29.6.2" dependencies: - jest-get-type "^29.4.3" + "jest-get-type" "^29.4.3" "@jest/expect@^29.6.2": - version "29.6.2" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.6.2.tgz#5a2ad58bb345165d9ce0a1845bbf873c480a4b28" - integrity sha512-m6DrEJxVKjkELTVAztTLyS/7C92Y2b0VYqmDROYKLLALHn8T/04yPs70NADUYPrV3ruI+H3J0iUIuhkjp7vkfg== + "integrity" "sha512-m6DrEJxVKjkELTVAztTLyS/7C92Y2b0VYqmDROYKLLALHn8T/04yPs70NADUYPrV3ruI+H3J0iUIuhkjp7vkfg==" + "resolved" "https://registry.npmjs.org/@jest/expect/-/expect-29.6.2.tgz" + "version" "29.6.2" dependencies: - expect "^29.6.2" - jest-snapshot "^29.6.2" + "expect" "^29.6.2" + "jest-snapshot" "^29.6.2" "@jest/fake-timers@^29.6.2": - version "29.6.2" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.6.2.tgz#fe9d43c5e4b1b901168fe6f46f861b3e652a2df4" - integrity sha512-euZDmIlWjm1Z0lJ1D0f7a0/y5Kh/koLFMUBE5SUYWrmy8oNhJpbTBDAP6CxKnadcMLDoDf4waRYCe35cH6G6PA== + "integrity" "sha512-euZDmIlWjm1Z0lJ1D0f7a0/y5Kh/koLFMUBE5SUYWrmy8oNhJpbTBDAP6CxKnadcMLDoDf4waRYCe35cH6G6PA==" + "resolved" "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/types" "^29.6.1" "@sinonjs/fake-timers" "^10.0.2" "@types/node" "*" - jest-message-util "^29.6.2" - jest-mock "^29.6.2" - jest-util "^29.6.2" + "jest-message-util" "^29.6.2" + "jest-mock" "^29.6.2" + "jest-util" "^29.6.2" "@jest/globals@^29.6.2": - version "29.6.2" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.6.2.tgz#74af81b9249122cc46f1eb25793617eec69bf21a" - integrity sha512-cjuJmNDjs6aMijCmSa1g2TNG4Lby/AeU7/02VtpW+SLcZXzOLK2GpN2nLqcFjmhy3B3AoPeQVx7BnyOf681bAw== + "integrity" "sha512-cjuJmNDjs6aMijCmSa1g2TNG4Lby/AeU7/02VtpW+SLcZXzOLK2GpN2nLqcFjmhy3B3AoPeQVx7BnyOf681bAw==" + "resolved" "https://registry.npmjs.org/@jest/globals/-/globals-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/environment" "^29.6.2" "@jest/expect" "^29.6.2" "@jest/types" "^29.6.1" - jest-mock "^29.6.2" + "jest-mock" "^29.6.2" "@jest/reporters@^29.6.2": - version "29.6.2" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.6.2.tgz#524afe1d76da33d31309c2c4a2c8062d0c48780a" - integrity sha512-sWtijrvIav8LgfJZlrGCdN0nP2EWbakglJY49J1Y5QihcQLfy7ovyxxjJBRXMNltgt4uPtEcFmIMbVshEDfFWw== + "integrity" "sha512-sWtijrvIav8LgfJZlrGCdN0nP2EWbakglJY49J1Y5QihcQLfy7ovyxxjJBRXMNltgt4uPtEcFmIMbVshEDfFWw==" + "resolved" "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.2.tgz" + "version" "29.6.2" dependencies: "@bcoe/v8-coverage" "^0.2.3" "@jest/console" "^29.6.2" @@ -1169,192 +1169,192 @@ "@jest/types" "^29.6.1" "@jridgewell/trace-mapping" "^0.3.18" "@types/node" "*" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^5.1.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.1.3" - jest-message-util "^29.6.2" - jest-util "^29.6.2" - jest-worker "^29.6.2" - slash "^3.0.0" - string-length "^4.0.1" - strip-ansi "^6.0.0" - v8-to-istanbul "^9.0.1" + "chalk" "^4.0.0" + "collect-v8-coverage" "^1.0.0" + "exit" "^0.1.2" + "glob" "^7.1.3" + "graceful-fs" "^4.2.9" + "istanbul-lib-coverage" "^3.0.0" + "istanbul-lib-instrument" "^5.1.0" + "istanbul-lib-report" "^3.0.0" + "istanbul-lib-source-maps" "^4.0.0" + "istanbul-reports" "^3.1.3" + "jest-message-util" "^29.6.2" + "jest-util" "^29.6.2" + "jest-worker" "^29.6.2" + "slash" "^3.0.0" + "string-length" "^4.0.1" + "strip-ansi" "^6.0.0" + "v8-to-istanbul" "^9.0.1" "@jest/schemas@^29.6.0": - version "29.6.0" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.0.tgz#0f4cb2c8e3dca80c135507ba5635a4fd755b0040" - integrity sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ== + "integrity" "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==" + "resolved" "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz" + "version" "29.6.0" dependencies: "@sinclair/typebox" "^0.27.8" "@jest/source-map@^29.6.0": - version "29.6.0" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.0.tgz#bd34a05b5737cb1a99d43e1957020ac8e5b9ddb1" - integrity sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA== + "integrity" "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==" + "resolved" "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz" + "version" "29.6.0" dependencies: "@jridgewell/trace-mapping" "^0.3.18" - callsites "^3.0.0" - graceful-fs "^4.2.9" + "callsites" "^3.0.0" + "graceful-fs" "^4.2.9" "@jest/test-result@^29.6.2": - version "29.6.2" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.6.2.tgz#fdd11583cd1608e4db3114e8f0cce277bf7a32ed" - integrity sha512-3VKFXzcV42EYhMCsJQURptSqnyjqCGbtLuX5Xxb6Pm6gUf1wIRIl+mandIRGJyWKgNKYF9cnstti6Ls5ekduqw== + "integrity" "sha512-3VKFXzcV42EYhMCsJQURptSqnyjqCGbtLuX5Xxb6Pm6gUf1wIRIl+mandIRGJyWKgNKYF9cnstti6Ls5ekduqw==" + "resolved" "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/console" "^29.6.2" "@jest/types" "^29.6.1" "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" + "collect-v8-coverage" "^1.0.0" "@jest/test-sequencer@^29.6.2": - version "29.6.2" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.6.2.tgz#585eff07a68dd75225a7eacf319780cb9f6b9bf4" - integrity sha512-GVYi6PfPwVejO7slw6IDO0qKVum5jtrJ3KoLGbgBWyr2qr4GaxFV6su+ZAjdTX75Sr1DkMFRk09r2ZVa+wtCGw== + "integrity" "sha512-GVYi6PfPwVejO7slw6IDO0qKVum5jtrJ3KoLGbgBWyr2qr4GaxFV6su+ZAjdTX75Sr1DkMFRk09r2ZVa+wtCGw==" + "resolved" "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/test-result" "^29.6.2" - graceful-fs "^4.2.9" - jest-haste-map "^29.6.2" - slash "^3.0.0" + "graceful-fs" "^4.2.9" + "jest-haste-map" "^29.6.2" + "slash" "^3.0.0" "@jest/transform@^29.6.2": - version "29.6.2" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.6.2.tgz#522901ebbb211af08835bc3bcdf765ab778094e3" - integrity sha512-ZqCqEISr58Ce3U+buNFJYUktLJZOggfyvR+bZMaiV1e8B1SIvJbwZMrYz3gx/KAPn9EXmOmN+uB08yLCjWkQQg== + "integrity" "sha512-ZqCqEISr58Ce3U+buNFJYUktLJZOggfyvR+bZMaiV1e8B1SIvJbwZMrYz3gx/KAPn9EXmOmN+uB08yLCjWkQQg==" + "resolved" "https://registry.npmjs.org/@jest/transform/-/transform-29.6.2.tgz" + "version" "29.6.2" dependencies: "@babel/core" "^7.11.6" "@jest/types" "^29.6.1" "@jridgewell/trace-mapping" "^0.3.18" - babel-plugin-istanbul "^6.1.1" - chalk "^4.0.0" - convert-source-map "^2.0.0" - fast-json-stable-stringify "^2.1.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.6.2" - jest-regex-util "^29.4.3" - jest-util "^29.6.2" - micromatch "^4.0.4" - pirates "^4.0.4" - slash "^3.0.0" - write-file-atomic "^4.0.2" + "babel-plugin-istanbul" "^6.1.1" + "chalk" "^4.0.0" + "convert-source-map" "^2.0.0" + "fast-json-stable-stringify" "^2.1.0" + "graceful-fs" "^4.2.9" + "jest-haste-map" "^29.6.2" + "jest-regex-util" "^29.4.3" + "jest-util" "^29.6.2" + "micromatch" "^4.0.4" + "pirates" "^4.0.4" + "slash" "^3.0.0" + "write-file-atomic" "^4.0.2" "@jest/types@^29.6.1": - version "29.6.1" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.1.tgz#ae79080278acff0a6af5eb49d063385aaa897bf2" - integrity sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw== + "integrity" "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==" + "resolved" "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz" + "version" "29.6.1" dependencies: "@jest/schemas" "^29.6.0" "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^3.0.0" "@types/node" "*" "@types/yargs" "^17.0.8" - chalk "^4.0.0" + "chalk" "^4.0.0" "@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" - integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + "integrity" "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==" + "resolved" "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz" + "version" "0.3.3" dependencies: "@jridgewell/set-array" "^1.0.1" "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" "@jridgewell/resolve-uri@^3.1.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" - integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== + "integrity" "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==" + "resolved" "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz" + "version" "3.1.1" "@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + "integrity" "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + "resolved" "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" + "version" "1.1.2" "@jridgewell/source-map@^0.3.3": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.5.tgz#a3bb4d5c6825aab0d281268f47f6ad5853431e91" - integrity sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ== + "integrity" "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==" + "resolved" "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz" + "version" "0.3.5" dependencies: "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + "integrity" "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + "resolved" "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" + "version" "1.4.15" "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.19" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz#f8a3249862f91be48d3127c3cfe992f79b4b8811" - integrity sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw== + "integrity" "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==" + "resolved" "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz" + "version" "0.3.19" dependencies: "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" "@leichtgewicht/ip-codec@^2.0.1": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" - integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== + "integrity" "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" + "resolved" "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz" + "version" "2.0.4" "@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3": - version "2.1.8-no-fsevents.3" - resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz#323d72dd25103d0c4fbdce89dadf574a787b1f9b" - integrity sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ== + "integrity" "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==" + "resolved" "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz" + "version" "2.1.8-no-fsevents.3" "@nodelib/fs.scandir@2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" - integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + "integrity" "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==" + "resolved" "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + "version" "2.1.5" dependencies: "@nodelib/fs.stat" "2.0.5" - run-parallel "^1.1.9" + "run-parallel" "^1.1.9" -"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" - integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== +"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": + "integrity" "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + "resolved" "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + "version" "2.0.5" "@nodelib/fs.walk@^1.2.3": - version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" - integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + "integrity" "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==" + "resolved" "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + "version" "1.2.8" dependencies: "@nodelib/fs.scandir" "2.1.5" - fastq "^1.6.0" + "fastq" "^1.6.0" "@sinclair/typebox@^0.27.8": - version "0.27.8" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" - integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + "integrity" "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + "resolved" "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz" + "version" "0.27.8" "@sinonjs/commons@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72" - integrity sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA== + "integrity" "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==" + "resolved" "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz" + "version" "3.0.0" dependencies: - type-detect "4.0.8" + "type-detect" "4.0.8" "@sinonjs/fake-timers@^10.0.2": - version "10.3.0" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" - integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== + "integrity" "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==" + "resolved" "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz" + "version" "10.3.0" dependencies: "@sinonjs/commons" "^3.0.0" "@trysound/sax@0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" - integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== + "integrity" "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==" + "resolved" "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz" + "version" "0.2.0" "@types/babel__core@^7.1.14": - version "7.20.1" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.1.tgz#916ecea274b0c776fec721e333e55762d3a9614b" - integrity sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw== + "integrity" "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==" + "resolved" "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz" + "version" "7.20.1" dependencies: "@babel/parser" "^7.20.7" "@babel/types" "^7.20.7" @@ -1363,82 +1363,82 @@ "@types/babel__traverse" "*" "@types/babel__generator@*": - version "7.6.4" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" - integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== + "integrity" "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==" + "resolved" "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz" + "version" "7.6.4" dependencies: "@babel/types" "^7.0.0" "@types/babel__template@*": - version "7.4.1" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" - integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== + "integrity" "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==" + "resolved" "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz" + "version" "7.4.1" dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.20.1" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.1.tgz#dd6f1d2411ae677dcb2db008c962598be31d6acf" - integrity sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg== + "integrity" "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==" + "resolved" "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz" + "version" "7.20.1" dependencies: "@babel/types" "^7.20.7" "@types/body-parser@*": - version "1.19.2" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" - integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + "integrity" "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==" + "resolved" "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz" + "version" "1.19.2" dependencies: "@types/connect" "*" "@types/node" "*" "@types/bonjour@^3.5.9": - version "3.5.10" - resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" - integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== + "integrity" "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==" + "resolved" "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz" + "version" "3.5.10" dependencies: "@types/node" "*" "@types/connect-history-api-fallback@^1.3.5": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz#9fd20b3974bdc2bcd4ac6567e2e0f6885cb2cf41" - integrity sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig== + "integrity" "sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig==" + "resolved" "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz" + "version" "1.5.0" dependencies: "@types/express-serve-static-core" "*" "@types/node" "*" "@types/connect@*": - version "3.4.35" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" - integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + "integrity" "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==" + "resolved" "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz" + "version" "3.4.35" dependencies: "@types/node" "*" "@types/eslint-scope@^3.7.3": - version "3.7.4" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" - integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== + "integrity" "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==" + "resolved" "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz" + "version" "3.7.4" dependencies: "@types/eslint" "*" "@types/estree" "*" "@types/eslint@*": - version "8.44.2" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.44.2.tgz#0d21c505f98a89b8dd4d37fa162b09da6089199a" - integrity sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg== + "integrity" "sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg==" + "resolved" "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.2.tgz" + "version" "8.44.2" dependencies: "@types/estree" "*" "@types/json-schema" "*" "@types/estree@*", "@types/estree@^1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194" - integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA== + "integrity" "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" + "resolved" "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz" + "version" "1.0.1" "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33": - version "4.17.35" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz#c95dd4424f0d32e525d23812aa8ab8e4d3906c4f" - integrity sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg== + "integrity" "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==" + "resolved" "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz" + "version" "4.17.35" dependencies: "@types/node" "*" "@types/qs" "*" @@ -1446,9 +1446,9 @@ "@types/send" "*" "@types/express@*", "@types/express@^4.17.13": - version "4.17.17" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.17.tgz#01d5437f6ef9cfa8668e616e13c2f2ac9a491ae4" - integrity sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q== + "integrity" "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==" + "resolved" "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz" + "version" "4.17.17" dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "^4.17.33" @@ -1456,257 +1456,252 @@ "@types/serve-static" "*" "@types/graceful-fs@^4.1.3": - version "4.1.6" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.6.tgz#e14b2576a1c25026b7f02ede1de3b84c3a1efeae" - integrity sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw== + "integrity" "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==" + "resolved" "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz" + "version" "4.1.6" dependencies: "@types/node" "*" "@types/html-minifier-terser@^6.0.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" - integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== + "integrity" "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + "resolved" "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz" + "version" "6.1.0" "@types/http-errors@*": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.1.tgz#20172f9578b225f6c7da63446f56d4ce108d5a65" - integrity sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ== + "integrity" "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" + "resolved" "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz" + "version" "2.0.1" "@types/http-proxy@^1.17.8": - version "1.17.11" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.11.tgz#0ca21949a5588d55ac2b659b69035c84bd5da293" - integrity sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA== + "integrity" "sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==" + "resolved" "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.11.tgz" + "version" "1.17.11" dependencies: "@types/node" "*" "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" - integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + "integrity" "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" + "resolved" "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz" + "version" "2.0.4" "@types/istanbul-lib-report@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" - integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + "integrity" "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==" + "resolved" "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz" + "version" "3.0.0" dependencies: "@types/istanbul-lib-coverage" "*" "@types/istanbul-reports@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" - integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + "integrity" "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==" + "resolved" "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz" + "version" "3.0.1" dependencies: "@types/istanbul-lib-report" "*" "@types/jest@^29.5.3": - version "29.5.3" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.3.tgz#7a35dc0044ffb8b56325c6802a4781a626b05777" - integrity sha512-1Nq7YrO/vJE/FYnqYyw0FS8LdrjExSgIiHyKg7xPpn+yi8Q4huZryKnkJatN1ZRH89Kw2v33/8ZMB7DuZeSLlA== + "integrity" "sha512-1Nq7YrO/vJE/FYnqYyw0FS8LdrjExSgIiHyKg7xPpn+yi8Q4huZryKnkJatN1ZRH89Kw2v33/8ZMB7DuZeSLlA==" + "resolved" "https://registry.npmjs.org/@types/jest/-/jest-29.5.3.tgz" + "version" "29.5.3" dependencies: - expect "^29.0.0" - pretty-format "^29.0.0" + "expect" "^29.0.0" + "pretty-format" "^29.0.0" "@types/json-schema@*", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": - version "7.0.12" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb" - integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== + "integrity" "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==" + "resolved" "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz" + "version" "7.0.12" -"@types/mime@*": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" - integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== - -"@types/mime@^1": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" - integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== +"@types/mime@*", "@types/mime@^1": + "integrity" "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + "resolved" "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz" + "version" "1.3.2" "@types/node@*": - version "20.4.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.9.tgz#c7164e0f8d3f12dfae336af0b1f7fdec8c6b204f" - integrity sha512-8e2HYcg7ohnTUbHk8focoklEQYvemQmu9M/f43DZVx43kHn0tE3BY/6gSDxS7k0SprtS0NHvj+L80cGLnoOUcQ== + "integrity" "sha512-8e2HYcg7ohnTUbHk8focoklEQYvemQmu9M/f43DZVx43kHn0tE3BY/6gSDxS7k0SprtS0NHvj+L80cGLnoOUcQ==" + "resolved" "https://registry.npmjs.org/@types/node/-/node-20.4.9.tgz" + "version" "20.4.9" "@types/qs@*": - version "6.9.7" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" - integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + "integrity" "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + "resolved" "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz" + "version" "6.9.7" "@types/range-parser@*": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" - integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + "integrity" "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + "resolved" "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz" + "version" "1.2.4" "@types/retry@0.12.0": - version "0.12.0" - resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" - integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== + "integrity" "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" + "resolved" "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz" + "version" "0.12.0" "@types/send@*": - version "0.17.1" - resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.1.tgz#ed4932b8a2a805f1fe362a70f4e62d0ac994e301" - integrity sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q== + "integrity" "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==" + "resolved" "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz" + "version" "0.17.1" dependencies: "@types/mime" "^1" "@types/node" "*" "@types/serve-index@^1.9.1": - version "1.9.1" - resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" - integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== + "integrity" "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==" + "resolved" "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz" + "version" "1.9.1" dependencies: "@types/express" "*" "@types/serve-static@*", "@types/serve-static@^1.13.10": - version "1.15.2" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.2.tgz#3e5419ecd1e40e7405d34093f10befb43f63381a" - integrity sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw== + "integrity" "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==" + "resolved" "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz" + "version" "1.15.2" dependencies: "@types/http-errors" "*" "@types/mime" "*" "@types/node" "*" "@types/sockjs@^0.3.33": - version "0.3.33" - resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" - integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== + "integrity" "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==" + "resolved" "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz" + "version" "0.3.33" dependencies: "@types/node" "*" "@types/stack-utils@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" - integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + "integrity" "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + "resolved" "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz" + "version" "2.0.1" "@types/ws@^8.5.1": - version "8.5.5" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.5.tgz#af587964aa06682702ee6dcbc7be41a80e4b28eb" - integrity sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg== + "integrity" "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==" + "resolved" "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz" + "version" "8.5.5" dependencies: "@types/node" "*" "@types/yargs-parser@*": - version "21.0.0" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" - integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + "integrity" "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" + "resolved" "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz" + "version" "21.0.0" "@types/yargs@^17.0.8": - version "17.0.24" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.24.tgz#b3ef8d50ad4aa6aecf6ddc97c580a00f5aa11902" - integrity sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw== + "integrity" "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==" + "resolved" "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz" + "version" "17.0.24" dependencies: "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^4.33.0": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz#c24dc7c8069c7706bc40d99f6fa87edcb2005276" - integrity sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg== + "integrity" "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==" + "resolved" "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz" + "version" "4.33.0" 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" + "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" "@typescript-eslint/experimental-utils@4.33.0": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz#6f2a786a4209fa2222989e9380b5331b2810f7fd" - integrity sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q== + "integrity" "sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==" + "resolved" "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz" + "version" "4.33.0" 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" + "eslint-scope" "^5.1.1" + "eslint-utils" "^3.0.0" -"@typescript-eslint/parser@^4.33.0": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.33.0.tgz#dfe797570d9694e560528d18eecad86c8c744899" - integrity sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA== +"@typescript-eslint/parser@^4.0.0", "@typescript-eslint/parser@^4.33.0": + "integrity" "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==" + "resolved" "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz" + "version" "4.33.0" 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" + "debug" "^4.3.1" "@typescript-eslint/scope-manager@4.33.0": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3" - integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ== + "integrity" "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==" + "resolved" "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz" + "version" "4.33.0" dependencies: "@typescript-eslint/types" "4.33.0" "@typescript-eslint/visitor-keys" "4.33.0" "@typescript-eslint/types@4.33.0": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" - integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== + "integrity" "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==" + "resolved" "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz" + "version" "4.33.0" "@typescript-eslint/typescript-estree@4.33.0": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609" - integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA== + "integrity" "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==" + "resolved" "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz" + "version" "4.33.0" 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" + "debug" "^4.3.1" + "globby" "^11.0.3" + "is-glob" "^4.0.1" + "semver" "^7.3.5" + "tsutils" "^3.21.0" "@typescript-eslint/visitor-keys@4.33.0": - version "4.33.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd" - integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg== + "integrity" "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==" + "resolved" "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz" + "version" "4.33.0" dependencies: "@typescript-eslint/types" "4.33.0" - eslint-visitor-keys "^2.0.0" + "eslint-visitor-keys" "^2.0.0" -"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24" - integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q== +"@webassemblyjs/ast@^1.11.5", "@webassemblyjs/ast@1.11.6": + "integrity" "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz" + "version" "1.11.6" dependencies: "@webassemblyjs/helper-numbers" "1.11.6" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" "@webassemblyjs/floating-point-hex-parser@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" - integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== + "integrity" "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz" + "version" "1.11.6" "@webassemblyjs/helper-api-error@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" - integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== + "integrity" "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz" + "version" "1.11.6" "@webassemblyjs/helper-buffer@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093" - integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA== + "integrity" "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz" + "version" "1.11.6" "@webassemblyjs/helper-numbers@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" - integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== + "integrity" "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz" + "version" "1.11.6" dependencies: "@webassemblyjs/floating-point-hex-parser" "1.11.6" "@webassemblyjs/helper-api-error" "1.11.6" "@xtuc/long" "4.2.2" "@webassemblyjs/helper-wasm-bytecode@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" - integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== + "integrity" "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz" + "version" "1.11.6" "@webassemblyjs/helper-wasm-section@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577" - integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g== + "integrity" "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz" + "version" "1.11.6" dependencies: "@webassemblyjs/ast" "1.11.6" "@webassemblyjs/helper-buffer" "1.11.6" @@ -1714,28 +1709,28 @@ "@webassemblyjs/wasm-gen" "1.11.6" "@webassemblyjs/ieee754@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" - integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== + "integrity" "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz" + "version" "1.11.6" dependencies: "@xtuc/ieee754" "^1.2.0" "@webassemblyjs/leb128@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" - integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== + "integrity" "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz" + "version" "1.11.6" dependencies: "@xtuc/long" "4.2.2" "@webassemblyjs/utf8@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" - integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== + "integrity" "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz" + "version" "1.11.6" "@webassemblyjs/wasm-edit@^1.11.5": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab" - integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw== + "integrity" "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz" + "version" "1.11.6" dependencies: "@webassemblyjs/ast" "1.11.6" "@webassemblyjs/helper-buffer" "1.11.6" @@ -1747,9 +1742,9 @@ "@webassemblyjs/wast-printer" "1.11.6" "@webassemblyjs/wasm-gen@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268" - integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA== + "integrity" "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz" + "version" "1.11.6" dependencies: "@webassemblyjs/ast" "1.11.6" "@webassemblyjs/helper-wasm-bytecode" "1.11.6" @@ -1758,19 +1753,19 @@ "@webassemblyjs/utf8" "1.11.6" "@webassemblyjs/wasm-opt@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2" - integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g== + "integrity" "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz" + "version" "1.11.6" dependencies: "@webassemblyjs/ast" "1.11.6" "@webassemblyjs/helper-buffer" "1.11.6" "@webassemblyjs/wasm-gen" "1.11.6" "@webassemblyjs/wasm-parser" "1.11.6" -"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1" - integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ== +"@webassemblyjs/wasm-parser@^1.11.5", "@webassemblyjs/wasm-parser@1.11.6": + "integrity" "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz" + "version" "1.11.6" dependencies: "@webassemblyjs/ast" "1.11.6" "@webassemblyjs/helper-api-error" "1.11.6" @@ -1780,433 +1775,455 @@ "@webassemblyjs/utf8" "1.11.6" "@webassemblyjs/wast-printer@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20" - integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A== + "integrity" "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==" + "resolved" "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz" + "version" "1.11.6" dependencies: "@webassemblyjs/ast" "1.11.6" "@xtuc/long" "4.2.2" "@webpack-cli/configtest@^2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646" - integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw== + "integrity" "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==" + "resolved" "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz" + "version" "2.1.1" "@webpack-cli/info@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd" - integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A== + "integrity" "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==" + "resolved" "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz" + "version" "2.0.2" "@webpack-cli/serve@^2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" - integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== + "integrity" "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==" + "resolved" "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz" + "version" "2.0.5" "@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + "integrity" "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + "resolved" "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz" + "version" "1.2.0" "@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - -acorn-import-assertions@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" - integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== - -acorn-jsx@^5.3.1: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - -acorn@^7.4.0: - version "7.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" - integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== - -acorn@^8.7.1, acorn@^8.8.2: - version "8.10.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" - integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== - -ajv-formats@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" - integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== - dependencies: - ajv "^8.0.0" - -ajv-keywords@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== - -ajv-keywords@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" - integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== - dependencies: - fast-deep-equal "^3.1.3" - -ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - 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" - -ajv@^8.0.0, ajv@^8.0.1, ajv@^8.9.0: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" - integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - -ansi-colors@^4.1.1: - version "4.1.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" - integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== - -ansi-escapes@^4.2.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-html-community@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" - integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== - -anymatch@^3.0.3, anymatch@~3.1.2: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== - -array-flatten@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" - integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -astral-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" - integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== - -babel-eslint@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" - integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== + "integrity" "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + "resolved" "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz" + "version" "4.2.2" + +"accepts@~1.3.4", "accepts@~1.3.5", "accepts@~1.3.8": + "integrity" "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==" + "resolved" "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" + "version" "1.3.8" + dependencies: + "mime-types" "~2.1.34" + "negotiator" "0.6.3" + +"acorn-import-assertions@^1.9.0": + "integrity" "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==" + "resolved" "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz" + "version" "1.9.0" + +"acorn-jsx@^5.3.1": + "integrity" "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==" + "resolved" "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" + "version" "5.3.2" + +"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", "acorn@^7.4.0": + "integrity" "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + "resolved" "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz" + "version" "7.4.1" + +"acorn@^8.8.2": + "integrity" "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==" + "resolved" "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz" + "version" "8.10.0" + +"acorn@^8", "acorn@^8.7.1": + "integrity" "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==" + "resolved" "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz" + "version" "8.10.0" + +"ajv-formats@^2.1.1": + "integrity" "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==" + "resolved" "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "ajv" "^8.0.0" + +"ajv-keywords@^3.5.2": + "integrity" "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + "resolved" "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" + "version" "3.5.2" + +"ajv-keywords@^5.1.0": + "integrity" "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==" + "resolved" "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "fast-deep-equal" "^3.1.3" + +"ajv@^6.10.0", "ajv@^6.12.4", "ajv@^6.12.5", "ajv@^6.9.1": + "integrity" "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==" + "resolved" "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" + "version" "6.12.6" + 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" + +"ajv@^8.0.0", "ajv@^8.8.2", "ajv@^8.9.0": + "integrity" "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==" + "resolved" "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz" + "version" "8.12.0" + dependencies: + "fast-deep-equal" "^3.1.1" + "json-schema-traverse" "^1.0.0" + "require-from-string" "^2.0.2" + "uri-js" "^4.2.2" + +"ajv@^8.0.1": + "integrity" "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==" + "resolved" "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz" + "version" "8.12.0" + dependencies: + "fast-deep-equal" "^3.1.1" + "json-schema-traverse" "^1.0.0" + "require-from-string" "^2.0.2" + "uri-js" "^4.2.2" + +"ansi-colors@^4.1.1": + "integrity" "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==" + "resolved" "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz" + "version" "4.1.3" + +"ansi-escapes@^4.2.1": + "integrity" "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==" + "resolved" "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" + "version" "4.3.2" + dependencies: + "type-fest" "^0.21.3" + +"ansi-html-community@^0.0.8": + "integrity" "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==" + "resolved" "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz" + "version" "0.0.8" + +"ansi-regex@^5.0.1": + "integrity" "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + "version" "5.0.1" + +"ansi-styles@^3.2.1": + "integrity" "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==" + "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + "version" "3.2.1" + dependencies: + "color-convert" "^1.9.0" + +"ansi-styles@^4.0.0": + "integrity" "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==" + "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "color-convert" "^2.0.1" + +"ansi-styles@^4.1.0": + "integrity" "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==" + "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "color-convert" "^2.0.1" + +"ansi-styles@^5.0.0": + "integrity" "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + "resolved" "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz" + "version" "5.2.0" + +"anymatch@^3.0.3", "anymatch@~3.1.2": + "integrity" "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==" + "resolved" "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" + "version" "3.1.3" + dependencies: + "normalize-path" "^3.0.0" + "picomatch" "^2.0.4" + +"argparse@^1.0.7": + "integrity" "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==" + "resolved" "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" + "version" "1.0.10" + dependencies: + "sprintf-js" "~1.0.2" + +"array-flatten@^2.1.2": + "integrity" "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + "resolved" "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz" + "version" "2.1.2" + +"array-flatten@1.1.1": + "integrity" "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "resolved" "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + "version" "1.1.1" + +"array-union@^2.1.0": + "integrity" "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + "resolved" "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" + "version" "2.1.0" + +"astral-regex@^2.0.0": + "integrity" "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==" + "resolved" "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz" + "version" "2.0.0" + +"babel-eslint@^10.1.0": + "integrity" "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==" + "resolved" "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz" + "version" "10.1.0" dependencies: "@babel/code-frame" "^7.0.0" "@babel/parser" "^7.7.0" "@babel/traverse" "^7.7.0" "@babel/types" "^7.7.0" - eslint-visitor-keys "^1.0.0" - resolve "^1.12.0" - -babel-helper-evaluate-path@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.5.0.tgz#a62fa9c4e64ff7ea5cea9353174ef023a900a67c" - integrity sha512-mUh0UhS607bGh5wUMAQfOpt2JX2ThXMtppHRdRU1kL7ZLRWIXxoV2UIV1r2cAeeNeU1M5SB5/RSUgUxrK8yOkA== - -babel-helper-flip-expressions@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.4.3.tgz#3696736a128ac18bc25254b5f40a22ceb3c1d3fd" - integrity sha512-rSrkRW4YQ2ETCWww9gbsWk4N0x1BOtln349Tk0dlCS90oT68WMLyGR7WvaMp3eAnsVrCqdUtC19lo1avyGPejA== - -babel-helper-is-nodes-equiv@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz#34e9b300b1479ddd98ec77ea0bbe9342dfe39684" - integrity sha512-ri/nsMFVRqXn7IyT5qW4/hIAGQxuYUFHa3qsxmPtbk6spZQcYlyDogfVpNm2XYOslH/ULS4VEJGUqQX5u7ACQw== - -babel-helper-is-void-0@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/babel-helper-is-void-0/-/babel-helper-is-void-0-0.4.3.tgz#7d9c01b4561e7b95dbda0f6eee48f5b60e67313e" - integrity sha512-07rBV0xPRM3TM5NVJEOQEkECX3qnHDjaIbFvWYPv+T1ajpUiVLiqTfC+MmiZxY5KOL/Ec08vJdJD9kZiP9UkUg== - -babel-helper-mark-eval-scopes@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz#d244a3bef9844872603ffb46e22ce8acdf551562" - integrity sha512-+d/mXPP33bhgHkdVOiPkmYoeXJ+rXRWi7OdhwpyseIqOS8CmzHQXHUp/+/Qr8baXsT0kjGpMHHofHs6C3cskdA== - -babel-helper-remove-or-void@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz#a4f03b40077a0ffe88e45d07010dee241ff5ae60" - integrity sha512-eYNceYtcGKpifHDir62gHJadVXdg9fAhuZEXiRQnJJ4Yi4oUTpqpNY//1pM4nVyjjDMPYaC2xSf0I+9IqVzwdA== - -babel-helper-to-multiple-sequence-expressions@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.5.0.tgz#a3f924e3561882d42fcf48907aa98f7979a4588d" - integrity sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA== - -babel-jest@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.6.2.tgz#cada0a59e07f5acaeb11cbae7e3ba92aec9c1126" - integrity sha512-BYCzImLos6J3BH/+HvUCHG1dTf2MzmAB4jaVxHV+29RZLjR29XuYTmsf2sdDwkrb+FczkGo3kOhE7ga6sI0P4A== + "eslint-visitor-keys" "^1.0.0" + "resolve" "^1.12.0" + +"babel-helper-evaluate-path@^0.5.0": + "integrity" "sha512-mUh0UhS607bGh5wUMAQfOpt2JX2ThXMtppHRdRU1kL7ZLRWIXxoV2UIV1r2cAeeNeU1M5SB5/RSUgUxrK8yOkA==" + "resolved" "https://registry.npmjs.org/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.5.0.tgz" + "version" "0.5.0" + +"babel-helper-flip-expressions@^0.4.3": + "integrity" "sha512-rSrkRW4YQ2ETCWww9gbsWk4N0x1BOtln349Tk0dlCS90oT68WMLyGR7WvaMp3eAnsVrCqdUtC19lo1avyGPejA==" + "resolved" "https://registry.npmjs.org/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.4.3.tgz" + "version" "0.4.3" + +"babel-helper-is-nodes-equiv@^0.0.1": + "integrity" "sha512-ri/nsMFVRqXn7IyT5qW4/hIAGQxuYUFHa3qsxmPtbk6spZQcYlyDogfVpNm2XYOslH/ULS4VEJGUqQX5u7ACQw==" + "resolved" "https://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz" + "version" "0.0.1" + +"babel-helper-is-void-0@^0.4.3": + "integrity" "sha512-07rBV0xPRM3TM5NVJEOQEkECX3qnHDjaIbFvWYPv+T1ajpUiVLiqTfC+MmiZxY5KOL/Ec08vJdJD9kZiP9UkUg==" + "resolved" "https://registry.npmjs.org/babel-helper-is-void-0/-/babel-helper-is-void-0-0.4.3.tgz" + "version" "0.4.3" + +"babel-helper-mark-eval-scopes@^0.4.3": + "integrity" "sha512-+d/mXPP33bhgHkdVOiPkmYoeXJ+rXRWi7OdhwpyseIqOS8CmzHQXHUp/+/Qr8baXsT0kjGpMHHofHs6C3cskdA==" + "resolved" "https://registry.npmjs.org/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz" + "version" "0.4.3" + +"babel-helper-remove-or-void@^0.4.3": + "integrity" "sha512-eYNceYtcGKpifHDir62gHJadVXdg9fAhuZEXiRQnJJ4Yi4oUTpqpNY//1pM4nVyjjDMPYaC2xSf0I+9IqVzwdA==" + "resolved" "https://registry.npmjs.org/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz" + "version" "0.4.3" + +"babel-helper-to-multiple-sequence-expressions@^0.5.0": + "integrity" "sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA==" + "resolved" "https://registry.npmjs.org/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.5.0.tgz" + "version" "0.5.0" + +"babel-jest@^29.6.2": + "integrity" "sha512-BYCzImLos6J3BH/+HvUCHG1dTf2MzmAB4jaVxHV+29RZLjR29XuYTmsf2sdDwkrb+FczkGo3kOhE7ga6sI0P4A==" + "resolved" "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/transform" "^29.6.2" "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^29.5.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - slash "^3.0.0" + "babel-plugin-istanbul" "^6.1.1" + "babel-preset-jest" "^29.5.0" + "chalk" "^4.0.0" + "graceful-fs" "^4.2.9" + "slash" "^3.0.0" -babel-loader@^9.1.3: - version "9.1.3" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-9.1.3.tgz#3d0e01b4e69760cc694ee306fe16d358aa1c6f9a" - integrity sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw== +"babel-loader@^9.1.3": + "integrity" "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==" + "resolved" "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz" + "version" "9.1.3" dependencies: - find-cache-dir "^4.0.0" - schema-utils "^4.0.0" + "find-cache-dir" "^4.0.0" + "schema-utils" "^4.0.0" -babel-plugin-istanbul@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" - integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== +"babel-plugin-istanbul@^6.1.1": + "integrity" "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==" + "resolved" "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz" + "version" "6.1.1" dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@istanbuljs/load-nyc-config" "^1.0.0" "@istanbuljs/schema" "^0.1.2" - istanbul-lib-instrument "^5.0.4" - test-exclude "^6.0.0" + "istanbul-lib-instrument" "^5.0.4" + "test-exclude" "^6.0.0" -babel-plugin-jest-hoist@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz#a97db437936f441ec196990c9738d4b88538618a" - integrity sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w== +"babel-plugin-jest-hoist@^29.5.0": + "integrity" "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==" + "resolved" "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz" + "version" "29.5.0" dependencies: "@babel/template" "^7.3.3" "@babel/types" "^7.3.3" "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" -babel-plugin-minify-builtins@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.5.0.tgz#31eb82ed1a0d0efdc31312f93b6e4741ce82c36b" - integrity sha512-wpqbN7Ov5hsNwGdzuzvFcjgRlzbIeVv1gMIlICbPj0xkexnfoIDe7q+AZHMkQmAE/F9R5jkrB6TLfTegImlXag== +"babel-plugin-minify-builtins@^0.5.0": + "integrity" "sha512-wpqbN7Ov5hsNwGdzuzvFcjgRlzbIeVv1gMIlICbPj0xkexnfoIDe7q+AZHMkQmAE/F9R5jkrB6TLfTegImlXag==" + "resolved" "https://registry.npmjs.org/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.5.0.tgz" + "version" "0.5.0" -babel-plugin-minify-constant-folding@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.5.0.tgz#f84bc8dbf6a561e5e350ff95ae216b0ad5515b6e" - integrity sha512-Vj97CTn/lE9hR1D+jKUeHfNy+m1baNiJ1wJvoGyOBUx7F7kJqDZxr9nCHjO/Ad+irbR3HzR6jABpSSA29QsrXQ== +"babel-plugin-minify-constant-folding@^0.5.0": + "integrity" "sha512-Vj97CTn/lE9hR1D+jKUeHfNy+m1baNiJ1wJvoGyOBUx7F7kJqDZxr9nCHjO/Ad+irbR3HzR6jABpSSA29QsrXQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.5.0.tgz" + "version" "0.5.0" dependencies: - babel-helper-evaluate-path "^0.5.0" + "babel-helper-evaluate-path" "^0.5.0" -babel-plugin-minify-dead-code-elimination@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.5.2.tgz#f386ceec77a80cc4e76022a04c21b7d68e0aa5eb" - integrity sha512-krq9Lwi0QIzyAlcNBXTL4usqUvevB4BzktdEsb8srcXC1AaYqRJiAQw6vdKdJSaXbz6snBvziGr6ch/aoRCfpA== +"babel-plugin-minify-dead-code-elimination@^0.5.2": + "integrity" "sha512-krq9Lwi0QIzyAlcNBXTL4usqUvevB4BzktdEsb8srcXC1AaYqRJiAQw6vdKdJSaXbz6snBvziGr6ch/aoRCfpA==" + "resolved" "https://registry.npmjs.org/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.5.2.tgz" + "version" "0.5.2" dependencies: - babel-helper-evaluate-path "^0.5.0" - babel-helper-mark-eval-scopes "^0.4.3" - babel-helper-remove-or-void "^0.4.3" - lodash "^4.17.11" + "babel-helper-evaluate-path" "^0.5.0" + "babel-helper-mark-eval-scopes" "^0.4.3" + "babel-helper-remove-or-void" "^0.4.3" + "lodash" "^4.17.11" -babel-plugin-minify-flip-comparisons@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.4.3.tgz#00ca870cb8f13b45c038b3c1ebc0f227293c965a" - integrity sha512-8hNwgLVeJzpeLVOVArag2DfTkbKodzOHU7+gAZ8mGBFGPQHK6uXVpg3jh5I/F6gfi5Q5usWU2OKcstn1YbAV7A== +"babel-plugin-minify-flip-comparisons@^0.4.3": + "integrity" "sha512-8hNwgLVeJzpeLVOVArag2DfTkbKodzOHU7+gAZ8mGBFGPQHK6uXVpg3jh5I/F6gfi5Q5usWU2OKcstn1YbAV7A==" + "resolved" "https://registry.npmjs.org/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.4.3.tgz" + "version" "0.4.3" dependencies: - babel-helper-is-void-0 "^0.4.3" + "babel-helper-is-void-0" "^0.4.3" -babel-plugin-minify-guarded-expressions@^0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.4.tgz#818960f64cc08aee9d6c75bec6da974c4d621135" - integrity sha512-RMv0tM72YuPPfLT9QLr3ix9nwUIq+sHT6z8Iu3sLbqldzC1Dls8DPCywzUIzkTx9Zh1hWX4q/m9BPoPed9GOfA== +"babel-plugin-minify-guarded-expressions@^0.4.4": + "integrity" "sha512-RMv0tM72YuPPfLT9QLr3ix9nwUIq+sHT6z8Iu3sLbqldzC1Dls8DPCywzUIzkTx9Zh1hWX4q/m9BPoPed9GOfA==" + "resolved" "https://registry.npmjs.org/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.4.tgz" + "version" "0.4.4" dependencies: - babel-helper-evaluate-path "^0.5.0" - babel-helper-flip-expressions "^0.4.3" + "babel-helper-evaluate-path" "^0.5.0" + "babel-helper-flip-expressions" "^0.4.3" -babel-plugin-minify-infinity@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.4.3.tgz#dfb876a1b08a06576384ef3f92e653ba607b39ca" - integrity sha512-X0ictxCk8y+NvIf+bZ1HJPbVZKMlPku3lgYxPmIp62Dp8wdtbMLSekczty3MzvUOlrk5xzWYpBpQprXUjDRyMA== +"babel-plugin-minify-infinity@^0.4.3": + "integrity" "sha512-X0ictxCk8y+NvIf+bZ1HJPbVZKMlPku3lgYxPmIp62Dp8wdtbMLSekczty3MzvUOlrk5xzWYpBpQprXUjDRyMA==" + "resolved" "https://registry.npmjs.org/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.4.3.tgz" + "version" "0.4.3" -babel-plugin-minify-mangle-names@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.5.1.tgz#3dfba7f4e649ff37a767542ea0d1093bee3bb155" - integrity sha512-8KMichAOae2FHlipjNDTo2wz97MdEb2Q0jrn4NIRXzHH7SJ3c5TaNNBkeTHbk9WUsMnqpNUx949ugM9NFWewzw== +"babel-plugin-minify-mangle-names@^0.5.1": + "integrity" "sha512-8KMichAOae2FHlipjNDTo2wz97MdEb2Q0jrn4NIRXzHH7SJ3c5TaNNBkeTHbk9WUsMnqpNUx949ugM9NFWewzw==" + "resolved" "https://registry.npmjs.org/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.5.1.tgz" + "version" "0.5.1" dependencies: - babel-helper-mark-eval-scopes "^0.4.3" + "babel-helper-mark-eval-scopes" "^0.4.3" -babel-plugin-minify-numeric-literals@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.4.3.tgz#8e4fd561c79f7801286ff60e8c5fd9deee93c0bc" - integrity sha512-5D54hvs9YVuCknfWywq0eaYDt7qYxlNwCqW9Ipm/kYeS9gYhJd0Rr/Pm2WhHKJ8DC6aIlDdqSBODSthabLSX3A== +"babel-plugin-minify-numeric-literals@^0.4.3": + "integrity" "sha512-5D54hvs9YVuCknfWywq0eaYDt7qYxlNwCqW9Ipm/kYeS9gYhJd0Rr/Pm2WhHKJ8DC6aIlDdqSBODSthabLSX3A==" + "resolved" "https://registry.npmjs.org/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.4.3.tgz" + "version" "0.4.3" -babel-plugin-minify-replace@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.5.0.tgz#d3e2c9946c9096c070efc96761ce288ec5c3f71c" - integrity sha512-aXZiaqWDNUbyNNNpWs/8NyST+oU7QTpK7J9zFEFSA0eOmtUNMU3fczlTTTlnCxHmq/jYNFEmkkSG3DDBtW3Y4Q== +"babel-plugin-minify-replace@^0.5.0": + "integrity" "sha512-aXZiaqWDNUbyNNNpWs/8NyST+oU7QTpK7J9zFEFSA0eOmtUNMU3fczlTTTlnCxHmq/jYNFEmkkSG3DDBtW3Y4Q==" + "resolved" "https://registry.npmjs.org/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.5.0.tgz" + "version" "0.5.0" -babel-plugin-minify-simplify@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.5.1.tgz#f21613c8b95af3450a2ca71502fdbd91793c8d6a" - integrity sha512-OSYDSnoCxP2cYDMk9gxNAed6uJDiDz65zgL6h8d3tm8qXIagWGMLWhqysT6DY3Vs7Fgq7YUDcjOomhVUb+xX6A== +"babel-plugin-minify-simplify@^0.5.1": + "integrity" "sha512-OSYDSnoCxP2cYDMk9gxNAed6uJDiDz65zgL6h8d3tm8qXIagWGMLWhqysT6DY3Vs7Fgq7YUDcjOomhVUb+xX6A==" + "resolved" "https://registry.npmjs.org/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.5.1.tgz" + "version" "0.5.1" dependencies: - babel-helper-evaluate-path "^0.5.0" - babel-helper-flip-expressions "^0.4.3" - babel-helper-is-nodes-equiv "^0.0.1" - babel-helper-to-multiple-sequence-expressions "^0.5.0" + "babel-helper-evaluate-path" "^0.5.0" + "babel-helper-flip-expressions" "^0.4.3" + "babel-helper-is-nodes-equiv" "^0.0.1" + "babel-helper-to-multiple-sequence-expressions" "^0.5.0" -babel-plugin-minify-type-constructors@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.4.3.tgz#1bc6f15b87f7ab1085d42b330b717657a2156500" - integrity sha512-4ADB0irJ/6BeXWHubjCJmrPbzhxDgjphBMjIjxCc25n4NGJ00NsYqwYt+F/OvE9RXx8KaSW7cJvp+iZX436tnQ== +"babel-plugin-minify-type-constructors@^0.4.3": + "integrity" "sha512-4ADB0irJ/6BeXWHubjCJmrPbzhxDgjphBMjIjxCc25n4NGJ00NsYqwYt+F/OvE9RXx8KaSW7cJvp+iZX436tnQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.4.3.tgz" + "version" "0.4.3" dependencies: - babel-helper-is-void-0 "^0.4.3" + "babel-helper-is-void-0" "^0.4.3" -babel-plugin-polyfill-corejs2@^0.4.5: - version "0.4.5" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz#8097b4cb4af5b64a1d11332b6fb72ef5e64a054c" - integrity sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg== +"babel-plugin-polyfill-corejs2@^0.4.5": + "integrity" "sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg==" + "resolved" "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz" + "version" "0.4.5" dependencies: "@babel/compat-data" "^7.22.6" "@babel/helper-define-polyfill-provider" "^0.4.2" - semver "^6.3.1" + "semver" "^6.3.1" -babel-plugin-polyfill-corejs3@^0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz#b4f719d0ad9bb8e0c23e3e630c0c8ec6dd7a1c52" - integrity sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA== +"babel-plugin-polyfill-corejs3@^0.8.3": + "integrity" "sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA==" + "resolved" "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz" + "version" "0.8.3" dependencies: "@babel/helper-define-polyfill-provider" "^0.4.2" - core-js-compat "^3.31.0" + "core-js-compat" "^3.31.0" -babel-plugin-polyfill-regenerator@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz#80d0f3e1098c080c8b5a65f41e9427af692dc326" - integrity sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA== +"babel-plugin-polyfill-regenerator@^0.5.2": + "integrity" "sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA==" + "resolved" "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz" + "version" "0.5.2" dependencies: "@babel/helper-define-polyfill-provider" "^0.4.2" -babel-plugin-transform-inline-consecutive-adds@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.4.3.tgz#323d47a3ea63a83a7ac3c811ae8e6941faf2b0d1" - integrity sha512-8D104wbzzI5RlxeVPYeQb9QsUyepiH1rAO5hpPpQ6NPRgQLpIVwkS/Nbx944pm4K8Z+rx7CgjPsFACz/VCBN0Q== - -babel-plugin-transform-member-expression-literals@^6.9.4: - version "6.9.4" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.9.4.tgz#37039c9a0c3313a39495faac2ff3a6b5b9d038bf" - integrity sha512-Xq9/Rarpj+bjOZSl1nBbZYETsNEDDJSrb6Plb1sS3/36FukWFLLRysgecva5KZECjUJTrJoQqjJgtWToaflk5Q== - -babel-plugin-transform-merge-sibling-variables@^6.9.5: - version "6.9.5" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.9.5.tgz#0b2faa9e027ef47d4e7502f77cd1a7f3a6dfbc7b" - integrity sha512-xj/KrWi6/uP+DrD844h66Qh2cZN++iugEIgH8QcIxhmZZPNP6VpOE9b4gP2FFW39xDAY43kCmYMM6U0QNKN8fw== - -babel-plugin-transform-minify-booleans@^6.9.4: - version "6.9.4" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.4.tgz#acbb3e56a3555dd23928e4b582d285162dd2b198" - integrity sha512-9pW9ePng6DZpzGPalcrULuhSCcauGAbn8AeU3bE34HcDkGm8Ldt0ysjGkyb64f0K3T5ilV4mriayOVv5fg0ASA== - -babel-plugin-transform-property-literals@^6.9.4: - version "6.9.4" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.4.tgz#98c1d21e255736573f93ece54459f6ce24985d39" - integrity sha512-Pf8JHTjTPxecqVyL6KSwD/hxGpoTZjiEgV7nCx0KFQsJYM0nuuoCajbg09KRmZWeZbJ5NGTySABYv8b/hY1eEA== - dependencies: - esutils "^2.0.2" - -babel-plugin-transform-regexp-constructors@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.4.3.tgz#58b7775b63afcf33328fae9a5f88fbd4fb0b4965" - integrity sha512-JjymDyEyRNhAoNFp09y/xGwYVYzT2nWTGrBrWaL6eCg2m+B24qH2jR0AA8V8GzKJTgC8NW6joJmc6nabvWBD/g== - -babel-plugin-transform-remove-console@^6.9.4: - version "6.9.4" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.4.tgz#b980360c067384e24b357a588d807d3c83527780" - integrity sha512-88blrUrMX3SPiGkT1GnvVY8E/7A+k6oj3MNvUtTIxJflFzXTw1bHkuJ/y039ouhFMp2prRn5cQGzokViYi1dsg== - -babel-plugin-transform-remove-debugger@^6.9.4: - version "6.9.4" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.9.4.tgz#42b727631c97978e1eb2d199a7aec84a18339ef2" - integrity sha512-Kd+eTBYlXfwoFzisburVwrngsrz4xh9I0ppoJnU/qlLysxVBRgI4Pj+dk3X8F5tDiehp3hhP8oarRMT9v2Z3lw== - -babel-plugin-transform-remove-undefined@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.5.0.tgz#80208b31225766c630c97fa2d288952056ea22dd" - integrity sha512-+M7fJYFaEE/M9CXa0/IRkDbiV3wRELzA1kKQFCJ4ifhrzLKn/9VCCgj9OFmYWwBd8IB48YdgPkHYtbYq+4vtHQ== - dependencies: - babel-helper-evaluate-path "^0.5.0" - -babel-plugin-transform-simplify-comparison-operators@^6.9.4: - version "6.9.4" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.4.tgz#f62afe096cab0e1f68a2d753fdf283888471ceb9" - integrity sha512-GLInxhGAQWJ9YIdjwF6dAFlmh4U+kN8pL6Big7nkDzHoZcaDQOtBm28atEhQJq6m9GpAovbiGEShKqXv4BSp0A== - -babel-plugin-transform-undefined-to-void@^6.9.4: - version "6.9.4" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz#be241ca81404030678b748717322b89d0c8fe280" - integrity sha512-D2UbwxawEY1xVc9svYAUZQM2xarwSNXue2qDIx6CeV2EuMGaes/0su78zlIDIAgE7BvnMw4UpmSo9fDy+znghg== - -babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== +"babel-plugin-transform-inline-consecutive-adds@^0.4.3": + "integrity" "sha512-8D104wbzzI5RlxeVPYeQb9QsUyepiH1rAO5hpPpQ6NPRgQLpIVwkS/Nbx944pm4K8Z+rx7CgjPsFACz/VCBN0Q==" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.4.3.tgz" + "version" "0.4.3" + +"babel-plugin-transform-member-expression-literals@^6.9.4": + "integrity" "sha512-Xq9/Rarpj+bjOZSl1nBbZYETsNEDDJSrb6Plb1sS3/36FukWFLLRysgecva5KZECjUJTrJoQqjJgtWToaflk5Q==" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.9.4.tgz" + "version" "6.9.4" + +"babel-plugin-transform-merge-sibling-variables@^6.9.5": + "integrity" "sha512-xj/KrWi6/uP+DrD844h66Qh2cZN++iugEIgH8QcIxhmZZPNP6VpOE9b4gP2FFW39xDAY43kCmYMM6U0QNKN8fw==" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.9.5.tgz" + "version" "6.9.5" + +"babel-plugin-transform-minify-booleans@^6.9.4": + "integrity" "sha512-9pW9ePng6DZpzGPalcrULuhSCcauGAbn8AeU3bE34HcDkGm8Ldt0ysjGkyb64f0K3T5ilV4mriayOVv5fg0ASA==" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.4.tgz" + "version" "6.9.4" + +"babel-plugin-transform-property-literals@^6.9.4": + "integrity" "sha512-Pf8JHTjTPxecqVyL6KSwD/hxGpoTZjiEgV7nCx0KFQsJYM0nuuoCajbg09KRmZWeZbJ5NGTySABYv8b/hY1eEA==" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.4.tgz" + "version" "6.9.4" + dependencies: + "esutils" "^2.0.2" + +"babel-plugin-transform-regexp-constructors@^0.4.3": + "integrity" "sha512-JjymDyEyRNhAoNFp09y/xGwYVYzT2nWTGrBrWaL6eCg2m+B24qH2jR0AA8V8GzKJTgC8NW6joJmc6nabvWBD/g==" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.4.3.tgz" + "version" "0.4.3" + +"babel-plugin-transform-remove-console@^6.9.4": + "integrity" "sha512-88blrUrMX3SPiGkT1GnvVY8E/7A+k6oj3MNvUtTIxJflFzXTw1bHkuJ/y039ouhFMp2prRn5cQGzokViYi1dsg==" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.4.tgz" + "version" "6.9.4" + +"babel-plugin-transform-remove-debugger@^6.9.4": + "integrity" "sha512-Kd+eTBYlXfwoFzisburVwrngsrz4xh9I0ppoJnU/qlLysxVBRgI4Pj+dk3X8F5tDiehp3hhP8oarRMT9v2Z3lw==" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.9.4.tgz" + "version" "6.9.4" + +"babel-plugin-transform-remove-undefined@^0.5.0": + "integrity" "sha512-+M7fJYFaEE/M9CXa0/IRkDbiV3wRELzA1kKQFCJ4ifhrzLKn/9VCCgj9OFmYWwBd8IB48YdgPkHYtbYq+4vtHQ==" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.5.0.tgz" + "version" "0.5.0" + dependencies: + "babel-helper-evaluate-path" "^0.5.0" + +"babel-plugin-transform-simplify-comparison-operators@^6.9.4": + "integrity" "sha512-GLInxhGAQWJ9YIdjwF6dAFlmh4U+kN8pL6Big7nkDzHoZcaDQOtBm28atEhQJq6m9GpAovbiGEShKqXv4BSp0A==" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.4.tgz" + "version" "6.9.4" + +"babel-plugin-transform-undefined-to-void@^6.9.4": + "integrity" "sha512-D2UbwxawEY1xVc9svYAUZQM2xarwSNXue2qDIx6CeV2EuMGaes/0su78zlIDIAgE7BvnMw4UpmSo9fDy+znghg==" + "resolved" "https://registry.npmjs.org/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz" + "version" "6.9.4" + +"babel-preset-current-node-syntax@^1.0.0": + "integrity" "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==" + "resolved" "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz" + "version" "1.0.1" dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-bigint" "^7.8.3" @@ -2221,1874 +2238,1891 @@ babel-preset-current-node-syntax@^1.0.0: "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-top-level-await" "^7.8.3" -babel-preset-jest@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz#57bc8cc88097af7ff6a5ab59d1cd29d52a5916e2" - integrity sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg== - dependencies: - babel-plugin-jest-hoist "^29.5.0" - babel-preset-current-node-syntax "^1.0.0" - -babel-preset-minify@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/babel-preset-minify/-/babel-preset-minify-0.5.2.tgz#4d5be8b1c21d126ac403a3fd002d8b5fb7bb3c34" - integrity sha512-v4GL+kk0TfovbRIKZnC3HPbu2cAGmPAby7BsOmuPdMJfHV+4FVdsGXTH/OOGQRKYdjemBuL1+MsE6mobobhe9w== - dependencies: - babel-plugin-minify-builtins "^0.5.0" - babel-plugin-minify-constant-folding "^0.5.0" - babel-plugin-minify-dead-code-elimination "^0.5.2" - babel-plugin-minify-flip-comparisons "^0.4.3" - babel-plugin-minify-guarded-expressions "^0.4.4" - babel-plugin-minify-infinity "^0.4.3" - babel-plugin-minify-mangle-names "^0.5.1" - babel-plugin-minify-numeric-literals "^0.4.3" - babel-plugin-minify-replace "^0.5.0" - babel-plugin-minify-simplify "^0.5.1" - babel-plugin-minify-type-constructors "^0.4.3" - babel-plugin-transform-inline-consecutive-adds "^0.4.3" - babel-plugin-transform-member-expression-literals "^6.9.4" - babel-plugin-transform-merge-sibling-variables "^6.9.5" - babel-plugin-transform-minify-booleans "^6.9.4" - babel-plugin-transform-property-literals "^6.9.4" - babel-plugin-transform-regexp-constructors "^0.4.3" - babel-plugin-transform-remove-console "^6.9.4" - babel-plugin-transform-remove-debugger "^6.9.4" - babel-plugin-transform-remove-undefined "^0.5.0" - babel-plugin-transform-simplify-comparison-operators "^6.9.4" - babel-plugin-transform-undefined-to-void "^6.9.4" - lodash "^4.17.11" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -batch@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== - -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -binascii@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/binascii/-/binascii-0.0.2.tgz#a7f8a8801dbccf8b1756b743daa0fee9e2d9e0ee" - integrity sha512-rA2CrUl1+6yKrn+XgLs8Hdy18OER1UW146nM+ixzhQXDY+Bd3ySkyIJGwF2a4I45JwbvF1mDL/nWkqBwpOcdBA== - -bls-signatures@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/bls-signatures/-/bls-signatures-2.0.2.tgz#a02cde31876d56dd4fb3c12b4e0b042a1b090a46" - integrity sha512-f60Oh1HRUfumYykCHaCzVRJKEXC2VlN+4YKl58fsFpovpx6/M023GdeK1sJqTH1eXFLqaERiCCPGWOhoubYtlA== - dependencies: - binascii "0.0.2" - -body-parser@1.20.1: - version "1.20.1" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" - integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== - dependencies: - bytes "3.1.2" - content-type "~1.0.4" - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - http-errors "2.0.0" - iconv-lite "0.4.24" - on-finished "2.4.1" - qs "6.11.0" - raw-body "2.5.1" - type-is "~1.6.18" - unpipe "1.0.0" - -bonjour-service@^1.0.11: - version "1.1.1" - resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.1.1.tgz#960948fa0e0153f5d26743ab15baf8e33752c135" - integrity sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg== - dependencies: - array-flatten "^2.1.2" - dns-equal "^1.0.0" - fast-deep-equal "^3.1.3" - multicast-dns "^7.2.5" - -boolbase@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^3.0.2, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.21.4, browserslist@^4.21.9: - version "4.21.10" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.10.tgz#dbbac576628c13d3b2231332cb2ec5a46e015bb0" - integrity sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ== - dependencies: - caniuse-lite "^1.0.30001517" - electron-to-chromium "^1.4.477" - node-releases "^2.0.13" - update-browserslist-db "^1.0.11" - -bser@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" - integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== - dependencies: - node-int64 "^0.4.0" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -call-bind@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camel-case@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" - integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== - dependencies: - pascal-case "^3.1.2" - tslib "^2.0.3" - -camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -camelcase@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -caniuse-api@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" - integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== - dependencies: - browserslist "^4.0.0" - caniuse-lite "^1.0.0" - lodash.memoize "^4.1.2" - lodash.uniq "^4.5.0" - -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001517: - version "1.0.30001519" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001519.tgz#3e7b8b8a7077e78b0eb054d69e6edf5c7df35601" - integrity sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg== - -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.0.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -char-regex@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" - integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== - -chokidar@^3.4.0, chokidar@^3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - 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" +"babel-preset-jest@^29.5.0": + "integrity" "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==" + "resolved" "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz" + "version" "29.5.0" + dependencies: + "babel-plugin-jest-hoist" "^29.5.0" + "babel-preset-current-node-syntax" "^1.0.0" + +"babel-preset-minify@^0.5.2": + "integrity" "sha512-v4GL+kk0TfovbRIKZnC3HPbu2cAGmPAby7BsOmuPdMJfHV+4FVdsGXTH/OOGQRKYdjemBuL1+MsE6mobobhe9w==" + "resolved" "https://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.5.2.tgz" + "version" "0.5.2" + dependencies: + "babel-plugin-minify-builtins" "^0.5.0" + "babel-plugin-minify-constant-folding" "^0.5.0" + "babel-plugin-minify-dead-code-elimination" "^0.5.2" + "babel-plugin-minify-flip-comparisons" "^0.4.3" + "babel-plugin-minify-guarded-expressions" "^0.4.4" + "babel-plugin-minify-infinity" "^0.4.3" + "babel-plugin-minify-mangle-names" "^0.5.1" + "babel-plugin-minify-numeric-literals" "^0.4.3" + "babel-plugin-minify-replace" "^0.5.0" + "babel-plugin-minify-simplify" "^0.5.1" + "babel-plugin-minify-type-constructors" "^0.4.3" + "babel-plugin-transform-inline-consecutive-adds" "^0.4.3" + "babel-plugin-transform-member-expression-literals" "^6.9.4" + "babel-plugin-transform-merge-sibling-variables" "^6.9.5" + "babel-plugin-transform-minify-booleans" "^6.9.4" + "babel-plugin-transform-property-literals" "^6.9.4" + "babel-plugin-transform-regexp-constructors" "^0.4.3" + "babel-plugin-transform-remove-console" "^6.9.4" + "babel-plugin-transform-remove-debugger" "^6.9.4" + "babel-plugin-transform-remove-undefined" "^0.5.0" + "babel-plugin-transform-simplify-comparison-operators" "^6.9.4" + "babel-plugin-transform-undefined-to-void" "^6.9.4" + "lodash" "^4.17.11" + +"balanced-match@^1.0.0": + "integrity" "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "resolved" "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + "version" "1.0.2" + +"batch@0.6.1": + "integrity" "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" + "resolved" "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz" + "version" "0.6.1" + +"big.js@^5.2.2": + "integrity" "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + "resolved" "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz" + "version" "5.2.2" + +"binary-extensions@^2.0.0": + "integrity" "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + "resolved" "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" + "version" "2.2.0" + +"binascii@0.0.2": + "integrity" "sha512-rA2CrUl1+6yKrn+XgLs8Hdy18OER1UW146nM+ixzhQXDY+Bd3ySkyIJGwF2a4I45JwbvF1mDL/nWkqBwpOcdBA==" + "resolved" "https://registry.npmjs.org/binascii/-/binascii-0.0.2.tgz" + "version" "0.0.2" + +"bls-signatures@^2.0.2": + "integrity" "sha512-f60Oh1HRUfumYykCHaCzVRJKEXC2VlN+4YKl58fsFpovpx6/M023GdeK1sJqTH1eXFLqaERiCCPGWOhoubYtlA==" + "resolved" "https://registry.npmjs.org/bls-signatures/-/bls-signatures-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "binascii" "0.0.2" + +"body-parser@1.20.1": + "integrity" "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==" + "resolved" "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz" + "version" "1.20.1" + dependencies: + "bytes" "3.1.2" + "content-type" "~1.0.4" + "debug" "2.6.9" + "depd" "2.0.0" + "destroy" "1.2.0" + "http-errors" "2.0.0" + "iconv-lite" "0.4.24" + "on-finished" "2.4.1" + "qs" "6.11.0" + "raw-body" "2.5.1" + "type-is" "~1.6.18" + "unpipe" "1.0.0" + +"bonjour-service@^1.0.11": + "integrity" "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==" + "resolved" "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "array-flatten" "^2.1.2" + "dns-equal" "^1.0.0" + "fast-deep-equal" "^3.1.3" + "multicast-dns" "^7.2.5" + +"boolbase@^1.0.0": + "integrity" "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + "resolved" "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" + "version" "1.0.0" + +"brace-expansion@^1.1.7": + "integrity" "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==" + "resolved" "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + "version" "1.1.11" + dependencies: + "balanced-match" "^1.0.0" + "concat-map" "0.0.1" + +"braces@^3.0.2", "braces@~3.0.2": + "integrity" "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==" + "resolved" "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "fill-range" "^7.0.1" + +"browserslist@^4.0.0", "browserslist@^4.14.5", "browserslist@^4.21.4", "browserslist@^4.21.9", "browserslist@>= 4.21.0": + "integrity" "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==" + "resolved" "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz" + "version" "4.21.10" + dependencies: + "caniuse-lite" "^1.0.30001517" + "electron-to-chromium" "^1.4.477" + "node-releases" "^2.0.13" + "update-browserslist-db" "^1.0.11" + +"bser@2.1.1": + "integrity" "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==" + "resolved" "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "node-int64" "^0.4.0" + +"buffer-from@^1.0.0": + "integrity" "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "resolved" "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" + "version" "1.1.2" + +"bytes@3.0.0": + "integrity" "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" + "resolved" "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz" + "version" "3.0.0" + +"bytes@3.1.2": + "integrity" "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + "resolved" "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" + "version" "3.1.2" + +"call-bind@^1.0.0": + "integrity" "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==" + "resolved" "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "function-bind" "^1.1.1" + "get-intrinsic" "^1.0.2" + +"callsites@^3.0.0": + "integrity" "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + "resolved" "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + "version" "3.1.0" + +"camel-case@^4.1.2": + "integrity" "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==" + "resolved" "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "pascal-case" "^3.1.2" + "tslib" "^2.0.3" + +"camelcase@^5.3.1": + "integrity" "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + "resolved" "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" + "version" "5.3.1" + +"camelcase@^6.2.0": + "integrity" "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + "resolved" "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + "version" "6.3.0" + +"caniuse-api@^3.0.0": + "integrity" "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==" + "resolved" "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "browserslist" "^4.0.0" + "caniuse-lite" "^1.0.0" + "lodash.memoize" "^4.1.2" + "lodash.uniq" "^4.5.0" + +"caniuse-lite@^1.0.0", "caniuse-lite@^1.0.30001517": + "integrity" "sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg==" + "resolved" "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001519.tgz" + "version" "1.0.30001519" + +"chalk@^2.4.2": + "integrity" "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "ansi-styles" "^3.2.1" + "escape-string-regexp" "^1.0.5" + "supports-color" "^5.3.0" + +"chalk@^4.0.0": + "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "ansi-styles" "^4.1.0" + "supports-color" "^7.1.0" + +"char-regex@^1.0.2": + "integrity" "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==" + "resolved" "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz" + "version" "1.0.2" + +"chokidar@^3.4.0", "chokidar@^3.5.3": + "integrity" "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==" + "resolved" "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" + "version" "3.5.3" + 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" optionalDependencies: - fsevents "~2.3.2" - -chrome-trace-event@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" - integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== - -ci-info@^3.2.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91" - integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== - -cjs-module-lexer@^1.0.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" - integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== - -clean-css@^5.2.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.2.tgz#70ecc7d4d4114921f5d298349ff86a31a9975224" - integrity sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww== - dependencies: - source-map "~0.6.0" - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== - dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== - -collect-v8-coverage@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" - integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -colord@^2.9.1: - version "2.9.3" - resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" - integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== - -colorette@^2.0.10, colorette@^2.0.14: - version "2.0.20" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" - integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== - -commander@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" - integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== - -commander@^2.20.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commander@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" - integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== - -commander@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - -commander@^8.3.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" - integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== - -common-path-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" - integrity sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w== - -compressible@~2.0.16: - version "2.0.18" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" - integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== - dependencies: - mime-db ">= 1.43.0 < 2" - -compression@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" - integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== - dependencies: - accepts "~1.3.5" - bytes "3.0.0" - compressible "~2.0.16" - debug "2.6.9" - on-headers "~1.0.2" - safe-buffer "5.1.2" - vary "~1.1.2" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -connect-history-api-fallback@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" - integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== - -content-disposition@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" - integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== - dependencies: - safe-buffer "5.2.1" - -content-type@~1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" - integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== - -convert-source-map@^1.1.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" - integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== - -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== - -cookie@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" - integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== - -core-js-compat@^3.31.0: - version "3.32.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.32.0.tgz#f41574b6893ab15ddb0ac1693681bd56c8550a90" - integrity sha512-7a9a3D1k4UCVKnLhrgALyFcP7YCsLOQIxPd0dKjf/6GuPcgyiGP70ewWdCGrSK7evyhymi0qO4EqCmSJofDeYw== - dependencies: - browserslist "^4.21.9" - -core-js@^2.6.5: - version "2.6.12" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" - integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - -cross-spawn@^7.0.2, cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -css-declaration-sorter@^6.3.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz#28beac7c20bad7f1775be3a7129d7eae409a3a71" - integrity sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g== - -css-loader@^6.8.1: - version "6.8.1" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.8.1.tgz#0f8f52699f60f5e679eab4ec0fcd68b8e8a50a88" - integrity sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g== - dependencies: - icss-utils "^5.1.0" - postcss "^8.4.21" - postcss-modules-extract-imports "^3.0.0" - postcss-modules-local-by-default "^4.0.3" - postcss-modules-scope "^3.0.0" - postcss-modules-values "^4.0.0" - postcss-value-parser "^4.2.0" - semver "^7.3.8" - -css-minimizer-webpack-plugin@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-5.0.1.tgz#33effe662edb1a0bf08ad633c32fa75d0f7ec565" - integrity sha512-3caImjKFQkS+ws1TGcFn0V1HyDJFq1Euy589JlD6/3rV2kj+w7r5G9WDMgSHvpvXHNZ2calVypZWuEDQd9wfLg== + "fsevents" "~2.3.2" + +"chrome-trace-event@^1.0.2": + "integrity" "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" + "resolved" "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz" + "version" "1.0.3" + +"ci-info@^3.2.0": + "integrity" "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==" + "resolved" "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz" + "version" "3.8.0" + +"cjs-module-lexer@^1.0.0": + "integrity" "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" + "resolved" "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz" + "version" "1.2.3" + +"clean-css@^5.2.2": + "integrity" "sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==" + "resolved" "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz" + "version" "5.3.2" + dependencies: + "source-map" "~0.6.0" + +"cliui@^8.0.1": + "integrity" "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==" + "resolved" "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" + "version" "8.0.1" + dependencies: + "string-width" "^4.2.0" + "strip-ansi" "^6.0.1" + "wrap-ansi" "^7.0.0" + +"clone-deep@^4.0.1": + "integrity" "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==" + "resolved" "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz" + "version" "4.0.1" + dependencies: + "is-plain-object" "^2.0.4" + "kind-of" "^6.0.2" + "shallow-clone" "^3.0.0" + +"co@^4.6.0": + "integrity" "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==" + "resolved" "https://registry.npmjs.org/co/-/co-4.6.0.tgz" + "version" "4.6.0" + +"collect-v8-coverage@^1.0.0": + "integrity" "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==" + "resolved" "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz" + "version" "1.0.2" + +"color-convert@^1.9.0": + "integrity" "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==" + "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + "version" "1.9.3" + dependencies: + "color-name" "1.1.3" + +"color-convert@^2.0.1": + "integrity" "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==" + "resolved" "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "color-name" "~1.1.4" + +"color-name@~1.1.4": + "integrity" "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + "version" "1.1.4" + +"color-name@1.1.3": + "integrity" "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + "resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + "version" "1.1.3" + +"colord@^2.9.1": + "integrity" "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" + "resolved" "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz" + "version" "2.9.3" + +"colorette@^2.0.10", "colorette@^2.0.14": + "integrity" "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + "resolved" "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz" + "version" "2.0.20" + +"commander@^10.0.1": + "integrity" "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==" + "resolved" "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz" + "version" "10.0.1" + +"commander@^2.20.0": + "integrity" "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "resolved" "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" + "version" "2.20.3" + +"commander@^4.0.1": + "integrity" "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" + "resolved" "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz" + "version" "4.1.1" + +"commander@^7.2.0": + "integrity" "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + "resolved" "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz" + "version" "7.2.0" + +"commander@^8.3.0": + "integrity" "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" + "resolved" "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz" + "version" "8.3.0" + +"common-path-prefix@^3.0.0": + "integrity" "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==" + "resolved" "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz" + "version" "3.0.0" + +"compressible@~2.0.16": + "integrity" "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==" + "resolved" "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz" + "version" "2.0.18" + dependencies: + "mime-db" ">= 1.43.0 < 2" + +"compression@^1.7.4": + "integrity" "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==" + "resolved" "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz" + "version" "1.7.4" + dependencies: + "accepts" "~1.3.5" + "bytes" "3.0.0" + "compressible" "~2.0.16" + "debug" "2.6.9" + "on-headers" "~1.0.2" + "safe-buffer" "5.1.2" + "vary" "~1.1.2" + +"concat-map@0.0.1": + "integrity" "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "resolved" "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + "version" "0.0.1" + +"connect-history-api-fallback@^2.0.0": + "integrity" "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==" + "resolved" "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz" + "version" "2.0.0" + +"content-disposition@0.5.4": + "integrity" "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==" + "resolved" "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" + "version" "0.5.4" + dependencies: + "safe-buffer" "5.2.1" + +"content-type@~1.0.4": + "integrity" "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" + "resolved" "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz" + "version" "1.0.5" + +"convert-source-map@^1.1.0", "convert-source-map@^1.6.0", "convert-source-map@^1.7.0": + "integrity" "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + "resolved" "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz" + "version" "1.9.0" + +"convert-source-map@^2.0.0": + "integrity" "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + "resolved" "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz" + "version" "2.0.0" + +"cookie-signature@1.0.6": + "integrity" "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "resolved" "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + "version" "1.0.6" + +"cookie@0.5.0": + "integrity" "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" + "resolved" "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz" + "version" "0.5.0" + +"core-js-compat@^3.31.0": + "integrity" "sha512-7a9a3D1k4UCVKnLhrgALyFcP7YCsLOQIxPd0dKjf/6GuPcgyiGP70ewWdCGrSK7evyhymi0qO4EqCmSJofDeYw==" + "resolved" "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.0.tgz" + "version" "3.32.0" + dependencies: + "browserslist" "^4.21.9" + +"core-js@^2.6.5": + "integrity" "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" + "resolved" "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz" + "version" "2.6.12" + +"core-util-is@~1.0.0": + "integrity" "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "resolved" "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" + "version" "1.0.3" + +"cross-spawn@^7.0.2", "cross-spawn@^7.0.3": + "integrity" "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==" + "resolved" "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" + "version" "7.0.3" + dependencies: + "path-key" "^3.1.0" + "shebang-command" "^2.0.0" + "which" "^2.0.1" + +"css-declaration-sorter@^6.3.1": + "integrity" "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==" + "resolved" "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz" + "version" "6.4.1" + +"css-loader@^6.8.1": + "integrity" "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==" + "resolved" "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz" + "version" "6.8.1" + dependencies: + "icss-utils" "^5.1.0" + "postcss" "^8.4.21" + "postcss-modules-extract-imports" "^3.0.0" + "postcss-modules-local-by-default" "^4.0.3" + "postcss-modules-scope" "^3.0.0" + "postcss-modules-values" "^4.0.0" + "postcss-value-parser" "^4.2.0" + "semver" "^7.3.8" + +"css-minimizer-webpack-plugin@^5.0.1": + "integrity" "sha512-3caImjKFQkS+ws1TGcFn0V1HyDJFq1Euy589JlD6/3rV2kj+w7r5G9WDMgSHvpvXHNZ2calVypZWuEDQd9wfLg==" + "resolved" "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-5.0.1.tgz" + "version" "5.0.1" dependencies: "@jridgewell/trace-mapping" "^0.3.18" - cssnano "^6.0.1" - jest-worker "^29.4.3" - postcss "^8.4.24" - schema-utils "^4.0.1" - serialize-javascript "^6.0.1" - -css-select@^4.1.3: - version "4.3.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" - integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== - dependencies: - boolbase "^1.0.0" - css-what "^6.0.1" - domhandler "^4.3.1" - domutils "^2.8.0" - nth-check "^2.0.1" - -css-select@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" - integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== - dependencies: - boolbase "^1.0.0" - css-what "^6.1.0" - domhandler "^5.0.2" - domutils "^3.0.1" - nth-check "^2.0.1" - -css-tree@^2.2.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.3.1.tgz#10264ce1e5442e8572fc82fbe490644ff54b5c20" - integrity sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw== - dependencies: - mdn-data "2.0.30" - source-map-js "^1.0.1" - -css-tree@~2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.2.1.tgz#36115d382d60afd271e377f9c5f67d02bd48c032" - integrity sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA== - dependencies: - mdn-data "2.0.28" - source-map-js "^1.0.1" - -css-what@^6.0.1, css-what@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" - integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== - -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - -cssnano-preset-default@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-6.0.1.tgz#2a93247140d214ddb9f46bc6a3562fa9177fe301" - integrity sha512-7VzyFZ5zEB1+l1nToKyrRkuaJIx0zi/1npjvZfbBwbtNTzhLtlvYraK/7/uqmX2Wb2aQtd983uuGw79jAjLSuQ== - dependencies: - css-declaration-sorter "^6.3.1" - cssnano-utils "^4.0.0" - postcss-calc "^9.0.0" - postcss-colormin "^6.0.0" - postcss-convert-values "^6.0.0" - postcss-discard-comments "^6.0.0" - postcss-discard-duplicates "^6.0.0" - postcss-discard-empty "^6.0.0" - postcss-discard-overridden "^6.0.0" - postcss-merge-longhand "^6.0.0" - postcss-merge-rules "^6.0.1" - postcss-minify-font-values "^6.0.0" - postcss-minify-gradients "^6.0.0" - postcss-minify-params "^6.0.0" - postcss-minify-selectors "^6.0.0" - postcss-normalize-charset "^6.0.0" - postcss-normalize-display-values "^6.0.0" - postcss-normalize-positions "^6.0.0" - postcss-normalize-repeat-style "^6.0.0" - postcss-normalize-string "^6.0.0" - postcss-normalize-timing-functions "^6.0.0" - postcss-normalize-unicode "^6.0.0" - postcss-normalize-url "^6.0.0" - postcss-normalize-whitespace "^6.0.0" - postcss-ordered-values "^6.0.0" - postcss-reduce-initial "^6.0.0" - postcss-reduce-transforms "^6.0.0" - postcss-svgo "^6.0.0" - postcss-unique-selectors "^6.0.0" - -cssnano-utils@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-4.0.0.tgz#d1da885ec04003ab19505ff0e62e029708d36b08" - integrity sha512-Z39TLP+1E0KUcd7LGyF4qMfu8ZufI0rDzhdyAMsa/8UyNUU8wpS0fhdBxbQbv32r64ea00h4878gommRVg2BHw== - -cssnano@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-6.0.1.tgz#87c38c4cd47049c735ab756d7e77ac3ca855c008" - integrity sha512-fVO1JdJ0LSdIGJq68eIxOqFpIJrZqXUsBt8fkrBcztCQqAjQD51OhZp7tc0ImcbwXD4k7ny84QTV90nZhmqbkg== - dependencies: - cssnano-preset-default "^6.0.1" - lilconfig "^2.1.0" - -csso@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/csso/-/csso-5.0.5.tgz#f9b7fe6cc6ac0b7d90781bb16d5e9874303e2ca6" - integrity sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ== - dependencies: - css-tree "~2.2.0" - -debug@2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -dedent@^1.0.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" - integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== - -deep-is@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" - integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== - -deepmerge@^4.2.2: - version "4.3.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" - integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== - -default-gateway@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" - integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== - dependencies: - execa "^5.0.0" - -define-lazy-prop@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" - integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== - -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== - -destroy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" - integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== - -detect-newline@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" - integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== - -detect-node@^2.0.4: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" - integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== - -diff-sequences@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.4.3.tgz#9314bc1fabe09267ffeca9cbafc457d8499a13f2" - integrity sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA== - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -dns-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== - -dns-packet@^5.2.2: - version "5.6.0" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.0.tgz#2202c947845c7a63c23ece58f2f70ff6ab4c2f7d" - integrity sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ== + "cssnano" "^6.0.1" + "jest-worker" "^29.4.3" + "postcss" "^8.4.24" + "schema-utils" "^4.0.1" + "serialize-javascript" "^6.0.1" + +"css-select@^4.1.3": + "integrity" "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==" + "resolved" "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "boolbase" "^1.0.0" + "css-what" "^6.0.1" + "domhandler" "^4.3.1" + "domutils" "^2.8.0" + "nth-check" "^2.0.1" + +"css-select@^5.1.0": + "integrity" "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==" + "resolved" "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "boolbase" "^1.0.0" + "css-what" "^6.1.0" + "domhandler" "^5.0.2" + "domutils" "^3.0.1" + "nth-check" "^2.0.1" + +"css-tree@^2.2.1": + "integrity" "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==" + "resolved" "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz" + "version" "2.3.1" + dependencies: + "mdn-data" "2.0.30" + "source-map-js" "^1.0.1" + +"css-tree@~2.2.0": + "integrity" "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==" + "resolved" "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz" + "version" "2.2.1" + dependencies: + "mdn-data" "2.0.28" + "source-map-js" "^1.0.1" + +"css-what@^6.0.1", "css-what@^6.1.0": + "integrity" "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" + "resolved" "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz" + "version" "6.1.0" + +"cssesc@^3.0.0": + "integrity" "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" + "resolved" "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" + "version" "3.0.0" + +"cssnano-preset-default@^6.0.1": + "integrity" "sha512-7VzyFZ5zEB1+l1nToKyrRkuaJIx0zi/1npjvZfbBwbtNTzhLtlvYraK/7/uqmX2Wb2aQtd983uuGw79jAjLSuQ==" + "resolved" "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "css-declaration-sorter" "^6.3.1" + "cssnano-utils" "^4.0.0" + "postcss-calc" "^9.0.0" + "postcss-colormin" "^6.0.0" + "postcss-convert-values" "^6.0.0" + "postcss-discard-comments" "^6.0.0" + "postcss-discard-duplicates" "^6.0.0" + "postcss-discard-empty" "^6.0.0" + "postcss-discard-overridden" "^6.0.0" + "postcss-merge-longhand" "^6.0.0" + "postcss-merge-rules" "^6.0.1" + "postcss-minify-font-values" "^6.0.0" + "postcss-minify-gradients" "^6.0.0" + "postcss-minify-params" "^6.0.0" + "postcss-minify-selectors" "^6.0.0" + "postcss-normalize-charset" "^6.0.0" + "postcss-normalize-display-values" "^6.0.0" + "postcss-normalize-positions" "^6.0.0" + "postcss-normalize-repeat-style" "^6.0.0" + "postcss-normalize-string" "^6.0.0" + "postcss-normalize-timing-functions" "^6.0.0" + "postcss-normalize-unicode" "^6.0.0" + "postcss-normalize-url" "^6.0.0" + "postcss-normalize-whitespace" "^6.0.0" + "postcss-ordered-values" "^6.0.0" + "postcss-reduce-initial" "^6.0.0" + "postcss-reduce-transforms" "^6.0.0" + "postcss-svgo" "^6.0.0" + "postcss-unique-selectors" "^6.0.0" + +"cssnano-utils@^4.0.0": + "integrity" "sha512-Z39TLP+1E0KUcd7LGyF4qMfu8ZufI0rDzhdyAMsa/8UyNUU8wpS0fhdBxbQbv32r64ea00h4878gommRVg2BHw==" + "resolved" "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.0.tgz" + "version" "4.0.0" + +"cssnano@^6.0.1": + "integrity" "sha512-fVO1JdJ0LSdIGJq68eIxOqFpIJrZqXUsBt8fkrBcztCQqAjQD51OhZp7tc0ImcbwXD4k7ny84QTV90nZhmqbkg==" + "resolved" "https://registry.npmjs.org/cssnano/-/cssnano-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "cssnano-preset-default" "^6.0.1" + "lilconfig" "^2.1.0" + +"csso@^5.0.5": + "integrity" "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==" + "resolved" "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz" + "version" "5.0.5" + dependencies: + "css-tree" "~2.2.0" + +"debug@^4.0.1", "debug@^4.1.0", "debug@^4.1.1", "debug@^4.3.1": + "integrity" "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==" + "resolved" "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" + "version" "4.3.4" + dependencies: + "ms" "2.1.2" + +"debug@2.6.9": + "integrity" "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" + "resolved" "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + "version" "2.6.9" + dependencies: + "ms" "2.0.0" + +"dedent@^1.0.0": + "integrity" "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==" + "resolved" "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz" + "version" "1.5.1" + +"deep-is@^0.1.3": + "integrity" "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + "resolved" "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" + "version" "0.1.4" + +"deepmerge@^4.2.2": + "integrity" "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" + "resolved" "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" + "version" "4.3.1" + +"default-gateway@^6.0.3": + "integrity" "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==" + "resolved" "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz" + "version" "6.0.3" + dependencies: + "execa" "^5.0.0" + +"define-lazy-prop@^2.0.0": + "integrity" "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" + "resolved" "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz" + "version" "2.0.0" + +"depd@~1.1.2": + "integrity" "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" + "resolved" "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" + "version" "1.1.2" + +"depd@2.0.0": + "integrity" "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + "resolved" "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" + "version" "2.0.0" + +"destroy@1.2.0": + "integrity" "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + "resolved" "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz" + "version" "1.2.0" + +"detect-newline@^3.0.0": + "integrity" "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==" + "resolved" "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz" + "version" "3.1.0" + +"detect-node@^2.0.4": + "integrity" "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + "resolved" "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz" + "version" "2.1.0" + +"diff-sequences@^29.4.3": + "integrity" "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==" + "resolved" "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz" + "version" "29.4.3" + +"dir-glob@^3.0.1": + "integrity" "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==" + "resolved" "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "path-type" "^4.0.0" + +"dns-equal@^1.0.0": + "integrity" "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" + "resolved" "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz" + "version" "1.0.0" + +"dns-packet@^5.2.2": + "integrity" "sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ==" + "resolved" "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.0.tgz" + "version" "5.6.0" dependencies: "@leichtgewicht/ip-codec" "^2.0.1" -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -dom-converter@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" - integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== - dependencies: - utila "~0.4" - -dom-serializer@^1.0.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" - integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.2.0" - entities "^2.0.0" - -dom-serializer@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" - integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== - dependencies: - domelementtype "^2.3.0" - domhandler "^5.0.2" - entities "^4.2.0" - -domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" - integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== - -domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" - integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== - dependencies: - domelementtype "^2.2.0" - -domhandler@^5.0.2, domhandler@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" - integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== - dependencies: - domelementtype "^2.3.0" - -domutils@^2.5.2, domutils@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" - integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== - dependencies: - dom-serializer "^1.0.1" - domelementtype "^2.2.0" - domhandler "^4.2.0" - -domutils@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" - integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== - dependencies: - dom-serializer "^2.0.0" - domelementtype "^2.3.0" - domhandler "^5.0.3" - -dot-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" - integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== - -electron-to-chromium@^1.4.477: - version "1.4.490" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.490.tgz#d99286f6e915667fa18ea4554def1aa60eb4d5f1" - integrity sha512-6s7NVJz+sATdYnIwhdshx/N/9O6rvMxmhVoDSDFdj6iA45gHR8EQje70+RYsF4GeB+k0IeNSBnP7yG9ZXJFr7A== - -emittery@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" - integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emojis-list@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" - integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== - -enhanced-resolve@^5.15.0: - version "5.15.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35" - integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg== - dependencies: - graceful-fs "^4.2.4" - tapable "^2.2.0" - -enquirer@^2.3.5: - version "2.4.1" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.4.1.tgz#93334b3fbd74fc7097b224ab4a8fb7e40bf4ae56" - integrity sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ== - dependencies: - ansi-colors "^4.1.1" - strip-ansi "^6.0.1" - -entities@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" - integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== - -entities@^4.2.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" - integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== - -envinfo@^7.7.3: - version "7.10.0" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.10.0.tgz#55146e3909cc5fe63c22da63fb15b05aeac35b13" - integrity sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-module-lexer@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.3.0.tgz#6be9c9e0b4543a60cd166ff6f8b4e9dae0b0c16f" - integrity sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA== - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-scope@5.1.1, eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-utils@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" - integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== - dependencies: - eslint-visitor-keys "^1.1.0" - -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" - integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== - -eslint-visitor-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" - integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== - -eslint@^7.32.0: - version "7.32.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" - integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== +"doctrine@^3.0.0": + "integrity" "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==" + "resolved" "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "esutils" "^2.0.2" + +"dom-converter@^0.2.0": + "integrity" "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==" + "resolved" "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz" + "version" "0.2.0" + dependencies: + "utila" "~0.4" + +"dom-serializer@^1.0.1": + "integrity" "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==" + "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz" + "version" "1.4.1" + dependencies: + "domelementtype" "^2.0.1" + "domhandler" "^4.2.0" + "entities" "^2.0.0" + +"dom-serializer@^2.0.0": + "integrity" "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==" + "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "domelementtype" "^2.3.0" + "domhandler" "^5.0.2" + "entities" "^4.2.0" + +"domelementtype@^2.0.1", "domelementtype@^2.2.0", "domelementtype@^2.3.0": + "integrity" "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + "resolved" "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz" + "version" "2.3.0" + +"domhandler@^4.0.0", "domhandler@^4.2.0", "domhandler@^4.3.1": + "integrity" "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==" + "resolved" "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz" + "version" "4.3.1" + dependencies: + "domelementtype" "^2.2.0" + +"domhandler@^5.0.2", "domhandler@^5.0.3": + "integrity" "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==" + "resolved" "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz" + "version" "5.0.3" + dependencies: + "domelementtype" "^2.3.0" + +"domutils@^2.5.2", "domutils@^2.8.0": + "integrity" "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==" + "resolved" "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz" + "version" "2.8.0" + dependencies: + "dom-serializer" "^1.0.1" + "domelementtype" "^2.2.0" + "domhandler" "^4.2.0" + +"domutils@^3.0.1": + "integrity" "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==" + "resolved" "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "dom-serializer" "^2.0.0" + "domelementtype" "^2.3.0" + "domhandler" "^5.0.3" + +"dot-case@^3.0.4": + "integrity" "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==" + "resolved" "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "no-case" "^3.0.4" + "tslib" "^2.0.3" + +"ee-first@1.1.1": + "integrity" "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "resolved" "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + "version" "1.1.1" + +"electron-to-chromium@^1.4.477": + "integrity" "sha512-6s7NVJz+sATdYnIwhdshx/N/9O6rvMxmhVoDSDFdj6iA45gHR8EQje70+RYsF4GeB+k0IeNSBnP7yG9ZXJFr7A==" + "resolved" "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.490.tgz" + "version" "1.4.490" + +"emittery@^0.13.1": + "integrity" "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==" + "resolved" "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz" + "version" "0.13.1" + +"emoji-regex@^8.0.0": + "integrity" "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "resolved" "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + "version" "8.0.0" + +"emojis-list@^3.0.0": + "integrity" "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + "resolved" "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz" + "version" "3.0.0" + +"encodeurl@~1.0.2": + "integrity" "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + "resolved" "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" + "version" "1.0.2" + +"enhanced-resolve@^5.15.0": + "integrity" "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==" + "resolved" "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz" + "version" "5.15.0" + dependencies: + "graceful-fs" "^4.2.4" + "tapable" "^2.2.0" + +"enquirer@^2.3.5": + "integrity" "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==" + "resolved" "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz" + "version" "2.4.1" + dependencies: + "ansi-colors" "^4.1.1" + "strip-ansi" "^6.0.1" + +"entities@^2.0.0": + "integrity" "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + "resolved" "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz" + "version" "2.2.0" + +"entities@^4.2.0": + "integrity" "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" + "resolved" "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz" + "version" "4.5.0" + +"envinfo@^7.7.3": + "integrity" "sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==" + "resolved" "https://registry.npmjs.org/envinfo/-/envinfo-7.10.0.tgz" + "version" "7.10.0" + +"error-ex@^1.3.1": + "integrity" "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==" + "resolved" "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" + "version" "1.3.2" + dependencies: + "is-arrayish" "^0.2.1" + +"es-module-lexer@^1.2.1": + "integrity" "sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==" + "resolved" "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz" + "version" "1.3.0" + +"escalade@^3.1.1": + "integrity" "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + "resolved" "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" + "version" "3.1.1" + +"escape-html@~1.0.3": + "integrity" "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "resolved" "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + "version" "1.0.3" + +"escape-string-regexp@^1.0.5": + "integrity" "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + "version" "1.0.5" + +"escape-string-regexp@^2.0.0": + "integrity" "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz" + "version" "2.0.0" + +"escape-string-regexp@^4.0.0": + "integrity" "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + "resolved" "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + "version" "4.0.0" + +"eslint-scope@^5.1.1", "eslint-scope@5.1.1": + "integrity" "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==" + "resolved" "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "esrecurse" "^4.3.0" + "estraverse" "^4.1.1" + +"eslint-utils@^2.1.0": + "integrity" "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==" + "resolved" "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "eslint-visitor-keys" "^1.1.0" + +"eslint-utils@^3.0.0": + "integrity" "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==" + "resolved" "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "eslint-visitor-keys" "^2.0.0" + +"eslint-visitor-keys@^1.0.0": + "integrity" "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" + "resolved" "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz" + "version" "1.3.0" + +"eslint-visitor-keys@^1.1.0": + "integrity" "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" + "resolved" "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz" + "version" "1.3.0" + +"eslint-visitor-keys@^1.3.0": + "integrity" "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" + "resolved" "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz" + "version" "1.3.0" + +"eslint-visitor-keys@^2.0.0": + "integrity" "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==" + "resolved" "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz" + "version" "2.1.0" + +"eslint@*", "eslint@^5.0.0 || ^6.0.0 || ^7.0.0", "eslint@^7.32.0", "eslint@>= 4.12.1", "eslint@>=5": + "integrity" "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==" + "resolved" "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz" + "version" "7.32.0" 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" - -espree@^7.3.0, espree@^7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" - integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== - dependencies: - acorn "^7.4.0" - acorn-jsx "^5.3.1" - eslint-visitor-keys "^1.3.0" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.4.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" - integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== - -eventemitter3@^4.0.0: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -events@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - -exit@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== - -expect@^29.0.0, expect@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.6.2.tgz#7b08e83eba18ddc4a2cf62b5f2d1918f5cd84521" - integrity sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA== + "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" + +"espree@^7.3.0", "espree@^7.3.1": + "integrity" "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==" + "resolved" "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz" + "version" "7.3.1" + dependencies: + "acorn" "^7.4.0" + "acorn-jsx" "^5.3.1" + "eslint-visitor-keys" "^1.3.0" + +"esprima@^4.0.0": + "integrity" "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "resolved" "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" + "version" "4.0.1" + +"esquery@^1.4.0": + "integrity" "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==" + "resolved" "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz" + "version" "1.5.0" + dependencies: + "estraverse" "^5.1.0" + +"esrecurse@^4.3.0": + "integrity" "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==" + "resolved" "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" + "version" "4.3.0" + dependencies: + "estraverse" "^5.2.0" + +"estraverse@^4.1.1": + "integrity" "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" + "version" "4.3.0" + +"estraverse@^5.1.0": + "integrity" "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" + "version" "5.3.0" + +"estraverse@^5.2.0": + "integrity" "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" + "version" "5.3.0" + +"esutils@^2.0.2": + "integrity" "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + "resolved" "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + "version" "2.0.3" + +"etag@~1.8.1": + "integrity" "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + "resolved" "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" + "version" "1.8.1" + +"eventemitter3@^4.0.0": + "integrity" "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + "resolved" "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" + "version" "4.0.7" + +"events@^3.2.0": + "integrity" "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + "resolved" "https://registry.npmjs.org/events/-/events-3.3.0.tgz" + "version" "3.3.0" + +"execa@^5.0.0": + "integrity" "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==" + "resolved" "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "cross-spawn" "^7.0.3" + "get-stream" "^6.0.0" + "human-signals" "^2.1.0" + "is-stream" "^2.0.0" + "merge-stream" "^2.0.0" + "npm-run-path" "^4.0.1" + "onetime" "^5.1.2" + "signal-exit" "^3.0.3" + "strip-final-newline" "^2.0.0" + +"exit@^0.1.2": + "integrity" "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==" + "resolved" "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" + "version" "0.1.2" + +"expect@^29.0.0", "expect@^29.6.2": + "integrity" "sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA==" + "resolved" "https://registry.npmjs.org/expect/-/expect-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/expect-utils" "^29.6.2" "@types/node" "*" - jest-get-type "^29.4.3" - jest-matcher-utils "^29.6.2" - jest-message-util "^29.6.2" - jest-util "^29.6.2" - -express@^4.17.3: - version "4.18.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" - integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== - dependencies: - accepts "~1.3.8" - array-flatten "1.1.1" - body-parser "1.20.1" - content-disposition "0.5.4" - content-type "~1.0.4" - cookie "0.5.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "2.0.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "1.2.0" - fresh "0.5.2" - http-errors "2.0.0" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "2.4.1" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.7" - qs "6.11.0" - range-parser "~1.2.1" - safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" - setprototypeof "1.2.0" - statuses "2.0.1" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.2.9: - version "3.3.1" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" - integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== + "jest-get-type" "^29.4.3" + "jest-matcher-utils" "^29.6.2" + "jest-message-util" "^29.6.2" + "jest-util" "^29.6.2" + +"express@^4.17.3": + "integrity" "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==" + "resolved" "https://registry.npmjs.org/express/-/express-4.18.2.tgz" + "version" "4.18.2" + dependencies: + "accepts" "~1.3.8" + "array-flatten" "1.1.1" + "body-parser" "1.20.1" + "content-disposition" "0.5.4" + "content-type" "~1.0.4" + "cookie" "0.5.0" + "cookie-signature" "1.0.6" + "debug" "2.6.9" + "depd" "2.0.0" + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "etag" "~1.8.1" + "finalhandler" "1.2.0" + "fresh" "0.5.2" + "http-errors" "2.0.0" + "merge-descriptors" "1.0.1" + "methods" "~1.1.2" + "on-finished" "2.4.1" + "parseurl" "~1.3.3" + "path-to-regexp" "0.1.7" + "proxy-addr" "~2.0.7" + "qs" "6.11.0" + "range-parser" "~1.2.1" + "safe-buffer" "5.2.1" + "send" "0.18.0" + "serve-static" "1.15.0" + "setprototypeof" "1.2.0" + "statuses" "2.0.1" + "type-is" "~1.6.18" + "utils-merge" "1.0.1" + "vary" "~1.1.2" + +"fast-deep-equal@^3.1.1", "fast-deep-equal@^3.1.3": + "integrity" "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "resolved" "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + "version" "3.1.3" + +"fast-glob@^3.2.9": + "integrity" "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==" + "resolved" "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz" + "version" "3.3.1" 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" - -fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== - -fastest-levenshtein@^1.0.12: - version "1.0.16" - resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" - integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== - -fastq@^1.6.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" - integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== - dependencies: - reusify "^1.0.4" - -faye-websocket@^0.11.3: - version "0.11.4" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" - integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== - dependencies: - websocket-driver ">=0.5.1" - -fb-watchman@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" - integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== - dependencies: - bser "2.1.1" - -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== - dependencies: - flat-cache "^3.0.4" - -file-loader@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" - integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== - dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "2.4.1" - parseurl "~1.3.3" - statuses "2.0.1" - unpipe "~1.0.0" - -find-cache-dir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-4.0.0.tgz#a30ee0448f81a3990708f6453633c733e2f6eec2" - integrity sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg== - dependencies: - common-path-prefix "^3.0.0" - pkg-dir "^7.0.0" - -find-up@^4.0.0, find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-6.3.0.tgz#2abab3d3280b2dc7ac10199ef324c4e002c8c790" - integrity sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw== - dependencies: - locate-path "^7.1.0" - path-exists "^5.0.0" - -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== - dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" - -flatted@^3.1.0: - version "3.2.7" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" - integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== - -follow-redirects@^1.0.0: - version "1.15.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== - -forwarded@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== - -fs-monkey@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.4.tgz#ee8c1b53d3fe8bb7e5d2c5c5dfc0168afdd2f747" - integrity sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ== - -fs-readdir-recursive@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" - integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@^2.3.2, fsevents@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-intrinsic@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" - integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-proto "^1.0.1" - has-symbols "^1.0.3" - -get-package-type@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -glob-parent@^5.1.2, glob-parent@~5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob-to-regexp@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" - integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== - -glob@^7.1.3, glob@^7.1.4, glob@^7.2.0: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^13.6.0, globals@^13.9.0: - version "13.20.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" - integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== - dependencies: - type-fest "^0.20.2" - -globby@^11.0.3: - version "11.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" - integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.2.9" - ignore "^5.2.0" - merge2 "^1.4.1" - slash "^3.0.0" - -graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -handle-thing@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" - integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== - -has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -he@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -hpack.js@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" - integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== - dependencies: - inherits "^2.0.1" - obuf "^1.0.0" - readable-stream "^2.0.1" - wbuf "^1.1.0" - -html-entities@^2.3.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.4.0.tgz#edd0cee70402584c8c76cc2c0556db09d1f45061" - integrity sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ== - -html-escaper@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" - integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== - -html-minifier-terser@^6.0.2: - version "6.1.0" - resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" - integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== - dependencies: - camel-case "^4.1.2" - clean-css "^5.2.2" - commander "^8.3.0" - he "^1.2.0" - param-case "^3.0.4" - relateurl "^0.2.7" - terser "^5.10.0" - -html-webpack-plugin@^5.5.3: - version "5.5.3" - resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.3.tgz#72270f4a78e222b5825b296e5e3e1328ad525a3e" - integrity sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg== + "glob-parent" "^5.1.2" + "merge2" "^1.3.0" + "micromatch" "^4.0.4" + +"fast-json-stable-stringify@^2.0.0", "fast-json-stable-stringify@^2.1.0": + "integrity" "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "resolved" "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" + "version" "2.1.0" + +"fast-levenshtein@^2.0.6": + "integrity" "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + "resolved" "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" + "version" "2.0.6" + +"fastest-levenshtein@^1.0.12": + "integrity" "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==" + "resolved" "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz" + "version" "1.0.16" + +"fastq@^1.6.0": + "integrity" "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==" + "resolved" "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz" + "version" "1.15.0" + dependencies: + "reusify" "^1.0.4" + +"faye-websocket@^0.11.3": + "integrity" "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==" + "resolved" "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz" + "version" "0.11.4" + dependencies: + "websocket-driver" ">=0.5.1" + +"fb-watchman@^2.0.0": + "integrity" "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==" + "resolved" "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "bser" "2.1.1" + +"file-entry-cache@^6.0.1": + "integrity" "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==" + "resolved" "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "flat-cache" "^3.0.4" + +"file-loader@*", "file-loader@^6.2.0": + "integrity" "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==" + "resolved" "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz" + "version" "6.2.0" + dependencies: + "loader-utils" "^2.0.0" + "schema-utils" "^3.0.0" + +"fill-range@^7.0.1": + "integrity" "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==" + "resolved" "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" + "version" "7.0.1" + dependencies: + "to-regex-range" "^5.0.1" + +"finalhandler@1.2.0": + "integrity" "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==" + "resolved" "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "debug" "2.6.9" + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "on-finished" "2.4.1" + "parseurl" "~1.3.3" + "statuses" "2.0.1" + "unpipe" "~1.0.0" + +"find-cache-dir@^4.0.0": + "integrity" "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==" + "resolved" "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "common-path-prefix" "^3.0.0" + "pkg-dir" "^7.0.0" + +"find-up@^4.0.0", "find-up@^4.1.0": + "integrity" "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==" + "resolved" "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "locate-path" "^5.0.0" + "path-exists" "^4.0.0" + +"find-up@^6.3.0": + "integrity" "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==" + "resolved" "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz" + "version" "6.3.0" + dependencies: + "locate-path" "^7.1.0" + "path-exists" "^5.0.0" + +"flat-cache@^3.0.4": + "integrity" "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==" + "resolved" "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "flatted" "^3.1.0" + "rimraf" "^3.0.2" + +"flatted@^3.1.0": + "integrity" "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" + "resolved" "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz" + "version" "3.2.7" + +"follow-redirects@^1.0.0": + "integrity" "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + "resolved" "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz" + "version" "1.15.2" + +"forwarded@0.2.0": + "integrity" "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + "resolved" "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" + "version" "0.2.0" + +"fresh@0.5.2": + "integrity" "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + "resolved" "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" + "version" "0.5.2" + +"fs-monkey@^1.0.4": + "integrity" "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==" + "resolved" "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz" + "version" "1.0.4" + +"fs-readdir-recursive@^1.1.0": + "integrity" "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==" + "resolved" "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz" + "version" "1.1.0" + +"fs.realpath@^1.0.0": + "integrity" "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "resolved" "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + "version" "1.0.0" + +"function-bind@^1.1.1": + "integrity" "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "resolved" "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" + "version" "1.1.1" + +"functional-red-black-tree@^1.0.1": + "integrity" "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==" + "resolved" "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" + "version" "1.0.1" + +"gensync@^1.0.0-beta.2": + "integrity" "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + "resolved" "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" + "version" "1.0.0-beta.2" + +"get-caller-file@^2.0.5": + "integrity" "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + "resolved" "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" + "version" "2.0.5" + +"get-intrinsic@^1.0.2": + "integrity" "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==" + "resolved" "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz" + "version" "1.2.1" + dependencies: + "function-bind" "^1.1.1" + "has" "^1.0.3" + "has-proto" "^1.0.1" + "has-symbols" "^1.0.3" + +"get-package-type@^0.1.0": + "integrity" "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==" + "resolved" "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" + "version" "0.1.0" + +"get-stream@^6.0.0": + "integrity" "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + "resolved" "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" + "version" "6.0.1" + +"glob-parent@^5.1.2", "glob-parent@~5.1.2": + "integrity" "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==" + "resolved" "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + "version" "5.1.2" + dependencies: + "is-glob" "^4.0.1" + +"glob-to-regexp@^0.4.1": + "integrity" "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + "resolved" "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz" + "version" "0.4.1" + +"glob@^7.1.3", "glob@^7.1.4", "glob@^7.2.0": + "integrity" "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==" + "resolved" "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" + "version" "7.2.3" + dependencies: + "fs.realpath" "^1.0.0" + "inflight" "^1.0.4" + "inherits" "2" + "minimatch" "^3.1.1" + "once" "^1.3.0" + "path-is-absolute" "^1.0.0" + +"globals@^11.1.0": + "integrity" "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + "resolved" "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + "version" "11.12.0" + +"globals@^13.6.0": + "integrity" "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==" + "resolved" "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz" + "version" "13.20.0" + dependencies: + "type-fest" "^0.20.2" + +"globals@^13.9.0": + "integrity" "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==" + "resolved" "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz" + "version" "13.20.0" + dependencies: + "type-fest" "^0.20.2" + +"globby@^11.0.3": + "integrity" "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==" + "resolved" "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" + "version" "11.1.0" + dependencies: + "array-union" "^2.1.0" + "dir-glob" "^3.0.1" + "fast-glob" "^3.2.9" + "ignore" "^5.2.0" + "merge2" "^1.4.1" + "slash" "^3.0.0" + +"graceful-fs@^4.1.2", "graceful-fs@^4.2.4", "graceful-fs@^4.2.6", "graceful-fs@^4.2.9": + "integrity" "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "resolved" "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" + "version" "4.2.11" + +"handle-thing@^2.0.0": + "integrity" "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + "resolved" "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz" + "version" "2.0.1" + +"has-flag@^3.0.0": + "integrity" "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" + "version" "3.0.0" + +"has-flag@^4.0.0": + "integrity" "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "resolved" "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + "version" "4.0.0" + +"has-proto@^1.0.1": + "integrity" "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" + "resolved" "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz" + "version" "1.0.1" + +"has-symbols@^1.0.3": + "integrity" "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + "resolved" "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" + "version" "1.0.3" + +"has@^1.0.3": + "integrity" "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==" + "resolved" "https://registry.npmjs.org/has/-/has-1.0.3.tgz" + "version" "1.0.3" + dependencies: + "function-bind" "^1.1.1" + +"he@^1.2.0": + "integrity" "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + "resolved" "https://registry.npmjs.org/he/-/he-1.2.0.tgz" + "version" "1.2.0" + +"hpack.js@^2.1.6": + "integrity" "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==" + "resolved" "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz" + "version" "2.1.6" + dependencies: + "inherits" "^2.0.1" + "obuf" "^1.0.0" + "readable-stream" "^2.0.1" + "wbuf" "^1.1.0" + +"html-entities@^2.3.2": + "integrity" "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==" + "resolved" "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz" + "version" "2.4.0" + +"html-escaper@^2.0.0": + "integrity" "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" + "resolved" "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz" + "version" "2.0.2" + +"html-minifier-terser@^6.0.2": + "integrity" "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==" + "resolved" "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "camel-case" "^4.1.2" + "clean-css" "^5.2.2" + "commander" "^8.3.0" + "he" "^1.2.0" + "param-case" "^3.0.4" + "relateurl" "^0.2.7" + "terser" "^5.10.0" + +"html-webpack-plugin@^5.5.3": + "integrity" "sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg==" + "resolved" "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.3.tgz" + "version" "5.5.3" dependencies: "@types/html-minifier-terser" "^6.0.0" - html-minifier-terser "^6.0.2" - lodash "^4.17.21" - pretty-error "^4.0.0" - tapable "^2.0.0" - -htmlparser2@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" - integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== - dependencies: - domelementtype "^2.0.1" - domhandler "^4.0.0" - domutils "^2.5.2" - entities "^2.0.0" - -http-deceiver@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" - integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== - -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" - -http-errors@~1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - -http-parser-js@>=0.5.1: - version "0.5.8" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" - integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== - -http-proxy-middleware@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" - integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== + "html-minifier-terser" "^6.0.2" + "lodash" "^4.17.21" + "pretty-error" "^4.0.0" + "tapable" "^2.0.0" + +"htmlparser2@^6.1.0": + "integrity" "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==" + "resolved" "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz" + "version" "6.1.0" + dependencies: + "domelementtype" "^2.0.1" + "domhandler" "^4.0.0" + "domutils" "^2.5.2" + "entities" "^2.0.0" + +"http-deceiver@^1.2.7": + "integrity" "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" + "resolved" "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" + "version" "1.2.7" + +"http-errors@~1.6.2": + "integrity" "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==" + "resolved" "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz" + "version" "1.6.3" + dependencies: + "depd" "~1.1.2" + "inherits" "2.0.3" + "setprototypeof" "1.1.0" + "statuses" ">= 1.4.0 < 2" + +"http-errors@2.0.0": + "integrity" "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==" + "resolved" "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "depd" "2.0.0" + "inherits" "2.0.4" + "setprototypeof" "1.2.0" + "statuses" "2.0.1" + "toidentifier" "1.0.1" + +"http-parser-js@>=0.5.1": + "integrity" "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + "resolved" "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz" + "version" "0.5.8" + +"http-proxy-middleware@^2.0.3": + "integrity" "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==" + "resolved" "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz" + "version" "2.0.6" dependencies: "@types/http-proxy" "^1.17.8" - http-proxy "^1.18.1" - is-glob "^4.0.1" - is-plain-obj "^3.0.0" - micromatch "^4.0.2" - -http-proxy@^1.18.1: - version "1.18.1" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -icss-utils@^5.0.0, icss-utils@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" - integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== - -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - -ignore@^5.1.8, ignore@^5.2.0: - version "5.2.4" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" - integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== - -import-fresh@^3.0.0, import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-local@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" - integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== - -interpret@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" - integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== - -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -ipaddr.js@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f" - integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ== - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-core-module@^2.13.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" - integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== - dependencies: - has "^1.0.3" - -is-docker@^2.0.0, is-docker@^2.1.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-fn@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" - integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-obj@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" - integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== - -is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-wsl@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== - dependencies: - is-docker "^2.0.0" - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== - -istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" - integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== - -istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" - integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + "http-proxy" "^1.18.1" + "is-glob" "^4.0.1" + "is-plain-obj" "^3.0.0" + "micromatch" "^4.0.2" + +"http-proxy@^1.18.1": + "integrity" "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==" + "resolved" "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz" + "version" "1.18.1" + dependencies: + "eventemitter3" "^4.0.0" + "follow-redirects" "^1.0.0" + "requires-port" "^1.0.0" + +"human-signals@^2.1.0": + "integrity" "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" + "resolved" "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" + "version" "2.1.0" + +"iconv-lite@0.4.24": + "integrity" "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==" + "resolved" "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" + "version" "0.4.24" + dependencies: + "safer-buffer" ">= 2.1.2 < 3" + +"icss-utils@^5.0.0", "icss-utils@^5.1.0": + "integrity" "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==" + "resolved" "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz" + "version" "5.1.0" + +"ignore@^4.0.6": + "integrity" "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + "resolved" "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz" + "version" "4.0.6" + +"ignore@^5.1.8", "ignore@^5.2.0": + "integrity" "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==" + "resolved" "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz" + "version" "5.2.4" + +"import-fresh@^3.0.0", "import-fresh@^3.2.1": + "integrity" "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==" + "resolved" "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" + "version" "3.3.0" + dependencies: + "parent-module" "^1.0.0" + "resolve-from" "^4.0.0" + +"import-local@^3.0.2": + "integrity" "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==" + "resolved" "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "pkg-dir" "^4.2.0" + "resolve-cwd" "^3.0.0" + +"imurmurhash@^0.1.4": + "integrity" "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" + "resolved" "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + "version" "0.1.4" + +"inflight@^1.0.4": + "integrity" "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==" + "resolved" "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + "version" "1.0.6" + dependencies: + "once" "^1.3.0" + "wrappy" "1" + +"inherits@^2.0.1", "inherits@^2.0.3", "inherits@~2.0.3", "inherits@2", "inherits@2.0.4": + "integrity" "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + "version" "2.0.4" + +"inherits@2.0.3": + "integrity" "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + "resolved" "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + "version" "2.0.3" + +"interpret@^3.1.1": + "integrity" "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==" + "resolved" "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz" + "version" "3.1.1" + +"ipaddr.js@^2.0.1": + "integrity" "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==" + "resolved" "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz" + "version" "2.1.0" + +"ipaddr.js@1.9.1": + "integrity" "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + "resolved" "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" + "version" "1.9.1" + +"is-arrayish@^0.2.1": + "integrity" "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + "resolved" "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + "version" "0.2.1" + +"is-binary-path@~2.1.0": + "integrity" "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==" + "resolved" "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "binary-extensions" "^2.0.0" + +"is-core-module@^2.13.0": + "integrity" "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==" + "resolved" "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz" + "version" "2.13.0" + dependencies: + "has" "^1.0.3" + +"is-docker@^2.0.0", "is-docker@^2.1.1": + "integrity" "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + "resolved" "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz" + "version" "2.2.1" + +"is-extglob@^2.1.1": + "integrity" "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + "resolved" "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + "version" "2.1.1" + +"is-fullwidth-code-point@^3.0.0": + "integrity" "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "resolved" "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + "version" "3.0.0" + +"is-generator-fn@^2.0.0": + "integrity" "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==" + "resolved" "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz" + "version" "2.1.0" + +"is-glob@^4.0.0", "is-glob@^4.0.1", "is-glob@~4.0.1": + "integrity" "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==" + "resolved" "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + "version" "4.0.3" + dependencies: + "is-extglob" "^2.1.1" + +"is-number@^7.0.0": + "integrity" "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + "resolved" "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + "version" "7.0.0" + +"is-plain-obj@^3.0.0": + "integrity" "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==" + "resolved" "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz" + "version" "3.0.0" + +"is-plain-object@^2.0.4": + "integrity" "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==" + "resolved" "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" + "version" "2.0.4" + dependencies: + "isobject" "^3.0.1" + +"is-stream@^2.0.0": + "integrity" "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + "resolved" "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" + "version" "2.0.1" + +"is-wsl@^2.2.0": + "integrity" "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==" + "resolved" "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "is-docker" "^2.0.0" + +"isarray@~1.0.0": + "integrity" "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "resolved" "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + "version" "1.0.0" + +"isexe@^2.0.0": + "integrity" "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "resolved" "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + "version" "2.0.0" + +"isobject@^3.0.1": + "integrity" "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" + "resolved" "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" + "version" "3.0.1" + +"istanbul-lib-coverage@^3.0.0", "istanbul-lib-coverage@^3.2.0": + "integrity" "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==" + "resolved" "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz" + "version" "3.2.0" + +"istanbul-lib-instrument@^5.0.4", "istanbul-lib-instrument@^5.1.0": + "integrity" "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==" + "resolved" "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz" + "version" "5.2.1" dependencies: "@babel/core" "^7.12.3" "@babel/parser" "^7.14.7" "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.2.0" - semver "^6.3.0" + "istanbul-lib-coverage" "^3.2.0" + "semver" "^6.3.0" -istanbul-lib-report@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" - integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== +"istanbul-lib-report@^3.0.0": + "integrity" "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==" + "resolved" "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz" + "version" "3.0.1" dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^4.0.0" - supports-color "^7.1.0" + "istanbul-lib-coverage" "^3.0.0" + "make-dir" "^4.0.0" + "supports-color" "^7.1.0" -istanbul-lib-source-maps@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" - integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== +"istanbul-lib-source-maps@^4.0.0": + "integrity" "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==" + "resolved" "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz" + "version" "4.0.1" dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" + "debug" "^4.1.1" + "istanbul-lib-coverage" "^3.0.0" + "source-map" "^0.6.1" -istanbul-reports@^3.1.3: - version "3.1.6" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a" - integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg== +"istanbul-reports@^3.1.3": + "integrity" "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==" + "resolved" "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz" + "version" "3.1.6" dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" + "html-escaper" "^2.0.0" + "istanbul-lib-report" "^3.0.0" -jest-changed-files@^29.5.0: - version "29.5.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.5.0.tgz#e88786dca8bf2aa899ec4af7644e16d9dcf9b23e" - integrity sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag== +"jest-changed-files@^29.5.0": + "integrity" "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==" + "resolved" "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz" + "version" "29.5.0" dependencies: - execa "^5.0.0" - p-limit "^3.1.0" + "execa" "^5.0.0" + "p-limit" "^3.1.0" -jest-circus@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.6.2.tgz#1e6ffca60151ac66cad63fce34f443f6b5bb4258" - integrity sha512-G9mN+KOYIUe2sB9kpJkO9Bk18J4dTDArNFPwoZ7WKHKel55eKIS/u2bLthxgojwlf9NLCVQfgzM/WsOVvoC6Fw== +"jest-circus@^29.6.2": + "integrity" "sha512-G9mN+KOYIUe2sB9kpJkO9Bk18J4dTDArNFPwoZ7WKHKel55eKIS/u2bLthxgojwlf9NLCVQfgzM/WsOVvoC6Fw==" + "resolved" "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/environment" "^29.6.2" "@jest/expect" "^29.6.2" "@jest/test-result" "^29.6.2" "@jest/types" "^29.6.1" "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - dedent "^1.0.0" - is-generator-fn "^2.0.0" - jest-each "^29.6.2" - jest-matcher-utils "^29.6.2" - jest-message-util "^29.6.2" - jest-runtime "^29.6.2" - jest-snapshot "^29.6.2" - jest-util "^29.6.2" - p-limit "^3.1.0" - pretty-format "^29.6.2" - pure-rand "^6.0.0" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-cli@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.6.2.tgz#edb381763398d1a292cd1b636a98bfa5644b8fda" - integrity sha512-TT6O247v6dCEX2UGHGyflMpxhnrL0DNqP2fRTKYm3nJJpCTfXX3GCMQPGFjXDoj0i5/Blp3jriKXFgdfmbYB6Q== + "chalk" "^4.0.0" + "co" "^4.6.0" + "dedent" "^1.0.0" + "is-generator-fn" "^2.0.0" + "jest-each" "^29.6.2" + "jest-matcher-utils" "^29.6.2" + "jest-message-util" "^29.6.2" + "jest-runtime" "^29.6.2" + "jest-snapshot" "^29.6.2" + "jest-util" "^29.6.2" + "p-limit" "^3.1.0" + "pretty-format" "^29.6.2" + "pure-rand" "^6.0.0" + "slash" "^3.0.0" + "stack-utils" "^2.0.3" + +"jest-cli@^29.6.2": + "integrity" "sha512-TT6O247v6dCEX2UGHGyflMpxhnrL0DNqP2fRTKYm3nJJpCTfXX3GCMQPGFjXDoj0i5/Blp3jriKXFgdfmbYB6Q==" + "resolved" "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/core" "^29.6.2" "@jest/test-result" "^29.6.2" "@jest/types" "^29.6.1" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - import-local "^3.0.2" - jest-config "^29.6.2" - jest-util "^29.6.2" - jest-validate "^29.6.2" - prompts "^2.0.1" - yargs "^17.3.1" - -jest-config@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.6.2.tgz#c68723f06b31ca5e63030686e604727d406cd7c3" - integrity sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw== + "chalk" "^4.0.0" + "exit" "^0.1.2" + "graceful-fs" "^4.2.9" + "import-local" "^3.0.2" + "jest-config" "^29.6.2" + "jest-util" "^29.6.2" + "jest-validate" "^29.6.2" + "prompts" "^2.0.1" + "yargs" "^17.3.1" + +"jest-config@^29.6.2": + "integrity" "sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw==" + "resolved" "https://registry.npmjs.org/jest-config/-/jest-config-29.6.2.tgz" + "version" "29.6.2" dependencies: "@babel/core" "^7.11.6" "@jest/test-sequencer" "^29.6.2" "@jest/types" "^29.6.1" - babel-jest "^29.6.2" - chalk "^4.0.0" - ci-info "^3.2.0" - deepmerge "^4.2.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-circus "^29.6.2" - jest-environment-node "^29.6.2" - jest-get-type "^29.4.3" - jest-regex-util "^29.4.3" - jest-resolve "^29.6.2" - jest-runner "^29.6.2" - jest-util "^29.6.2" - jest-validate "^29.6.2" - micromatch "^4.0.4" - parse-json "^5.2.0" - pretty-format "^29.6.2" - slash "^3.0.0" - strip-json-comments "^3.1.1" - -jest-diff@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.6.2.tgz#c36001e5543e82a0805051d3ceac32e6825c1c46" - integrity sha512-t+ST7CB9GX5F2xKwhwCf0TAR17uNDiaPTZnVymP9lw0lssa9vG+AFyDZoeIHStU3WowFFwT+ky+er0WVl2yGhA== - dependencies: - chalk "^4.0.0" - diff-sequences "^29.4.3" - jest-get-type "^29.4.3" - pretty-format "^29.6.2" - -jest-docblock@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.4.3.tgz#90505aa89514a1c7dceeac1123df79e414636ea8" - integrity sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg== - dependencies: - detect-newline "^3.0.0" - -jest-each@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.6.2.tgz#c9e4b340bcbe838c73adf46b76817b15712d02ce" - integrity sha512-MsrsqA0Ia99cIpABBc3izS1ZYoYfhIy0NNWqPSE0YXbQjwchyt6B1HD2khzyPe1WiJA7hbxXy77ZoUQxn8UlSw== + "babel-jest" "^29.6.2" + "chalk" "^4.0.0" + "ci-info" "^3.2.0" + "deepmerge" "^4.2.2" + "glob" "^7.1.3" + "graceful-fs" "^4.2.9" + "jest-circus" "^29.6.2" + "jest-environment-node" "^29.6.2" + "jest-get-type" "^29.4.3" + "jest-regex-util" "^29.4.3" + "jest-resolve" "^29.6.2" + "jest-runner" "^29.6.2" + "jest-util" "^29.6.2" + "jest-validate" "^29.6.2" + "micromatch" "^4.0.4" + "parse-json" "^5.2.0" + "pretty-format" "^29.6.2" + "slash" "^3.0.0" + "strip-json-comments" "^3.1.1" + +"jest-diff@^29.6.2": + "integrity" "sha512-t+ST7CB9GX5F2xKwhwCf0TAR17uNDiaPTZnVymP9lw0lssa9vG+AFyDZoeIHStU3WowFFwT+ky+er0WVl2yGhA==" + "resolved" "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.2.tgz" + "version" "29.6.2" + dependencies: + "chalk" "^4.0.0" + "diff-sequences" "^29.4.3" + "jest-get-type" "^29.4.3" + "pretty-format" "^29.6.2" + +"jest-docblock@^29.4.3": + "integrity" "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==" + "resolved" "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz" + "version" "29.4.3" + dependencies: + "detect-newline" "^3.0.0" + +"jest-each@^29.6.2": + "integrity" "sha512-MsrsqA0Ia99cIpABBc3izS1ZYoYfhIy0NNWqPSE0YXbQjwchyt6B1HD2khzyPe1WiJA7hbxXy77ZoUQxn8UlSw==" + "resolved" "https://registry.npmjs.org/jest-each/-/jest-each-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/types" "^29.6.1" - chalk "^4.0.0" - jest-get-type "^29.4.3" - jest-util "^29.6.2" - pretty-format "^29.6.2" + "chalk" "^4.0.0" + "jest-get-type" "^29.4.3" + "jest-util" "^29.6.2" + "pretty-format" "^29.6.2" -jest-environment-node@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.6.2.tgz#a9ea2cabff39b08eca14ccb32c8ceb924c8bb1ad" - integrity sha512-YGdFeZ3T9a+/612c5mTQIllvWkddPbYcN2v95ZH24oWMbGA4GGS2XdIF92QMhUhvrjjuQWYgUGW2zawOyH63MQ== +"jest-environment-node@^29.6.2": + "integrity" "sha512-YGdFeZ3T9a+/612c5mTQIllvWkddPbYcN2v95ZH24oWMbGA4GGS2XdIF92QMhUhvrjjuQWYgUGW2zawOyH63MQ==" + "resolved" "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/environment" "^29.6.2" "@jest/fake-timers" "^29.6.2" "@jest/types" "^29.6.1" "@types/node" "*" - jest-mock "^29.6.2" - jest-util "^29.6.2" + "jest-mock" "^29.6.2" + "jest-util" "^29.6.2" -jest-get-type@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.4.3.tgz#1ab7a5207c995161100b5187159ca82dd48b3dd5" - integrity sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg== +"jest-get-type@^29.4.3": + "integrity" "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==" + "resolved" "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz" + "version" "29.4.3" -jest-haste-map@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.6.2.tgz#298c25ea5255cfad8b723179d4295cf3a50a70d1" - integrity sha512-+51XleTDAAysvU8rT6AnS1ZJ+WHVNqhj1k6nTvN2PYP+HjU3kqlaKQ1Lnw3NYW3bm2r8vq82X0Z1nDDHZMzHVA== +"jest-haste-map@^29.6.2": + "integrity" "sha512-+51XleTDAAysvU8rT6AnS1ZJ+WHVNqhj1k6nTvN2PYP+HjU3kqlaKQ1Lnw3NYW3bm2r8vq82X0Z1nDDHZMzHVA==" + "resolved" "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/types" "^29.6.1" "@types/graceful-fs" "^4.1.3" "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^29.4.3" - jest-util "^29.6.2" - jest-worker "^29.6.2" - micromatch "^4.0.4" - walker "^1.0.8" + "anymatch" "^3.0.3" + "fb-watchman" "^2.0.0" + "graceful-fs" "^4.2.9" + "jest-regex-util" "^29.4.3" + "jest-util" "^29.6.2" + "jest-worker" "^29.6.2" + "micromatch" "^4.0.4" + "walker" "^1.0.8" optionalDependencies: - fsevents "^2.3.2" + "fsevents" "^2.3.2" -jest-leak-detector@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.6.2.tgz#e2b307fee78cab091c37858a98c7e1d73cdf5b38" - integrity sha512-aNqYhfp5uYEO3tdWMb2bfWv6f0b4I0LOxVRpnRLAeque2uqOVVMLh6khnTcE2qJ5wAKop0HcreM1btoysD6bPQ== +"jest-leak-detector@^29.6.2": + "integrity" "sha512-aNqYhfp5uYEO3tdWMb2bfWv6f0b4I0LOxVRpnRLAeque2uqOVVMLh6khnTcE2qJ5wAKop0HcreM1btoysD6bPQ==" + "resolved" "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.2.tgz" + "version" "29.6.2" dependencies: - jest-get-type "^29.4.3" - pretty-format "^29.6.2" + "jest-get-type" "^29.4.3" + "pretty-format" "^29.6.2" -jest-matcher-utils@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.6.2.tgz#39de0be2baca7a64eacb27291f0bd834fea3a535" - integrity sha512-4LiAk3hSSobtomeIAzFTe+N8kL6z0JtF3n6I4fg29iIW7tt99R7ZcIFW34QkX+DuVrf+CUe6wuVOpm7ZKFJzZQ== +"jest-matcher-utils@^29.6.2": + "integrity" "sha512-4LiAk3hSSobtomeIAzFTe+N8kL6z0JtF3n6I4fg29iIW7tt99R7ZcIFW34QkX+DuVrf+CUe6wuVOpm7ZKFJzZQ==" + "resolved" "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.2.tgz" + "version" "29.6.2" dependencies: - chalk "^4.0.0" - jest-diff "^29.6.2" - jest-get-type "^29.4.3" - pretty-format "^29.6.2" + "chalk" "^4.0.0" + "jest-diff" "^29.6.2" + "jest-get-type" "^29.4.3" + "pretty-format" "^29.6.2" -jest-message-util@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.6.2.tgz#af7adc2209c552f3f5ae31e77cf0a261f23dc2bb" - integrity sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ== +"jest-message-util@^29.6.2": + "integrity" "sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ==" + "resolved" "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.2.tgz" + "version" "29.6.2" dependencies: "@babel/code-frame" "^7.12.13" "@jest/types" "^29.6.1" "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.6.2" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-mock@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.6.2.tgz#ef9c9b4d38c34a2ad61010a021866dad41ce5e00" - integrity sha512-hoSv3lb3byzdKfwqCuT6uTscan471GUECqgNYykg6ob0yiAw3zYc7OrPnI9Qv8Wwoa4lC7AZ9hyS4AiIx5U2zg== + "chalk" "^4.0.0" + "graceful-fs" "^4.2.9" + "micromatch" "^4.0.4" + "pretty-format" "^29.6.2" + "slash" "^3.0.0" + "stack-utils" "^2.0.3" + +"jest-mock@^29.6.2": + "integrity" "sha512-hoSv3lb3byzdKfwqCuT6uTscan471GUECqgNYykg6ob0yiAw3zYc7OrPnI9Qv8Wwoa4lC7AZ9hyS4AiIx5U2zg==" + "resolved" "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/types" "^29.6.1" "@types/node" "*" - jest-util "^29.6.2" - -jest-pnp-resolver@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" - integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== - -jest-regex-util@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.4.3.tgz#a42616141e0cae052cfa32c169945d00c0aa0bb8" - integrity sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg== - -jest-resolve-dependencies@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.2.tgz#36435269b6672c256bcc85fb384872c134cc4cf2" - integrity sha512-LGqjDWxg2fuQQm7ypDxduLu/m4+4Lb4gczc13v51VMZbVP5tSBILqVx8qfWcsdP8f0G7aIqByIALDB0R93yL+w== - dependencies: - jest-regex-util "^29.4.3" - jest-snapshot "^29.6.2" - -jest-resolve@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.6.2.tgz#f18405fe4b50159b7b6d85e81f6a524d22afb838" - integrity sha512-G/iQUvZWI5e3SMFssc4ug4dH0aZiZpsDq9o1PtXTV1210Ztyb2+w+ZgQkB3iOiC5SmAEzJBOHWz6Hvrd+QnNPw== - dependencies: - chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.6.2" - jest-pnp-resolver "^1.2.2" - jest-util "^29.6.2" - jest-validate "^29.6.2" - resolve "^1.20.0" - resolve.exports "^2.0.0" - slash "^3.0.0" - -jest-runner@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.6.2.tgz#89e8e32a8fef24781a7c4c49cd1cb6358ac7fc01" - integrity sha512-wXOT/a0EspYgfMiYHxwGLPCZfC0c38MivAlb2lMEAlwHINKemrttu1uSbcGbfDV31sFaPWnWJPmb2qXM8pqZ4w== + "jest-util" "^29.6.2" + +"jest-pnp-resolver@^1.2.2": + "integrity" "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==" + "resolved" "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz" + "version" "1.2.3" + +"jest-regex-util@^29.4.3": + "integrity" "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==" + "resolved" "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz" + "version" "29.4.3" + +"jest-resolve-dependencies@^29.6.2": + "integrity" "sha512-LGqjDWxg2fuQQm7ypDxduLu/m4+4Lb4gczc13v51VMZbVP5tSBILqVx8qfWcsdP8f0G7aIqByIALDB0R93yL+w==" + "resolved" "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.2.tgz" + "version" "29.6.2" + dependencies: + "jest-regex-util" "^29.4.3" + "jest-snapshot" "^29.6.2" + +"jest-resolve@*", "jest-resolve@^29.6.2": + "integrity" "sha512-G/iQUvZWI5e3SMFssc4ug4dH0aZiZpsDq9o1PtXTV1210Ztyb2+w+ZgQkB3iOiC5SmAEzJBOHWz6Hvrd+QnNPw==" + "resolved" "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.2.tgz" + "version" "29.6.2" + dependencies: + "chalk" "^4.0.0" + "graceful-fs" "^4.2.9" + "jest-haste-map" "^29.6.2" + "jest-pnp-resolver" "^1.2.2" + "jest-util" "^29.6.2" + "jest-validate" "^29.6.2" + "resolve" "^1.20.0" + "resolve.exports" "^2.0.0" + "slash" "^3.0.0" + +"jest-runner@^29.6.2": + "integrity" "sha512-wXOT/a0EspYgfMiYHxwGLPCZfC0c38MivAlb2lMEAlwHINKemrttu1uSbcGbfDV31sFaPWnWJPmb2qXM8pqZ4w==" + "resolved" "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/console" "^29.6.2" "@jest/environment" "^29.6.2" @@ -4096,26 +4130,26 @@ jest-runner@^29.6.2: "@jest/transform" "^29.6.2" "@jest/types" "^29.6.1" "@types/node" "*" - chalk "^4.0.0" - emittery "^0.13.1" - graceful-fs "^4.2.9" - jest-docblock "^29.4.3" - jest-environment-node "^29.6.2" - jest-haste-map "^29.6.2" - jest-leak-detector "^29.6.2" - jest-message-util "^29.6.2" - jest-resolve "^29.6.2" - jest-runtime "^29.6.2" - jest-util "^29.6.2" - jest-watcher "^29.6.2" - jest-worker "^29.6.2" - p-limit "^3.1.0" - source-map-support "0.5.13" - -jest-runtime@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.6.2.tgz#692f25e387f982e89ab83270e684a9786248e545" - integrity sha512-2X9dqK768KufGJyIeLmIzToDmsN0m7Iek8QNxRSI/2+iPFYHF0jTwlO3ftn7gdKd98G/VQw9XJCk77rbTGZnJg== + "chalk" "^4.0.0" + "emittery" "^0.13.1" + "graceful-fs" "^4.2.9" + "jest-docblock" "^29.4.3" + "jest-environment-node" "^29.6.2" + "jest-haste-map" "^29.6.2" + "jest-leak-detector" "^29.6.2" + "jest-message-util" "^29.6.2" + "jest-resolve" "^29.6.2" + "jest-runtime" "^29.6.2" + "jest-util" "^29.6.2" + "jest-watcher" "^29.6.2" + "jest-worker" "^29.6.2" + "p-limit" "^3.1.0" + "source-map-support" "0.5.13" + +"jest-runtime@^29.6.2": + "integrity" "sha512-2X9dqK768KufGJyIeLmIzToDmsN0m7Iek8QNxRSI/2+iPFYHF0jTwlO3ftn7gdKd98G/VQw9XJCk77rbTGZnJg==" + "resolved" "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/environment" "^29.6.2" "@jest/fake-timers" "^29.6.2" @@ -4125,25 +4159,25 @@ jest-runtime@^29.6.2: "@jest/transform" "^29.6.2" "@jest/types" "^29.6.1" "@types/node" "*" - chalk "^4.0.0" - cjs-module-lexer "^1.0.0" - collect-v8-coverage "^1.0.0" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^29.6.2" - jest-message-util "^29.6.2" - jest-mock "^29.6.2" - jest-regex-util "^29.4.3" - jest-resolve "^29.6.2" - jest-snapshot "^29.6.2" - jest-util "^29.6.2" - slash "^3.0.0" - strip-bom "^4.0.0" - -jest-snapshot@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.6.2.tgz#9b431b561a83f2bdfe041e1cab8a6becdb01af9c" - integrity sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA== + "chalk" "^4.0.0" + "cjs-module-lexer" "^1.0.0" + "collect-v8-coverage" "^1.0.0" + "glob" "^7.1.3" + "graceful-fs" "^4.2.9" + "jest-haste-map" "^29.6.2" + "jest-message-util" "^29.6.2" + "jest-mock" "^29.6.2" + "jest-regex-util" "^29.4.3" + "jest-resolve" "^29.6.2" + "jest-snapshot" "^29.6.2" + "jest-util" "^29.6.2" + "slash" "^3.0.0" + "strip-bom" "^4.0.0" + +"jest-snapshot@^29.6.2": + "integrity" "sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA==" + "resolved" "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.2.tgz" + "version" "29.6.2" dependencies: "@babel/core" "^7.11.6" "@babel/generator" "^7.7.2" @@ -4153,1827 +4187,1871 @@ jest-snapshot@^29.6.2: "@jest/expect-utils" "^29.6.2" "@jest/transform" "^29.6.2" "@jest/types" "^29.6.1" - babel-preset-current-node-syntax "^1.0.0" - chalk "^4.0.0" - expect "^29.6.2" - graceful-fs "^4.2.9" - jest-diff "^29.6.2" - jest-get-type "^29.4.3" - jest-matcher-utils "^29.6.2" - jest-message-util "^29.6.2" - jest-util "^29.6.2" - natural-compare "^1.4.0" - pretty-format "^29.6.2" - semver "^7.5.3" - -jest-util@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.6.2.tgz#8a052df8fff2eebe446769fd88814521a517664d" - integrity sha512-3eX1qb6L88lJNCFlEADKOkjpXJQyZRiavX1INZ4tRnrBVr2COd3RgcTLyUiEXMNBlDU/cgYq6taUS0fExrWW4w== + "babel-preset-current-node-syntax" "^1.0.0" + "chalk" "^4.0.0" + "expect" "^29.6.2" + "graceful-fs" "^4.2.9" + "jest-diff" "^29.6.2" + "jest-get-type" "^29.4.3" + "jest-matcher-utils" "^29.6.2" + "jest-message-util" "^29.6.2" + "jest-util" "^29.6.2" + "natural-compare" "^1.4.0" + "pretty-format" "^29.6.2" + "semver" "^7.5.3" + +"jest-util@^29.6.2": + "integrity" "sha512-3eX1qb6L88lJNCFlEADKOkjpXJQyZRiavX1INZ4tRnrBVr2COd3RgcTLyUiEXMNBlDU/cgYq6taUS0fExrWW4w==" + "resolved" "https://registry.npmjs.org/jest-util/-/jest-util-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/types" "^29.6.1" "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" + "chalk" "^4.0.0" + "ci-info" "^3.2.0" + "graceful-fs" "^4.2.9" + "picomatch" "^2.2.3" -jest-validate@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.6.2.tgz#25d972af35b2415b83b1373baf1a47bb266c1082" - integrity sha512-vGz0yMN5fUFRRbpJDPwxMpgSXW1LDKROHfBopAvDcmD6s+B/s8WJrwi+4bfH4SdInBA5C3P3BI19dBtKzx1Arg== +"jest-validate@^29.6.2": + "integrity" "sha512-vGz0yMN5fUFRRbpJDPwxMpgSXW1LDKROHfBopAvDcmD6s+B/s8WJrwi+4bfH4SdInBA5C3P3BI19dBtKzx1Arg==" + "resolved" "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/types" "^29.6.1" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^29.4.3" - leven "^3.1.0" - pretty-format "^29.6.2" + "camelcase" "^6.2.0" + "chalk" "^4.0.0" + "jest-get-type" "^29.4.3" + "leven" "^3.1.0" + "pretty-format" "^29.6.2" -jest-watcher@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.6.2.tgz#77c224674f0620d9f6643c4cfca186d8893ca088" - integrity sha512-GZitlqkMkhkefjfN/p3SJjrDaxPflqxEAv3/ik10OirZqJGYH5rPiIsgVcfof0Tdqg3shQGdEIxDBx+B4tuLzA== +"jest-watcher@^29.6.2": + "integrity" "sha512-GZitlqkMkhkefjfN/p3SJjrDaxPflqxEAv3/ik10OirZqJGYH5rPiIsgVcfof0Tdqg3shQGdEIxDBx+B4tuLzA==" + "resolved" "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/test-result" "^29.6.2" "@jest/types" "^29.6.1" "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - emittery "^0.13.1" - jest-util "^29.6.2" - string-length "^4.0.1" + "ansi-escapes" "^4.2.1" + "chalk" "^4.0.0" + "emittery" "^0.13.1" + "jest-util" "^29.6.2" + "string-length" "^4.0.1" -jest-worker@^27.4.5: - version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" - integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== +"jest-worker@^27.4.5": + "integrity" "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==" + "resolved" "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz" + "version" "27.5.1" dependencies: "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" + "merge-stream" "^2.0.0" + "supports-color" "^8.0.0" -jest-worker@^29.4.3, jest-worker@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.6.2.tgz#682fbc4b6856ad0aa122a5403c6d048b83f3fb44" - integrity sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ== +"jest-worker@^29.4.3", "jest-worker@^29.6.2": + "integrity" "sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ==" + "resolved" "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.2.tgz" + "version" "29.6.2" dependencies: "@types/node" "*" - jest-util "^29.6.2" - merge-stream "^2.0.0" - supports-color "^8.0.0" + "jest-util" "^29.6.2" + "merge-stream" "^2.0.0" + "supports-color" "^8.0.0" -jest@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.6.2.tgz#3bd55b9fd46a161b2edbdf5f1d1bd0d1eab76c42" - integrity sha512-8eQg2mqFbaP7CwfsTpCxQ+sHzw1WuNWL5UUvjnWP4hx2riGz9fPSzYOaU5q8/GqWn1TfgZIVTqYJygbGbWAANg== +"jest@^29.6.2": + "integrity" "sha512-8eQg2mqFbaP7CwfsTpCxQ+sHzw1WuNWL5UUvjnWP4hx2riGz9fPSzYOaU5q8/GqWn1TfgZIVTqYJygbGbWAANg==" + "resolved" "https://registry.npmjs.org/jest/-/jest-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/core" "^29.6.2" "@jest/types" "^29.6.1" - import-local "^3.0.2" - jest-cli "^29.6.2" - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== - -json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== - -json5@^2.1.2, json5@^2.2.2: - version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - -kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -launch-editor@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.6.0.tgz#4c0c1a6ac126c572bd9ff9a30da1d2cae66defd7" - integrity sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ== - dependencies: - picocolors "^1.0.0" - shell-quote "^1.7.3" - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -lilconfig@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" - integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -loader-runner@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" - integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== - -loader-utils@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" - integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^2.1.2" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -locate-path@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-7.2.0.tgz#69cb1779bd90b35ab1e771e1f2f89a202c2a8a8a" - integrity sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA== - dependencies: - p-locate "^6.0.0" - -lodash.debounce@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== - -lodash.memoize@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== - -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.truncate@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" - integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== - -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== - -lodash@^4.17.11, lodash@^4.17.20, lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -lower-case@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" - integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== - dependencies: - tslib "^2.0.3" - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -make-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" - integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== - dependencies: - pify "^4.0.1" - semver "^5.6.0" - -make-dir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" - integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== - dependencies: - semver "^7.5.3" - -makeerror@1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" - integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== - dependencies: - tmpl "1.0.5" - -mdn-data@2.0.28: - version "2.0.28" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.28.tgz#5ec48e7bef120654539069e1ae4ddc81ca490eba" - integrity sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g== - -mdn-data@2.0.30: - version "2.0.30" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.30.tgz#ce4df6f80af6cfbe218ecd5c552ba13c4dfa08cc" - integrity sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA== - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== - -memfs@^3.4.3: - version "3.6.0" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6" - integrity sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ== - dependencies: - fs-monkey "^1.0.4" - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0, merge2@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== - -micromatch@^4.0.2, micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - -mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -mini-css-extract-plugin@^2.7.6: - version "2.7.6" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz#282a3d38863fddcd2e0c220aaed5b90bc156564d" - integrity sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw== - dependencies: - schema-utils "^4.0.0" - -minimalistic-assert@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimatch@^3.0.4, minimatch@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -multicast-dns@^7.2.5: - version "7.2.5" - resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced" - integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg== - dependencies: - dns-packet "^5.2.2" - thunky "^1.0.2" - -nanoid@^3.3.6: - version "3.3.6" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" - integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -neo-async@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - -no-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" - integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== - dependencies: - lower-case "^2.0.2" - tslib "^2.0.3" - -node-forge@^1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" - integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== - -node-int64@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== - -node-releases@^2.0.13: - version "2.0.13" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" - integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -nth-check@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" - integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== - dependencies: - boolbase "^1.0.0" - -object-inspect@^1.9.0: - version "1.12.3" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" - integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== - -obuf@^1.0.0, obuf@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" - integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== - -on-finished@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -open@^8.0.9: - version "8.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" - integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== - dependencies: - define-lazy-prop "^2.0.0" - is-docker "^2.1.1" - is-wsl "^2.2.0" - -optionator@^0.9.1: - version "0.9.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" - integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== + "import-local" "^3.0.2" + "jest-cli" "^29.6.2" + +"js-tokens@^4.0.0": + "integrity" "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "resolved" "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + "version" "4.0.0" + +"js-yaml@^3.13.1": + "integrity" "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==" + "resolved" "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + "version" "3.14.1" + dependencies: + "argparse" "^1.0.7" + "esprima" "^4.0.0" + +"jsesc@^2.5.1": + "integrity" "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + "resolved" "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" + "version" "2.5.2" + +"jsesc@~0.5.0": + "integrity" "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==" + "resolved" "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" + "version" "0.5.0" + +"json-parse-even-better-errors@^2.3.0", "json-parse-even-better-errors@^2.3.1": + "integrity" "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + "resolved" "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" + "version" "2.3.1" + +"json-schema-traverse@^0.4.1": + "integrity" "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "resolved" "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" + "version" "0.4.1" + +"json-schema-traverse@^1.0.0": + "integrity" "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "resolved" "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" + "version" "1.0.0" + +"json-stable-stringify-without-jsonify@^1.0.1": + "integrity" "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + "resolved" "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" + "version" "1.0.1" + +"json5@^2.1.2", "json5@^2.2.2": + "integrity" "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" + "resolved" "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" + "version" "2.2.3" + +"kind-of@^6.0.2": + "integrity" "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + "resolved" "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" + "version" "6.0.3" + +"kleur@^3.0.3": + "integrity" "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" + "resolved" "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" + "version" "3.0.3" + +"launch-editor@^2.6.0": + "integrity" "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==" + "resolved" "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz" + "version" "2.6.0" + dependencies: + "picocolors" "^1.0.0" + "shell-quote" "^1.7.3" + +"leven@^3.1.0": + "integrity" "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + "resolved" "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" + "version" "3.1.0" + +"levn@^0.4.1": + "integrity" "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==" + "resolved" "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" + "version" "0.4.1" + dependencies: + "prelude-ls" "^1.2.1" + "type-check" "~0.4.0" + +"lilconfig@^2.1.0": + "integrity" "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==" + "resolved" "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz" + "version" "2.1.0" + +"lines-and-columns@^1.1.6": + "integrity" "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + "resolved" "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + "version" "1.2.4" + +"loader-runner@^4.2.0": + "integrity" "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==" + "resolved" "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz" + "version" "4.3.0" + +"loader-utils@^2.0.0": + "integrity" "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==" + "resolved" "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz" + "version" "2.0.4" + dependencies: + "big.js" "^5.2.2" + "emojis-list" "^3.0.0" + "json5" "^2.1.2" + +"locate-path@^5.0.0": + "integrity" "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==" + "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" + "version" "5.0.0" + dependencies: + "p-locate" "^4.1.0" + +"locate-path@^7.1.0": + "integrity" "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==" + "resolved" "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz" + "version" "7.2.0" + dependencies: + "p-locate" "^6.0.0" + +"lodash.debounce@^4.0.8": + "integrity" "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + "resolved" "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" + "version" "4.0.8" + +"lodash.memoize@^4.1.2": + "integrity" "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" + "resolved" "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz" + "version" "4.1.2" + +"lodash.merge@^4.6.2": + "integrity" "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "resolved" "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" + "version" "4.6.2" + +"lodash.truncate@^4.4.2": + "integrity" "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==" + "resolved" "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz" + "version" "4.4.2" + +"lodash.uniq@^4.5.0": + "integrity" "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + "resolved" "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz" + "version" "4.5.0" + +"lodash@^4.17.11", "lodash@^4.17.20", "lodash@^4.17.21": + "integrity" "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + "version" "4.17.21" + +"lower-case@^2.0.2": + "integrity" "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==" + "resolved" "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "tslib" "^2.0.3" + +"lru-cache@^5.1.1": + "integrity" "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==" + "resolved" "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" + "version" "5.1.1" + dependencies: + "yallist" "^3.0.2" + +"lru-cache@^6.0.0": + "integrity" "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==" + "resolved" "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "yallist" "^4.0.0" + +"make-dir@^2.1.0": + "integrity" "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==" + "resolved" "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "pify" "^4.0.1" + "semver" "^5.6.0" + +"make-dir@^4.0.0": + "integrity" "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==" + "resolved" "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "semver" "^7.5.3" + +"makeerror@1.0.12": + "integrity" "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==" + "resolved" "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz" + "version" "1.0.12" + dependencies: + "tmpl" "1.0.5" + +"mdn-data@2.0.28": + "integrity" "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==" + "resolved" "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz" + "version" "2.0.28" + +"mdn-data@2.0.30": + "integrity" "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" + "resolved" "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz" + "version" "2.0.30" + +"media-typer@0.3.0": + "integrity" "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + "resolved" "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + "version" "0.3.0" + +"memfs@^3.4.3": + "integrity" "sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ==" + "resolved" "https://registry.npmjs.org/memfs/-/memfs-3.6.0.tgz" + "version" "3.6.0" + dependencies: + "fs-monkey" "^1.0.4" + +"merge-descriptors@1.0.1": + "integrity" "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "resolved" "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + "version" "1.0.1" + +"merge-stream@^2.0.0": + "integrity" "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + "resolved" "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" + "version" "2.0.0" + +"merge2@^1.3.0", "merge2@^1.4.1": + "integrity" "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + "resolved" "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + "version" "1.4.1" + +"methods@~1.1.2": + "integrity" "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + "resolved" "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + "version" "1.1.2" + +"micromatch@^4.0.2", "micromatch@^4.0.4": + "integrity" "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==" + "resolved" "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz" + "version" "4.0.5" + dependencies: + "braces" "^3.0.2" + "picomatch" "^2.3.1" + +"mime-db@>= 1.43.0 < 2", "mime-db@1.52.0": + "integrity" "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + "resolved" "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" + "version" "1.52.0" + +"mime-types@^2.1.27", "mime-types@^2.1.31", "mime-types@~2.1.17", "mime-types@~2.1.24", "mime-types@~2.1.34": + "integrity" "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==" + "resolved" "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" + "version" "2.1.35" + dependencies: + "mime-db" "1.52.0" + +"mime@1.6.0": + "integrity" "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + "resolved" "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" + "version" "1.6.0" + +"mimic-fn@^2.1.0": + "integrity" "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + "resolved" "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" + "version" "2.1.0" + +"mini-css-extract-plugin@^2.7.6": + "integrity" "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==" + "resolved" "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz" + "version" "2.7.6" + dependencies: + "schema-utils" "^4.0.0" + +"minimalistic-assert@^1.0.0": + "integrity" "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + "resolved" "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" + "version" "1.0.1" + +"minimatch@^3.0.4", "minimatch@^3.1.1": + "integrity" "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==" + "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + "version" "3.1.2" + dependencies: + "brace-expansion" "^1.1.7" + +"ms@2.0.0": + "integrity" "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "resolved" "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + "version" "2.0.0" + +"ms@2.1.2": + "integrity" "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + "version" "2.1.2" + +"ms@2.1.3": + "integrity" "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + "version" "2.1.3" + +"multicast-dns@^7.2.5": + "integrity" "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==" + "resolved" "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz" + "version" "7.2.5" + dependencies: + "dns-packet" "^5.2.2" + "thunky" "^1.0.2" + +"nanoid@^3.3.6": + "integrity" "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" + "resolved" "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz" + "version" "3.3.6" + +"natural-compare@^1.4.0": + "integrity" "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + "resolved" "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" + "version" "1.4.0" + +"negotiator@0.6.3": + "integrity" "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + "resolved" "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" + "version" "0.6.3" + +"neo-async@^2.6.2": + "integrity" "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + "resolved" "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" + "version" "2.6.2" + +"no-case@^3.0.4": + "integrity" "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==" + "resolved" "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "lower-case" "^2.0.2" + "tslib" "^2.0.3" + +"node-forge@^1": + "integrity" "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" + "resolved" "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz" + "version" "1.3.1" + +"node-int64@^0.4.0": + "integrity" "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" + "resolved" "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz" + "version" "0.4.0" + +"node-releases@^2.0.13": + "integrity" "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" + "resolved" "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz" + "version" "2.0.13" + +"normalize-path@^3.0.0", "normalize-path@~3.0.0": + "integrity" "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + "resolved" "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + "version" "3.0.0" + +"npm-run-path@^4.0.1": + "integrity" "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==" + "resolved" "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" + "version" "4.0.1" + dependencies: + "path-key" "^3.0.0" + +"nth-check@^2.0.1": + "integrity" "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==" + "resolved" "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "boolbase" "^1.0.0" + +"object-inspect@^1.9.0": + "integrity" "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" + "resolved" "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz" + "version" "1.12.3" + +"obuf@^1.0.0", "obuf@^1.1.2": + "integrity" "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + "resolved" "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz" + "version" "1.1.2" + +"on-finished@2.4.1": + "integrity" "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==" + "resolved" "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz" + "version" "2.4.1" + dependencies: + "ee-first" "1.1.1" + +"on-headers@~1.0.2": + "integrity" "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + "resolved" "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz" + "version" "1.0.2" + +"once@^1.3.0": + "integrity" "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==" + "resolved" "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + "version" "1.4.0" + dependencies: + "wrappy" "1" + +"onetime@^5.1.2": + "integrity" "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==" + "resolved" "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" + "version" "5.1.2" + dependencies: + "mimic-fn" "^2.1.0" + +"open@^8.0.9": + "integrity" "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==" + "resolved" "https://registry.npmjs.org/open/-/open-8.4.2.tgz" + "version" "8.4.2" + dependencies: + "define-lazy-prop" "^2.0.0" + "is-docker" "^2.1.1" + "is-wsl" "^2.2.0" + +"optionator@^0.9.1": + "integrity" "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==" + "resolved" "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz" + "version" "0.9.3" dependencies: "@aashutoshrathi/word-wrap" "^1.2.3" - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" + "deep-is" "^0.1.3" + "fast-levenshtein" "^2.0.6" + "levn" "^0.4.1" + "prelude-ls" "^1.2.1" + "type-check" "^0.4.0" -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== +"p-limit@^2.2.0": + "integrity" "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==" + "resolved" "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" + "version" "2.3.0" dependencies: - p-try "^2.0.0" + "p-try" "^2.0.0" -p-limit@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== +"p-limit@^3.1.0": + "integrity" "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==" + "resolved" "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + "version" "3.1.0" dependencies: - yocto-queue "^0.1.0" + "yocto-queue" "^0.1.0" -p-limit@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-4.0.0.tgz#914af6544ed32bfa54670b061cafcbd04984b644" - integrity sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ== +"p-limit@^4.0.0": + "integrity" "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==" + "resolved" "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz" + "version" "4.0.0" dependencies: - yocto-queue "^1.0.0" + "yocto-queue" "^1.0.0" -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== +"p-locate@^4.1.0": + "integrity" "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==" + "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" + "version" "4.1.0" dependencies: - p-limit "^2.2.0" + "p-limit" "^2.2.0" -p-locate@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-6.0.0.tgz#3da9a49d4934b901089dca3302fa65dc5a05c04f" - integrity sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw== +"p-locate@^6.0.0": + "integrity" "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==" + "resolved" "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz" + "version" "6.0.0" dependencies: - p-limit "^4.0.0" + "p-limit" "^4.0.0" -p-retry@^4.5.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" - integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== +"p-retry@^4.5.0": + "integrity" "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==" + "resolved" "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz" + "version" "4.6.2" dependencies: "@types/retry" "0.12.0" - retry "^0.13.1" + "retry" "^0.13.1" -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +"p-try@^2.0.0": + "integrity" "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + "resolved" "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" + "version" "2.2.0" -param-case@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" - integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== +"param-case@^3.0.4": + "integrity" "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==" + "resolved" "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz" + "version" "3.0.4" dependencies: - dot-case "^3.0.4" - tslib "^2.0.3" + "dot-case" "^3.0.4" + "tslib" "^2.0.3" -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== +"parent-module@^1.0.0": + "integrity" "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==" + "resolved" "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" + "version" "1.0.1" dependencies: - callsites "^3.0.0" + "callsites" "^3.0.0" -parse-json@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== +"parse-json@^5.2.0": + "integrity" "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==" + "resolved" "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" + "version" "5.2.0" dependencies: "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -parseurl@~1.3.2, parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascal-case@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" - integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== - dependencies: - no-case "^3.0.4" - tslib "^2.0.3" - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-exists@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-5.0.0.tgz#a6aad9489200b21fab31e49cf09277e5116fb9e7" - integrity sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - -pirates@^4.0.4: - version "4.0.6" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" - integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== - -pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -pkg-dir@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-7.0.0.tgz#8f0c08d6df4476756c5ff29b3282d0bab7517d11" - integrity sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA== - dependencies: - find-up "^6.3.0" - -postcss-calc@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-9.0.1.tgz#a744fd592438a93d6de0f1434c572670361eb6c6" - integrity sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ== - dependencies: - postcss-selector-parser "^6.0.11" - postcss-value-parser "^4.2.0" - -postcss-colormin@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-6.0.0.tgz#d4250652e952e1c0aca70c66942da93d3cdeaafe" - integrity sha512-EuO+bAUmutWoZYgHn2T1dG1pPqHU6L4TjzPlu4t1wZGXQ/fxV16xg2EJmYi0z+6r+MGV1yvpx1BHkUaRrPa2bw== - dependencies: - browserslist "^4.21.4" - caniuse-api "^3.0.0" - colord "^2.9.1" - postcss-value-parser "^4.2.0" - -postcss-convert-values@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-6.0.0.tgz#ec94a954957e5c3f78f0e8f65dfcda95280b8996" - integrity sha512-U5D8QhVwqT++ecmy8rnTb+RL9n/B806UVaS3m60lqle4YDFcpbS3ae5bTQIh3wOGUSDHSEtMYLs/38dNG7EYFw== - dependencies: - browserslist "^4.21.4" - postcss-value-parser "^4.2.0" - -postcss-discard-comments@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-6.0.0.tgz#9ca335e8b68919f301b24ba47dde226a42e535fe" - integrity sha512-p2skSGqzPMZkEQvJsgnkBhCn8gI7NzRH2683EEjrIkoMiwRELx68yoUJ3q3DGSGuQ8Ug9Gsn+OuDr46yfO+eFw== - -postcss-discard-duplicates@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.0.tgz#c26177a6c33070922e67e9a92c0fd23d443d1355" - integrity sha512-bU1SXIizMLtDW4oSsi5C/xHKbhLlhek/0/yCnoMQany9k3nPBq+Ctsv/9oMmyqbR96HYHxZcHyK2HR5P/mqoGA== - -postcss-discard-empty@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-6.0.0.tgz#06c1c4fce09e22d2a99e667c8550eb8a3a1b9aee" - integrity sha512-b+h1S1VT6dNhpcg+LpyiUrdnEZfICF0my7HAKgJixJLW7BnNmpRH34+uw/etf5AhOlIhIAuXApSzzDzMI9K/gQ== - -postcss-discard-overridden@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-6.0.0.tgz#49c5262db14e975e349692d9024442de7cd8e234" - integrity sha512-4VELwssYXDFigPYAZ8vL4yX4mUepF/oCBeeIT4OXsJPYOtvJumyz9WflmJWTfDwCUcpDR+z0zvCWBXgTx35SVw== - -postcss-merge-longhand@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-6.0.0.tgz#6f627b27db939bce316eaa97e22400267e798d69" - integrity sha512-4VSfd1lvGkLTLYcxFuISDtWUfFS4zXe0FpF149AyziftPFQIWxjvFSKhA4MIxMe4XM3yTDgQMbSNgzIVxChbIg== - dependencies: - postcss-value-parser "^4.2.0" - stylehacks "^6.0.0" - -postcss-merge-rules@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-6.0.1.tgz#39f165746404e646c0f5c510222ccde4824a86aa" - integrity sha512-a4tlmJIQo9SCjcfiCcCMg/ZCEe0XTkl/xK0XHBs955GWg9xDX3NwP9pwZ78QUOWB8/0XCjZeJn98Dae0zg6AAw== - dependencies: - browserslist "^4.21.4" - caniuse-api "^3.0.0" - cssnano-utils "^4.0.0" - postcss-selector-parser "^6.0.5" - -postcss-minify-font-values@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-6.0.0.tgz#68d4a028f9fa5f61701974724b2cc9445d8e6070" - integrity sha512-zNRAVtyh5E8ndZEYXA4WS8ZYsAp798HiIQ1V2UF/C/munLp2r1UGHwf1+6JFu7hdEhJFN+W1WJQKBrtjhFgEnA== - dependencies: - postcss-value-parser "^4.2.0" - -postcss-minify-gradients@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-6.0.0.tgz#22b5c88cc63091dadbad34e31ff958404d51d679" - integrity sha512-wO0F6YfVAR+K1xVxF53ueZJza3L+R3E6cp0VwuXJQejnNUH0DjcAFe3JEBeTY1dLwGa0NlDWueCA1VlEfiKgAA== - dependencies: - colord "^2.9.1" - cssnano-utils "^4.0.0" - postcss-value-parser "^4.2.0" + "error-ex" "^1.3.1" + "json-parse-even-better-errors" "^2.3.0" + "lines-and-columns" "^1.1.6" + +"parseurl@~1.3.2", "parseurl@~1.3.3": + "integrity" "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + "resolved" "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" + "version" "1.3.3" + +"pascal-case@^3.1.2": + "integrity" "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==" + "resolved" "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz" + "version" "3.1.2" + dependencies: + "no-case" "^3.0.4" + "tslib" "^2.0.3" + +"path-exists@^4.0.0": + "integrity" "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + "resolved" "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + "version" "4.0.0" + +"path-exists@^5.0.0": + "integrity" "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==" + "resolved" "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz" + "version" "5.0.0" + +"path-is-absolute@^1.0.0": + "integrity" "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + "resolved" "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + "version" "1.0.1" + +"path-key@^3.0.0", "path-key@^3.1.0": + "integrity" "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + "resolved" "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + "version" "3.1.1" + +"path-parse@^1.0.7": + "integrity" "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "resolved" "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + "version" "1.0.7" + +"path-to-regexp@0.1.7": + "integrity" "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "resolved" "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + "version" "0.1.7" + +"path-type@^4.0.0": + "integrity" "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + "resolved" "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" + "version" "4.0.0" + +"picocolors@^1.0.0": + "integrity" "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "resolved" "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" + "version" "1.0.0" + +"picomatch@^2.0.4", "picomatch@^2.2.1", "picomatch@^2.2.3", "picomatch@^2.3.1": + "integrity" "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + "resolved" "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + "version" "2.3.1" + +"pify@^4.0.1": + "integrity" "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + "resolved" "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" + "version" "4.0.1" + +"pirates@^4.0.4": + "integrity" "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==" + "resolved" "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz" + "version" "4.0.6" + +"pkg-dir@^4.2.0": + "integrity" "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==" + "resolved" "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" + "version" "4.2.0" + dependencies: + "find-up" "^4.0.0" + +"pkg-dir@^7.0.0": + "integrity" "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==" + "resolved" "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz" + "version" "7.0.0" + dependencies: + "find-up" "^6.3.0" + +"postcss-calc@^9.0.0": + "integrity" "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==" + "resolved" "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz" + "version" "9.0.1" + dependencies: + "postcss-selector-parser" "^6.0.11" + "postcss-value-parser" "^4.2.0" + +"postcss-colormin@^6.0.0": + "integrity" "sha512-EuO+bAUmutWoZYgHn2T1dG1pPqHU6L4TjzPlu4t1wZGXQ/fxV16xg2EJmYi0z+6r+MGV1yvpx1BHkUaRrPa2bw==" + "resolved" "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "browserslist" "^4.21.4" + "caniuse-api" "^3.0.0" + "colord" "^2.9.1" + "postcss-value-parser" "^4.2.0" + +"postcss-convert-values@^6.0.0": + "integrity" "sha512-U5D8QhVwqT++ecmy8rnTb+RL9n/B806UVaS3m60lqle4YDFcpbS3ae5bTQIh3wOGUSDHSEtMYLs/38dNG7EYFw==" + "resolved" "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "browserslist" "^4.21.4" + "postcss-value-parser" "^4.2.0" + +"postcss-discard-comments@^6.0.0": + "integrity" "sha512-p2skSGqzPMZkEQvJsgnkBhCn8gI7NzRH2683EEjrIkoMiwRELx68yoUJ3q3DGSGuQ8Ug9Gsn+OuDr46yfO+eFw==" + "resolved" "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.0.tgz" + "version" "6.0.0" + +"postcss-discard-duplicates@^6.0.0": + "integrity" "sha512-bU1SXIizMLtDW4oSsi5C/xHKbhLlhek/0/yCnoMQany9k3nPBq+Ctsv/9oMmyqbR96HYHxZcHyK2HR5P/mqoGA==" + "resolved" "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.0.tgz" + "version" "6.0.0" + +"postcss-discard-empty@^6.0.0": + "integrity" "sha512-b+h1S1VT6dNhpcg+LpyiUrdnEZfICF0my7HAKgJixJLW7BnNmpRH34+uw/etf5AhOlIhIAuXApSzzDzMI9K/gQ==" + "resolved" "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.0.tgz" + "version" "6.0.0" + +"postcss-discard-overridden@^6.0.0": + "integrity" "sha512-4VELwssYXDFigPYAZ8vL4yX4mUepF/oCBeeIT4OXsJPYOtvJumyz9WflmJWTfDwCUcpDR+z0zvCWBXgTx35SVw==" + "resolved" "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.0.tgz" + "version" "6.0.0" + +"postcss-merge-longhand@^6.0.0": + "integrity" "sha512-4VSfd1lvGkLTLYcxFuISDtWUfFS4zXe0FpF149AyziftPFQIWxjvFSKhA4MIxMe4XM3yTDgQMbSNgzIVxChbIg==" + "resolved" "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "postcss-value-parser" "^4.2.0" + "stylehacks" "^6.0.0" + +"postcss-merge-rules@^6.0.1": + "integrity" "sha512-a4tlmJIQo9SCjcfiCcCMg/ZCEe0XTkl/xK0XHBs955GWg9xDX3NwP9pwZ78QUOWB8/0XCjZeJn98Dae0zg6AAw==" + "resolved" "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "browserslist" "^4.21.4" + "caniuse-api" "^3.0.0" + "cssnano-utils" "^4.0.0" + "postcss-selector-parser" "^6.0.5" + +"postcss-minify-font-values@^6.0.0": + "integrity" "sha512-zNRAVtyh5E8ndZEYXA4WS8ZYsAp798HiIQ1V2UF/C/munLp2r1UGHwf1+6JFu7hdEhJFN+W1WJQKBrtjhFgEnA==" + "resolved" "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "postcss-value-parser" "^4.2.0" + +"postcss-minify-gradients@^6.0.0": + "integrity" "sha512-wO0F6YfVAR+K1xVxF53ueZJza3L+R3E6cp0VwuXJQejnNUH0DjcAFe3JEBeTY1dLwGa0NlDWueCA1VlEfiKgAA==" + "resolved" "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-6.0.0.tgz" + "version" "6.0.0" + dependencies: + "colord" "^2.9.1" + "cssnano-utils" "^4.0.0" + "postcss-value-parser" "^4.2.0" -postcss-minify-params@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-6.0.0.tgz#2b3a85a9e3b990d7a16866f430f5fd1d5961b539" - integrity sha512-Fz/wMQDveiS0n5JPcvsMeyNXOIMrwF88n7196puSuQSWSa+/Ofc1gDOSY2xi8+A4PqB5dlYCKk/WfqKqsI+ReQ== +"postcss-minify-params@^6.0.0": + "integrity" "sha512-Fz/wMQDveiS0n5JPcvsMeyNXOIMrwF88n7196puSuQSWSa+/Ofc1gDOSY2xi8+A4PqB5dlYCKk/WfqKqsI+ReQ==" + "resolved" "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-6.0.0.tgz" + "version" "6.0.0" dependencies: - browserslist "^4.21.4" - cssnano-utils "^4.0.0" - postcss-value-parser "^4.2.0" + "browserslist" "^4.21.4" + "cssnano-utils" "^4.0.0" + "postcss-value-parser" "^4.2.0" -postcss-minify-selectors@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-6.0.0.tgz#5046c5e8680a586e5a0cad52cc9aa36d6be5bda2" - integrity sha512-ec/q9JNCOC2CRDNnypipGfOhbYPuUkewGwLnbv6omue/PSASbHSU7s6uSQ0tcFRVv731oMIx8k0SP4ZX6be/0g== +"postcss-minify-selectors@^6.0.0": + "integrity" "sha512-ec/q9JNCOC2CRDNnypipGfOhbYPuUkewGwLnbv6omue/PSASbHSU7s6uSQ0tcFRVv731oMIx8k0SP4ZX6be/0g==" + "resolved" "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-6.0.0.tgz" + "version" "6.0.0" dependencies: - postcss-selector-parser "^6.0.5" + "postcss-selector-parser" "^6.0.5" -postcss-modules-extract-imports@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" - integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== - -postcss-modules-local-by-default@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz#b08eb4f083050708998ba2c6061b50c2870ca524" - integrity sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA== - dependencies: - icss-utils "^5.0.0" - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.1.0" +"postcss-modules-extract-imports@^3.0.0": + "integrity" "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==" + "resolved" "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz" + "version" "3.0.0" + +"postcss-modules-local-by-default@^4.0.3": + "integrity" "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==" + "resolved" "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz" + "version" "4.0.3" + dependencies: + "icss-utils" "^5.0.0" + "postcss-selector-parser" "^6.0.2" + "postcss-value-parser" "^4.1.0" -postcss-modules-scope@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" - integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== +"postcss-modules-scope@^3.0.0": + "integrity" "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==" + "resolved" "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz" + "version" "3.0.0" dependencies: - postcss-selector-parser "^6.0.4" + "postcss-selector-parser" "^6.0.4" -postcss-modules-values@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" - integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== +"postcss-modules-values@^4.0.0": + "integrity" "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==" + "resolved" "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz" + "version" "4.0.0" dependencies: - icss-utils "^5.0.0" + "icss-utils" "^5.0.0" -postcss-normalize-charset@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-6.0.0.tgz#36cc12457259064969fb96f84df491652a4b0975" - integrity sha512-cqundwChbu8yO/gSWkuFDmKrCZ2vJzDAocheT2JTd0sFNA4HMGoKMfbk2B+J0OmO0t5GUkiAkSM5yF2rSLUjgQ== +"postcss-normalize-charset@^6.0.0": + "integrity" "sha512-cqundwChbu8yO/gSWkuFDmKrCZ2vJzDAocheT2JTd0sFNA4HMGoKMfbk2B+J0OmO0t5GUkiAkSM5yF2rSLUjgQ==" + "resolved" "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.0.tgz" + "version" "6.0.0" -postcss-normalize-display-values@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.0.tgz#8d2961415078644d8c6bbbdaf9a2fdd60f546cd4" - integrity sha512-Qyt5kMrvy7dJRO3OjF7zkotGfuYALETZE+4lk66sziWSPzlBEt7FrUshV6VLECkI4EN8Z863O6Nci4NXQGNzYw== +"postcss-normalize-display-values@^6.0.0": + "integrity" "sha512-Qyt5kMrvy7dJRO3OjF7zkotGfuYALETZE+4lk66sziWSPzlBEt7FrUshV6VLECkI4EN8Z863O6Nci4NXQGNzYw==" + "resolved" "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.0.tgz" + "version" "6.0.0" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-positions@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-6.0.0.tgz#25b96df99a69f8925f730eaee0be74416865e301" - integrity sha512-mPCzhSV8+30FZyWhxi6UoVRYd3ZBJgTRly4hOkaSifo0H+pjDYcii/aVT4YE6QpOil15a5uiv6ftnY3rm0igPg== +"postcss-normalize-positions@^6.0.0": + "integrity" "sha512-mPCzhSV8+30FZyWhxi6UoVRYd3ZBJgTRly4hOkaSifo0H+pjDYcii/aVT4YE6QpOil15a5uiv6ftnY3rm0igPg==" + "resolved" "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-6.0.0.tgz" + "version" "6.0.0" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-repeat-style@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.0.tgz#ddf30ad8762feb5b1eb97f39f251acd7b8353299" - integrity sha512-50W5JWEBiOOAez2AKBh4kRFm2uhrT3O1Uwdxz7k24aKtbD83vqmcVG7zoIwo6xI2FZ/HDlbrCopXhLeTpQib1A== +"postcss-normalize-repeat-style@^6.0.0": + "integrity" "sha512-50W5JWEBiOOAez2AKBh4kRFm2uhrT3O1Uwdxz7k24aKtbD83vqmcVG7zoIwo6xI2FZ/HDlbrCopXhLeTpQib1A==" + "resolved" "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.0.tgz" + "version" "6.0.0" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-string@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-6.0.0.tgz#948282647a51e409d69dde7910f0ac2ff97cb5d8" - integrity sha512-KWkIB7TrPOiqb8ZZz6homet2KWKJwIlysF5ICPZrXAylGe2hzX/HSf4NTX2rRPJMAtlRsj/yfkrWGavFuB+c0w== +"postcss-normalize-string@^6.0.0": + "integrity" "sha512-KWkIB7TrPOiqb8ZZz6homet2KWKJwIlysF5ICPZrXAylGe2hzX/HSf4NTX2rRPJMAtlRsj/yfkrWGavFuB+c0w==" + "resolved" "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-6.0.0.tgz" + "version" "6.0.0" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-timing-functions@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.0.tgz#5f13e650b8c43351989fc5de694525cc2539841c" - integrity sha512-tpIXWciXBp5CiFs8sem90IWlw76FV4oi6QEWfQwyeREVwUy39VSeSqjAT7X0Qw650yAimYW5gkl2Gd871N5SQg== +"postcss-normalize-timing-functions@^6.0.0": + "integrity" "sha512-tpIXWciXBp5CiFs8sem90IWlw76FV4oi6QEWfQwyeREVwUy39VSeSqjAT7X0Qw650yAimYW5gkl2Gd871N5SQg==" + "resolved" "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.0.tgz" + "version" "6.0.0" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-unicode@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-6.0.0.tgz#741b3310f874616bdcf07764f5503695d3604730" - integrity sha512-ui5crYkb5ubEUDugDc786L/Me+DXp2dLg3fVJbqyAl0VPkAeALyAijF2zOsnZyaS1HyfPuMH0DwyY18VMFVNkg== +"postcss-normalize-unicode@^6.0.0": + "integrity" "sha512-ui5crYkb5ubEUDugDc786L/Me+DXp2dLg3fVJbqyAl0VPkAeALyAijF2zOsnZyaS1HyfPuMH0DwyY18VMFVNkg==" + "resolved" "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-6.0.0.tgz" + "version" "6.0.0" dependencies: - browserslist "^4.21.4" - postcss-value-parser "^4.2.0" + "browserslist" "^4.21.4" + "postcss-value-parser" "^4.2.0" -postcss-normalize-url@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-6.0.0.tgz#d0a31e962a16401fb7deb7754b397a323fb650b4" - integrity sha512-98mvh2QzIPbb02YDIrYvAg4OUzGH7s1ZgHlD3fIdTHLgPLRpv1ZTKJDnSAKr4Rt21ZQFzwhGMXxpXlfrUBKFHw== +"postcss-normalize-url@^6.0.0": + "integrity" "sha512-98mvh2QzIPbb02YDIrYvAg4OUzGH7s1ZgHlD3fIdTHLgPLRpv1ZTKJDnSAKr4Rt21ZQFzwhGMXxpXlfrUBKFHw==" + "resolved" "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-6.0.0.tgz" + "version" "6.0.0" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-normalize-whitespace@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.0.tgz#accb961caa42e25ca4179b60855b79b1f7129d4d" - integrity sha512-7cfE1AyLiK0+ZBG6FmLziJzqQCpTQY+8XjMhMAz8WSBSCsCNNUKujgIgjCAmDT3cJ+3zjTXFkoD15ZPsckArVw== +"postcss-normalize-whitespace@^6.0.0": + "integrity" "sha512-7cfE1AyLiK0+ZBG6FmLziJzqQCpTQY+8XjMhMAz8WSBSCsCNNUKujgIgjCAmDT3cJ+3zjTXFkoD15ZPsckArVw==" + "resolved" "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.0.tgz" + "version" "6.0.0" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-ordered-values@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-6.0.0.tgz#374704cdff25560d44061d17ba3c6308837a3218" - integrity sha512-K36XzUDpvfG/nWkjs6d1hRBydeIxGpKS2+n+ywlKPzx1nMYDYpoGbcjhj5AwVYJK1qV2/SDoDEnHzlPD6s3nMg== +"postcss-ordered-values@^6.0.0": + "integrity" "sha512-K36XzUDpvfG/nWkjs6d1hRBydeIxGpKS2+n+ywlKPzx1nMYDYpoGbcjhj5AwVYJK1qV2/SDoDEnHzlPD6s3nMg==" + "resolved" "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.0.tgz" + "version" "6.0.0" dependencies: - cssnano-utils "^4.0.0" - postcss-value-parser "^4.2.0" + "cssnano-utils" "^4.0.0" + "postcss-value-parser" "^4.2.0" -postcss-reduce-initial@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-6.0.0.tgz#7d16e83e60e27e2fa42f56ec0b426f1da332eca7" - integrity sha512-s2UOnidpVuXu6JiiI5U+fV2jamAw5YNA9Fdi/GRK0zLDLCfXmSGqQtzpUPtfN66RtCbb9fFHoyZdQaxOB3WxVA== +"postcss-reduce-initial@^6.0.0": + "integrity" "sha512-s2UOnidpVuXu6JiiI5U+fV2jamAw5YNA9Fdi/GRK0zLDLCfXmSGqQtzpUPtfN66RtCbb9fFHoyZdQaxOB3WxVA==" + "resolved" "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.0.0.tgz" + "version" "6.0.0" dependencies: - browserslist "^4.21.4" - caniuse-api "^3.0.0" + "browserslist" "^4.21.4" + "caniuse-api" "^3.0.0" -postcss-reduce-transforms@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.0.tgz#28ff2601a6d9b96a2f039b3501526e1f4d584a46" - integrity sha512-FQ9f6xM1homnuy1wLe9lP1wujzxnwt1EwiigtWwuyf8FsqqXUDUp2Ulxf9A5yjlUOTdCJO6lonYjg1mgqIIi2w== +"postcss-reduce-transforms@^6.0.0": + "integrity" "sha512-FQ9f6xM1homnuy1wLe9lP1wujzxnwt1EwiigtWwuyf8FsqqXUDUp2Ulxf9A5yjlUOTdCJO6lonYjg1mgqIIi2w==" + "resolved" "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.0.tgz" + "version" "6.0.0" dependencies: - postcss-value-parser "^4.2.0" + "postcss-value-parser" "^4.2.0" -postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5: - version "6.0.13" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz#d05d8d76b1e8e173257ef9d60b706a8e5e99bf1b" - integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ== +"postcss-selector-parser@^6.0.11", "postcss-selector-parser@^6.0.2", "postcss-selector-parser@^6.0.4", "postcss-selector-parser@^6.0.5": + "integrity" "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==" + "resolved" "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz" + "version" "6.0.13" dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" + "cssesc" "^3.0.0" + "util-deprecate" "^1.0.2" -postcss-svgo@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-6.0.0.tgz#7b18742d38d4505a0455bbe70d52b49f00eaf69d" - integrity sha512-r9zvj/wGAoAIodn84dR/kFqwhINp5YsJkLoujybWG59grR/IHx+uQ2Zo+IcOwM0jskfYX3R0mo+1Kip1VSNcvw== +"postcss-svgo@^6.0.0": + "integrity" "sha512-r9zvj/wGAoAIodn84dR/kFqwhINp5YsJkLoujybWG59grR/IHx+uQ2Zo+IcOwM0jskfYX3R0mo+1Kip1VSNcvw==" + "resolved" "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-6.0.0.tgz" + "version" "6.0.0" dependencies: - postcss-value-parser "^4.2.0" - svgo "^3.0.2" + "postcss-value-parser" "^4.2.0" + "svgo" "^3.0.2" -postcss-unique-selectors@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-6.0.0.tgz#c94e9b0f7bffb1203894e42294b5a1b3fb34fbe1" - integrity sha512-EPQzpZNxOxP7777t73RQpZE5e9TrnCrkvp7AH7a0l89JmZiPnS82y216JowHXwpBCQitfyxrof9TK3rYbi7/Yw== +"postcss-unique-selectors@^6.0.0": + "integrity" "sha512-EPQzpZNxOxP7777t73RQpZE5e9TrnCrkvp7AH7a0l89JmZiPnS82y216JowHXwpBCQitfyxrof9TK3rYbi7/Yw==" + "resolved" "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-6.0.0.tgz" + "version" "6.0.0" dependencies: - postcss-selector-parser "^6.0.5" + "postcss-selector-parser" "^6.0.5" -postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" - integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== +"postcss-value-parser@^4.1.0", "postcss-value-parser@^4.2.0": + "integrity" "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "resolved" "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" + "version" "4.2.0" -postcss@^8.4.21, postcss@^8.4.24: - version "8.4.27" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.27.tgz#234d7e4b72e34ba5a92c29636734349e0d9c3057" - integrity sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ== +"postcss@^8.0.9", "postcss@^8.1.0", "postcss@^8.2.15", "postcss@^8.2.2", "postcss@^8.4.21", "postcss@^8.4.24": + "integrity" "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==" + "resolved" "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz" + "version" "8.4.27" dependencies: - nanoid "^3.3.6" - picocolors "^1.0.0" - source-map-js "^1.0.2" + "nanoid" "^3.3.6" + "picocolors" "^1.0.0" + "source-map-js" "^1.0.2" -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +"prelude-ls@^1.2.1": + "integrity" "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" + "resolved" "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" + "version" "1.2.1" -pretty-error@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" - integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== +"pretty-error@^4.0.0": + "integrity" "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==" + "resolved" "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz" + "version" "4.0.0" dependencies: - lodash "^4.17.20" - renderkid "^3.0.0" + "lodash" "^4.17.20" + "renderkid" "^3.0.0" -pretty-format@^29.0.0, pretty-format@^29.6.2: - version "29.6.2" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.6.2.tgz#3d5829261a8a4d89d8b9769064b29c50ed486a47" - integrity sha512-1q0oC8eRveTg5nnBEWMXAU2qpv65Gnuf2eCQzSjxpWFkPaPARwqZZDGuNE0zPAZfTCHzIk3A8dIjwlQKKLphyg== +"pretty-format@^29.0.0", "pretty-format@^29.6.2": + "integrity" "sha512-1q0oC8eRveTg5nnBEWMXAU2qpv65Gnuf2eCQzSjxpWFkPaPARwqZZDGuNE0zPAZfTCHzIk3A8dIjwlQKKLphyg==" + "resolved" "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.2.tgz" + "version" "29.6.2" dependencies: "@jest/schemas" "^29.6.0" - ansi-styles "^5.0.0" - react-is "^18.0.0" - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -progress@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - -prompts@^2.0.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - -proxy-addr@~2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== - dependencies: - forwarded "0.2.0" - ipaddr.js "1.9.1" - -punycode@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" - integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== - -pure-rand@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.2.tgz#a9c2ddcae9b68d736a8163036f088a2781c8b306" - integrity sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ== - -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - side-channel "^1.0.4" - -queue-microtask@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" - integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -range-parser@^1.2.1, range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" - integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - -react-is@^18.0.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" - integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== - -readable-stream@^2.0.1: - version "2.3.8" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" - integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== - 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" - -readable-stream@^3.0.6: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@~3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" - integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== - dependencies: - picomatch "^2.2.1" - -rechoir@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" - integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== - dependencies: - resolve "^1.20.0" - -regenerate-unicode-properties@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" - integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ== - dependencies: - regenerate "^1.4.2" - -regenerate@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" - integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== - -regenerator-runtime@^0.13.4: - version "0.13.11" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" - integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== - -regenerator-runtime@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" - integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== - -regenerator-transform@^0.15.2: - version "0.15.2" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" - integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== + "ansi-styles" "^5.0.0" + "react-is" "^18.0.0" + +"process-nextick-args@~2.0.0": + "integrity" "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "resolved" "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" + "version" "2.0.1" + +"progress@^2.0.0": + "integrity" "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + "resolved" "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" + "version" "2.0.3" + +"prompts@^2.0.1": + "integrity" "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==" + "resolved" "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz" + "version" "2.4.2" + dependencies: + "kleur" "^3.0.3" + "sisteransi" "^1.0.5" + +"proxy-addr@~2.0.7": + "integrity" "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==" + "resolved" "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" + "version" "2.0.7" + dependencies: + "forwarded" "0.2.0" + "ipaddr.js" "1.9.1" + +"punycode@^2.1.0": + "integrity" "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" + "resolved" "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz" + "version" "2.3.0" + +"pure-rand@^6.0.0": + "integrity" "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==" + "resolved" "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz" + "version" "6.0.2" + +"qs@6.11.0": + "integrity" "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==" + "resolved" "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz" + "version" "6.11.0" + dependencies: + "side-channel" "^1.0.4" + +"queue-microtask@^1.2.2": + "integrity" "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + "resolved" "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + "version" "1.2.3" + +"randombytes@^2.1.0": + "integrity" "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==" + "resolved" "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "safe-buffer" "^5.1.0" + +"range-parser@^1.2.1", "range-parser@~1.2.1": + "integrity" "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + "resolved" "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" + "version" "1.2.1" + +"raw-body@2.5.1": + "integrity" "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==" + "resolved" "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz" + "version" "2.5.1" + dependencies: + "bytes" "3.1.2" + "http-errors" "2.0.0" + "iconv-lite" "0.4.24" + "unpipe" "1.0.0" + +"react-is@^18.0.0": + "integrity" "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "resolved" "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz" + "version" "18.2.0" + +"readable-stream@^2.0.1": + "integrity" "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==" + "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz" + "version" "2.3.8" + 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" + +"readable-stream@^3.0.6": + "integrity" "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==" + "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" + "version" "3.6.2" + dependencies: + "inherits" "^2.0.3" + "string_decoder" "^1.1.1" + "util-deprecate" "^1.0.1" + +"readdirp@~3.6.0": + "integrity" "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==" + "resolved" "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + "version" "3.6.0" + dependencies: + "picomatch" "^2.2.1" + +"rechoir@^0.8.0": + "integrity" "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==" + "resolved" "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz" + "version" "0.8.0" + dependencies: + "resolve" "^1.20.0" + +"regenerate-unicode-properties@^10.1.0": + "integrity" "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==" + "resolved" "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz" + "version" "10.1.0" + dependencies: + "regenerate" "^1.4.2" + +"regenerate@^1.4.2": + "integrity" "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + "resolved" "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" + "version" "1.4.2" + +"regenerator-runtime@^0.13.4": + "integrity" "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + "resolved" "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz" + "version" "0.13.11" + +"regenerator-runtime@^0.14.0": + "integrity" "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + "resolved" "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz" + "version" "0.14.0" + +"regenerator-transform@^0.15.2": + "integrity" "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==" + "resolved" "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz" + "version" "0.15.2" dependencies: "@babel/runtime" "^7.8.4" -regexpp@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== +"regexpp@^3.1.0": + "integrity" "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==" + "resolved" "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz" + "version" "3.2.0" -regexpu-core@^5.3.1: - version "5.3.2" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" - integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== +"regexpu-core@^5.3.1": + "integrity" "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==" + "resolved" "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz" + "version" "5.3.2" dependencies: "@babel/regjsgen" "^0.8.0" - regenerate "^1.4.2" - regenerate-unicode-properties "^10.1.0" - regjsparser "^0.9.1" - unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.1.0" - -regjsparser@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" - integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== - dependencies: - jsesc "~0.5.0" - -relateurl@^0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" - integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog== - -renderkid@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" - integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== - dependencies: - css-select "^4.1.3" - dom-converter "^0.2.0" - htmlparser2 "^6.1.0" - lodash "^4.17.21" - strip-ansi "^6.0.1" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== - -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve.exports@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" - integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== - -resolve@^1.12.0, resolve@^1.14.2, resolve@^1.20.0: - version "1.22.4" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34" - integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -retry@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" - integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -run-parallel@^1.1.9: - version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" - integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== - dependencies: - queue-microtask "^1.2.2" - -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + "regenerate" "^1.4.2" + "regenerate-unicode-properties" "^10.1.0" + "regjsparser" "^0.9.1" + "unicode-match-property-ecmascript" "^2.0.0" + "unicode-match-property-value-ecmascript" "^2.1.0" + +"regjsparser@^0.9.1": + "integrity" "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==" + "resolved" "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz" + "version" "0.9.1" + dependencies: + "jsesc" "~0.5.0" + +"relateurl@^0.2.7": + "integrity" "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==" + "resolved" "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz" + "version" "0.2.7" + +"renderkid@^3.0.0": + "integrity" "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==" + "resolved" "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "css-select" "^4.1.3" + "dom-converter" "^0.2.0" + "htmlparser2" "^6.1.0" + "lodash" "^4.17.21" + "strip-ansi" "^6.0.1" + +"require-directory@^2.1.1": + "integrity" "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + "resolved" "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" + "version" "2.1.1" + +"require-from-string@^2.0.2": + "integrity" "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + "resolved" "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" + "version" "2.0.2" + +"requires-port@^1.0.0": + "integrity" "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + "resolved" "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" + "version" "1.0.0" + +"resolve-cwd@^3.0.0": + "integrity" "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==" + "resolved" "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "resolve-from" "^5.0.0" + +"resolve-from@^4.0.0": + "integrity" "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + "resolved" "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" + "version" "4.0.0" + +"resolve-from@^5.0.0": + "integrity" "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" + "resolved" "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" + "version" "5.0.0" + +"resolve.exports@^2.0.0": + "integrity" "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==" + "resolved" "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz" + "version" "2.0.2" + +"resolve@^1.12.0", "resolve@^1.14.2", "resolve@^1.20.0": + "integrity" "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==" + "resolved" "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz" + "version" "1.22.4" + dependencies: + "is-core-module" "^2.13.0" + "path-parse" "^1.0.7" + "supports-preserve-symlinks-flag" "^1.0.0" + +"retry@^0.13.1": + "integrity" "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" + "resolved" "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz" + "version" "0.13.1" + +"reusify@^1.0.4": + "integrity" "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + "resolved" "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" + "version" "1.0.4" + +"rimraf@^3.0.2": + "integrity" "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==" + "resolved" "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "glob" "^7.1.3" + +"run-parallel@^1.1.9": + "integrity" "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==" + "resolved" "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "queue-microtask" "^1.2.2" + +"safe-buffer@^5.1.0", "safe-buffer@>=5.1.0", "safe-buffer@~5.2.0", "safe-buffer@5.2.1": + "integrity" "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + "version" "5.2.1" + +"safe-buffer@~5.1.0", "safe-buffer@~5.1.1": + "integrity" "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + "version" "5.1.2" + +"safe-buffer@5.1.2": + "integrity" "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "resolved" "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + "version" "5.1.2" "safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + "integrity" "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "resolved" "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + "version" "2.1.2" + +"schema-utils@^3.0.0": + "integrity" "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==" + "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz" + "version" "3.3.0" + dependencies: + "@types/json-schema" "^7.0.8" + "ajv" "^6.12.5" + "ajv-keywords" "^3.5.2" + +"schema-utils@^3.1.1": + "integrity" "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==" + "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz" + "version" "3.3.0" + dependencies: + "@types/json-schema" "^7.0.8" + "ajv" "^6.12.5" + "ajv-keywords" "^3.5.2" -schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" - integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== +"schema-utils@^3.2.0": + "integrity" "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==" + "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz" + "version" "3.3.0" dependencies: "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" + "ajv" "^6.12.5" + "ajv-keywords" "^3.5.2" -schema-utils@^4.0.0, schema-utils@^4.0.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" - integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== +"schema-utils@^4.0.0", "schema-utils@^4.0.1": + "integrity" "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==" + "resolved" "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz" + "version" "4.2.0" dependencies: "@types/json-schema" "^7.0.9" - ajv "^8.9.0" - ajv-formats "^2.1.1" - ajv-keywords "^5.1.0" - -select-hose@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" - integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== - -selfsigned@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.1.1.tgz#18a7613d714c0cd3385c48af0075abf3f266af61" - integrity sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ== - dependencies: - node-forge "^1" - -semver@^5.6.0: - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@^6.3.0, semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.2.1, semver@^7.3.5, semver@^7.3.8, semver@^7.5.3: - version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== - dependencies: - lru-cache "^6.0.0" - -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== - dependencies: - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "2.0.0" - mime "1.6.0" - ms "2.1.3" - on-finished "2.4.1" - range-parser "~1.2.1" - statuses "2.0.1" - -serialize-javascript@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" - integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== - dependencies: - randombytes "^2.1.0" - -serve-index@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" - integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== - dependencies: - accepts "~1.3.4" - batch "0.6.1" - debug "2.6.9" - escape-html "~1.0.3" - http-errors "~1.6.2" - mime-types "~2.1.17" - parseurl "~1.3.2" - -serve-static@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.18.0" - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -shell-quote@^1.7.3: - version "1.8.1" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" - integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== - -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -signal-exit@^3.0.3, signal-exit@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== - -slash@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" - integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slice-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" - integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - -sockjs@^0.3.24: - version "0.3.24" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" - integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== - dependencies: - faye-websocket "^0.11.3" - uuid "^8.3.2" - websocket-driver "^0.7.4" - -source-map-js@^1.0.1, source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-support@~0.5.20: - version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -spdy-transport@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" - integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== - dependencies: - debug "^4.1.0" - detect-node "^2.0.4" - hpack.js "^2.1.6" - obuf "^1.1.2" - readable-stream "^3.0.6" - wbuf "^1.7.3" - -spdy@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" - integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== - dependencies: - debug "^4.1.0" - handle-thing "^2.0.0" - http-deceiver "^1.2.7" - select-hose "^2.0.0" - spdy-transport "^3.0.0" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== - -stack-utils@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" - integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== - dependencies: - escape-string-regexp "^2.0.0" - -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + "ajv" "^8.9.0" + "ajv-formats" "^2.1.1" + "ajv-keywords" "^5.1.0" + +"select-hose@^2.0.0": + "integrity" "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" + "resolved" "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" + "version" "2.0.0" + +"selfsigned@^2.1.1": + "integrity" "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==" + "resolved" "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "node-forge" "^1" + +"semver@^5.6.0": + "integrity" "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" + "resolved" "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz" + "version" "5.7.2" + +"semver@^6.3.0", "semver@^6.3.1": + "integrity" "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + "resolved" "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" + "version" "6.3.1" + +"semver@^7.2.1": + "integrity" "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" + "version" "7.5.4" + dependencies: + "lru-cache" "^6.0.0" + +"semver@^7.3.5": + "integrity" "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" + "version" "7.5.4" + dependencies: + "lru-cache" "^6.0.0" + +"semver@^7.3.8": + "integrity" "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" + "version" "7.5.4" + dependencies: + "lru-cache" "^6.0.0" + +"semver@^7.5.3": + "integrity" "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==" + "resolved" "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" + "version" "7.5.4" + dependencies: + "lru-cache" "^6.0.0" + +"send@0.18.0": + "integrity" "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==" + "resolved" "https://registry.npmjs.org/send/-/send-0.18.0.tgz" + "version" "0.18.0" + dependencies: + "debug" "2.6.9" + "depd" "2.0.0" + "destroy" "1.2.0" + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "etag" "~1.8.1" + "fresh" "0.5.2" + "http-errors" "2.0.0" + "mime" "1.6.0" + "ms" "2.1.3" + "on-finished" "2.4.1" + "range-parser" "~1.2.1" + "statuses" "2.0.1" + +"serialize-javascript@^6.0.1": + "integrity" "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==" + "resolved" "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "randombytes" "^2.1.0" + +"serve-index@^1.9.1": + "integrity" "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==" + "resolved" "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz" + "version" "1.9.1" + dependencies: + "accepts" "~1.3.4" + "batch" "0.6.1" + "debug" "2.6.9" + "escape-html" "~1.0.3" + "http-errors" "~1.6.2" + "mime-types" "~2.1.17" + "parseurl" "~1.3.2" + +"serve-static@1.15.0": + "integrity" "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==" + "resolved" "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz" + "version" "1.15.0" + dependencies: + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "parseurl" "~1.3.3" + "send" "0.18.0" + +"setprototypeof@1.1.0": + "integrity" "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + "resolved" "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz" + "version" "1.1.0" + +"setprototypeof@1.2.0": + "integrity" "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "resolved" "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" + "version" "1.2.0" + +"shallow-clone@^3.0.0": + "integrity" "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==" + "resolved" "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "kind-of" "^6.0.2" + +"shebang-command@^2.0.0": + "integrity" "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==" + "resolved" "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "shebang-regex" "^3.0.0" + +"shebang-regex@^3.0.0": + "integrity" "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + "resolved" "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" + "version" "3.0.0" + +"shell-quote@^1.7.3": + "integrity" "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==" + "resolved" "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz" + "version" "1.8.1" + +"side-channel@^1.0.4": + "integrity" "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==" + "resolved" "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz" + "version" "1.0.4" + dependencies: + "call-bind" "^1.0.0" + "get-intrinsic" "^1.0.2" + "object-inspect" "^1.9.0" + +"signal-exit@^3.0.3", "signal-exit@^3.0.7": + "integrity" "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + "resolved" "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" + "version" "3.0.7" + +"sisteransi@^1.0.5": + "integrity" "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + "resolved" "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" + "version" "1.0.5" + +"slash@^2.0.0": + "integrity" "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" + "resolved" "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz" + "version" "2.0.0" + +"slash@^3.0.0": + "integrity" "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + "resolved" "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + "version" "3.0.0" + +"slice-ansi@^4.0.0": + "integrity" "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==" + "resolved" "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "ansi-styles" "^4.0.0" + "astral-regex" "^2.0.0" + "is-fullwidth-code-point" "^3.0.0" + +"sockjs@^0.3.24": + "integrity" "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==" + "resolved" "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz" + "version" "0.3.24" + dependencies: + "faye-websocket" "^0.11.3" + "uuid" "^8.3.2" + "websocket-driver" "^0.7.4" + +"source-map-js@^1.0.1", "source-map-js@^1.0.2": + "integrity" "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" + "resolved" "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz" + "version" "1.0.2" + +"source-map-support@~0.5.20": + "integrity" "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==" + "resolved" "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" + "version" "0.5.21" + dependencies: + "buffer-from" "^1.0.0" + "source-map" "^0.6.0" + +"source-map-support@0.5.13": + "integrity" "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==" + "resolved" "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz" + "version" "0.5.13" + dependencies: + "buffer-from" "^1.0.0" + "source-map" "^0.6.0" + +"source-map@^0.6.0", "source-map@^0.6.1", "source-map@~0.6.0": + "integrity" "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "resolved" "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + "version" "0.6.1" + +"spdy-transport@^3.0.0": + "integrity" "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==" + "resolved" "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "debug" "^4.1.0" + "detect-node" "^2.0.4" + "hpack.js" "^2.1.6" + "obuf" "^1.1.2" + "readable-stream" "^3.0.6" + "wbuf" "^1.7.3" + +"spdy@^4.0.2": + "integrity" "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==" + "resolved" "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz" + "version" "4.0.2" + dependencies: + "debug" "^4.1.0" + "handle-thing" "^2.0.0" + "http-deceiver" "^1.2.7" + "select-hose" "^2.0.0" + "spdy-transport" "^3.0.0" + +"sprintf-js@~1.0.2": + "integrity" "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + "resolved" "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + "version" "1.0.3" + +"stack-utils@^2.0.3": + "integrity" "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==" + "resolved" "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz" + "version" "2.0.6" + dependencies: + "escape-string-regexp" "^2.0.0" "statuses@>= 1.4.0 < 2": - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + "integrity" "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" + "resolved" "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" + "version" "1.5.0" + +"statuses@2.0.1": + "integrity" "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + "resolved" "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" + "version" "2.0.1" -string-length@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" - integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== +"string_decoder@^1.1.1": + "integrity" "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==" + "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + "version" "1.3.0" dependencies: - char-regex "^1.0.2" - strip-ansi "^6.0.0" + "safe-buffer" "~5.2.0" -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== +"string_decoder@~1.1.1": + "integrity" "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==" + "resolved" "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + "version" "1.1.1" dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" + "safe-buffer" "~5.1.0" -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== +"string-length@^4.0.1": + "integrity" "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==" + "resolved" "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz" + "version" "4.0.2" dependencies: - safe-buffer "~5.2.0" + "char-regex" "^1.0.2" + "strip-ansi" "^6.0.0" -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== +"string-width@^4.1.0", "string-width@^4.2.0", "string-width@^4.2.3": + "integrity" "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==" + "resolved" "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + "version" "4.2.3" dependencies: - safe-buffer "~5.1.0" + "emoji-regex" "^8.0.0" + "is-fullwidth-code-point" "^3.0.0" + "strip-ansi" "^6.0.1" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== +"strip-ansi@^6.0.0", "strip-ansi@^6.0.1": + "integrity" "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==" + "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + "version" "6.0.1" dependencies: - ansi-regex "^5.0.1" + "ansi-regex" "^5.0.1" -strip-bom@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" - integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== +"strip-bom@^4.0.0": + "integrity" "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==" + "resolved" "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz" + "version" "4.0.0" -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +"strip-final-newline@^2.0.0": + "integrity" "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + "resolved" "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" + "version" "2.0.0" -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +"strip-json-comments@^3.1.0", "strip-json-comments@^3.1.1": + "integrity" "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" + "resolved" "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + "version" "3.1.1" -style-loader@^3.3.2: - version "3.3.3" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.3.tgz#bba8daac19930169c0c9c96706749a597ae3acff" - integrity sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw== +"style-loader@^3.3.2": + "integrity" "sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==" + "resolved" "https://registry.npmjs.org/style-loader/-/style-loader-3.3.3.tgz" + "version" "3.3.3" -stylehacks@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-6.0.0.tgz#9fdd7c217660dae0f62e14d51c89f6c01b3cb738" - integrity sha512-+UT589qhHPwz6mTlCLSt/vMNTJx8dopeJlZAlBMJPWA3ORqu6wmQY7FBXf+qD+FsqoBJODyqNxOUP3jdntFRdw== +"stylehacks@^6.0.0": + "integrity" "sha512-+UT589qhHPwz6mTlCLSt/vMNTJx8dopeJlZAlBMJPWA3ORqu6wmQY7FBXf+qD+FsqoBJODyqNxOUP3jdntFRdw==" + "resolved" "https://registry.npmjs.org/stylehacks/-/stylehacks-6.0.0.tgz" + "version" "6.0.0" dependencies: - browserslist "^4.21.4" - postcss-selector-parser "^6.0.4" + "browserslist" "^4.21.4" + "postcss-selector-parser" "^6.0.4" -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== +"supports-color@^5.3.0": + "integrity" "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + "version" "5.5.0" dependencies: - has-flag "^3.0.0" + "has-flag" "^3.0.0" -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== +"supports-color@^7.1.0": + "integrity" "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + "version" "7.2.0" dependencies: - has-flag "^4.0.0" + "has-flag" "^4.0.0" -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== +"supports-color@^8.0.0": + "integrity" "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + "version" "8.1.1" dependencies: - has-flag "^4.0.0" + "has-flag" "^4.0.0" -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +"supports-preserve-symlinks-flag@^1.0.0": + "integrity" "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + "resolved" "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + "version" "1.0.0" -svgo@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-3.0.2.tgz#5e99eeea42c68ee0dc46aa16da093838c262fe0a" - integrity sha512-Z706C1U2pb1+JGP48fbazf3KxHrWOsLme6Rv7imFBn5EnuanDW1GPaA/P1/dvObE670JDePC3mnj0k0B7P0jjQ== +"svgo@^3.0.2": + "integrity" "sha512-Z706C1U2pb1+JGP48fbazf3KxHrWOsLme6Rv7imFBn5EnuanDW1GPaA/P1/dvObE670JDePC3mnj0k0B7P0jjQ==" + "resolved" "https://registry.npmjs.org/svgo/-/svgo-3.0.2.tgz" + "version" "3.0.2" dependencies: "@trysound/sax" "0.2.0" - commander "^7.2.0" - css-select "^5.1.0" - css-tree "^2.2.1" - csso "^5.0.5" - picocolors "^1.0.0" - -table@^6.0.9: - version "6.8.1" - resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" - integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== - dependencies: - ajv "^8.0.1" - lodash.truncate "^4.4.2" - slice-ansi "^4.0.0" - string-width "^4.2.3" - strip-ansi "^6.0.1" - -tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" - integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== - -terser-webpack-plugin@^5.3.7, terser-webpack-plugin@^5.3.9: - version "5.3.9" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1" - integrity sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA== + "commander" "^7.2.0" + "css-select" "^5.1.0" + "css-tree" "^2.2.1" + "csso" "^5.0.5" + "picocolors" "^1.0.0" + +"table@^6.0.9": + "integrity" "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==" + "resolved" "https://registry.npmjs.org/table/-/table-6.8.1.tgz" + "version" "6.8.1" + dependencies: + "ajv" "^8.0.1" + "lodash.truncate" "^4.4.2" + "slice-ansi" "^4.0.0" + "string-width" "^4.2.3" + "strip-ansi" "^6.0.1" + +"tapable@^2.0.0", "tapable@^2.1.1", "tapable@^2.2.0": + "integrity" "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + "resolved" "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" + "version" "2.2.1" + +"terser-webpack-plugin@^5.3.7", "terser-webpack-plugin@^5.3.9": + "integrity" "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==" + "resolved" "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz" + "version" "5.3.9" dependencies: "@jridgewell/trace-mapping" "^0.3.17" - jest-worker "^27.4.5" - schema-utils "^3.1.1" - serialize-javascript "^6.0.1" - terser "^5.16.8" + "jest-worker" "^27.4.5" + "schema-utils" "^3.1.1" + "serialize-javascript" "^6.0.1" + "terser" "^5.16.8" -terser@^5.10.0, terser@^5.16.8: - version "5.19.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.19.2.tgz#bdb8017a9a4a8de4663a7983f45c506534f9234e" - integrity sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA== +"terser@^5.10.0", "terser@^5.16.8": + "integrity" "sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==" + "resolved" "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz" + "version" "5.19.2" dependencies: "@jridgewell/source-map" "^0.3.3" - acorn "^8.8.2" - commander "^2.20.0" - source-map-support "~0.5.20" + "acorn" "^8.8.2" + "commander" "^2.20.0" + "source-map-support" "~0.5.20" -test-exclude@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" - integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== +"test-exclude@^6.0.0": + "integrity" "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==" + "resolved" "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz" + "version" "6.0.0" dependencies: "@istanbuljs/schema" "^0.1.2" - glob "^7.1.4" - minimatch "^3.0.4" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== - -thunky@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" - integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== - -tmpl@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" - integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -tslib@^1.8.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslib@^2.0.3: - version "2.6.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.1.tgz#fd8c9a0ff42590b25703c0acb3de3d3f4ede0410" - integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig== - -tsutils@^3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" - integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== - dependencies: - tslib "^1.8.1" - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-detect@4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -typescript@^4.9.5: - version "4.9.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" - integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== - -unicode-canonical-property-names-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" - integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== - -unicode-match-property-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" - integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== - dependencies: - unicode-canonical-property-names-ecmascript "^2.0.0" - unicode-property-aliases-ecmascript "^2.0.0" - -unicode-match-property-value-ecmascript@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0" - integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== - -unicode-property-aliases-ecmascript@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" - integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - -update-browserslist-db@^1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940" - integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - -uri-js@^4.2.2: - version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" - integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== - dependencies: - punycode "^2.1.0" - -url-loader@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2" - integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA== - dependencies: - loader-utils "^2.0.0" - mime-types "^2.1.27" - schema-utils "^3.0.0" - -util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - -utila@~0.4: - version "0.4.0" - resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" - integrity sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA== - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== - -uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -v8-compile-cache@^2.0.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" - integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== - -v8-to-istanbul@^9.0.1: - version "9.1.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz#1b83ed4e397f58c85c266a570fc2558b5feb9265" - integrity sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA== + "glob" "^7.1.4" + "minimatch" "^3.0.4" + +"text-table@^0.2.0": + "integrity" "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + "resolved" "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" + "version" "0.2.0" + +"thunky@^1.0.2": + "integrity" "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + "resolved" "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz" + "version" "1.1.0" + +"tmpl@1.0.5": + "integrity" "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" + "resolved" "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz" + "version" "1.0.5" + +"to-fast-properties@^2.0.0": + "integrity" "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" + "resolved" "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" + "version" "2.0.0" + +"to-regex-range@^5.0.1": + "integrity" "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==" + "resolved" "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + "version" "5.0.1" + dependencies: + "is-number" "^7.0.0" + +"toidentifier@1.0.1": + "integrity" "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + "resolved" "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" + "version" "1.0.1" + +"tslib@^1.8.1": + "integrity" "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "resolved" "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" + "version" "1.14.1" + +"tslib@^2.0.3": + "integrity" "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" + "resolved" "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz" + "version" "2.6.1" + +"tsutils@^3.21.0": + "integrity" "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==" + "resolved" "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz" + "version" "3.21.0" + dependencies: + "tslib" "^1.8.1" + +"type-check@^0.4.0", "type-check@~0.4.0": + "integrity" "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==" + "resolved" "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" + "version" "0.4.0" + dependencies: + "prelude-ls" "^1.2.1" + +"type-detect@4.0.8": + "integrity" "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + "resolved" "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" + "version" "4.0.8" + +"type-fest@^0.20.2": + "integrity" "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + "resolved" "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" + "version" "0.20.2" + +"type-fest@^0.21.3": + "integrity" "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" + "resolved" "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" + "version" "0.21.3" + +"type-is@~1.6.18": + "integrity" "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==" + "resolved" "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" + "version" "1.6.18" + dependencies: + "media-typer" "0.3.0" + "mime-types" "~2.1.24" + +"typescript@^4.9.5", "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": + "integrity" "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" + "resolved" "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz" + "version" "4.9.5" + +"unicode-canonical-property-names-ecmascript@^2.0.0": + "integrity" "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" + "resolved" "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz" + "version" "2.0.0" + +"unicode-match-property-ecmascript@^2.0.0": + "integrity" "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==" + "resolved" "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "unicode-canonical-property-names-ecmascript" "^2.0.0" + "unicode-property-aliases-ecmascript" "^2.0.0" + +"unicode-match-property-value-ecmascript@^2.1.0": + "integrity" "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==" + "resolved" "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz" + "version" "2.1.0" + +"unicode-property-aliases-ecmascript@^2.0.0": + "integrity" "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==" + "resolved" "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz" + "version" "2.1.0" + +"unpipe@~1.0.0", "unpipe@1.0.0": + "integrity" "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + "resolved" "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + "version" "1.0.0" + +"update-browserslist-db@^1.0.11": + "integrity" "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==" + "resolved" "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz" + "version" "1.0.11" + dependencies: + "escalade" "^3.1.1" + "picocolors" "^1.0.0" + +"uri-js@^4.2.2": + "integrity" "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==" + "resolved" "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" + "version" "4.4.1" + dependencies: + "punycode" "^2.1.0" + +"url-loader@^4.1.1": + "integrity" "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==" + "resolved" "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz" + "version" "4.1.1" + dependencies: + "loader-utils" "^2.0.0" + "mime-types" "^2.1.27" + "schema-utils" "^3.0.0" + +"util-deprecate@^1.0.1", "util-deprecate@^1.0.2", "util-deprecate@~1.0.1": + "integrity" "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "resolved" "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + "version" "1.0.2" + +"utila@~0.4": + "integrity" "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" + "resolved" "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz" + "version" "0.4.0" + +"utils-merge@1.0.1": + "integrity" "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + "resolved" "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" + "version" "1.0.1" + +"uuid@^8.3.2": + "integrity" "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + "resolved" "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" + "version" "8.3.2" + +"v8-compile-cache@^2.0.3": + "integrity" "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" + "resolved" "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz" + "version" "2.3.0" + +"v8-to-istanbul@^9.0.1": + "integrity" "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==" + "resolved" "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz" + "version" "9.1.0" dependencies: "@jridgewell/trace-mapping" "^0.3.12" "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^1.6.0" + "convert-source-map" "^1.6.0" -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +"vary@~1.1.2": + "integrity" "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + "resolved" "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" + "version" "1.1.2" -walker@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" - integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== +"walker@^1.0.8": + "integrity" "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==" + "resolved" "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz" + "version" "1.0.8" dependencies: - makeerror "1.0.12" + "makeerror" "1.0.12" -watchpack@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" - integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== +"watchpack@^2.4.0": + "integrity" "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==" + "resolved" "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz" + "version" "2.4.0" dependencies: - glob-to-regexp "^0.4.1" - graceful-fs "^4.1.2" + "glob-to-regexp" "^0.4.1" + "graceful-fs" "^4.1.2" -wbuf@^1.1.0, wbuf@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" - integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== +"wbuf@^1.1.0", "wbuf@^1.7.3": + "integrity" "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==" + "resolved" "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz" + "version" "1.7.3" dependencies: - minimalistic-assert "^1.0.0" + "minimalistic-assert" "^1.0.0" -webpack-cli@^5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" - integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg== +"webpack-cli@^5.1.4", "webpack-cli@5.x.x": + "integrity" "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==" + "resolved" "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz" + "version" "5.1.4" dependencies: "@discoveryjs/json-ext" "^0.5.0" "@webpack-cli/configtest" "^2.1.1" "@webpack-cli/info" "^2.0.2" "@webpack-cli/serve" "^2.0.5" - colorette "^2.0.14" - commander "^10.0.1" - cross-spawn "^7.0.3" - envinfo "^7.7.3" - fastest-levenshtein "^1.0.12" - import-local "^3.0.2" - interpret "^3.1.1" - rechoir "^0.8.0" - webpack-merge "^5.7.3" - -webpack-dev-middleware@^5.3.1: - version "5.3.3" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f" - integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA== - dependencies: - colorette "^2.0.10" - memfs "^3.4.3" - mime-types "^2.1.31" - range-parser "^1.2.1" - schema-utils "^4.0.0" - -webpack-dev-server@4.13.3: - version "4.13.3" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.13.3.tgz#9feb740b8b56b886260bae1360286818a221bae8" - integrity sha512-KqqzrzMRSRy5ePz10VhjyL27K2dxqwXQLP5rAKwRJBPUahe7Z2bBWzHw37jeb8GCPKxZRO79ZdQUAPesMh/Nug== + "colorette" "^2.0.14" + "commander" "^10.0.1" + "cross-spawn" "^7.0.3" + "envinfo" "^7.7.3" + "fastest-levenshtein" "^1.0.12" + "import-local" "^3.0.2" + "interpret" "^3.1.1" + "rechoir" "^0.8.0" + "webpack-merge" "^5.7.3" + +"webpack-dev-middleware@^5.3.1": + "integrity" "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==" + "resolved" "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz" + "version" "5.3.3" + dependencies: + "colorette" "^2.0.10" + "memfs" "^3.4.3" + "mime-types" "^2.1.31" + "range-parser" "^1.2.1" + "schema-utils" "^4.0.0" + +"webpack-dev-server@4.13.3": + "integrity" "sha512-KqqzrzMRSRy5ePz10VhjyL27K2dxqwXQLP5rAKwRJBPUahe7Z2bBWzHw37jeb8GCPKxZRO79ZdQUAPesMh/Nug==" + "resolved" "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.13.3.tgz" + "version" "4.13.3" dependencies: "@types/bonjour" "^3.5.9" "@types/connect-history-api-fallback" "^1.3.5" @@ -5982,165 +6060,165 @@ webpack-dev-server@4.13.3: "@types/serve-static" "^1.13.10" "@types/sockjs" "^0.3.33" "@types/ws" "^8.5.1" - ansi-html-community "^0.0.8" - bonjour-service "^1.0.11" - chokidar "^3.5.3" - colorette "^2.0.10" - compression "^1.7.4" - connect-history-api-fallback "^2.0.0" - default-gateway "^6.0.3" - express "^4.17.3" - graceful-fs "^4.2.6" - html-entities "^2.3.2" - http-proxy-middleware "^2.0.3" - ipaddr.js "^2.0.1" - launch-editor "^2.6.0" - open "^8.0.9" - p-retry "^4.5.0" - rimraf "^3.0.2" - schema-utils "^4.0.0" - selfsigned "^2.1.1" - serve-index "^1.9.1" - sockjs "^0.3.24" - spdy "^4.0.2" - webpack-dev-middleware "^5.3.1" - ws "^8.13.0" - -webpack-merge@^5.7.3: - version "5.9.0" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.9.0.tgz#dc160a1c4cf512ceca515cc231669e9ddb133826" - integrity sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg== - dependencies: - clone-deep "^4.0.1" - wildcard "^2.0.0" - -webpack-sources@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" - integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== - -webpack@^5.88.2: - version "5.88.2" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.88.2.tgz#f62b4b842f1c6ff580f3fcb2ed4f0b579f4c210e" - integrity sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ== + "ansi-html-community" "^0.0.8" + "bonjour-service" "^1.0.11" + "chokidar" "^3.5.3" + "colorette" "^2.0.10" + "compression" "^1.7.4" + "connect-history-api-fallback" "^2.0.0" + "default-gateway" "^6.0.3" + "express" "^4.17.3" + "graceful-fs" "^4.2.6" + "html-entities" "^2.3.2" + "http-proxy-middleware" "^2.0.3" + "ipaddr.js" "^2.0.1" + "launch-editor" "^2.6.0" + "open" "^8.0.9" + "p-retry" "^4.5.0" + "rimraf" "^3.0.2" + "schema-utils" "^4.0.0" + "selfsigned" "^2.1.1" + "serve-index" "^1.9.1" + "sockjs" "^0.3.24" + "spdy" "^4.0.2" + "webpack-dev-middleware" "^5.3.1" + "ws" "^8.13.0" + +"webpack-merge@^5.7.3": + "integrity" "sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==" + "resolved" "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz" + "version" "5.9.0" + dependencies: + "clone-deep" "^4.0.1" + "wildcard" "^2.0.0" + +"webpack-sources@^3.2.3": + "integrity" "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==" + "resolved" "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz" + "version" "3.2.3" + +"webpack@^4.0.0 || ^5.0.0", "webpack@^4.37.0 || ^5.0.0", "webpack@^5.0.0", "webpack@^5.1.0", "webpack@^5.20.0", "webpack@^5.88.2", "webpack@>=5", "webpack@5.x.x": + "integrity" "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==" + "resolved" "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz" + "version" "5.88.2" dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^1.0.0" "@webassemblyjs/ast" "^1.11.5" "@webassemblyjs/wasm-edit" "^1.11.5" "@webassemblyjs/wasm-parser" "^1.11.5" - acorn "^8.7.1" - acorn-import-assertions "^1.9.0" - browserslist "^4.14.5" - chrome-trace-event "^1.0.2" - enhanced-resolve "^5.15.0" - es-module-lexer "^1.2.1" - eslint-scope "5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" - json-parse-even-better-errors "^2.3.1" - loader-runner "^4.2.0" - mime-types "^2.1.27" - neo-async "^2.6.2" - schema-utils "^3.2.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.3.7" - watchpack "^2.4.0" - webpack-sources "^3.2.3" - -websocket-driver@>=0.5.1, websocket-driver@^0.7.4: - version "0.7.4" - resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" - integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== - dependencies: - http-parser-js ">=0.5.1" - safe-buffer ">=5.1.0" - websocket-extensions ">=0.1.1" - -websocket-extensions@>=0.1.1: - version "0.1.4" - resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" - integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -wildcard@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" - integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -write-file-atomic@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" - integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== - dependencies: - imurmurhash "^0.1.4" - signal-exit "^3.0.7" - -ws@^8.13.0: - version "8.13.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" - integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs@^17.3.1: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -yocto-queue@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" - integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== + "acorn" "^8.7.1" + "acorn-import-assertions" "^1.9.0" + "browserslist" "^4.14.5" + "chrome-trace-event" "^1.0.2" + "enhanced-resolve" "^5.15.0" + "es-module-lexer" "^1.2.1" + "eslint-scope" "5.1.1" + "events" "^3.2.0" + "glob-to-regexp" "^0.4.1" + "graceful-fs" "^4.2.9" + "json-parse-even-better-errors" "^2.3.1" + "loader-runner" "^4.2.0" + "mime-types" "^2.1.27" + "neo-async" "^2.6.2" + "schema-utils" "^3.2.0" + "tapable" "^2.1.1" + "terser-webpack-plugin" "^5.3.7" + "watchpack" "^2.4.0" + "webpack-sources" "^3.2.3" + +"websocket-driver@^0.7.4", "websocket-driver@>=0.5.1": + "integrity" "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==" + "resolved" "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz" + "version" "0.7.4" + dependencies: + "http-parser-js" ">=0.5.1" + "safe-buffer" ">=5.1.0" + "websocket-extensions" ">=0.1.1" + +"websocket-extensions@>=0.1.1": + "integrity" "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" + "resolved" "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz" + "version" "0.1.4" + +"which@^2.0.1": + "integrity" "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==" + "resolved" "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "isexe" "^2.0.0" + +"wildcard@^2.0.0": + "integrity" "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==" + "resolved" "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz" + "version" "2.0.1" + +"wrap-ansi@^7.0.0": + "integrity" "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==" + "resolved" "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + "version" "7.0.0" + dependencies: + "ansi-styles" "^4.0.0" + "string-width" "^4.1.0" + "strip-ansi" "^6.0.0" + +"wrappy@1": + "integrity" "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "resolved" "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + "version" "1.0.2" + +"write-file-atomic@^4.0.2": + "integrity" "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==" + "resolved" "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz" + "version" "4.0.2" + dependencies: + "imurmurhash" "^0.1.4" + "signal-exit" "^3.0.7" + +"ws@^8.13.0": + "integrity" "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==" + "resolved" "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz" + "version" "8.13.0" + +"y18n@^5.0.5": + "integrity" "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + "resolved" "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" + "version" "5.0.8" + +"yallist@^3.0.2": + "integrity" "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "resolved" "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" + "version" "3.1.1" + +"yallist@^4.0.0": + "integrity" "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "resolved" "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + "version" "4.0.0" + +"yargs-parser@^21.1.1": + "integrity" "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" + "resolved" "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" + "version" "21.1.1" + +"yargs@^17.3.1": + "integrity" "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==" + "resolved" "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" + "version" "17.7.2" + dependencies: + "cliui" "^8.0.1" + "escalade" "^3.1.1" + "get-caller-file" "^2.0.5" + "require-directory" "^2.1.1" + "string-width" "^4.2.3" + "y18n" "^5.0.5" + "yargs-parser" "^21.1.1" + +"yocto-queue@^0.1.0": + "integrity" "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + "resolved" "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + "version" "0.1.0" + +"yocto-queue@^1.0.0": + "integrity" "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==" + "resolved" "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz" + "version" "1.0.0"