mirror of
https://github.com/leanprover/lean4.git
synced 2026-03-19 03:14:08 +00:00
Compare commits
1 Commits
hexnum
...
sofia/pars
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13435ed957 |
6
.gitattributes
vendored
6
.gitattributes
vendored
@@ -4,9 +4,3 @@ RELEASES.md merge=union
|
||||
stage0/** binary linguist-generated
|
||||
# The following file is often manually edited, so do show it in diffs
|
||||
stage0/src/stdlib_flags.h -binary -linguist-generated
|
||||
# These files should not have line endings translated on Windows, because
|
||||
# it throws off parser tests. Later lines override earlier ones, so the
|
||||
# runner code is still treated as ordinary text.
|
||||
tests/lean/docparse/* eol=lf
|
||||
tests/lean/docparse/*.lean eol=auto
|
||||
tests/lean/docparse/*.sh eol=auto
|
||||
|
||||
5
.github/actionlint.yaml
vendored
5
.github/actionlint.yaml
vendored
@@ -1,5 +0,0 @@
|
||||
self-hosted-runner:
|
||||
labels:
|
||||
- nscloud-ubuntu-22.04-amd64-4x16
|
||||
- nscloud-ubuntu-22.04-amd64-8x16
|
||||
- nscloud-macos-sonoma-arm64-6x14
|
||||
2
.github/workflows/actionlint.yml
vendored
2
.github/workflows/actionlint.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
- name: actionlint
|
||||
uses: raven-actions/actionlint@v2
|
||||
with:
|
||||
|
||||
2
.github/workflows/awaiting-manual.yml
vendored
2
.github/workflows/awaiting-manual.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
- name: Check awaiting-manual label
|
||||
id: check-awaiting-manual-label
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const { labels, number: prNumber } = context.payload.pull_request;
|
||||
|
||||
2
.github/workflows/awaiting-mathlib.yml
vendored
2
.github/workflows/awaiting-mathlib.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
- name: Check awaiting-mathlib label
|
||||
id: check-awaiting-mathlib-label
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const { labels, number: prNumber } = context.payload.pull_request;
|
||||
|
||||
82
.github/workflows/build-template.yml
vendored
82
.github/workflows/build-template.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
include: ${{fromJson(inputs.config)}}
|
||||
# complete all jobs
|
||||
fail-fast: false
|
||||
runs-on: ${{ endsWith(matrix.os, '-with-cache') && fromJSON(format('["{0}", "nscloud-git-mirror-1gb"]', matrix.os)) || matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
defaults:
|
||||
run:
|
||||
shell: ${{ matrix.shell || 'nix develop -c bash -euxo pipefail {0}' }}
|
||||
@@ -69,16 +69,10 @@ jobs:
|
||||
brew install ccache tree zstd coreutils gmp libuv
|
||||
if: runner.os == 'macOS'
|
||||
- name: Checkout
|
||||
if: (!endsWith(matrix.os, '-with-cache'))
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# the default is to use a virtual merge commit between the PR and master: just use the PR
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Namespace Checkout
|
||||
if: endsWith(matrix.os, '-with-cache')
|
||||
uses: namespacelabs/nscloud-checkout-action@v7
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Open Nix shell once
|
||||
run: true
|
||||
if: runner.os == 'Linux'
|
||||
@@ -103,37 +97,31 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y gcc-multilib g++-multilib ccache libuv1-dev:i386 pkgconf:i386
|
||||
if: matrix.cmultilib
|
||||
- name: Restore Cache
|
||||
- name: Cache
|
||||
id: restore-cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
# NOTE: must be in sync with `save` below and with `restore-cache` in `update-stage0.yml`
|
||||
# NOTE: must be in sync with `save` below
|
||||
path: |
|
||||
.ccache
|
||||
${{ matrix.name == 'Linux Lake' && 'build/stage1/**/*.trace
|
||||
${{ matrix.name == 'Linux Lake' && false && 'build/stage1/**/*.trace
|
||||
build/stage1/**/*.olean*
|
||||
build/stage1/**/*.ilean
|
||||
build/stage1/**/*.ir
|
||||
build/stage1/**/*.c
|
||||
build/stage1/**/*.c.o*' || '' }}
|
||||
key: ${{ matrix.name }}-build-v4-${{ github.sha }}
|
||||
key: ${{ matrix.name }}-build-v3-${{ github.sha }}
|
||||
# fall back to (latest) previous cache
|
||||
restore-keys: |
|
||||
${{ matrix.name }}-build-v4
|
||||
${{ matrix.name }}-build-v3
|
||||
# open nix-shell once for initial setup
|
||||
- name: Setup
|
||||
run: |
|
||||
ccache --zero-stats
|
||||
if: runner.os == 'Linux'
|
||||
- name: Set up env
|
||||
- name: Set up NPROC
|
||||
run: |
|
||||
echo "NPROC=$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 4)" >> $GITHUB_ENV
|
||||
if ! diff src/stdlib_flags.h stage0/src/stdlib_flags.h; then
|
||||
echo "src/stdlib_flags.h and stage0/src/stdlib_flags.h differ, will test and pack stage 2"
|
||||
echo "TARGET_STAGE=stage2" >> $GITHUB_ENV
|
||||
else
|
||||
echo "TARGET_STAGE=stage1" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Build
|
||||
run: |
|
||||
ulimit -c unlimited # coredumps
|
||||
@@ -154,9 +142,6 @@ jobs:
|
||||
if [[ -n '${{ matrix.prepare-llvm }}' ]]; then
|
||||
wget -q ${{ matrix.llvm-url }}
|
||||
PREPARE="$(${{ matrix.prepare-llvm }})"
|
||||
if [ "$TARGET_STAGE" == "stage2" ]; then
|
||||
cp -r stage1 stage2
|
||||
fi
|
||||
eval "OPTIONS+=($PREPARE)"
|
||||
fi
|
||||
if [[ -n '${{ matrix.release }}' && -n '${{ inputs.nightly }}' ]]; then
|
||||
@@ -171,28 +156,10 @@ jobs:
|
||||
fi
|
||||
# contortion to support empty OPTIONS with old macOS bash
|
||||
cmake .. --preset ${{ matrix.CMAKE_PRESET || 'release' }} -B . ${{ matrix.CMAKE_OPTIONS }} ${OPTIONS[@]+"${OPTIONS[@]}"} -DLEAN_INSTALL_PREFIX=$PWD/..
|
||||
time make $TARGET_STAGE -j$NPROC
|
||||
# Should be done as early as possible and in particular *before* "Check rebootstrap" which
|
||||
# changes the state of stage1/
|
||||
- name: Save Cache
|
||||
# Caching on cancellation created some mysterious issues perhaps related to improper build
|
||||
# shutdown
|
||||
if: steps.restore-cache.outputs.cache-hit != 'true' && !cancelled()
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
# NOTE: must be in sync with `restore` above
|
||||
path: |
|
||||
.ccache
|
||||
${{ matrix.name == 'Linux Lake' && 'build/stage1/**/*.trace
|
||||
build/stage1/**/*.olean*
|
||||
build/stage1/**/*.ilean
|
||||
build/stage1/**/*.ir
|
||||
build/stage1/**/*.c
|
||||
build/stage1/**/*.c.o*' || '' }}
|
||||
key: ${{ steps.restore-cache.outputs.cache-primary-key }}
|
||||
time make -j$NPROC
|
||||
- name: Install
|
||||
run: |
|
||||
make -C build/$TARGET_STAGE install
|
||||
make -C build install
|
||||
- name: Check Binaries
|
||||
run: ${{ matrix.binary-check }} lean-*/bin/* || true
|
||||
- name: Count binary symbols
|
||||
@@ -223,18 +190,18 @@ jobs:
|
||||
path: pack/*
|
||||
- name: Lean stats
|
||||
run: |
|
||||
build/$TARGET_STAGE/bin/lean --stats src/Lean.lean -Dexperimental.module=true
|
||||
build/stage1/bin/lean --stats src/Lean.lean
|
||||
if: ${{ !matrix.cross }}
|
||||
- name: Test
|
||||
id: test
|
||||
run: |
|
||||
ulimit -c unlimited # coredumps
|
||||
time ctest --preset ${{ matrix.CMAKE_PRESET || 'release' }} --test-dir build/$TARGET_STAGE -j$NPROC --output-junit test-results.xml ${{ matrix.CTEST_OPTIONS }}
|
||||
time ctest --preset ${{ matrix.CMAKE_PRESET || 'release' }} --test-dir build/stage1 -j$NPROC --output-junit test-results.xml ${{ matrix.CTEST_OPTIONS }}
|
||||
if: (matrix.wasm || !matrix.cross) && (inputs.check-level >= 1 || matrix.test)
|
||||
- name: Test Summary
|
||||
uses: test-summary/action@v2
|
||||
with:
|
||||
paths: build/${{ env.TARGET_STAGE }}/test-results.xml
|
||||
paths: build/stage1/test-results.xml
|
||||
# prefix `if` above with `always` so it's run even if tests failed
|
||||
if: always() && steps.test.conclusion != 'skipped'
|
||||
- name: Check Test Binary
|
||||
@@ -259,13 +226,8 @@ jobs:
|
||||
if: matrix.test-speedcenter
|
||||
- name: Check rebootstrap
|
||||
run: |
|
||||
set -e
|
||||
# clean rebuild in case of Makefile changes/Lake does not detect uncommited stage 0
|
||||
# changes yet
|
||||
make -C build update-stage0
|
||||
make -C build/stage1 clean-stdlib
|
||||
time make -C build -j$NPROC
|
||||
time ctest --preset ${{ matrix.CMAKE_PRESET || 'release' }} --test-dir build/stage1 -j$NPROC
|
||||
# clean rebuild in case of Makefile changes
|
||||
make -C build update-stage0 && rm -rf build/stage* && make -C build -j$NPROC
|
||||
if: matrix.check-rebootstrap
|
||||
- name: CCache stats
|
||||
if: always()
|
||||
@@ -277,3 +239,17 @@ jobs:
|
||||
progbin="$(file $c | sed "s/.*execfn: '\([^']*\)'.*/\1/")"
|
||||
echo bt | $GDB/bin/gdb -q $progbin $c || true
|
||||
done
|
||||
- name: Save Cache
|
||||
if: always() && steps.restore-cache.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
# NOTE: must be in sync with `restore` above
|
||||
path: |
|
||||
.ccache
|
||||
${{ matrix.name == 'Linux Lake' && false && 'build/stage1/**/*.trace
|
||||
build/stage1/**/*.olean*
|
||||
build/stage1/**/*.ilean
|
||||
build/stage1/**/*.ir
|
||||
build/stage1/**/*.c
|
||||
build/stage1/**/*.c.o*' || '' }}
|
||||
key: ${{ steps.restore-cache.outputs.cache-primary-key }}
|
||||
|
||||
2
.github/workflows/check-prelude.yml
vendored
2
.github/workflows/check-prelude.yml
vendored
@@ -7,7 +7,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# the default is to use a virtual merge commit between the PR and master: just use the PR
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
4
.github/workflows/check-stage0.yml
vendored
4
.github/workflows/check-stage0.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
check-stage0-on-queue:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
filter: blob:none
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
|
||||
- if: github.event_name == 'pull_request'
|
||||
name: Set label
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const { owner, repo, number: issue_number } = context.issue;
|
||||
|
||||
50
.github/workflows/ci.yml
vendored
50
.github/workflows/ci.yml
vendored
@@ -54,7 +54,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
# don't schedule nightlies on forks
|
||||
if: github.event_name == 'schedule' && github.repository == 'leanprover/lean4' || inputs.action == 'release nightly'
|
||||
- name: Set Nightly
|
||||
@@ -137,7 +137,7 @@ jobs:
|
||||
|
||||
- name: Configure build matrix
|
||||
id: set-matrix
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const level = ${{ steps.set-level.outputs.check-level }};
|
||||
@@ -165,7 +165,7 @@ jobs:
|
||||
{
|
||||
// portable release build: use channel with older glibc (2.26)
|
||||
"name": "Linux release",
|
||||
"os": "ubuntu-latest",
|
||||
"os": large && level < 2 ? "nscloud-ubuntu-22.04-amd64-4x16" : "ubuntu-latest",
|
||||
"release": true,
|
||||
// Special handling for release jobs. We want:
|
||||
// 1. To run it in PRs so developers get PR toolchains (so secondary is sufficient)
|
||||
@@ -181,18 +181,17 @@ jobs:
|
||||
"prepare-llvm": "../script/prepare-llvm-linux.sh lean-llvm*",
|
||||
"binary-check": "ldd -v",
|
||||
// foreign code may be linked against more recent glibc
|
||||
"CTEST_OPTIONS": "-E 'foreign'",
|
||||
"CTEST_OPTIONS": "-E 'foreign'"
|
||||
},
|
||||
{
|
||||
"name": "Linux Lake",
|
||||
"os": large ? "nscloud-ubuntu-22.04-amd64-8x16-with-cache" : "ubuntu-latest",
|
||||
"os": large ? "nscloud-ubuntu-22.04-amd64-8x16" : "ubuntu-latest",
|
||||
"check-level": 0,
|
||||
"test": true,
|
||||
"check-rebootstrap": level >= 1,
|
||||
"check-stage3": level >= 2,
|
||||
// NOTE: `test-speedcenter` currently seems to be broken on `ubuntu-latest`
|
||||
"test-speedcenter": large && level >= 2,
|
||||
// made explicit until it can be assumed to have propagated to PRs
|
||||
"CMAKE_OPTIONS": "-DUSE_LAKE=ON",
|
||||
},
|
||||
{
|
||||
@@ -200,6 +199,8 @@ jobs:
|
||||
"os": "ubuntu-latest",
|
||||
"check-level": 2,
|
||||
"CMAKE_PRESET": "reldebug",
|
||||
// exclude seriously slow/stackoverflowing tests
|
||||
"CTEST_OPTIONS": "-E 'interactivetest|leanpkgtest|laketest|benchtest|bv_bitblast_stress|3807'"
|
||||
},
|
||||
// TODO: suddenly started failing in CI
|
||||
/*{
|
||||
@@ -213,20 +214,19 @@ jobs:
|
||||
},*/
|
||||
{
|
||||
"name": "macOS",
|
||||
"os": "macos-15-intel",
|
||||
"os": "macos-13",
|
||||
"release": true,
|
||||
"check-level": 2,
|
||||
"shell": "bash -euxo pipefail {0}",
|
||||
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/19.1.2/lean-llvm-x86_64-apple-darwin.tar.zst",
|
||||
"prepare-llvm": "../script/prepare-llvm-macos.sh lean-llvm*",
|
||||
"binary-check": "otool -L",
|
||||
"tar": "gtar", // https://github.com/actions/runner-images/issues/2619
|
||||
"CTEST_OPTIONS": "-E 'leanlaketest_hello'", // started failing from unpack
|
||||
"tar": "gtar" // https://github.com/actions/runner-images/issues/2619
|
||||
},
|
||||
{
|
||||
"name": "macOS aarch64",
|
||||
// standard GH runner only comes with 7GB so use large runner if possible when running tests
|
||||
"os": large && !isPr ? "nscloud-macos-sequoia-arm64-6x14" : "macos-15",
|
||||
// standard GH runner only comes with 7GB so use large runner if possible
|
||||
"os": large ? "nscloud-macos-sonoma-arm64-6x14" : "macos-14",
|
||||
"CMAKE_OPTIONS": "-DLEAN_INSTALL_SUFFIX=-darwin_aarch64",
|
||||
"release": true,
|
||||
"shell": "bash -euxo pipefail {0}",
|
||||
@@ -234,20 +234,22 @@ jobs:
|
||||
"prepare-llvm": "../script/prepare-llvm-macos.sh lean-llvm*",
|
||||
"binary-check": "otool -L",
|
||||
"tar": "gtar", // https://github.com/actions/runner-images/issues/2619
|
||||
// See "Linux release" for release job levels; Grove is not a concern here
|
||||
// See above for release job levels
|
||||
"check-level": isPr ? 0 : 2,
|
||||
"secondary": isPr,
|
||||
},
|
||||
{
|
||||
"name": "Windows",
|
||||
"os": large && level == 2 ? "namespace-profile-windows-amd64-4x16" : "windows-2022",
|
||||
"os": "windows-2022",
|
||||
"release": true,
|
||||
"check-level": 2,
|
||||
"shell": "msys2 {0}",
|
||||
"CMAKE_OPTIONS": "-G \"Unix Makefiles\"",
|
||||
// for reasons unknown, interactivetests are flaky on Windows
|
||||
"CTEST_OPTIONS": "--repeat until-pass:2",
|
||||
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/19.1.2/lean-llvm-x86_64-w64-windows-gnu.tar.zst",
|
||||
"prepare-llvm": "../script/prepare-llvm-mingw.sh lean-llvm*",
|
||||
"binary-check": "ldd",
|
||||
"binary-check": "ldd"
|
||||
},
|
||||
{
|
||||
"name": "Linux aarch64",
|
||||
@@ -257,7 +259,7 @@ jobs:
|
||||
"check-level": 2,
|
||||
"shell": "nix develop .#oldGlibcAArch -c bash -euxo pipefail {0}",
|
||||
"llvm-url": "https://github.com/leanprover/lean-llvm/releases/download/19.1.2/lean-llvm-aarch64-linux-gnu.tar.zst",
|
||||
"prepare-llvm": "../script/prepare-llvm-linux.sh lean-llvm*",
|
||||
"prepare-llvm": "../script/prepare-llvm-linux.sh lean-llvm*"
|
||||
},
|
||||
// Started running out of memory building expensive modules, a 2GB heap is just not that much even before fragmentation
|
||||
//{
|
||||
@@ -286,12 +288,6 @@ jobs:
|
||||
// "CTEST_OPTIONS": "-R \"leantest_1007\\.lean|leantest_Format\\.lean|leanruntest\\_1037.lean|leanruntest_ac_rfl\\.lean|leanruntest_tempfile.lean\\.|leanruntest_libuv\\.lean\""
|
||||
// }
|
||||
];
|
||||
for (const job of matrix) {
|
||||
if (job["prepare-llvm"]) {
|
||||
// `USE_LAKE` is not compatible with `prepare-llvm` currently
|
||||
job["CMAKE_OPTIONS"] = (job["CMAKE_OPTIONS"] ? job["CMAKE_OPTIONS"] + " " : "") + "-DUSE_LAKE=OFF";
|
||||
}
|
||||
}
|
||||
console.log(`matrix:\n${JSON.stringify(matrix, null, 2)}`);
|
||||
matrix = matrix.filter((job) => level >= job["check-level"]);
|
||||
core.setOutput('matrix', matrix.filter((job) => !job["secondary"]));
|
||||
@@ -350,7 +346,7 @@ jobs:
|
||||
content: |
|
||||
A build of `${{ github.ref_name }}`, triggered by event `${{ github.event_name }}`, [failed](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}).
|
||||
- if: contains(needs.*.result, 'failure')
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
core.setFailed('Some jobs failed')
|
||||
@@ -363,11 +359,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836
|
||||
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
|
||||
with:
|
||||
files: artifacts/*/*
|
||||
fail_on_unmatched_files: true
|
||||
@@ -388,12 +384,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# needed for tagging
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.PUSH_NIGHTLY_TOKEN }}
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts
|
||||
- name: Prepare Nightly Release
|
||||
@@ -411,7 +407,7 @@ jobs:
|
||||
echo -e "\n*Full commit log*\n" >> diff.md
|
||||
git log --oneline "$last_tag"..HEAD | sed 's/^/* /' >> diff.md
|
||||
- name: Release Nightly
|
||||
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836
|
||||
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
|
||||
with:
|
||||
body_path: diff.md
|
||||
prerelease: true
|
||||
|
||||
2
.github/workflows/copyright-header.yml
vendored
2
.github/workflows/copyright-header.yml
vendored
@@ -6,7 +6,7 @@ jobs:
|
||||
check-lean-files:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Verify .lean files start with a copyright header.
|
||||
run: |
|
||||
|
||||
14
.github/workflows/grove.yml
vendored
14
.github/workflows/grove.yml
vendored
@@ -30,8 +30,8 @@ jobs:
|
||||
# Check if it's a push to master (no PR number and target branch is master)
|
||||
if [ -z "${{ steps.workflow-info.outputs.pullRequestNumber }}" ]; then
|
||||
if [ "${{ github.event.workflow_run.head_branch }}" = "master" ]; then
|
||||
echo "Push to master detected. Running Grove."
|
||||
echo "should-run=true" >> "$GITHUB_OUTPUT"
|
||||
echo "Push to master detected. Skipping for now, to be enabled later."
|
||||
echo "should-run=false" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "Push to non-master branch, skipping"
|
||||
echo "should-run=false" >> "$GITHUB_OUTPUT"
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
# Check if it's a PR with grove label
|
||||
PR_LABELS='${{ steps.workflow-info.outputs.pullRequestLabels }}'
|
||||
if echo "$PR_LABELS" | grep -q '"grove"'; then
|
||||
echo "PR with grove label detected. Running Grove."
|
||||
echo "PR with grove label detected"
|
||||
echo "should-run=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "PR without grove label, skipping"
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
- name: Fetch upstream invalidated facts
|
||||
if: ${{ steps.should-run.outputs.should-run == 'true' && steps.workflow-info.outputs.pullRequestNumber != '' }}
|
||||
id: fetch-upstream
|
||||
uses: TwoFx/grove-action/fetch-upstream@v0.4
|
||||
uses: TwoFx/grove-action/fetch-upstream@v0.3
|
||||
with:
|
||||
artifact-name: grove-invalidated-facts
|
||||
base-ref: master
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
commit: ${{ steps.workflow-info.outputs.sourceHeadSha }}
|
||||
workflow: ci.yml
|
||||
path: artifacts
|
||||
name: "build-Linux release"
|
||||
name: build-Linux.*
|
||||
name_is_regexp: true
|
||||
|
||||
- name: Unpack toolchain
|
||||
@@ -95,7 +95,7 @@ jobs:
|
||||
- name: Build
|
||||
if: ${{ steps.should-run.outputs.should-run == 'true' }}
|
||||
id: build
|
||||
uses: TwoFx/grove-action/build@v0.4
|
||||
uses: TwoFx/grove-action/build@v0.3
|
||||
with:
|
||||
project-path: doc/std/grove
|
||||
script-name: grove-stdlib
|
||||
@@ -110,7 +110,7 @@ jobs:
|
||||
# material.
|
||||
- id: deploy-alias
|
||||
if: ${{ steps.should-run.outputs.should-run == 'true' }}
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
name: Compute Alias
|
||||
with:
|
||||
result-encoding: string
|
||||
|
||||
2
.github/workflows/labels-from-comments.yml
vendored
2
.github/workflows/labels-from-comments.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Add label based on comment
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
|
||||
2
.github/workflows/pr-body.yml
vendored
2
.github/workflows/pr-body.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
steps:
|
||||
- name: Check PR body
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const { title, body, labels, draft } = context.payload.pull_request;
|
||||
|
||||
22
.github/workflows/pr-release.yml
vendored
22
.github/workflows/pr-release.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
- name: Download artifact from the previous workflow.
|
||||
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
|
||||
id: download-artifact
|
||||
uses: dawidd6/action-download-artifact@v11 # https://github.com/marketplace/actions/download-workflow-artifact
|
||||
uses: dawidd6/action-download-artifact@v10 # https://github.com/marketplace/actions/download-workflow-artifact
|
||||
with:
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
path: artifacts
|
||||
@@ -71,7 +71,7 @@ jobs:
|
||||
GH_TOKEN: ${{ secrets.PR_RELEASES_TOKEN }}
|
||||
- name: Release (short format)
|
||||
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
|
||||
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836
|
||||
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
|
||||
with:
|
||||
name: Release for PR ${{ steps.workflow-info.outputs.pullRequestNumber }}
|
||||
# There are coredumps files here as well, but all in deeper subdirectories.
|
||||
@@ -86,7 +86,7 @@ jobs:
|
||||
|
||||
- name: Release (SHA-suffixed format)
|
||||
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
|
||||
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836
|
||||
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631
|
||||
with:
|
||||
name: Release for PR ${{ steps.workflow-info.outputs.pullRequestNumber }} (${{ steps.workflow-info.outputs.sourceHeadSha }})
|
||||
# There are coredumps files here as well, but all in deeper subdirectories.
|
||||
@@ -101,7 +101,7 @@ jobs:
|
||||
|
||||
- name: Report release status (short format)
|
||||
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
await github.rest.repos.createCommitStatus({
|
||||
@@ -115,7 +115,7 @@ jobs:
|
||||
|
||||
- name: Report release status (SHA-suffixed format)
|
||||
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
await github.rest.repos.createCommitStatus({
|
||||
@@ -129,7 +129,7 @@ jobs:
|
||||
|
||||
- name: Add label
|
||||
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
await github.rest.issues.addLabels({
|
||||
@@ -151,7 +151,7 @@ jobs:
|
||||
|
||||
- name: 'Setup jq'
|
||||
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' }}
|
||||
uses: dcarbone/install-jq-action@v3.2.0
|
||||
uses: dcarbone/install-jq-action@v3.1.1
|
||||
|
||||
# Check that the most recently nightly coincides with 'git merge-base HEAD master'
|
||||
- name: Check merge-base and nightly-testing-YYYY-MM-DD for Mathlib/Batteries
|
||||
@@ -368,7 +368,7 @@ jobs:
|
||||
|
||||
- name: Report mathlib base
|
||||
if: ${{ steps.workflow-info.outputs.pullRequestNumber != '' && steps.ready.outputs.mathlib_ready == 'true' }}
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const description =
|
||||
@@ -395,7 +395,7 @@ jobs:
|
||||
# Checkout the Batteries repository with all branches
|
||||
- name: Checkout Batteries repository
|
||||
if: steps.workflow-info.outputs.pullRequestNumber != '' && steps.ready.outputs.mathlib_ready == 'true'
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: leanprover-community/batteries
|
||||
token: ${{ secrets.MATHLIB4_BOT }}
|
||||
@@ -454,7 +454,7 @@ jobs:
|
||||
# Checkout the mathlib4 repository with all branches
|
||||
- name: Checkout mathlib4 repository
|
||||
if: steps.workflow-info.outputs.pullRequestNumber != '' && steps.ready.outputs.mathlib_ready == 'true'
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: leanprover-community/mathlib4-nightly-testing
|
||||
token: ${{ secrets.MATHLIB4_BOT }}
|
||||
@@ -524,7 +524,7 @@ jobs:
|
||||
# Checkout the reference manual repository with all branches
|
||||
- name: Checkout mathlib4 repository
|
||||
if: steps.workflow-info.outputs.pullRequestNumber != '' && steps.reference-manual-ready.outputs.manual_ready == 'true'
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: leanprover/reference-manual
|
||||
token: ${{ secrets.MANUAL_PR_BOT }}
|
||||
|
||||
2
.github/workflows/pr-title.yml
vendored
2
.github/workflows/pr-title.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check PR title
|
||||
uses: actions/github-script@v8
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const msg = context.payload.pull_request? context.payload.pull_request.title : context.payload.merge_group.head_commit.message;
|
||||
|
||||
2
.github/workflows/stale.yml
vendored
2
.github/workflows/stale.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v10
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
days-before-stale: -1
|
||||
days-before-pr-stale: 30
|
||||
|
||||
33
.github/workflows/update-stage0.yml
vendored
33
.github/workflows/update-stage0.yml
vendored
@@ -18,16 +18,12 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
update-stage0:
|
||||
runs-on: nscloud-ubuntu-22.04-amd64-8x16
|
||||
env:
|
||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||
CCACHE_COMPRESS: true
|
||||
CCACHE_MAXSIZE: 400M
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# This action should push to an otherwise protected branch, so it
|
||||
# uses a deploy key with write permissions, as suggested at
|
||||
# https://stackoverflow.com/a/76135647/946226
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ssh-key: ${{secrets.STAGE0_SSH_KEY}}
|
||||
- run: echo "should_update_stage0=yes" >> "$GITHUB_ENV"
|
||||
@@ -56,32 +52,11 @@ jobs:
|
||||
run: |
|
||||
echo "NPROC=$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 4)" >> $GITHUB_ENV
|
||||
shell: 'nix develop -c bash -euxo pipefail {0}'
|
||||
- name: Restore Cache
|
||||
if: env.should_update_stage0 == 'yes'
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
# NOTE: must be in sync with `restore-cache` in `build-template.yml`
|
||||
path: |
|
||||
.ccache
|
||||
build/stage1/**/*.trace
|
||||
build/stage1/**/*.olean*
|
||||
build/stage1/**/*.ilean
|
||||
build/stage1/**/*.ir
|
||||
build/stage1/**/*.c
|
||||
build/stage1/**/*.c.o*
|
||||
key: Linux Lake-build-v4-${{ github.sha }}
|
||||
# fall back to (latest) previous cache
|
||||
restore-keys: |
|
||||
Linux Lake-build-v4
|
||||
- if: env.should_update_stage0 == 'yes'
|
||||
# sync options with `Linux Lake` to ensure cache reuse
|
||||
run: |
|
||||
mkdir -p build
|
||||
cmake --preset release -B build -DLEAN_EXTRA_MAKE_OPTS=-DwarningAsError=true
|
||||
run: cmake --preset release
|
||||
shell: 'nix develop -c bash -euxo pipefail {0}'
|
||||
- if: env.should_update_stage0 == 'yes'
|
||||
run: |
|
||||
make -j$NPROC -C build update-stage0-commit
|
||||
run: make -j$NPROC -C build/release update-stage0-commit
|
||||
shell: 'nix develop -c bash -euxo pipefail {0}'
|
||||
- if: env.should_update_stage0 == 'yes'
|
||||
run: git show --stat
|
||||
|
||||
@@ -147,10 +147,6 @@ add_custom_target(test
|
||||
COMMAND $(MAKE) -C stage1 test
|
||||
DEPENDS stage1)
|
||||
|
||||
add_custom_target(clean-stdlib
|
||||
COMMAND $(MAKE) -C stage1 clean-stdlib
|
||||
DEPENDS stage1)
|
||||
|
||||
install(CODE "execute_process(COMMAND make -C stage1 install)")
|
||||
|
||||
add_custom_target(check-stage3
|
||||
|
||||
@@ -45,10 +45,3 @@
|
||||
/src/Std/Tactic/BVDecide/ @hargoniX
|
||||
/src/Lean/Elab/Tactic/BVDecide/ @hargoniX
|
||||
/src/Std/Sat/ @hargoniX
|
||||
/src/Std/Do @sgraf812
|
||||
/src/Std/Tactic/Do @sgraf812
|
||||
/src/Lean/Elab/Tactic/Do @sgraf812
|
||||
/src/Init/Data/Range/Polymorphic @datokrat
|
||||
/src/Init/Data/Slice @datokrat
|
||||
/src/Init/Data/Iterators @datokrat
|
||||
/src/Std/Data/Iterators @datokrat
|
||||
|
||||
@@ -2,19 +2,19 @@ This is the repository for **Lean 4**.
|
||||
|
||||
# About
|
||||
|
||||
- [Quickstart](https://lean-lang.org/install/)
|
||||
- [Quickstart](https://lean-lang.org/documentation/setup/)
|
||||
- [Homepage](https://lean-lang.org)
|
||||
- [Theorem Proving Tutorial](https://lean-lang.org/theorem_proving_in_lean4/)
|
||||
- [Functional Programming in Lean](https://lean-lang.org/functional_programming_in_lean/)
|
||||
- [Documentation Overview](https://lean-lang.org/learn/)
|
||||
- [Documentation Overview](https://lean-lang.org/documentation/)
|
||||
- [Language Reference](https://lean-lang.org/doc/reference/latest/)
|
||||
- [Release notes](RELEASES.md) starting at v4.0.0-m3
|
||||
- [Examples](https://lean-lang.org/examples/)
|
||||
- [Examples](https://lean-lang.org/documentation/examples/)
|
||||
- [External Contribution Guidelines](CONTRIBUTING.md)
|
||||
|
||||
# Installation
|
||||
|
||||
See [Install Lean](https://lean-lang.org/install/).
|
||||
See [Setting Up Lean](https://lean-lang.org/documentation/setup/).
|
||||
|
||||
# Contributing
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Lean Build Bootstrapping
|
||||
|
||||
Lean is a bootstrapped program: the
|
||||
Since version 4, Lean is a partially bootstrapped program: most parts of the
|
||||
frontend and compiler are written in Lean itself and thus need to be built before
|
||||
building Lean itself - which is needed to again build those parts. This cycle is
|
||||
broken by using pre-built C files checked into the repository (which ultimately
|
||||
@@ -73,11 +73,6 @@ update the archived C source code of the stage 0 compiler in `stage0/src`.
|
||||
The github repository will automatically update stage0 on `master` once
|
||||
`src/stdlib_flags.h` and `stage0/src/stdlib_flags.h` are out of sync.
|
||||
|
||||
NOTE: A full rebuild of stage 1 will only be triggered when the *committed* contents of `stage0/` are changed.
|
||||
Thus if you change files in it manually instead of through `update-stage0-commit` (see below) or fetching updates from git, you either need to commit those changes first or run `make -C build/release clean-stdlib`.
|
||||
The same is true for further stages except that a rebuild of them is retriggered on any committed change, not just to a specific directory.
|
||||
Thus when debugging e.g. stage 2 failures, you can resume the build from these failures on but may want to explicitly call `clean-stdlib` to either observe changes from `.olean` files of modules that built successfully or to check that you did not break modules that built successfully at some prior point.
|
||||
|
||||
If you have write access to the lean4 repository, you can also manually
|
||||
trigger that process, for example to be able to use new features in the compiler itself.
|
||||
You can do that on <https://github.com/leanprover/lean4/actions/workflows/update-stage0.yml>
|
||||
@@ -87,13 +82,13 @@ gh workflow run update-stage0.yml
|
||||
```
|
||||
|
||||
Leaving stage0 updates to the CI automation is preferable, but should you need
|
||||
to do it locally, you can use `make -C build/release update-stage0-commit` to
|
||||
update `stage0` from `stage1` or `make -C build/release/stageN update-stage0-commit` to
|
||||
to do it locally, you can use `make update-stage0-commit` in `build/release` to
|
||||
update `stage0` from `stage1` or `make -C stageN update-stage0-commit` to
|
||||
update from another stage. This command will automatically stage the updated files
|
||||
and introduce a commit, so make sure to commit your work before that.
|
||||
and introduce a commit,so make sure to commit your work before that.
|
||||
|
||||
If you rebased the branch (either onto a newer version of `master`, or fixing
|
||||
up some commits prior to the stage0 update), recreate the stage0 update commits.
|
||||
up some commits prior to the stage0 update, recreate the stage0 update commits.
|
||||
The script `script/rebase-stage0.sh` can be used for that.
|
||||
|
||||
The CI should prevent PRs with changes to stage0 (besides `stdlib_flags.h`)
|
||||
|
||||
@@ -8,8 +8,8 @@ You should not edit the `stage0` directory except using the commands described i
|
||||
|
||||
## Development Setup
|
||||
|
||||
You can use any of the [supported editors](https://lean-lang.org/install/manual/) for editing the Lean source code.
|
||||
Please see below for specific instructions for VS Code.
|
||||
You can use any of the [supported editors](../setup.md) for editing the Lean source code.
|
||||
If you set up `elan` as below, opening `src/` as a *workspace folder* should ensure that stage 0 (i.e. the stage that first compiles `src/`) will be used for files in that directory.
|
||||
|
||||
### Dev setup using elan
|
||||
|
||||
@@ -68,10 +68,6 @@ code lean.code-workspace
|
||||
```
|
||||
on the command line.
|
||||
|
||||
You can use the `Refresh File Dependencies` command as in other projects to rebuild modules from inside VS Code but be aware that this does not trigger any non-Lake build targets.
|
||||
In particular, after updating `stage0/` (or fetching an update to it), you will want to invoke `make` directly to rebuild `stage0/bin/lean` as described in [building Lean](../make/index.md).
|
||||
You should then run the `Restart Server` command to update all open files and the server watchdog process as well.
|
||||
|
||||
### `ccache`
|
||||
|
||||
Lean's build process uses [`ccache`](https://ccache.dev/) if it is
|
||||
@@ -99,19 +95,3 @@ on to `nightly-with-manual` branch. (It is fine to force push after rebasing.)
|
||||
CI will generate a branch of the reference manual called `lean-pr-testing-NNNN`
|
||||
in `leanprover/reference-manual`. This branch uses the toolchain for your PR,
|
||||
and will report back to the Lean PR with results from Mathlib CI.
|
||||
|
||||
### Avoiding rebuilds for downstream projects
|
||||
|
||||
If you want to test changes to Lean on downstream projects and would like to avoid rebuilding modules you have already built/fetched using the project's configured Lean toolchain, you can often do so as long as your build of Lean is close enough to that Lean toolchain (compatible .olean format including structure of all relevant environment extensions).
|
||||
|
||||
To override the toolchain without rebuilding for a single command, for example `lake build` or `lake lean`, you can use the prefix
|
||||
```
|
||||
LEAN_GITHASH=$(lean --githash) lake +lean4 ...
|
||||
```
|
||||
Alternatively, use
|
||||
```
|
||||
export LEAN_GITHASH=$(lean --githash)
|
||||
export ELAN_TOOLCHAIN=lean4
|
||||
```
|
||||
to persist these changes for the lifetime of the current shell, which will affect any processes spawned from it such as VS Code started via `code .`.
|
||||
If you use a setup where you cannot directly start your editor from the command line, such as VS Code Remote, you might want to consider using [direnv](https://direnv.net/) together with an editor extension for it instead so that you can put the lines above into `.envrc`.
|
||||
|
||||
@@ -59,7 +59,7 @@ All these tests are included by [src/shell/CMakeLists.txt](https://github.com/le
|
||||
open Foo in
|
||||
theorem tst2 (h : a ≤ b) : a + 2 ≤ b + 2 :=
|
||||
Bla.
|
||||
--^ completion
|
||||
--^ textDocument/completion
|
||||
```
|
||||
In this example, the test driver [`test_single.sh`](https://github.com/leanprover/lean4/tree/master/tests/lean/interactive/test_single.sh) will simulate an
|
||||
auto-completion request at `Bla.`. The expected output is stored in
|
||||
|
||||
@@ -282,7 +282,7 @@ theorem BinTree.find_insert_of_ne (b : BinTree β) (ne : k ≠ k') (v : β)
|
||||
let ⟨t, h⟩ := b; simp
|
||||
induction t with simp
|
||||
| leaf =>
|
||||
intro le
|
||||
intros le
|
||||
exact Nat.lt_of_le_of_ne le ne
|
||||
| node left key value right ihl ihr =>
|
||||
let .node hl hr bl br := h
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
These are instructions to set up a working development environment for those who wish to make changes to Lean itself. It is part of the [Development Guide](../dev/index.md).
|
||||
|
||||
We strongly suggest that new users instead follow the [Installation Instructions](https://lean-lang.org/install/) to get started using Lean, since this sets up an environment that can automatically manage multiple Lean toolchain versions, which is necessary when working within the Lean ecosystem.
|
||||
We strongly suggest that new users instead follow the [Quickstart](../quickstart.md) to get started using Lean, since this sets up an environment that can automatically manage multiple Lean toolchain versions, which is necessary when working within the Lean ecosystem.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
@@ -44,12 +44,12 @@ Useful CMake Configuration Settings
|
||||
Pass these along with the `cmake --preset release` command.
|
||||
There are also two alternative presets that combine some of these options you can use instead of `release`: `debug` and `sandebug` (sanitize + debug).
|
||||
|
||||
* `-DCMAKE_BUILD_TYPE=`\
|
||||
* `-D CMAKE_BUILD_TYPE=`\
|
||||
Select the build type. Valid values are `RELEASE` (default), `DEBUG`,
|
||||
`RELWITHDEBINFO`, and `MINSIZEREL`.
|
||||
|
||||
* `-DCMAKE_C_COMPILER=`\
|
||||
`-DCMAKE_CXX_COMPILER=`\
|
||||
* `-D CMAKE_C_COMPILER=`\
|
||||
`-D CMAKE_CXX_COMPILER=`\
|
||||
Select the C/C++ compilers to use. Official Lean releases currently use Clang;
|
||||
see also `.github/workflows/ci.yml` for the CI config.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Install Packages on OS X
|
||||
# Install Packages on OS X 14.5
|
||||
|
||||
We assume that you are using [homebrew][homebrew] as a package manager.
|
||||
|
||||
@@ -6,23 +6,23 @@ We assume that you are using [homebrew][homebrew] as a package manager.
|
||||
|
||||
## Compilers
|
||||
|
||||
You need a C++14-compatible compiler to build Lean. As of July
|
||||
2025, you have three options:
|
||||
You need a C++11-compatible compiler to build Lean. As of November
|
||||
2014, you have three options:
|
||||
|
||||
- clang++ shipped with OSX (at time of writing v17.0.0)
|
||||
- clang++ via homebrew (at time of writing, v20.1.8)
|
||||
- gcc via homebrew (at time of writing, v15.1.0)
|
||||
- clang++-3.5 (shipped with OSX, Apple LLVM version 6.0)
|
||||
- gcc-4.9.1 (homebrew)
|
||||
- clang++-3.5 (homebrew)
|
||||
|
||||
We recommend to use Apple's clang++ because it is pre-shipped with OS
|
||||
X and requires no further installation.
|
||||
|
||||
To install gcc via homebrew, please execute:
|
||||
To install gcc-4.9.1 via homebrew, please execute:
|
||||
```bash
|
||||
brew install gcc
|
||||
```
|
||||
To install clang via homebrew, please execute:
|
||||
To install clang++-3.5 via homebrew, please execute:
|
||||
```bash
|
||||
brew install llvm lld
|
||||
brew install llvm
|
||||
```
|
||||
To use compilers other than the default one (Apple's clang++), you
|
||||
need to use `-DCMAKE_CXX_COMPILER` option to specify the compiler
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import Grove.Framework
|
||||
import GroveStdlib.Generated.«associative-query-operations»
|
||||
import GroveStdlib.Generated.«associative-creation-operations»
|
||||
import GroveStdlib.Generated.«associative-modification-operations»
|
||||
import GroveStdlib.Generated.«associative-create-then-query»
|
||||
import GroveStdlib.Generated.«associative-all-operations-covered»
|
||||
|
||||
/-
|
||||
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
|
||||
@@ -16,7 +12,3 @@ namespace GroveStdlib.Generated
|
||||
|
||||
def restoreState : RestoreStateM Unit := do
|
||||
«associative-query-operations».restoreState
|
||||
«associative-creation-operations».restoreState
|
||||
«associative-modification-operations».restoreState
|
||||
«associative-create-then-query».restoreState
|
||||
«associative-all-operations-covered».restoreState
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
import Grove.Framework
|
||||
|
||||
/-
|
||||
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
|
||||
conflicts, but be careful.
|
||||
-/
|
||||
|
||||
open Grove.Framework Widget
|
||||
|
||||
namespace GroveStdlib.Generated.«associative-all-operations-covered»
|
||||
|
||||
def «all-covered» : Assertion.Fact where
|
||||
widgetId := "associative-all-operations-covered"
|
||||
factId := "all-covered"
|
||||
assertionId := "all-covered"
|
||||
state := {
|
||||
assertionId := "all-covered"
|
||||
description := "All operations should be covered"
|
||||
passed := false
|
||||
message := "There were 19697 operations that were not covered."
|
||||
}
|
||||
metadata := {
|
||||
status := .bad
|
||||
comment := "Still missing some!"
|
||||
}
|
||||
|
||||
def table : Assertion.Data where
|
||||
widgetId := "associative-all-operations-covered"
|
||||
facts := #[
|
||||
«all-covered»,
|
||||
]
|
||||
|
||||
def restoreState : RestoreStateM Unit := do
|
||||
addAssertion table
|
||||
@@ -1,357 +0,0 @@
|
||||
import Grove.Framework
|
||||
|
||||
/-
|
||||
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
|
||||
conflicts, but be careful.
|
||||
-/
|
||||
|
||||
open Grove.Framework Widget
|
||||
|
||||
namespace GroveStdlib.Generated.«associative-create-then-query»
|
||||
|
||||
def «2cb3c441-9663-4ce7-9527-0f40fc29925a:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap» : Table.Fact .subexpression .subexpression .declaration where
|
||||
widgetId := "associative-create-then-query"
|
||||
factId := "2cb3c441-9663-4ce7-9527-0f40fc29925a:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap"
|
||||
rowAssociationId := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
|
||||
columnAssociationId := "01f88623-fa5f-4380-9772-b30f2fec5c94"
|
||||
selectedLayers := #["Std.DHashMap", "Std.DHashMap.Raw", "Std.ExtDHashMap", "Std.DTreeMap", "Std.DTreeMap.Raw", "Std.ExtDTreeMap", ]
|
||||
layerStates := #[
|
||||
{
|
||||
layerIdentifier := "Std.DHashMap"
|
||||
rowState :=
|
||||
|
||||
some ⟨"Std.DHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.emptyWithCapacity,
|
||||
renderedStatement := "Std.DHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.DHashMap α β",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.DHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.isEmpty,
|
||||
renderedStatement := "Std.DHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.DHashMap α β) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DHashMap.Raw"
|
||||
rowState :=
|
||||
|
||||
some ⟨"Std.DHashMap.Raw.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.Raw.emptyWithCapacity,
|
||||
renderedStatement := "Std.DHashMap.Raw.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} (capacity : Nat := 8) :\n Std.DHashMap.Raw α β",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.DHashMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.Raw.isEmpty,
|
||||
renderedStatement := "Std.DHashMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} (m : Std.DHashMap.Raw α β) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.ExtDHashMap"
|
||||
rowState :=
|
||||
|
||||
some ⟨"Std.ExtDHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDHashMap.emptyWithCapacity,
|
||||
renderedStatement := "Std.ExtDHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.ExtDHashMap α β",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.ExtDHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDHashMap.isEmpty,
|
||||
renderedStatement := "Std.ExtDHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [EquivBEq α] [LawfulHashable α] (m : Std.ExtDHashMap α β) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DTreeMap"
|
||||
rowState :=
|
||||
|
||||
some ⟨"Std.DTreeMap.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.empty,
|
||||
renderedStatement := "Std.DTreeMap.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} :\n Std.DTreeMap α β cmp",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.DTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.isEmpty,
|
||||
renderedStatement := "Std.DTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap α β cmp) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DTreeMap.Raw"
|
||||
rowState :=
|
||||
|
||||
some ⟨"Std.DTreeMap.Raw.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.empty,
|
||||
renderedStatement := "Std.DTreeMap.Raw.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} :\n Std.DTreeMap.Raw α β cmp",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.DTreeMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.isEmpty,
|
||||
renderedStatement := "Std.DTreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.ExtDTreeMap"
|
||||
rowState :=
|
||||
|
||||
some ⟨"Std.ExtDTreeMap.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.empty,
|
||||
renderedStatement := "Std.ExtDTreeMap.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} :\n Std.ExtDTreeMap α β cmp",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.ExtDTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.isEmpty,
|
||||
renderedStatement := "Std.ExtDTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.ExtDTreeMap α β cmp) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
]
|
||||
},
|
||||
]
|
||||
metadata := {
|
||||
status := .done
|
||||
comment := "Not necessary for `ExtDHashMap` because of simp lemma turning into varno"
|
||||
}
|
||||
|
||||
def «5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap» : Table.Fact .subexpression .subexpression .declaration where
|
||||
widgetId := "associative-create-then-query"
|
||||
factId := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap"
|
||||
rowAssociationId := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
|
||||
columnAssociationId := "01f88623-fa5f-4380-9772-b30f2fec5c94"
|
||||
selectedLayers := #["Std.DHashMap", "Std.DHashMap.Raw", "Std.ExtDHashMap", "Std.DTreeMap", "Std.DTreeMap.Raw", "Std.ExtDTreeMap", ]
|
||||
layerStates := #[
|
||||
{
|
||||
layerIdentifier := "Std.DHashMap"
|
||||
rowState :=
|
||||
|
||||
some ⟨"app (EmptyCollection.emptyCollection) (Std.DHashMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.DHashMap*)", displayShort := "∅" }⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.DHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.isEmpty,
|
||||
renderedStatement := "Std.DHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.DHashMap α β) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
⟨"Std.DHashMap.isEmpty_empty", Grove.Framework.Declaration.thm
|
||||
{ name := `Std.DHashMap.isEmpty_empty,
|
||||
renderedStatement := "Std.DHashMap.isEmpty_empty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} :\n ∅.isEmpty = true",
|
||||
isSimp := true,
|
||||
isDeprecated := false }⟩
|
||||
,
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DHashMap.Raw"
|
||||
rowState :=
|
||||
|
||||
some ⟨"app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)", displayShort := "∅" }⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.DHashMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.Raw.isEmpty,
|
||||
renderedStatement := "Std.DHashMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} (m : Std.DHashMap.Raw α β) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
⟨"Std.DHashMap.Raw.isEmpty_emptyc", Grove.Framework.Declaration.thm
|
||||
{ name := `Std.DHashMap.Raw.isEmpty_emptyc,
|
||||
renderedStatement := "Std.DHashMap.Raw.isEmpty_emptyc.{u_1, u_2} {α : Type u_1} {β : α → Type u_2} [BEq α] [Hashable α] :\n ∅.isEmpty = true",
|
||||
isSimp := false,
|
||||
isDeprecated := true }⟩
|
||||
,
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.ExtDHashMap"
|
||||
rowState :=
|
||||
|
||||
some ⟨"app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)", displayShort := "∅" }⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.ExtDHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDHashMap.isEmpty,
|
||||
renderedStatement := "Std.ExtDHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [EquivBEq α] [LawfulHashable α] (m : Std.ExtDHashMap α β) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DTreeMap"
|
||||
rowState :=
|
||||
|
||||
some ⟨"app (EmptyCollection.emptyCollection) (Std.DTreeMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.DTreeMap*)", displayShort := "∅" }⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.DTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.isEmpty,
|
||||
renderedStatement := "Std.DTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap α β cmp) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
⟨"Std.DTreeMap.isEmpty_emptyc", Grove.Framework.Declaration.thm
|
||||
{ name := `Std.DTreeMap.isEmpty_emptyc,
|
||||
renderedStatement := "Std.DTreeMap.isEmpty_emptyc.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} :\n ∅.isEmpty = true",
|
||||
isSimp := true,
|
||||
isDeprecated := false }⟩
|
||||
,
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DTreeMap.Raw"
|
||||
rowState :=
|
||||
|
||||
some ⟨"app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)", displayShort := "∅" }⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.DTreeMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.isEmpty,
|
||||
renderedStatement := "Std.DTreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
⟨"Std.DTreeMap.Raw.isEmpty_emptyc", Grove.Framework.Declaration.thm
|
||||
{ name := `Std.DTreeMap.Raw.isEmpty_emptyc,
|
||||
renderedStatement := "Std.DTreeMap.Raw.isEmpty_emptyc.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} :\n ∅.isEmpty = true",
|
||||
isSimp := true,
|
||||
isDeprecated := false }⟩
|
||||
,
|
||||
]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.ExtDTreeMap"
|
||||
rowState :=
|
||||
|
||||
some ⟨"app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)", displayShort := "∅" }⟩
|
||||
|
||||
columnState :=
|
||||
|
||||
some ⟨"Std.ExtDTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.isEmpty,
|
||||
renderedStatement := "Std.ExtDTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.ExtDTreeMap α β cmp) : Bool",
|
||||
isDeprecated := false })⟩
|
||||
|
||||
selectedCellStates := #[
|
||||
⟨"Std.ExtDTreeMap.isEmpty_empty", Grove.Framework.Declaration.thm
|
||||
{ name := `Std.ExtDTreeMap.isEmpty_empty,
|
||||
renderedStatement := "Std.ExtDTreeMap.isEmpty_empty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} :\n ∅.isEmpty = true",
|
||||
isSimp := true,
|
||||
isDeprecated := false }⟩
|
||||
,
|
||||
]
|
||||
},
|
||||
]
|
||||
metadata := {
|
||||
status := .bad
|
||||
comment := "Missing for `ExtDHashMap`"
|
||||
}
|
||||
|
||||
def table : Table.Data .subexpression .subexpression .declaration where
|
||||
widgetId := "associative-create-then-query"
|
||||
selectedRowAssociations := #["2cb3c441-9663-4ce7-9527-0f40fc29925a", "7743a485-024d-43b6-bd5f-ebd3182eb94d", "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d", ]
|
||||
selectedColumnAssociations := #["01f88623-fa5f-4380-9772-b30f2fec5c94", "f084f852-af71-45b6-8ab3-d251a8144f72", ]
|
||||
selectedLayers := #["Std.DHashMap", "Std.DHashMap.Raw", "Std.ExtDHashMap", "Std.DTreeMap", "Std.DTreeMap.Raw", "Std.ExtDTreeMap", ]
|
||||
selectedCellOptions := #[
|
||||
{
|
||||
layerIdentifier := "Std.DHashMap"
|
||||
rowValue := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
|
||||
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
|
||||
selectedCellOptions := #["Std.DHashMap.isEmpty_emptyWithCapacity", ]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DHashMap.Raw"
|
||||
rowValue := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
|
||||
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
|
||||
selectedCellOptions := #["Std.DHashMap.Raw.isEmpty_emptyWithCapacity", ]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DHashMap"
|
||||
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
|
||||
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
|
||||
selectedCellOptions := #["Std.DHashMap.isEmpty_empty", ]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DHashMap.Raw"
|
||||
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
|
||||
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
|
||||
selectedCellOptions := #["Std.DHashMap.Raw.isEmpty_emptyc", ]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DTreeMap"
|
||||
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
|
||||
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
|
||||
selectedCellOptions := #["Std.DTreeMap.isEmpty_emptyc", ]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.DTreeMap.Raw"
|
||||
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
|
||||
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
|
||||
selectedCellOptions := #["Std.DTreeMap.Raw.isEmpty_emptyc", ]
|
||||
},
|
||||
{
|
||||
layerIdentifier := "Std.ExtDTreeMap"
|
||||
rowValue := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
|
||||
columnValue := "01f88623-fa5f-4380-9772-b30f2fec5c94"
|
||||
selectedCellOptions := #["Std.ExtDTreeMap.isEmpty_empty", ]
|
||||
},
|
||||
]
|
||||
facts := #[
|
||||
«2cb3c441-9663-4ce7-9527-0f40fc29925a:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap»,
|
||||
«5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d:::01f88623-fa5f-4380-9772-b30f2fec5c94:::Std.DHashMap::Std.DHashMap.Raw::Std.ExtDHashMap::Std.DTreeMap::Std.DTreeMap.Raw::Std.ExtDTreeMap»,
|
||||
]
|
||||
|
||||
def restoreState : RestoreStateM Unit := do
|
||||
addTable table
|
||||
@@ -1,216 +0,0 @@
|
||||
import Grove.Framework
|
||||
|
||||
/-
|
||||
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
|
||||
conflicts, but be careful.
|
||||
-/
|
||||
|
||||
open Grove.Framework Widget
|
||||
|
||||
namespace GroveStdlib.Generated.«associative-creation-operations»
|
||||
|
||||
def «2cb3c441-9663-4ce7-9527-0f40fc29925a» : AssociationTable.Fact .subexpression where
|
||||
widgetId := "associative-creation-operations"
|
||||
factId := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
|
||||
rowId := "2cb3c441-9663-4ce7-9527-0f40fc29925a"
|
||||
rowState := #[⟨"Std.DHashMap", "Std.DHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.emptyWithCapacity,
|
||||
renderedStatement := "Std.DHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.DHashMap α β",
|
||||
isDeprecated := false })⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.Raw.emptyWithCapacity,
|
||||
renderedStatement := "Std.DHashMap.Raw.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} (capacity : Nat := 8) :\n Std.DHashMap.Raw α β",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDHashMap.emptyWithCapacity,
|
||||
renderedStatement := "Std.ExtDHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.ExtDHashMap α β",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap", "Std.DTreeMap.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.empty,
|
||||
renderedStatement := "Std.DTreeMap.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} :\n Std.DTreeMap α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.empty,
|
||||
renderedStatement := "Std.DTreeMap.Raw.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} :\n Std.DTreeMap.Raw α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.empty,
|
||||
renderedStatement := "Std.ExtDTreeMap.empty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} :\n Std.ExtDTreeMap α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap", "Std.HashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.emptyWithCapacity,
|
||||
renderedStatement := "Std.HashMap.emptyWithCapacity.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.HashMap α β",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap.Raw", "Std.HashMap.Raw.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.Raw.emptyWithCapacity,
|
||||
renderedStatement := "Std.HashMap.Raw.emptyWithCapacity.{u, v} {α : Type u} {β : Type v} (capacity : Nat := 8) :\n Std.HashMap.Raw α β",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashMap", "Std.ExtHashMap.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashMap.emptyWithCapacity,
|
||||
renderedStatement := "Std.ExtHashMap.emptyWithCapacity.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α]\n (capacity : Nat := 8) : Std.ExtHashMap α β",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap", "Std.TreeMap.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.empty,
|
||||
renderedStatement := "Std.TreeMap.empty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} : Std.TreeMap α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.Raw.empty,
|
||||
renderedStatement := "Std.TreeMap.Raw.empty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} :\n Std.TreeMap.Raw α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeMap.empty,
|
||||
renderedStatement := "Std.ExtTreeMap.empty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} :\n Std.ExtTreeMap α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet", "Std.HashSet.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.emptyWithCapacity,
|
||||
renderedStatement := "Std.HashSet.emptyWithCapacity.{u} {α : Type u} [BEq α] [Hashable α] (capacity : Nat := 8) :\n Std.HashSet α",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.Raw.emptyWithCapacity,
|
||||
renderedStatement := "Std.HashSet.Raw.emptyWithCapacity.{u} {α : Type u} (capacity : Nat := 8) : Std.HashSet.Raw α",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashSet", "Std.ExtHashSet.emptyWithCapacity", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashSet.emptyWithCapacity,
|
||||
renderedStatement := "Std.ExtHashSet.emptyWithCapacity.{u} {α : Type u} [BEq α] [Hashable α] (capacity : Nat := 8) :\n Std.ExtHashSet α",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet", "Std.TreeSet.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.empty,
|
||||
renderedStatement := "Std.TreeSet.empty.{u} {α : Type u} {cmp : α → α → Ordering} : Std.TreeSet α cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.Raw.empty,
|
||||
renderedStatement := "Std.TreeSet.Raw.empty.{u} {α : Type u} {cmp : α → α → Ordering} : Std.TreeSet.Raw α cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.empty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeSet.empty,
|
||||
renderedStatement := "Std.ExtTreeSet.empty.{u} {α : Type u} {cmp : α → α → Ordering} : Std.ExtTreeSet α cmp",
|
||||
isDeprecated := false })⟩,]
|
||||
metadata := {
|
||||
status := .done
|
||||
comment := ""
|
||||
}
|
||||
def «7743a485-024d-43b6-bd5f-ebd3182eb94d» : AssociationTable.Fact .subexpression where
|
||||
widgetId := "associative-creation-operations"
|
||||
factId := "7743a485-024d-43b6-bd5f-ebd3182eb94d"
|
||||
rowId := "7743a485-024d-43b6-bd5f-ebd3182eb94d"
|
||||
rowState := #[⟨"Std.DHashMap", "Std.DHashMap.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.ofList,
|
||||
renderedStatement := "Std.DHashMap.ofList.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (l : List ((a : α) × β a)) : Std.DHashMap α β",
|
||||
isDeprecated := false })⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.Raw.ofList,
|
||||
renderedStatement := "Std.DHashMap.Raw.ofList.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (l : List ((a : α) × β a)) : Std.DHashMap.Raw α β",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDHashMap.ofList,
|
||||
renderedStatement := "Std.ExtDHashMap.ofList.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α]\n (l : List ((a : α) × β a)) : Std.ExtDHashMap α β",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap", "Std.DTreeMap.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.ofList,
|
||||
renderedStatement := "Std.DTreeMap.ofList.{u, v} {α : Type u} {β : α → Type v} (l : List ((a : α) × β a))\n (cmp : α → α → Ordering := by exact compare) : Std.DTreeMap α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.ofList,
|
||||
renderedStatement := "Std.DTreeMap.Raw.ofList.{u, v} {α : Type u} {β : α → Type v} (l : List ((a : α) × β a))\n (cmp : α → α → Ordering := by exact compare) : Std.DTreeMap.Raw α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.ofList,
|
||||
renderedStatement := "Std.ExtDTreeMap.ofList.{u, v} {α : Type u} {β : α → Type v} (l : List ((a : α) × β a))\n (cmp : α → α → Ordering := by exact compare) : Std.ExtDTreeMap α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap", "Std.HashMap.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.ofList,
|
||||
renderedStatement := "Std.HashMap.ofList.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (l : List (α × β)) :\n Std.HashMap α β",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap.Raw", "Std.HashMap.Raw.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.Raw.ofList,
|
||||
renderedStatement := "Std.HashMap.Raw.ofList.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (l : List (α × β)) :\n Std.HashMap.Raw α β",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashMap", "Std.ExtHashMap.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashMap.ofList,
|
||||
renderedStatement := "Std.ExtHashMap.ofList.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (l : List (α × β)) :\n Std.ExtHashMap α β",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap", "Std.TreeMap.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.ofList,
|
||||
renderedStatement := "Std.TreeMap.ofList.{u, v} {α : Type u} {β : Type v} (l : List (α × β))\n (cmp : α → α → Ordering := by exact compare) : Std.TreeMap α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.Raw.ofList,
|
||||
renderedStatement := "Std.TreeMap.Raw.ofList.{u, v} {α : Type u} {β : Type v} (l : List (α × β))\n (cmp : α → α → Ordering := by exact compare) : Std.TreeMap.Raw α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeMap.ofList,
|
||||
renderedStatement := "Std.ExtTreeMap.ofList.{u, v} {α : Type u} {β : Type v} (l : List (α × β))\n (cmp : α → α → Ordering := by exact compare) : Std.ExtTreeMap α β cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet", "Std.HashSet.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.ofList,
|
||||
renderedStatement := "Std.HashSet.ofList.{u} {α : Type u} [BEq α] [Hashable α] (l : List α) : Std.HashSet α",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.Raw.ofList,
|
||||
renderedStatement := "Std.HashSet.Raw.ofList.{u} {α : Type u} [BEq α] [Hashable α] (l : List α) : Std.HashSet.Raw α",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashSet", "Std.ExtHashSet.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashSet.ofList,
|
||||
renderedStatement := "Std.ExtHashSet.ofList.{u} {α : Type u} [BEq α] [Hashable α] (l : List α) : Std.ExtHashSet α",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet", "Std.TreeSet.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.ofList,
|
||||
renderedStatement := "Std.TreeSet.ofList.{u} {α : Type u} (l : List α) (cmp : α → α → Ordering := by exact compare) :\n Std.TreeSet α cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.Raw.ofList,
|
||||
renderedStatement := "Std.TreeSet.Raw.ofList.{u} {α : Type u} (l : List α) (cmp : α → α → Ordering := by exact compare) :\n Std.TreeSet.Raw α cmp",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.ofList", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeSet.ofList,
|
||||
renderedStatement := "Std.ExtTreeSet.ofList.{u} {α : Type u} (l : List α) (cmp : α → α → Ordering := by exact compare) :\n Std.ExtTreeSet α cmp",
|
||||
isDeprecated := false })⟩,]
|
||||
metadata := {
|
||||
status := .done
|
||||
comment := ""
|
||||
}
|
||||
def «5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d» : AssociationTable.Fact .subexpression where
|
||||
widgetId := "associative-creation-operations"
|
||||
factId := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
|
||||
rowId := "5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d"
|
||||
rowState := #[⟨"Std.DHashMap", "app (EmptyCollection.emptyCollection) (Std.DHashMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.DHashMap*)", displayShort := "∅" }⟩,⟨"Std.DHashMap.Raw", "app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)", displayShort := "∅" }⟩,⟨"Std.ExtDHashMap", "app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)", displayShort := "∅" }⟩,⟨"Std.DTreeMap", "app (EmptyCollection.emptyCollection) (Std.DTreeMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.DTreeMap*)", displayShort := "∅" }⟩,⟨"Std.DTreeMap.Raw", "app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)", displayShort := "∅" }⟩,⟨"Std.ExtDTreeMap", "app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)", displayShort := "∅" }⟩,⟨"Std.HashMap", "app (EmptyCollection.emptyCollection) (Std.HashMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.HashMap*)", displayShort := "∅" }⟩,⟨"Std.HashMap.Raw", "app (EmptyCollection.emptyCollection) (Std.HashMap.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.HashMap.Raw*)", displayShort := "∅" }⟩,⟨"Std.ExtHashMap", "app (EmptyCollection.emptyCollection) (Std.ExtHashMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtHashMap*)", displayShort := "∅" }⟩,⟨"Std.TreeMap", "app (EmptyCollection.emptyCollection) (Std.TreeMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.TreeMap*)", displayShort := "∅" }⟩,⟨"Std.TreeMap.Raw", "app (EmptyCollection.emptyCollection) (Std.TreeMap.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.TreeMap.Raw*)", displayShort := "∅" }⟩,⟨"Std.ExtTreeMap", "app (EmptyCollection.emptyCollection) (Std.ExtTreeMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtTreeMap*)", displayShort := "∅" }⟩,⟨"Std.HashSet", "app (EmptyCollection.emptyCollection) (Std.HashSet*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.HashSet*)", displayShort := "∅" }⟩,⟨"Std.HashSet.Raw", "app (EmptyCollection.emptyCollection) (Std.HashSet.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.HashSet.Raw*)", displayShort := "∅" }⟩,⟨"Std.ExtHashSet", "app (EmptyCollection.emptyCollection) (Std.ExtHashSet*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtHashSet*)", displayShort := "∅" }⟩,⟨"Std.TreeSet", "app (EmptyCollection.emptyCollection) (Std.TreeSet*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.TreeSet*)", displayShort := "∅" }⟩,⟨"Std.TreeSet.Raw", "app (EmptyCollection.emptyCollection) (Std.TreeSet.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.TreeSet.Raw*)", displayShort := "∅" }⟩,⟨"Std.ExtTreeSet", "app (EmptyCollection.emptyCollection) (Std.ExtTreeSet*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (EmptyCollection.emptyCollection) (Std.ExtTreeSet*)", displayShort := "∅" }⟩,]
|
||||
metadata := {
|
||||
status := .done
|
||||
comment := ""
|
||||
}
|
||||
|
||||
def table : AssociationTable.Data .subexpression where
|
||||
widgetId := "associative-creation-operations"
|
||||
rows := #[
|
||||
⟨"2cb3c441-9663-4ce7-9527-0f40fc29925a", "empty", #[⟨"Std.DHashMap", "Std.DHashMap.emptyWithCapacity"⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.emptyWithCapacity"⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.emptyWithCapacity"⟩,⟨"Std.DTreeMap", "Std.DTreeMap.empty"⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.empty"⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.empty"⟩,⟨"Std.HashMap", "Std.HashMap.emptyWithCapacity"⟩,⟨"Std.HashMap.Raw", "Std.HashMap.Raw.emptyWithCapacity"⟩,⟨"Std.ExtHashMap", "Std.ExtHashMap.emptyWithCapacity"⟩,⟨"Std.TreeMap", "Std.TreeMap.empty"⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.empty"⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.empty"⟩,⟨"Std.HashSet", "Std.HashSet.emptyWithCapacity"⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.emptyWithCapacity"⟩,⟨"Std.ExtHashSet", "Std.ExtHashSet.emptyWithCapacity"⟩,⟨"Std.TreeSet", "Std.TreeSet.empty"⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.empty"⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.empty"⟩,]⟩,
|
||||
⟨"7743a485-024d-43b6-bd5f-ebd3182eb94d", "ofList", #[⟨"Std.DHashMap", "Std.DHashMap.ofList"⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.ofList"⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.ofList"⟩,⟨"Std.DTreeMap", "Std.DTreeMap.ofList"⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.ofList"⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.ofList"⟩,⟨"Std.HashMap", "Std.HashMap.ofList"⟩,⟨"Std.HashMap.Raw", "Std.HashMap.Raw.ofList"⟩,⟨"Std.ExtHashMap", "Std.ExtHashMap.ofList"⟩,⟨"Std.TreeMap", "Std.TreeMap.ofList"⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.ofList"⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.ofList"⟩,⟨"Std.HashSet", "Std.HashSet.ofList"⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.ofList"⟩,⟨"Std.ExtHashSet", "Std.ExtHashSet.ofList"⟩,⟨"Std.TreeSet", "Std.TreeSet.ofList"⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.ofList"⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.ofList"⟩,]⟩,
|
||||
⟨"5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d", "emptyCollection", #[⟨"Std.DHashMap", "app (EmptyCollection.emptyCollection) (Std.DHashMap*)"⟩,⟨"Std.DHashMap.Raw", "app (EmptyCollection.emptyCollection) (Std.DHashMap.Raw*)"⟩,⟨"Std.ExtDHashMap", "app (EmptyCollection.emptyCollection) (Std.ExtDHashMap*)"⟩,⟨"Std.DTreeMap", "app (EmptyCollection.emptyCollection) (Std.DTreeMap*)"⟩,⟨"Std.DTreeMap.Raw", "app (EmptyCollection.emptyCollection) (Std.DTreeMap.Raw*)"⟩,⟨"Std.ExtDTreeMap", "app (EmptyCollection.emptyCollection) (Std.ExtDTreeMap*)"⟩,⟨"Std.HashMap", "app (EmptyCollection.emptyCollection) (Std.HashMap*)"⟩,⟨"Std.HashMap.Raw", "app (EmptyCollection.emptyCollection) (Std.HashMap.Raw*)"⟩,⟨"Std.ExtHashMap", "app (EmptyCollection.emptyCollection) (Std.ExtHashMap*)"⟩,⟨"Std.TreeMap", "app (EmptyCollection.emptyCollection) (Std.TreeMap*)"⟩,⟨"Std.TreeMap.Raw", "app (EmptyCollection.emptyCollection) (Std.TreeMap.Raw*)"⟩,⟨"Std.ExtTreeMap", "app (EmptyCollection.emptyCollection) (Std.ExtTreeMap*)"⟩,⟨"Std.HashSet", "app (EmptyCollection.emptyCollection) (Std.HashSet*)"⟩,⟨"Std.HashSet.Raw", "app (EmptyCollection.emptyCollection) (Std.HashSet.Raw*)"⟩,⟨"Std.ExtHashSet", "app (EmptyCollection.emptyCollection) (Std.ExtHashSet*)"⟩,⟨"Std.TreeSet", "app (EmptyCollection.emptyCollection) (Std.TreeSet*)"⟩,⟨"Std.TreeSet.Raw", "app (EmptyCollection.emptyCollection) (Std.TreeSet.Raw*)"⟩,⟨"Std.ExtTreeSet", "app (EmptyCollection.emptyCollection) (Std.ExtTreeSet*)"⟩,]⟩,
|
||||
]
|
||||
facts := #[
|
||||
«2cb3c441-9663-4ce7-9527-0f40fc29925a»,
|
||||
«7743a485-024d-43b6-bd5f-ebd3182eb94d»,
|
||||
«5ceaa26a-d2cb-4df3-9ac8-b5c11db2ae9d»,
|
||||
]
|
||||
|
||||
def restoreState : RestoreStateM Unit := do
|
||||
addAssociationTable table
|
||||
@@ -1,21 +0,0 @@
|
||||
import Grove.Framework
|
||||
|
||||
/-
|
||||
This file is autogenerated by grove. You can manually edit it, for example to resolve merge
|
||||
conflicts, but be careful.
|
||||
-/
|
||||
|
||||
open Grove.Framework Widget
|
||||
|
||||
namespace GroveStdlib.Generated.«associative-modification-operations»
|
||||
|
||||
|
||||
def table : AssociationTable.Data .subexpression where
|
||||
widgetId := "associative-modification-operations"
|
||||
rows := #[
|
||||
]
|
||||
facts := #[
|
||||
]
|
||||
|
||||
def restoreState : RestoreStateM Unit := do
|
||||
addAssociationTable table
|
||||
@@ -16,7 +16,7 @@ def «01f88623-fa5f-4380-9772-b30f2fec5c94» : AssociationTable.Fact .subexpress
|
||||
rowState := #[⟨"Std.DHashMap", "Std.DHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.isEmpty,
|
||||
renderedStatement := "Std.DHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.DHashMap α β) : Bool",
|
||||
renderedStatement := "Std.DHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.DHashMap α β) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.Raw.isEmpty,
|
||||
@@ -24,23 +24,23 @@ def «01f88623-fa5f-4380-9772-b30f2fec5c94» : AssociationTable.Fact .subexpress
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDHashMap.isEmpty,
|
||||
renderedStatement := "Std.ExtDHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [EquivBEq α] [LawfulHashable α] (m : Std.ExtDHashMap α β) : Bool",
|
||||
renderedStatement := "Std.ExtDHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtDHashMap α β) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap", "Std.DTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.isEmpty,
|
||||
renderedStatement := "Std.DTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap α β cmp) : Bool",
|
||||
renderedStatement := "Std.DTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.DTreeMap α β cmp) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.isEmpty,
|
||||
renderedStatement := "Std.DTreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) : Bool",
|
||||
renderedStatement := "Std.DTreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.DTreeMap.Raw α β cmp) :\n Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.isEmpty,
|
||||
renderedStatement := "Std.ExtDTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.ExtDTreeMap α β cmp) : Bool",
|
||||
renderedStatement := "Std.ExtDTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.ExtDTreeMap α β cmp) :\n Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap", "Std.HashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.isEmpty,
|
||||
renderedStatement := "Std.HashMap.isEmpty.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.HashMap α β) : Bool",
|
||||
renderedStatement := "Std.HashMap.isEmpty.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashMap α β) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap.Raw", "Std.HashMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.Raw.isEmpty,
|
||||
@@ -48,19 +48,19 @@ def «01f88623-fa5f-4380-9772-b30f2fec5c94» : AssociationTable.Fact .subexpress
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashMap", "Std.ExtHashMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashMap.isEmpty,
|
||||
renderedStatement := "Std.ExtHashMap.isEmpty.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtHashMap α β) : Bool",
|
||||
renderedStatement := "Std.ExtHashMap.isEmpty.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashMap α β) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap", "Std.TreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.isEmpty,
|
||||
renderedStatement := "Std.TreeMap.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.TreeMap α β cmp) : Bool",
|
||||
renderedStatement := "Std.TreeMap.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap α β cmp) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.Raw.isEmpty,
|
||||
renderedStatement := "Std.TreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.TreeMap.Raw α β cmp) : Bool",
|
||||
renderedStatement := "Std.TreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap.Raw α β cmp) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeMap.isEmpty,
|
||||
renderedStatement := "Std.ExtTreeMap.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.ExtTreeMap α β cmp) : Bool",
|
||||
renderedStatement := "Std.ExtTreeMap.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.ExtTreeMap α β cmp) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet", "Std.HashSet.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.isEmpty,
|
||||
@@ -72,7 +72,7 @@ def «01f88623-fa5f-4380-9772-b30f2fec5c94» : AssociationTable.Fact .subexpress
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashSet", "Std.ExtHashSet.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashSet.isEmpty,
|
||||
renderedStatement := "Std.ExtHashSet.isEmpty.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtHashSet α) : Bool",
|
||||
renderedStatement := "Std.ExtHashSet.isEmpty.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashSet α) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet", "Std.TreeSet.isEmpty", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.isEmpty,
|
||||
@@ -97,7 +97,7 @@ def «f084f852-af71-45b6-8ab3-d251a8144f72» : AssociationTable.Fact .subexpress
|
||||
rowState := #[⟨"Std.DHashMap", "Std.DHashMap.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.size,
|
||||
renderedStatement := "Std.DHashMap.size.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.DHashMap α β) : Nat",
|
||||
renderedStatement := "Std.DHashMap.size.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.DHashMap α β) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.Raw.size,
|
||||
@@ -105,23 +105,23 @@ def «f084f852-af71-45b6-8ab3-d251a8144f72» : AssociationTable.Fact .subexpress
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDHashMap.size,
|
||||
renderedStatement := "Std.ExtDHashMap.size.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [EquivBEq α] [LawfulHashable α] (m : Std.ExtDHashMap α β) : Nat",
|
||||
renderedStatement := "Std.ExtDHashMap.size.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtDHashMap α β) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap", "Std.DTreeMap.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.size,
|
||||
renderedStatement := "Std.DTreeMap.size.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap α β cmp) : Nat",
|
||||
renderedStatement := "Std.DTreeMap.size.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.DTreeMap α β cmp) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.size,
|
||||
renderedStatement := "Std.DTreeMap.Raw.size.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) : Nat",
|
||||
renderedStatement := "Std.DTreeMap.Raw.size.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.DTreeMap.Raw α β cmp) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.size,
|
||||
renderedStatement := "Std.ExtDTreeMap.size.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.ExtDTreeMap α β cmp) : Nat",
|
||||
renderedStatement := "Std.ExtDTreeMap.size.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.ExtDTreeMap α β cmp) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap", "Std.HashMap.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.size,
|
||||
renderedStatement := "Std.HashMap.size.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.HashMap α β) : Nat",
|
||||
renderedStatement := "Std.HashMap.size.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashMap α β) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap.Raw", "Std.HashMap.Raw.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.Raw.size,
|
||||
@@ -129,19 +129,19 @@ def «f084f852-af71-45b6-8ab3-d251a8144f72» : AssociationTable.Fact .subexpress
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashMap", "Std.ExtHashMap.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashMap.size,
|
||||
renderedStatement := "Std.ExtHashMap.size.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtHashMap α β) : Nat",
|
||||
renderedStatement := "Std.ExtHashMap.size.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashMap α β) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap", "Std.TreeMap.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.size,
|
||||
renderedStatement := "Std.TreeMap.size.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.TreeMap α β cmp) : Nat",
|
||||
renderedStatement := "Std.TreeMap.size.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap α β cmp) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.Raw.size,
|
||||
renderedStatement := "Std.TreeMap.Raw.size.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.TreeMap.Raw α β cmp) : Nat",
|
||||
renderedStatement := "Std.TreeMap.Raw.size.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap.Raw α β cmp) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeMap.size,
|
||||
renderedStatement := "Std.ExtTreeMap.size.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.ExtTreeMap α β cmp) : Nat",
|
||||
renderedStatement := "Std.ExtTreeMap.size.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.ExtTreeMap α β cmp) : Nat",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet", "Std.HashSet.size", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.size,
|
||||
@@ -178,11 +178,11 @@ def «f4e6fa70-5aed-439d-aaad-5f4ced65bf7b» : AssociationTable.Fact .subexpress
|
||||
rowState := #[⟨"Std.DTreeMap", "Std.DTreeMap.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.any,
|
||||
renderedStatement := "Std.DTreeMap.any.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap α β cmp) (p : (a : α) → β a → Bool) : Bool",
|
||||
renderedStatement := "Std.DTreeMap.any.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.DTreeMap α β cmp)\n (p : (a : α) → β a → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.any,
|
||||
renderedStatement := "Std.DTreeMap.Raw.any.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) (p : (a : α) → β a → Bool) : Bool",
|
||||
renderedStatement := "Std.DTreeMap.Raw.any.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.DTreeMap.Raw α β cmp)\n (p : (a : α) → β a → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.any,
|
||||
@@ -190,11 +190,11 @@ def «f4e6fa70-5aed-439d-aaad-5f4ced65bf7b» : AssociationTable.Fact .subexpress
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap", "Std.TreeMap.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.any,
|
||||
renderedStatement := "Std.TreeMap.any.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap α β cmp)\n (p : α → β → Bool) : Bool",
|
||||
renderedStatement := "Std.TreeMap.any.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap α β cmp) (p : α → β → Bool) :\n Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.Raw.any,
|
||||
renderedStatement := "Std.TreeMap.Raw.any.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.TreeMap.Raw α β cmp) (p : α → β → Bool) : Bool",
|
||||
renderedStatement := "Std.TreeMap.Raw.any.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap.Raw α β cmp)\n (p : α → β → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeMap.any,
|
||||
@@ -202,7 +202,7 @@ def «f4e6fa70-5aed-439d-aaad-5f4ced65bf7b» : AssociationTable.Fact .subexpress
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet", "Std.HashSet.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.any,
|
||||
renderedStatement := "Std.HashSet.any.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashSet α)\n (p : α → Bool) : Bool",
|
||||
renderedStatement := "Std.HashSet.any.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashSet α) (p : α → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.Raw.any,
|
||||
@@ -210,15 +210,15 @@ def «f4e6fa70-5aed-439d-aaad-5f4ced65bf7b» : AssociationTable.Fact .subexpress
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet", "Std.TreeSet.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.any,
|
||||
renderedStatement := "Std.TreeSet.any.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet α cmp) (p : α → Bool) :\n Bool",
|
||||
renderedStatement := "Std.TreeSet.any.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet α cmp) (p : α → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.Raw.any,
|
||||
renderedStatement := "Std.TreeSet.Raw.any.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet.Raw α cmp)\n (p : α → Bool) : Bool",
|
||||
renderedStatement := "Std.TreeSet.Raw.any.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet.Raw α cmp) (p : α → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.any", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeSet.any,
|
||||
renderedStatement := "Std.ExtTreeSet.any.{u} {α : Type u} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeSet α cmp) (p : α → Bool) : Bool",
|
||||
renderedStatement := "Std.ExtTreeSet.any.{u} {α : Type u} {cmp : α → α → Ordering} [Std.TransCmp cmp] (t : Std.ExtTreeSet α cmp)\n (p : α → Bool) : Bool",
|
||||
isDeprecated := false })⟩,]
|
||||
metadata := {
|
||||
status := .bad
|
||||
@@ -228,51 +228,62 @@ def «c1d181f6-3204-4956-946f-e81619f9feb4» : AssociationTable.Fact .subexpress
|
||||
widgetId := "associative-query-operations"
|
||||
factId := "c1d181f6-3204-4956-946f-e81619f9feb4"
|
||||
rowId := "c1d181f6-3204-4956-946f-e81619f9feb4"
|
||||
rowState := #[⟨"Std.DTreeMap", "Std.DTreeMap.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.all,
|
||||
renderedStatement := "Std.DTreeMap.all.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap α β cmp) (p : (a : α) → β a → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.all,
|
||||
renderedStatement := "Std.DTreeMap.Raw.all.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) (p : (a : α) → β a → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.all,
|
||||
renderedStatement := "Std.ExtDTreeMap.all.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtDTreeMap α β cmp) (p : (a : α) → β a → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap", "Std.TreeMap.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.all,
|
||||
renderedStatement := "Std.TreeMap.all.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap α β cmp)\n (p : α → β → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.Raw.all,
|
||||
renderedStatement := "Std.TreeMap.Raw.all.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.TreeMap.Raw α β cmp) (p : α → β → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeMap.all,
|
||||
renderedStatement := "Std.ExtTreeMap.all.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeMap α β cmp) (p : α → β → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet", "Std.HashSet.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.all,
|
||||
renderedStatement := "Std.HashSet.all.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashSet α)\n (p : α → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.Raw.all,
|
||||
renderedStatement := "Std.HashSet.Raw.all.{u} {α : Type u} (m : Std.HashSet.Raw α) (p : α → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet", "Std.TreeSet.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.all,
|
||||
renderedStatement := "Std.TreeSet.all.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet α cmp) (p : α → Bool) :\n Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.Raw.all,
|
||||
renderedStatement := "Std.TreeSet.Raw.all.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet.Raw α cmp)\n (p : α → Bool) : Bool",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.all", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeSet.all,
|
||||
renderedStatement := "Std.ExtTreeSet.all.{u} {α : Type u} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeSet α cmp) (p : α → Bool) : Bool",
|
||||
isDeprecated := false })⟩,]
|
||||
rowState := #[⟨"Std.DTreeMap", "Std.DTreeMap.all", .declaration (Declaration.def {
|
||||
name := `Std.DTreeMap.all
|
||||
renderedStatement := "Std.DTreeMap.all.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.DTreeMap α β cmp)\n (p : (a : α) → β a → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.all", .declaration (Declaration.def {
|
||||
name := `Std.DTreeMap.Raw.all
|
||||
renderedStatement := "Std.DTreeMap.Raw.all.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} (t : Std.DTreeMap.Raw α β cmp)\n (p : (a : α) → β a → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.all", .declaration (Declaration.def {
|
||||
name := `Std.ExtDTreeMap.all
|
||||
renderedStatement := "Std.ExtDTreeMap.all.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtDTreeMap α β cmp) (p : (a : α) → β a → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeMap", "Std.TreeMap.all", .declaration (Declaration.def {
|
||||
name := `Std.TreeMap.all
|
||||
renderedStatement := "Std.TreeMap.all.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap α β cmp) (p : α → β → Bool) :\n Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.all", .declaration (Declaration.def {
|
||||
name := `Std.TreeMap.Raw.all
|
||||
renderedStatement := "Std.TreeMap.Raw.all.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap.Raw α β cmp)\n (p : α → β → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.all", .declaration (Declaration.def {
|
||||
name := `Std.ExtTreeMap.all
|
||||
renderedStatement := "Std.ExtTreeMap.all.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeMap α β cmp) (p : α → β → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.HashSet", "Std.HashSet.all", .declaration (Declaration.def {
|
||||
name := `Std.HashSet.all
|
||||
renderedStatement := "Std.HashSet.all.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashSet α) (p : α → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.all", .declaration (Declaration.def {
|
||||
name := `Std.HashSet.Raw.all
|
||||
renderedStatement := "Std.HashSet.Raw.all.{u} {α : Type u} (m : Std.HashSet.Raw α) (p : α → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeSet", "Std.TreeSet.all", .declaration (Declaration.def {
|
||||
name := `Std.TreeSet.all
|
||||
renderedStatement := "Std.TreeSet.all.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet α cmp) (p : α → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.all", .declaration (Declaration.def {
|
||||
name := `Std.TreeSet.Raw.all
|
||||
renderedStatement := "Std.TreeSet.Raw.all.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet.Raw α cmp) (p : α → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.all", .declaration (Declaration.def {
|
||||
name := `Std.ExtTreeSet.all
|
||||
renderedStatement := "Std.ExtTreeSet.all.{u} {α : Type u} {cmp : α → α → Ordering} [Std.TransCmp cmp] (t : Std.ExtTreeSet α cmp)\n (p : α → Bool) : Bool"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,]
|
||||
metadata := {
|
||||
status := .bad
|
||||
comment := "Missing for some containers"
|
||||
@@ -281,79 +292,97 @@ def «efe57f41-7db7-4303-b3a6-5216a70c43ce» : AssociationTable.Fact .subexpress
|
||||
widgetId := "associative-query-operations"
|
||||
factId := "efe57f41-7db7-4303-b3a6-5216a70c43ce"
|
||||
rowId := "efe57f41-7db7-4303-b3a6-5216a70c43ce"
|
||||
rowState := #[⟨"Std.DHashMap", "Std.DHashMap.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.getD,
|
||||
renderedStatement := "Std.DHashMap.getD.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.DHashMap α β) (a : α) (fallback : β a) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.Raw.getD,
|
||||
renderedStatement := "Std.DHashMap.Raw.getD.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α] [LawfulBEq α]\n (m : Std.DHashMap.Raw α β) (a : α) (fallback : β a) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDHashMap.getD,
|
||||
renderedStatement := "Std.ExtDHashMap.getD.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [LawfulBEq α] (m : Std.ExtDHashMap α β) (a : α) (fallback : β a) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap", "Std.DTreeMap.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.getD,
|
||||
renderedStatement := "Std.DTreeMap.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n [Std.LawfulEqCmp cmp] (t : Std.DTreeMap α β cmp) (a : α) (fallback : β a) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.getD,
|
||||
renderedStatement := "Std.DTreeMap.Raw.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n [Std.LawfulEqCmp cmp] (t : Std.DTreeMap.Raw α β cmp) (a : α) (fallback : β a) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.getD,
|
||||
renderedStatement := "Std.ExtDTreeMap.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n [Std.TransCmp cmp] [Std.LawfulEqCmp cmp] (t : Std.ExtDTreeMap α β cmp) (a : α) (fallback : β a) :\n β a",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap", "Std.HashMap.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.getD,
|
||||
renderedStatement := "Std.HashMap.getD.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (m : Std.HashMap α β) (a : α) (fallback : β) : β",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap.Raw", "Std.HashMap.Raw.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashMap.Raw.getD,
|
||||
renderedStatement := "Std.HashMap.Raw.getD.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (m : Std.HashMap.Raw α β)\n (a : α) (fallback : β) : β",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashMap", "Std.ExtHashMap.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashMap.getD,
|
||||
renderedStatement := "Std.ExtHashMap.getD.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtHashMap α β) (a : α) (fallback : β) : β",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap", "Std.TreeMap.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.getD,
|
||||
renderedStatement := "Std.TreeMap.getD.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap α β cmp)\n (a : α) (fallback : β) : β",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeMap.Raw.getD,
|
||||
renderedStatement := "Std.TreeMap.Raw.getD.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.TreeMap.Raw α β cmp) (a : α) (fallback : β) : β",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeMap.getD,
|
||||
renderedStatement := "Std.ExtTreeMap.getD.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeMap α β cmp) (a : α) (fallback : β) : β",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet", "Std.HashSet.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.getD,
|
||||
renderedStatement := "Std.HashSet.getD.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet α) (a fallback : α) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.Raw.getD,
|
||||
renderedStatement := "Std.HashSet.Raw.getD.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet.Raw α)\n (a fallback : α) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashSet", "Std.ExtHashSet.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashSet.getD,
|
||||
renderedStatement := "Std.ExtHashSet.getD.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashSet α) (a fallback : α) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet", "Std.TreeSet.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.getD,
|
||||
renderedStatement := "Std.TreeSet.getD.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet α cmp)\n (a fallback : α) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.Raw.getD,
|
||||
renderedStatement := "Std.TreeSet.Raw.getD.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet.Raw α cmp)\n (a fallback : α) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.getD", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeSet.getD,
|
||||
renderedStatement := "Std.ExtTreeSet.getD.{u} {α : Type u} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeSet α cmp) (a fallback : α) : α",
|
||||
isDeprecated := false })⟩,]
|
||||
rowState := #[⟨"Std.DHashMap", "Std.DHashMap.getD", .declaration (Declaration.def {
|
||||
name := `Std.DHashMap.getD
|
||||
renderedStatement := "Std.DHashMap.getD.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.DHashMap α β) (a : α) (fallback : β a) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.getD", .declaration (Declaration.def {
|
||||
name := `Std.DHashMap.Raw.getD
|
||||
renderedStatement := "Std.DHashMap.Raw.getD.{u, v} {α : Type u} {β : α → Type v} [BEq α] [Hashable α] [LawfulBEq α] (m : Std.DHashMap.Raw α β)\n (a : α) (fallback : β a) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.getD", .declaration (Declaration.def {
|
||||
name := `Std.ExtDHashMap.getD
|
||||
renderedStatement := "Std.ExtDHashMap.getD.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.ExtDHashMap α β) (a : α) (fallback : β a) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.DTreeMap", "Std.DTreeMap.getD", .declaration (Declaration.def {
|
||||
name := `Std.DTreeMap.getD
|
||||
renderedStatement := "Std.DTreeMap.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.LawfulEqCmp cmp]\n (t : Std.DTreeMap α β cmp) (a : α) (fallback : β a) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.getD", .declaration (Declaration.def {
|
||||
name := `Std.DTreeMap.Raw.getD
|
||||
renderedStatement := "Std.DTreeMap.Raw.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.LawfulEqCmp cmp]\n (t : Std.DTreeMap.Raw α β cmp) (a : α) (fallback : β a) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.getD", .declaration (Declaration.def {
|
||||
name := `Std.ExtDTreeMap.getD
|
||||
renderedStatement := "Std.ExtDTreeMap.getD.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n [Std.LawfulEqCmp cmp] (t : Std.ExtDTreeMap α β cmp) (a : α) (fallback : β a) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.HashMap", "Std.HashMap.getD", .declaration (Declaration.def {
|
||||
name := `Std.HashMap.getD
|
||||
renderedStatement := "Std.HashMap.getD.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashMap α β) (a : α)\n (fallback : β) : β"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.HashMap.Raw", "Std.HashMap.Raw.getD", .declaration (Declaration.def {
|
||||
name := `Std.HashMap.Raw.getD
|
||||
renderedStatement := "Std.HashMap.Raw.getD.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (m : Std.HashMap.Raw α β) (a : α)\n (fallback : β) : β"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtHashMap", "Std.ExtHashMap.getD", .declaration (Declaration.def {
|
||||
name := `Std.ExtHashMap.getD
|
||||
renderedStatement := "Std.ExtHashMap.getD.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashMap α β) (a : α) (fallback : β) : β"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeMap", "Std.TreeMap.getD", .declaration (Declaration.def {
|
||||
name := `Std.TreeMap.getD
|
||||
renderedStatement := "Std.TreeMap.getD.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap α β cmp) (a : α)\n (fallback : β) : β"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeMap.Raw", "Std.TreeMap.Raw.getD", .declaration (Declaration.def {
|
||||
name := `Std.TreeMap.Raw.getD
|
||||
renderedStatement := "Std.TreeMap.Raw.getD.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap.Raw α β cmp) (a : α)\n (fallback : β) : β"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtTreeMap", "Std.ExtTreeMap.getD", .declaration (Declaration.def {
|
||||
name := `Std.ExtTreeMap.getD
|
||||
renderedStatement := "Std.ExtTreeMap.getD.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeMap α β cmp) (a : α) (fallback : β) : β"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.HashSet", "Std.HashSet.getD", .declaration (Declaration.def {
|
||||
name := `Std.HashSet.getD
|
||||
renderedStatement := "Std.HashSet.getD.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet α) (a fallback : α) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.getD", .declaration (Declaration.def {
|
||||
name := `Std.HashSet.Raw.getD
|
||||
renderedStatement := "Std.HashSet.Raw.getD.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet.Raw α) (a fallback : α) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtHashSet", "Std.ExtHashSet.getD", .declaration (Declaration.def {
|
||||
name := `Std.ExtHashSet.getD
|
||||
renderedStatement := "Std.ExtHashSet.getD.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashSet α) (a fallback : α) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeSet", "Std.TreeSet.getD", .declaration (Declaration.def {
|
||||
name := `Std.TreeSet.getD
|
||||
renderedStatement := "Std.TreeSet.getD.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet α cmp) (a fallback : α) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.getD", .declaration (Declaration.def {
|
||||
name := `Std.TreeSet.Raw.getD
|
||||
renderedStatement := "Std.TreeSet.Raw.getD.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet.Raw α cmp) (a fallback : α) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.getD", .declaration (Declaration.def {
|
||||
name := `Std.ExtTreeSet.getD
|
||||
renderedStatement := "Std.ExtTreeSet.getD.{u} {α : Type u} {cmp : α → α → Ordering} [Std.TransCmp cmp] (t : Std.ExtTreeSet α cmp)\n (a fallback : α) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,]
|
||||
metadata := {
|
||||
status := .done
|
||||
comment := ""
|
||||
@@ -362,61 +391,73 @@ def «e23b1119-3b57-433e-a68d-68fd70b9943d» : AssociationTable.Fact .subexpress
|
||||
widgetId := "associative-query-operations"
|
||||
factId := "e23b1119-3b57-433e-a68d-68fd70b9943d"
|
||||
rowId := "e23b1119-3b57-433e-a68d-68fd70b9943d"
|
||||
rowState := #[⟨"Std.DHashMap", "Std.DHashMap.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.get,
|
||||
renderedStatement := "Std.DHashMap.get.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.DHashMap α β) (a : α) (h : a ∈ m) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.Const.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DHashMap.Raw.Const.get,
|
||||
renderedStatement := "Std.DHashMap.Raw.Const.get.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α]\n (m : Std.DHashMap.Raw α fun x => β) (a : α) (h : a ∈ m) : β",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDHashMap.get,
|
||||
renderedStatement := "Std.ExtDHashMap.get.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [LawfulBEq α] (m : Std.ExtDHashMap α β) (a : α) (h : a ∈ m) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap", "Std.DTreeMap.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.get,
|
||||
renderedStatement := "Std.DTreeMap.get.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.LawfulEqCmp cmp]\n (t : Std.DTreeMap α β cmp) (a : α) (h : a ∈ t) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.DTreeMap.Raw.get,
|
||||
renderedStatement := "Std.DTreeMap.Raw.get.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n [Std.LawfulEqCmp cmp] (t : Std.DTreeMap.Raw α β cmp) (a : α) (h : a ∈ t) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtDTreeMap.get,
|
||||
renderedStatement := "Std.ExtDTreeMap.get.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n [Std.LawfulEqCmp cmp] (t : Std.ExtDTreeMap α β cmp) (a : α) (h : a ∈ t) : β a",
|
||||
isDeprecated := false })⟩,⟨"Std.HashMap", "app (GetElem.getElem) (Std.HashMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
rowState := #[⟨"Std.DHashMap", "Std.DHashMap.get", .declaration (Declaration.def {
|
||||
name := `Std.DHashMap.get
|
||||
renderedStatement := "Std.DHashMap.get.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.DHashMap α β) (a : α) (h : a ∈ m) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.DHashMap.Raw", "Std.DHashMap.Raw.Const.get", .declaration (Declaration.def {
|
||||
name := `Std.DHashMap.Raw.Const.get
|
||||
renderedStatement := "Std.DHashMap.Raw.Const.get.{u, v} {α : Type u} {β : Type v} [BEq α] [Hashable α] (m : Std.DHashMap.Raw α fun x => β)\n (a : α) (h : a ∈ m) : β"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtDHashMap", "Std.ExtDHashMap.get", .declaration (Declaration.def {
|
||||
name := `Std.ExtDHashMap.get
|
||||
renderedStatement := "Std.ExtDHashMap.get.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [LawfulBEq α]\n (m : Std.ExtDHashMap α β) (a : α) (h : a ∈ m) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.DTreeMap", "Std.DTreeMap.get", .declaration (Declaration.def {
|
||||
name := `Std.DTreeMap.get
|
||||
renderedStatement := "Std.DTreeMap.get.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.LawfulEqCmp cmp]\n (t : Std.DTreeMap α β cmp) (a : α) (h : a ∈ t) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.DTreeMap.Raw", "Std.DTreeMap.Raw.get", .declaration (Declaration.def {
|
||||
name := `Std.DTreeMap.Raw.get
|
||||
renderedStatement := "Std.DTreeMap.Raw.get.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.LawfulEqCmp cmp]\n (t : Std.DTreeMap.Raw α β cmp) (a : α) (h : a ∈ t) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtDTreeMap", "Std.ExtDTreeMap.get", .declaration (Declaration.def {
|
||||
name := `Std.ExtDTreeMap.get
|
||||
renderedStatement := "Std.ExtDTreeMap.get.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n [Std.LawfulEqCmp cmp] (t : Std.ExtDTreeMap α β cmp) (a : α) (h : a ∈ t) : β a"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.HashMap", "app (GetElem.getElem) (Std.HashMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (GetElem.getElem) (Std.HashMap*)", displayShort := "Std.HashMap[·]" }⟩,⟨"Std.HashMap.Raw", "app (GetElem.getElem) (Std.HashMap.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (GetElem.getElem) (Std.HashMap.Raw*)", displayShort := "Std.HashMap.Raw[·]" }⟩,⟨"Std.ExtHashMap", "app (GetElem.getElem) (Std.ExtHashMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (GetElem.getElem) (Std.ExtHashMap*)", displayShort := "Std.ExtHashMap[·]" }⟩,⟨"Std.TreeMap", "app (GetElem.getElem) (Std.TreeMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (GetElem.getElem) (Std.TreeMap*)", displayShort := "Std.TreeMap[·]" }⟩,⟨"Std.TreeMap.Raw", "app (GetElem.getElem) (Std.TreeMap.Raw*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (GetElem.getElem) (Std.TreeMap.Raw*)", displayShort := "Std.TreeMap.Raw[·]" }⟩,⟨"Std.ExtTreeMap", "app (GetElem.getElem) (Std.ExtTreeMap*)", Grove.Framework.Subexpression.State.predicate
|
||||
{ key := "app (GetElem.getElem) (Std.ExtTreeMap*)", displayShort := "Std.ExtTreeMap[·]" }⟩,⟨"Std.HashSet", "Std.HashSet.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.get,
|
||||
renderedStatement := "Std.HashSet.get.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet α) (a : α) (h : a ∈ m) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.HashSet.Raw.get,
|
||||
renderedStatement := "Std.HashSet.Raw.get.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet.Raw α) (a : α)\n (h : a ∈ m) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtHashSet", "Std.ExtHashSet.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtHashSet.get,
|
||||
renderedStatement := "Std.ExtHashSet.get.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashSet α) (a : α) (h : a ∈ m) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet", "Std.TreeSet.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.get,
|
||||
renderedStatement := "Std.TreeSet.get.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet α cmp) (a : α)\n (h : a ∈ t) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.TreeSet.Raw.get,
|
||||
renderedStatement := "Std.TreeSet.Raw.get.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet.Raw α cmp) (a : α)\n (h : a ∈ t) : α",
|
||||
isDeprecated := false })⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.get", Grove.Framework.Subexpression.State.declaration
|
||||
(Grove.Framework.Declaration.def
|
||||
{ name := `Std.ExtTreeSet.get,
|
||||
renderedStatement := "Std.ExtTreeSet.get.{u} {α : Type u} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeSet α cmp) (a : α) (h : a ∈ t) : α",
|
||||
isDeprecated := false })⟩,]
|
||||
{ key := "app (GetElem.getElem) (Std.ExtTreeMap*)", displayShort := "Std.ExtTreeMap[·]" }⟩,⟨"Std.HashSet", "Std.HashSet.get", .declaration (Declaration.def {
|
||||
name := `Std.HashSet.get
|
||||
renderedStatement := "Std.HashSet.get.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet α) (a : α) (h : a ∈ m) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.HashSet.Raw", "Std.HashSet.Raw.get", .declaration (Declaration.def {
|
||||
name := `Std.HashSet.Raw.get
|
||||
renderedStatement := "Std.HashSet.Raw.get.{u} {α : Type u} [BEq α] [Hashable α] (m : Std.HashSet.Raw α) (a : α) (h : a ∈ m) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtHashSet", "Std.ExtHashSet.get", .declaration (Declaration.def {
|
||||
name := `Std.ExtHashSet.get
|
||||
renderedStatement := "Std.ExtHashSet.get.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α] [LawfulHashable α]\n (m : Std.ExtHashSet α) (a : α) (h : a ∈ m) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeSet", "Std.TreeSet.get", .declaration (Declaration.def {
|
||||
name := `Std.TreeSet.get
|
||||
renderedStatement := "Std.TreeSet.get.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet α cmp) (a : α) (h : a ∈ t) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.TreeSet.Raw", "Std.TreeSet.Raw.get", .declaration (Declaration.def {
|
||||
name := `Std.TreeSet.Raw.get
|
||||
renderedStatement := "Std.TreeSet.Raw.get.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet.Raw α cmp) (a : α) (h : a ∈ t) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,⟨"Std.ExtTreeSet", "Std.ExtTreeSet.get", .declaration (Declaration.def {
|
||||
name := `Std.ExtTreeSet.get
|
||||
renderedStatement := "Std.ExtTreeSet.get.{u} {α : Type u} {cmp : α → α → Ordering} [Std.TransCmp cmp] (t : Std.ExtTreeSet α cmp) (a : α)\n (h : a ∈ t) : α"
|
||||
isDeprecated := false
|
||||
}
|
||||
)⟩,]
|
||||
metadata := {
|
||||
status := .bad
|
||||
comment := "Should *Set have GetElem?"
|
||||
|
||||
@@ -20,75 +20,23 @@ def sequentialContainers : Node :=
|
||||
|
||||
namespace AssociativeContainers
|
||||
|
||||
def associativeContainers : List Lean.Name :=
|
||||
[`Std.DHashMap, `Std.DHashMap.Raw, `Std.ExtDHashMap, `Std.DTreeMap, `Std.DTreeMap.Raw, `Std.ExtDTreeMap, `Std.HashMap,
|
||||
`Std.HashMap.Raw, `Std.ExtHashMap, `Std.TreeMap, `Std.TreeMap.Raw, `Std.ExtTreeMap, `Std.HashSet, `Std.HashSet.Raw, `Std.ExtHashSet,
|
||||
`Std.TreeSet, `Std.TreeSet.Raw, `Std.ExtTreeSet]
|
||||
|
||||
def associativeQueryOperations : AssociationTable .subexpression associativeContainers where
|
||||
def associativeQueryOperations : AssociationTable .subexpression
|
||||
[`Std.DHashMap, `Std.DHashMap.Raw, `Std.ExtDHashMap, `Std.DTreeMap, `Std.DTreeMap.Raw, `Std.ExtDTreeMap, `Std.HashMap,
|
||||
`Std.HashMap.Raw, `Std.ExtHashMap, `Std.TreeMap, `Std.TreeMap.Raw, `Std.ExtTreeMap, `Std.HashSet, `Std.HashSet.Raw, `Std.ExtHashSet,
|
||||
`Std.TreeSet, `Std.TreeSet.Raw, `Std.ExtTreeSet] where
|
||||
id := "associative-query-operations"
|
||||
title := "Associative query operations"
|
||||
description := "Operations that take as input an associative container and return a 'single' piece of information (e.g., `GetElem` or `isEmpty`, but not `toList`)."
|
||||
dataSources n :=
|
||||
(DataSource.definitionsInNamespace n)
|
||||
(DataSource.declarationsInNamespace n .definitionsOnly)
|
||||
|>.map Subexpression.declaration
|
||||
|>.or (DataSource.getElem n)
|
||||
|
||||
def associativeCreationOperations : AssociationTable .subexpression associativeContainers where
|
||||
id := "associative-creation-operations"
|
||||
title := "Associative creation operations"
|
||||
description := "Operations that create a new associative container"
|
||||
dataSources n :=
|
||||
(DataSource.definitionsInNamespace n)
|
||||
|>.map Subexpression.declaration
|
||||
|>.or (DataSource.emptyCollection n)
|
||||
|
||||
def associativeModificationOperations : AssociationTable .subexpression associativeContainers where
|
||||
id := "associative-modification-operations"
|
||||
title := "Associative modification operations"
|
||||
description := "Operations that both accept and return an associative container"
|
||||
dataSources n :=
|
||||
(DataSource.definitionsInNamespace n)
|
||||
|>.map Subexpression.declaration
|
||||
|
||||
def associativeCreateThenQuery : Table .subexpression .subexpression .declaration associativeContainers where
|
||||
id := "associative-create-then-query"
|
||||
title := "Associative create then query"
|
||||
description := "Lemmas that say what happens when creating a new associative container and then immediately querying from it"
|
||||
rowsFrom := .table associativeCreationOperations
|
||||
columnsFrom := .table associativeQueryOperations
|
||||
cellData := .classic _ { relevantNamespaces := associativeContainers }
|
||||
|
||||
def allOperationsCovered : Assertion where
|
||||
widgetId := "associative-all-operations-covered"
|
||||
title := "All operations on associative containers covered"
|
||||
description := "All operations on an associative container should appear in at least one of the tables"
|
||||
check := do
|
||||
let allValuesArray : Array String ← #[associativeQueryOperations, associativeCreationOperations, associativeModificationOperations].flatMapM valuesInAssociationTable
|
||||
let allValues : Std.HashSet String := Std.HashSet.ofArray allValuesArray
|
||||
let env ← Lean.getEnv
|
||||
let mut numBad := 0
|
||||
for (n, _) in env.constants do
|
||||
if associativeContainers.any (fun namesp => namesp.isPrefixOf n) then
|
||||
if !n.toString ∈ allValues then
|
||||
numBad := numBad + 1
|
||||
return #[{
|
||||
assertionId := "all-covered"
|
||||
description := "All operations should be covered"
|
||||
passed := numBad == 0
|
||||
message := if numBad = 0 then "All operations were covered" else s!"There were {numBad} operations that were not covered."
|
||||
}]
|
||||
|
||||
end AssociativeContainers
|
||||
|
||||
open AssociativeContainers in
|
||||
def associativeContainers : Node :=
|
||||
.section "associative-containers" "Associative containers" #[
|
||||
.associationTable associativeQueryOperations,
|
||||
.associationTable associativeCreationOperations,
|
||||
.associationTable associativeModificationOperations,
|
||||
.table associativeCreateThenQuery,
|
||||
.assertion allOperationsCovered
|
||||
.associationTable AssociativeContainers.associativeQueryOperations
|
||||
]
|
||||
|
||||
namespace PersistentDataStructures
|
||||
|
||||
@@ -3,10 +3,8 @@
|
||||
lake exe grove-stdlib --full metadata.json
|
||||
cd .lake/packages/grove/frontend
|
||||
npm install
|
||||
cp ../../../../metadata.json public/metadata.json
|
||||
if [ -f "../../../../invalidated.json" ]; then
|
||||
cp ../../../../invalidated.json public/invalidated.json
|
||||
GROVE_DATA_LOCATION=public/metadata.json GROVE_UPSTREAM_INVALIDATED_FACTS_LOCATION=public/invalidated.json npm run dev
|
||||
GROVE_DATA_LOCATION=../../../../metadata.json GROVE_UPSTREAM_INVALIDATED_FACTS_LOCATION=../../../../invalidated.json npm run dev
|
||||
else
|
||||
GROVE_DATA_LOCATION=public/metadata.json npm run dev
|
||||
fi
|
||||
GROVE_DATA_LOCATION=../../../../metadata.json npm run dev
|
||||
fi
|
||||
@@ -5,7 +5,7 @@
|
||||
"type": "git",
|
||||
"subDir": "backend",
|
||||
"scope": "",
|
||||
"rev": "3e8aabdea58c11813c5d3b7eeb187ded44ee9a34",
|
||||
"rev": "e8127fc6554b99fb988ecdceb770a5e112afbe24",
|
||||
"name": "grove",
|
||||
"manifestFile": "lake-manifest.json",
|
||||
"inputRev": "master",
|
||||
|
||||
13
flake.nix
13
flake.nix
@@ -18,15 +18,14 @@
|
||||
# An old nixpkgs for creating releases with an old glibc
|
||||
pkgsDist-old-aarch = import inputs.nixpkgs-old { localSystem.config = "aarch64-unknown-linux-gnu"; };
|
||||
|
||||
llvmPackages = pkgs.llvmPackages_15;
|
||||
lean-packages = pkgs.callPackage (./nix/packages.nix) { src = ./.; };
|
||||
|
||||
devShellWithDist = pkgsDist: pkgs.mkShell.override {
|
||||
stdenv = pkgs.overrideCC pkgs.stdenv llvmPackages.clang;
|
||||
stdenv = pkgs.overrideCC pkgs.stdenv lean-packages.llvmPackages.clang;
|
||||
} ({
|
||||
buildInputs = with pkgs; [
|
||||
cmake gmp libuv ccache pkg-config
|
||||
llvmPackages.bintools # wrapped lld
|
||||
llvmPackages.llvm # llvm-symbolizer for asan/lsan
|
||||
lean-packages.llvmPackages.llvm # llvm-symbolizer for asan/lsan
|
||||
gdb
|
||||
tree # for CI
|
||||
];
|
||||
@@ -61,6 +60,12 @@
|
||||
GDB = pkgsDist.gdb;
|
||||
});
|
||||
in {
|
||||
packages.${system} = {
|
||||
# to be removed when Nix CI is not needed anymore
|
||||
inherit (lean-packages) cacheRoots test update-stage0-commit ciShell;
|
||||
deprecated = lean-packages;
|
||||
};
|
||||
|
||||
devShells.${system} = {
|
||||
# The default development shell for working on lean itself
|
||||
default = devShellWithDist pkgs;
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
},
|
||||
{
|
||||
"path": "tests"
|
||||
},
|
||||
{
|
||||
"path": "script"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
@@ -40,15 +37,6 @@
|
||||
"isDefault": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "build-old",
|
||||
"type": "shell",
|
||||
"command": "make -C build/release -j$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 4) LAKE_EXTRA_ARGS=--old",
|
||||
"problemMatcher": [],
|
||||
"group": {
|
||||
"kind": "build"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "test",
|
||||
"type": "shell",
|
||||
|
||||
7
nix/bareStdenv/setup
Normal file
7
nix/bareStdenv/setup
Normal file
@@ -0,0 +1,7 @@
|
||||
set -eo pipefail
|
||||
|
||||
for pkg in $buildInputs; do
|
||||
export PATH=$PATH:$pkg/bin
|
||||
done
|
||||
|
||||
: ${outputs:=out}
|
||||
208
nix/bootstrap.nix
Normal file
208
nix/bootstrap.nix
Normal file
@@ -0,0 +1,208 @@
|
||||
{ src, debug ? false, stage0debug ? false, extraCMakeFlags ? [],
|
||||
stdenv, lib, cmake, pkg-config, gmp, libuv, cadical, git, gnumake, bash, buildLeanPackage, writeShellScriptBin, runCommand, symlinkJoin, lndir, perl, gnused, darwin, llvmPackages, linkFarmFromDrvs,
|
||||
... } @ args:
|
||||
with builtins;
|
||||
lib.warn "The Nix-based build is deprecated" rec {
|
||||
inherit stdenv;
|
||||
sourceByRegex = p: rs: lib.sourceByRegex p (map (r: "(/src/)?${r}") rs);
|
||||
buildCMake = args: stdenv.mkDerivation ({
|
||||
nativeBuildInputs = [ cmake pkg-config ];
|
||||
buildInputs = [ gmp libuv llvmPackages.llvm ];
|
||||
# https://github.com/NixOS/nixpkgs/issues/60919
|
||||
hardeningDisable = [ "all" ];
|
||||
dontStrip = (args.debug or debug);
|
||||
|
||||
postConfigure = ''
|
||||
patchShebangs .
|
||||
'';
|
||||
} // args // {
|
||||
src = args.realSrc or (sourceByRegex args.src [ "[a-z].*" "CMakeLists\.txt" ]);
|
||||
cmakeFlags = ["-DSMALL_ALLOCATOR=ON" "-DUSE_MIMALLOC=OFF"] ++ (args.cmakeFlags or [ "-DSTAGE=1" "-DPREV_STAGE=./faux-prev-stage" "-DUSE_GITHASH=OFF" "-DCADICAL=${cadical}/bin/cadical" ]) ++ (args.extraCMakeFlags or extraCMakeFlags) ++ lib.optional (args.debug or debug) [ "-DCMAKE_BUILD_TYPE=Debug" ];
|
||||
preConfigure = args.preConfigure or "" + ''
|
||||
# ignore absence of submodule
|
||||
sed -i 's!lake/Lake.lean!!' CMakeLists.txt
|
||||
'';
|
||||
});
|
||||
lean-bin-tools-unwrapped = buildCMake {
|
||||
name = "lean-bin-tools";
|
||||
outputs = [ "out" "leanc_src" ];
|
||||
realSrc = sourceByRegex (src + "/src") [ "CMakeLists\.txt" "[a-z].*" ".*\.in" "Leanc\.lean" ];
|
||||
dontBuild = true;
|
||||
installPhase = ''
|
||||
mkdir $out $leanc_src
|
||||
mv bin/ include/ share/ $out/
|
||||
mv leanc.sh $out/bin/leanc
|
||||
mv leanc/Leanc.lean $leanc_src/
|
||||
substituteInPlace $out/bin/leanc --replace '$root' "$out" --replace " sed " " ${gnused}/bin/sed "
|
||||
substituteInPlace $out/bin/leanmake --replace "make" "${gnumake}/bin/make"
|
||||
substituteInPlace $out/share/lean/lean.mk --replace "/usr/bin/env bash" "${bash}/bin/bash"
|
||||
'';
|
||||
};
|
||||
leancpp = buildCMake {
|
||||
name = "leancpp";
|
||||
src = src + "/src";
|
||||
buildFlags = [ "leancpp" "leanrt" "leanrt_initial-exec" "leanshell" "leanmain" ];
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
mv lib/ $out/
|
||||
mv runtime/libleanrt_initial-exec.a $out/lib
|
||||
'';
|
||||
};
|
||||
stage0 = args.stage0 or (buildCMake {
|
||||
name = "lean-stage0";
|
||||
realSrc = src + "/stage0/src";
|
||||
debug = stage0debug;
|
||||
cmakeFlags = [ "-DSTAGE=0" ];
|
||||
extraCMakeFlags = [];
|
||||
preConfigure = ''
|
||||
ln -s ${src + "/stage0/stdlib"} ../stdlib
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin $out/lib/lean
|
||||
mv bin/lean $out/bin/
|
||||
mv lib/lean/*.{so,dylib} $out/lib/lean
|
||||
'';
|
||||
meta.mainProgram = "lean";
|
||||
});
|
||||
stage = { stage, prevStage, self }:
|
||||
let
|
||||
desc = "stage${toString stage}";
|
||||
build = args: buildLeanPackage.override {
|
||||
lean = prevStage;
|
||||
leanc = lean-bin-tools-unwrapped;
|
||||
# use same stage for retrieving dependencies
|
||||
lean-leanDeps = stage0;
|
||||
lean-final = self;
|
||||
} ({
|
||||
src = src + "/src";
|
||||
roots = [ { mod = args.name; glob = "andSubmodules"; } ];
|
||||
fullSrc = src;
|
||||
srcPath = "$PWD/src:$PWD/src/lake";
|
||||
inherit debug;
|
||||
leanFlags = [ "-DwarningAsError=true" ];
|
||||
} // args);
|
||||
Init' = build { name = "Init"; deps = []; };
|
||||
Std' = build { name = "Std"; deps = [ Init' ]; };
|
||||
Lean' = build { name = "Lean"; deps = [ Std' ]; };
|
||||
attachSharedLib = sharedLib: pkg: pkg // {
|
||||
inherit sharedLib;
|
||||
mods = mapAttrs (_: m: m // { inherit sharedLib; propagatedLoadDynlibs = []; }) pkg.mods;
|
||||
};
|
||||
in (all: all // all.lean) rec {
|
||||
inherit (Lean) emacs-dev emacs-package vscode-dev vscode-package;
|
||||
Init = attachSharedLib leanshared Init';
|
||||
Std = attachSharedLib leanshared Std' // { allExternalDeps = [ Init ]; };
|
||||
Lean = attachSharedLib leanshared Lean' // { allExternalDeps = [ Std ]; };
|
||||
Lake = build {
|
||||
name = "Lake";
|
||||
sharedLibName = "Lake_shared";
|
||||
src = src + "/src/lake";
|
||||
deps = [ Init Lean ];
|
||||
};
|
||||
Lake-Main = build {
|
||||
name = "LakeMain";
|
||||
roots = [{ glob = "one"; mod = "LakeMain"; }];
|
||||
executableName = "lake";
|
||||
deps = [ Lake ];
|
||||
linkFlags = lib.optional stdenv.isLinux "-rdynamic";
|
||||
src = src + "/src/lake";
|
||||
};
|
||||
stdlib = [ Init Std Lean Lake ];
|
||||
modDepsFiles = symlinkJoin { name = "modDepsFiles"; paths = map (l: l.modDepsFile) (stdlib ++ [ Leanc ]); };
|
||||
depRoots = symlinkJoin { name = "depRoots"; paths = map (l: l.depRoots) stdlib; };
|
||||
iTree = symlinkJoin { name = "ileans"; paths = map (l: l.iTree) stdlib; };
|
||||
Leanc = build { name = "Leanc"; src = lean-bin-tools-unwrapped.leanc_src; deps = stdlib; roots = [ "Leanc" ]; };
|
||||
stdlibLinkFlags = "${lib.concatMapStringsSep " " (l: "-L${l.staticLib}") stdlib} -L${leancpp}/lib/lean";
|
||||
libInit_shared = runCommand "libInit_shared" { buildInputs = [ stdenv.cc ]; libName = "libInit_shared${stdenv.hostPlatform.extensions.sharedLibrary}"; } ''
|
||||
mkdir $out
|
||||
touch empty.c
|
||||
${stdenv.cc}/bin/cc -shared -o $out/$libName empty.c
|
||||
'';
|
||||
leanshared_1 = runCommand "leanshared_1" { buildInputs = [ stdenv.cc ]; libName = "leanshared_1${stdenv.hostPlatform.extensions.sharedLibrary}"; } ''
|
||||
mkdir $out
|
||||
touch empty.c
|
||||
${stdenv.cc}/bin/cc -shared -o $out/$libName empty.c
|
||||
'';
|
||||
leanshared = runCommand "leanshared" { buildInputs = [ stdenv.cc ]; libName = "libleanshared${stdenv.hostPlatform.extensions.sharedLibrary}"; } ''
|
||||
mkdir $out
|
||||
LEAN_CC=${stdenv.cc}/bin/cc ${lean-bin-tools-unwrapped}/bin/leanc -shared ${lib.optionalString stdenv.isLinux "-Wl,-Bsymbolic"} \
|
||||
-Wl,--whole-archive ${leancpp}/lib/temp/libleanshell.a -lInit -lStd -lLean -lleancpp ${leancpp}/lib/libleanrt_initial-exec.a -Wl,--no-whole-archive -lstdc++ \
|
||||
-lm ${stdlibLinkFlags} \
|
||||
$(${llvmPackages.libllvm.dev}/bin/llvm-config --ldflags --libs) \
|
||||
-o $out/$libName
|
||||
'';
|
||||
mods = foldl' (mods: pkg: mods // pkg.mods) {} stdlib;
|
||||
print-paths = Lean.makePrintPathsFor [] mods;
|
||||
leanc = writeShellScriptBin "leanc" ''
|
||||
LEAN_CC=${stdenv.cc}/bin/cc ${Leanc.executable}/bin/leanc -I${lean-bin-tools-unwrapped}/include ${stdlibLinkFlags} -L${libInit_shared} -L${leanshared_1} -L${leanshared} -L${Lake.sharedLib} "$@"
|
||||
'';
|
||||
lean = runCommand "lean" { buildInputs = lib.optional stdenv.isDarwin darwin.cctools; } ''
|
||||
mkdir -p $out/bin
|
||||
${leanc}/bin/leanc ${leancpp}/lib/temp/libleanmain.a ${libInit_shared}/* ${leanshared_1}/* ${leanshared}/* -o $out/bin/lean
|
||||
'';
|
||||
# derivation following the directory layout of the "basic" setup, mostly useful for running tests
|
||||
lean-all = stdenv.mkDerivation {
|
||||
name = "lean-${desc}";
|
||||
buildCommand = ''
|
||||
mkdir -p $out/bin $out/lib/lean
|
||||
ln -sf ${leancpp}/lib/lean/* ${lib.concatMapStringsSep " " (l: "${l.modRoot}/* ${l.staticLib}/*") (lib.reverseList stdlib)} ${libInit_shared}/* ${leanshared_1}/* ${leanshared}/* ${Lake.sharedLib}/* $out/lib/lean/
|
||||
# put everything in a single final derivation so `IO.appDir` references work
|
||||
cp ${lean}/bin/lean ${leanc}/bin/leanc ${Lake-Main.executable}/bin/lake $out/bin
|
||||
# NOTE: `lndir` will not override existing `bin/leanc`
|
||||
${lndir}/bin/lndir -silent ${lean-bin-tools-unwrapped} $out
|
||||
'';
|
||||
meta.mainProgram = "lean";
|
||||
};
|
||||
cacheRoots = linkFarmFromDrvs "cacheRoots" ([
|
||||
stage0 lean leanc lean-all iTree modDepsFiles depRoots Leanc.src
|
||||
] ++ map (lib: lib.oTree) stdlib);
|
||||
test = buildCMake {
|
||||
name = "lean-test-${desc}";
|
||||
realSrc = lib.sourceByRegex src [ "src.*" "tests.*" ];
|
||||
buildInputs = [ gmp libuv perl git cadical ];
|
||||
preConfigure = ''
|
||||
cd src
|
||||
'';
|
||||
extraCMakeFlags = [ "-DLLVM=OFF" ];
|
||||
postConfigure = ''
|
||||
patchShebangs ../../tests ../lake
|
||||
rm -r bin lib include share
|
||||
ln -sf ${lean-all}/* .
|
||||
'';
|
||||
buildPhase = ''
|
||||
ctest --output-junit test-results.xml --output-on-failure -E 'leancomptest_(doc_example|foreign)|leanlaketest_reverse-ffi|leanruntest_timeIO' -j$NIX_BUILD_CORES
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir $out
|
||||
mv test-results.xml $out
|
||||
'';
|
||||
};
|
||||
update-stage0 =
|
||||
let cTree = symlinkJoin { name = "cs"; paths = map (lib: lib.cTree) (stdlib ++ [Lake-Main]); }; in
|
||||
writeShellScriptBin "update-stage0" ''
|
||||
CSRCS=${cTree} CP_C_PARAMS="--dereference --no-preserve=all" ${src + "/script/lib/update-stage0"}
|
||||
'';
|
||||
update-stage0-commit = writeShellScriptBin "update-stage0-commit" ''
|
||||
set -euo pipefail
|
||||
${update-stage0}/bin/update-stage0
|
||||
git commit -m "chore: update stage0"
|
||||
'';
|
||||
link-ilean = writeShellScriptBin "link-ilean" ''
|
||||
dest=''${1:-src}
|
||||
rm -rf $dest/build/lib || true
|
||||
mkdir -p $dest/build/lib
|
||||
ln -s ${iTree}/* $dest/build/lib
|
||||
'';
|
||||
benchmarks =
|
||||
let
|
||||
entries = attrNames (readDir (src + "/tests/bench"));
|
||||
leanFiles = map (n: elemAt n 0) (filter (n: n != null) (map (match "(.*)\.lean") entries));
|
||||
in lib.genAttrs leanFiles (n: (buildLeanPackage {
|
||||
name = n;
|
||||
src = filterSource (e: _: baseNameOf e == "${n}.lean") (src + "/tests/bench");
|
||||
}).executable);
|
||||
};
|
||||
stage1 = stage { stage = 1; prevStage = stage0; self = stage1; };
|
||||
stage2 = stage { stage = 2; prevStage = stage1; self = stage2; };
|
||||
stage3 = stage { stage = 3; prevStage = stage2; self = stage3; };
|
||||
}
|
||||
247
nix/buildLeanPackage.nix
Normal file
247
nix/buildLeanPackage.nix
Normal file
@@ -0,0 +1,247 @@
|
||||
{ lean, lean-leanDeps ? lean, lean-final ? lean, leanc,
|
||||
stdenv, lib, coreutils, gnused, writeShellScriptBin, bash, substituteAll, symlinkJoin, linkFarmFromDrvs,
|
||||
runCommand, darwin, mkShell, ... }:
|
||||
let lean-final' = lean-final; in
|
||||
lib.makeOverridable (
|
||||
{ name, src, fullSrc ? src, srcPrefix ? "", srcPath ? "$PWD/${srcPrefix}",
|
||||
# Lean dependencies. Each entry should be an output of buildLeanPackage.
|
||||
deps ? [ lean.Init lean.Std lean.Lean ],
|
||||
# Static library dependencies. Each derivation `static` should contain a static library in the directory `${static}`.
|
||||
staticLibDeps ? [],
|
||||
# Whether to wrap static library inputs in a -Wl,--start-group [...] -Wl,--end-group to ensure dependencies are resolved.
|
||||
groupStaticLibs ? false,
|
||||
# Shared library dependencies included at interpretation with --load-dynlib and linked to. Each derivation `shared` should contain a
|
||||
# shared library at the path `${shared}/${shared.libName or shared.name}` and a name to link to like `-l${shared.linkName or shared.name}`.
|
||||
# These libs are also linked to in packages that depend on this one.
|
||||
nativeSharedLibs ? [],
|
||||
# Lean modules to include.
|
||||
# A set of Lean modules names as strings (`"Foo.Bar"`) or attrsets (`{ name = "Foo.Bar"; glob = "one" | "submodules" | "andSubmodules"; }`);
|
||||
# see Lake README for glob meanings. Dependencies of selected modules are always included.
|
||||
roots ? [ name ],
|
||||
# Output from `lean --deps-json` on package source files. Persist the corresponding output attribute to a file and pass it back in here to avoid IFD.
|
||||
# Must be refreshed on any change in `import`s or set of source file names.
|
||||
modDepsFile ? null,
|
||||
# Whether to compile each module into a native shared library that is loaded whenever the module is imported in order to accelerate evaluation
|
||||
precompileModules ? false,
|
||||
# Whether to compile the package into a native shared library that is loaded whenever *any* of the package's modules is imported into another package.
|
||||
# If `precompileModules` is also `true`, the latter only affects imports within the current package.
|
||||
precompilePackage ? precompileModules,
|
||||
# Lean plugin dependencies. Each derivation `plugin` should contain a plugin library at path `${plugin}/${plugin.name}`.
|
||||
pluginDeps ? [],
|
||||
# `overrideAttrs` for `buildMod`
|
||||
overrideBuildModAttrs ? null,
|
||||
debug ? false, leanFlags ? [], leancFlags ? [], linkFlags ? [], executableName ? lib.toLower name, libName ? name, sharedLibName ? libName,
|
||||
srcTarget ? "..#stage0", srcArgs ? "(\${args[*]})", lean-final ? lean-final' }@args:
|
||||
with builtins; let
|
||||
# "Init.Core" ~> "Init/Core"
|
||||
modToPath = mod: replaceStrings ["."] ["/"] mod;
|
||||
modToAbsPath = mod: "${src}/${modToPath mod}";
|
||||
# sanitize file name before copying to store, except when already in store
|
||||
copyToStoreSafe = base: suffix: if lib.isDerivation base then base + suffix else
|
||||
builtins.path { name = lib.strings.sanitizeDerivationName (baseNameOf suffix); path = base + suffix; };
|
||||
modToLean = mod: copyToStoreSafe src "/${modToPath mod}.lean";
|
||||
bareStdenv = ./bareStdenv;
|
||||
mkBareDerivation = args: derivation (args // {
|
||||
name = lib.strings.sanitizeDerivationName args.name;
|
||||
stdenv = bareStdenv;
|
||||
inherit (stdenv) system;
|
||||
buildInputs = (args.buildInputs or []) ++ [ coreutils ];
|
||||
builder = stdenv.shell;
|
||||
args = [ "-c" ''
|
||||
source $stdenv/setup
|
||||
set -u
|
||||
${args.buildCommand}
|
||||
'' ];
|
||||
}) // { overrideAttrs = f: mkBareDerivation (lib.fix (lib.extends f (_: args))); };
|
||||
runBareCommand = name: args: buildCommand: mkBareDerivation (args // { inherit name buildCommand; });
|
||||
runBareCommandLocal = name: args: buildCommand: runBareCommand name (args // {
|
||||
preferLocalBuild = true;
|
||||
allowSubstitutes = false;
|
||||
}) buildCommand;
|
||||
mkSharedLib = name: args: runBareCommand "${name}-dynlib" {
|
||||
buildInputs = [ stdenv.cc ] ++ lib.optional stdenv.isDarwin darwin.cctools;
|
||||
libName = "${name}${stdenv.hostPlatform.extensions.sharedLibrary}";
|
||||
} ''
|
||||
mkdir -p $out
|
||||
${leanc}/bin/leanc -shared ${args} -o $out/$libName
|
||||
'';
|
||||
depRoot = name: deps: mkBareDerivation {
|
||||
name = "${name}-depRoot";
|
||||
inherit deps;
|
||||
depRoots = map (drv: drv.LEAN_PATH) deps;
|
||||
|
||||
passAsFile = [ "deps" "depRoots" ];
|
||||
buildCommand = ''
|
||||
mkdir -p $out
|
||||
for i in $(cat $depRootsPath); do
|
||||
cp -dru --no-preserve=mode $i/. $out
|
||||
done
|
||||
for i in $(cat $depsPath); do
|
||||
cp -drsu --no-preserve=mode $i/. $out
|
||||
done
|
||||
'';
|
||||
};
|
||||
srcRoot = src;
|
||||
|
||||
# A flattened list of Lean-module dependencies (`deps`)
|
||||
allExternalDeps = lib.unique (lib.foldr (dep: allExternalDeps: allExternalDeps ++ [ dep ] ++ dep.allExternalDeps) [] deps);
|
||||
allNativeSharedLibs =
|
||||
lib.unique (lib.flatten (nativeSharedLibs ++ (map (dep: dep.allNativeSharedLibs or []) allExternalDeps)));
|
||||
|
||||
# A flattened list of all static library dependencies: this and every dep module's explicitly provided `staticLibDeps`,
|
||||
# plus every dep module itself: `dep.staticLib`
|
||||
allStaticLibDeps =
|
||||
lib.unique (lib.flatten (staticLibDeps ++ (map (dep: [dep.staticLib] ++ dep.staticLibDeps or []) allExternalDeps)));
|
||||
|
||||
pathOfSharedLib = dep: dep.libPath or "${dep}/${dep.libName or dep.name}";
|
||||
|
||||
leanPluginFlags = lib.concatStringsSep " " (map (dep: "--plugin=${pathOfSharedLib dep}") pluginDeps);
|
||||
loadDynlibsOfDeps = deps: lib.unique (concatMap (d: d.propagatedLoadDynlibs) deps);
|
||||
|
||||
# submodules "Init" = ["Init.List.Basic", "Init.Core", ...]
|
||||
submodules = mod: let
|
||||
dir = readDir (modToAbsPath mod);
|
||||
f = p: t:
|
||||
if t == "directory" then
|
||||
submodules "${mod}.${p}"
|
||||
else
|
||||
let m = builtins.match "(.*)\.lean" p;
|
||||
in lib.optional (m != null) "${mod}.${head m}";
|
||||
in concatLists (lib.mapAttrsToList f dir);
|
||||
|
||||
# conservatively approximate list of source files matched by glob
|
||||
expandGlobAllApprox = g:
|
||||
if typeOf g == "string" then
|
||||
# we can't know the required files without parsing dependencies (which is what we want this
|
||||
# function for), so we approximate to the entire package.
|
||||
let root = (head (split "\\." g));
|
||||
in lib.optional (pathExists (src + "/${modToPath root}.lean")) root ++ lib.optionals (pathExists (modToAbsPath root)) (submodules root)
|
||||
else if g.glob == "one" then expandGlobAllApprox g.mod
|
||||
else if g.glob == "submodules" then submodules g.mod
|
||||
else if g.glob == "andSubmodules" then [g.mod] ++ submodules g.mod
|
||||
else throw "unknown glob kind '${g}'";
|
||||
# list of modules that could potentially be involved in the build
|
||||
candidateMods = lib.unique (concatMap expandGlobAllApprox roots);
|
||||
candidateFiles = map modToLean candidateMods;
|
||||
modDepsFile = args.modDepsFile or mkBareDerivation {
|
||||
name = "${name}-deps.json";
|
||||
candidateFiles = lib.concatStringsSep " " candidateFiles;
|
||||
passAsFile = [ "candidateFiles" ];
|
||||
buildCommand = ''
|
||||
mkdir $out
|
||||
${lean-leanDeps}/bin/lean --deps-json --stdin < $candidateFilesPath > $out/$name
|
||||
'';
|
||||
};
|
||||
modDeps = fromJSON (
|
||||
# the only possible references to store paths in the JSON should be inside errors, so no chance of missed dependencies from this
|
||||
unsafeDiscardStringContext (readFile "${modDepsFile}/${modDepsFile.name}"));
|
||||
# map from module name to list of imports
|
||||
modDepsMap = listToAttrs (lib.zipListsWith lib.nameValuePair candidateMods modDeps.imports);
|
||||
maybeOverrideAttrs = f: x: if f != null then x.overrideAttrs f else x;
|
||||
# build module (.olean and .c) given derivations of all (immediate) dependencies
|
||||
# TODO: make `rec` parts override-compatible?
|
||||
buildMod = mod: deps: maybeOverrideAttrs overrideBuildModAttrs (mkBareDerivation rec {
|
||||
name = "${mod}";
|
||||
LEAN_PATH = depRoot mod deps;
|
||||
LEAN_ABORT_ON_PANIC = "1";
|
||||
relpath = modToPath mod;
|
||||
buildInputs = [ lean ];
|
||||
leanPath = relpath + ".lean";
|
||||
# should be either single .lean file or directory directly containing .lean file plus dependencies
|
||||
src = copyToStoreSafe srcRoot ("/" + leanPath);
|
||||
outputs = [ "out" "ilean" "c" ];
|
||||
oleanPath = relpath + ".olean";
|
||||
ileanPath = relpath + ".ilean";
|
||||
cPath = relpath + ".c";
|
||||
inherit leanFlags leanPluginFlags;
|
||||
leanLoadDynlibFlags = map (p: "--load-dynlib=${pathOfSharedLib p}") (loadDynlibsOfDeps deps);
|
||||
buildCommand = ''
|
||||
dir=$(dirname $relpath)
|
||||
mkdir -p $dir $out/$dir $ilean/$dir $c/$dir
|
||||
if [ -d $src ]; then cp -r $src/. .; else cp $src $leanPath; fi
|
||||
lean -o $out/$oleanPath -i $out/$ileanPath -c $c/$cPath $leanPath $leanFlags $leanPluginFlags $leanLoadDynlibFlags
|
||||
'';
|
||||
}) // {
|
||||
inherit deps;
|
||||
propagatedLoadDynlibs = loadDynlibsOfDeps deps;
|
||||
};
|
||||
compileMod = mod: drv: mkBareDerivation {
|
||||
name = "${mod}-cc";
|
||||
buildInputs = [ leanc stdenv.cc ];
|
||||
hardeningDisable = [ "all" ];
|
||||
oPath = drv.relpath + ".o";
|
||||
inherit leancFlags;
|
||||
buildCommand = ''
|
||||
mkdir -p $out/$(dirname ${drv.relpath})
|
||||
# make local "copy" so `drv`'s Nix store path doesn't end up in ccache's hash
|
||||
ln -s ${drv.c}/${drv.cPath} src.c
|
||||
# on the other hand, a debug build is pretty fast anyway, so preserve the path for gdb
|
||||
leanc -c -o $out/$oPath $leancFlags -fPIC ${if debug then "${drv.c}/${drv.cPath} -g" else "src.c -O3 -DNDEBUG -DLEAN_EXPORTING"}
|
||||
'';
|
||||
};
|
||||
mkMod = mod: deps:
|
||||
let drv = buildMod mod deps;
|
||||
obj = compileMod mod drv;
|
||||
# this attribute will only be used if any dependent module is precompiled
|
||||
sharedLib = mkSharedLib mod "${obj}/${obj.oPath} ${lib.concatStringsSep " " (map (d: pathOfSharedLib d.sharedLib) deps)}";
|
||||
in drv // {
|
||||
inherit obj sharedLib;
|
||||
} // lib.optionalAttrs precompileModules {
|
||||
propagatedLoadDynlibs = [sharedLib];
|
||||
};
|
||||
externalModMap = lib.foldr (dep: depMap: depMap // dep.mods) {} allExternalDeps;
|
||||
# map from module name to derivation
|
||||
modCandidates = mapAttrs (mod: header:
|
||||
let
|
||||
deps = if header.errors == []
|
||||
then map (m: m.module) header.result.imports
|
||||
else abort "errors while parsing imports of ${mod}:\n${lib.concatStringsSep "\n" header.errors}";
|
||||
in mkMod mod (map (dep: if modDepsMap ? ${dep} then modCandidates.${dep} else externalModMap.${dep}) deps)) modDepsMap;
|
||||
expandGlob = g:
|
||||
if typeOf g == "string" then [g]
|
||||
else if g.glob == "one" then [g.mod]
|
||||
else if g.glob == "submodules" then submodules g.mod
|
||||
else if g.glob == "andSubmodules" then [g.mod] ++ submodules g.mod
|
||||
else throw "unknown glob kind '${g}'";
|
||||
# subset of `modCandidates` that is transitively reachable from `roots`
|
||||
mods' = listToAttrs (map (e: { name = e.key; value = modCandidates.${e.key}; }) (genericClosure {
|
||||
startSet = map (m: { key = m; }) (concatMap expandGlob roots);
|
||||
operator = e: if modDepsMap ? ${e.key} then map (m: { key = m.module; }) (filter (m: modCandidates ? ${m.module}) modDepsMap.${e.key}.result.imports) else [];
|
||||
}));
|
||||
allLinkFlags = lib.foldr (shared: acc: acc ++ [ "-L${shared}" "-l${shared.linkName or shared.name}" ]) linkFlags allNativeSharedLibs;
|
||||
|
||||
objects = mapAttrs (_: m: m.obj) mods';
|
||||
bintools = if stdenv.isDarwin then darwin.cctools else stdenv.cc.bintools.bintools;
|
||||
staticLib = runCommand "${name}-lib" { buildInputs = [ bintools ]; } ''
|
||||
mkdir -p $out
|
||||
ar Trcs $out/lib${libName}.a ${lib.concatStringsSep " " (map (drv: "${drv}/${drv.oPath}") (attrValues objects))};
|
||||
'';
|
||||
|
||||
staticLibLinkWrapper = libs: if groupStaticLibs && !stdenv.isDarwin
|
||||
then "-Wl,--start-group ${libs} -Wl,--end-group"
|
||||
else "${libs}";
|
||||
in rec {
|
||||
inherit name lean deps staticLibDeps allNativeSharedLibs allLinkFlags allExternalDeps src objects staticLib modDepsFile;
|
||||
mods = mapAttrs (_: m:
|
||||
m //
|
||||
# if neither precompilation option was set but a dependent module wants to be precompiled, default to precompiling this package whole
|
||||
lib.optionalAttrs (precompilePackage || !precompileModules) { inherit sharedLib; } //
|
||||
lib.optionalAttrs precompilePackage { propagatedLoadDynlibs = [sharedLib]; })
|
||||
mods';
|
||||
modRoot = depRoot name (attrValues mods);
|
||||
depRoots = linkFarmFromDrvs "depRoots" (map (m: m.LEAN_PATH) (attrValues mods));
|
||||
cTree = symlinkJoin { name = "${name}-cTree"; paths = map (mod: mod.c) (attrValues mods); };
|
||||
oTree = symlinkJoin { name = "${name}-oTree"; paths = (attrValues objects); };
|
||||
iTree = symlinkJoin { name = "${name}-iTree"; paths = map (mod: mod.ilean) (attrValues mods); };
|
||||
sharedLib = mkSharedLib "lib${sharedLibName}" ''
|
||||
${if stdenv.isDarwin then "-Wl,-force_load,${staticLib}/lib${libName}.a" else "-Wl,--whole-archive ${staticLib}/lib${libName}.a -Wl,--no-whole-archive"} \
|
||||
${lib.concatStringsSep " " (map (d: "${d.sharedLib}/*") deps)}'';
|
||||
executable = lib.makeOverridable ({ withSharedStdlib ? true }: let
|
||||
objPaths = map (drv: "${drv}/${drv.oPath}") (attrValues objects) ++ lib.optional withSharedStdlib "${lean-final.leanshared}/*";
|
||||
in runCommand executableName { buildInputs = [ stdenv.cc leanc ]; } ''
|
||||
mkdir -p $out/bin
|
||||
leanc ${staticLibLinkWrapper (lib.concatStringsSep " " (objPaths ++ map (d: "${d}/*.a") allStaticLibDeps))} \
|
||||
-o $out/bin/${executableName} \
|
||||
${lib.concatStringsSep " " allLinkFlags}
|
||||
'') {};
|
||||
})
|
||||
42
nix/lake-dev.in
Normal file
42
nix/lake-dev.in
Normal file
@@ -0,0 +1,42 @@
|
||||
#!@bash@/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
function pebkac() {
|
||||
echo 'This is just a simple Nix adapter for `lake print-paths|serve`.'
|
||||
exit 1
|
||||
}
|
||||
|
||||
[[ $# -gt 0 ]] || pebkac
|
||||
case $1 in
|
||||
--version)
|
||||
# minimum version for `lake serve` with fallback
|
||||
echo 3.1.0
|
||||
;;
|
||||
print-paths)
|
||||
shift
|
||||
deps="$@"
|
||||
root=.
|
||||
# fall back to initial package if not in package
|
||||
[[ ! -f "$root/flake.nix" ]] && root="@srcRoot@"
|
||||
target="$root#print-paths"
|
||||
args=()
|
||||
# HACK: use stage 0 instead of 1 inside Lean's own `src/`
|
||||
[[ -d Lean && -f ../flake.nix ]] && target="@srcTarget@print-paths" && args=@srcArgs@
|
||||
for dep in $deps; do
|
||||
target="$target.\"$dep\""
|
||||
done
|
||||
echo "Building dependencies..." >&2
|
||||
# -v only has "built ...", but "-vv" is a bit too verbose
|
||||
exec @nix@/bin/nix run "$target" ${args[*]} -v
|
||||
;;
|
||||
serve)
|
||||
shift
|
||||
[[ ${1:-} == "--" ]] && shift
|
||||
# `link-ilean` puts them there
|
||||
LEAN_PATH=${LEAN_PATH:+$LEAN_PATH:}$PWD/build/lib exec $(dirname $0)/lean --server "$@"
|
||||
;;
|
||||
*)
|
||||
pebkac
|
||||
;;
|
||||
esac
|
||||
28
nix/lean-dev.in
Normal file
28
nix/lean-dev.in
Normal file
@@ -0,0 +1,28 @@
|
||||
#!@bash@/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
root="."
|
||||
# find package root
|
||||
while [[ "$root" != / ]]; do
|
||||
[ -f "$root/flake.nix" ] && break
|
||||
root="$(realpath "$root/..")"
|
||||
done
|
||||
# fall back to initial package if not in package
|
||||
[[ ! -f "$root/flake.nix" ]] && root="@srcRoot@"
|
||||
|
||||
# use Lean w/ package unless in server mode (which has its own LEAN_PATH logic)
|
||||
target="$root#lean-package"
|
||||
for arg in "$@"; do
|
||||
case $arg in
|
||||
--server | --worker | -v | --version)
|
||||
target="$root#lean"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
args=(-- "$@")
|
||||
# HACK: use stage 0 instead of 1 inside Lean's own `src/`
|
||||
[[ -d Lean && -f ../flake.nix ]] && target="@srcTarget@" && args=@srcArgs@
|
||||
|
||||
LEAN_SYSROOT="$(dirname "$0")/.." exec @nix@/bin/nix ${LEAN_NIX_ARGS:-} run "$target" ${args[*]}
|
||||
52
nix/packages.nix
Normal file
52
nix/packages.nix
Normal file
@@ -0,0 +1,52 @@
|
||||
{ src, pkgs, ... } @ args:
|
||||
with pkgs;
|
||||
let
|
||||
# https://github.com/NixOS/nixpkgs/issues/130963
|
||||
llvmPackages = if stdenv.isDarwin then llvmPackages_11 else llvmPackages_15;
|
||||
cc = (ccacheWrapper.override rec {
|
||||
cc = llvmPackages.clang;
|
||||
extraConfig = ''
|
||||
export CCACHE_DIR=/nix/var/cache/ccache
|
||||
export CCACHE_UMASK=007
|
||||
export CCACHE_BASE_DIR=$NIX_BUILD_TOP
|
||||
# https://github.com/NixOS/nixpkgs/issues/109033
|
||||
args=("$@")
|
||||
for ((i=0; i<"''${#args[@]}"; i++)); do
|
||||
case ''${args[i]} in
|
||||
-frandom-seed=*) unset args[i]; break;;
|
||||
esac
|
||||
done
|
||||
set -- "''${args[@]}"
|
||||
[ -d $CCACHE_DIR ] || exec ${cc}/bin/$(basename "$0") "$@"
|
||||
'';
|
||||
}).overrideAttrs (old: {
|
||||
# https://github.com/NixOS/nixpkgs/issues/119779
|
||||
installPhase = builtins.replaceStrings ["use_response_file_by_default=1"] ["use_response_file_by_default=0"] old.installPhase;
|
||||
});
|
||||
stdenv' = if stdenv.isLinux then useGoldLinker stdenv else stdenv;
|
||||
lean = callPackage (import ./bootstrap.nix) (args // {
|
||||
stdenv = overrideCC stdenv' cc;
|
||||
inherit src buildLeanPackage llvmPackages;
|
||||
});
|
||||
makeOverridableLeanPackage = f:
|
||||
let newF = origArgs: f origArgs // {
|
||||
overrideArgs = newArgs: makeOverridableLeanPackage f (origArgs // newArgs);
|
||||
};
|
||||
in lib.setFunctionArgs newF (lib.getFunctionArgs f) // {
|
||||
override = args: makeOverridableLeanPackage (f.override args);
|
||||
};
|
||||
buildLeanPackage = makeOverridableLeanPackage (callPackage (import ./buildLeanPackage.nix) (args // {
|
||||
inherit (lean) stdenv;
|
||||
lean = lean.stage1;
|
||||
inherit (lean.stage1) leanc;
|
||||
}));
|
||||
in {
|
||||
inherit cc buildLeanPackage llvmPackages;
|
||||
nixpkgs = pkgs;
|
||||
ciShell = writeShellScriptBin "ciShell" ''
|
||||
set -o pipefail
|
||||
export PATH=${moreutils}/bin:$PATH
|
||||
# prefix lines with cumulative and individual execution time
|
||||
"$@" |& ts -i "(%.S)]" | ts -s "[%M:%S"
|
||||
'';
|
||||
} // lean.stage1
|
||||
1
nix/templates/pkg/MyPackage.lean
Normal file
1
nix/templates/pkg/MyPackage.lean
Normal file
@@ -0,0 +1 @@
|
||||
#eval "Hello, world!"
|
||||
21
nix/templates/pkg/flake.nix
Normal file
21
nix/templates/pkg/flake.nix
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
description = "My Lean package";
|
||||
|
||||
inputs.lean.url = "github:leanprover/lean4";
|
||||
inputs.flake-utils.url = "github:numtide/flake-utils";
|
||||
|
||||
outputs = { self, lean, flake-utils }: flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
leanPkgs = lean.packages.${system};
|
||||
pkg = leanPkgs.buildLeanPackage {
|
||||
name = "MyPackage"; # must match the name of the top-level .lean file
|
||||
src = ./.;
|
||||
};
|
||||
in {
|
||||
packages = pkg // {
|
||||
inherit (leanPkgs) lean;
|
||||
};
|
||||
|
||||
defaultPackage = pkg.modRoot;
|
||||
});
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
/-
|
||||
Copyright (c) 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Leonardo de Moura
|
||||
-/
|
||||
import Lean
|
||||
|
||||
namespace Lean.Meta.Grind.Analyzer
|
||||
|
||||
|
||||
/-!
|
||||
A simple E-matching annotation analyzer.
|
||||
For each theorem annotated as an E-matching candidate, it creates an artificial goal, executes `grind` and shows the
|
||||
number of instances created.
|
||||
For a theorem of the form `params -> type`, the artificial goal is of the form `params -> type -> False`.
|
||||
-/
|
||||
|
||||
/--
|
||||
`grind` configuration for the analyzer. We disable case-splits and lookahead,
|
||||
increase the number of generations, and limit the number of instances generated.
|
||||
-/
|
||||
def config : Grind.Config := {
|
||||
splits := 0
|
||||
lookahead := false
|
||||
mbtc := false
|
||||
ematch := 20
|
||||
instances := 100
|
||||
gen := 10
|
||||
}
|
||||
|
||||
structure Config where
|
||||
/-- Minimum number of instantiations to trigger summary report -/
|
||||
min : Nat := 10
|
||||
/-- Minimum number of instantiations to trigger detailed report -/
|
||||
detailed : Nat := 50
|
||||
|
||||
def mkParams : MetaM Params := do
|
||||
let params ← Grind.mkParams config
|
||||
let ematch ← getEMatchTheorems
|
||||
let casesTypes ← Grind.getCasesTypes
|
||||
return { params with ematch, casesTypes }
|
||||
|
||||
/-- Returns the total number of generated instances. -/
|
||||
private def sum (cs : PHashMap Origin Nat) : Nat := Id.run do
|
||||
let mut r := 0
|
||||
for (_, c) in cs do
|
||||
r := r + c
|
||||
return r
|
||||
|
||||
private def thmsToMessageData (thms : PHashMap Origin Nat) : MetaM MessageData := do
|
||||
let data := thms.toArray.filterMap fun (origin, c) =>
|
||||
match origin with
|
||||
| .decl declName => some (declName, c)
|
||||
| _ => none
|
||||
let data := data.qsort fun (d₁, c₁) (d₂, c₂) => if c₁ == c₂ then Name.lt d₁ d₂ else c₁ > c₂
|
||||
let data ← data.mapM fun (declName, counter) =>
|
||||
return .trace { cls := `thm } m!"{.ofConst (← mkConstWithLevelParams declName)} ↦ {counter}" #[]
|
||||
return .trace { cls := `thm } "instances" data
|
||||
|
||||
/--
|
||||
Analyzes theorem `declName`. That is, creates the artificial goal based on `declName` type,
|
||||
and invokes `grind` on it.
|
||||
-/
|
||||
def analyzeEMatchTheorem (declName : Name) (c : Config) : MetaM Unit := do
|
||||
let info ← getConstInfo declName
|
||||
let mvarId ← forallTelescope info.type fun _ type => do
|
||||
withLocalDeclD `h type fun _ => do
|
||||
return (← mkFreshExprMVar (mkConst ``False)).mvarId!
|
||||
let result ← Grind.main mvarId (← mkParams) (pure ())
|
||||
let thms := result.counters.thm
|
||||
let s := sum thms
|
||||
if s > c.min then
|
||||
IO.println s!"{declName} : {s}"
|
||||
if s > c.detailed then
|
||||
logInfo m!"{declName}\n{← thmsToMessageData thms}"
|
||||
|
||||
-- Not sure why this is failing: `down_pure` perhaps has an unnecessary universe parameter?
|
||||
run_meta analyzeEMatchTheorem ``Std.Do.SPred.down_pure {}
|
||||
|
||||
/-- Analyzes all theorems in the standard library marked as E-matching theorems. -/
|
||||
def analyzeEMatchTheorems (c : Config := {}) : MetaM Unit := do
|
||||
let origins := (← getEMatchTheorems).getOrigins
|
||||
let decls := origins.filterMap fun | .decl declName => some declName | _ => none
|
||||
for declName in decls.mergeSort Name.lt do
|
||||
try
|
||||
analyzeEMatchTheorem declName c
|
||||
catch e =>
|
||||
logError m!"{declName} failed with {e.toMessageData}"
|
||||
logInfo m!"Finished analyzing {decls.length} theorems"
|
||||
|
||||
/-- Macro for analyzing E-match theorems with unlimited heartbeats -/
|
||||
macro "#analyzeEMatchTheorems" : command => `(
|
||||
set_option maxHeartbeats 0 in
|
||||
run_meta analyzeEMatchTheorems
|
||||
)
|
||||
|
||||
#analyzeEMatchTheorems
|
||||
|
||||
-- -- We can analyze specific theorems using commands such as
|
||||
set_option trace.grind.ematch.instance true
|
||||
|
||||
-- 1. grind immediately sees `(#[] : Array α) = ([] : List α).toArray` but probably this should be hidden.
|
||||
-- 2. `Vector.toArray_empty` keys on `Array.mk []` rather than `#v[].toArray`
|
||||
-- I guess we could add `(#[].extract _ _).extract _ _` as a stop pattern.
|
||||
run_meta analyzeEMatchTheorem ``Array.extract_empty {}
|
||||
|
||||
-- Neither `Option.bind_some` nor `Option.bind_fun_some` fire, because the terms appear inside
|
||||
-- lambdas. So we get crazy things like:
|
||||
-- `fun x => ((some x).bind some).bind fun x => (some x).bind fun x => (some x).bind some`
|
||||
-- We could consider replacing `filterMap_some` with
|
||||
-- `filterMap g (filterMap f xs) = filterMap (f >=> g) xs`
|
||||
-- to avoid the lambda that `grind` struggles with, but this would require more API around the fish.
|
||||
run_meta analyzeEMatchTheorem ``Array.filterMap_some {}
|
||||
|
||||
-- Not entirely certain what is wrong here, but certainly
|
||||
-- `eq_empty_of_append_eq_empty` is firing too often.
|
||||
-- Ideally we could instantiate this is we fine `xs ++ ys` in the same equivalence class,
|
||||
-- note just as soon as we see `xs ++ ys`.
|
||||
-- I've tried removing this in https://github.com/leanprover/lean4/pull/10162
|
||||
run_meta analyzeEMatchTheorem ``Array.range'_succ {}
|
||||
|
||||
-- Perhaps the same story here.
|
||||
run_meta analyzeEMatchTheorem ``Array.range_succ {}
|
||||
|
||||
-- `zip_map_left` and `zip_map_right` are bad grind lemmas,
|
||||
-- checking if they can be removed in https://github.com/leanprover/lean4/pull/10163
|
||||
run_meta analyzeEMatchTheorem ``Array.zip_map {}
|
||||
|
||||
-- It seems crazy to me that as soon as we have `0 >>> n = 0`, we instantiate based on the
|
||||
-- pattern `0 >>> n >>> m` by substituting `0` into `0 >>> n` to produce the `0 >>> n >>> n`.
|
||||
-- I don't think any forbidden subterms can help us here. I don't know what to do. :-(
|
||||
run_meta analyzeEMatchTheorem ``Int.zero_shiftRight {}
|
||||
@@ -1,75 +0,0 @@
|
||||
import Lake.CLI.Main
|
||||
|
||||
/-!
|
||||
|
||||
Usage: `lean --run script/Modulize.lean [--meta] file1.lean file2.lean ...`
|
||||
|
||||
A simple script that inserts `module` and `public section` into un-modulized files and
|
||||
bumps their imports to `public`.
|
||||
|
||||
When `--meta` is passed, `public meta section` and `public meta import` is used instead.
|
||||
-/
|
||||
|
||||
open Lean Parser.Module
|
||||
|
||||
def main (args : List String) : IO Unit := do
|
||||
let mut args := args
|
||||
let mut doMeta := false
|
||||
while !args.isEmpty && args[0]!.startsWith "-" do
|
||||
match args[0]! with
|
||||
| "--meta" => doMeta := true
|
||||
| arg => throw <| .userError s!"unknown flag '{arg}'"
|
||||
args := args.tail
|
||||
|
||||
for path in args do
|
||||
-- Parse the input file
|
||||
let mut text ← IO.FS.readFile path
|
||||
let inputCtx := Parser.mkInputContext text path
|
||||
let (header, parserState, msgs) ← Parser.parseHeader inputCtx
|
||||
if !msgs.toList.isEmpty then -- skip this file if there are parse errors
|
||||
msgs.forM fun msg => msg.toString >>= IO.println
|
||||
throw <| .userError "parse errors in file"
|
||||
let `(header| $[module%$moduleTk?]? $imps:import*) := header
|
||||
| throw <| .userError s!"unexpected header syntax of {path}"
|
||||
if moduleTk?.isSome then
|
||||
continue
|
||||
|
||||
-- initial whitespace if empty header
|
||||
let startPos := header.raw.getPos? |>.getD parserState.pos
|
||||
|
||||
let dummyEnv ← mkEmptyEnvironment
|
||||
let (initCmd, parserState', _) :=
|
||||
Parser.parseCommand inputCtx { env := dummyEnv, options := {} } parserState msgs
|
||||
|
||||
-- insert section if any trailing command
|
||||
if !initCmd.isOfKind ``Parser.Command.eoi then
|
||||
let insertPos? :=
|
||||
-- put below initial module docstring if any
|
||||
guard (initCmd.isOfKind ``Parser.Command.moduleDoc) *> initCmd.getTailPos? <|>
|
||||
-- else below header
|
||||
header.raw.getTailPos?
|
||||
let insertPos := insertPos?.getD startPos -- empty header
|
||||
let mut sec := if doMeta then
|
||||
"public meta section"
|
||||
else
|
||||
"@[expose] public section"
|
||||
if !imps.isEmpty then
|
||||
sec := "\n\n" ++ sec
|
||||
if insertPos?.isNone then
|
||||
sec := sec ++ "\n\n"
|
||||
text := text.extract 0 insertPos ++ sec ++ text.extract insertPos text.endPos
|
||||
|
||||
-- prepend each import with `public `
|
||||
for imp in imps.reverse do
|
||||
let insertPos := imp.raw.getPos?.get!
|
||||
let prfx := if doMeta then "public meta " else "public "
|
||||
text := text.extract 0 insertPos ++ prfx ++ text.extract insertPos text.endPos
|
||||
|
||||
-- insert `module` header
|
||||
let mut initText := text.extract 0 startPos
|
||||
if !initText.trim.isEmpty then
|
||||
-- If there is a header comment, preserve it and put `module` in the line after
|
||||
initText := initText.trimRight ++ "\n"
|
||||
text := initText ++ "module\n\n" ++ text.extract startPos text.endPos
|
||||
|
||||
IO.FS.writeFile path text
|
||||
@@ -1,584 +0,0 @@
|
||||
/-
|
||||
Copyright (c) 2023 Mario Carneiro. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Mario Carneiro, Sebastian Ullrich
|
||||
-/
|
||||
import Lake.CLI.Main
|
||||
import Lean.ExtraModUses
|
||||
|
||||
/-! # `lake exe shake` command
|
||||
|
||||
This command will check the current project (or a specified target module) and all dependencies for
|
||||
unused imports. This works by looking at generated `.olean` files to deduce required imports and
|
||||
ensuring that every import is used to contribute some constant or other elaboration dependency
|
||||
recorded by `recordExtraModUse`. Because recompilation is not needed this is quite fast (about 8
|
||||
seconds to check `Mathlib` and all dependencies).
|
||||
-/
|
||||
|
||||
/-- help string for the command line interface -/
|
||||
def help : String := "Lean project tree shaking tool
|
||||
Usage: lake exe shake [OPTIONS] <MODULE>..
|
||||
|
||||
Arguments:
|
||||
<MODULE>
|
||||
A module path like `Mathlib`. All files transitively reachable from the
|
||||
provided module(s) will be checked.
|
||||
|
||||
Options:
|
||||
--force
|
||||
Skips the `lake build --no-build` sanity check
|
||||
|
||||
--fix
|
||||
Apply the suggested fixes directly. Make sure you have a clean checkout
|
||||
before running this, so you can review the changes.
|
||||
"
|
||||
|
||||
open Lean
|
||||
|
||||
/-- We use `Nat` as a bitset for doing efficient set operations.
|
||||
The bit indexes will usually be a module index. -/
|
||||
structure Bitset where
|
||||
toNat : Nat
|
||||
deriving Inhabited, DecidableEq, Repr
|
||||
|
||||
namespace Bitset
|
||||
|
||||
instance : EmptyCollection Bitset where
|
||||
emptyCollection := { toNat := 0 }
|
||||
|
||||
instance : Insert Nat Bitset where
|
||||
insert i s := { toNat := s.toNat ||| (1 <<< i) }
|
||||
|
||||
instance : Singleton Nat Bitset where
|
||||
singleton i := insert i ∅
|
||||
|
||||
instance : Inter Bitset where
|
||||
inter a b := { toNat := a.toNat &&& b.toNat }
|
||||
|
||||
instance : Union Bitset where
|
||||
union a b := { toNat := a.toNat ||| b.toNat }
|
||||
|
||||
instance : XorOp Bitset where
|
||||
xor a b := { toNat := a.toNat ^^^ b.toNat }
|
||||
|
||||
def has (s : Bitset) (i : Nat) : Bool := s ∩ {i} ≠ ∅
|
||||
|
||||
end Bitset
|
||||
|
||||
/-- The kind of a module dependency, corresponding to the homonymous `ExtraModUse` fields. -/
|
||||
structure NeedsKind where
|
||||
isExported : Bool
|
||||
isMeta : Bool
|
||||
deriving Inhabited, BEq, Repr, Hashable
|
||||
|
||||
namespace NeedsKind
|
||||
|
||||
@[match_pattern] abbrev priv : NeedsKind := { isExported := false, isMeta := false }
|
||||
@[match_pattern] abbrev pub : NeedsKind := { isExported := true, isMeta := false }
|
||||
@[match_pattern] abbrev metaPriv : NeedsKind := { isExported := false, isMeta := true }
|
||||
@[match_pattern] abbrev metaPub : NeedsKind := { isExported := true, isMeta := true }
|
||||
|
||||
def all : Array NeedsKind := #[pub, priv, metaPub, metaPriv]
|
||||
|
||||
def ofImport : Lean.Import → NeedsKind
|
||||
| { isExported := true, isMeta := true, .. } => .metaPub
|
||||
| { isExported := true, isMeta := false, .. } => .pub
|
||||
| { isExported := false, isMeta := true, .. } => .metaPriv
|
||||
| { isExported := false, isMeta := false, .. } => .priv
|
||||
|
||||
end NeedsKind
|
||||
|
||||
/-- Logically, a map `NeedsKind → Bitset`. -/
|
||||
structure Needs where
|
||||
pub : Bitset
|
||||
priv : Bitset
|
||||
metaPub : Bitset
|
||||
metaPriv : Bitset
|
||||
deriving Inhabited, Repr
|
||||
|
||||
def Needs.empty : Needs := default
|
||||
|
||||
def Needs.get (needs : Needs) (k : NeedsKind) : Bitset :=
|
||||
match k with
|
||||
| .pub => needs.pub
|
||||
| .priv => needs.priv
|
||||
| .metaPub => needs.metaPub
|
||||
| .metaPriv => needs.metaPriv
|
||||
|
||||
def Needs.has (needs : Needs) (k : NeedsKind) (i : ModuleIdx) : Bool :=
|
||||
needs.get k |>.has i
|
||||
|
||||
def Needs.set (needs : Needs) (k : NeedsKind) (s : Bitset) : Needs :=
|
||||
match k with
|
||||
| .pub => { needs with pub := s }
|
||||
| .priv => { needs with priv := s }
|
||||
| .metaPub => { needs with metaPub := s }
|
||||
| .metaPriv => { needs with metaPriv := s }
|
||||
|
||||
def Needs.modify (needs : Needs) (k : NeedsKind) (f : Bitset → Bitset) : Needs :=
|
||||
needs.set k (f (needs.get k))
|
||||
|
||||
def Needs.union (needs : Needs) (k : NeedsKind) (s : Bitset) : Needs :=
|
||||
needs.modify k (· ∪ s)
|
||||
|
||||
def Needs.sub (needs : Needs) (k : NeedsKind) (s : Bitset) : Needs :=
|
||||
needs.modify k (fun s' => s' ^^^ (s' ∩ s))
|
||||
|
||||
/-- The main state of the checker, containing information on all loaded modules. -/
|
||||
structure State where
|
||||
env : Environment
|
||||
/--
|
||||
`transDeps[i]` is the (non-reflexive) transitive closure of `mods[i].imports`. More specifically,
|
||||
* `j ∈ transDeps[i].pub` if `i -(public import)->+ j`
|
||||
* `j ∈ transDeps[i].priv` if `i -(import ...)-> _ -(public import)->* j`
|
||||
* `j ∈ transDeps[i].priv` if `i -(import all)->+ -(public import ...)-> _ -(public import)->* j`
|
||||
* `j ∈ transDeps[i].metaPub` if `i -(public (meta)? import)->* _ -(public meta import)-> _ -(public (meta)? import ...)->* j`
|
||||
* `j ∈ transDeps[i].metaPriv` if `i -(meta import ...)-> _ -(public (meta)? import ...)->* j`
|
||||
* `j ∈ transDeps[i].metaPriv` if `i -(import all)->+ -(public meta import ...)-> _ -(public (meta)? import ...)->* j`
|
||||
-/
|
||||
transDeps : Array Needs := #[]
|
||||
/--
|
||||
`transDepsOrig` is the initial value of `transDeps` before changes potentially resulting from
|
||||
changes to upstream headers.
|
||||
-/
|
||||
transDepsOrig : Array Needs := #[]
|
||||
|
||||
def State.mods (s : State) := s.env.header.moduleData
|
||||
def State.modNames (s : State) := s.env.header.moduleNames
|
||||
|
||||
/--
|
||||
Given module `j`'s transitive dependencies, computes the union of `transImps` and the transitive
|
||||
dependencies resulting from importing the module via `imp` according to the rules of
|
||||
`State.transDeps`.
|
||||
-/
|
||||
def addTransitiveImps (transImps : Needs) (imp : Import) (j : Nat) (impTransImps : Needs) : Needs := Id.run do
|
||||
let mut transImps := transImps
|
||||
|
||||
-- `j ∈ transDeps[i].pub` if `i -(public import)->+ j`
|
||||
if imp.isExported && !imp.isMeta then
|
||||
transImps := transImps.union .pub {j} |>.union .pub (impTransImps.get .pub)
|
||||
|
||||
if !imp.isExported && !imp.isMeta then
|
||||
-- `j ∈ transDeps[i].priv` if `i -(import ...)-> _ -(public import)->* j`
|
||||
transImps := transImps.union .priv {j} |>.union .priv (impTransImps.get .pub)
|
||||
if imp.importAll then
|
||||
-- `j ∈ transDeps[i].priv` if `i -(import all)->+ -(public import ...)-> _ -(public import)->* j`
|
||||
transImps := transImps.union .priv (impTransImps.get .pub)
|
||||
|
||||
-- `j ∈ transDeps[i].metaPub` if `i -(public (meta)? import)->* _ -(public meta import)-> _ -(public (meta)? import ...)->* j`
|
||||
if imp.isExported then
|
||||
transImps := transImps.union .metaPub (impTransImps.get .metaPub)
|
||||
if imp.isMeta then
|
||||
transImps := transImps.union .metaPub {j} |>.union .metaPub (impTransImps.get .pub ∪ impTransImps.get .metaPub)
|
||||
|
||||
if !imp.isExported then
|
||||
if imp.isMeta then
|
||||
-- `j ∈ transDeps[i].metaPriv` if `i -(meta import ...)-> _ -(public (meta)? import ...)->* j`
|
||||
transImps := transImps.union .metaPriv {j} |>.union .metaPriv (impTransImps.get .pub ∪ impTransImps.get .metaPub)
|
||||
if imp.importAll then
|
||||
-- `j ∈ transDeps[i].metaPriv` if `i -(import all)->+ -(public meta import ...)-> _ -(public (meta)? import ...)->* j`
|
||||
transImps := transImps.union .metaPriv (impTransImps.get .metaPub)
|
||||
|
||||
transImps
|
||||
|
||||
/-- Calculates the needs for a given module `mod` from constants and recorded extra uses. -/
|
||||
def calcNeeds (env : Environment) (i : ModuleIdx) : Needs := Id.run do
|
||||
let mut needs := default
|
||||
for ci in env.header.moduleData[i]!.constants do
|
||||
let pubCI? := env.setExporting true |>.find? ci.name
|
||||
let k := { isExported := pubCI?.isSome, isMeta := isMeta env ci.name }
|
||||
needs := visitExpr k ci.type needs
|
||||
if let some e := ci.value? (allowOpaque := true) then
|
||||
-- type and value has identical visibility under `meta`
|
||||
let k := if k.isMeta then k else
|
||||
if pubCI?.any (·.hasValue (allowOpaque := true)) then .pub else .priv
|
||||
needs := visitExpr k e needs
|
||||
|
||||
for use in getExtraModUses env i do
|
||||
let j := env.getModuleIdx? use.module |>.get!
|
||||
needs := needs.union { use with } {j}
|
||||
|
||||
return needs
|
||||
where
|
||||
/-- Accumulate the results from expression `e` into `deps`. -/
|
||||
visitExpr (k : NeedsKind) e deps :=
|
||||
Lean.Expr.foldConsts e deps fun c deps => match env.getModuleIdxFor? c with
|
||||
| some j =>
|
||||
let k := { k with isMeta := k.isMeta && !isMeta env c }
|
||||
if j != i then deps.union k {j} else deps
|
||||
| _ => deps
|
||||
|
||||
/--
|
||||
Calculates the same as `calcNeeds` but tracing each module to a use-def declaration pair or
|
||||
`none` if merely a recorded extra use.
|
||||
-/
|
||||
def getExplanations (env : Environment) (i : ModuleIdx) :
|
||||
Std.HashMap (ModuleIdx × NeedsKind) (Option (Name × Name)) := Id.run do
|
||||
let mut deps := default
|
||||
for ci in env.header.moduleData[i]!.constants do
|
||||
let pubCI? := env.setExporting true |>.find? ci.name
|
||||
let k := { isExported := pubCI?.isSome, isMeta := isMeta env ci.name }
|
||||
deps := visitExpr k ci.name ci.type deps
|
||||
if let some e := ci.value? (allowOpaque := true) then
|
||||
let k := if k.isMeta then k else
|
||||
if pubCI?.any (·.hasValue (allowOpaque := true)) then .pub else .priv
|
||||
deps := visitExpr k ci.name e deps
|
||||
|
||||
for use in getExtraModUses env i do
|
||||
let j := env.getModuleIdx? use.module |>.get!
|
||||
if !deps.contains (j, { use with }) then
|
||||
deps := deps.insert (j, { use with }) none
|
||||
|
||||
return deps
|
||||
where
|
||||
/-- Accumulate the results from expression `e` into `deps`. -/
|
||||
visitExpr (k : NeedsKind) name e deps :=
|
||||
Lean.Expr.foldConsts e deps fun c deps => match env.getModuleIdxFor? c with
|
||||
| some i =>
|
||||
let k := { k with isMeta := k.isMeta && !isMeta env c }
|
||||
if
|
||||
if let some (some (name', _)) := deps[(i, k)]? then
|
||||
decide (name.toString.length < name'.toString.length)
|
||||
else true
|
||||
then
|
||||
deps.insert (i, k) (name, c)
|
||||
else
|
||||
deps
|
||||
| _ => deps
|
||||
|
||||
partial def initStateFromEnv (env : Environment) : State := Id.run do
|
||||
let mut s := { env }
|
||||
for i in 0...env.header.moduleData.size do
|
||||
let mod := env.header.moduleData[i]!
|
||||
let mut imps := #[]
|
||||
let mut transImps := Needs.empty
|
||||
for imp in mod.imports do
|
||||
let j := env.getModuleIdx? imp.module |>.get!
|
||||
imps := imps.push j
|
||||
transImps := addTransitiveImps transImps imp j s.transDeps[j]!
|
||||
s := { s with transDeps := s.transDeps.push transImps }
|
||||
s := { s with transDepsOrig := s.transDeps }
|
||||
return s
|
||||
|
||||
/-- The list of edits that will be applied in `--fix`. `edits[i] = (removed, added)` where:
|
||||
|
||||
* If `j ∈ removed` then we want to delete module named `j` from the imports of `i`
|
||||
* If `j ∈ added` then we want to add module index `j` to the imports of `i`.
|
||||
-/
|
||||
abbrev Edits := Std.HashMap Name (Array Import × Array Import)
|
||||
|
||||
/-- Register that we want to remove `tgt` from the imports of `src`. -/
|
||||
def Edits.remove (ed : Edits) (src : Name) (tgt : Import) : Edits :=
|
||||
match ed.get? src with
|
||||
| none => ed.insert src (#[tgt], #[])
|
||||
| some (a, b) => ed.insert src (a.push tgt, b)
|
||||
|
||||
/-- Register that we want to add `tgt` to the imports of `src`. -/
|
||||
def Edits.add (ed : Edits) (src : Name) (tgt : Import) : Edits :=
|
||||
match ed.get? src with
|
||||
| none => ed.insert src (#[], #[tgt])
|
||||
| some (a, b) => ed.insert src (a, b.push tgt)
|
||||
|
||||
/-- Parse a source file to extract the location of the import lines, for edits and error messages.
|
||||
|
||||
Returns `(path, inputCtx, imports, endPos)` where `imports` is the `Lean.Parser.Module.import` list
|
||||
and `endPos` is the position of the end of the header.
|
||||
-/
|
||||
def parseHeaderFromString (text path : String) :
|
||||
IO (System.FilePath × Parser.InputContext ×
|
||||
TSyntaxArray ``Parser.Module.import × String.Pos) := do
|
||||
let inputCtx := Parser.mkInputContext text path
|
||||
let (header, parserState, msgs) ← Parser.parseHeader inputCtx
|
||||
if !msgs.toList.isEmpty then -- skip this file if there are parse errors
|
||||
msgs.forM fun msg => msg.toString >>= IO.println
|
||||
throw <| .userError "parse errors in file"
|
||||
-- the insertion point for `add` is the first newline after the imports
|
||||
let insertion := header.raw.getTailPos?.getD parserState.pos
|
||||
let insertion := text.findAux (· == '\n') text.endPos insertion + ⟨1⟩
|
||||
pure (path, inputCtx, .mk header.raw[2].getArgs, insertion)
|
||||
|
||||
/-- Parse a source file to extract the location of the import lines, for edits and error messages.
|
||||
|
||||
Returns `(path, inputCtx, imports, endPos)` where `imports` is the `Lean.Parser.Module.import` list
|
||||
and `endPos` is the position of the end of the header.
|
||||
-/
|
||||
def parseHeader (srcSearchPath : SearchPath) (mod : Name) :
|
||||
IO (System.FilePath × Parser.InputContext ×
|
||||
TSyntaxArray ``Parser.Module.import × String.Pos) := do
|
||||
-- Parse the input file
|
||||
let some path ← srcSearchPath.findModuleWithExt "lean" mod
|
||||
| throw <| .userError s!"error: failed to find source file for {mod}"
|
||||
let text ← IO.FS.readFile path
|
||||
parseHeaderFromString text path.toString
|
||||
|
||||
def decodeImport : TSyntax ``Parser.Module.import → Import
|
||||
| `(Parser.Module.import| $[public%$pubTk?]? $[meta%$metaTk?]? import $[all%$allTk?]? $id) =>
|
||||
{ module := id.getId, isExported := pubTk?.isSome, isMeta := metaTk?.isSome, importAll := allTk?.isSome }
|
||||
| stx => panic! s!"unexpected syntax {stx}"
|
||||
|
||||
/-- Analyze and report issues from module `i`. Arguments:
|
||||
|
||||
* `srcSearchPath`: Used to find the path for error reporting purposes
|
||||
* `i`: the module index
|
||||
* `needs`: the module's calculated needs
|
||||
* `pinned`: dependencies that should be preserved even if unused
|
||||
* `edits`: accumulates the list of edits to apply if `--fix` is true
|
||||
* `addOnly`: if true, only add missing imports, do not remove unused ones
|
||||
-/
|
||||
def visitModule (srcSearchPath : SearchPath)
|
||||
(i : Nat) (needs : Needs) (preserve : Needs) (edits : Edits)
|
||||
(addOnly := false) (githubStyle := false) (explain := false) : StateT State IO Edits := do
|
||||
let s ← get
|
||||
-- Do transitive reduction of `needs` in `deps`.
|
||||
let mut deps := needs
|
||||
for j in [0:s.mods.size] do
|
||||
let transDeps := s.transDeps[j]!
|
||||
for k in NeedsKind.all do
|
||||
if s.transDepsOrig[i]!.has k j && preserve.has k j then
|
||||
deps := deps.union k {j}
|
||||
if deps.has k j then
|
||||
let transDeps := addTransitiveImps .empty { k with module := .anonymous } j transDeps
|
||||
for k' in NeedsKind.all do
|
||||
deps := deps.sub k' (transDeps.sub k' {j} |>.get k')
|
||||
|
||||
-- Any import which is not in `transDeps` was unused.
|
||||
-- Also accumulate `newDeps` which is the transitive closure of the remaining imports
|
||||
let mut toRemove : Array Import := #[]
|
||||
let mut newDeps := Needs.empty
|
||||
for imp in s.mods[i]!.imports do
|
||||
let j := s.env.getModuleIdx? imp.module |>.get!
|
||||
if
|
||||
-- skip folder-nested imports
|
||||
s.modNames[i]!.isPrefixOf imp.module ||
|
||||
imp.importAll then
|
||||
newDeps := addTransitiveImps newDeps imp j s.transDeps[j]!
|
||||
else
|
||||
let k := NeedsKind.ofImport imp
|
||||
if !addOnly && !deps.has k j && !deps.has { k with isExported := false } j then
|
||||
toRemove := toRemove.push imp
|
||||
else
|
||||
newDeps := addTransitiveImps newDeps imp j s.transDeps[j]!
|
||||
|
||||
-- If `newDeps` does not cover `deps`, then we have to add back some imports until it does.
|
||||
-- To minimize new imports we pick only new imports which are not transitively implied by
|
||||
-- another new import
|
||||
let mut toAdd : Array Import := #[]
|
||||
for j in [0:s.mods.size] do
|
||||
for k in NeedsKind.all do
|
||||
if deps.has k j && !newDeps.has k j && !newDeps.has { k with isExported := true } j then
|
||||
let imp := { k with module := s.modNames[j]! }
|
||||
toAdd := toAdd.push imp
|
||||
newDeps := addTransitiveImps newDeps imp j s.transDeps[j]!
|
||||
|
||||
-- mark and report the removals
|
||||
let mut edits := toRemove.foldl (init := edits) fun edits imp =>
|
||||
edits.remove s.modNames[i]! imp
|
||||
|
||||
if !toAdd.isEmpty || !toRemove.isEmpty || explain then
|
||||
if let some path ← srcSearchPath.findModuleWithExt "lean" s.modNames[i]! then
|
||||
println! "{path}:"
|
||||
else
|
||||
println! "{s.modNames[i]!}:"
|
||||
|
||||
if !toRemove.isEmpty then
|
||||
println! " remove {toRemove}"
|
||||
|
||||
if githubStyle then
|
||||
try
|
||||
let (path, inputCtx, imports, endHeader) ← parseHeader srcSearchPath s.modNames[i]!
|
||||
for stx in imports do
|
||||
if toRemove.any fun imp => imp == decodeImport stx then
|
||||
let pos := inputCtx.fileMap.toPosition stx.raw.getPos?.get!
|
||||
println! "{path}:{pos.line}:{pos.column+1}: warning: unused import \
|
||||
(use `lake exe shake --fix` to fix this, or `lake exe shake --update` to ignore)"
|
||||
if !toAdd.isEmpty then
|
||||
-- we put the insert message on the beginning of the last import line
|
||||
let pos := inputCtx.fileMap.toPosition endHeader
|
||||
println! "{path}:{pos.line-1}:1: warning: \
|
||||
add {toAdd} instead"
|
||||
catch _ => pure ()
|
||||
|
||||
-- mark and report the additions
|
||||
edits := toAdd.foldl (init := edits) fun edits imp =>
|
||||
edits.add s.modNames[i]! imp
|
||||
|
||||
if !toAdd.isEmpty then
|
||||
println! " add {toAdd}"
|
||||
|
||||
-- recalculate transitive dependencies of downstream modules
|
||||
let mut newTransDepsI := Needs.empty
|
||||
for imp in s.mods[i]!.imports do
|
||||
if !toRemove.contains imp then
|
||||
let j := s.env.getModuleIdx? imp.module |>.get!
|
||||
newTransDepsI := addTransitiveImps newTransDepsI imp j s.transDeps[j]!
|
||||
for imp in toAdd do
|
||||
let j := s.env.getModuleIdx? imp.module |>.get!
|
||||
newTransDepsI := addTransitiveImps newTransDepsI imp j s.transDeps[j]!
|
||||
|
||||
set { s with transDeps := s.transDeps.set! i newTransDepsI }
|
||||
|
||||
if explain then
|
||||
let explanation := getExplanations s.env i
|
||||
let sanitize n := if n.hasMacroScopes then (sanitizeName n).run' { options := {} } else n
|
||||
let run (imp : Import) := do
|
||||
let j := s.env.getModuleIdx? imp.module |>.get!
|
||||
if let some exp? := explanation[(j, NeedsKind.ofImport imp)]? then
|
||||
println! " note: `{imp}` required"
|
||||
if let some (n, c) := exp? then
|
||||
println! " because `{sanitize n}` refers to `{sanitize c}`"
|
||||
else
|
||||
println! " because of additional compile-time dependencies"
|
||||
for j in s.mods[i]!.imports do
|
||||
if !toRemove.contains j then
|
||||
run j
|
||||
for i in toAdd do run i
|
||||
|
||||
return edits
|
||||
|
||||
/-- Convert a list of module names to a bitset of module indexes -/
|
||||
def toBitset (s : State) (ns : List Name) : Bitset :=
|
||||
ns.foldl (init := ∅) fun c name =>
|
||||
match s.env.getModuleIdxFor? name with
|
||||
| some i => c ∪ {i}
|
||||
| none => c
|
||||
|
||||
/-- The parsed CLI arguments. See `help` for more information -/
|
||||
structure Args where
|
||||
/-- `--help`: shows the help -/
|
||||
help : Bool := false
|
||||
/-- `--force`: skips the `lake build --no-build` sanity check -/
|
||||
force : Bool := false
|
||||
/-- `--gh-style`: output messages that can be parsed by `gh-problem-matcher-wrap` -/
|
||||
githubStyle : Bool := false
|
||||
/-- `--explain`: give constants explaining why each module is needed -/
|
||||
explain : Bool := false
|
||||
/-- `--fix`: apply the fixes directly -/
|
||||
fix : Bool := false
|
||||
/-- `<MODULE>..`: the list of root modules to check -/
|
||||
mods : Array Name := #[]
|
||||
|
||||
local instance : Ord Import where
|
||||
compare a b :=
|
||||
if a.isExported && !b.isExported then
|
||||
Ordering.lt
|
||||
else if !a.isExported && b.isExported then
|
||||
Ordering.gt
|
||||
else
|
||||
a.module.cmp b.module
|
||||
|
||||
/-- The main entry point. See `help` for more information on arguments. -/
|
||||
def main (args : List String) : IO UInt32 := do
|
||||
initSearchPath (← findSysroot)
|
||||
-- Parse the arguments
|
||||
let rec parseArgs (args : Args) : List String → Args
|
||||
| [] => args
|
||||
| "--help" :: rest => parseArgs { args with help := true } rest
|
||||
| "--force" :: rest => parseArgs { args with force := true } rest
|
||||
| "--fix" :: rest => parseArgs { args with fix := true } rest
|
||||
| "--explain" :: rest => parseArgs { args with explain := true } rest
|
||||
| "--gh-style" :: rest => parseArgs { args with githubStyle := true } rest
|
||||
| "--" :: rest => { args with mods := args.mods ++ rest.map (·.toName) }
|
||||
| other :: rest => parseArgs { args with mods := args.mods.push other.toName } rest
|
||||
let args := parseArgs {} args
|
||||
|
||||
-- Bail if `--help` is passed
|
||||
if args.help then
|
||||
IO.println help
|
||||
IO.Process.exit 0
|
||||
|
||||
if !args.force then
|
||||
if (← IO.Process.output { cmd := "lake", args := #["build", "--no-build"] }).exitCode != 0 then
|
||||
IO.println "There are out of date oleans. Run `lake build` or `lake exe cache get` first"
|
||||
IO.Process.exit 1
|
||||
|
||||
-- Determine default module(s) to run shake on
|
||||
let defaultTargetModules : Array Name ← try
|
||||
let (elanInstall?, leanInstall?, lakeInstall?) ← Lake.findInstall?
|
||||
let config ← Lake.MonadError.runEIO <| Lake.mkLoadConfig { elanInstall?, leanInstall?, lakeInstall? }
|
||||
let some workspace ← Lake.loadWorkspace config |>.toBaseIO
|
||||
| throw <| IO.userError "failed to load Lake workspace"
|
||||
let defaultTargetModules := workspace.root.defaultTargets.flatMap fun target =>
|
||||
if let some lib := workspace.root.findLeanLib? target then
|
||||
lib.roots
|
||||
else if let some exe := workspace.root.findLeanExe? target then
|
||||
#[exe.config.root]
|
||||
else
|
||||
#[]
|
||||
pure defaultTargetModules
|
||||
catch _ =>
|
||||
pure #[]
|
||||
|
||||
let srcSearchPath ← getSrcSearchPath
|
||||
-- the list of root modules
|
||||
let mods := if args.mods.isEmpty then defaultTargetModules else args.mods
|
||||
-- Only submodules of `pkg` will be edited or have info reported on them
|
||||
let pkg := mods[0]!.components.head!
|
||||
|
||||
-- Load all the modules
|
||||
let imps := mods.map ({ module := · })
|
||||
let (_, s) ← importModulesCore imps (isExported := true) |>.run
|
||||
let s := s.markAllExported
|
||||
let env ← finalizeImport s (isModule := true) imps {} (leakEnv := false) (loadExts := false)
|
||||
|
||||
StateT.run' (s := initStateFromEnv env) do
|
||||
|
||||
let s ← get
|
||||
-- Parse the config file
|
||||
|
||||
-- Run the calculation of the `needs` array in parallel
|
||||
let needs := s.mods.mapIdx fun i _ =>
|
||||
Task.spawn fun _ => calcNeeds s.env i
|
||||
|
||||
if args.fix then
|
||||
println! "The following changes will be made automatically:"
|
||||
|
||||
-- Check all selected modules
|
||||
let mut edits : Edits := ∅
|
||||
let mut revNeeds : Needs := default
|
||||
for i in [0:s.mods.size], t in needs do
|
||||
edits ← visitModule (addOnly := !pkg.isPrefixOf s.modNames[i]!) srcSearchPath i t.get revNeeds edits args.githubStyle args.explain
|
||||
if isExtraRevModUse s.env i then
|
||||
revNeeds := revNeeds.union .priv {i}
|
||||
|
||||
if !args.fix then
|
||||
-- return error if any issues were found
|
||||
return if edits.isEmpty then 0 else 1
|
||||
|
||||
-- Apply the edits to existing files
|
||||
let count ← edits.foldM (init := 0) fun count mod (remove, add) => do
|
||||
let add : Array Import := add.qsortOrd
|
||||
|
||||
-- Parse the input file
|
||||
let (path, inputCtx, imports, insertion) ←
|
||||
try parseHeader srcSearchPath mod
|
||||
catch e => println! e.toString; return count
|
||||
let text := inputCtx.fileMap.source
|
||||
|
||||
-- Calculate the edit result
|
||||
let mut pos : String.Pos := 0
|
||||
let mut out : String := ""
|
||||
let mut seen : Std.HashSet Import := {}
|
||||
for stx in imports do
|
||||
let mod := decodeImport stx
|
||||
if remove.contains mod || seen.contains mod then
|
||||
out := out ++ text.extract pos stx.raw.getPos?.get!
|
||||
-- We use the end position of the syntax, but include whitespace up to the first newline
|
||||
pos := text.findAux (· == '\n') text.endPos stx.raw.getTailPos?.get! + ⟨1⟩
|
||||
seen := seen.insert mod
|
||||
out := out ++ text.extract pos insertion
|
||||
for mod in add do
|
||||
if !seen.contains mod then
|
||||
seen := seen.insert mod
|
||||
out := out ++ s!"{mod}\n"
|
||||
out := out ++ text.extract insertion text.endPos
|
||||
|
||||
IO.FS.writeFile path out
|
||||
return count + 1
|
||||
|
||||
-- Since we throw an error upon encountering issues, we can be sure that everything worked
|
||||
-- if we reach this point of the script.
|
||||
if count > 0 then
|
||||
println! "Successfully applied {count} suggestions."
|
||||
else
|
||||
println! "No edits required."
|
||||
return 0
|
||||
@@ -1,96 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euxo pipefail
|
||||
set -euo pipefail
|
||||
|
||||
cmake --preset release 1>&2
|
||||
|
||||
# We benchmark against stage2/bin to test new optimizations.
|
||||
timeout -s KILL 1h time make -C build/release -j$(nproc) stage3 1>&2
|
||||
# We benchmark against stage 2 to test new optimizations.
|
||||
timeout -s KILL 1h time bash -c 'mkdir -p build/release; cd build/release; cmake ../.. && make -j$(nproc) stage2' 1>&2
|
||||
export PATH=$PWD/build/release/stage2/bin:$PATH
|
||||
|
||||
# The extra opts used to be passed to the Makefile during benchmarking only but with Lake it is
|
||||
# easier to configure them statically.
|
||||
cmake -B build/release/stage3 -S src -DLEAN_EXTRA_LAKEFILE_TOML='weakLeanArgs=["-Dprofiler=true", "-Dprofiler.threshold=9999999", "--stats"]' 1>&2
|
||||
|
||||
(
|
||||
cd tests/bench
|
||||
timeout -s KILL 1h time temci exec --config speedcenter.yaml --in speedcenter.exec.velcom.yaml 1>&2
|
||||
temci report run_output.yaml --reporter codespeed2
|
||||
)
|
||||
|
||||
if [ -d .git ]; then
|
||||
DIR="$(git rev-parse @)"
|
||||
BASE_URL="https://speed.lean-lang.org/lean4-out/$DIR"
|
||||
{
|
||||
cat <<'EOF'
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Lakeprof Report</title>
|
||||
</head>
|
||||
<h1>Lakeprof Report</h1>
|
||||
<button type="button" id="btn_fetch">View build trace in Perfetto</button>
|
||||
<script type="text/javascript">
|
||||
const ORIGIN = 'https://ui.perfetto.dev';
|
||||
|
||||
const btnFetch = document.getElementById('btn_fetch');
|
||||
|
||||
async function fetchAndOpen(traceUrl) {
|
||||
const resp = await fetch(traceUrl);
|
||||
// Error checking is left as an exercise to the reader.
|
||||
const blob = await resp.blob();
|
||||
const arrayBuffer = await blob.arrayBuffer();
|
||||
openTrace(arrayBuffer, traceUrl);
|
||||
}
|
||||
|
||||
function openTrace(arrayBuffer, traceUrl) {
|
||||
const win = window.open(ORIGIN);
|
||||
if (!win) {
|
||||
btnFetch.style.background = '#f3ca63';
|
||||
btnFetch.onclick = () => openTrace(arrayBuffer);
|
||||
btnFetch.innerText = 'Popups blocked, click here to open the trace file';
|
||||
return;
|
||||
}
|
||||
|
||||
const timer = setInterval(() => win.postMessage('PING', ORIGIN), 50);
|
||||
|
||||
const onMessageHandler = (evt) => {
|
||||
if (evt.data !== 'PONG') return;
|
||||
|
||||
// We got a PONG, the UI is ready.
|
||||
window.clearInterval(timer);
|
||||
window.removeEventListener('message', onMessageHandler);
|
||||
|
||||
const reopenUrl = new URL(location.href);
|
||||
reopenUrl.hash = `#reopen=${traceUrl}`;
|
||||
win.postMessage({
|
||||
perfetto: {
|
||||
buffer: arrayBuffer,
|
||||
title: 'Lake Build Trace',
|
||||
url: reopenUrl.toString(),
|
||||
}}, ORIGIN);
|
||||
};
|
||||
|
||||
window.addEventListener('message', onMessageHandler);
|
||||
}
|
||||
|
||||
// This is triggered when following the link from the Perfetto UI's sidebar.
|
||||
if (location.hash.startsWith('#reopen=')) {
|
||||
const traceUrl = location.hash.substr(8);
|
||||
fetchAndOpen(traceUrl);
|
||||
}
|
||||
EOF
|
||||
cat <<EOF
|
||||
btnFetch.onclick = () => fetchAndOpen("$BASE_URL/lakeprof.trace_event");
|
||||
</script>
|
||||
EOF
|
||||
echo "<pre><code>"
|
||||
(cd src; lakeprof report -prc)
|
||||
echo "</code></pre>"
|
||||
echo "</body></html>"
|
||||
} | tee index.html
|
||||
|
||||
curl -T index.html $BASE_URL/index.html
|
||||
curl -T src/lakeprof.log $BASE_URL/lakeprof.log
|
||||
curl -T src/lakeprof.trace_event $BASE_URL/lakeprof.trace_event
|
||||
fi
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
name = "scripts"
|
||||
|
||||
[[lean_exe]]
|
||||
name = "modulize"
|
||||
root = "Modulize"
|
||||
|
||||
[[lean_exe]]
|
||||
name = "shake"
|
||||
root = "Shake"
|
||||
@@ -1 +0,0 @@
|
||||
lean4
|
||||
@@ -5,7 +5,6 @@ Merge a tag into a branch on a GitHub repository.
|
||||
|
||||
This script checks if a specified tag can be merged cleanly into a branch and performs
|
||||
the merge if possible. If the merge cannot be done cleanly, it prints a helpful message.
|
||||
Merge conflicts in the lean-toolchain file are automatically resolved by accepting the incoming changes.
|
||||
|
||||
Usage:
|
||||
python3 merge_remote.py <org/repo> <branch> <tag>
|
||||
@@ -59,32 +58,6 @@ def clone_repo(repo, temp_dir):
|
||||
return True
|
||||
|
||||
|
||||
def get_conflicted_files():
|
||||
"""Get list of files with merge conflicts."""
|
||||
result = run_command("git diff --name-only --diff-filter=U", check=False)
|
||||
if result.returncode == 0:
|
||||
return result.stdout.strip().split('\n') if result.stdout.strip() else []
|
||||
return []
|
||||
|
||||
|
||||
def resolve_lean_toolchain_conflict(tag):
|
||||
"""Resolve lean-toolchain conflict by accepting incoming (tag) changes."""
|
||||
print("Resolving lean-toolchain conflict by accepting incoming changes...")
|
||||
# Accept theirs (incoming) version for lean-toolchain
|
||||
result = run_command(f"git checkout --theirs lean-toolchain", check=False)
|
||||
if result.returncode != 0:
|
||||
print("Failed to resolve lean-toolchain conflict")
|
||||
return False
|
||||
|
||||
# Add the resolved file
|
||||
add_result = run_command("git add lean-toolchain", check=False)
|
||||
if add_result.returncode != 0:
|
||||
print("Failed to stage resolved lean-toolchain")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def check_and_merge(repo, branch, tag, temp_dir):
|
||||
"""Check if tag can be merged into branch and perform the merge if possible."""
|
||||
# Change to the temporary directory
|
||||
@@ -125,37 +98,12 @@ def check_and_merge(repo, branch, tag, temp_dir):
|
||||
# Try merging the tag directly
|
||||
print(f"Merging {tag} into {branch}...")
|
||||
merge_result = run_command(f"git merge {tag} --no-edit", check=False)
|
||||
|
||||
|
||||
if merge_result.returncode != 0:
|
||||
# Check which files have conflicts
|
||||
conflicted_files = get_conflicted_files()
|
||||
|
||||
if conflicted_files == ['lean-toolchain']:
|
||||
# Only lean-toolchain has conflicts, resolve it
|
||||
print("Merge conflict detected only in lean-toolchain.")
|
||||
if resolve_lean_toolchain_conflict(tag):
|
||||
# Continue the merge with the resolved conflict
|
||||
print("Continuing merge with resolved lean-toolchain...")
|
||||
continue_result = run_command(f"git commit --no-edit", check=False)
|
||||
if continue_result.returncode != 0:
|
||||
print("Failed to complete merge after resolving lean-toolchain")
|
||||
run_command("git merge --abort")
|
||||
return False
|
||||
else:
|
||||
print("Failed to resolve lean-toolchain conflict")
|
||||
run_command("git merge --abort")
|
||||
return False
|
||||
else:
|
||||
# Other files have conflicts, or unable to determine
|
||||
if conflicted_files:
|
||||
print(f"Cannot merge {tag} cleanly into {branch}.")
|
||||
print(f"Merge conflicts in: {', '.join(conflicted_files)}")
|
||||
else:
|
||||
print(f"Cannot merge {tag} cleanly into {branch}.")
|
||||
print("Merge conflicts would occur.")
|
||||
print("Aborting merge.")
|
||||
run_command("git merge --abort")
|
||||
return False
|
||||
print(f"Cannot merge {tag} cleanly into {branch}.")
|
||||
print("Merge conflicts would occur. Aborting merge.")
|
||||
run_command("git merge --abort")
|
||||
return False
|
||||
|
||||
print(f"Pushing changes to remote...")
|
||||
push_result = run_command(f"git push origin {branch}")
|
||||
|
||||
@@ -52,7 +52,6 @@ def sort_sections_order():
|
||||
return [
|
||||
"Language",
|
||||
"Library",
|
||||
"Tactics",
|
||||
"Compiler",
|
||||
"Pretty Printing",
|
||||
"Documentation",
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
repositories:
|
||||
- name: lean4-cli
|
||||
url: https://github.com/leanprover/lean4-cli
|
||||
toolchain-tag: true
|
||||
stable-branch: false
|
||||
branch: main
|
||||
dependencies: []
|
||||
|
||||
- name: batteries
|
||||
url: https://github.com/leanprover-community/batteries
|
||||
toolchain-tag: true
|
||||
@@ -14,13 +7,6 @@ repositories:
|
||||
bump-branch: true
|
||||
dependencies: []
|
||||
|
||||
- name: verso
|
||||
url: https://github.com/leanprover/verso
|
||||
toolchain-tag: true
|
||||
stable-branch: false
|
||||
branch: main
|
||||
dependencies: []
|
||||
|
||||
- name: lean4checker
|
||||
url: https://github.com/leanprover/lean4checker
|
||||
toolchain-tag: true
|
||||
@@ -35,21 +21,13 @@ repositories:
|
||||
branch: master
|
||||
dependencies: []
|
||||
|
||||
- name: plausible
|
||||
url: https://github.com/leanprover-community/plausible
|
||||
- name: lean4-cli
|
||||
url: https://github.com/leanprover/lean4-cli
|
||||
toolchain-tag: true
|
||||
stable-branch: false
|
||||
branch: main
|
||||
dependencies: []
|
||||
|
||||
- name: import-graph
|
||||
url: https://github.com/leanprover-community/import-graph
|
||||
toolchain-tag: true
|
||||
stable-branch: false
|
||||
branch: main
|
||||
dependencies:
|
||||
- lean4-cli
|
||||
|
||||
- name: doc-gen4
|
||||
url: https://github.com/leanprover/doc-gen4
|
||||
toolchain-tag: true
|
||||
@@ -57,6 +35,13 @@ repositories:
|
||||
branch: main
|
||||
dependencies: [lean4-cli]
|
||||
|
||||
- name: verso
|
||||
url: https://github.com/leanprover/verso
|
||||
toolchain-tag: true
|
||||
stable-branch: false
|
||||
branch: main
|
||||
dependencies: []
|
||||
|
||||
- name: reference-manual
|
||||
url: https://github.com/leanprover/reference-manual
|
||||
toolchain-tag: true
|
||||
@@ -80,6 +65,22 @@ repositories:
|
||||
dependencies:
|
||||
- batteries
|
||||
|
||||
- name: import-graph
|
||||
url: https://github.com/leanprover-community/import-graph
|
||||
toolchain-tag: true
|
||||
stable-branch: false
|
||||
branch: main
|
||||
dependencies:
|
||||
- lean4-cli
|
||||
- batteries
|
||||
|
||||
- name: plausible
|
||||
url: https://github.com/leanprover-community/plausible
|
||||
toolchain-tag: true
|
||||
stable-branch: false
|
||||
branch: main
|
||||
dependencies: []
|
||||
|
||||
- name: mathlib4
|
||||
url: https://github.com/leanprover-community/mathlib4
|
||||
toolchain-tag: true
|
||||
@@ -96,15 +97,6 @@ repositories:
|
||||
- import-graph
|
||||
- plausible
|
||||
|
||||
- name: cslib
|
||||
url: https://github.com/leanprover/cslib
|
||||
toolchain-tag: true
|
||||
stable-branch: true
|
||||
branch: main
|
||||
bump-branch: true
|
||||
dependencies:
|
||||
- mathlib4
|
||||
|
||||
- name: repl
|
||||
url: https://github.com/leanprover-community/repl
|
||||
toolchain-tag: true
|
||||
@@ -112,11 +104,3 @@ repositories:
|
||||
branch: master
|
||||
dependencies:
|
||||
- mathlib4
|
||||
|
||||
- name: lean-fro.org
|
||||
url: https://github.com/leanprover/lean-fro.org
|
||||
toolchain-tag: false
|
||||
stable-branch: false
|
||||
branch: master
|
||||
dependencies:
|
||||
- verso
|
||||
|
||||
@@ -195,7 +195,7 @@ def execute_release_steps(repo, version, config):
|
||||
run_command(f"git checkout {default_branch} && git pull", cwd=repo_path)
|
||||
|
||||
# Special rc1 safety check for batteries and mathlib4 (before creating any branches)
|
||||
if repo_name in ["batteries", "mathlib4"] and version.endswith('-rc1'):
|
||||
if re.search(r'rc\d+$', version) and repo_name in ["batteries", "mathlib4"] and version.endswith('-rc1'):
|
||||
print(blue("This repo has nightly-testing infrastructure"))
|
||||
print(blue(f"Checking if nightly-testing can be safely merged into bump/{version.split('-rc')[0]}..."))
|
||||
|
||||
@@ -377,33 +377,6 @@ def execute_release_steps(repo, version, config):
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(red("Tests failed, but continuing with PR creation..."))
|
||||
print(red(f"Test error: {e}"))
|
||||
elif repo_name == "lean-fro.org":
|
||||
# Update lean-toolchain in examples/hero
|
||||
print(blue("Updating examples/hero/lean-toolchain..."))
|
||||
docs_toolchain = repo_path / "examples" / "hero" / "lean-toolchain"
|
||||
with open(docs_toolchain, "w") as f:
|
||||
f.write(f"leanprover/lean4:{version}\n")
|
||||
print(green(f"Updated examples/hero/lean-toolchain to leanprover/lean4:{version}"))
|
||||
|
||||
print(blue("Running `lake update`..."))
|
||||
run_command("lake update", cwd=repo_path, stream_output=True)
|
||||
print(blue("Running `lake update` in examples/hero..."))
|
||||
run_command("lake update", cwd=repo_path / "examples" / "hero", stream_output=True)
|
||||
elif repo_name == "cslib":
|
||||
print(blue("Updating lakefile.toml..."))
|
||||
run_command(f'perl -pi -e \'s/"v4\\.[0-9]+(\\.[0-9]+)?(-rc[0-9]+)?"/"' + version + '"/g\' lakefile.*', cwd=repo_path)
|
||||
|
||||
print(blue("Updating docs/lakefile.toml..."))
|
||||
run_command(f'perl -pi -e \'s/"v4\\.[0-9]+(\\.[0-9]+)?(-rc[0-9]+)?"/"' + version + '"/g\' lakefile.*', cwd=repo_path / "docs")
|
||||
|
||||
# Update lean-toolchain in docs
|
||||
print(blue("Updating docs/lean-toolchain..."))
|
||||
docs_toolchain = repo_path / "docs" / "lean-toolchain"
|
||||
with open(docs_toolchain, "w") as f:
|
||||
f.write(f"leanprover/lean4:{version}\n")
|
||||
print(green(f"Updated docs/lean-toolchain to leanprover/lean4:{version}"))
|
||||
|
||||
run_command("lake update", cwd=repo_path, stream_output=True)
|
||||
elif dependencies:
|
||||
run_command(f'perl -pi -e \'s/"v4\\.[0-9]+(\\.[0-9]+)?(-rc[0-9]+)?"/"' + version + '"/g\' lakefile.*', cwd=repo_path)
|
||||
run_command("lake update", cwd=repo_path, stream_output=True)
|
||||
@@ -430,7 +403,7 @@ def execute_release_steps(repo, version, config):
|
||||
raise
|
||||
|
||||
# Handle special merging cases
|
||||
if version.endswith('-rc1') and repo_name in ["batteries", "mathlib4"]:
|
||||
if re.search(r'rc\d+$', version) and repo_name in ["batteries", "mathlib4"]:
|
||||
print(blue("This repo uses `bump/v4.X.0` branches for reviewed content from nightly-testing."))
|
||||
|
||||
# Determine which remote to use for bump branches
|
||||
@@ -501,7 +474,7 @@ def execute_release_steps(repo, version, config):
|
||||
|
||||
print(green("✅ Merge completed successfully with automatic conflict resolution"))
|
||||
|
||||
elif version.endswith('-rc1'):
|
||||
elif re.search(r'rc\d+$', version):
|
||||
# For all other repos with rc versions, merge nightly-testing
|
||||
if repo_name in ["verso", "reference-manual"]:
|
||||
print(yellow("This repo does development on nightly-testing: remember to rebase merge the PR."))
|
||||
|
||||
@@ -10,7 +10,7 @@ endif()
|
||||
include(ExternalProject)
|
||||
project(LEAN CXX C)
|
||||
set(LEAN_VERSION_MAJOR 4)
|
||||
set(LEAN_VERSION_MINOR 25)
|
||||
set(LEAN_VERSION_MINOR 23)
|
||||
set(LEAN_VERSION_PATCH 0)
|
||||
set(LEAN_VERSION_IS_RELEASE 0) # This number is 1 in the release revision, and 0 otherwise.
|
||||
set(LEAN_SPECIAL_VERSION_DESC "" CACHE STRING "Additional version description like 'nightly-2018-03-11'")
|
||||
@@ -34,14 +34,7 @@ if (NOT LEAN_PLATFORM_TARGET)
|
||||
OUTPUT_VARIABLE LEAN_PLATFORM_TARGET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
endif()
|
||||
|
||||
set(LEAN_EXTRA_LINKER_FLAGS_DEFAULT "")
|
||||
# Use lld by default, if available
|
||||
find_program(LLD_PATH lld)
|
||||
if(LLD_PATH)
|
||||
string(APPEND LEAN_EXTRA_LINKER_FLAGS_DEFAULT " -fuse-ld=lld")
|
||||
endif()
|
||||
|
||||
set(LEAN_EXTRA_LINKER_FLAGS ${LEAN_EXTRA_LINKER_FLAGS_DEFAULT} CACHE STRING "Additional flags used by the linker")
|
||||
set(LEAN_EXTRA_LINKER_FLAGS "" CACHE STRING "Additional flags used by the linker")
|
||||
set(LEAN_EXTRA_CXX_FLAGS "" CACHE STRING "Additional flags used by the C++ compiler")
|
||||
set(LEAN_TEST_VARS "LEAN_CC=${CMAKE_C_COMPILER}" CACHE STRING "Additional environment variables used when running tests")
|
||||
|
||||
@@ -88,8 +81,7 @@ option(USE_MIMALLOC "use mimalloc" ON)
|
||||
|
||||
# development-specific options
|
||||
option(CHECK_OLEAN_VERSION "Only load .olean files compiled with the current version of Lean" OFF)
|
||||
option(USE_LAKE "Use Lake instead of lean.mk for building core libs from language server" ON)
|
||||
option(USE_LAKE_CACHE "Use the Lake artifact cache for stage 1 builds (requires USE_LAKE)" OFF)
|
||||
option(USE_LAKE "Use Lake instead of lean.mk for building core libs from language server" OFF)
|
||||
|
||||
set(LEAN_EXTRA_MAKE_OPTS "" CACHE STRING "extra options to lean --make")
|
||||
set(LEANC_CC ${CMAKE_C_COMPILER} CACHE STRING "C compiler to use in `leanc`")
|
||||
@@ -477,7 +469,6 @@ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
string(APPEND CMAKE_CXX_FLAGS " -ftls-model=initial-exec")
|
||||
string(APPEND INIT_SHARED_LINKER_FLAGS " -install_name @rpath/libInit_shared.dylib")
|
||||
string(APPEND LEANSHARED_1_LINKER_FLAGS " -install_name @rpath/libleanshared_1.dylib")
|
||||
string(APPEND LEANSHARED_2_LINKER_FLAGS " -install_name @rpath/libleanshared_2.dylib")
|
||||
string(APPEND LEANSHARED_LINKER_FLAGS " -install_name @rpath/libleanshared.dylib")
|
||||
string(APPEND LAKESHARED_LINKER_FLAGS " -Wl,-force_load,${CMAKE_BINARY_DIR}/lib/lean/libLake.a.export -install_name @rpath/libLake_shared.dylib")
|
||||
string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,-rpath,@executable_path/../lib -Wl,-rpath,@executable_path/../lib/lean")
|
||||
@@ -511,7 +502,7 @@ endif()
|
||||
# are already loaded) and probably fail unless we set up LD_LIBRARY_PATH.
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
# import libraries created by the stdlib.make targets
|
||||
string(APPEND LEANC_SHARED_LINKER_FLAGS " -lInit_shared -lleanshared_2 -lleanshared_1 -lleanshared")
|
||||
string(APPEND LEANC_SHARED_LINKER_FLAGS " -lInit_shared -lleanshared_1 -lleanshared")
|
||||
elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
|
||||
# The second flag is necessary to even *load* dylibs without resolved symbols, as can happen
|
||||
# if a Lake `extern_lib` depends on a symbols defined by the Lean library but is loaded even
|
||||
@@ -542,21 +533,12 @@ else()
|
||||
OUTPUT_VARIABLE GIT_SHA1
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
message(STATUS "stage0 sha1: ${GIT_SHA1}")
|
||||
# Now that we've prepared the information for the next stage, we can forget that we will use
|
||||
# Lake in the future as we won't use it in this stage
|
||||
set(USE_LAKE OFF)
|
||||
else()
|
||||
set(GIT_SHA1 "")
|
||||
endif()
|
||||
endif()
|
||||
configure_file("${LEAN_SOURCE_DIR}/githash.h.in" "${LEAN_BINARY_DIR}/githash.h")
|
||||
|
||||
if(USE_LAKE AND ${STAGE} EQUAL 0)
|
||||
# Now that we've prepared the information for the next stage, we can forget that we will use
|
||||
# Lake in the future as we won't use it in this stage
|
||||
set(USE_LAKE OFF)
|
||||
endif()
|
||||
|
||||
# Windows uses ";" as a path separator. We use `LEAN_PATH_SEPARATOR` on scripts such as lean.mk.in
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
set(LEAN_PATH_SEPARATOR ";")
|
||||
@@ -598,7 +580,7 @@ endif()
|
||||
|
||||
add_subdirectory(initialize)
|
||||
add_subdirectory(shell)
|
||||
# to be included in `leanshared` but not the smaller `leanshared_*` (as it would pull
|
||||
# to be included in `leanshared` but not the smaller `leanshared_1` (as it would pull
|
||||
# in the world)
|
||||
add_library(leaninitialize STATIC $<TARGET_OBJECTS:initialize>)
|
||||
set_target_properties(leaninitialize PROPERTIES
|
||||
@@ -652,6 +634,8 @@ else()
|
||||
set(LEAN_OBJS ${LEAN_OBJS} $<TARGET_OBJECTS:library>)
|
||||
add_subdirectory(library/constructions)
|
||||
set(LEAN_OBJS ${LEAN_OBJS} $<TARGET_OBJECTS:constructions>)
|
||||
add_subdirectory(library/compiler)
|
||||
set(LEAN_OBJS ${LEAN_OBJS} $<TARGET_OBJECTS:compiler>)
|
||||
|
||||
# leancpp without `initialize` (see `leaninitialize` above)
|
||||
add_library(leancpp_1 STATIC ${LEAN_OBJS})
|
||||
@@ -693,17 +677,12 @@ if (LLVM AND ${STAGE} GREATER 0)
|
||||
set(EXTRA_LEANMAKE_OPTS "LLVM=1")
|
||||
endif()
|
||||
|
||||
set(STDLIBS Init Std Lean Leanc)
|
||||
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
|
||||
list(APPEND STDLIBS Lake)
|
||||
endif()
|
||||
|
||||
add_custom_target(make_stdlib ALL
|
||||
WORKING_DIRECTORY ${LEAN_SOURCE_DIR}
|
||||
# The actual rule is in a separate makefile because we want to prefix it with '+' to use the Make job server
|
||||
# for a parallelized nested build, but CMake doesn't let us do that.
|
||||
# We use `lean` from the previous stage, but `leanc`, headers, etc. from the current stage
|
||||
COMMAND $(MAKE) -f ${CMAKE_BINARY_DIR}/stdlib.make ${STDLIBS}
|
||||
COMMAND $(MAKE) -f ${CMAKE_BINARY_DIR}/stdlib.make Init Std Lean Leanc
|
||||
VERBATIM)
|
||||
|
||||
# if we have LLVM enabled, then build `lean.h.bc` which has the LLVM bitcode
|
||||
@@ -723,7 +702,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
|
||||
)
|
||||
add_custom_target(leanshared ALL
|
||||
DEPENDS Init_shared leancpp
|
||||
COMMAND touch ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libleanshared_2${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
COMMAND touch ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libleanshared_1${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
COMMAND touch ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libleanshared${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
)
|
||||
@@ -744,13 +722,18 @@ else()
|
||||
COMMAND $(MAKE) -f ${CMAKE_BINARY_DIR}/stdlib.make leanshared
|
||||
VERBATIM)
|
||||
|
||||
string(APPEND CMAKE_EXE_LINKER_FLAGS " -lInit_shared -lleanshared_2 -lleanshared_1 -lleanshared")
|
||||
string(APPEND CMAKE_EXE_LINKER_FLAGS " -lInit_shared -lleanshared_1 -lleanshared")
|
||||
endif()
|
||||
|
||||
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
|
||||
add_custom_target(lake_shared
|
||||
add_custom_target(lake_lib
|
||||
WORKING_DIRECTORY ${LEAN_SOURCE_DIR}
|
||||
DEPENDS leanshared
|
||||
COMMAND $(MAKE) -f ${CMAKE_BINARY_DIR}/stdlib.make Lake
|
||||
VERBATIM)
|
||||
add_custom_target(lake_shared
|
||||
WORKING_DIRECTORY ${LEAN_SOURCE_DIR}
|
||||
DEPENDS lake_lib
|
||||
COMMAND $(MAKE) -f ${CMAKE_BINARY_DIR}/stdlib.make libLake_shared
|
||||
VERBATIM)
|
||||
add_custom_target(lake ALL
|
||||
@@ -805,9 +788,6 @@ install(DIRECTORY "${CMAKE_BINARY_DIR}/lib/" DESTINATION lib
|
||||
|
||||
# symlink source into expected installation location for go-to-definition, if file system allows it
|
||||
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/src)
|
||||
# get rid of all files in `src/lean` that may have been loaded from the cache
|
||||
# (at the time of writing this, this is the case for some lake test .c files)
|
||||
file(REMOVE_RECURSE ${CMAKE_BINARY_DIR}/src/lean)
|
||||
if(${STAGE} EQUAL 0)
|
||||
file(CREATE_LINK ${CMAKE_SOURCE_DIR}/../../src ${CMAKE_BINARY_DIR}/src/lean RESULT _IGNORE_RES SYMBOLIC)
|
||||
else()
|
||||
@@ -834,15 +814,6 @@ if(LEAN_INSTALL_PREFIX)
|
||||
set(CMAKE_INSTALL_PREFIX "${LEAN_INSTALL_PREFIX}/lean-${LEAN_VERSION_STRING}${LEAN_INSTALL_SUFFIX}")
|
||||
endif()
|
||||
|
||||
|
||||
if (USE_LAKE_CACHE AND STAGE EQUAL 1)
|
||||
set(LAKE_ARTIFACT_CACHE_TOML "true")
|
||||
else()
|
||||
# The build of stage2+ may depend on local changes made to src/ that are not reflected by the
|
||||
# commit hash in stage1/bin/lean, so we make sure to disable the global cache
|
||||
set(LAKE_ARTIFACT_CACHE_TOML "false")
|
||||
endif()
|
||||
|
||||
# Escape for `make`. Yes, twice.
|
||||
string(REPLACE "$" "\\\$$" CMAKE_EXE_LINKER_FLAGS_MAKE "${CMAKE_EXE_LINKER_FLAGS}")
|
||||
configure_file(${LEAN_SOURCE_DIR}/stdlib.make.in ${CMAKE_BINARY_DIR}/stdlib.make)
|
||||
@@ -858,19 +829,17 @@ endfunction()
|
||||
string(REPLACE "ROOT" "${CMAKE_BINARY_DIR}" LEANC_CC "${LEANC_CC}")
|
||||
string(REPLACE "ROOT" "${CMAKE_BINARY_DIR}" LEANC_INTERNAL_FLAGS "${LEANC_INTERNAL_FLAGS}")
|
||||
string(REPLACE "ROOT" "${CMAKE_BINARY_DIR}" LEANC_INTERNAL_LINKER_FLAGS "${LEANC_INTERNAL_LINKER_FLAGS}")
|
||||
set(LEANC_OPTS_TOML "${LEANC_OPTS} ${LEANC_EXTRA_CC_FLAGS} ${LEANC_INTERNAL_FLAGS}")
|
||||
set(LINK_OPTS_TOML "${LEANC_INTERNAL_LINKER_FLAGS} -L${CMAKE_BINARY_DIR}/lib/lean ${LEAN_EXTRA_LINKER_FLAGS}")
|
||||
|
||||
toml_escape("${LEAN_EXTRA_MAKE_OPTS}" LEAN_EXTRA_OPTS_TOML)
|
||||
toml_escape("${LEANC_OPTS_TOML}" LEANC_OPTS_TOML)
|
||||
toml_escape("${LINK_OPTS_TOML}" LINK_OPTS_TOML)
|
||||
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES "Debug|Release|RelWithDebInfo|MinSizeRel")
|
||||
set(CMAKE_BUILD_TYPE_TOML "${CMAKE_BUILD_TYPE}")
|
||||
else()
|
||||
set(CMAKE_BUILD_TYPE_TOML "Release")
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
set(LAKE_LIB_PREFIX "lib")
|
||||
endif()
|
||||
|
||||
if(USE_LAKE)
|
||||
configure_file(${LEAN_SOURCE_DIR}/lakefile.toml.in ${CMAKE_BINARY_DIR}/lakefile.toml)
|
||||
# copy for editing
|
||||
if(STAGE EQUAL 1)
|
||||
configure_file(${LEAN_SOURCE_DIR}/lakefile.toml.in ${LEAN_SOURCE_DIR}/lakefile.toml)
|
||||
endif()
|
||||
if(USE_LAKE AND STAGE EQUAL 1)
|
||||
configure_file(${LEAN_SOURCE_DIR}/lakefile.toml.in ${LEAN_SOURCE_DIR}/lakefile.toml)
|
||||
endif()
|
||||
|
||||
@@ -42,8 +42,5 @@ public import Init.While
|
||||
public import Init.Syntax
|
||||
public import Init.Internal
|
||||
public import Init.Try
|
||||
public meta import Init.Try -- make sure `Try.Config` can be evaluated anywhere
|
||||
public import Init.BinderNameHint
|
||||
public import Init.Task
|
||||
public import Init.MethodSpecsSimp
|
||||
public import Init.LawfulBEqTactics
|
||||
|
||||
@@ -39,7 +39,7 @@ This gadget is supported by
|
||||
* `simp`, `dsimp` and `rw` in the right-hand-side of an equation
|
||||
* `simp` in the assumptions of congruence rules
|
||||
|
||||
It is ineffective in other positions (hypotheses of rewrite rules) or when used by other tactics
|
||||
It is ineffective in other positions (hyptheses of rewrite rules) or when used by other tactics
|
||||
(e.g. `apply`).
|
||||
-/
|
||||
@[simp ↓, expose]
|
||||
|
||||
@@ -8,7 +8,7 @@ module
|
||||
prelude
|
||||
public import Init.PropLemmas
|
||||
|
||||
@[expose] public section
|
||||
public section
|
||||
|
||||
universe u v
|
||||
|
||||
|
||||
@@ -16,3 +16,5 @@ public import Init.Control.Option
|
||||
public import Init.Control.Lawful
|
||||
public import Init.Control.StateCps
|
||||
public import Init.Control.ExceptCps
|
||||
|
||||
public section
|
||||
|
||||
@@ -9,7 +9,7 @@ prelude
|
||||
public import Init.Core
|
||||
public import Init.BinderNameHint
|
||||
|
||||
@[expose] public section
|
||||
public section
|
||||
|
||||
universe u v w
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ variable {ε σ α : Type u}
|
||||
|
||||
instance [ToString ε] [ToString α] : ToString (Result ε σ α) where
|
||||
toString
|
||||
| Result.ok a _ => String.Internal.append "ok: " (toString a)
|
||||
| Result.error e _ => String.Internal.append "error: " (toString e)
|
||||
| Result.ok a _ => "ok: " ++ toString a
|
||||
| Result.error e _ => "error: " ++ toString e
|
||||
|
||||
instance [Repr ε] [Repr α] : Repr (Result ε σ α) where
|
||||
reprPrec
|
||||
|
||||
@@ -12,7 +12,7 @@ public import Init.Control.Basic
|
||||
public import Init.Control.Id
|
||||
public import Init.Coe
|
||||
|
||||
@[expose] public section
|
||||
public section
|
||||
|
||||
namespace Except
|
||||
variable {ε : Type u}
|
||||
|
||||
@@ -10,3 +10,5 @@ public import Init.Control.Lawful.Basic
|
||||
public import Init.Control.Lawful.Instances
|
||||
public import Init.Control.Lawful.Lemmas
|
||||
public import Init.Control.Lawful.MonadLift
|
||||
|
||||
public section
|
||||
|
||||
@@ -147,7 +147,7 @@ class LawfulMonad (m : Type u → Type v) [Monad m] : Prop extends LawfulApplica
|
||||
|
||||
export LawfulMonad (bind_pure_comp bind_map pure_bind bind_assoc)
|
||||
attribute [simp] pure_bind bind_assoc bind_pure_comp
|
||||
attribute [grind <=] pure_bind
|
||||
attribute [grind] pure_bind
|
||||
|
||||
@[simp] theorem bind_pure [Monad m] [LawfulMonad m] (x : m α) : x >>= pure = x := by
|
||||
change x >>= (fun a => pure (id a)) = x
|
||||
|
||||
@@ -7,12 +7,8 @@ module
|
||||
|
||||
prelude
|
||||
public import Init.Control.Lawful.Basic
|
||||
public import Init.Control.Except
|
||||
import all Init.Control.Except
|
||||
public import Init.Control.Option
|
||||
import all Init.Control.Option
|
||||
public import Init.Control.State
|
||||
import all Init.Control.State
|
||||
public import all Init.Control.Except
|
||||
public import all Init.Control.State
|
||||
public import Init.Control.StateRef
|
||||
public import Init.Ext
|
||||
|
||||
@@ -24,24 +20,23 @@ open Function
|
||||
|
||||
namespace ExceptT
|
||||
|
||||
@[ext, grind ext] theorem ext {x y : ExceptT ε m α} (h : x.run = y.run) : x = y := by
|
||||
@[ext] theorem ext {x y : ExceptT ε m α} (h : x.run = y.run) : x = y := by
|
||||
simp [run] at h
|
||||
assumption
|
||||
|
||||
@[simp, grind =] theorem run_pure [Monad m] (x : α) : run (pure x : ExceptT ε m α) = pure (Except.ok x) := rfl
|
||||
@[simp] theorem run_pure [Monad m] (x : α) : run (pure x : ExceptT ε m α) = pure (Except.ok x) := rfl
|
||||
|
||||
@[simp, grind =] theorem run_lift [Monad.{u, v} m] (x : m α) : run (ExceptT.lift x : ExceptT ε m α) = (Except.ok <$> x : m (Except ε α)) := rfl
|
||||
@[simp] theorem run_lift [Monad.{u, v} m] (x : m α) : run (ExceptT.lift x : ExceptT ε m α) = (Except.ok <$> x : m (Except ε α)) := rfl
|
||||
|
||||
@[simp, grind =] theorem run_throw [Monad m] : run (throw e : ExceptT ε m β) = pure (Except.error e) := rfl
|
||||
@[simp] theorem run_throw [Monad m] : run (throw e : ExceptT ε m β) = pure (Except.error e) := rfl
|
||||
|
||||
@[simp, grind =] theorem run_bind_lift [Monad m] [LawfulMonad m] (x : m α) (f : α → ExceptT ε m β) : run (ExceptT.lift x >>= f : ExceptT ε m β) = x >>= fun a => run (f a) := by
|
||||
@[simp] theorem run_bind_lift [Monad m] [LawfulMonad m] (x : m α) (f : α → ExceptT ε m β) : run (ExceptT.lift x >>= f : ExceptT ε m β) = x >>= fun a => run (f a) := by
|
||||
simp [ExceptT.run, ExceptT.lift, bind, ExceptT.bind, ExceptT.mk, ExceptT.bindCont]
|
||||
|
||||
@[simp, grind =] theorem bind_throw [Monad m] [LawfulMonad m] (f : α → ExceptT ε m β) : (throw e >>= f) = throw e := by
|
||||
@[simp] theorem bind_throw [Monad m] [LawfulMonad m] (f : α → ExceptT ε m β) : (throw e >>= f) = throw e := by
|
||||
simp [throw, throwThe, MonadExceptOf.throw, bind, ExceptT.bind, ExceptT.bindCont, ExceptT.mk]
|
||||
|
||||
@[grind =]
|
||||
theorem run_bind [Monad m] (x : ExceptT ε m α) (f : α → ExceptT ε m β)
|
||||
theorem run_bind [Monad m] (x : ExceptT ε m α)
|
||||
: run (x >>= f : ExceptT ε m β)
|
||||
=
|
||||
run x >>= fun
|
||||
@@ -49,10 +44,10 @@ theorem run_bind [Monad m] (x : ExceptT ε m α) (f : α → ExceptT ε m β)
|
||||
| Except.error e => pure (Except.error e) :=
|
||||
rfl
|
||||
|
||||
@[simp, grind =] theorem lift_pure [Monad m] [LawfulMonad m] (a : α) : ExceptT.lift (pure a) = (pure a : ExceptT ε m α) := by
|
||||
@[simp] theorem lift_pure [Monad m] [LawfulMonad m] (a : α) : ExceptT.lift (pure a) = (pure a : ExceptT ε m α) := by
|
||||
simp [ExceptT.lift, pure, ExceptT.pure]
|
||||
|
||||
@[simp, grind =] theorem run_map [Monad m] [LawfulMonad m] (f : α → β) (x : ExceptT ε m α)
|
||||
@[simp] theorem run_map [Monad m] [LawfulMonad m] (f : α → β) (x : ExceptT ε m α)
|
||||
: (f <$> x).run = Except.map f <$> x.run := by
|
||||
simp [Functor.map, ExceptT.map, ←bind_pure_comp]
|
||||
apply bind_congr
|
||||
@@ -112,147 +107,32 @@ instance : LawfulMonad (Except ε) := LawfulMonad.mk'
|
||||
instance : LawfulApplicative (Except ε) := inferInstance
|
||||
instance : LawfulFunctor (Except ε) := inferInstance
|
||||
|
||||
/-! # OptionT -/
|
||||
|
||||
namespace OptionT
|
||||
|
||||
@[ext] theorem ext {x y : OptionT m α} (h : x.run = y.run) : x = y := by
|
||||
simp [run] at h
|
||||
assumption
|
||||
|
||||
@[simp, grind =] theorem run_mk {m : Type u → Type v} (x : m (Option α)) :
|
||||
OptionT.run (OptionT.mk x) = x := by rfl
|
||||
|
||||
@[simp, grind =] theorem run_pure [Monad m] (x : α) : run (pure x : OptionT m α) = pure (some x) := by
|
||||
simp [run, pure, OptionT.pure, OptionT.mk]
|
||||
|
||||
@[simp, grind =] theorem run_lift [Monad.{u, v} m] (x : m α) : run (OptionT.lift x : OptionT m α) = (return some (← x) : m (Option α)) := by
|
||||
simp [run, OptionT.lift, OptionT.mk]
|
||||
|
||||
@[simp, grind =] theorem run_throw [Monad m] : run (throw e : OptionT m β) = pure none := by
|
||||
simp [run, throw, throwThe, MonadExceptOf.throw, OptionT.fail, OptionT.mk]
|
||||
|
||||
@[simp, grind =] theorem run_bind_lift [Monad m] [LawfulMonad m] (x : m α) (f : α → OptionT m β) : run (OptionT.lift x >>= f : OptionT m β) = x >>= fun a => run (f a) := by
|
||||
simp [OptionT.run, OptionT.lift, bind, OptionT.bind, OptionT.mk]
|
||||
|
||||
@[simp, grind =] theorem bind_throw [Monad m] [LawfulMonad m] (f : α → OptionT m β) : (throw e >>= f) = throw e := by
|
||||
simp [throw, throwThe, MonadExceptOf.throw, bind, OptionT.bind, OptionT.mk, OptionT.fail]
|
||||
|
||||
@[simp, grind =] theorem run_bind (f : α → OptionT m β) [Monad m] :
|
||||
(x >>= f).run = Option.elimM x.run (pure none) (fun x => (f x).run) := by
|
||||
change x.run >>= _ = _
|
||||
simp [Option.elimM]
|
||||
exact bind_congr fun |some _ => rfl | none => rfl
|
||||
|
||||
@[simp, grind =] theorem lift_pure [Monad m] [LawfulMonad m] {α : Type u} (a : α) : OptionT.lift (pure a : m α) = pure a := by
|
||||
simp only [OptionT.lift, OptionT.mk, bind_pure_comp, map_pure, pure, OptionT.pure]
|
||||
|
||||
@[simp, grind =] theorem run_map [Monad m] [LawfulMonad m] (f : α → β) (x : OptionT m α)
|
||||
: (f <$> x).run = Option.map f <$> x.run := by
|
||||
simp [Functor.map, Option.map, ←bind_pure_comp]
|
||||
apply bind_congr
|
||||
intro a; cases a <;> simp [OptionT.pure, OptionT.mk]
|
||||
|
||||
protected theorem seq_eq {α β : Type u} [Monad m] (mf : OptionT m (α → β)) (x : OptionT m α) : mf <*> x = mf >>= fun f => f <$> x :=
|
||||
rfl
|
||||
|
||||
protected theorem bind_pure_comp [Monad m] (f : α → β) (x : OptionT m α) : x >>= pure ∘ f = f <$> x := by
|
||||
intros; rfl
|
||||
|
||||
protected theorem seqLeft_eq {α β : Type u} {m : Type u → Type v} [Monad m] [LawfulMonad m] (x : OptionT m α) (y : OptionT m β) : x <* y = const β <$> x <*> y := by
|
||||
change (x >>= fun a => y >>= fun _ => pure a) = (const (α := α) β <$> x) >>= fun f => f <$> y
|
||||
rw [← OptionT.bind_pure_comp]
|
||||
apply ext
|
||||
simp [Option.elimM, Option.elim]
|
||||
apply bind_congr
|
||||
intro
|
||||
| none => simp
|
||||
| some _ =>
|
||||
simp [←bind_pure_comp]; apply bind_congr; intro b;
|
||||
cases b <;> simp [const]
|
||||
|
||||
protected theorem seqRight_eq [Monad m] [LawfulMonad m] (x : OptionT m α) (y : OptionT m β) : x *> y = const α id <$> x <*> y := by
|
||||
change (x >>= fun _ => y) = (const α id <$> x) >>= fun f => f <$> y
|
||||
rw [← OptionT.bind_pure_comp]
|
||||
apply ext
|
||||
simp [Option.elimM, Option.elim]
|
||||
apply bind_congr
|
||||
intro a; cases a <;> simp
|
||||
|
||||
instance [Monad m] [LawfulMonad m] : LawfulMonad (OptionT m) where
|
||||
id_map := by intros; apply ext; simp
|
||||
map_const := by intros; rfl
|
||||
seqLeft_eq := OptionT.seqLeft_eq
|
||||
seqRight_eq := OptionT.seqRight_eq
|
||||
pure_seq := by intros; apply ext; simp [OptionT.seq_eq, Option.elimM, Option.elim]
|
||||
bind_pure_comp := OptionT.bind_pure_comp
|
||||
bind_map := by intros; rfl
|
||||
pure_bind := by intros; apply ext; simp [Option.elimM, Option.elim]
|
||||
bind_assoc := by intros; apply ext; simp [Option.elimM, Option.elim]; apply bind_congr; intro a; cases a <;> simp
|
||||
|
||||
@[simp] theorem run_seq [Monad m] [LawfulMonad m] (f : OptionT m (α → β)) (x : OptionT m α) :
|
||||
(f <*> x).run = Option.elimM f.run (pure none) (fun f => Option.map f <$> x.run) := by
|
||||
simp [seq_eq_bind, Option.elimM, Option.elim]
|
||||
|
||||
@[simp] theorem run_seqLeft [Monad m] [LawfulMonad m] (x : OptionT m α) (y : OptionT m β) :
|
||||
(x <* y).run = Option.elimM x.run (pure none)
|
||||
(fun x => Option.map (Function.const β x) <$> y.run) := by
|
||||
simp [seqLeft_eq, seq_eq_bind, Option.elimM, OptionT.run_bind]
|
||||
|
||||
@[simp] theorem run_seqRight [Monad m] [LawfulMonad m] (x : OptionT m α) (y : OptionT m β) :
|
||||
(x *> y).run = Option.elimM x.run (pure none) (Function.const α y.run) := by
|
||||
simp only [seqRight_eq, run_seq, Option.elimM, run_map, Option.elim, bind_map_left]
|
||||
refine bind_congr (fun | some _ => by simp | none => by simp)
|
||||
|
||||
@[simp, grind =] theorem run_failure [Monad m] : (failure : OptionT m α).run = pure none := by rfl
|
||||
|
||||
@[simp] theorem map_failure [Monad m] [LawfulMonad m] {α β : Type _} (f : α → β) :
|
||||
f <$> (failure : OptionT m α) = (failure : OptionT m β) := by
|
||||
simp [OptionT.mk, Functor.map, Alternative.failure, OptionT.fail, OptionT.bind]
|
||||
|
||||
@[simp] theorem run_orElse [Monad m] (x : OptionT m α) (y : OptionT m α) :
|
||||
(x <|> y).run = Option.elimM x.run y.run (fun x => pure (some x)) :=
|
||||
bind_congr fun | some _ => by rfl | none => by rfl
|
||||
|
||||
end OptionT
|
||||
|
||||
/-! # Option -/
|
||||
|
||||
instance : LawfulMonad Option := LawfulMonad.mk'
|
||||
(id_map := fun x => by cases x <;> rfl)
|
||||
(pure_bind := fun _ _ => by rfl)
|
||||
(bind_assoc := fun a _ _ => by cases a <;> rfl)
|
||||
(bind_pure_comp := bind_pure_comp)
|
||||
|
||||
instance : LawfulApplicative Option := inferInstance
|
||||
instance : LawfulFunctor Option := inferInstance
|
||||
|
||||
/-! # ReaderT -/
|
||||
|
||||
namespace ReaderT
|
||||
|
||||
@[ext, grind ext] theorem ext {x y : ReaderT ρ m α} (h : ∀ ctx, x.run ctx = y.run ctx) : x = y := by
|
||||
@[ext] theorem ext {x y : ReaderT ρ m α} (h : ∀ ctx, x.run ctx = y.run ctx) : x = y := by
|
||||
simp [run] at h
|
||||
exact funext h
|
||||
|
||||
@[simp, grind =] theorem run_pure [Monad m] (a : α) (ctx : ρ) : (pure a : ReaderT ρ m α).run ctx = pure a := rfl
|
||||
@[simp] theorem run_pure [Monad m] (a : α) (ctx : ρ) : (pure a : ReaderT ρ m α).run ctx = pure a := rfl
|
||||
|
||||
@[simp, grind =] theorem run_bind [Monad m] (x : ReaderT ρ m α) (f : α → ReaderT ρ m β) (ctx : ρ)
|
||||
@[simp] theorem run_bind [Monad m] (x : ReaderT ρ m α) (f : α → ReaderT ρ m β) (ctx : ρ)
|
||||
: (x >>= f).run ctx = x.run ctx >>= λ a => (f a).run ctx := rfl
|
||||
|
||||
@[simp, grind =] theorem run_mapConst [Monad m] (a : α) (x : ReaderT ρ m β) (ctx : ρ)
|
||||
@[simp] theorem run_mapConst [Monad m] (a : α) (x : ReaderT ρ m β) (ctx : ρ)
|
||||
: (Functor.mapConst a x).run ctx = Functor.mapConst a (x.run ctx) := rfl
|
||||
|
||||
@[simp, grind =] theorem run_map [Monad m] (f : α → β) (x : ReaderT ρ m α) (ctx : ρ)
|
||||
@[simp] theorem run_map [Monad m] (f : α → β) (x : ReaderT ρ m α) (ctx : ρ)
|
||||
: (f <$> x).run ctx = f <$> x.run ctx := rfl
|
||||
|
||||
@[simp, grind =] theorem run_monadLift [MonadLiftT n m] (x : n α) (ctx : ρ)
|
||||
@[simp] theorem run_monadLift [MonadLiftT n m] (x : n α) (ctx : ρ)
|
||||
: (monadLift x : ReaderT ρ m α).run ctx = (monadLift x : m α) := rfl
|
||||
|
||||
@[simp, grind =] theorem run_monadMap [MonadFunctorT n m] (f : {β : Type u} → n β → n β) (x : ReaderT ρ m α) (ctx : ρ)
|
||||
@[simp] theorem run_monadMap [MonadFunctorT n m] (f : {β : Type u} → n β → n β) (x : ReaderT ρ m α) (ctx : ρ)
|
||||
: (monadMap @f x : ReaderT ρ m α).run ctx = monadMap @f (x.run ctx) := rfl
|
||||
|
||||
@[simp, grind =] theorem run_read [Monad m] (ctx : ρ) : (ReaderT.read : ReaderT ρ m ρ).run ctx = pure ctx := rfl
|
||||
@[simp] theorem run_read [Monad m] (ctx : ρ) : (ReaderT.read : ReaderT ρ m ρ).run ctx = pure ctx := rfl
|
||||
|
||||
@[simp] theorem run_seq {α β : Type u} [Monad m] (f : ReaderT ρ m (α → β)) (x : ReaderT ρ m α) (ctx : ρ)
|
||||
: (f <*> x).run ctx = (f.run ctx <*> x.run ctx) := rfl
|
||||
@@ -293,39 +173,38 @@ instance [Monad m] [LawfulMonad m] : LawfulMonad (StateRefT' ω σ m) :=
|
||||
|
||||
namespace StateT
|
||||
|
||||
@[ext, grind ext] theorem ext {x y : StateT σ m α} (h : ∀ s, x.run s = y.run s) : x = y :=
|
||||
@[ext] theorem ext {x y : StateT σ m α} (h : ∀ s, x.run s = y.run s) : x = y :=
|
||||
funext h
|
||||
|
||||
@[simp, grind =] theorem run'_eq [Monad m] (x : StateT σ m α) (s : σ) : run' x s = (·.1) <$> run x s :=
|
||||
@[simp] theorem run'_eq [Monad m] (x : StateT σ m α) (s : σ) : run' x s = (·.1) <$> run x s :=
|
||||
rfl
|
||||
|
||||
@[simp, grind =] theorem run_pure [Monad m] (a : α) (s : σ) : (pure a : StateT σ m α).run s = pure (a, s) := rfl
|
||||
@[simp] theorem run_pure [Monad m] (a : α) (s : σ) : (pure a : StateT σ m α).run s = pure (a, s) := rfl
|
||||
|
||||
@[simp, grind =] theorem run_bind [Monad m] (x : StateT σ m α) (f : α → StateT σ m β) (s : σ)
|
||||
@[simp] theorem run_bind [Monad m] (x : StateT σ m α) (f : α → StateT σ m β) (s : σ)
|
||||
: (x >>= f).run s = x.run s >>= λ p => (f p.1).run p.2 := by
|
||||
simp [bind, StateT.bind, run]
|
||||
|
||||
@[simp, grind =] theorem run_map {α β σ : Type u} [Monad m] [LawfulMonad m] (f : α → β) (x : StateT σ m α) (s : σ) : (f <$> x).run s = (fun (p : α × σ) => (f p.1, p.2)) <$> x.run s := by
|
||||
@[simp] theorem run_map {α β σ : Type u} [Monad m] [LawfulMonad m] (f : α → β) (x : StateT σ m α) (s : σ) : (f <$> x).run s = (fun (p : α × σ) => (f p.1, p.2)) <$> x.run s := by
|
||||
simp [Functor.map, StateT.map, run, ←bind_pure_comp]
|
||||
|
||||
@[simp, grind =] theorem run_get [Monad m] (s : σ) : (get : StateT σ m σ).run s = pure (s, s) := rfl
|
||||
@[simp] theorem run_get [Monad m] (s : σ) : (get : StateT σ m σ).run s = pure (s, s) := rfl
|
||||
|
||||
@[simp, grind =] theorem run_set [Monad m] (s s' : σ) : (set s' : StateT σ m PUnit).run s = pure (⟨⟩, s') := rfl
|
||||
@[simp] theorem run_set [Monad m] (s s' : σ) : (set s' : StateT σ m PUnit).run s = pure (⟨⟩, s') := rfl
|
||||
|
||||
@[simp, grind =] theorem run_modify [Monad m] (f : σ → σ) (s : σ) : (modify f : StateT σ m PUnit).run s = pure (⟨⟩, f s) := rfl
|
||||
@[simp] theorem run_modify [Monad m] (f : σ → σ) (s : σ) : (modify f : StateT σ m PUnit).run s = pure (⟨⟩, f s) := rfl
|
||||
|
||||
@[simp, grind =] theorem run_modifyGet [Monad m] (f : σ → α × σ) (s : σ) : (modifyGet f : StateT σ m α).run s = pure ((f s).1, (f s).2) := by
|
||||
@[simp] theorem run_modifyGet [Monad m] (f : σ → α × σ) (s : σ) : (modifyGet f : StateT σ m α).run s = pure ((f s).1, (f s).2) := by
|
||||
simp [modifyGet, MonadStateOf.modifyGet, StateT.modifyGet, run]
|
||||
|
||||
@[simp, grind =] theorem run_lift {α σ : Type u} [Monad m] (x : m α) (s : σ) : (StateT.lift x : StateT σ m α).run s = x >>= fun a => pure (a, s) := rfl
|
||||
@[simp] theorem run_lift {α σ : Type u} [Monad m] (x : m α) (s : σ) : (StateT.lift x : StateT σ m α).run s = x >>= fun a => pure (a, s) := rfl
|
||||
|
||||
@[grind =]
|
||||
theorem run_bind_lift {α σ : Type u} [Monad m] [LawfulMonad m] (x : m α) (f : α → StateT σ m β) (s : σ) : (StateT.lift x >>= f).run s = x >>= fun a => (f a).run s := by
|
||||
simp [StateT.lift, StateT.run, bind, StateT.bind]
|
||||
|
||||
@[simp, grind =] theorem run_monadLift {α σ : Type u} [Monad m] [MonadLiftT n m] (x : n α) (s : σ) : (monadLift x : StateT σ m α).run s = (monadLift x : m α) >>= fun a => pure (a, s) := rfl
|
||||
@[simp] theorem run_monadLift {α σ : Type u} [Monad m] [MonadLiftT n m] (x : n α) (s : σ) : (monadLift x : StateT σ m α).run s = (monadLift x : m α) >>= fun a => pure (a, s) := rfl
|
||||
|
||||
@[simp, grind =] theorem run_monadMap [MonadFunctorT n m] (f : {β : Type u} → n β → n β) (x : StateT σ m α) (s : σ) :
|
||||
@[simp] theorem run_monadMap [MonadFunctorT n m] (f : {β : Type u} → n β → n β) (x : StateT σ m α) (s : σ) :
|
||||
(monadMap @f x : StateT σ m α).run s = monadMap @f (x.run s) := rfl
|
||||
|
||||
@[simp] theorem run_seq {α β σ : Type u} [Monad m] [LawfulMonad m] (f : StateT σ m (α → β)) (x : StateT σ m α) (s : σ) : (f <*> x).run s = (f.run s >>= fun fs => (fun (p : α × σ) => (fs.1 p.1, p.2)) <$> x.run fs.2) := by
|
||||
|
||||
@@ -9,3 +9,5 @@ prelude
|
||||
public import Init.Control.Lawful.MonadLift.Basic
|
||||
public import Init.Control.Lawful.MonadLift.Lemmas
|
||||
public import Init.Control.Lawful.MonadLift.Instances
|
||||
|
||||
public section
|
||||
|
||||
@@ -6,18 +6,12 @@ Authors: Quang Dao, Paul Reichert
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Init.Control.Option
|
||||
import all Init.Control.Option
|
||||
public import Init.Control.Except
|
||||
import all Init.Control.Except
|
||||
public import Init.Control.ExceptCps
|
||||
import all Init.Control.ExceptCps
|
||||
public import Init.Control.StateRef
|
||||
import all Init.Control.StateRef
|
||||
public import Init.Control.StateCps
|
||||
import all Init.Control.StateCps
|
||||
public import Init.Control.Id
|
||||
import all Init.Control.Id
|
||||
public import all Init.Control.Option
|
||||
public import all Init.Control.Except
|
||||
public import all Init.Control.ExceptCps
|
||||
public import all Init.Control.StateRef
|
||||
public import all Init.Control.StateCps
|
||||
public import all Init.Control.Id
|
||||
public import Init.Control.Lawful.MonadLift.Lemmas
|
||||
public import Init.Control.Lawful.Instances
|
||||
|
||||
@@ -64,6 +58,10 @@ namespace OptionT
|
||||
|
||||
variable [Monad m] [LawfulMonad m]
|
||||
|
||||
@[simp]
|
||||
theorem lift_pure {α : Type u} (a : α) : OptionT.lift (pure a : m α) = pure a := by
|
||||
simp only [OptionT.lift, OptionT.mk, bind_pure_comp, map_pure, pure, OptionT.pure]
|
||||
|
||||
@[simp]
|
||||
theorem lift_bind {α β : Type u} (ma : m α) (f : α → m β) :
|
||||
OptionT.lift (ma >>= f) = OptionT.lift ma >>= (fun a => OptionT.lift (f a)) := by
|
||||
|
||||
@@ -39,14 +39,13 @@ variable {m : Type u → Type v} [Monad m] {α β : Type u}
|
||||
Converts an action that returns an `Option` into one that might fail, with `none` indicating
|
||||
failure.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
protected def mk (x : m (Option α)) : OptionT m α :=
|
||||
x
|
||||
|
||||
/--
|
||||
Sequences two potentially-failing actions. The second action is run only if the first succeeds.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
protected def bind (x : OptionT m α) (f : α → OptionT m β) : OptionT m β := OptionT.mk do
|
||||
match (← x) with
|
||||
| some a => f a
|
||||
@@ -55,7 +54,7 @@ protected def bind (x : OptionT m α) (f : α → OptionT m β) : OptionT m β :
|
||||
/--
|
||||
Succeeds with the provided value.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
protected def pure (a : α) : OptionT m α := OptionT.mk do
|
||||
pure (some a)
|
||||
|
||||
|
||||
@@ -52,4 +52,4 @@ instance ReaderT.tryFinally [MonadFinally m] : MonadFinally (ReaderT ρ m) where
|
||||
A monad with access to a read-only value of type `ρ`. The value can be locally overridden by
|
||||
`withReader`, but it cannot be mutated.
|
||||
-/
|
||||
abbrev ReaderM (ρ : Type u) := ReaderT ρ Id
|
||||
@[reducible] def ReaderM (ρ : Type u) := ReaderT ρ Id
|
||||
|
||||
@@ -187,9 +187,6 @@ match [a, b] with
|
||||
simplifies to `a`. -/
|
||||
syntax (name := simpMatch) "simp_match" : conv
|
||||
|
||||
/-- Removes one or more hypotheses from the local context. -/
|
||||
syntax (name := clear) "clear" (ppSpace colGt term:max)+ : conv
|
||||
|
||||
/-- Executes the given tactic block without converting `conv` goal into a regular goal. -/
|
||||
syntax (name := nestedTacticCore) "tactic'" " => " tacticSeq : conv
|
||||
|
||||
@@ -265,7 +262,7 @@ resulting in `t'`, which becomes the new target subgoal. -/
|
||||
syntax (name := convConvSeq) "conv" " => " convSeq : conv
|
||||
|
||||
/-- `· conv` focuses on the main conv goal and tries to solve it using `s`. -/
|
||||
macro dot:patternIgnore("· " <|> ". ") s:convSeq : conv => `(conv| {%$dot ($s) })
|
||||
macro dot:patternIgnore("·" <|> ".") s:convSeq : conv => `(conv| {%$dot ($s) })
|
||||
|
||||
|
||||
/-- `fail_if_success t` fails if the tactic `t` succeeds. -/
|
||||
@@ -290,17 +287,13 @@ macro "right" : conv => `(conv| rhs)
|
||||
/-- `intro` traverses into binders. Synonym for `ext`. -/
|
||||
macro "intro" xs:(ppSpace colGt binderIdent)* : conv => `(conv| ext $xs*)
|
||||
|
||||
syntax enterPattern := "in " (occs)? term
|
||||
|
||||
syntax enterArg := binderIdent <|> argArg <|> enterPattern
|
||||
syntax enterArg := binderIdent <|> argArg
|
||||
|
||||
/-- `enter [arg, ...]` is a compact way to describe a path to a subterm.
|
||||
It is a shorthand for other conv tactics as follows:
|
||||
* `enter [i]` is equivalent to `arg i`.
|
||||
* `enter [@i]` is equivalent to `arg @i`.
|
||||
* `enter [x]` (where `x` is an identifier) is equivalent to `ext x`.
|
||||
* `enter [in e]` (where `e` is a term) is equivalent to `pattern e`.
|
||||
Occurrences can be specified with `enter [in (occs := ...) e]`.
|
||||
For example, given the target `f (g a (fun x => x b))`, `enter [1, 2, x, 1]`
|
||||
will traverse to the subterm `b`. -/
|
||||
syntax (name := enter) "enter" " [" withoutPosition(enterArg,+) "]" : conv
|
||||
@@ -349,7 +342,7 @@ This is the conv mode version of the `lift_lets` tactic.
|
||||
syntax (name := liftLets) "lift_lets " optConfig : conv
|
||||
|
||||
/--
|
||||
Transforms `let` expressions into `have` expressions within the target expression when possible.
|
||||
Transforms `let` expressions into `have` expressions within th etarget expression when possible.
|
||||
This is the conv mode version of the `let_to_have` tactic.
|
||||
-/
|
||||
syntax (name := letToHave) "let_to_have" : conv
|
||||
|
||||
@@ -29,29 +29,6 @@ theorem id_def {α : Sort u} (a : α) : id a = a := rfl
|
||||
|
||||
attribute [grind] id
|
||||
|
||||
/--
|
||||
A helper gadget for instructing the kernel to eagerly reduce terms.
|
||||
|
||||
When the gadget wraps the argument of an application, then when checking that
|
||||
the expected and inferred type of the argument match, the kernel will evaluate terms more eagerly.
|
||||
It is often used to wrap `Eq.refl true` proof terms as `eagerReduce (Eq.refl true)`
|
||||
when using proof by reflection.
|
||||
As an example, consider the theorem:
|
||||
```
|
||||
theorem eq_norm (ctx : Context) (p₁ p₂ : Poly) (h : (p₁.norm == p₂) = true) :
|
||||
p₁.denote ctx = 0 → p₂.denote ctx = 0
|
||||
```
|
||||
The argument `h : (p₁.norm == p₂) = true` is a candidate for `eagerReduce`.
|
||||
When applying this theorem, we would write:
|
||||
|
||||
```
|
||||
eq_norm ctx p q (eagerReduce (Eq.refl true)) h
|
||||
```
|
||||
to instruct the kernel to use eager reduction when establishing that `(p.norm == q) = true` is
|
||||
definitionally equal to `true = true`.
|
||||
-/
|
||||
@[expose] def eagerReduce {α : Sort u} (a : α) : α := a
|
||||
|
||||
/--
|
||||
`flip f a b` is `f b a`. It is useful for "point-free" programming,
|
||||
since it can sometimes be used to avoid introducing variables.
|
||||
@@ -144,9 +121,8 @@ Computed values are cached, so the value is not recomputed.
|
||||
x.fn ()
|
||||
|
||||
-- Ensure `Thunk.fn` is still computable even if it shouldn't be accessed directly.
|
||||
/-- Implementation detail. -/
|
||||
@[inline] def Thunk.fnImpl (x : Thunk α) : Unit → α := fun _ => x.get
|
||||
@[csimp] theorem Thunk.fn_eq_fnImpl : @Thunk.fn = @Thunk.fnImpl := rfl
|
||||
@[inline] private def Thunk.fnImpl (x : Thunk α) : Unit → α := fun _ => x.get
|
||||
@[csimp] private theorem Thunk.fn_eq_fnImpl : @Thunk.fn = @Thunk.fnImpl := rfl
|
||||
|
||||
/--
|
||||
Constructs a new thunk that forces `x` and then applies `x` to the result. Upon forcing, the result
|
||||
@@ -776,8 +752,6 @@ Unlike `x ≠ y` (which is notation for `Ne x y`), this is `Bool` valued instead
|
||||
|
||||
@[inherit_doc] infix:50 " != " => bne
|
||||
|
||||
macro_rules | `($x != $y) => `(binrel_no_prop% bne $x $y)
|
||||
|
||||
recommended_spelling "bne" for "!=" in [bne, «term_!=_»]
|
||||
|
||||
/-- `ReflBEq α` says that the `BEq` implementation is reflexive. -/
|
||||
@@ -879,8 +853,6 @@ and asserts that `a` and `b` are not equal.
|
||||
|
||||
@[inherit_doc] infix:50 " ≠ " => Ne
|
||||
|
||||
macro_rules | `($x ≠ $y) => `(binrel% Ne $x $y)
|
||||
|
||||
recommended_spelling "ne" for "≠" in [Ne, «term_≠_»]
|
||||
|
||||
section Ne
|
||||
@@ -1560,13 +1532,38 @@ end Setoid
|
||||
/-! # Propositional extensionality -/
|
||||
|
||||
/--
|
||||
The [axiom](lean-manual://section/axioms) of **propositional extensionality**. It asserts that if
|
||||
propositions `a` and `b` are logically equivalent (that is, if `a` can be proved from `b` and vice
|
||||
versa), then `a` and `b` are *equal*, meaning `a` can be replaced with `b` in all contexts.
|
||||
The axiom of **propositional extensionality**. It asserts that if propositions
|
||||
`a` and `b` are logically equivalent (i.e. we can prove `a` from `b` and vice versa),
|
||||
then `a` and `b` are *equal*, meaning that we can replace `a` with `b` in all
|
||||
contexts.
|
||||
|
||||
The standard logical connectives provably respect propositional extensionality. However, an axiom is
|
||||
needed for higher order expressions like `P a` where `P : Prop → Prop` is unknown, as well as for
|
||||
equality. Propositional extensionality is intuitionistically valid.
|
||||
For simple expressions like `a ∧ c ∨ d → e` we can prove that because all the logical
|
||||
connectives respect logical equivalence, we can replace `a` with `b` in this expression
|
||||
without using `propext`. However, for higher order expressions like `P a` where
|
||||
`P : Prop → Prop` is unknown, or indeed for `a = b` itself, we cannot replace `a` with `b`
|
||||
without an axiom which says exactly this.
|
||||
|
||||
This is a relatively uncontroversial axiom, which is intuitionistically valid.
|
||||
It does however block computation when using `#reduce` to reduce proofs directly
|
||||
(which is not recommended), meaning that canonicity,
|
||||
the property that all closed terms of type `Nat` normalize to numerals,
|
||||
fails to hold when this (or any) axiom is used:
|
||||
```
|
||||
set_option pp.proofs true
|
||||
|
||||
def foo : Nat := by
|
||||
have : (True → True) ↔ True := ⟨λ _ => trivial, λ _ _ => trivial⟩
|
||||
have := propext this ▸ (2 : Nat)
|
||||
exact this
|
||||
|
||||
#reduce foo
|
||||
-- propext { mp := fun x x => True.intro, mpr := fun x => True.intro } ▸ 2
|
||||
|
||||
#eval foo -- 2
|
||||
```
|
||||
`#eval` can evaluate it to a numeral because the compiler erases casts and
|
||||
does not evaluate proofs, so `propext`, whose return type is a proposition,
|
||||
can never block it.
|
||||
-/
|
||||
axiom propext {a b : Prop} : (a ↔ b) → a = b
|
||||
|
||||
@@ -1581,7 +1578,6 @@ instance {p q : Prop} [d : Decidable (p ↔ q)] : Decidable (p = q) :=
|
||||
|
||||
gen_injective_theorems% Array
|
||||
gen_injective_theorems% BitVec
|
||||
gen_injective_theorems% ByteArray
|
||||
gen_injective_theorems% Char
|
||||
gen_injective_theorems% DoResultBC
|
||||
gen_injective_theorems% DoResultPR
|
||||
@@ -1598,7 +1594,6 @@ gen_injective_theorems% MProd
|
||||
gen_injective_theorems% NonScalar
|
||||
gen_injective_theorems% Option
|
||||
gen_injective_theorems% PLift
|
||||
gen_injective_theorems% PULift
|
||||
gen_injective_theorems% PNonScalar
|
||||
gen_injective_theorems% PProd
|
||||
gen_injective_theorems% Prod
|
||||
@@ -1606,7 +1601,7 @@ gen_injective_theorems% PSigma
|
||||
gen_injective_theorems% PSum
|
||||
gen_injective_theorems% Sigma
|
||||
gen_injective_theorems% String
|
||||
gen_injective_theorems% String.Pos.Raw
|
||||
gen_injective_theorems% String.Pos
|
||||
gen_injective_theorems% Substring
|
||||
gen_injective_theorems% Subtype
|
||||
gen_injective_theorems% Sum
|
||||
@@ -2524,17 +2519,12 @@ class Antisymm (r : α → α → Prop) : Prop where
|
||||
/-- An antisymmetric relation `r` satisfies `r a b → r b a → a = b`. -/
|
||||
antisymm (a b : α) : r a b → r b a → a = b
|
||||
|
||||
/-- `Asymm r` means that the binary relation `r` is asymmetric, that is,
|
||||
/-- `Asymm X r` means that the binary relation `r` on `X` is asymmetric, that is,
|
||||
`r a b → ¬ r b a`. -/
|
||||
class Asymm (r : α → α → Prop) : Prop where
|
||||
/-- An asymmetric relation satisfies `r a b → ¬ r b a`. -/
|
||||
asymm : ∀ a b, r a b → ¬r b a
|
||||
|
||||
/-- `Symm r` means that the binary relation `r` is symmetric, that is, `r a b → r b a`. -/
|
||||
class Symm (r : α → α → Prop) : Prop where
|
||||
/-- A symmetric relation satisfies `r a b → r b a`. -/
|
||||
symm : ∀ a b, r a b → r b a
|
||||
|
||||
/-- `Total X r` means that the binary relation `r` on `X` is total, that is, that for any
|
||||
`x y : X` we have `r x y` or `r y x`. -/
|
||||
class Total (r : α → α → Prop) : Prop where
|
||||
|
||||
@@ -30,7 +30,6 @@ public import Init.Data.Random
|
||||
public import Init.Data.ToString
|
||||
public import Init.Data.Range
|
||||
public import Init.Data.Hashable
|
||||
public import Init.Data.LawfulHashable
|
||||
public import Init.Data.OfScientific
|
||||
public import Init.Data.Format
|
||||
public import Init.Data.Stream
|
||||
@@ -50,6 +49,5 @@ public import Init.Data.Vector
|
||||
public import Init.Data.Iterators
|
||||
public import Init.Data.Range.Polymorphic
|
||||
public import Init.Data.Slice
|
||||
public import Init.Data.Order
|
||||
public import Init.Data.Rat
|
||||
public import Init.Data.Dyadic
|
||||
|
||||
public section
|
||||
|
||||
@@ -10,7 +10,7 @@ prelude
|
||||
public import Init.Classical
|
||||
public import Init.ByCases
|
||||
|
||||
@[expose] public section
|
||||
public section
|
||||
|
||||
namespace Lean.Data.AC
|
||||
inductive Expr
|
||||
|
||||
@@ -30,3 +30,5 @@ public import Init.Data.Array.Erase
|
||||
public import Init.Data.Array.Zip
|
||||
public import Init.Data.Array.InsertIdx
|
||||
public import Init.Data.Array.Extract
|
||||
|
||||
public section
|
||||
|
||||
@@ -9,8 +9,7 @@ prelude
|
||||
public import Init.Data.Array.Mem
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.Array.Count
|
||||
public import Init.Data.List.Attach
|
||||
import all Init.Data.List.Attach
|
||||
public import all Init.Data.List.Attach
|
||||
|
||||
public section
|
||||
|
||||
@@ -84,10 +83,10 @@ well-founded recursion mechanism to prove that the function terminates.
|
||||
simp [pmap]
|
||||
|
||||
/-- Implementation of `pmap` using the zero-copy version of `attach`. -/
|
||||
@[inline] def pmapImpl {P : α → Prop} (f : ∀ a, P a → β) (xs : Array α) (H : ∀ a ∈ xs, P a) :
|
||||
@[inline] private def pmapImpl {P : α → Prop} (f : ∀ a, P a → β) (xs : Array α) (H : ∀ a ∈ xs, P a) :
|
||||
Array β := (xs.attachWith _ H).map fun ⟨x, h'⟩ => f x h'
|
||||
|
||||
@[csimp] theorem pmap_eq_pmapImpl : @pmap = @pmapImpl := by
|
||||
@[csimp] private theorem pmap_eq_pmapImpl : @pmap = @pmapImpl := by
|
||||
funext α β p f xs H
|
||||
cases xs
|
||||
simp only [pmap, pmapImpl, List.attachWith_toArray, List.map_toArray, mk.injEq, List.map_attachWith_eq_pmap]
|
||||
@@ -95,16 +94,16 @@ well-founded recursion mechanism to prove that the function terminates.
|
||||
intro a m h₁ h₂
|
||||
congr
|
||||
|
||||
@[simp] theorem pmap_empty {P : α → Prop} (f : ∀ a, P a → β) : pmap f #[] (by simp) = #[] := rfl
|
||||
@[simp, grind =] theorem pmap_empty {P : α → Prop} (f : ∀ a, P a → β) : pmap f #[] (by simp) = #[] := rfl
|
||||
|
||||
@[simp] theorem pmap_push {P : α → Prop} (f : ∀ a, P a → β) (a : α) (xs : Array α) (h : ∀ b ∈ xs.push a, P b) :
|
||||
@[simp, grind =] theorem pmap_push {P : α → Prop} (f : ∀ a, P a → β) (a : α) (xs : Array α) (h : ∀ b ∈ xs.push a, P b) :
|
||||
pmap f (xs.push a) h =
|
||||
(pmap f xs (fun a m => by simp at h; exact h a (.inl m))).push (f a (h a (by simp))) := by
|
||||
simp [pmap]
|
||||
|
||||
@[simp] theorem attach_empty : (#[] : Array α).attach = #[] := rfl
|
||||
@[simp, grind =] theorem attach_empty : (#[] : Array α).attach = #[] := rfl
|
||||
|
||||
@[simp] theorem attachWith_empty {P : α → Prop} (H : ∀ x ∈ #[], P x) : (#[] : Array α).attachWith P H = #[] := rfl
|
||||
@[simp, grind =] theorem attachWith_empty {P : α → Prop} (H : ∀ x ∈ #[], P x) : (#[] : Array α).attachWith P H = #[] := rfl
|
||||
|
||||
@[simp] theorem _root_.List.attachWith_mem_toArray {l : List α} :
|
||||
l.attachWith (fun x => x ∈ l.toArray) (fun x h => by simpa using h) =
|
||||
@@ -121,15 +120,17 @@ theorem pmap_eq_map {p : α → Prop} {f : α → β} {xs : Array α} (H) :
|
||||
theorem pmap_congr_left {p q : α → Prop} {f : ∀ a, p a → β} {g : ∀ a, q a → β} (xs : Array α) {H₁ H₂}
|
||||
(h : ∀ a ∈ xs, ∀ (h₁ h₂), f a h₁ = g a h₂) : pmap f xs H₁ = pmap g xs H₂ := by
|
||||
cases xs
|
||||
simp only [List.mem_toArray] at h
|
||||
simp only [mem_toArray] at h
|
||||
simp only [List.pmap_toArray, mk.injEq]
|
||||
rw [List.pmap_congr_left _ h]
|
||||
|
||||
@[grind =]
|
||||
theorem map_pmap {p : α → Prop} {g : β → γ} {f : ∀ a, p a → β} {xs : Array α} (H) :
|
||||
map g (pmap f xs H) = pmap (fun a h => g (f a h)) xs H := by
|
||||
cases xs
|
||||
simp [List.map_pmap]
|
||||
|
||||
@[grind =]
|
||||
theorem pmap_map {p : β → Prop} {g : ∀ b, p b → γ} {f : α → β} {xs : Array α} (H) :
|
||||
pmap g (map f xs) H = pmap (fun a h => g (f a) h) xs fun _ h => H _ (mem_map_of_mem h) := by
|
||||
cases xs
|
||||
@@ -145,14 +146,14 @@ theorem attachWith_congr {xs ys : Array α} (w : xs = ys) {P : α → Prop} {H :
|
||||
subst w
|
||||
simp
|
||||
|
||||
@[simp] theorem attach_push {a : α} {xs : Array α} :
|
||||
@[simp, grind =] theorem attach_push {a : α} {xs : Array α} :
|
||||
(xs.push a).attach =
|
||||
(xs.attach.map (fun ⟨x, h⟩ => ⟨x, mem_push_of_mem a h⟩)).push ⟨a, by simp⟩ := by
|
||||
cases xs
|
||||
rw [attach_congr (List.push_toArray _ _)]
|
||||
simp [Function.comp_def]
|
||||
|
||||
@[simp] theorem attachWith_push {a : α} {xs : Array α} {P : α → Prop} {H : ∀ x ∈ xs.push a, P x} :
|
||||
@[simp, grind =] theorem attachWith_push {a : α} {xs : Array α} {P : α → Prop} {H : ∀ x ∈ xs.push a, P x} :
|
||||
(xs.push a).attachWith P H =
|
||||
(xs.attachWith P (fun x h => by simp at H; exact H x (.inl h))).push ⟨a, H a (by simp)⟩ := by
|
||||
cases xs
|
||||
@@ -174,6 +175,9 @@ theorem attach_map_val (xs : Array α) (f : α → β) :
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[deprecated attach_map_val (since := "2025-02-17")]
|
||||
abbrev attach_map_coe := @attach_map_val
|
||||
|
||||
-- The argument `xs : Array α` is explicit to allow rewriting from right to left.
|
||||
theorem attach_map_subtype_val (xs : Array α) : xs.attach.map Subtype.val = xs := by
|
||||
cases xs; simp
|
||||
@@ -182,18 +186,21 @@ theorem attachWith_map_val {p : α → Prop} {f : α → β} {xs : Array α} (H
|
||||
((xs.attachWith p H).map fun (i : { i // p i}) => f i) = xs.map f := by
|
||||
cases xs; simp
|
||||
|
||||
@[deprecated attachWith_map_val (since := "2025-02-17")]
|
||||
abbrev attachWith_map_coe := @attachWith_map_val
|
||||
|
||||
theorem attachWith_map_subtype_val {p : α → Prop} {xs : Array α} (H : ∀ a ∈ xs, p a) :
|
||||
(xs.attachWith p H).map Subtype.val = xs := by
|
||||
cases xs; simp
|
||||
|
||||
@[simp, grind ←]
|
||||
@[simp, grind]
|
||||
theorem mem_attach (xs : Array α) : ∀ x, x ∈ xs.attach
|
||||
| ⟨a, h⟩ => by
|
||||
have := mem_map.1 (by rw [attach_map_subtype_val] <;> exact h)
|
||||
rcases this with ⟨⟨_, _⟩, m, rfl⟩
|
||||
exact m
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp, grind]
|
||||
theorem mem_attachWith {xs : Array α} {q : α → Prop} (H) (x : {x // q x}) :
|
||||
x ∈ xs.attachWith q H ↔ x.1 ∈ xs := by
|
||||
cases xs
|
||||
@@ -204,13 +211,12 @@ theorem mem_pmap {p : α → Prop} {f : ∀ a, p a → β} {xs H b} :
|
||||
b ∈ pmap f xs H ↔ ∃ (a : _) (h : a ∈ xs), f a (H a h) = b := by
|
||||
simp only [pmap_eq_map_attach, mem_map, mem_attach, true_and, Subtype.exists, eq_comm]
|
||||
|
||||
@[grind]
|
||||
theorem mem_pmap_of_mem {p : α → Prop} {f : ∀ a, p a → β} {xs H} {a} (h : a ∈ xs) :
|
||||
f a (H a h) ∈ pmap f xs H := by
|
||||
rw [mem_pmap]
|
||||
exact ⟨a, h, rfl⟩
|
||||
|
||||
grind_pattern mem_pmap_of_mem => _ ∈ pmap f xs H, a ∈ xs
|
||||
|
||||
@[simp, grind =]
|
||||
theorem size_pmap {p : α → Prop} {f : ∀ a, p a → β} {xs H} : (pmap f xs H).size = xs.size := by
|
||||
cases xs; simp
|
||||
@@ -286,23 +292,25 @@ theorem getElem_attach {xs : Array α} {i : Nat} (h : i < xs.attach.size) :
|
||||
xs.attach[i] = ⟨xs[i]'(by simpa using h), getElem_mem (by simpa using h)⟩ :=
|
||||
getElem_attachWith h
|
||||
|
||||
@[simp] theorem pmap_attach {xs : Array α} {p : {x // x ∈ xs} → Prop} {f : ∀ a, p a → β} (H) :
|
||||
@[simp, grind =] theorem pmap_attach {xs : Array α} {p : {x // x ∈ xs} → Prop} {f : ∀ a, p a → β} (H) :
|
||||
pmap f xs.attach H =
|
||||
xs.pmap (P := fun a => ∃ h : a ∈ xs, p ⟨a, h⟩)
|
||||
(fun a h => f ⟨a, h.1⟩ h.2) (fun a h => ⟨h, H ⟨a, h⟩ (by simp)⟩) := by
|
||||
ext <;> simp
|
||||
|
||||
@[simp] theorem pmap_attachWith {xs : Array α} {p : {x // q x} → Prop} {f : ∀ a, p a → β} (H₁ H₂) :
|
||||
@[simp, grind =] theorem pmap_attachWith {xs : Array α} {p : {x // q x} → Prop} {f : ∀ a, p a → β} (H₁ H₂) :
|
||||
pmap f (xs.attachWith q H₁) H₂ =
|
||||
xs.pmap (P := fun a => ∃ h : q a, p ⟨a, h⟩)
|
||||
(fun a h => f ⟨a, h.1⟩ h.2) (fun a h => ⟨H₁ _ h, H₂ ⟨a, H₁ _ h⟩ (by simpa)⟩) := by
|
||||
ext <;> simp
|
||||
|
||||
@[grind =]
|
||||
theorem foldl_pmap {xs : Array α} {P : α → Prop} {f : (a : α) → P a → β}
|
||||
(H : ∀ (a : α), a ∈ xs → P a) (g : γ → β → γ) (x : γ) :
|
||||
(xs.pmap f H).foldl g x = xs.attach.foldl (fun acc a => g acc (f a.1 (H _ a.2))) x := by
|
||||
rw [pmap_eq_map_attach, foldl_map]
|
||||
|
||||
@[grind =]
|
||||
theorem foldr_pmap {xs : Array α} {P : α → Prop} {f : (a : α) → P a → β}
|
||||
(H : ∀ (a : α), a ∈ xs → P a) (g : β → γ → γ) (x : γ) :
|
||||
(xs.pmap f H).foldr g x = xs.attach.foldr (fun a acc => g (f a.1 (H _ a.2)) acc) x := by
|
||||
@@ -336,7 +344,7 @@ theorem foldl_attach {xs : Array α} {f : β → α → β} {b : β} :
|
||||
xs.attach.foldl (fun acc t => f acc t.1) b = xs.foldl f b := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp only [List.attach_toArray, List.attachWith_mem_toArray, List.size_toArray,
|
||||
List.foldl_toArray', List.mem_toArray, List.foldl_subtype]
|
||||
List.foldl_toArray', mem_toArray, List.foldl_subtype]
|
||||
congr
|
||||
ext
|
||||
simpa using fun a => List.mem_of_getElem? a
|
||||
@@ -355,23 +363,25 @@ theorem foldr_attach {xs : Array α} {f : α → β → β} {b : β} :
|
||||
xs.attach.foldr (fun t acc => f t.1 acc) b = xs.foldr f b := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp only [List.attach_toArray, List.attachWith_mem_toArray, List.size_toArray,
|
||||
List.foldr_toArray', List.mem_toArray, List.foldr_subtype]
|
||||
List.foldr_toArray', mem_toArray, List.foldr_subtype]
|
||||
congr
|
||||
ext
|
||||
simpa using fun a => List.mem_of_getElem? a
|
||||
|
||||
@[grind =]
|
||||
theorem attach_map {xs : Array α} {f : α → β} :
|
||||
(xs.map f).attach = xs.attach.map (fun ⟨x, h⟩ => ⟨f x, mem_map_of_mem h⟩) := by
|
||||
cases xs
|
||||
ext <;> simp
|
||||
|
||||
@[grind =]
|
||||
theorem attachWith_map {xs : Array α} {f : α → β} {P : β → Prop} (H : ∀ (b : β), b ∈ xs.map f → P b) :
|
||||
(xs.map f).attachWith P H = (xs.attachWith (P ∘ f) (fun _ h => H _ (mem_map_of_mem h))).map
|
||||
fun ⟨x, h⟩ => ⟨f x, h⟩ := by
|
||||
cases xs
|
||||
simp [List.attachWith_map]
|
||||
|
||||
@[simp] theorem map_attachWith {xs : Array α} {P : α → Prop} {H : ∀ (a : α), a ∈ xs → P a}
|
||||
@[simp, grind =] theorem map_attachWith {xs : Array α} {P : α → Prop} {H : ∀ (a : α), a ∈ xs → P a}
|
||||
{f : { x // P x } → β} :
|
||||
(xs.attachWith P H).map f = xs.attach.map fun ⟨x, h⟩ => f ⟨x, H _ h⟩ := by
|
||||
cases xs <;> simp_all
|
||||
@@ -389,6 +399,9 @@ theorem map_attach_eq_pmap {xs : Array α} {f : { x // x ∈ xs } → β} :
|
||||
cases xs
|
||||
ext <;> simp
|
||||
|
||||
@[deprecated map_attach_eq_pmap (since := "2025-02-09")]
|
||||
abbrev map_attach := @map_attach_eq_pmap
|
||||
|
||||
@[grind =]
|
||||
theorem attach_filterMap {xs : Array α} {f : α → Option β} :
|
||||
(xs.filterMap f).attach = xs.attach.filterMap
|
||||
@@ -424,6 +437,7 @@ theorem filter_attachWith {q : α → Prop} {xs : Array α} {p : {x // q x} →
|
||||
cases xs
|
||||
simp [Function.comp_def, List.filter_map]
|
||||
|
||||
@[grind =]
|
||||
theorem pmap_pmap {p : α → Prop} {q : β → Prop} {g : ∀ a, p a → β} {f : ∀ b, q b → γ} {xs} (H₁ H₂) :
|
||||
pmap f (pmap g xs H₁) H₂ =
|
||||
pmap (α := { x // x ∈ xs }) (fun a h => f (g a h) (H₂ (g a h) (mem_pmap_of_mem a.2))) xs.attach
|
||||
@@ -431,7 +445,7 @@ theorem pmap_pmap {p : α → Prop} {q : β → Prop} {g : ∀ a, p a → β} {f
|
||||
cases xs
|
||||
simp [List.pmap_pmap, List.pmap_map]
|
||||
|
||||
@[simp] theorem pmap_append {p : ι → Prop} {f : ∀ a : ι, p a → α} {xs ys : Array ι}
|
||||
@[simp, grind =] theorem pmap_append {p : ι → Prop} {f : ∀ a : ι, p a → α} {xs ys : Array ι}
|
||||
(h : ∀ a ∈ xs ++ ys, p a) :
|
||||
(xs ++ ys).pmap f h =
|
||||
(xs.pmap f fun a ha => h a (mem_append_left ys ha)) ++
|
||||
@@ -446,7 +460,7 @@ theorem pmap_append' {p : α → Prop} {f : ∀ a : α, p a → β} {xs ys : Arr
|
||||
xs.pmap f h₁ ++ ys.pmap f h₂ :=
|
||||
pmap_append _
|
||||
|
||||
@[simp] theorem attach_append {xs ys : Array α} :
|
||||
@[simp, grind =] theorem attach_append {xs ys : Array α} :
|
||||
(xs ++ ys).attach = xs.attach.map (fun ⟨x, h⟩ => ⟨x, mem_append_left ys h⟩) ++
|
||||
ys.attach.map fun ⟨x, h⟩ => ⟨x, mem_append_right xs h⟩ := by
|
||||
cases xs
|
||||
@@ -454,59 +468,62 @@ theorem pmap_append' {p : α → Prop} {f : ∀ a : α, p a → β} {xs ys : Arr
|
||||
rw [attach_congr (List.append_toArray _ _)]
|
||||
simp [List.attach_append, Function.comp_def]
|
||||
|
||||
@[simp] theorem attachWith_append {P : α → Prop} {xs ys : Array α}
|
||||
@[simp, grind =] theorem attachWith_append {P : α → Prop} {xs ys : Array α}
|
||||
{H : ∀ (a : α), a ∈ xs ++ ys → P a} :
|
||||
(xs ++ ys).attachWith P H = xs.attachWith P (fun a h => H a (mem_append_left ys h)) ++
|
||||
ys.attachWith P (fun a h => H a (mem_append_right xs h)) := by
|
||||
simp [attachWith]
|
||||
|
||||
@[simp] theorem pmap_reverse {P : α → Prop} {f : (a : α) → P a → β} {xs : Array α}
|
||||
@[simp, grind =] theorem pmap_reverse {P : α → Prop} {f : (a : α) → P a → β} {xs : Array α}
|
||||
(H : ∀ (a : α), a ∈ xs.reverse → P a) :
|
||||
xs.reverse.pmap f H = (xs.pmap f (fun a h => H a (by simpa using h))).reverse := by
|
||||
induction xs <;> simp_all
|
||||
|
||||
@[grind =]
|
||||
theorem reverse_pmap {P : α → Prop} {f : (a : α) → P a → β} {xs : Array α}
|
||||
(H : ∀ (a : α), a ∈ xs → P a) :
|
||||
(xs.pmap f H).reverse = xs.reverse.pmap f (fun a h => H a (by simpa using h)) := by
|
||||
rw [pmap_reverse]
|
||||
|
||||
@[simp] theorem attachWith_reverse {P : α → Prop} {xs : Array α}
|
||||
@[simp, grind =] theorem attachWith_reverse {P : α → Prop} {xs : Array α}
|
||||
{H : ∀ (a : α), a ∈ xs.reverse → P a} :
|
||||
xs.reverse.attachWith P H =
|
||||
(xs.attachWith P (fun a h => H a (by simpa using h))).reverse := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[grind =]
|
||||
theorem reverse_attachWith {P : α → Prop} {xs : Array α}
|
||||
{H : ∀ (a : α), a ∈ xs → P a} :
|
||||
(xs.attachWith P H).reverse = (xs.reverse.attachWith P (fun a h => H a (by simpa using h))) := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem attach_reverse {xs : Array α} :
|
||||
@[simp, grind =] theorem attach_reverse {xs : Array α} :
|
||||
xs.reverse.attach = xs.attach.reverse.map fun ⟨x, h⟩ => ⟨x, by simpa using h⟩ := by
|
||||
cases xs
|
||||
rw [attach_congr List.reverse_toArray]
|
||||
simp
|
||||
|
||||
@[grind =]
|
||||
theorem reverse_attach {xs : Array α} :
|
||||
xs.attach.reverse = xs.reverse.attach.map fun ⟨x, h⟩ => ⟨x, by simpa using h⟩ := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem back?_pmap {P : α → Prop} {f : (a : α) → P a → β} {xs : Array α}
|
||||
@[simp, grind =] theorem back?_pmap {P : α → Prop} {f : (a : α) → P a → β} {xs : Array α}
|
||||
(H : ∀ (a : α), a ∈ xs → P a) :
|
||||
(xs.pmap f H).back? = xs.attach.back?.map fun ⟨a, m⟩ => f a (H a m) := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem back?_attachWith {P : α → Prop} {xs : Array α}
|
||||
@[simp, grind =] theorem back?_attachWith {P : α → Prop} {xs : Array α}
|
||||
{H : ∀ (a : α), a ∈ xs → P a} :
|
||||
(xs.attachWith P H).back? = xs.back?.pbind (fun a h => some ⟨a, H _ (mem_of_back? h)⟩) := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp]
|
||||
@[simp, grind =]
|
||||
theorem back?_attach {xs : Array α} :
|
||||
xs.attach.back? = xs.back?.pbind fun a h => some ⟨a, mem_of_back? h⟩ := by
|
||||
cases xs
|
||||
@@ -688,7 +705,7 @@ and simplifies these to the function directly taking the value.
|
||||
{f : { x // p x } → Array β} {g : α → Array β} (hf : ∀ x h, f ⟨x, h⟩ = g x) :
|
||||
(xs.flatMap f) = xs.unattach.flatMap g := by
|
||||
cases xs
|
||||
simp only [List.flatMap_toArray, List.unattach_toArray,
|
||||
simp only [List.flatMap_toArray, List.unattach_toArray,
|
||||
mk.injEq]
|
||||
rw [List.flatMap_subtype]
|
||||
simp [hf]
|
||||
|
||||
@@ -10,11 +10,11 @@ public import Init.WFTactics
|
||||
public import Init.Data.Nat.Basic
|
||||
public import Init.Data.Fin.Basic
|
||||
public import Init.Data.UInt.BasicAux
|
||||
public import Init.Data.Repr
|
||||
public import Init.Data.ToString.Basic
|
||||
public import Init.GetElem
|
||||
public import Init.Data.List.ToArrayImpl
|
||||
import all Init.Data.List.ToArrayImpl
|
||||
public import Init.Data.Array.Set
|
||||
import all Init.Data.Array.Set
|
||||
public import all Init.Data.List.ToArrayImpl
|
||||
public import all Init.Data.Array.Set
|
||||
|
||||
public section
|
||||
|
||||
@@ -40,11 +40,11 @@ namespace Array
|
||||
|
||||
/-! ### Preliminary theorems -/
|
||||
|
||||
@[simp, grind =] theorem size_set {xs : Array α} {i : Nat} {v : α} (h : i < xs.size) :
|
||||
@[simp, grind] theorem size_set {xs : Array α} {i : Nat} {v : α} (h : i < xs.size) :
|
||||
(set xs i v h).size = xs.size :=
|
||||
List.length_set ..
|
||||
|
||||
@[simp, grind =] theorem size_push {xs : Array α} (v : α) : (push xs v).size = xs.size + 1 :=
|
||||
@[simp, grind] theorem size_push {xs : Array α} (v : α) : (push xs v).size = xs.size + 1 :=
|
||||
List.length_concat ..
|
||||
|
||||
theorem ext {xs ys : Array α}
|
||||
@@ -108,19 +108,13 @@ instance : Membership α (Array α) where
|
||||
theorem mem_def {a : α} {as : Array α} : a ∈ as ↔ a ∈ as.toList :=
|
||||
⟨fun | .mk h => h, Array.Mem.mk⟩
|
||||
|
||||
@[simp, grind =] theorem _root_.List.mem_toArray {a : α} {l : List α} : a ∈ l.toArray ↔ a ∈ l := by
|
||||
@[simp, grind =] theorem mem_toArray {a : α} {l : List α} : a ∈ l.toArray ↔ a ∈ l := by
|
||||
simp [mem_def]
|
||||
|
||||
@[deprecated List.mem_toArray (since := "2025-09-04")]
|
||||
theorem mem_toArray {a : α} {l : List α} : a ∈ l.toArray ↔ a ∈ l :=
|
||||
List.mem_toArray
|
||||
|
||||
@[simp] theorem getElem_mem {xs : Array α} {i : Nat} (h : i < xs.size) : xs[i] ∈ xs := by
|
||||
@[simp, grind] theorem getElem_mem {xs : Array α} {i : Nat} (h : i < xs.size) : xs[i] ∈ xs := by
|
||||
rw [Array.mem_def, ← getElem_toList]
|
||||
apply List.getElem_mem
|
||||
|
||||
grind_pattern getElem_mem => xs[i] ∈ xs
|
||||
|
||||
@[simp, grind =] theorem emptyWithCapacity_eq {α n} : @emptyWithCapacity α n = #[] := rfl
|
||||
|
||||
@[simp] theorem mkEmpty_eq {α n} : @mkEmpty α n = #[] := rfl
|
||||
@@ -129,10 +123,19 @@ end Array
|
||||
|
||||
namespace List
|
||||
|
||||
@[deprecated Array.toArray_toList (since := "2025-02-17")]
|
||||
abbrev toArray_toList := @Array.toArray_toList
|
||||
|
||||
-- This does not need to be a simp lemma, as already after the `whnfR` the right hand side is `as`.
|
||||
theorem toList_toArray {as : List α} : as.toArray.toList = as := rfl
|
||||
|
||||
@[simp, grind =] theorem size_toArray {as : List α} : as.toArray.size = as.length := by simp [Array.size]
|
||||
@[deprecated toList_toArray (since := "2025-02-17")]
|
||||
abbrev _root_.Array.toList_toArray := @List.toList_toArray
|
||||
|
||||
@[simp, grind] theorem size_toArray {as : List α} : as.toArray.size = as.length := by simp [Array.size]
|
||||
|
||||
@[deprecated size_toArray (since := "2025-02-17")]
|
||||
abbrev _root_.Array.size_toArray := @List.size_toArray
|
||||
|
||||
@[simp, grind =] theorem getElem_toArray {xs : List α} {i : Nat} (h : i < xs.toArray.size) :
|
||||
xs.toArray[i] = xs[i]'(by simpa using h) := rfl
|
||||
@@ -159,8 +162,8 @@ This is a low-level version of `Array.size` that directly queries the runtime sy
|
||||
representation of arrays. While this is not provable, `Array.usize` always returns the exact size of
|
||||
the array since the implementation only supports arrays of size less than `USize.size`.
|
||||
-/
|
||||
@[extern "lean_array_size", simp, expose]
|
||||
def usize (xs : @& Array α) : USize := xs.size.toUSize
|
||||
@[extern "lean_array_size", simp]
|
||||
def usize (a : @& Array α) : USize := a.size.toUSize
|
||||
|
||||
/--
|
||||
Low-level indexing operator which is as fast as a C array read.
|
||||
@@ -168,8 +171,8 @@ Low-level indexing operator which is as fast as a C array read.
|
||||
This avoids overhead due to unboxing a `Nat` used as an index.
|
||||
-/
|
||||
@[extern "lean_array_uget", simp, expose]
|
||||
def uget (xs : @& Array α) (i : USize) (h : i.toNat < xs.size) : α :=
|
||||
xs[i.toNat]
|
||||
def uget (a : @& Array α) (i : USize) (h : i.toNat < a.size) : α :=
|
||||
a[i.toNat]
|
||||
|
||||
/--
|
||||
Low-level modification operator which is as fast as a C array write. The modification is performed
|
||||
@@ -177,7 +180,7 @@ in-place when the reference to the array is unique.
|
||||
|
||||
This avoids overhead due to unboxing a `Nat` used as an index.
|
||||
-/
|
||||
@[extern "lean_array_uset", expose]
|
||||
@[extern "lean_array_uset"]
|
||||
def uset (xs : Array α) (i : USize) (v : α) (h : i.toNat < xs.size) : Array α :=
|
||||
xs.set i.toNat v h
|
||||
|
||||
@@ -194,7 +197,7 @@ Examples:
|
||||
def pop (xs : Array α) : Array α where
|
||||
toList := xs.toList.dropLast
|
||||
|
||||
@[simp, grind =] theorem size_pop {xs : Array α} : xs.pop.size = xs.size - 1 := by
|
||||
@[simp, grind] theorem size_pop {xs : Array α} : xs.pop.size = xs.size - 1 := by
|
||||
match xs with
|
||||
| ⟨[]⟩ => rfl
|
||||
| ⟨a::as⟩ => simp [pop, Nat.succ_sub_succ_eq_sub, size]
|
||||
@@ -403,6 +406,10 @@ that requires a proof the array is non-empty.
|
||||
def back? (xs : Array α) : Option α :=
|
||||
xs[xs.size - 1]?
|
||||
|
||||
@[deprecated "Use `a[i]?` instead." (since := "2025-02-12"), expose]
|
||||
def get? (xs : Array α) (i : Nat) : Option α :=
|
||||
if h : i < xs.size then some xs[i] else none
|
||||
|
||||
/--
|
||||
Swaps a new element with the element at the given index.
|
||||
|
||||
@@ -434,7 +441,7 @@ def swapAt! (xs : Array α) (i : Nat) (v : α) : α × Array α :=
|
||||
swapAt xs i v
|
||||
else
|
||||
have : Inhabited (α × Array α) := ⟨(v, xs)⟩
|
||||
panic! String.Internal.append (String.Internal.append "index " (toString i)) " out of bounds"
|
||||
panic! ("index " ++ toString i ++ " out of bounds")
|
||||
|
||||
/--
|
||||
Returns the first `n` elements of an array. The resulting array is produced by repeatedly calling
|
||||
@@ -1017,7 +1024,7 @@ The optional parameters `start` and `stop` control the region of the array to wh
|
||||
applied. Iteration proceeds from `start` (inclusive) to `stop` (exclusive), so `f` is not invoked
|
||||
unless `start < stop`. By default, the entire array is used.
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
protected def forM {α : Type u} {m : Type v → Type w} [Monad m] (f : α → m PUnit) (as : Array α) (start := 0) (stop := as.size) : m PUnit :=
|
||||
as.foldlM (fun _ => f) ⟨⟩ start stop
|
||||
|
||||
@@ -1158,7 +1165,7 @@ Examples:
|
||||
def zipIdx (xs : Array α) (start := 0) : Array (α × Nat) :=
|
||||
xs.mapIdx fun i a => (a, start + i)
|
||||
|
||||
|
||||
@[deprecated zipIdx (since := "2025-01-21")] abbrev zipWithIndex := @zipIdx
|
||||
|
||||
/--
|
||||
Returns the first element of the array for which the predicate `p` returns `true`, or `none` if no
|
||||
@@ -1278,7 +1285,7 @@ def findFinIdx? {α : Type u} (p : α → Bool) (as : Array α) : Option (Fin as
|
||||
decreasing_by simp_wf; decreasing_trivial_pre_omega
|
||||
loop 0
|
||||
|
||||
private theorem findIdx?_loop_eq_map_findFinIdx?_loop_val {xs : Array α} {p : α → Bool} {j} :
|
||||
theorem findIdx?_loop_eq_map_findFinIdx?_loop_val {xs : Array α} {p : α → Bool} {j} :
|
||||
findIdx?.loop p xs j = (findFinIdx?.loop p xs j).map (·.val) := by
|
||||
unfold findIdx?.loop
|
||||
unfold findFinIdx?.loop
|
||||
@@ -1315,7 +1322,8 @@ def idxOfAux [BEq α] (xs : Array α) (v : α) (i : Nat) : Option (Fin xs.size)
|
||||
else none
|
||||
decreasing_by simp_wf; decreasing_trivial_pre_omega
|
||||
|
||||
|
||||
@[deprecated idxOfAux (since := "2025-01-29")]
|
||||
abbrev indexOfAux := @idxOfAux
|
||||
|
||||
/--
|
||||
Returns the index of the first element equal to `a`, or the size of the array if no element is equal
|
||||
@@ -1330,7 +1338,8 @@ Examples:
|
||||
def finIdxOf? [BEq α] (xs : Array α) (v : α) : Option (Fin xs.size) :=
|
||||
idxOfAux xs v 0
|
||||
|
||||
|
||||
@[deprecated "`Array.indexOf?` has been deprecated, use `idxOf?` or `finIdxOf?` instead." (since := "2025-01-29")]
|
||||
abbrev indexOf? := @finIdxOf?
|
||||
|
||||
/--
|
||||
Returns the index of the first element equal to `a`, or the size of the array if no element is equal
|
||||
@@ -1799,6 +1808,7 @@ Examples:
|
||||
* `#["apple", "pear", "orange"].eraseIdxIfInBounds 3 = #["apple", "pear", "orange"]`
|
||||
* `#["apple", "pear", "orange"].eraseIdxIfInBounds 5 = #["apple", "pear", "orange"]`
|
||||
-/
|
||||
@[grind]
|
||||
def eraseIdxIfInBounds (xs : Array α) (i : Nat) : Array α :=
|
||||
if h : i < xs.size then xs.eraseIdx i h else xs
|
||||
|
||||
@@ -1946,16 +1956,16 @@ def isPrefixOf [BEq α] (as bs : Array α) : Bool :=
|
||||
false
|
||||
|
||||
@[semireducible, specialize] -- This is otherwise irreducible because it uses well-founded recursion.
|
||||
def zipWithMAux {m : Type v → Type w} [Monad m] (as : Array α) (bs : Array β) (f : α → β → m γ) (i : Nat) (cs : Array γ) : m (Array γ) := do
|
||||
def zipWithAux (as : Array α) (bs : Array β) (f : α → β → γ) (i : Nat) (cs : Array γ) : Array γ :=
|
||||
if h : i < as.size then
|
||||
let a := as[i]
|
||||
if h : i < bs.size then
|
||||
let b := bs[i]
|
||||
zipWithMAux as bs f (i+1) <| cs.push (← f a b)
|
||||
zipWithAux as bs f (i+1) <| cs.push <| f a b
|
||||
else
|
||||
return cs
|
||||
cs
|
||||
else
|
||||
return cs
|
||||
cs
|
||||
decreasing_by simp_wf; decreasing_trivial_pre_omega
|
||||
|
||||
/--
|
||||
@@ -1969,7 +1979,7 @@ Examples:
|
||||
* `#[x₁, x₂, x₃].zipWith f #[y₁, y₂, y₃, y₄] = #[f x₁ y₁, f x₂ y₂, f x₃ y₃]`
|
||||
-/
|
||||
@[inline] def zipWith (f : α → β → γ) (as : Array α) (bs : Array β) : Array γ :=
|
||||
Id.run (zipWithMAux as bs (pure <| f · ·) 0 #[])
|
||||
zipWithAux as bs f 0 #[]
|
||||
|
||||
/--
|
||||
Combines two arrays into an array of pairs in which the first and second components are the
|
||||
@@ -2006,13 +2016,6 @@ where go (as : Array α) (bs : Array β) (i : Nat) (cs : Array γ) :=
|
||||
termination_by max as.size bs.size - i
|
||||
decreasing_by simp_wf; decreasing_trivial_pre_omega
|
||||
|
||||
/--
|
||||
Applies a monadic function to the corresponding elements of two arrays, left-to-right, stopping at
|
||||
the end of the shorter array. `zipWithM f as bs` is equivalent to `mapM id (zipWith f as bs)`.
|
||||
-/
|
||||
@[inline] def zipWithM {m : Type v → Type w} [Monad m] (f : α → β → m γ) (as : Array α) (bs : Array β) : m (Array γ) :=
|
||||
zipWithMAux as bs f 0 #[]
|
||||
|
||||
/--
|
||||
Separates an array of pairs into two arrays that contain the respective first and second components.
|
||||
|
||||
@@ -2159,7 +2162,7 @@ instance {α : Type u} [Repr α] : Repr (Array α) where
|
||||
reprPrec xs _ := Array.repr xs
|
||||
|
||||
instance [ToString α] : ToString (Array α) where
|
||||
toString xs := String.Internal.append "#" (toString xs.toList)
|
||||
toString xs := "#" ++ toString xs.toList
|
||||
|
||||
end Array
|
||||
|
||||
|
||||
@@ -6,8 +6,7 @@ Authors: Leonardo de Moura
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Nat.Linear
|
||||
public import Init.NotationExtra
|
||||
|
||||
|
||||
@@ -8,8 +8,7 @@ module
|
||||
|
||||
prelude
|
||||
public import Init.Data.List.TakeDrop
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import all Init.Data.Array.Basic
|
||||
|
||||
public section
|
||||
|
||||
@@ -24,6 +23,29 @@ set_option linter.indexVariables true -- Enforce naming conventions for index va
|
||||
|
||||
namespace Array
|
||||
|
||||
/--
|
||||
Use the indexing notation `a[i]` instead.
|
||||
|
||||
Access an element from an array without needing a runtime bounds checks,
|
||||
using a `Nat` index and a proof that it is in bounds.
|
||||
|
||||
This function does not use `get_elem_tactic` to automatically find the proof that
|
||||
the index is in bounds. This is because the tactic itself needs to look up values in
|
||||
arrays.
|
||||
-/
|
||||
@[deprecated "Use indexing notation `as[i]` instead" (since := "2025-02-17")]
|
||||
def get {α : Type u} (a : @& Array α) (i : @& Nat) (h : LT.lt i a.size) : α :=
|
||||
a.toList.get ⟨i, h⟩
|
||||
|
||||
/--
|
||||
Use the indexing notation `a[i]!` instead.
|
||||
|
||||
Access an element from an array, or panic if the index is out of bounds.
|
||||
-/
|
||||
@[deprecated "Use indexing notation `as[i]!` instead" (since := "2025-02-17"), expose]
|
||||
def get! {α : Type u} [Inhabited α] (a : @& Array α) (i : @& Nat) : α :=
|
||||
Array.getD a i default
|
||||
|
||||
theorem foldlM_toList.aux [Monad m]
|
||||
{f : β → α → m β} {xs : Array α} {i j} (H : xs.size ≤ i + j) {b} :
|
||||
foldlM.loop f xs xs.size (Nat.le_refl _) i j b = (xs.toList.drop j).foldlM f b := by
|
||||
@@ -85,6 +107,9 @@ abbrev push_toList := @toList_push
|
||||
|
||||
@[simp, grind =] theorem toList_pop {xs : Array α} : xs.pop.toList = xs.toList.dropLast := rfl
|
||||
|
||||
@[deprecated toList_pop (since := "2025-02-17")]
|
||||
abbrev pop_toList := @Array.toList_pop
|
||||
|
||||
@[simp] theorem append_eq_append {xs ys : Array α} : xs.append ys = xs ++ ys := rfl
|
||||
|
||||
@[simp, grind =] theorem toList_append {xs ys : Array α} :
|
||||
@@ -98,9 +123,15 @@ abbrev push_toList := @toList_push
|
||||
@[simp, grind =] theorem append_empty {xs : Array α} : xs ++ #[] = xs := by
|
||||
apply ext'; simp only [toList_append, List.append_nil]
|
||||
|
||||
@[deprecated append_empty (since := "2025-01-13")]
|
||||
abbrev append_nil := @append_empty
|
||||
|
||||
@[simp, grind =] theorem empty_append {xs : Array α} : #[] ++ xs = xs := by
|
||||
apply ext'; simp only [toList_append, List.nil_append]
|
||||
|
||||
@[deprecated empty_append (since := "2025-01-13")]
|
||||
abbrev nil_append := @empty_append
|
||||
|
||||
@[simp, grind _=_] theorem append_assoc {xs ys zs : Array α} : xs ++ ys ++ zs = xs ++ (ys ++ zs) := by
|
||||
apply ext'; simp only [toList_append, List.append_assoc]
|
||||
|
||||
@@ -111,6 +142,7 @@ abbrev push_toList := @toList_push
|
||||
rw [← appendList_eq_append]; unfold Array.appendList
|
||||
induction l generalizing xs <;> simp [*]
|
||||
|
||||
|
||||
@[deprecated toList_appendList (since := "2024-12-11")]
|
||||
abbrev appendList_toList := @toList_appendList
|
||||
|
||||
end Array
|
||||
|
||||
@@ -6,8 +6,7 @@ Authors: Kim Morrison
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.List.Nat.Count
|
||||
|
||||
@@ -63,7 +62,7 @@ theorem size_eq_countP_add_countP {xs : Array α} : xs.size = countP p xs + coun
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.length_eq_countP_add_countP (p := p)]
|
||||
|
||||
@[grind =]
|
||||
@[grind _=_]
|
||||
theorem countP_eq_size_filter {xs : Array α} : countP p xs = (filter p xs).size := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.countP_eq_length_filter]
|
||||
|
||||
@@ -6,8 +6,7 @@ Authors: Leonardo de Moura
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.BEq
|
||||
public import Init.Data.List.Nat.BEq
|
||||
public import Init.ByCases
|
||||
|
||||
@@ -6,8 +6,7 @@ Authors: Kim Morrison
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.List.Nat.Erase
|
||||
public import Init.Data.List.Nat.Basic
|
||||
@@ -91,7 +90,7 @@ theorem mem_of_mem_eraseP {xs : Array α} : a ∈ xs.eraseP p → a ∈ xs := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simpa using List.mem_of_mem_eraseP
|
||||
|
||||
@[simp, grind =] theorem mem_eraseP_of_neg {xs : Array α} (pa : ¬p a) : a ∈ xs.eraseP p ↔ a ∈ xs := by
|
||||
@[simp, grind] theorem mem_eraseP_of_neg {xs : Array α} (pa : ¬p a) : a ∈ xs.eraseP p ↔ a ∈ xs := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simpa using List.mem_eraseP_of_neg pa
|
||||
|
||||
@@ -240,7 +239,7 @@ theorem mem_of_mem_erase {a b : α} {xs : Array α} (h : a ∈ xs.erase b) : a
|
||||
rcases xs with ⟨xs⟩
|
||||
simpa using List.mem_of_mem_erase (by simpa using h)
|
||||
|
||||
@[simp, grind =] theorem mem_erase_of_ne [LawfulBEq α] {a b : α} {xs : Array α} (ab : a ≠ b) :
|
||||
@[simp, grind] theorem mem_erase_of_ne [LawfulBEq α] {a b : α} {xs : Array α} (ab : a ≠ b) :
|
||||
a ∈ xs.erase b ↔ a ∈ xs :=
|
||||
erase_eq_eraseP b xs ▸ mem_eraseP_of_neg (mt eq_of_beq ab.symm)
|
||||
|
||||
@@ -271,7 +270,7 @@ theorem erase_append [LawfulBEq α] {a : α} {xs ys : Array α} :
|
||||
(xs ++ ys).erase a = if a ∈ xs then xs.erase a ++ ys else xs ++ ys.erase a := by
|
||||
rcases xs with ⟨xs⟩
|
||||
rcases ys with ⟨ys⟩
|
||||
simp only [List.append_toArray, List.erase_toArray, List.erase_append, List.mem_toArray]
|
||||
simp only [List.append_toArray, List.erase_toArray, List.erase_append, mem_toArray]
|
||||
split <;> simp
|
||||
|
||||
@[grind =]
|
||||
@@ -324,13 +323,6 @@ abbrev erase_mkArray_ne := @erase_replicate_ne
|
||||
|
||||
end erase
|
||||
|
||||
/-! ### eraseIdxIfInBounds -/
|
||||
|
||||
@[grind =]
|
||||
theorem eraseIdxIfInBounds_eq {xs : Array α} {i : Nat} :
|
||||
xs.eraseIdxIfInBounds i = if h : i < xs.size then xs.eraseIdx i else xs := by
|
||||
simp [eraseIdxIfInBounds]
|
||||
|
||||
/-! ### eraseIdx -/
|
||||
|
||||
theorem eraseIdx_eq_eraseIdxIfInBounds {xs : Array α} {i : Nat} (h : i < xs.size) :
|
||||
@@ -390,12 +382,11 @@ theorem eraseIdx_ne_empty_iff {xs : Array α} {i : Nat} {h} : xs.eraseIdx i ≠
|
||||
simp [h]
|
||||
· simp
|
||||
|
||||
@[grind →]
|
||||
theorem mem_of_mem_eraseIdx {xs : Array α} {i : Nat} {h} {a : α} (h : a ∈ xs.eraseIdx i) : a ∈ xs := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simpa using List.mem_of_mem_eraseIdx (by simpa using h)
|
||||
|
||||
grind_pattern mem_of_mem_eraseIdx => a ∈ xs.eraseIdx i
|
||||
|
||||
theorem eraseIdx_append_of_lt_size {xs : Array α} {k : Nat} (hk : k < xs.size) (ys : Array α) (h) :
|
||||
eraseIdx (xs ++ ys) k = eraseIdx xs k ++ ys := by
|
||||
rcases xs with ⟨l⟩
|
||||
|
||||
@@ -7,8 +7,7 @@ module
|
||||
|
||||
prelude
|
||||
public import Init.Data.List.Nat.Find
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.Array.Attach
|
||||
public import Init.Data.Array.Range
|
||||
@@ -27,11 +26,11 @@ open Nat
|
||||
|
||||
/-! ### findSome? -/
|
||||
|
||||
@[simp, grind =] theorem findSome?_empty : (#[] : Array α).findSome? f = none := rfl
|
||||
@[simp, grind =] theorem findSome?_push {xs : Array α} : (xs.push a).findSome? f = (xs.findSome? f).or (f a) := by
|
||||
@[simp, grind] theorem findSome?_empty : (#[] : Array α).findSome? f = none := rfl
|
||||
@[simp, grind] theorem findSome?_push {xs : Array α} : (xs.push a).findSome? f = (xs.findSome? f).or (f a) := by
|
||||
cases xs; simp [List.findSome?_append]
|
||||
|
||||
@[grind =]
|
||||
@[grind]
|
||||
theorem findSome?_singleton {a : α} {f : α → Option β} : #[a].findSome? f = f a := by
|
||||
simp
|
||||
|
||||
@@ -228,12 +227,11 @@ theorem mem_of_find?_eq_some {xs : Array α} (h : find? p xs = some a) : a ∈ x
|
||||
simp at h
|
||||
simpa using List.mem_of_find?_eq_some h
|
||||
|
||||
@[grind]
|
||||
theorem get_find?_mem {xs : Array α} (h) : (xs.find? p).get h ∈ xs := by
|
||||
cases xs
|
||||
simp [List.get_find?_mem]
|
||||
|
||||
grind_pattern get_find?_mem => (xs.find? p).get h
|
||||
|
||||
@[simp, grind =] theorem find?_filter {xs : Array α} (p q : α → Bool) :
|
||||
(xs.filter p).find? q = xs.find? (fun a => p a ∧ q a) := by
|
||||
cases xs; simp
|
||||
@@ -278,6 +276,9 @@ theorem find?_flatten_eq_none_iff {xss : Array (Array α)} {p : α → Bool} :
|
||||
xss.flatten.find? p = none ↔ ∀ ys ∈ xss, ∀ x ∈ ys, !p x := by
|
||||
simp
|
||||
|
||||
@[deprecated find?_flatten_eq_none_iff (since := "2025-02-03")]
|
||||
abbrev find?_flatten_eq_none := @find?_flatten_eq_none_iff
|
||||
|
||||
/--
|
||||
If `find? p` returns `some a` from `xs.flatten`, then `p a` holds, and
|
||||
some array in `xs` contains `a`, and no earlier element of that array satisfies `p`.
|
||||
@@ -303,6 +304,9 @@ theorem find?_flatten_eq_some_iff {xss : Array (Array α)} {p : α → Bool} {a
|
||||
⟨zs.toList, bs.toList.map Array.toList, by simpa using h⟩,
|
||||
by simpa using h₁, by simpa using h₂⟩
|
||||
|
||||
@[deprecated find?_flatten_eq_some_iff (since := "2025-02-03")]
|
||||
abbrev find?_flatten_eq_some := @find?_flatten_eq_some_iff
|
||||
|
||||
@[simp, grind =] theorem find?_flatMap {xs : Array α} {f : α → Array β} {p : β → Bool} :
|
||||
(xs.flatMap f).find? p = xs.findSome? (fun x => (f x).find? p) := by
|
||||
cases xs
|
||||
@@ -312,11 +316,17 @@ theorem find?_flatMap_eq_none_iff {xs : Array α} {f : α → Array β} {p : β
|
||||
(xs.flatMap f).find? p = none ↔ ∀ x ∈ xs, ∀ y ∈ f x, !p y := by
|
||||
simp
|
||||
|
||||
@[deprecated find?_flatMap_eq_none_iff (since := "2025-02-03")]
|
||||
abbrev find?_flatMap_eq_none := @find?_flatMap_eq_none_iff
|
||||
|
||||
@[grind =]
|
||||
theorem find?_replicate :
|
||||
find? p (replicate n a) = if n = 0 then none else if p a then some a else none := by
|
||||
simp [← List.toArray_replicate, List.find?_replicate]
|
||||
|
||||
@[deprecated find?_replicate (since := "2025-03-18")]
|
||||
abbrev find?_mkArray := @find?_replicate
|
||||
|
||||
@[simp] theorem find?_replicate_of_size_pos (h : 0 < n) :
|
||||
find? p (replicate n a) = if p a then some a else none := by
|
||||
simp [find?_replicate, Nat.ne_of_gt h]
|
||||
@@ -334,19 +344,34 @@ abbrev find?_mkArray_of_pos := @find?_replicate_of_pos
|
||||
@[simp] theorem find?_replicate_of_neg (h : ¬ p a) : find? p (replicate n a) = none := by
|
||||
simp [find?_replicate, h]
|
||||
|
||||
@[deprecated find?_replicate_of_neg (since := "2025-03-18")]
|
||||
abbrev find?_mkArray_of_neg := @find?_replicate_of_neg
|
||||
|
||||
-- This isn't a `@[simp]` lemma since there is already a lemma for `l.find? p = none` for any `l`.
|
||||
theorem find?_replicate_eq_none_iff {n : Nat} {a : α} {p : α → Bool} :
|
||||
(replicate n a).find? p = none ↔ n = 0 ∨ !p a := by
|
||||
simp [← List.toArray_replicate, Classical.or_iff_not_imp_left]
|
||||
|
||||
@[deprecated find?_replicate_eq_none_iff (since := "2025-03-18")]
|
||||
abbrev find?_mkArray_eq_none_iff := @find?_replicate_eq_none_iff
|
||||
|
||||
@[simp] theorem find?_replicate_eq_some_iff {n : Nat} {a b : α} {p : α → Bool} :
|
||||
(replicate n a).find? p = some b ↔ n ≠ 0 ∧ p a ∧ a = b := by
|
||||
simp [← List.toArray_replicate]
|
||||
|
||||
@[deprecated find?_replicate_eq_some_iff (since := "2025-03-18")]
|
||||
abbrev find?_mkArray_eq_some_iff := @find?_replicate_eq_some_iff
|
||||
|
||||
@[deprecated find?_replicate_eq_some_iff (since := "2025-02-03")]
|
||||
abbrev find?_mkArray_eq_some := @find?_replicate_eq_some_iff
|
||||
|
||||
@[simp] theorem get_find?_replicate {n : Nat} {a : α} {p : α → Bool} (h) :
|
||||
((replicate n a).find? p).get h = a := by
|
||||
simp [← List.toArray_replicate]
|
||||
|
||||
@[deprecated get_find?_replicate (since := "2025-03-18")]
|
||||
abbrev get_find?_mkArray := @get_find?_replicate
|
||||
|
||||
@[grind =]
|
||||
theorem find?_pmap {P : α → Prop} {f : (a : α) → P a → β} {xs : Array α}
|
||||
(H : ∀ (a : α), a ∈ xs → P a) {p : β → Bool} :
|
||||
@@ -362,13 +387,14 @@ theorem find?_eq_some_iff_getElem {xs : Array α} {p : α → Bool} {b : α} :
|
||||
/-! ### findIdx -/
|
||||
|
||||
@[grind =]
|
||||
theorem findIdx_empty : findIdx p #[] = 0 := by simp
|
||||
theorem findIdx_empty : findIdx p #[] = 0 := rfl
|
||||
|
||||
@[grind =]
|
||||
theorem findIdx_singleton {a : α} {p : α → Bool} :
|
||||
#[a].findIdx p = if p a then 0 else 1 := by
|
||||
simp
|
||||
|
||||
@[grind →]
|
||||
theorem findIdx_of_getElem?_eq_some {xs : Array α} (w : xs[xs.findIdx p]? = some y) : p y := by
|
||||
rcases xs with ⟨xs⟩
|
||||
exact List.findIdx_of_getElem?_eq_some (by simpa using w)
|
||||
@@ -701,7 +727,7 @@ theorem isNone_findFinIdx? {xs : Array α} {p : α → Bool} :
|
||||
cases xs
|
||||
simp only [List.findFinIdx?_toArray, hf, List.findFinIdx?_subtype]
|
||||
rw [findFinIdx?_congr List.unattach_toArray]
|
||||
simp only [Option.map_map, Function.comp_def, Fin.cast_cast]
|
||||
simp only [Option.map_map, Function.comp_def, Fin.cast_trans]
|
||||
simp [Array.size]
|
||||
|
||||
/-! ### idxOf
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,3 +8,5 @@ module
|
||||
prelude
|
||||
public import Init.Data.Array.Lex.Basic
|
||||
public import Init.Data.Array.Lex.Lemmas
|
||||
|
||||
public section
|
||||
|
||||
@@ -6,12 +6,9 @@ Author: Kim Morrison
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Init.Core
|
||||
import Init.Data.Array.Basic
|
||||
import Init.Data.Nat.Lemmas
|
||||
public import Init.Data.Range.Polymorphic.Iterators
|
||||
public import Init.Data.Range.Polymorphic.Nat
|
||||
import Init.Data.Iterators.Consumers
|
||||
public import Init.Data.Array.Basic
|
||||
public import Init.Data.Nat.Lemmas
|
||||
public import Init.Data.Range
|
||||
|
||||
public section
|
||||
|
||||
@@ -29,9 +26,9 @@ Specifically, `Array.lex as bs lt` is true if
|
||||
* there is an index `i` such that `lt as[i] bs[i]`, and for all `j < i`, `as[j] == bs[j]`.
|
||||
-/
|
||||
def lex [BEq α] (as bs : Array α) (lt : α → α → Bool := by exact (· < ·)) : Bool := Id.run do
|
||||
for h : i in 0...(min as.size bs.size) do
|
||||
-- TODO: `get_elem_tactic` should be able to find this itself.
|
||||
have : i < min as.size bs.size := Std.Rco.lt_upper_of_mem h
|
||||
for h : i in [0 : min as.size bs.size] do
|
||||
-- TODO: `omega` should be able to find this itself.
|
||||
have : i < min as.size bs.size := Membership.get_elem_helper h rfl
|
||||
if lt as[i] bs[i] then
|
||||
return true
|
||||
else if as[i] != bs[i] then
|
||||
|
||||
@@ -6,18 +6,12 @@ Author: Kim Morrison
|
||||
module
|
||||
|
||||
prelude
|
||||
import all Init.Data.Array.Lex.Basic
|
||||
public import Init.Data.Array.Lex.Basic
|
||||
public import all Init.Data.Array.Lex.Basic
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.List.Lex
|
||||
import Init.Data.Range.Polymorphic.Lemmas
|
||||
import Init.Data.Range.Polymorphic.NatLemmas
|
||||
import Init.Data.Order.Lemmas
|
||||
|
||||
public section
|
||||
|
||||
open Std
|
||||
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
@@ -25,54 +19,28 @@ namespace Array
|
||||
|
||||
/-! ### Lexicographic ordering -/
|
||||
|
||||
@[simp] theorem _root_.List.lt_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray < l₂.toArray ↔ l₁ < l₂ := Iff.rfl
|
||||
@[simp] theorem _root_.List.le_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray ≤ l₂.toArray ↔ l₁ ≤ l₂ := Iff.rfl
|
||||
@[simp, grind =] theorem _root_.List.lt_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray < l₂.toArray ↔ l₁ < l₂ := Iff.rfl
|
||||
@[simp, grind =] theorem _root_.List.le_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray ≤ l₂.toArray ↔ l₁ ≤ l₂ := Iff.rfl
|
||||
|
||||
@[simp] theorem lt_toList [LT α] {xs ys : Array α} : xs.toList < ys.toList ↔ xs < ys := Iff.rfl
|
||||
@[simp] theorem le_toList [LT α] {xs ys : Array α} : xs.toList ≤ ys.toList ↔ xs ≤ ys := Iff.rfl
|
||||
|
||||
grind_pattern _root_.List.lt_toArray => l₁.toArray < l₂.toArray
|
||||
grind_pattern _root_.List.le_toArray => l₁.toArray ≤ l₂.toArray
|
||||
grind_pattern lt_toList => xs.toList < ys.toList
|
||||
grind_pattern le_toList => xs.toList ≤ ys.toList
|
||||
@[simp, grind =] theorem lt_toList [LT α] {xs ys : Array α} : xs.toList < ys.toList ↔ xs < ys := Iff.rfl
|
||||
@[simp, grind =] theorem le_toList [LT α] {xs ys : Array α} : xs.toList ≤ ys.toList ↔ xs ≤ ys := Iff.rfl
|
||||
|
||||
protected theorem not_lt_iff_ge [LT α] {xs ys : Array α} : ¬ xs < ys ↔ ys ≤ xs := Iff.rfl
|
||||
protected theorem not_le_iff_gt [LT α] {xs ys : Array α} :
|
||||
protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {xs ys : Array α} :
|
||||
¬ xs ≤ ys ↔ ys < xs :=
|
||||
Classical.not_not
|
||||
Decidable.not_not
|
||||
|
||||
@[simp] theorem lex_empty [BEq α] {lt : α → α → Bool} {xs : Array α} : xs.lex #[] lt = false := by
|
||||
simp [lex, Std.Rco.forIn'_eq_if]
|
||||
|
||||
private theorem cons_lex_cons.forIn'_congr_aux [Monad m] {as bs : ρ} {_ : Membership α ρ}
|
||||
[ForIn' m ρ α inferInstance] (w : as = bs)
|
||||
{b b' : β} (hb : b = b')
|
||||
{f : (a' : α) → a' ∈ as → β → m (ForInStep β)}
|
||||
{g : (a' : α) → a' ∈ bs → β → m (ForInStep β)}
|
||||
(h : ∀ a m b, f a (by simpa [w] using m) b = g a m b) :
|
||||
forIn' as b f = forIn' bs b' g := by
|
||||
cases hb
|
||||
cases w
|
||||
have : f = g := by
|
||||
ext a ha acc
|
||||
apply h
|
||||
cases this
|
||||
rfl
|
||||
simp [lex]
|
||||
|
||||
private theorem cons_lex_cons [BEq α] {lt : α → α → Bool} {a b : α} {xs ys : Array α} :
|
||||
(#[a] ++ xs).lex (#[b] ++ ys) lt =
|
||||
(lt a b || a == b && xs.lex ys lt) := by
|
||||
simp only [lex, size_append, List.size_toArray, List.length_cons, List.length_nil, Nat.zero_add,
|
||||
Nat.add_min_add_left, Nat.add_lt_add_iff_left, Std.Rco.forIn'_eq_forIn'_toList]
|
||||
conv =>
|
||||
lhs; congr; congr
|
||||
rw [cons_lex_cons.forIn'_congr_aux Std.Rco.toList_eq_if rfl (fun _ _ _ => rfl)]
|
||||
simp only [bind_pure_comp, map_pure]
|
||||
rw [cons_lex_cons.forIn'_congr_aux (if_pos (by omega)) rfl (fun _ _ _ => rfl)]
|
||||
simp only [Std.toList_Roo_eq_toList_Rco_of_isSome_succ? (lo := 0) (h := rfl),
|
||||
Std.PRange.UpwardEnumerable.succ?, Nat.add_comm 1, Std.PRange.Nat.toList_Rco_succ_succ,
|
||||
Option.get_some, List.forIn'_cons, List.size_toArray, List.length_cons, List.length_nil,
|
||||
Nat.lt_add_one, getElem_append_left, List.getElem_toArray, List.getElem_cons_zero]
|
||||
simp only [lex]
|
||||
simp only [Std.Range.forIn'_eq_forIn'_range', size_append, List.size_toArray, List.length_singleton,
|
||||
Nat.add_comm 1]
|
||||
simp [Nat.add_min_add_right, List.range'_succ, getElem_append_left, List.range'_succ_left,
|
||||
getElem_append_right]
|
||||
cases lt a b
|
||||
· rw [bne]
|
||||
cases a == b <;> simp
|
||||
@@ -81,11 +49,10 @@ private theorem cons_lex_cons [BEq α] {lt : α → α → Bool} {a b : α} {xs
|
||||
@[simp, grind =] theorem _root_.List.lex_toArray [BEq α] {lt : α → α → Bool} {l₁ l₂ : List α} :
|
||||
l₁.toArray.lex l₂.toArray lt = l₁.lex l₂ lt := by
|
||||
induction l₁ generalizing l₂ with
|
||||
| nil =>
|
||||
cases l₂ <;> simp [lex, Std.Rco.forIn'_eq_if]
|
||||
| nil => cases l₂ <;> simp [lex]
|
||||
| cons x l₁ ih =>
|
||||
cases l₂ with
|
||||
| nil => simp [lex, Std.Rco.forIn'_eq_if]
|
||||
| nil => simp [lex]
|
||||
| cons y l₂ =>
|
||||
rw [List.toArray_cons, List.toArray_cons y, cons_lex_cons, List.lex, ih]
|
||||
|
||||
@@ -96,14 +63,6 @@ theorem singleton_lex_singleton [BEq α] {lt : α → α → Bool} : #[a].lex #[
|
||||
xs.toList.lex ys.toList lt = xs.lex ys lt := by
|
||||
cases xs <;> cases ys <;> simp
|
||||
|
||||
instance [LT α] [LE α] [LawfulOrderLT α] [IsLinearOrder α] : IsLinearOrder (Array α) := by
|
||||
apply IsLinearOrder.of_le
|
||||
· constructor
|
||||
intro _ _ hab hba
|
||||
simpa using Std.le_antisymm (α := List α) hab hba
|
||||
· constructor; exact Std.le_trans (α := List α)
|
||||
· constructor; exact fun _ _ => Std.le_total (α := List α)
|
||||
|
||||
protected theorem lt_irrefl [LT α] [Std.Irrefl (· < · : α → α → Prop)] (xs : Array α) : ¬ xs < xs :=
|
||||
List.lt_irrefl xs.toList
|
||||
|
||||
@@ -135,35 +94,27 @@ instance [LT α] [Trans (· < · : α → α → Prop) (· < ·) (· < ·)] :
|
||||
Trans (· < · : Array α → Array α → Prop) (· < ·) (· < ·) where
|
||||
trans h₁ h₂ := Array.lt_trans h₁ h₂
|
||||
|
||||
protected theorem lt_of_le_of_lt [LE α] [LT α] [LawfulOrderLT α] [IsLinearOrder α]
|
||||
{xs ys zs : Array α} (h₁ : xs ≤ ys) (h₂ : ys < zs) : xs < zs :=
|
||||
Std.lt_of_le_of_lt (α := List α) h₁ h₂
|
||||
|
||||
@[deprecated Array.lt_of_le_of_lt (since := "2025-08-01")]
|
||||
protected theorem lt_of_le_of_lt' [LT α]
|
||||
protected theorem lt_of_le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
|
||||
[i₀ : Std.Irrefl (· < · : α → α → Prop)]
|
||||
[i₁ : Std.Asymm (· < · : α → α → Prop)]
|
||||
[i₂ : Std.Antisymm (¬ · < · : α → α → Prop)]
|
||||
[i₃ : Trans (¬ · < · : α → α → Prop) (¬ · < ·) (¬ · < ·)]
|
||||
{xs ys zs : Array α} (h₁ : xs ≤ ys) (h₂ : ys < zs) : xs < zs :=
|
||||
letI := LE.ofLT α
|
||||
haveI : IsLinearOrder α := IsLinearOrder.of_lt
|
||||
Array.lt_of_le_of_lt h₁ h₂
|
||||
List.lt_of_le_of_lt h₁ h₂
|
||||
|
||||
protected theorem le_trans [LE α] [LT α] [LawfulOrderLT α] [IsLinearOrder α]
|
||||
protected theorem le_trans [DecidableEq α] [LT α] [DecidableLT α]
|
||||
[Std.Irrefl (· < · : α → α → Prop)]
|
||||
[Std.Asymm (· < · : α → α → Prop)]
|
||||
[Std.Antisymm (¬ · < · : α → α → Prop)]
|
||||
[Trans (¬ · < · : α → α → Prop) (¬ · < ·) (¬ · < ·)]
|
||||
{xs ys zs : Array α} (h₁ : xs ≤ ys) (h₂ : ys ≤ zs) : xs ≤ zs :=
|
||||
fun h₃ => h₁ (Array.lt_of_le_of_lt h₂ h₃)
|
||||
|
||||
@[deprecated Array.le_trans (since := "2025-08-01")]
|
||||
protected theorem le_trans' [LT α]
|
||||
[i₁ : Std.Asymm (· < · : α → α → Prop)]
|
||||
[i₂ : Std.Antisymm (¬ · < · : α → α → Prop)]
|
||||
[i₃ : Trans (¬ · < · : α → α → Prop) (¬ · < ·) (¬ · < ·)]
|
||||
{xs ys zs : Array α} (h₁ : xs ≤ ys) (h₂ : ys ≤ zs) : xs ≤ zs :=
|
||||
letI := LE.ofLT α
|
||||
haveI : IsLinearOrder α := IsLinearOrder.of_lt
|
||||
Array.le_trans h₁ h₂
|
||||
|
||||
instance [LE α] [LT α] [LawfulOrderLT α] [IsLinearOrder α] :
|
||||
instance [DecidableEq α] [LT α] [DecidableLT α]
|
||||
[Std.Irrefl (· < · : α → α → Prop)]
|
||||
[Std.Asymm (· < · : α → α → Prop)]
|
||||
[Std.Antisymm (¬ · < · : α → α → Prop)]
|
||||
[Trans (¬ · < · : α → α → Prop) (¬ · < ·) (¬ · < ·)] :
|
||||
Trans (· ≤ · : Array α → Array α → Prop) (· ≤ ·) (· ≤ ·) where
|
||||
trans h₁ h₂ := Array.le_trans h₁ h₂
|
||||
|
||||
@@ -171,38 +122,35 @@ protected theorem lt_asymm [LT α]
|
||||
[i : Std.Asymm (· < · : α → α → Prop)]
|
||||
{xs ys : Array α} (h : xs < ys) : ¬ ys < xs := List.lt_asymm h
|
||||
|
||||
instance [LT α]
|
||||
instance [DecidableEq α] [LT α] [DecidableLT α]
|
||||
[Std.Asymm (· < · : α → α → Prop)] :
|
||||
Std.Asymm (· < · : Array α → Array α → Prop) where
|
||||
asymm _ _ := Array.lt_asymm
|
||||
|
||||
protected theorem le_total [LT α]
|
||||
[i : Std.Asymm (· < · : α → α → Prop)] (xs ys : Array α) : xs ≤ ys ∨ ys ≤ xs :=
|
||||
protected theorem le_total [DecidableEq α] [LT α] [DecidableLT α]
|
||||
[i : Std.Total (¬ · < · : α → α → Prop)] (xs ys : Array α) : xs ≤ ys ∨ ys ≤ xs :=
|
||||
List.le_total xs.toList ys.toList
|
||||
|
||||
@[simp] protected theorem not_lt [LT α]
|
||||
{xs ys : Array α} : ¬ xs < ys ↔ ys ≤ xs := Iff.rfl
|
||||
|
||||
@[simp] protected theorem not_le [LT α]
|
||||
{xs ys : Array α} : ¬ ys ≤ xs ↔ xs < ys := Classical.not_not
|
||||
@[simp] protected theorem not_le [DecidableEq α] [LT α] [DecidableLT α]
|
||||
{xs ys : Array α} : ¬ ys ≤ xs ↔ xs < ys := Decidable.not_not
|
||||
|
||||
protected theorem le_of_lt [LT α]
|
||||
[i : Std.Asymm (· < · : α → α → Prop)]
|
||||
protected theorem le_of_lt [DecidableEq α] [LT α] [DecidableLT α]
|
||||
[i : Std.Total (¬ · < · : α → α → Prop)]
|
||||
{xs ys : Array α} (h : xs < ys) : xs ≤ ys :=
|
||||
List.le_of_lt h
|
||||
|
||||
protected theorem le_iff_lt_or_eq [LT α]
|
||||
protected theorem le_iff_lt_or_eq [DecidableEq α] [LT α] [DecidableLT α]
|
||||
[Std.Irrefl (· < · : α → α → Prop)]
|
||||
[Std.Antisymm (¬ · < · : α → α → Prop)]
|
||||
[Std.Asymm (· < · : α → α → Prop)]
|
||||
[Std.Total (¬ · < · : α → α → Prop)]
|
||||
{xs ys : Array α} : xs ≤ ys ↔ xs < ys ∨ xs = ys := by
|
||||
simpa using List.le_iff_lt_or_eq (l₁ := xs.toList) (l₂ := ys.toList)
|
||||
|
||||
protected theorem le_antisymm [LT α] [LE α] [IsLinearOrder α] [LawfulOrderLT α]
|
||||
{xs ys : Array α} : xs ≤ ys → ys ≤ xs → xs = ys := by
|
||||
simpa using List.le_antisymm (as := xs.toList) (bs := ys.toList)
|
||||
|
||||
instance [LT α] [Std.Asymm (· < · : α → α → Prop)] :
|
||||
instance [DecidableEq α] [LT α] [DecidableLT α]
|
||||
[Std.Total (¬ · < · : α → α → Prop)] :
|
||||
Std.Total (· ≤ · : Array α → Array α → Prop) where
|
||||
total := Array.le_total
|
||||
|
||||
@@ -270,7 +218,7 @@ theorem lex_eq_false_iff_exists [BEq α] [PartialEquivBEq α] (lt : α → α
|
||||
cases l₂
|
||||
simp_all [List.lex_eq_false_iff_exists]
|
||||
|
||||
protected theorem lt_iff_exists [LT α] {xs ys : Array α} :
|
||||
protected theorem lt_iff_exists [DecidableEq α] [LT α] [DecidableLT α] {xs ys : Array α} :
|
||||
xs < ys ↔
|
||||
(xs = ys.take xs.size ∧ xs.size < ys.size) ∨
|
||||
(∃ (i : Nat) (h₁ : i < xs.size) (h₂ : i < ys.size),
|
||||
@@ -280,7 +228,8 @@ protected theorem lt_iff_exists [LT α] {xs ys : Array α} :
|
||||
cases ys
|
||||
simp [List.lt_iff_exists]
|
||||
|
||||
protected theorem le_iff_exists [LT α]
|
||||
protected theorem le_iff_exists [DecidableEq α] [LT α] [DecidableLT α]
|
||||
[Std.Irrefl (· < · : α → α → Prop)]
|
||||
[Std.Asymm (· < · : α → α → Prop)]
|
||||
[Std.Antisymm (¬ · < · : α → α → Prop)] {xs ys : Array α} :
|
||||
xs ≤ ys ↔
|
||||
@@ -299,7 +248,8 @@ theorem append_left_lt [LT α] {xs ys zs : Array α} (h : ys < zs) :
|
||||
cases zs
|
||||
simpa using List.append_left_lt h
|
||||
|
||||
theorem append_left_le [LT α]
|
||||
theorem append_left_le [DecidableEq α] [LT α] [DecidableLT α]
|
||||
[Std.Irrefl (· < · : α → α → Prop)]
|
||||
[Std.Asymm (· < · : α → α → Prop)]
|
||||
[Std.Antisymm (¬ · < · : α → α → Prop)]
|
||||
{xs ys zs : Array α} (h : ys ≤ zs) :
|
||||
@@ -322,9 +272,11 @@ protected theorem map_lt [LT α] [LT β]
|
||||
cases ys
|
||||
simpa using List.map_lt w h
|
||||
|
||||
protected theorem map_le [LT α] [LT β]
|
||||
protected theorem map_le [DecidableEq α] [LT α] [DecidableLT α] [DecidableEq β] [LT β] [DecidableLT β]
|
||||
[Std.Irrefl (· < · : α → α → Prop)]
|
||||
[Std.Asymm (· < · : α → α → Prop)]
|
||||
[Std.Antisymm (¬ · < · : α → α → Prop)]
|
||||
[Std.Irrefl (· < · : β → β → Prop)]
|
||||
[Std.Asymm (· < · : β → β → Prop)]
|
||||
[Std.Antisymm (¬ · < · : β → β → Prop)]
|
||||
{xs ys : Array α} {f : α → β} (w : ∀ x y, x < y → f x < f y) (h : xs ≤ ys) :
|
||||
|
||||
@@ -6,13 +6,11 @@ Authors: Mario Carneiro, Kim Morrison
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.Array.Attach
|
||||
public import Init.Data.Array.OfFn
|
||||
public import Init.Data.List.MapIdx
|
||||
import all Init.Data.List.MapIdx
|
||||
public import all Init.Data.List.MapIdx
|
||||
|
||||
public section
|
||||
|
||||
@@ -62,7 +60,7 @@ theorem mapFinIdx_spec {xs : Array α} {f : (i : Nat) → α → (h : i < xs.siz
|
||||
@[simp, grind =] theorem size_zipIdx {xs : Array α} {k : Nat} : (xs.zipIdx k).size = xs.size :=
|
||||
Array.size_mapFinIdx
|
||||
|
||||
|
||||
@[deprecated size_zipIdx (since := "2025-01-21")] abbrev size_zipWithIndex := @size_zipIdx
|
||||
|
||||
@[simp, grind =] theorem getElem_mapFinIdx {xs : Array α} {f : (i : Nat) → α → (h : i < xs.size) → β} {i : Nat}
|
||||
(h : i < (xs.mapFinIdx f).size) :
|
||||
@@ -134,20 +132,23 @@ namespace Array
|
||||
(xs.zipIdx k)[i] = (xs[i]'(by simp_all), k + i) := by
|
||||
simp [zipIdx]
|
||||
|
||||
|
||||
@[deprecated getElem_zipIdx (since := "2025-01-21")]
|
||||
abbrev getElem_zipWithIndex := @getElem_zipIdx
|
||||
|
||||
@[simp, grind =] theorem zipIdx_toArray {l : List α} {k : Nat} :
|
||||
l.toArray.zipIdx k = (l.zipIdx k).toArray := by
|
||||
ext i hi₁ hi₂ <;> simp
|
||||
|
||||
|
||||
@[deprecated zipIdx_toArray (since := "2025-01-21")]
|
||||
abbrev zipWithIndex_toArray := @zipIdx_toArray
|
||||
|
||||
@[simp, grind =] theorem toList_zipIdx {xs : Array α} {k : Nat} :
|
||||
(xs.zipIdx k).toList = xs.toList.zipIdx k := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
|
||||
@[deprecated toList_zipIdx (since := "2025-01-21")]
|
||||
abbrev toList_zipWithIndex := @toList_zipIdx
|
||||
|
||||
theorem mk_mem_zipIdx_iff_le_and_getElem?_sub {k i : Nat} {x : α} {xs : Array α} :
|
||||
(x, i) ∈ xs.zipIdx k ↔ k ≤ i ∧ xs[i - k]? = some x := by
|
||||
@@ -172,7 +173,11 @@ theorem mem_zipIdx_iff_getElem? {x : α × Nat} {xs : Array α} :
|
||||
x ∈ xs.zipIdx ↔ xs[x.2]? = some x.1 := by
|
||||
rw [mk_mem_zipIdx_iff_getElem?]
|
||||
|
||||
@[deprecated mk_mem_zipIdx_iff_getElem? (since := "2025-01-21")]
|
||||
abbrev mk_mem_zipWithIndex_iff_getElem? := @mk_mem_zipIdx_iff_getElem?
|
||||
|
||||
@[deprecated mem_zipIdx_iff_getElem? (since := "2025-01-21")]
|
||||
abbrev mem_zipWithIndex_iff_getElem? := @mem_zipIdx_iff_getElem?
|
||||
|
||||
/-! ### mapFinIdx -/
|
||||
|
||||
@@ -217,7 +222,8 @@ theorem mapFinIdx_eq_zipIdx_map {xs : Array α} {f : (i : Nat) → α → (h : i
|
||||
f i x (by simp [mk_mem_zipIdx_iff_getElem?, getElem?_eq_some_iff] at m; exact m.1) := by
|
||||
ext <;> simp
|
||||
|
||||
|
||||
@[deprecated mapFinIdx_eq_zipIdx_map (since := "2025-01-21")]
|
||||
abbrev mapFinIdx_eq_zipWithIndex_map := @mapFinIdx_eq_zipIdx_map
|
||||
|
||||
@[simp]
|
||||
theorem mapFinIdx_eq_empty_iff {xs : Array α} {f : (i : Nat) → α → (h : i < xs.size) → β} :
|
||||
@@ -326,7 +332,8 @@ theorem mapIdx_eq_zipIdx_map {xs : Array α} {f : Nat → α → β} :
|
||||
xs.mapIdx f = xs.zipIdx.map fun ⟨a, i⟩ => f i a := by
|
||||
ext <;> simp
|
||||
|
||||
|
||||
@[deprecated mapIdx_eq_zipIdx_map (since := "2025-01-21")]
|
||||
abbrev mapIdx_eq_zipWithIndex_map := @mapIdx_eq_zipIdx_map
|
||||
|
||||
@[grind =]
|
||||
theorem mapIdx_append {xs ys : Array α} :
|
||||
|
||||
@@ -18,11 +18,11 @@ set_option linter.indexVariables true -- Enforce naming conventions for index va
|
||||
namespace Array
|
||||
|
||||
theorem sizeOf_lt_of_mem [SizeOf α] {as : Array α} (h : a ∈ as) : sizeOf a < sizeOf as := by
|
||||
cases as with | _ as
|
||||
cases as with | _ as =>
|
||||
exact Nat.lt_trans (List.sizeOf_lt_of_mem h.val) (by simp +arith)
|
||||
|
||||
theorem sizeOf_get [SizeOf α] (as : Array α) (i : Nat) (h : i < as.size) : sizeOf as[i] < sizeOf as := by
|
||||
cases as with | _ as
|
||||
cases as with | _ as =>
|
||||
simpa using Nat.lt_trans (List.sizeOf_get _ ⟨i, h⟩) (by simp +arith)
|
||||
|
||||
@[simp] theorem sizeOf_getElem [SizeOf α] (as : Array α) (i : Nat) (h : i < as.size) :
|
||||
|
||||
@@ -6,10 +6,8 @@ Authors: Kim Morrison
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Init.Data.List.Control
|
||||
import all Init.Data.List.Control
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import all Init.Data.List.Control
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.Array.Attach
|
||||
public import Init.Data.List.Monadic
|
||||
@@ -167,7 +165,7 @@ theorem foldrM_filter [Monad m] [LawfulMonad m] {p : α → Bool} {g : α → β
|
||||
(h : ∀ a m b, f a (by simpa [w] using m) b = g a m b) :
|
||||
forIn' as b f = forIn' bs b' g := by
|
||||
cases as <;> cases bs
|
||||
simp only [mk.injEq, List.mem_toArray, List.forIn'_toArray] at w h ⊢
|
||||
simp only [mk.injEq, mem_toArray, List.forIn'_toArray] at w h ⊢
|
||||
exact List.forIn'_congr w hb h
|
||||
|
||||
/--
|
||||
|
||||
@@ -6,8 +6,7 @@ Authors: Kim Morrison
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.Array.Monadic
|
||||
public import Init.Data.List.OfFn
|
||||
|
||||
@@ -7,8 +7,7 @@ module
|
||||
|
||||
prelude
|
||||
public import Init.Data.List.Nat.Perm
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Lemmas
|
||||
|
||||
public section
|
||||
|
||||
@@ -7,3 +7,5 @@ module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Array.QSort.Basic
|
||||
|
||||
public section
|
||||
|
||||
@@ -7,7 +7,7 @@ module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Vector.Basic
|
||||
public import Init.Data.Ord.Basic
|
||||
public import Init.Data.Ord
|
||||
|
||||
public section
|
||||
|
||||
|
||||
@@ -7,10 +7,8 @@ module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.OfFn
|
||||
import all Init.Data.Array.OfFn
|
||||
public import all Init.Data.Array.Basic
|
||||
public import all Init.Data.Array.OfFn
|
||||
public import Init.Data.Array.MapIdx
|
||||
public import Init.Data.Array.Zip
|
||||
public import Init.Data.List.Nat.Range
|
||||
@@ -116,7 +114,7 @@ theorem range'_eq_append_iff : range' s n = xs ++ ys ↔ ∃ k, k ≤ n ∧ xs =
|
||||
@[simp] theorem find?_range'_eq_some {s n : Nat} {i : Nat} {p : Nat → Bool} :
|
||||
(range' s n).find? p = some i ↔ p i ∧ i ∈ range' s n ∧ ∀ j, s ≤ j → j < i → !p j := by
|
||||
rw [← List.toArray_range']
|
||||
simp only [List.find?_toArray, List.mem_toArray]
|
||||
simp only [List.find?_toArray, mem_toArray]
|
||||
simp [List.find?_range'_eq_some]
|
||||
|
||||
@[simp] theorem find?_range'_eq_none {s n : Nat} {p : Nat → Bool} :
|
||||
|
||||
@@ -6,9 +6,7 @@ Authors: Leonardo de Moura
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Init.GetElem
|
||||
public import Init.Data.Array.Basic
|
||||
import Init.Data.Array.GetLit
|
||||
public import Init.Data.Slice.Basic
|
||||
|
||||
public section
|
||||
@@ -161,10 +159,64 @@ instance : EmptyCollection (Subarray α) :=
|
||||
instance : Inhabited (Subarray α) :=
|
||||
⟨{}⟩
|
||||
|
||||
/-!
|
||||
`ForIn`, `foldlM`, `foldl` and other operations are implemented in `Init.Data.Slice.Array.Iterator`
|
||||
using the slice iterator.
|
||||
/--
|
||||
The run-time implementation of `ForIn.forIn` for `Subarray`, which allows it to be used with `for`
|
||||
loops in `do`-notation.
|
||||
|
||||
This definition replaces `Subarray.forIn`.
|
||||
-/
|
||||
@[inline] unsafe def forInUnsafe {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (s : Subarray α) (b : β) (f : α → β → m (ForInStep β)) : m β :=
|
||||
let sz := USize.ofNat s.stop
|
||||
let rec @[specialize] loop (i : USize) (b : β) : m β := do
|
||||
if i < sz then
|
||||
let a := s.array.uget i lcProof
|
||||
match (← f a b) with
|
||||
| ForInStep.done b => pure b
|
||||
| ForInStep.yield b => loop (i+1) b
|
||||
else
|
||||
pure b
|
||||
loop (USize.ofNat s.start) b
|
||||
|
||||
/--
|
||||
The implementation of `ForIn.forIn` for `Subarray`, which allows it to be used with `for` loops in
|
||||
`do`-notation.
|
||||
-/
|
||||
-- TODO: provide reference implementation
|
||||
@[implemented_by Subarray.forInUnsafe]
|
||||
protected opaque forIn {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (s : Subarray α) (b : β) (f : α → β → m (ForInStep β)) : m β :=
|
||||
pure b
|
||||
|
||||
instance : ForIn m (Subarray α) α where
|
||||
forIn := Subarray.forIn
|
||||
|
||||
/--
|
||||
Folds a monadic operation from left to right over the elements in a subarray.
|
||||
|
||||
An accumulator of type `β` is constructed by starting with `init` and monadically combining each
|
||||
element of the subarray with the current accumulator value in turn. The monad in question may permit
|
||||
early termination or repetition.
|
||||
|
||||
Examples:
|
||||
```lean example
|
||||
#eval #["red", "green", "blue"].toSubarray.foldlM (init := "") fun acc x => do
|
||||
let l ← Option.guard (· ≠ 0) x.length
|
||||
return s!"{acc}({l}){x} "
|
||||
```
|
||||
```output
|
||||
some "(3)red (5)green (4)blue "
|
||||
```
|
||||
```lean example
|
||||
#eval #["red", "green", "blue"].toSubarray.foldlM (init := 0) fun acc x => do
|
||||
let l ← Option.guard (· ≠ 5) x.length
|
||||
return s!"{acc}({l}){x} "
|
||||
```
|
||||
```output
|
||||
none
|
||||
```
|
||||
-/
|
||||
@[inline]
|
||||
def foldlM {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (f : β → α → m β) (init : β) (as : Subarray α) : m β :=
|
||||
as.array.foldlM f (init := init) (start := as.start) (stop := as.stop)
|
||||
|
||||
/--
|
||||
Folds a monadic operation from right to left over the elements in a subarray.
|
||||
@@ -261,6 +313,20 @@ The elements are processed starting at the highest index and moving down.
|
||||
def forRevM {α : Type u} {m : Type v → Type w} [Monad m] (f : α → m PUnit) (as : Subarray α) : m PUnit :=
|
||||
as.array.forRevM f (start := as.stop) (stop := as.start)
|
||||
|
||||
/--
|
||||
Folds an operation from left to right over the elements in a subarray.
|
||||
|
||||
An accumulator of type `β` is constructed by starting with `init` and combining each
|
||||
element of the subarray with the current accumulator value in turn.
|
||||
|
||||
Examples:
|
||||
* `#["red", "green", "blue"].toSubarray.foldl (· + ·.length) 0 = 12`
|
||||
* `#["red", "green", "blue"].toSubarray.popFront.foldl (· + ·.length) 0 = 9`
|
||||
-/
|
||||
@[inline]
|
||||
def foldl {α : Type u} {β : Type v} (f : β → α → β) (init : β) (as : Subarray α) : β :=
|
||||
Id.run <| as.foldlM (pure <| f · ·) (init := init)
|
||||
|
||||
/--
|
||||
Folds an operation from right to left over the elements in a subarray.
|
||||
|
||||
@@ -268,8 +334,8 @@ An accumulator of type `β` is constructed by starting with `init` and combining
|
||||
subarray with the current accumulator value in turn, moving from the end to the start.
|
||||
|
||||
Examples:
|
||||
* `#["red", "green", "blue"].toSubarray.foldr (·.length + ·) 0 = 12`
|
||||
* `#["red", "green", "blue"].toSubarray.popFront.foldr (·.length + ·) 0 = 9`
|
||||
* `#eval #["red", "green", "blue"].toSubarray.foldr (·.length + ·) 0 = 12`
|
||||
* `#["red", "green", "blue"].toSubarray.popFront.foldlr (·.length + ·) 0 = 9`
|
||||
-/
|
||||
@[inline]
|
||||
def foldr {α : Type u} {β : Type v} (f : α → β → β) (init : β) (as : Subarray α) : β :=
|
||||
@@ -398,6 +464,18 @@ def toSubarray (as : Array α) (start : Nat := 0) (stop : Nat := as.size) : Suba
|
||||
start_le_stop := Nat.le_refl _,
|
||||
stop_le_array_size := Nat.le_refl _ }⟩
|
||||
|
||||
/--
|
||||
Allocates a new array that contains the contents of the subarray.
|
||||
-/
|
||||
@[coe]
|
||||
def ofSubarray (s : Subarray α) : Array α := Id.run do
|
||||
let mut as := mkEmpty (s.stop - s.start)
|
||||
for a in s do
|
||||
as := as.push a
|
||||
return as
|
||||
|
||||
instance : Coe (Subarray α) (Array α) := ⟨ofSubarray⟩
|
||||
|
||||
/-- A subarray with the provided bounds.-/
|
||||
syntax:max term noWs "[" withoutPosition(term ":" term) "]" : term
|
||||
/-- A subarray with the provided lower bound that extends to the rest of the array. -/
|
||||
@@ -411,3 +489,22 @@ macro_rules
|
||||
| `($a[$start : ]) => `(let a := $a; Array.toSubarray a $start a.size)
|
||||
|
||||
end Array
|
||||
|
||||
@[inherit_doc Array.ofSubarray]
|
||||
def Subarray.toArray (s : Subarray α) : Array α :=
|
||||
Array.ofSubarray s
|
||||
|
||||
instance : Append (Subarray α) where
|
||||
append x y :=
|
||||
let a := x.toArray ++ y.toArray
|
||||
a.toSubarray 0 a.size
|
||||
|
||||
/-- `Subarray` representation. -/
|
||||
protected def Subarray.repr [Repr α] (s : Subarray α) : Std.Format :=
|
||||
repr s.toArray ++ ".toSubarray"
|
||||
|
||||
instance [Repr α] : Repr (Subarray α) where
|
||||
reprPrec s _ := Subarray.repr s
|
||||
|
||||
instance [ToString α] : ToString (Subarray α) where
|
||||
toString s := toString s.toArray
|
||||
|
||||
@@ -8,8 +8,7 @@ module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Subarray
|
||||
import all Init.Data.Array.Subarray
|
||||
public import all Init.Data.Array.Subarray
|
||||
public import Init.Omega
|
||||
|
||||
public section
|
||||
|
||||
@@ -6,8 +6,7 @@ Authors: Markus Himmel
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.List.Nat.TakeDrop
|
||||
|
||||
|
||||
@@ -6,8 +6,7 @@ Authors: Kim Morrison
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Array.Basic
|
||||
import all Init.Data.Array.Basic
|
||||
public import all Init.Data.Array.Basic
|
||||
public import Init.Data.Array.TakeDrop
|
||||
public import Init.Data.List.Zip
|
||||
|
||||
@@ -119,7 +118,7 @@ theorem zipWith_foldl_eq_zip_foldl {f : α → β → γ} {i : δ} :
|
||||
theorem zipWith_eq_empty_iff {f : α → β → γ} {as : Array α} {bs : Array β} : zipWith f as bs = #[] ↔ as = #[] ∨ bs = #[] := by
|
||||
cases as <;> cases bs <;> simp
|
||||
|
||||
@[simp, grind =]
|
||||
@[grind =]
|
||||
theorem map_zipWith {δ : Type _} {f : α → β} {g : γ → δ → α} {cs : Array γ} {ds : Array δ} :
|
||||
map f (zipWith g cs ds) = zipWith (fun x y => f (g x y)) cs ds := by
|
||||
cases cs
|
||||
@@ -231,9 +230,11 @@ theorem zip_map {f : α → γ} {g : β → δ} {as : Array α} {bs : Array β}
|
||||
cases bs
|
||||
simp [List.zip_map]
|
||||
|
||||
@[grind _=_]
|
||||
theorem zip_map_left {f : α → γ} {as : Array α} {bs : Array β} :
|
||||
zip (as.map f) bs = (zip as bs).map (Prod.map f id) := by rw [← zip_map, map_id]
|
||||
|
||||
@[grind _=_]
|
||||
theorem zip_map_right {f : β → γ} {as : Array α} {bs : Array β} :
|
||||
zip as (bs.map f) = (zip as bs).map (Prod.map id f) := by rw [← zip_map, map_id]
|
||||
|
||||
@@ -353,15 +354,6 @@ theorem map_zipWithAll {δ : Type _} {f : α → β} {g : Option γ → Option
|
||||
@[deprecated zipWithAll_replicate (since := "2025-03-18")]
|
||||
abbrev zipWithAll_mkArray := @zipWithAll_replicate
|
||||
|
||||
/-! ### zipWithM -/
|
||||
|
||||
@[simp, grind =]
|
||||
theorem zipWithM_eq_mapM_id_zipWith {m : Type v → Type w} [Monad m] [LawfulMonad m] {f : α → β → m γ} {as : Array α} {bs : Array β} :
|
||||
zipWithM f as bs = mapM id (zipWith f as bs) := by
|
||||
cases as
|
||||
cases bs
|
||||
simp [List.zipWithM_toArray, ← List.zipWithM'_eq_zipWithM]
|
||||
|
||||
/-! ### unzip -/
|
||||
|
||||
@[deprecated fst_unzip (since := "2025-05-26")]
|
||||
|
||||
@@ -23,14 +23,11 @@ class PartialEquivBEq (α) [BEq α] : Prop where
|
||||
/-- Transitivity for `BEq`. If `a == b` and `b == c` then `a == c`. -/
|
||||
trans : (a : α) == b → b == c → a == c
|
||||
|
||||
instance [BEq α] [PartialEquivBEq α] : Std.Symm (α := α) (· == ·) where
|
||||
symm _ _ h := PartialEquivBEq.symm h
|
||||
|
||||
/-- `EquivBEq` says that the `BEq` implementation is an equivalence relation. -/
|
||||
class EquivBEq (α) [BEq α] : Prop extends PartialEquivBEq α, ReflBEq α
|
||||
|
||||
theorem BEq.symm [BEq α] [Std.Symm (α := α) (· == ·)] {a b : α} : a == b → b == a :=
|
||||
Std.Symm.symm a b (r := (· == ·))
|
||||
theorem BEq.symm [BEq α] [PartialEquivBEq α] {a b : α} : a == b → b == a :=
|
||||
PartialEquivBEq.symm
|
||||
|
||||
theorem BEq.comm [BEq α] [PartialEquivBEq α] {a b : α} : (a == b) = (b == a) :=
|
||||
Bool.eq_iff_iff.2 ⟨BEq.symm, BEq.symm⟩
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user