mirror of
https://github.com/leanprover/lean4.git
synced 2026-04-11 14:44:06 +00:00
Compare commits
250 Commits
sg/fix-pos
...
release_st
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0abedb3e69 | ||
|
|
c4c3497776 | ||
|
|
d45cc674ea | ||
|
|
8a0d036e82 | ||
|
|
9d93b10919 | ||
|
|
2412d52536 | ||
|
|
e686d040ea | ||
|
|
2dce18655d | ||
|
|
6cf22b32aa | ||
|
|
d24219697e | ||
|
|
d353a25a36 | ||
|
|
9dc4dbebe1 | ||
|
|
04be1c6b5c | ||
|
|
e46a3108d9 | ||
|
|
4cbfa485fa | ||
|
|
9328271dd0 | ||
|
|
f137d43931 | ||
|
|
0ba5413266 | ||
|
|
fefc033515 | ||
|
|
d888039468 | ||
|
|
ddc4cf0a97 | ||
|
|
aa5b392e35 | ||
|
|
6346fdb253 | ||
|
|
7d2a7dba81 | ||
|
|
98f05c47d0 | ||
|
|
67bbc947af | ||
|
|
64219ac91e | ||
|
|
dedd9275ec | ||
|
|
4dbe84dc98 | ||
|
|
0cc4c91800 | ||
|
|
548d564c18 | ||
|
|
2d30e3913c | ||
|
|
ec13bb963f | ||
|
|
9006597f59 | ||
|
|
e28569f2a1 | ||
|
|
751947482f | ||
|
|
b7ab7ea745 | ||
|
|
6f5532f069 | ||
|
|
30ca6c82e0 | ||
|
|
968a708a9f | ||
|
|
bb23700f24 | ||
|
|
9a34f6bc95 | ||
|
|
f3e1795175 | ||
|
|
d57d1fcd36 | ||
|
|
e134cfea8f | ||
|
|
8b8561a699 | ||
|
|
51ae98ae30 | ||
|
|
09de5cd70e | ||
|
|
23e88b4e1d | ||
|
|
fcd60e73f8 | ||
|
|
b7f433c5b9 | ||
|
|
f3ac38ff2c | ||
|
|
c5a5c5572f | ||
|
|
2f7c0366f5 | ||
|
|
1a9757d1f6 | ||
|
|
3aaa3beeee | ||
|
|
deef4e8e23 | ||
|
|
c660f63748 | ||
|
|
b7e220039f | ||
|
|
34bd6e8bfd | ||
|
|
5cd5885da4 | ||
|
|
5f4e6a86d5 | ||
|
|
1043569648 | ||
|
|
383256defa | ||
|
|
cdab726e3d | ||
|
|
7b9ead4a1a | ||
|
|
6e191720b3 | ||
|
|
9fc31abb1f | ||
|
|
3878d6da85 | ||
|
|
097952c48f | ||
|
|
e5730e9b7e | ||
|
|
49546687d9 | ||
|
|
2c08280854 | ||
|
|
ebe68faf7f | ||
|
|
65abbd90bf | ||
|
|
119854e248 | ||
|
|
442ef6e64c | ||
|
|
fb462fdf9e | ||
|
|
d667522524 | ||
|
|
c1b5d54737 | ||
|
|
f94d7b333a | ||
|
|
d7ef2880c8 | ||
|
|
f3944a3d49 | ||
|
|
263a77fa89 | ||
|
|
2584b6abf9 | ||
|
|
ca9b804163 | ||
|
|
e9ccdeecd0 | ||
|
|
2ed4f39ffe | ||
|
|
1959e6088b | ||
|
|
ffbb21a032 | ||
|
|
e088549330 | ||
|
|
587979341a | ||
|
|
180bfeaba4 | ||
|
|
e6cce355e3 | ||
|
|
e9b75e34b7 | ||
|
|
e286f20179 | ||
|
|
d4afa3caaa | ||
|
|
e069c9eb0e | ||
|
|
dc2f256448 | ||
|
|
62ded77e81 | ||
|
|
466e8a6c5e | ||
|
|
b131e8b97f | ||
|
|
d7ef2a8d1c | ||
|
|
3b58a7d36b | ||
|
|
e9a318df16 | ||
|
|
166d1c0dab | ||
|
|
0926d27100 | ||
|
|
aa6f22d102 | ||
|
|
6adeab2160 | ||
|
|
6cbdd6b815 | ||
|
|
a8c0348300 | ||
|
|
08d8bed022 | ||
|
|
6e9bc1359d | ||
|
|
aac501a645 | ||
|
|
cf94e1b162 | ||
|
|
96e7ab078d | ||
|
|
9d33f2ad33 | ||
|
|
a4b5eecb8e | ||
|
|
f224452971 | ||
|
|
caf815b009 | ||
|
|
c0079fd9dd | ||
|
|
cfb13b1689 | ||
|
|
105843519c | ||
|
|
97698bfc38 | ||
|
|
7f1869016a | ||
|
|
0931033c72 | ||
|
|
a7789d863c | ||
|
|
bcc6fb54c2 | ||
|
|
b04ee0de57 | ||
|
|
7a83adf10d | ||
|
|
d642880b7d | ||
|
|
74206c755f | ||
|
|
c7b4d843e2 | ||
|
|
c90cc392f7 | ||
|
|
f298360ff9 | ||
|
|
275e483885 | ||
|
|
e87ce2bd5b | ||
|
|
3c6a923f1b | ||
|
|
b25ef7682d | ||
|
|
71b5bf3ef6 | ||
|
|
8dfc71c4fd | ||
|
|
243bbd74a5 | ||
|
|
aba49508f1 | ||
|
|
ae2a9b4688 | ||
|
|
d36fc8df67 | ||
|
|
6c20cd08f1 | ||
|
|
46b04c8405 | ||
|
|
efc101d3b4 | ||
|
|
e2e36087e1 | ||
|
|
d4e11f754a | ||
|
|
837ea41ede | ||
|
|
5778a3c0f2 | ||
|
|
668a892cdb | ||
|
|
0fdb63f258 | ||
|
|
338456e765 | ||
|
|
18a82c04fc | ||
|
|
4520206f4a | ||
|
|
9ee8e0c896 | ||
|
|
62dc8d64fa | ||
|
|
7845154a3d | ||
|
|
66de09bc9c | ||
|
|
3e37eef9ea | ||
|
|
d3a4bb29a7 | ||
|
|
1db5e35b59 | ||
|
|
efe5e9a752 | ||
|
|
a4f38cc782 | ||
|
|
b579c5c7d8 | ||
|
|
575adbae18 | ||
|
|
5e19c47710 | ||
|
|
a7675ad4b2 | ||
|
|
d2e604f74d | ||
|
|
4c93ab7602 | ||
|
|
625de14b23 | ||
|
|
b13b916b7e | ||
|
|
9f2b796639 | ||
|
|
4955dde748 | ||
|
|
3b18ae2209 | ||
|
|
9620cb1b90 | ||
|
|
d664b6b888 | ||
|
|
192c0c8e67 | ||
|
|
cec0c82f1c | ||
|
|
4ff4ed88bc | ||
|
|
a05311d1ec | ||
|
|
f675ee2062 | ||
|
|
cb127b42ac | ||
|
|
c7c5de38b3 | ||
|
|
6ad12525ad | ||
|
|
bb5df157bc | ||
|
|
77442f5486 | ||
|
|
97aca690d0 | ||
|
|
173629ebd5 | ||
|
|
beeeead99f | ||
|
|
d38c36001d | ||
|
|
7386cc3b12 | ||
|
|
7958e01b1c | ||
|
|
47e8483b38 | ||
|
|
0b2bdaebd6 | ||
|
|
ac600853c0 | ||
|
|
77a0c2bf9b | ||
|
|
46c43c3ecb | ||
|
|
6de68dd8ef | ||
|
|
97fd75c660 | ||
|
|
cf6a182f69 | ||
|
|
655c7ab548 | ||
|
|
70368ed1a5 | ||
|
|
765f98770b | ||
|
|
05630fc149 | ||
|
|
2d173615ba | ||
|
|
b2920d6410 | ||
|
|
aee2da809a | ||
|
|
2bf9130b63 | ||
|
|
67d9d9d936 | ||
|
|
0c5946ab3f | ||
|
|
98e4b2882f | ||
|
|
6e98dfbc64 | ||
|
|
e7e4119cf4 | ||
|
|
6cf8828ce7 | ||
|
|
5d46391dde | ||
|
|
c9debdaf2a | ||
|
|
9b7a14b156 | ||
|
|
ff5d96096a | ||
|
|
53d4139cf1 | ||
|
|
c1f1287e24 | ||
|
|
4322a0c7d3 | ||
|
|
d0e097cd1d | ||
|
|
bd7e6c3c61 | ||
|
|
1443982924 | ||
|
|
15586e28a8 | ||
|
|
6f5fdf5c3e | ||
|
|
bd06e07624 | ||
|
|
2cf6c2ddc9 | ||
|
|
38d4dc7058 | ||
|
|
149fc2173c | ||
|
|
12536d2015 | ||
|
|
36c036d952 | ||
|
|
bebffc0d20 | ||
|
|
dd7bc0e643 | ||
|
|
264aac4a33 | ||
|
|
d981a2a9a8 | ||
|
|
2ca6c3bf4d | ||
|
|
722ab706c8 | ||
|
|
9697c7264d | ||
|
|
01b0c3e0cc | ||
|
|
37cffbda51 | ||
|
|
f5e47480f2 | ||
|
|
66ffd8d5c2 | ||
|
|
162e81af57 | ||
|
|
2bf4192ab7 | ||
|
|
106d50e46c | ||
|
|
d89f336db2 |
28
.github/workflows/build-template.yml
vendored
28
.github/workflows/build-template.yml
vendored
@@ -104,7 +104,7 @@ jobs:
|
||||
# NOTE: must be in sync with `save` below and with `restore-cache` in `update-stage0.yml`
|
||||
path: |
|
||||
.ccache
|
||||
${{ matrix.name == 'Linux Lake' && false && 'build/stage1/**/*.trace
|
||||
${{ matrix.name == 'Linux Lake (cached)' && 'build/stage1/**/*.trace
|
||||
build/stage1/**/*.olean*
|
||||
build/stage1/**/*.ilean
|
||||
build/stage1/**/*.ir
|
||||
@@ -119,9 +119,15 @@ jobs:
|
||||
run: |
|
||||
ccache --zero-stats
|
||||
if: runner.os == 'Linux'
|
||||
- name: Set up NPROC
|
||||
- name: Set up env
|
||||
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
|
||||
@@ -142,6 +148,9 @@ 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
|
||||
@@ -156,10 +165,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 -j$NPROC
|
||||
time make $TARGET_STAGE -j$NPROC
|
||||
- name: Install
|
||||
run: |
|
||||
make -C build install
|
||||
make -C build/$TARGET_STAGE install
|
||||
- name: Check Binaries
|
||||
run: ${{ matrix.binary-check }} lean-*/bin/* || true
|
||||
- name: Count binary symbols
|
||||
@@ -196,12 +205,12 @@ jobs:
|
||||
id: test
|
||||
run: |
|
||||
ulimit -c unlimited # coredumps
|
||||
time ctest --preset ${{ matrix.CMAKE_PRESET || 'release' }} --test-dir build/stage1 -j$NPROC --output-junit test-results.xml ${{ matrix.CTEST_OPTIONS }}
|
||||
time ctest --preset ${{ matrix.CMAKE_PRESET || 'release' }} --test-dir build/$TARGET_STAGE -j$NPROC --output-junit test-results.xml ${{ matrix.CTARGET_OPTIONS }}
|
||||
if: (matrix.wasm || !matrix.cross) && (inputs.check-level >= 1 || matrix.test)
|
||||
- name: Test Summary
|
||||
uses: test-summary/action@v2
|
||||
with:
|
||||
paths: build/stage1/test-results.xml
|
||||
paths: build/${{ env.TARGET_STAGE }}/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
|
||||
@@ -226,8 +235,9 @@ jobs:
|
||||
if: matrix.test-speedcenter
|
||||
- name: Check rebootstrap
|
||||
run: |
|
||||
# clean rebuild in case of Makefile changes
|
||||
make -C build update-stage0 && rm -rf build/stage* && make -C build -j$NPROC
|
||||
# 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 && make -C build -j$NPROC
|
||||
if: matrix.check-rebootstrap
|
||||
- name: CCache stats
|
||||
if: always()
|
||||
@@ -246,7 +256,7 @@ jobs:
|
||||
# NOTE: must be in sync with `restore` above
|
||||
path: |
|
||||
.ccache
|
||||
${{ matrix.name == 'Linux Lake' && false && 'build/stage1/**/*.trace
|
||||
${{ matrix.name == 'Linux Lake (cached)' && 'build/stage1/**/*.trace
|
||||
build/stage1/**/*.olean*
|
||||
build/stage1/**/*.ilean
|
||||
build/stage1/**/*.ir
|
||||
|
||||
17
.github/workflows/ci.yml
vendored
17
.github/workflows/ci.yml
vendored
@@ -165,7 +165,7 @@ jobs:
|
||||
{
|
||||
// portable release build: use channel with older glibc (2.26)
|
||||
"name": "Linux release",
|
||||
"os": large && level < 2 ? "nscloud-ubuntu-22.04-amd64-4x16" : "ubuntu-latest",
|
||||
"os": "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)
|
||||
@@ -194,6 +194,13 @@ jobs:
|
||||
"test-speedcenter": large && level >= 2,
|
||||
"CMAKE_OPTIONS": "-DUSE_LAKE=ON",
|
||||
},
|
||||
{
|
||||
"name": "Linux Lake (cached)",
|
||||
"os": "ubuntu-latest",
|
||||
"check-level": (isPr || isPushToMaster) ? 0 : 2,
|
||||
"secondary": true,
|
||||
"CMAKE_OPTIONS": "-DUSE_LAKE=ON",
|
||||
},
|
||||
{
|
||||
"name": "Linux Reldebug",
|
||||
"os": "ubuntu-latest",
|
||||
@@ -225,8 +232,8 @@ jobs:
|
||||
},
|
||||
{
|
||||
"name": "macOS aarch64",
|
||||
// standard GH runner only comes with 7GB so use large runner if possible
|
||||
"os": large ? "nscloud-macos-sonoma-arm64-6x14" : "macos-14",
|
||||
// standard GH runner only comes with 7GB so use large runner if possible when running tests
|
||||
"os": large && !isPr ? "nscloud-macos-sonoma-arm64-6x14" : "macos-14",
|
||||
"CMAKE_OPTIONS": "-DLEAN_INSTALL_SUFFIX=-darwin_aarch64",
|
||||
"release": true,
|
||||
"shell": "bash -euxo pipefail {0}",
|
||||
@@ -234,13 +241,13 @@ 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 above for release job levels
|
||||
// See "Linux release" for release job levels; Grove is not a concern here
|
||||
"check-level": isPr ? 0 : 2,
|
||||
"secondary": isPr,
|
||||
},
|
||||
{
|
||||
"name": "Windows",
|
||||
"os": "windows-2022",
|
||||
"os": large && level == 2 ? "namespace-profile-windows-amd64-4x16" : "windows-2022",
|
||||
"release": true,
|
||||
"check-level": 2,
|
||||
"shell": "msys2 {0}",
|
||||
|
||||
12
.github/workflows/grove.yml
vendored
12
.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. Skipping for now, to be enabled later."
|
||||
echo "should-run=false" >> "$GITHUB_OUTPUT"
|
||||
echo "Push to master detected. Running Grove."
|
||||
echo "should-run=true" >> "$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"
|
||||
echo "PR with grove label detected. Running Grove."
|
||||
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.3
|
||||
uses: TwoFx/grove-action/fetch-upstream@v0.4
|
||||
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.*
|
||||
name: "build-Linux release"
|
||||
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.3
|
||||
uses: TwoFx/grove-action/build@v0.4
|
||||
with:
|
||||
project-path: doc/std/grove
|
||||
script-name: grove-stdlib
|
||||
|
||||
@@ -45,3 +45,6 @@
|
||||
/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
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
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
|
||||
@@ -12,3 +16,7 @@ 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
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
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
|
||||
@@ -0,0 +1,357 @@
|
||||
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
|
||||
@@ -0,0 +1,216 @@
|
||||
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
|
||||
@@ -0,0 +1,21 @@
|
||||
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 α} (m : Std.DHashMap α β) : Bool",
|
||||
renderedStatement := "Std.DHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (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 α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtDHashMap α β) : Bool",
|
||||
renderedStatement := "Std.ExtDHashMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [EquivBEq α] [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} (t : Std.DTreeMap α β cmp) : Bool",
|
||||
renderedStatement := "Std.DTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (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} (t : Std.DTreeMap.Raw α β cmp) :\n Bool",
|
||||
renderedStatement := "Std.DTreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.DTreeMap.Raw α β cmp) : 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} (t : Std.ExtDTreeMap α β cmp) :\n Bool",
|
||||
renderedStatement := "Std.ExtDTreeMap.isEmpty.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (t : Std.ExtDTreeMap α β cmp) : 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 α} (m : Std.HashMap α β) : Bool",
|
||||
renderedStatement := "Std.HashMap.isEmpty.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (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 α] [LawfulHashable α]\n (m : Std.ExtHashMap α β) : Bool",
|
||||
renderedStatement := "Std.ExtHashMap.isEmpty.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (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} (t : Std.TreeMap α β cmp) : Bool",
|
||||
renderedStatement := "Std.TreeMap.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (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} (t : Std.TreeMap.Raw α β cmp) : Bool",
|
||||
renderedStatement := "Std.TreeMap.Raw.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (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} (t : Std.ExtTreeMap α β cmp) : Bool",
|
||||
renderedStatement := "Std.ExtTreeMap.isEmpty.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (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 α] [LawfulHashable α]\n (m : Std.ExtHashSet α) : Bool",
|
||||
renderedStatement := "Std.ExtHashSet.isEmpty.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (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 α} (m : Std.DHashMap α β) : Nat",
|
||||
renderedStatement := "Std.DHashMap.size.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (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 α} [EquivBEq α]\n [LawfulHashable α] (m : Std.ExtDHashMap α β) : Nat",
|
||||
renderedStatement := "Std.ExtDHashMap.size.{u, v} {α : Type u} {β : α → Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n [EquivBEq α] [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} (t : Std.DTreeMap α β cmp) : Nat",
|
||||
renderedStatement := "Std.DTreeMap.size.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (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} (t : Std.DTreeMap.Raw α β cmp) : Nat",
|
||||
renderedStatement := "Std.DTreeMap.Raw.size.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (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} (t : Std.ExtDTreeMap α β cmp) : Nat",
|
||||
renderedStatement := "Std.ExtDTreeMap.size.{u, v} {α : Type u} {β : α → Type v} {cmp : α → α → Ordering}\n (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 α} (m : Std.HashMap α β) : Nat",
|
||||
renderedStatement := "Std.HashMap.size.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α}\n (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 α] [LawfulHashable α]\n (m : Std.ExtHashMap α β) : Nat",
|
||||
renderedStatement := "Std.ExtHashMap.size.{u, v} {α : Type u} {β : Type v} {x✝ : BEq α} {x✝¹ : Hashable α} [EquivBEq α]\n [LawfulHashable α] (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} (t : Std.TreeMap α β cmp) : Nat",
|
||||
renderedStatement := "Std.TreeMap.size.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (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} (t : Std.TreeMap.Raw α β cmp) : Nat",
|
||||
renderedStatement := "Std.TreeMap.Raw.size.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (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} (t : Std.ExtTreeMap α β cmp) : Nat",
|
||||
renderedStatement := "Std.ExtTreeMap.size.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (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} (t : Std.DTreeMap α β cmp)\n (p : (a : α) → β a → Bool) : Bool",
|
||||
renderedStatement := "Std.DTreeMap.any.{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.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} (t : Std.DTreeMap.Raw α β cmp)\n (p : (a : α) → β a → Bool) : Bool",
|
||||
renderedStatement := "Std.DTreeMap.Raw.any.{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.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) (p : α → β → Bool) :\n Bool",
|
||||
renderedStatement := "Std.TreeMap.any.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering} (t : Std.TreeMap α β cmp)\n (p : α → β → Bool) : 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} (t : Std.TreeMap.Raw α β cmp)\n (p : α → β → Bool) : Bool",
|
||||
renderedStatement := "Std.TreeMap.Raw.any.{u, v} {α : Type u} {β : Type v} {cmp : α → α → Ordering}\n (t : Std.TreeMap.Raw α β cmp) (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 α) (p : α → Bool) : Bool",
|
||||
renderedStatement := "Std.HashSet.any.{u} {α : Type u} {x✝ : BEq α} {x✝¹ : Hashable α} (m : Std.HashSet α)\n (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) : Bool",
|
||||
renderedStatement := "Std.TreeSet.any.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet α cmp) (p : α → Bool) :\n 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) (p : α → Bool) : Bool",
|
||||
renderedStatement := "Std.TreeSet.Raw.any.{u} {α : Type u} {cmp : α → α → Ordering} (t : Std.TreeSet.Raw α cmp)\n (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] (t : Std.ExtTreeSet α cmp)\n (p : α → Bool) : Bool",
|
||||
renderedStatement := "Std.ExtTreeSet.any.{u} {α : Type u} {cmp : α → α → Ordering} [Std.TransCmp cmp]\n (t : Std.ExtTreeSet α cmp) (p : α → Bool) : Bool",
|
||||
isDeprecated := false })⟩,]
|
||||
metadata := {
|
||||
status := .bad
|
||||
@@ -228,62 +228,51 @@ 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", .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
|
||||
}
|
||||
)⟩,]
|
||||
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 })⟩,]
|
||||
metadata := {
|
||||
status := .bad
|
||||
comment := "Missing for some containers"
|
||||
@@ -292,97 +281,79 @@ 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", .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
|
||||
}
|
||||
)⟩,]
|
||||
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 })⟩,]
|
||||
metadata := {
|
||||
status := .done
|
||||
comment := ""
|
||||
@@ -391,73 +362,61 @@ 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", .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
|
||||
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
|
||||
{ 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", .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
|
||||
}
|
||||
)⟩,]
|
||||
{ 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 })⟩,]
|
||||
metadata := {
|
||||
status := .bad
|
||||
comment := "Should *Set have GetElem?"
|
||||
|
||||
@@ -20,23 +20,75 @@ def sequentialContainers : Node :=
|
||||
|
||||
namespace AssociativeContainers
|
||||
|
||||
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
|
||||
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
|
||||
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.declarationsInNamespace n .definitionsOnly)
|
||||
(DataSource.definitionsInNamespace n)
|
||||
|>.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 AssociativeContainers.associativeQueryOperations
|
||||
.associationTable associativeQueryOperations,
|
||||
.associationTable associativeCreationOperations,
|
||||
.associationTable associativeModificationOperations,
|
||||
.table associativeCreateThenQuery,
|
||||
.assertion allOperationsCovered
|
||||
]
|
||||
|
||||
namespace PersistentDataStructures
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
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
|
||||
GROVE_DATA_LOCATION=../../../../metadata.json GROVE_UPSTREAM_INVALIDATED_FACTS_LOCATION=../../../../invalidated.json npm run dev
|
||||
cp ../../../../invalidated.json public/invalidated.json
|
||||
GROVE_DATA_LOCATION=public/metadata.json GROVE_UPSTREAM_INVALIDATED_FACTS_LOCATION=public/invalidated.json npm run dev
|
||||
else
|
||||
GROVE_DATA_LOCATION=../../../../metadata.json npm run dev
|
||||
fi
|
||||
GROVE_DATA_LOCATION=public/metadata.json npm run dev
|
||||
fi
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"type": "git",
|
||||
"subDir": "backend",
|
||||
"scope": "",
|
||||
"rev": "e8127fc6554b99fb988ecdceb770a5e112afbe24",
|
||||
"rev": "3e8aabdea58c11813c5d3b7eeb187ded44ee9a34",
|
||||
"name": "grove",
|
||||
"manifestFile": "lake-manifest.json",
|
||||
"inputRev": "master",
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cmake --preset release -DUSE_LAKE=ON 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
|
||||
timeout -s KILL 1h time make -C build/release -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/stage2 -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
|
||||
|
||||
@@ -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 re.search(r'rc\d+$', version) and repo_name in ["batteries", "mathlib4"] and version.endswith('-rc1'):
|
||||
if 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]}..."))
|
||||
|
||||
@@ -403,7 +403,7 @@ def execute_release_steps(repo, version, config):
|
||||
raise
|
||||
|
||||
# Handle special merging cases
|
||||
if re.search(r'rc\d+$', version) and repo_name in ["batteries", "mathlib4"]:
|
||||
if version.endswith('-rc1') 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
|
||||
@@ -474,7 +474,7 @@ def execute_release_steps(repo, version, config):
|
||||
|
||||
print(green("✅ Merge completed successfully with automatic conflict resolution"))
|
||||
|
||||
elif re.search(r'rc\d+$', version):
|
||||
elif version.endswith('-rc1'):
|
||||
# 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."))
|
||||
|
||||
@@ -533,12 +533,21 @@ 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 ";")
|
||||
@@ -634,8 +643,6 @@ 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})
|
||||
@@ -814,6 +821,12 @@ if(LEAN_INSTALL_PREFIX)
|
||||
set(CMAKE_INSTALL_PREFIX "${LEAN_INSTALL_PREFIX}/lean-${LEAN_VERSION_STRING}${LEAN_INSTALL_SUFFIX}")
|
||||
endif()
|
||||
|
||||
if (STAGE GREATER 1)
|
||||
# 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
|
||||
string(APPEND LEAN_EXTRA_LAKEFILE_TOML "\n\nenableArtifactCache = 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)
|
||||
@@ -840,6 +853,10 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
set(LAKE_LIB_PREFIX "lib")
|
||||
endif()
|
||||
|
||||
if(USE_LAKE AND STAGE EQUAL 1)
|
||||
configure_file(${LEAN_SOURCE_DIR}/lakefile.toml.in ${LEAN_SOURCE_DIR}/lakefile.toml)
|
||||
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()
|
||||
endif()
|
||||
|
||||
@@ -12,7 +12,7 @@ public import Init.Control.Basic
|
||||
public import Init.Control.Id
|
||||
public import Init.Coe
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
|
||||
namespace Except
|
||||
variable {ε : Type u}
|
||||
|
||||
@@ -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.
|
||||
-/
|
||||
@[reducible] def ReaderM (ρ : Type u) := ReaderT ρ Id
|
||||
abbrev ReaderM (ρ : Type u) := ReaderT ρ Id
|
||||
|
||||
@@ -262,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. -/
|
||||
|
||||
@@ -752,6 +752,8 @@ 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. -/
|
||||
@@ -853,6 +855,8 @@ 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
|
||||
|
||||
@@ -10,7 +10,7 @@ prelude
|
||||
public import Init.Classical
|
||||
public import Init.ByCases
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
|
||||
namespace Lean.Data.AC
|
||||
inductive Expr
|
||||
|
||||
@@ -872,24 +872,24 @@ theorem elem_eq_mem [BEq α] [LawfulBEq α] {a : α} {xs : Array α} :
|
||||
@[grind] theorem all_empty [BEq α] {p : α → Bool} : (#[] : Array α).all p = true := by simp
|
||||
|
||||
/-- Variant of `any_push` with a side condition on `stop`. -/
|
||||
@[simp, grind] theorem any_push' [BEq α] {xs : Array α} {a : α} {p : α → Bool} (h : stop = xs.size + 1) :
|
||||
@[simp, grind] theorem any_push' {xs : Array α} {a : α} {p : α → Bool} (h : stop = xs.size + 1) :
|
||||
(xs.push a).any p 0 stop = (xs.any p || p a) := by
|
||||
cases xs
|
||||
rw [List.push_toArray]
|
||||
simp [h]
|
||||
|
||||
theorem any_push [BEq α] {xs : Array α} {a : α} {p : α → Bool} :
|
||||
theorem any_push {xs : Array α} {a : α} {p : α → Bool} :
|
||||
(xs.push a).any p = (xs.any p || p a) :=
|
||||
any_push' (by simp)
|
||||
|
||||
/-- Variant of `all_push` with a side condition on `stop`. -/
|
||||
@[simp, grind] theorem all_push' [BEq α] {xs : Array α} {a : α} {p : α → Bool} (h : stop = xs.size + 1) :
|
||||
@[simp, grind] theorem all_push' {xs : Array α} {a : α} {p : α → Bool} (h : stop = xs.size + 1) :
|
||||
(xs.push a).all p 0 stop = (xs.all p && p a) := by
|
||||
cases xs
|
||||
rw [List.push_toArray]
|
||||
simp [h]
|
||||
|
||||
theorem all_push [BEq α] {xs : Array α} {a : α} {p : α → Bool} :
|
||||
theorem all_push {xs : Array α} {a : α} {p : α → Bool} :
|
||||
(xs.push a).all p = (xs.all p && p a) :=
|
||||
all_push' (by simp)
|
||||
|
||||
|
||||
@@ -6,9 +6,12 @@ Author: Kim Morrison
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Init.Data.Array.Basic
|
||||
public import Init.Data.Nat.Lemmas
|
||||
public import Init.Data.Range
|
||||
public import Init.Core
|
||||
import Init.Data.Array.Basic
|
||||
import Init.Data.Nat.Lemmas
|
||||
import Init.Data.Range.Polymorphic.Iterators
|
||||
import Init.Data.Range.Polymorphic.Nat
|
||||
import Init.Data.Iterators.Consumers
|
||||
|
||||
public section
|
||||
|
||||
@@ -26,9 +29,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: `omega` should be able to find this itself.
|
||||
have : i < min as.size bs.size := Membership.get_elem_helper h rfl
|
||||
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.PRange.lt_upper_of_mem h
|
||||
if lt as[i] bs[i] then
|
||||
return true
|
||||
else if as[i] != bs[i] then
|
||||
|
||||
@@ -6,9 +6,12 @@ Author: Kim Morrison
|
||||
module
|
||||
|
||||
prelude
|
||||
public import all Init.Data.Array.Lex.Basic
|
||||
import all Init.Data.Array.Lex.Basic
|
||||
public import 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
|
||||
|
||||
public section
|
||||
|
||||
@@ -36,16 +39,38 @@ protected theorem not_le_iff_gt [LT α] {xs ys : Array α} :
|
||||
Classical.not_not
|
||||
|
||||
@[simp] theorem lex_empty [BEq α] {lt : α → α → Bool} {xs : Array α} : xs.lex #[] lt = false := by
|
||||
simp [lex]
|
||||
rw [lex, Std.PRange.forIn'_eq_match]
|
||||
simp [Std.PRange.SupportsUpperBound.IsSatisfied]
|
||||
|
||||
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
|
||||
|
||||
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]
|
||||
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]
|
||||
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.PRange.forIn'_eq_forIn'_toList]
|
||||
conv =>
|
||||
lhs; congr; congr
|
||||
rw [cons_lex_cons.forIn'_congr_aux Std.PRange.toList_eq_match rfl (fun _ _ _ => rfl)]
|
||||
simp only [Std.PRange.SupportsUpperBound.IsSatisfied, bind_pure_comp, map_pure]
|
||||
rw [cons_lex_cons.forIn'_congr_aux (if_pos (by omega)) rfl (fun _ _ _ => rfl)]
|
||||
simp only [Std.PRange.toList_open_eq_toList_closed_of_isSome_succ? (lo := 0) (h := rfl),
|
||||
Std.PRange.UpwardEnumerable.succ?, Nat.add_comm 1, Std.PRange.Nat.ClosedOpen.toList_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]
|
||||
cases lt a b
|
||||
· rw [bne]
|
||||
cases a == b <;> simp
|
||||
@@ -54,10 +79,17 @@ 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]
|
||||
| nil =>
|
||||
cases l₂
|
||||
· rw [lex, Std.PRange.forIn'_eq_match]
|
||||
simp [Std.PRange.SupportsUpperBound.IsSatisfied]
|
||||
· rw [lex, Std.PRange.forIn'_eq_match]
|
||||
simp [Std.PRange.SupportsUpperBound.IsSatisfied]
|
||||
| cons x l₁ ih =>
|
||||
cases l₂ with
|
||||
| nil => simp [lex]
|
||||
| nil =>
|
||||
rw [lex, Std.PRange.forIn'_eq_match]
|
||||
simp [Std.PRange.SupportsUpperBound.IsSatisfied]
|
||||
| cons y l₂ =>
|
||||
rw [List.toArray_cons, List.toArray_cons y, cons_lex_cons, List.lex, ih]
|
||||
|
||||
|
||||
@@ -161,7 +161,8 @@ instance : Inhabited (Subarray α) :=
|
||||
⟨{}⟩
|
||||
|
||||
/-!
|
||||
`ForIn` and `foldlM` are implemented in `Init.Data.Slice.Array.Iterator` using the slice iterator.
|
||||
`ForIn`, `foldlM`, `foldl` and other operations are implemented in `Init.Data.Slice.Array.Iterator`
|
||||
using the slice iterator.
|
||||
-/
|
||||
|
||||
/--
|
||||
|
||||
@@ -12,7 +12,7 @@ public import Init.Data.Nat.Power2
|
||||
public import Init.Data.Int.Bitwise
|
||||
public import Init.Data.BitVec.BasicAux
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
|
||||
/-!
|
||||
We define the basic algebraic structure of bitvectors. We choose the `Fin` representation over
|
||||
@@ -736,10 +736,10 @@ def twoPow (w : Nat) (i : Nat) : BitVec w := 1#w <<< i
|
||||
end bitwise
|
||||
|
||||
/-- The bitvector of width `w` that has the smallest value when interpreted as an integer. -/
|
||||
def intMin (w : Nat) := twoPow w (w - 1)
|
||||
@[expose] def intMin (w : Nat) := twoPow w (w - 1)
|
||||
|
||||
/-- The bitvector of width `w` that has the largest value when interpreted as an integer. -/
|
||||
def intMax (w : Nat) := (twoPow w (w - 1)) - 1
|
||||
@[expose] def intMax (w : Nat) := (twoPow w (w - 1)) - 1
|
||||
|
||||
/--
|
||||
Computes a hash of a bitvector, combining 64-bit words using `mixHash`.
|
||||
|
||||
@@ -15,7 +15,7 @@ public import Init.Data.BitVec.Decidable
|
||||
public import Init.Data.BitVec.Lemmas
|
||||
public import Init.Data.BitVec.Folds
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
|
||||
/-!
|
||||
# Bit blasting of bitvectors
|
||||
@@ -336,7 +336,7 @@ theorem add_eq_or_of_and_eq_zero {w : Nat} (x y : BitVec w)
|
||||
(h : x &&& y = 0#w) : x + y = x ||| y := by
|
||||
rw [add_eq_adc, adc, iunfoldr_replace (fun _ => false) (x ||| y)]
|
||||
· rfl
|
||||
· simp only [adcb, atLeastTwo, Bool.and_false, Bool.or_false, bne_false,
|
||||
· simp only [adcb, atLeastTwo, Bool.and_false, Bool.or_false, bne_false,
|
||||
Prod.mk.injEq, and_eq_false_imp]
|
||||
intros i
|
||||
replace h : (x &&& y).getLsbD i = (0#w).getLsbD i := by rw [h]
|
||||
@@ -586,7 +586,6 @@ A recurrence that describes multiplication as repeated addition.
|
||||
|
||||
This function is useful for bit blasting multiplication.
|
||||
-/
|
||||
@[expose]
|
||||
def mulRec (x y : BitVec w) (s : Nat) : BitVec w :=
|
||||
let cur := if y.getLsbD s then (x <<< s) else 0
|
||||
match s with
|
||||
@@ -622,7 +621,7 @@ theorem setWidth_setWidth_succ_eq_setWidth_setWidth_add_twoPow (x : BitVec w) (i
|
||||
simp [hik', hik'']
|
||||
omega
|
||||
· ext k
|
||||
simp only [and_twoPow,
|
||||
simp only [and_twoPow,
|
||||
]
|
||||
by_cases hi : x.getLsbD i <;> simp [hi] <;> omega
|
||||
|
||||
@@ -1047,7 +1046,6 @@ theorem lawful_divSubtractShift (qr : DivModState w) (h : qr.Poised args) :
|
||||
/-! ### Core division algorithm circuit -/
|
||||
|
||||
/-- A recursive definition of division for bit blasting, in terms of a shift-subtraction circuit. -/
|
||||
@[expose]
|
||||
def divRec {w : Nat} (m : Nat) (args : DivModArgs w) (qr : DivModState w) :
|
||||
DivModState w :=
|
||||
match m with
|
||||
@@ -1944,7 +1942,7 @@ The remainder for `srem`, i.e. division with rounding to zero is negative
|
||||
iff `x` is negative and `y` does not divide `x`.
|
||||
|
||||
We can eventually build fast circuits for the divisibility test `x.srem y = 0`.
|
||||
-/
|
||||
-/
|
||||
theorem msb_srem {x y : BitVec w} : (x.srem y).msb =
|
||||
(x.msb && decide (x.srem y ≠ 0)) := by
|
||||
rw [msb_eq_toInt]
|
||||
|
||||
@@ -5771,6 +5771,22 @@ theorem clzAuxRec_eq_clzAuxRec_of_le (x : BitVec w) (h : w - 1 ≤ n) :
|
||||
simp [show w - 1 + (k + 1) = (w - 1 + k) + 1 by omega, clzAuxRec_succ, ihk,
|
||||
show x.getLsbD (w - 1 + k + 1) = false by simp only [show w ≤ w - 1 + k + 1 by omega, getLsbD_of_ge]]
|
||||
|
||||
theorem clzAuxRec_eq_clzAuxRec_of_getLsbD_false {x : BitVec w} (h : ∀ i, n < i → x.getLsbD i = false) :
|
||||
x.clzAuxRec n = x.clzAuxRec (n + k) := by
|
||||
induction k
|
||||
· case zero => simp
|
||||
· case succ k ihk =>
|
||||
simp only [show n + (k + 1) = (n + k) + 1 by omega, clzAuxRec_succ]
|
||||
by_cases hxn : x.getLsbD (n + k + 1)
|
||||
· have : ¬ ∀ (i : Nat), n < i → x.getLsbD i = false := by
|
||||
simp only [Classical.not_forall, Bool.not_eq_false]
|
||||
exists n + k + 1
|
||||
simp [show n < n + k + 1 by omega, hxn]
|
||||
contradiction
|
||||
· simp only [hxn, Bool.false_eq_true, ↓reduceIte]
|
||||
exact ihk
|
||||
|
||||
|
||||
/-! ### Inequalities (le / lt) -/
|
||||
|
||||
theorem ule_eq_not_ult (x y : BitVec w) : x.ule y = !y.ult x := by
|
||||
|
||||
@@ -12,7 +12,7 @@ public import Init.Data.UInt.Basic
|
||||
public import all Init.Data.UInt.BasicAux
|
||||
public import Init.Data.Option.Basic
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
universe u
|
||||
|
||||
structure ByteArray where
|
||||
|
||||
@@ -8,7 +8,7 @@ module
|
||||
prelude
|
||||
public import Init.Data.UInt.BasicAux
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
|
||||
/-- Determines if the given integer is a valid [Unicode scalar value](https://www.unicode.org/glossary/#unicode_scalar_value).
|
||||
|
||||
|
||||
@@ -927,24 +927,34 @@ For the induction:
|
||||
-/
|
||||
@[elab_as_elim] def reverseInduction {motive : Fin (n + 1) → Sort _} (last : motive (Fin.last n))
|
||||
(cast : ∀ i : Fin n, motive i.succ → motive (castSucc i)) (i : Fin (n + 1)) : motive i :=
|
||||
if hi : i = Fin.last n then _root_.cast (congrArg motive hi.symm) last
|
||||
else
|
||||
let j : Fin n := ⟨i, Nat.lt_of_le_of_ne (Nat.le_of_lt_succ i.2) fun h => hi (Fin.ext h)⟩
|
||||
cast _ (reverseInduction last cast j.succ)
|
||||
termination_by n + 1 - i
|
||||
decreasing_by decreasing_with
|
||||
-- FIXME: we put the proof down here to avoid getting a dummy `have` in the definition
|
||||
try simp only [Nat.succ_sub_succ_eq_sub]
|
||||
exact Nat.add_sub_add_right .. ▸ Nat.sub_lt_sub_left i.2 (Nat.lt_succ_self i)
|
||||
let rec go (j : Nat) (h) (h2 : i ≤ j) (x : motive ⟨j, h⟩) : motive i :=
|
||||
if hi : i.1 = j then _root_.cast (by simp [← hi]) x
|
||||
else match j with
|
||||
| 0 => by omega
|
||||
| j + 1 => go j (by omega) (by omega) (cast ⟨j, by omega⟩ x)
|
||||
go _ _ (by omega) last
|
||||
|
||||
@[simp] theorem reverseInduction_last {n : Nat} {motive : Fin (n + 1) → Sort _} {zero succ} :
|
||||
(reverseInduction zero succ (Fin.last n) : motive (Fin.last n)) = zero := by
|
||||
rw [reverseInduction]; simp
|
||||
rw [reverseInduction, reverseInduction.go]; simp
|
||||
|
||||
@[simp] theorem reverseInduction_castSucc_aux {n : Nat} {motive : Fin (n + 1) → Sort _} {succ}
|
||||
(i : Fin n) (j : Nat) (h) (h2 : i.1 < j) (zero : motive ⟨j, h⟩) :
|
||||
reverseInduction.go (motive := motive) succ i.castSucc j h (Nat.le_of_lt h2) zero =
|
||||
succ i (reverseInduction.go succ i.succ j h h2 zero) := by
|
||||
induction j generalizing i with
|
||||
| zero => omega
|
||||
| succ j ih =>
|
||||
rw [reverseInduction.go, dif_neg (by exact Nat.ne_of_lt h2)]
|
||||
by_cases hij : i = j
|
||||
· subst hij; simp [reverseInduction.go]
|
||||
dsimp only
|
||||
rw [ih _ _ (by omega), eq_comm, reverseInduction.go, dif_neg (by change i.1 + 1 ≠ _; omega)]
|
||||
|
||||
@[simp] theorem reverseInduction_castSucc {n : Nat} {motive : Fin (n + 1) → Sort _} {zero succ}
|
||||
(i : Fin n) : reverseInduction (motive := motive) zero succ (castSucc i) =
|
||||
succ i (reverseInduction zero succ i.succ) := by
|
||||
rw [reverseInduction, dif_neg (Fin.ne_of_lt (Fin.castSucc_lt_last i))]; rfl
|
||||
rw [reverseInduction, reverseInduction_castSucc_aux _ _ _ i.isLt, reverseInduction]
|
||||
|
||||
/--
|
||||
Proves a statement by cases on the underlying `Nat` value in a `Fin (n + 1)`, checking whether the
|
||||
|
||||
@@ -1737,32 +1737,6 @@ theorem emod_le (x y : Int) (n : Int) : emod_le_cert y n → x % y + n ≤ 0 :=
|
||||
simp only [Int.add_comm, Int.sub_neg, Int.add_zero]
|
||||
exact Int.emod_lt_of_pos x h
|
||||
|
||||
theorem natCast_nonneg (x : Nat) : (-1:Int) * NatCast.natCast x ≤ 0 := by
|
||||
simp
|
||||
|
||||
theorem natCast_sub (x y : Nat)
|
||||
: (NatCast.natCast (x - y) : Int)
|
||||
=
|
||||
if (NatCast.natCast y : Int) + (-1)*NatCast.natCast x ≤ 0 then
|
||||
(NatCast.natCast x : Int) + -1*NatCast.natCast y
|
||||
else
|
||||
(0 : Int) := by
|
||||
change (↑(x - y) : Int) = if (↑y : Int) + (-1)*↑x ≤ 0 then (↑x : Int) + (-1)*↑y else 0
|
||||
rw [Int.neg_mul, ← Int.sub_eq_add_neg, Int.one_mul]
|
||||
rw [Int.neg_mul, ← Int.sub_eq_add_neg, Int.one_mul]
|
||||
split
|
||||
next h =>
|
||||
replace h := Int.le_of_sub_nonpos h
|
||||
rw [Int.ofNat_le] at h
|
||||
rw [Int.ofNat_sub h]
|
||||
next h =>
|
||||
have : ¬ (↑y : Int) ≤ ↑x := by
|
||||
intro h
|
||||
replace h := Int.sub_nonpos_of_le h
|
||||
contradiction
|
||||
rw [Int.ofNat_le] at this
|
||||
rw [Lean.Omega.Int.ofNat_sub_eq_zero this]
|
||||
|
||||
private theorem dvd_le_tight' {d p b₁ b₂ : Int} (hd : d > 0) (h₁ : d ∣ p + b₁) (h₂ : p + b₂ ≤ 0)
|
||||
: p + (b₁ - d*((b₁-b₂) / d)) ≤ 0 := by
|
||||
have ⟨k, h⟩ := h₁
|
||||
@@ -1881,31 +1855,6 @@ theorem of_not_dvd (a b : Int) : a != 0 → ¬ (a ∣ b) → b % a > 0 := by
|
||||
simp [h₁] at h₂
|
||||
assumption
|
||||
|
||||
@[expose]
|
||||
def le_of_le_cert (p q : Poly) (k : Nat) : Bool :=
|
||||
q == p.addConst (- k)
|
||||
|
||||
theorem le_of_le (ctx : Context) (p q : Poly) (k : Nat)
|
||||
: le_of_le_cert p q k → p.denote' ctx ≤ 0 → q.denote' ctx ≤ 0 := by
|
||||
simp [le_of_le_cert]; intro; subst q; simp
|
||||
intro h
|
||||
simp [Lean.Omega.Int.add_le_zero_iff_le_neg']
|
||||
exact Int.le_trans h (Int.ofNat_zero_le _)
|
||||
|
||||
@[expose]
|
||||
def not_le_of_le_cert (p q : Poly) (k : Nat) : Bool :=
|
||||
q == (p.mul (-1)).addConst (1 + k)
|
||||
|
||||
theorem not_le_of_le (ctx : Context) (p q : Poly) (k : Nat)
|
||||
: not_le_of_le_cert p q k → p.denote' ctx ≤ 0 → ¬ q.denote' ctx ≤ 0 := by
|
||||
simp [not_le_of_le_cert]; intro; subst q
|
||||
intro h
|
||||
apply Int.pos_of_neg_neg
|
||||
apply Int.lt_of_add_one_le
|
||||
simp [Int.neg_add]
|
||||
rw [← Int.add_assoc, ← Int.add_assoc, Int.add_neg_cancel_right, Lean.Omega.Int.add_le_zero_iff_le_neg']
|
||||
simp; exact Int.le_trans h (Int.ofNat_zero_le _)
|
||||
|
||||
@[expose]
|
||||
def eq_def_cert (x : Var) (xPoly : Poly) (p : Poly) : Bool :=
|
||||
p == .add (-1) x xPoly
|
||||
@@ -1950,6 +1899,62 @@ theorem diseq_norm_poly (ctx : Context) (p p' : Poly) : p.denote' ctx = p'.denot
|
||||
theorem dvd_norm_poly (ctx : Context) (d : Int) (p p' : Poly) : p.denote' ctx = p'.denote' ctx → d ∣ p.denote' ctx → d ∣ p'.denote' ctx := by
|
||||
intro h; rw [h]; simp
|
||||
|
||||
/-!
|
||||
Constraint propagation helper theorems.
|
||||
-/
|
||||
|
||||
@[expose]
|
||||
def le_of_le_cert (p₁ p₂ : Poly) : Bool :=
|
||||
match p₁, p₂ with
|
||||
| .add .., .num _ => false
|
||||
| .num _, .add .. => false
|
||||
| .num c₁, .num c₂ => c₁ ≥ c₂
|
||||
| .add a₁ x₁ p₁, .add a₂ x₂ p₂ => a₁ == a₂ && x₁ == x₂ && le_of_le_cert p₁ p₂
|
||||
|
||||
theorem le_of_le' (ctx : Context) (p₁ p₂ : Poly) : le_of_le_cert p₁ p₂ → ∀ k, p₁.denote' ctx ≤ k → p₂.denote' ctx ≤ k := by
|
||||
simp [Poly.denote'_eq_denote]
|
||||
fun_induction le_of_le_cert <;> simp [Poly.denote]
|
||||
next c₁ c₂ =>
|
||||
intro h k h₁
|
||||
exact Int.le_trans h h₁
|
||||
next a₁ x₁ p₁ a₂ x₂ p₂ ih =>
|
||||
intro _ _ h; subst a₁ x₁
|
||||
replace ih := ih h; clear h
|
||||
intro k h
|
||||
replace h : p₁.denote ctx ≤ k - a₂ * x₂.denote ctx := by omega
|
||||
replace ih := ih _ h
|
||||
omega
|
||||
|
||||
theorem le_of_le (ctx : Context) (p₁ p₂ : Poly) : le_of_le_cert p₁ p₂ → p₁.denote' ctx ≤ 0 → p₂.denote' ctx ≤ 0 :=
|
||||
fun h => le_of_le' ctx p₁ p₂ h 0
|
||||
|
||||
@[expose]
|
||||
def not_le_of_le_cert (p₁ p₂ : Poly) : Bool :=
|
||||
match p₁, p₂ with
|
||||
| .add .., .num _ => false
|
||||
| .num _, .add .. => false
|
||||
| .num c₁, .num c₂ => c₁ ≥ 1 - c₂
|
||||
| .add a₁ x₁ p₁, .add a₂ x₂ p₂ => a₁ == -a₂ && x₁ == x₂ && not_le_of_le_cert p₁ p₂
|
||||
|
||||
theorem not_le_of_le' (ctx : Context) (p₁ p₂ : Poly) : not_le_of_le_cert p₁ p₂ → ∀ k, p₁.denote' ctx ≤ k → ¬ (p₂.denote' ctx ≤ -k) := by
|
||||
simp [Poly.denote'_eq_denote]
|
||||
fun_induction not_le_of_le_cert <;> simp [Poly.denote]
|
||||
next c₁ c₂ =>
|
||||
intro h k h₁
|
||||
omega
|
||||
next a₁ x₁ p₁ a₂ x₂ p₂ ih =>
|
||||
intro _ _ h; subst a₁ x₁
|
||||
replace ih := ih h; clear h
|
||||
intro k h
|
||||
replace h : p₁.denote ctx ≤ k + a₂ * x₂.denote ctx := by rw [Int.neg_mul] at h; omega
|
||||
replace ih := ih _ h
|
||||
omega
|
||||
|
||||
theorem not_le_of_le (ctx : Context) (p₁ p₂ : Poly) : not_le_of_le_cert p₁ p₂ → p₁.denote' ctx ≤ 0 → ¬ (p₂.denote' ctx ≤ 0) := by
|
||||
intro h h₁
|
||||
have := not_le_of_le' ctx p₁ p₂ h 0 h₁; simp at this
|
||||
simp [*]
|
||||
|
||||
end Int.Linear
|
||||
|
||||
theorem Int.not_le_eq (a b : Int) : (¬a ≤ b) = (b + 1 ≤ a) := by
|
||||
|
||||
@@ -13,92 +13,91 @@ public import Init.Data.RArray
|
||||
|
||||
public section
|
||||
|
||||
namespace Int.OfNat
|
||||
/-!
|
||||
Helper definitions and theorems for converting `Nat` expressions into `Int` one.
|
||||
We use them to implement the arithmetic theories in `grind`
|
||||
-/
|
||||
namespace Nat.ToInt
|
||||
|
||||
abbrev Var := Nat
|
||||
abbrev Context := Lean.RArray Nat
|
||||
@[expose]
|
||||
def Var.denote (ctx : Context) (v : Var) : Nat :=
|
||||
ctx.get v
|
||||
theorem ofNat_toNat (a : Int) : (NatCast.natCast a.toNat : Int) = if a ≤ 0 then 0 else a := by simp [Int.max_def]
|
||||
|
||||
inductive Expr where
|
||||
| num (v : Nat)
|
||||
| var (i : Var)
|
||||
| add (a b : Expr)
|
||||
| mul (a b : Expr)
|
||||
| div (a b : Expr)
|
||||
| mod (a b : Expr)
|
||||
| pow (a : Expr) (k : Nat)
|
||||
deriving BEq
|
||||
theorem toNat_nonneg (x : Nat) : (-1:Int) * (NatCast.natCast x) ≤ 0 := by simp
|
||||
|
||||
@[expose]
|
||||
def Expr.denote (ctx : Context) : Expr → Nat
|
||||
| .num k => k
|
||||
| .var v => v.denote ctx
|
||||
| .add a b => Nat.add (denote ctx a) (denote ctx b)
|
||||
| .mul a b => Nat.mul (denote ctx a) (denote ctx b)
|
||||
| .div a b => Nat.div (denote ctx a) (denote ctx b)
|
||||
| .mod a b => Nat.mod (denote ctx a) (denote ctx b)
|
||||
| .pow a k => Nat.pow (denote ctx a) k
|
||||
theorem natCast_ofNat (n : Nat) : (NatCast.natCast (OfNat.ofNat n : Nat) : Int) = OfNat.ofNat n := by rfl
|
||||
|
||||
@[expose]
|
||||
def Expr.denoteAsInt (ctx : Context) : Expr → Int
|
||||
| .num k => Int.ofNat k
|
||||
| .var v => Int.ofNat (v.denote ctx)
|
||||
| .add a b => Int.add (denoteAsInt ctx a) (denoteAsInt ctx b)
|
||||
| .mul a b => Int.mul (denoteAsInt ctx a) (denoteAsInt ctx b)
|
||||
| .div a b => Int.ediv (denoteAsInt ctx a) (denoteAsInt ctx b)
|
||||
| .mod a b => Int.emod (denoteAsInt ctx a) (denoteAsInt ctx b)
|
||||
| .pow a k => Int.pow (denoteAsInt ctx a) k
|
||||
theorem of_eq {a b : Nat} {a' b' : Int}
|
||||
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : a = b → a' = b' := by
|
||||
intro h; replace h := congrArg (NatCast.natCast (R := Int)) h
|
||||
rw [h₁, h₂] at h; assumption
|
||||
|
||||
theorem Expr.denoteAsInt_eq (ctx : Context) (e : Expr) : e.denoteAsInt ctx = e.denote ctx := by
|
||||
induction e <;> simp [denote, denoteAsInt, *] <;> rfl
|
||||
theorem of_diseq {a b : Nat} {a' b' : Int}
|
||||
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : a ≠ b → a' ≠ b' := by
|
||||
intro hne h; rw [← h₁, ← h₂] at h
|
||||
replace h := Int.ofNat_inj.mp h; contradiction
|
||||
|
||||
theorem Expr.eq_denoteAsInt (ctx : Context) (e : Expr) : e.denote ctx = e.denoteAsInt ctx := by
|
||||
apply Eq.symm; apply denoteAsInt_eq
|
||||
theorem of_dvd (d a : Nat) (d' a' : Int)
|
||||
(h₁ : NatCast.natCast d = d') (h₂ : NatCast.natCast a = a') : d ∣ a → d' ∣ a' := by
|
||||
simp [← h₁, ←h₂, Int.ofNat_dvd]
|
||||
|
||||
theorem Expr.eq (ctx : Context) (lhs rhs : Expr)
|
||||
: (lhs.denote ctx = rhs.denote ctx) = (lhs.denoteAsInt ctx = rhs.denoteAsInt ctx) := by
|
||||
simp [denoteAsInt_eq, Int.ofNat_inj]
|
||||
theorem of_le {a b : Nat} {a' b' : Int}
|
||||
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : a ≤ b → a' ≤ b' := by
|
||||
intro h; replace h := Int.ofNat_le |>.mpr h
|
||||
rw [← h₁, ← h₂]; assumption
|
||||
|
||||
theorem Expr.le (ctx : Context) (lhs rhs : Expr)
|
||||
: (lhs.denote ctx ≤ rhs.denote ctx) = (lhs.denoteAsInt ctx ≤ rhs.denoteAsInt ctx) := by
|
||||
simp [denoteAsInt_eq, Int.ofNat_le]
|
||||
theorem of_not_le {a b : Nat} {a' b' : Int}
|
||||
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : ¬ (a ≤ b) → b' + 1 ≤ a' := by
|
||||
intro h; rw [← Int.ofNat_le] at h
|
||||
rw [← h₁, ← h₂]; show (↑b + 1 : Int) ≤ a; omega
|
||||
|
||||
theorem of_le (ctx : Context) (lhs rhs : Expr)
|
||||
: lhs.denote ctx ≤ rhs.denote ctx → lhs.denoteAsInt ctx ≤ rhs.denoteAsInt ctx := by
|
||||
rw [Expr.le ctx lhs rhs]; simp
|
||||
theorem add_congr {a b : Nat} {a' b' : Int}
|
||||
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : NatCast.natCast (a + b) = a' + b' := by
|
||||
simp_all [Int.natCast_add]
|
||||
|
||||
theorem of_not_le (ctx : Context) (lhs rhs : Expr)
|
||||
: ¬ lhs.denote ctx ≤ rhs.denote ctx → ¬ lhs.denoteAsInt ctx ≤ rhs.denoteAsInt ctx := by
|
||||
rw [Expr.le ctx lhs rhs]; simp
|
||||
theorem mul_congr {a b : Nat} {a' b' : Int}
|
||||
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : NatCast.natCast (a * b) = a' * b' := by
|
||||
simp_all [Int.natCast_mul]
|
||||
|
||||
theorem of_dvd (ctx : Context) (d : Nat) (e : Expr)
|
||||
: d ∣ e.denote ctx → Int.ofNat d ∣ e.denoteAsInt ctx := by
|
||||
simp [Expr.denoteAsInt_eq, Int.ofNat_dvd]
|
||||
|
||||
theorem of_eq (ctx : Context) (lhs rhs : Expr)
|
||||
: lhs.denote ctx = rhs.denote ctx → lhs.denoteAsInt ctx = rhs.denoteAsInt ctx := by
|
||||
rw [Expr.eq ctx lhs rhs]; simp
|
||||
|
||||
theorem of_not_eq (ctx : Context) (lhs rhs : Expr)
|
||||
: ¬ lhs.denote ctx = rhs.denote ctx → ¬ lhs.denoteAsInt ctx = rhs.denoteAsInt ctx := by
|
||||
rw [Expr.eq ctx lhs rhs]; simp
|
||||
|
||||
theorem ofNat_toNat (a : Int) : (NatCast.natCast a.toNat : Int) = if a ≤ 0 then 0 else a := by
|
||||
theorem sub_congr {a b : Nat} {a' b' : Int}
|
||||
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : NatCast.natCast (a - b) = if b' + (-1)*a' ≤ 0 then a' - b' else 0 := by
|
||||
rw [Int.neg_mul, ← Int.sub_eq_add_neg, Int.one_mul]
|
||||
split
|
||||
next h =>
|
||||
rw [Int.toNat_of_nonpos h]; rfl
|
||||
have h := Int.le_of_sub_nonpos h
|
||||
simp [← h₁, ← h₂, Int.ofNat_le] at h
|
||||
simp [Int.ofNat_sub h]
|
||||
rw [← h₁, ← h₂]
|
||||
next h =>
|
||||
simp at h
|
||||
have := Int.toNat_of_nonneg (Int.le_of_lt h)
|
||||
assumption
|
||||
have : ¬ (↑b : Int) ≤ ↑a := by
|
||||
intro h
|
||||
replace h := Int.sub_nonpos_of_le h
|
||||
simp [h₁, h₂] at h
|
||||
contradiction
|
||||
rw [Int.ofNat_le] at this
|
||||
simp [Lean.Omega.Int.ofNat_sub_eq_zero this]
|
||||
|
||||
theorem Expr.denoteAsInt_nonneg (ctx : Context) (e : Expr) : 0 ≤ e.denoteAsInt ctx := by
|
||||
simp [Expr.denoteAsInt_eq]
|
||||
theorem pow_congr {a : Nat} (k : Nat) (a' : Int)
|
||||
(h₁ : NatCast.natCast a = a') : NatCast.natCast (a ^ k) = a' ^ k := by
|
||||
simp_all [Int.natCast_pow]
|
||||
|
||||
end Int.OfNat
|
||||
theorem div_congr {a b : Nat} {a' b' : Int}
|
||||
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : NatCast.natCast (a / b) = a' / b' := by
|
||||
simp_all [Int.natCast_ediv]
|
||||
|
||||
theorem mod_congr {a b : Nat} {a' b' : Int}
|
||||
(h₁ : NatCast.natCast a = a') (h₂ : NatCast.natCast b = b') : NatCast.natCast (a % b) = a' % b' := by
|
||||
simp_all [Int.natCast_emod]
|
||||
|
||||
end Nat.ToInt
|
||||
|
||||
namespace Int.Nonneg
|
||||
|
||||
@[expose] def num_cert (a : Int) : Bool := a ≥ 0
|
||||
theorem num (a : Int) : num_cert a → a ≥ 0 := by simp [num_cert]
|
||||
theorem add (a b : Int) (h₁ : a ≥ 0) (h₂ : b ≥ 0) : a + b ≥ 0 := by exact Int.add_nonneg h₁ h₂
|
||||
theorem mul (a b : Int) (h₁ : a ≥ 0) (h₂ : b ≥ 0) : a * b ≥ 0 := by exact Int.mul_nonneg h₁ h₂
|
||||
theorem div (a b : Int) (h₁ : a ≥ 0) (h₂ : b ≥ 0) : a / b ≥ 0 := by exact Int.ediv_nonneg h₁ h₂
|
||||
theorem pow (a : Int) (k : Nat) (h₁ : a ≥ 0) : a ^ k ≥ 0 := by exact Int.pow_nonneg h₁
|
||||
theorem mod (a b : Int) (h₁ : a ≥ 0) : a % b ≥ 0 := by
|
||||
by_cases b = 0
|
||||
next => simp [*]
|
||||
next h => exact emod_nonneg a h
|
||||
theorem natCast (a : Nat) : (NatCast.natCast a : Int) ≥ 0 := by simp
|
||||
theorem toPoly (e : Int) : e ≥ 0 → -1 * e ≤ 0 := by omega
|
||||
|
||||
end Int.Nonneg
|
||||
|
||||
@@ -10,7 +10,7 @@ public import Init.Data.Iterators.Consumers.Partial
|
||||
public import Init.Data.Iterators.Consumers.Loop
|
||||
public import Init.Data.Iterators.Consumers.Monadic.Access
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
|
||||
namespace Std.Iterators
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ public import Init.Data.Iterators.Basic
|
||||
public import Init.Data.Iterators.Consumers.Partial
|
||||
public import Init.Data.Iterators.Consumers.Monadic.Collect
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
|
||||
/-!
|
||||
# Collectors
|
||||
|
||||
@@ -9,7 +9,7 @@ prelude
|
||||
public import Init.Data.Iterators.Consumers.Monadic.Partial
|
||||
public import Init.Data.Iterators.Internal.LawfulMonadLiftFunction
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
|
||||
/-!
|
||||
# Collectors
|
||||
|
||||
@@ -9,6 +9,7 @@ prelude
|
||||
public import Init.RCases
|
||||
public import Init.Data.Iterators.Basic
|
||||
public import Init.Data.Iterators.Consumers.Monadic.Partial
|
||||
public import Init.Data.Iterators.Internal.LawfulMonadLiftFunction
|
||||
|
||||
public section
|
||||
|
||||
@@ -32,6 +33,8 @@ asserts that an `IteratorLoop` instance equals the default implementation.
|
||||
|
||||
namespace Std.Iterators
|
||||
|
||||
open Std.Internal
|
||||
|
||||
section Typeclasses
|
||||
|
||||
/--
|
||||
@@ -39,6 +42,7 @@ Relation that needs to be well-formed in order for a loop over an iterator to te
|
||||
It is assumed that the `plausible_forInStep` predicate relates the input and output of the
|
||||
stepper function.
|
||||
-/
|
||||
@[expose]
|
||||
def IteratorLoop.rel (α : Type w) (m : Type w → Type w') {β : Type w} [Iterator α m β]
|
||||
{γ : Type x} (plausible_forInStep : β → γ → ForInStep γ → Prop)
|
||||
(p' p : IterM (α := α) m β × γ) : Prop :=
|
||||
@@ -48,6 +52,7 @@ def IteratorLoop.rel (α : Type w) (m : Type w → Type w') {β : Type w} [Itera
|
||||
/--
|
||||
Asserts that `IteratorLoop.rel` is well-founded.
|
||||
-/
|
||||
@[expose]
|
||||
def IteratorLoop.WellFounded (α : Type w) (m : Type w → Type w') {β : Type w} [Iterator α m β]
|
||||
{γ : Type x} (plausible_forInStep : β → γ → ForInStep γ → Prop) : Prop :=
|
||||
_root_.WellFounded (IteratorLoop.rel α m plausible_forInStep)
|
||||
@@ -61,6 +66,7 @@ This class is experimental and users of the iterator API should not explicitly d
|
||||
They can, however, assume that consumers that require an instance will work for all iterators
|
||||
provided by the standard library.
|
||||
-/
|
||||
@[ext]
|
||||
class IteratorLoop (α : Type w) (m : Type w → Type w') {β : Type w} [Iterator α m β]
|
||||
(n : Type x → Type x') where
|
||||
forIn : ∀ (_liftBind : (γ : Type w) → (δ : Type x) → (γ → n δ) → m γ → n δ) (γ : Type x),
|
||||
@@ -108,29 +114,24 @@ class IteratorSizePartial (α : Type w) (m : Type w → Type w') {β : Type w} [
|
||||
end Typeclasses
|
||||
|
||||
/-- Internal implementation detail of the iterator library. -/
|
||||
def IteratorLoop.WFRel {α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β]
|
||||
{γ : Type x} {plausible_forInStep : β → γ → ForInStep γ → Prop}
|
||||
(_wf : WellFounded α m plausible_forInStep) :=
|
||||
IterM (α := α) m β × γ
|
||||
structure IteratorLoop.WithWF (α : Type w) (m : Type w → Type w') {β : Type w} [Iterator α m β]
|
||||
{γ : Type x} (PlausibleForInStep : β → γ → ForInStep γ → Prop)
|
||||
(hwf : IteratorLoop.WellFounded α m PlausibleForInStep) where
|
||||
it : IterM (α := α) m β
|
||||
acc : γ
|
||||
|
||||
/-- Internal implementation detail of the iterator library. -/
|
||||
def IteratorLoop.WFRel.mk {α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β]
|
||||
{γ : Type x} {plausible_forInStep : β → γ → ForInStep γ → Prop}
|
||||
(wf : WellFounded α m plausible_forInStep) (it : IterM (α := α) m β) (c : γ) :
|
||||
IteratorLoop.WFRel wf :=
|
||||
(it, c)
|
||||
|
||||
private instance {α : Type w} {m : Type w → Type w'} {β : Type w} [Iterator α m β]
|
||||
{γ : Type x} {plausible_forInStep : β → γ → ForInStep γ → Prop}
|
||||
(wf : IteratorLoop.WellFounded α m plausible_forInStep) :
|
||||
WellFoundedRelation (IteratorLoop.WFRel wf) where
|
||||
rel := IteratorLoop.rel α m plausible_forInStep
|
||||
wf := wf
|
||||
instance IteratorLoop.WithWF.instWellFoundedRelation
|
||||
(α : Type w) (m : Type w → Type w') {β : Type w} [Iterator α m β]
|
||||
{γ : Type x} (PlausibleForInStep : β → γ → ForInStep γ → Prop)
|
||||
(hwf : IteratorLoop.WellFounded α m PlausibleForInStep) :
|
||||
WellFoundedRelation (WithWF α m PlausibleForInStep hwf) where
|
||||
rel := InvImage (IteratorLoop.rel α m PlausibleForInStep) (fun x => (x.it, x.acc))
|
||||
wf := by exact InvImage.wf _ hwf
|
||||
|
||||
/--
|
||||
This is the loop implementation of the default instance `IteratorLoop.defaultImplementation`.
|
||||
-/
|
||||
@[specialize]
|
||||
@[specialize, expose]
|
||||
def IterM.DefaultConsumers.forIn' {m : Type w → Type w'} {α : Type w} {β : Type w}
|
||||
[Iterator α m β]
|
||||
{n : Type x → Type x'} [Monad n]
|
||||
@@ -142,27 +143,59 @@ def IterM.DefaultConsumers.forIn' {m : Type w → Type w'} {α : Type w} {β : T
|
||||
(f : (b : β) → P b → (c : γ) → n (Subtype (plausible_forInStep b c))) : n γ :=
|
||||
haveI : WellFounded _ := wf
|
||||
(lift _ _ · it.step) fun
|
||||
| .yield it' out h => do
|
||||
match ← f out (hP _ <| .direct ⟨_, h⟩) init with
|
||||
| ⟨.yield c, _⟩ =>
|
||||
IterM.DefaultConsumers.forIn' lift _ plausible_forInStep wf it' c P
|
||||
(fun _ h' => hP _ <| .indirect ⟨_, rfl, h⟩ h') f
|
||||
| ⟨.done c, _⟩ => return c
|
||||
| .skip it' h =>
|
||||
IterM.DefaultConsumers.forIn' lift _ plausible_forInStep wf it' init P
|
||||
(fun _ h' => hP _ <| .indirect ⟨_, rfl, h⟩ h') f
|
||||
| .done _ => return init
|
||||
termination_by IteratorLoop.WFRel.mk wf it init
|
||||
| .yield it' out h => do
|
||||
match ← f out (hP _ <| .direct ⟨_, h⟩) init with
|
||||
| ⟨.yield c, _⟩ =>
|
||||
IterM.DefaultConsumers.forIn' lift _ plausible_forInStep wf it' c P
|
||||
(fun _ h' => hP _ <| .indirect ⟨_, rfl, h⟩ h') f
|
||||
| ⟨.done c, _⟩ => return c
|
||||
| .skip it' h =>
|
||||
IterM.DefaultConsumers.forIn' lift _ plausible_forInStep wf it' init P
|
||||
(fun _ h' => hP _ <| .indirect ⟨_, rfl, h⟩ h') f
|
||||
| .done _ => return init
|
||||
termination_by IteratorLoop.WithWF.mk it init (hwf := wf)
|
||||
decreasing_by
|
||||
· exact Or.inl ⟨out, ‹_›, ‹_›⟩
|
||||
· exact Or.inr ⟨‹_›, rfl⟩
|
||||
|
||||
theorem IterM.DefaultConsumers.forIn'_eq_forIn' {m : Type w → Type w'} {α : Type w} {β : Type w}
|
||||
[Iterator α m β]
|
||||
{n : Type x → Type x'} [Monad n]
|
||||
{lift : ∀ γ δ, (γ → n δ) → m γ → n δ} {γ : Type x}
|
||||
{Pl : β → γ → ForInStep γ → Prop}
|
||||
{wf : IteratorLoop.WellFounded α m Pl}
|
||||
{it : IterM (α := α) m β} {init : γ}
|
||||
{P : β → Prop} {hP : ∀ b, it.IsPlausibleIndirectOutput b → P b}
|
||||
{Q : β → Prop} {hQ : ∀ b, it.IsPlausibleIndirectOutput b → Q b}
|
||||
{f : (b : β) → P b → (c : γ) → n (Subtype (Pl b c))}
|
||||
{g : (b : β) → Q b → (c : γ) → n (Subtype (Pl b c))}
|
||||
(hfg : ∀ b c, (hPb : P b) → (hQb : Q b) → f b hPb c = g b hQb c) :
|
||||
IterM.DefaultConsumers.forIn' lift γ Pl wf it init P hP f =
|
||||
IterM.DefaultConsumers.forIn' lift γ Pl wf it init Q hQ g := by
|
||||
rw [forIn', forIn']
|
||||
congr; ext step
|
||||
split
|
||||
· congr
|
||||
· apply hfg
|
||||
· ext
|
||||
split
|
||||
· apply IterM.DefaultConsumers.forIn'_eq_forIn'
|
||||
assumption
|
||||
· rfl
|
||||
· apply IterM.DefaultConsumers.forIn'_eq_forIn'
|
||||
assumption
|
||||
· rfl
|
||||
termination_by IteratorLoop.WithWF.mk it init (hwf := wf)
|
||||
decreasing_by
|
||||
· exact Or.inl ⟨_, ‹_›, ‹_›⟩
|
||||
· exact Or.inr ⟨‹_›, rfl⟩
|
||||
|
||||
/--
|
||||
This is the default implementation of the `IteratorLoop` class.
|
||||
It simply iterates through the iterator using `IterM.step`. For certain iterators, more efficient
|
||||
implementations are possible and should be used instead.
|
||||
-/
|
||||
@[always_inline, inline]
|
||||
@[always_inline, inline, expose]
|
||||
def IteratorLoop.defaultImplementation {α : Type w} {m : Type w → Type w'} {n : Type x → Type x'}
|
||||
[Monad n] [Iterator α m β] :
|
||||
IteratorLoop α m n where
|
||||
@@ -173,8 +206,9 @@ Asserts that a given `IteratorLoop` instance is equal to `IteratorLoop.defaultIm
|
||||
(Even though equal, the given instance might be vastly more efficient.)
|
||||
-/
|
||||
class LawfulIteratorLoop (α : Type w) (m : Type w → Type w') (n : Type x → Type x')
|
||||
[Monad n] [Iterator α m β] [Finite α m] [i : IteratorLoop α m n] where
|
||||
lawful : i = .defaultImplementation
|
||||
[Monad m] [Monad n] [Iterator α m β] [i : IteratorLoop α m n] where
|
||||
lawful : ∀ lift [LawfulMonadLiftBindFunction lift], i.forIn lift =
|
||||
IteratorLoop.defaultImplementation.forIn lift
|
||||
|
||||
/--
|
||||
This is the loop implementation of the default instance `IteratorLoopPartial.defaultImplementation`.
|
||||
@@ -214,7 +248,7 @@ instance (α : Type w) (m : Type w → Type w') (n : Type x → Type x')
|
||||
letI : IteratorLoop α m n := .defaultImplementation
|
||||
LawfulIteratorLoop α m n :=
|
||||
letI : IteratorLoop α m n := .defaultImplementation
|
||||
⟨rfl⟩
|
||||
⟨fun _ => rfl⟩
|
||||
|
||||
theorem IteratorLoop.wellFounded_of_finite {m : Type w → Type w'}
|
||||
{α β : Type w} {γ : Type x} [Iterator α m β] [Finite α m] :
|
||||
|
||||
@@ -24,6 +24,12 @@ the requirement that the `MonadLift(T)` instance induced by `f` admits a
|
||||
|
||||
namespace Std.Internal
|
||||
|
||||
class LawfulMonadLiftBindFunction {m : Type u → Type v} {n : Type w → Type x} [Monad m]
|
||||
[Monad n] (liftBind : ∀ γ δ, (γ → n δ) → m γ → n δ) where
|
||||
liftBind_pure {γ δ} (f : γ → n δ) (a : γ) : liftBind γ δ f (pure a) = f a
|
||||
liftBind_bind {β γ δ} (f : γ → n δ) (x : m β) (g : β → m γ) :
|
||||
liftBind γ δ f (x >>= g) = liftBind β δ (fun b => liftBind γ δ f (g b)) x
|
||||
|
||||
class LawfulMonadLiftFunction {m : Type u → Type v} {n : Type u → Type w}
|
||||
[Monad m] [Monad n] (lift : ⦃α : Type u⦄ → m α → n α) where
|
||||
lift_pure {α : Type u} (a : α) : lift (pure a) = pure a
|
||||
@@ -79,4 +85,35 @@ instance [LawfulMonadLiftFunction lift] :
|
||||
{ monadLift_pure := LawfulMonadLiftFunction.lift_pure
|
||||
monadLift_bind := LawfulMonadLiftFunction.lift_bind }
|
||||
|
||||
section LiftBind
|
||||
|
||||
variable {liftBind : ∀ γ δ, (γ → m δ) → m γ → m δ}
|
||||
|
||||
instance [LawfulMonadLiftBindFunction (n := n) (fun _ _ f x => lift x >>= f)] [LawfulMonad n] :
|
||||
LawfulMonadLiftFunction lift where
|
||||
lift_pure {γ} a := by
|
||||
simpa using LawfulMonadLiftBindFunction.liftBind_pure (n := n)
|
||||
(liftBind := fun _ _ f x => lift x >>= f) (γ := γ) (δ := γ) pure a
|
||||
lift_bind {β γ} x g := by
|
||||
simpa using LawfulMonadLiftBindFunction.liftBind_bind (n := n)
|
||||
(liftBind := fun _ _ f x => lift x >>= f) (β := β) (γ := γ) (δ := γ) pure x g
|
||||
|
||||
def LawfulMonadLiftBindFunction.id [Monad m] [LawfulMonad m] :
|
||||
LawfulMonadLiftBindFunction (m := Id) (n := m) (fun _ _ f x => f x.run) where
|
||||
liftBind_pure := by simp
|
||||
liftBind_bind := by simp
|
||||
|
||||
instance {m : Type u → Type v} [Monad m] {n : Type u → Type w} [Monad n] [MonadLiftT m n]
|
||||
[LawfulMonadLiftT m n] [LawfulMonad n] :
|
||||
LawfulMonadLiftBindFunction (fun γ δ (f : γ → n δ) (x : m γ) => monadLift x >>= f) where
|
||||
liftBind_pure := by simp
|
||||
liftBind_bind := by simp
|
||||
|
||||
instance {n : Type u → Type w} [Monad n] [LawfulMonad n] :
|
||||
LawfulMonadLiftBindFunction (fun γ δ (f : γ → n δ) (x : Id γ) => f x.run) where
|
||||
liftBind_pure := by simp
|
||||
liftBind_bind := by simp
|
||||
|
||||
end LiftBind
|
||||
|
||||
end Std.Internal
|
||||
|
||||
@@ -6,6 +6,7 @@ Authors: Paul Reichert
|
||||
module
|
||||
|
||||
prelude
|
||||
public import Init.Control.Lawful.MonadLift.Instances
|
||||
public import Init.Data.Iterators.Lemmas.Consumers.Collect
|
||||
public import all Init.Data.Iterators.Lemmas.Consumers.Monadic.Loop
|
||||
public import all Init.Data.Iterators.Consumers.Loop
|
||||
@@ -16,7 +17,7 @@ public section
|
||||
namespace Std.Iterators
|
||||
|
||||
theorem Iter.forIn'_eq {α β : Type w} [Iterator α Id β] [Finite α Id]
|
||||
{m : Type x → Type x'} [Monad m] [IteratorLoop α Id m] [hl : LawfulIteratorLoop α Id m]
|
||||
{m : Type x → Type x'} [Monad m] [LawfulMonad m] [IteratorLoop α Id m] [hl : LawfulIteratorLoop α Id m]
|
||||
{γ : Type x} {it : Iter (α := α) β} {init : γ}
|
||||
{f : (b : β) → it.IsPlausibleIndirectOutput b → γ → m (ForInStep γ)} :
|
||||
letI : ForIn' m (Iter (α := α) β) β _ := Iter.instForIn'
|
||||
@@ -25,21 +26,22 @@ theorem Iter.forIn'_eq {α β : Type w} [Iterator α Id β] [Finite α Id]
|
||||
IteratorLoop.wellFounded_of_finite it.toIterM init _ (fun _ => id)
|
||||
(fun out h acc => (⟨·, .intro⟩) <$>
|
||||
f out (Iter.isPlausibleIndirectOutput_iff_isPlausibleIndirectOutput_toIterM.mpr h) acc) := by
|
||||
cases hl.lawful; rfl
|
||||
simp [instForIn', ForIn'.forIn', IteratorLoop.finiteForIn', hl.lawful (fun γ δ f x => f x.run),
|
||||
IteratorLoop.defaultImplementation]
|
||||
|
||||
theorem Iter.forIn_eq {α β : Type w} [Iterator α Id β] [Finite α Id]
|
||||
{m : Type x → Type x'} [Monad m] [IteratorLoop α Id m] [hl : LawfulIteratorLoop α Id m]
|
||||
{γ : Type x} {it : Iter (α := α) β} {init : γ}
|
||||
{m : Type x → Type x'} [Monad m] [LawfulMonad m] [IteratorLoop α Id m]
|
||||
[hl : LawfulIteratorLoop α Id m] {γ : Type x} {it : Iter (α := α) β} {init : γ}
|
||||
{f : (b : β) → γ → m (ForInStep γ)} :
|
||||
ForIn.forIn it init f =
|
||||
IterM.DefaultConsumers.forIn' (fun _ _ f c => f c.run) γ (fun _ _ _ => True)
|
||||
IteratorLoop.wellFounded_of_finite it.toIterM init _ (fun _ => id)
|
||||
(fun out _ acc => (⟨·, .intro⟩) <$>
|
||||
f out acc) := by
|
||||
cases hl.lawful; rfl
|
||||
simp [ForIn.forIn, forIn'_eq, -forIn'_eq_forIn]
|
||||
|
||||
theorem Iter.forIn'_eq_forIn'_toIterM {α β : Type w} [Iterator α Id β]
|
||||
[Finite α Id] {m : Type w → Type w'} [Monad m] [LawfulMonad m]
|
||||
[Finite α Id] {m : Type w → Type w''} [Monad m] [LawfulMonad m]
|
||||
[IteratorLoop α Id m] [LawfulIteratorLoop α Id m]
|
||||
{γ : Type w} {it : Iter (α := α) β} {init : γ}
|
||||
{f : (out : β) → _ → γ → m (ForInStep γ)} :
|
||||
|
||||
@@ -38,60 +38,31 @@ theorem IterM.DefaultConsumers.forIn'_eq_match_step {α β : Type w} {m : Type w
|
||||
cases step using PlausibleIterStep.casesOn <;> rfl
|
||||
|
||||
theorem IterM.forIn'_eq {α β : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
|
||||
{n : Type w → Type w''} [Monad n] [IteratorLoop α m n] [hl : LawfulIteratorLoop α m n]
|
||||
[MonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
|
||||
{n : Type w → Type w''} [Monad m] [Monad n] [LawfulMonad n] [IteratorLoop α m n]
|
||||
[hl : LawfulIteratorLoop α m n]
|
||||
[MonadLiftT m n] [LawfulMonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
|
||||
{f : (b : β) → it.IsPlausibleIndirectOutput b → γ → n (ForInStep γ)} :
|
||||
letI : ForIn' n (IterM (α := α) m β) β _ := IterM.instForIn'
|
||||
ForIn'.forIn' it init f = IterM.DefaultConsumers.forIn' (n := n)
|
||||
(fun _ _ f x => monadLift x >>= f) γ (fun _ _ _ => True)
|
||||
IteratorLoop.wellFounded_of_finite it init _ (fun _ => id) ((⟨·, .intro⟩) <$> f · · ·) := by
|
||||
cases hl.lawful; rfl
|
||||
simp [instForIn', ForIn'.forIn', IteratorLoop.finiteForIn',
|
||||
hl.lawful (fun _ _ f x => monadLift x >>= f), IteratorLoop.defaultImplementation]
|
||||
|
||||
theorem IterM.forIn_eq {α β : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
|
||||
{n : Type w → Type w''} [Monad n] [IteratorLoop α m n] [hl : LawfulIteratorLoop α m n]
|
||||
[MonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
|
||||
{n : Type w → Type w''} [Monad m] [Monad n] [LawfulMonad n] [IteratorLoop α m n]
|
||||
[hl : LawfulIteratorLoop α m n]
|
||||
[MonadLiftT m n] [LawfulMonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
|
||||
{f : β → γ → n (ForInStep γ)} :
|
||||
ForIn.forIn it init f = IterM.DefaultConsumers.forIn' (n := n)
|
||||
(fun _ _ f x => monadLift x >>= f) γ (fun _ _ _ => True)
|
||||
IteratorLoop.wellFounded_of_finite it init _ (fun _ => id) (fun out _ acc => (⟨·, .intro⟩) <$> f out acc) := by
|
||||
cases hl.lawful; rfl
|
||||
|
||||
theorem IterM.DefaultConsumers.forIn'_eq_forIn' {m : Type w → Type w'} {α : Type w} {β : Type w}
|
||||
[Iterator α m β]
|
||||
{n : Type x → Type x'} [Monad n]
|
||||
{liftBind : ∀ γ δ, (γ → n δ) → m γ → n δ} {γ : Type x}
|
||||
{Pl : β → γ → ForInStep γ → Prop}
|
||||
{wf : IteratorLoop.WellFounded α m Pl}
|
||||
{it : IterM (α := α) m β} {init : γ}
|
||||
{P : β → Prop} {hP : ∀ b, it.IsPlausibleIndirectOutput b → P b}
|
||||
{Q : β → Prop} {hQ : ∀ b, it.IsPlausibleIndirectOutput b → Q b}
|
||||
{f : (b : β) → P b → (c : γ) → n (Subtype (Pl b c))}
|
||||
{g : (b : β) → Q b → (c : γ) → n (Subtype (Pl b c))}
|
||||
(hfg : ∀ b c, (hPb : P b) → (hQb : Q b) → f b hPb c = g b hQb c) :
|
||||
IterM.DefaultConsumers.forIn' liftBind γ Pl wf it init P hP f =
|
||||
IterM.DefaultConsumers.forIn' liftBind γ Pl wf it init Q hQ g := by
|
||||
rw [forIn', forIn']
|
||||
congr; ext step
|
||||
split
|
||||
· congr
|
||||
· apply hfg
|
||||
· ext
|
||||
split
|
||||
· apply IterM.DefaultConsumers.forIn'_eq_forIn'
|
||||
assumption
|
||||
· rfl
|
||||
· apply IterM.DefaultConsumers.forIn'_eq_forIn'
|
||||
assumption
|
||||
· rfl
|
||||
termination_by IteratorLoop.WFRel.mk wf it init
|
||||
decreasing_by
|
||||
· exact Or.inl ⟨_, ‹_›, ‹_›⟩
|
||||
· exact Or.inr ⟨‹_›, rfl⟩
|
||||
simp only [ForIn.forIn, forIn'_eq]
|
||||
|
||||
theorem IterM.forIn'_eq_match_step {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
|
||||
[Finite α m] {n : Type w → Type w''} [Monad n] [LawfulMonad n]
|
||||
[Finite α m] {n : Type w → Type w''} [Monad m] [Monad n] [LawfulMonad n]
|
||||
[IteratorLoop α m n] [LawfulIteratorLoop α m n]
|
||||
[MonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
|
||||
[MonadLiftT m n] [LawfulMonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
|
||||
{f : (out : β) → _ → γ → n (ForInStep γ)} :
|
||||
letI : ForIn' n (IterM (α := α) m β) β _ := IterM.instForIn'
|
||||
ForIn'.forIn' it init f = (do
|
||||
@@ -124,9 +95,9 @@ theorem IterM.forIn'_eq_match_step {α β : Type w} {m : Type w → Type w'} [It
|
||||
· simp
|
||||
|
||||
theorem IterM.forIn_eq_match_step {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
|
||||
[Finite α m] {n : Type w → Type w''} [Monad n] [LawfulMonad n]
|
||||
[Finite α m] {n : Type w → Type w''} [Monad m] [Monad n] [LawfulMonad n]
|
||||
[IteratorLoop α m n] [LawfulIteratorLoop α m n]
|
||||
[MonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
|
||||
[MonadLiftT m n] [LawfulMonadLiftT m n] {γ : Type w} {it : IterM (α := α) m β} {init : γ}
|
||||
{f : β → γ → n (ForInStep γ)} :
|
||||
ForIn.forIn it init f = (do
|
||||
match ← it.step with
|
||||
@@ -140,7 +111,7 @@ theorem IterM.forIn_eq_match_step {α β : Type w} {m : Type w → Type w'} [Ite
|
||||
exact forIn'_eq_match_step
|
||||
|
||||
theorem IterM.forM_eq_forIn {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
|
||||
[Finite α m] {n : Type w → Type w''} [Monad n] [LawfulMonad n]
|
||||
[Finite α m] {n : Type w → Type w''} [Monad m] [Monad n] [LawfulMonad n]
|
||||
[IteratorLoop α m n] [LawfulIteratorLoop α m n]
|
||||
[MonadLiftT m n] {it : IterM (α := α) m β}
|
||||
{f : β → n PUnit} :
|
||||
@@ -148,9 +119,9 @@ theorem IterM.forM_eq_forIn {α β : Type w} {m : Type w → Type w'} [Iterator
|
||||
rfl
|
||||
|
||||
theorem IterM.forM_eq_match_step {α β : Type w} {m : Type w → Type w'} [Iterator α m β]
|
||||
[Finite α m] {n : Type w → Type w''} [Monad n] [LawfulMonad n]
|
||||
[Finite α m] {n : Type w → Type w''} [Monad m] [Monad n] [LawfulMonad n]
|
||||
[IteratorLoop α m n] [LawfulIteratorLoop α m n]
|
||||
[MonadLiftT m n] {it : IterM (α := α) m β}
|
||||
[MonadLiftT m n] [LawfulMonadLiftT m n] {it : IterM (α := α) m β}
|
||||
{f : β → n PUnit} :
|
||||
ForM.forM it f = (do
|
||||
match ← it.step with
|
||||
@@ -171,7 +142,7 @@ theorem IterM.foldM_eq_forIn {α β γ : Type w} {m : Type w → Type w'} [Itera
|
||||
(rfl)
|
||||
|
||||
theorem IterM.forIn_yield_eq_foldM {α β γ δ : Type w} {m : Type w → Type w'} [Iterator α m β]
|
||||
[Finite α m] {n : Type w → Type w''} [Monad n] [LawfulMonad n] [IteratorLoop α m n]
|
||||
[Finite α m] {n : Type w → Type w''} [Monad m] [Monad n] [LawfulMonad n] [IteratorLoop α m n]
|
||||
[LawfulIteratorLoop α m n] [MonadLiftT m n] {f : β → γ → n δ} {g : β → γ → δ → γ} {init : γ}
|
||||
{it : IterM (α := α) m β} :
|
||||
ForIn.forIn it init (fun c b => (fun d => .yield (g c b d)) <$> f c b) =
|
||||
@@ -179,8 +150,9 @@ theorem IterM.forIn_yield_eq_foldM {α β γ δ : Type w} {m : Type w → Type w
|
||||
simp [IterM.foldM_eq_forIn]
|
||||
|
||||
theorem IterM.foldM_eq_match_step {α β γ : Type w} {m : Type w → Type w'} [Iterator α m β] [Finite α m]
|
||||
{n : Type w → Type w''} [Monad n] [LawfulMonad n] [IteratorLoop α m n] [LawfulIteratorLoop α m n]
|
||||
[MonadLiftT m n] {f : γ → β → n γ} {init : γ} {it : IterM (α := α) m β} :
|
||||
{n : Type w → Type w''} [Monad m] [Monad n] [LawfulMonad n] [IteratorLoop α m n]
|
||||
[LawfulIteratorLoop α m n] [MonadLiftT m n] [LawfulMonadLiftT m n]
|
||||
{f : γ → β → n γ} {init : γ} {it : IterM (α := α) m β} :
|
||||
it.foldM (init := init) f = (do
|
||||
match ← it.step with
|
||||
| .yield it' out _ => it'.foldM (init := ← f init out) f
|
||||
|
||||
@@ -1369,7 +1369,7 @@ Each element of a list is related to all later elements of the list by `R`.
|
||||
`Pairwise R l` means that all the elements of `l` with earlier indexes are `R`-related to all the
|
||||
elements with later indexes.
|
||||
|
||||
For example, `Pairwise (· ≠ ·) l` asserts that `l` has no duplicates, and if `Pairwise (· < ·) l`
|
||||
For example, `Pairwise (· ≠ ·) l` asserts that `l` has no duplicates, and `Pairwise (· < ·) l`
|
||||
asserts that `l` is (strictly) sorted.
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -57,7 +57,7 @@ theorem finRange_reverse {n} : (finRange n).reverse = (finRange n).map Fin.rev :
|
||||
conv => rhs; rw [finRange_succ]
|
||||
rw [reverse_append, reverse_cons, reverse_nil, nil_append, singleton_append, ← map_reverse,
|
||||
map_cons, ih, map_map, map_map]
|
||||
congr; funext
|
||||
congr 2; funext
|
||||
simp [Fin.rev_succ]
|
||||
|
||||
end List
|
||||
|
||||
@@ -523,7 +523,7 @@ private theorem findIdx?_go_eq {p : α → Bool} {xs : List α} {i : Nat} :
|
||||
split
|
||||
· simp_all
|
||||
· simp_all only [findIdx?_go_succ, Bool.not_eq_true, Option.map_map, Nat.zero_add]
|
||||
congr
|
||||
congr 1
|
||||
ext
|
||||
simp only [Nat.add_comm i, Function.comp_apply, Nat.add_assoc]
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ theorem max?_le_iff [Max α] [LE α]
|
||||
|
||||
-- This could be refactored by designing appropriate typeclasses to replace `le_refl`, `max_eq_or`,
|
||||
-- and `le_min_iff`.
|
||||
theorem max?_eq_some_iff [Max α] [LE α] [anti : Std.Antisymm ((· : α) ≤ ·)]
|
||||
theorem max?_eq_some_iff [Max α] [LE α] [anti : Std.Antisymm (· ≤ · : α → α → Prop)]
|
||||
(le_refl : ∀ a : α, a ≤ a)
|
||||
(max_eq_or : ∀ a b : α, max a b = a ∨ max a b = b)
|
||||
(max_le_iff : ∀ a b c : α, max b c ≤ a ↔ b ≤ a ∧ c ≤ a) {xs : List α} :
|
||||
|
||||
@@ -137,7 +137,7 @@ of a number.
|
||||
/--
|
||||
Returns `true` if the `(n+1)`th least significant bit is `1`, or `false` if it is `0`.
|
||||
-/
|
||||
def testBit (m n : Nat) : Bool :=
|
||||
@[expose] def testBit (m n : Nat) : Bool :=
|
||||
-- `1 &&& n` is faster than `n &&& 1` for big `n`.
|
||||
1 &&& (m >>> n) != 0
|
||||
|
||||
|
||||
@@ -350,12 +350,7 @@ theorem mod_le (x y : Nat) : x % y ≤ x := by
|
||||
theorem mod_lt_of_lt {a b c : Nat} (h : a < c) : a % b < c :=
|
||||
Nat.lt_of_le_of_lt (Nat.mod_le _ _) h
|
||||
|
||||
@[simp] theorem zero_mod (b : Nat) : 0 % b = 0 := by
|
||||
rw [mod_eq]
|
||||
have : ¬ (0 < b ∧ b = 0) := by
|
||||
intro ⟨h₁, h₂⟩
|
||||
simp_all
|
||||
simp [this]
|
||||
@[simp] theorem zero_mod (b : Nat) : 0 % b = 0 := rfl
|
||||
|
||||
@[simp] theorem mod_self (n : Nat) : n % n = 0 := by
|
||||
rw [mod_eq_sub_mod (Nat.le_refl _), Nat.sub_self, zero_mod]
|
||||
|
||||
@@ -10,7 +10,7 @@ public import Init.Data.Range.Polymorphic.RangeIterator
|
||||
public import Init.Data.Range.Polymorphic.Basic
|
||||
public import Init.Data.Iterators.Combinators.Attach
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
|
||||
open Std.Iterators
|
||||
|
||||
@@ -29,7 +29,7 @@ def Internal.iter {sl su α} [UpwardEnumerable α] [BoundedUpwardEnumerable sl
|
||||
Returns the elements of the given range as a list in ascending order, given that ranges of the given
|
||||
type and shape support this function and the range is finite.
|
||||
-/
|
||||
@[always_inline, inline]
|
||||
@[always_inline, inline, expose]
|
||||
def toList {sl su α} [UpwardEnumerable α] [BoundedUpwardEnumerable sl α]
|
||||
[SupportsUpperBound su α]
|
||||
(r : PRange ⟨sl, su⟩ α)
|
||||
@@ -58,50 +58,6 @@ def size {sl su α} [UpwardEnumerable α] [BoundedUpwardEnumerable sl α]
|
||||
|
||||
section Iterator
|
||||
|
||||
theorem RangeIterator.isPlausibleIndirectOutput_iff {su α}
|
||||
[UpwardEnumerable α] [SupportsUpperBound su α]
|
||||
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableUpperBound su α]
|
||||
{it : Iter (α := RangeIterator su α) α} {out : α} :
|
||||
it.IsPlausibleIndirectOutput out ↔
|
||||
∃ n, it.internalState.next.bind (UpwardEnumerable.succMany? n ·) = some out ∧
|
||||
SupportsUpperBound.IsSatisfied it.internalState.upperBound out := by
|
||||
constructor
|
||||
· intro h
|
||||
induction h
|
||||
case direct h =>
|
||||
rw [RangeIterator.isPlausibleOutput_iff] at h
|
||||
refine ⟨0, by simp [h, LawfulUpwardEnumerable.succMany?_zero]⟩
|
||||
case indirect h _ ih =>
|
||||
rw [RangeIterator.isPlausibleSuccessorOf_iff] at h
|
||||
obtain ⟨n, hn⟩ := ih
|
||||
obtain ⟨a, ha, h₁, h₂, h₃⟩ := h
|
||||
refine ⟨n + 1, ?_⟩
|
||||
simp [ha, ← h₃, hn.2, LawfulUpwardEnumerable.succMany?_succ_eq_succ?_bind_succMany?, h₂, hn]
|
||||
· rintro ⟨n, hn, hu⟩
|
||||
induction n generalizing it
|
||||
case zero =>
|
||||
apply Iter.IsPlausibleIndirectOutput.direct
|
||||
rw [RangeIterator.isPlausibleOutput_iff]
|
||||
exact ⟨by simpa [LawfulUpwardEnumerable.succMany?_zero] using hn, hu⟩
|
||||
case succ ih =>
|
||||
cases hn' : it.internalState.next
|
||||
· simp [hn'] at hn
|
||||
rename_i a
|
||||
simp only [hn', Option.bind_some] at hn
|
||||
have hle : UpwardEnumerable.LE a out := ⟨_, hn⟩
|
||||
rw [LawfulUpwardEnumerable.succMany?_succ_eq_succ?_bind_succMany?] at hn
|
||||
cases hn' : UpwardEnumerable.succ? a
|
||||
· simp only [hn', Option.bind_none, reduceCtorEq] at hn
|
||||
rename_i a'
|
||||
simp only [hn', Option.bind_some] at hn
|
||||
specialize ih (it := ⟨some a', it.internalState.upperBound⟩) hn hu
|
||||
refine Iter.IsPlausibleIndirectOutput.indirect ?_ ih
|
||||
rw [RangeIterator.isPlausibleSuccessorOf_iff]
|
||||
refine ⟨a, ‹_›, ?_, hn', rfl⟩
|
||||
apply LawfulUpwardEnumerableUpperBound.isSatisfied_of_le _ a out
|
||||
· exact hu
|
||||
· exact hle
|
||||
|
||||
theorem Internal.isPlausibleIndirectOutput_iter_iff {sl su α}
|
||||
[UpwardEnumerable α] [BoundedUpwardEnumerable sl α]
|
||||
[SupportsLowerBound sl α] [SupportsUpperBound su α]
|
||||
@@ -142,7 +98,6 @@ instance {sl su α m} [UpwardEnumerable α] [BoundedUpwardEnumerable sl α]
|
||||
[Monad m] [Finite (RangeIterator su α) Id] :
|
||||
ForIn' m (PRange ⟨sl, su⟩ α) α inferInstance where
|
||||
forIn' r init f := by
|
||||
haveI : MonadLift Id m := ⟨Std.Internal.idToMonad (α := _)⟩
|
||||
haveI := Iter.instForIn' (α := RangeIterator su α) (β := α) (n := m)
|
||||
refine ForIn'.forIn' (α := α) (PRange.Internal.iter r) init (fun a ha acc => f a ?_ acc)
|
||||
simp only [Membership.mem] at ha
|
||||
|
||||
@@ -17,8 +17,8 @@ theorem succ_eq {n : Nat} : UpwardEnumerable.succ n = n + 1 :=
|
||||
rfl
|
||||
|
||||
theorem ClosedOpen.toList_succ_succ {m n : Nat} :
|
||||
(PRange.mk (shape := ⟨.closed, .open⟩) (m+1) (n+1)).toList =
|
||||
(PRange.mk (shape := ⟨.closed, .open⟩) m n).toList.map (· + 1) := by
|
||||
((m+1)...(n+1)).toList =
|
||||
(m...n).toList.map (· + 1) := by
|
||||
simp only [← succ_eq]
|
||||
rw [Std.PRange.ClosedOpen.toList_succ_succ_eq_map]
|
||||
|
||||
|
||||
@@ -110,16 +110,6 @@ theorem RangeIterator.step_eq_step {su} [UpwardEnumerable α] [SupportsUpperBoun
|
||||
it.step = ⟨RangeIterator.step it, isPlausibleStep_iff.mpr rfl⟩ := by
|
||||
simp [Iter.step, step_eq_monadicStep, Monadic.step_eq_step, IterM.Step.toPure]
|
||||
|
||||
@[always_inline, inline]
|
||||
instance RangeIterator.instIteratorLoop {su} [UpwardEnumerable α] [SupportsUpperBound su α]
|
||||
{n : Type v → Type w} [Monad n] :
|
||||
IteratorLoop (RangeIterator su α) Id n :=
|
||||
.defaultImplementation
|
||||
|
||||
instance RangeIterator.instIteratorLoopPartial {su} [UpwardEnumerable α] [SupportsUpperBound su α]
|
||||
{n : Type v → Type w} [Monad n] : IteratorLoopPartial (RangeIterator su α) Id n :=
|
||||
.defaultImplementation
|
||||
|
||||
instance RangeIterator.instIteratorCollect {su} [UpwardEnumerable α] [SupportsUpperBound su α]
|
||||
{n : Type u → Type w} [Monad n] : IteratorCollect (RangeIterator su α) Id n :=
|
||||
.defaultImplementation
|
||||
@@ -370,4 +360,223 @@ instance RangeIterator.instLawfulDeterministicIterator {su} [UpwardEnumerable α
|
||||
LawfulDeterministicIterator (RangeIterator su α) Id where
|
||||
isPlausibleStep_eq_eq it := ⟨Monadic.step it, rfl⟩
|
||||
|
||||
end Std.PRange
|
||||
theorem RangeIterator.Monadic.isPlausibleIndirectOutput_iff {su α}
|
||||
[UpwardEnumerable α] [SupportsUpperBound su α]
|
||||
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableUpperBound su α]
|
||||
{it : IterM (α := RangeIterator su α) Id α} {out : α} :
|
||||
it.IsPlausibleIndirectOutput out ↔
|
||||
∃ n, it.internalState.next.bind (UpwardEnumerable.succMany? n ·) = some out ∧
|
||||
SupportsUpperBound.IsSatisfied it.internalState.upperBound out := by
|
||||
constructor
|
||||
· intro h
|
||||
induction h
|
||||
case direct h =>
|
||||
rw [RangeIterator.Monadic.isPlausibleOutput_iff] at h
|
||||
refine ⟨0, by simp [h, LawfulUpwardEnumerable.succMany?_zero]⟩
|
||||
case indirect h _ ih =>
|
||||
rw [RangeIterator.Monadic.isPlausibleSuccessorOf_iff] at h
|
||||
obtain ⟨n, hn⟩ := ih
|
||||
obtain ⟨a, ha, h₁, h₂, h₃⟩ := h
|
||||
refine ⟨n + 1, ?_⟩
|
||||
simp [ha, ← h₃, hn.2, LawfulUpwardEnumerable.succMany?_succ_eq_succ?_bind_succMany?, h₂, hn]
|
||||
· rintro ⟨n, hn, hu⟩
|
||||
induction n generalizing it
|
||||
case zero =>
|
||||
apply IterM.IsPlausibleIndirectOutput.direct
|
||||
rw [RangeIterator.Monadic.isPlausibleOutput_iff]
|
||||
exact ⟨by simpa [LawfulUpwardEnumerable.succMany?_zero] using hn, hu⟩
|
||||
case succ ih =>
|
||||
cases hn' : it.internalState.next
|
||||
· simp [hn'] at hn
|
||||
rename_i a
|
||||
simp only [hn', Option.bind_some] at hn
|
||||
have hle : UpwardEnumerable.LE a out := ⟨_, hn⟩
|
||||
rw [LawfulUpwardEnumerable.succMany?_succ_eq_succ?_bind_succMany?] at hn
|
||||
cases hn' : UpwardEnumerable.succ? a
|
||||
· simp only [hn', Option.bind_none, reduceCtorEq] at hn
|
||||
rename_i a'
|
||||
simp only [hn', Option.bind_some] at hn
|
||||
specialize ih (it := ⟨some a', it.internalState.upperBound⟩) hn hu
|
||||
refine IterM.IsPlausibleIndirectOutput.indirect ?_ ih
|
||||
rw [RangeIterator.Monadic.isPlausibleSuccessorOf_iff]
|
||||
refine ⟨a, ‹_›, ?_, hn', rfl⟩
|
||||
apply LawfulUpwardEnumerableUpperBound.isSatisfied_of_le _ a out
|
||||
· exact hu
|
||||
· exact hle
|
||||
|
||||
theorem RangeIterator.isPlausibleIndirectOutput_iff {su α}
|
||||
[UpwardEnumerable α] [SupportsUpperBound su α]
|
||||
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableUpperBound su α]
|
||||
{it : Iter (α := RangeIterator su α) α} {out : α} :
|
||||
it.IsPlausibleIndirectOutput out ↔
|
||||
∃ n, it.internalState.next.bind (UpwardEnumerable.succMany? n ·) = some out ∧
|
||||
SupportsUpperBound.IsSatisfied it.internalState.upperBound out := by
|
||||
simp only [Iter.isPlausibleIndirectOutput_iff_isPlausibleIndirectOutput_toIterM,
|
||||
Monadic.isPlausibleIndirectOutput_iff, Iter.toIterM]
|
||||
|
||||
section IteratorLoop
|
||||
|
||||
/-!
|
||||
## Efficient `IteratorLoop` instance
|
||||
As long as the compiler cannot optimize away the `Option` in the internal state, we use a special
|
||||
loop implementation.
|
||||
-/
|
||||
|
||||
@[always_inline, inline]
|
||||
instance RangeIterator.instIteratorLoop {su} [UpwardEnumerable α] [SupportsUpperBound su α]
|
||||
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableUpperBound su α]
|
||||
{n : Type u → Type w} [Monad n] :
|
||||
IteratorLoop (RangeIterator su α) Id n where
|
||||
forIn _ γ Pl wf it init f :=
|
||||
match it with
|
||||
| ⟨⟨some next, upperBound⟩⟩ =>
|
||||
if hu : SupportsUpperBound.IsSatisfied upperBound next then
|
||||
loop γ Pl wf upperBound next init (fun a ha₁ ha₂ c => f a ?hf c) next ?hle hu
|
||||
else
|
||||
return init
|
||||
| ⟨⟨none, _⟩⟩ => return init
|
||||
where
|
||||
@[specialize]
|
||||
loop γ Pl wf (upperBound : Bound su α) least acc
|
||||
(f : (out : α) → UpwardEnumerable.LE least out → SupportsUpperBound.IsSatisfied upperBound out → (c : γ) → n (Subtype (fun s : ForInStep γ => Pl out c s)))
|
||||
(next : α) (hl : UpwardEnumerable.LE least next) (hu : SupportsUpperBound.IsSatisfied upperBound next) : n γ := do
|
||||
match ← f next hl hu acc with
|
||||
| ⟨.yield acc', h⟩ =>
|
||||
match hs : UpwardEnumerable.succ? next with
|
||||
| some next' =>
|
||||
if hu : SupportsUpperBound.IsSatisfied upperBound next' then
|
||||
loop γ Pl wf upperBound least acc' f next' ?hle' hu
|
||||
else
|
||||
return acc'
|
||||
| none => return acc'
|
||||
| ⟨.done acc', _⟩ => return acc'
|
||||
termination_by IteratorLoop.WithWF.mk ⟨⟨some next, upperBound⟩⟩ acc (hwf := wf)
|
||||
decreasing_by
|
||||
simp [IteratorLoop.rel, RangeIterator.Monadic.isPlausibleStep_iff,
|
||||
RangeIterator.Monadic.step, *]
|
||||
finally
|
||||
case hf =>
|
||||
rw [RangeIterator.Monadic.isPlausibleIndirectOutput_iff]
|
||||
obtain ⟨n, hn⟩ := ha₁
|
||||
exact ⟨n, hn, ha₂⟩
|
||||
case hle =>
|
||||
exact UpwardEnumerable.le_refl _
|
||||
case hle' =>
|
||||
refine UpwardEnumerable.le_trans hl ⟨1, ?_⟩
|
||||
simp [UpwardEnumerable.succMany?_one, hs]
|
||||
|
||||
partial instance RepeatIterator.instIteratorLoopPartial {su} [UpwardEnumerable α]
|
||||
[SupportsUpperBound su α] [LawfulUpwardEnumerable α] [LawfulUpwardEnumerableUpperBound su α]
|
||||
{n : Type u → Type w} [Monad n] : IteratorLoopPartial (RangeIterator su α) Id n where
|
||||
forInPartial _ γ it init f :=
|
||||
match it with
|
||||
| ⟨⟨some next, upperBound⟩⟩ =>
|
||||
if hu : SupportsUpperBound.IsSatisfied upperBound next then
|
||||
loop γ upperBound next init (fun a ha₁ ha₂ c => f a ?hf c) next ?hle hu
|
||||
else
|
||||
return init
|
||||
| ⟨⟨none, _⟩⟩ => return init
|
||||
where
|
||||
@[specialize]
|
||||
loop γ (upperBound : Bound su α) least acc
|
||||
(f : (out : α) → UpwardEnumerable.LE least out → SupportsUpperBound.IsSatisfied upperBound out → (c : γ) → n (ForInStep γ))
|
||||
(next : α) (hl : UpwardEnumerable.LE least next) (hu : SupportsUpperBound.IsSatisfied upperBound next) : n γ := do
|
||||
match ← f next hl hu acc with
|
||||
| .yield acc' =>
|
||||
match hs : UpwardEnumerable.succ? next with
|
||||
| some next' =>
|
||||
if hu : SupportsUpperBound.IsSatisfied upperBound next' then
|
||||
loop γ upperBound least acc' f next' ?hle' hu
|
||||
else
|
||||
return acc'
|
||||
| none => return acc'
|
||||
| .done acc' => return acc'
|
||||
finally
|
||||
case hf =>
|
||||
rw [RangeIterator.Monadic.isPlausibleIndirectOutput_iff]
|
||||
obtain ⟨n, hn⟩ := ha₁
|
||||
exact ⟨n, hn, ha₂⟩
|
||||
case hle =>
|
||||
exact UpwardEnumerable.le_refl _
|
||||
case hle' =>
|
||||
refine UpwardEnumerable.le_trans hl ⟨1, ?_⟩
|
||||
simp [UpwardEnumerable.succMany?_one, hs]
|
||||
|
||||
theorem RangeIterator.instIteratorLoop.loop_eq {su} [UpwardEnumerable α] [SupportsUpperBound su α]
|
||||
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableUpperBound su α]
|
||||
{n : Type u → Type w} [Monad n] [LawfulMonad n] {γ : Type u}
|
||||
{lift} [Internal.LawfulMonadLiftBindFunction lift]
|
||||
{PlausibleForInStep} {upperBound} {next} {hl} {hu} {f} {acc} {wf} :
|
||||
loop (α := α) (su := su) (n := n) γ PlausibleForInStep wf upperBound least acc f next hl hu =
|
||||
(do
|
||||
match ← f next hl hu acc with
|
||||
| ⟨.yield c, _⟩ =>
|
||||
letI it' : IterM (α := RangeIterator su α) Id α := ⟨⟨UpwardEnumerable.succ? next, upperBound⟩⟩
|
||||
IterM.DefaultConsumers.forIn' (m := Id) lift γ
|
||||
PlausibleForInStep wf it' c it'.IsPlausibleIndirectOutput (fun _ => id)
|
||||
(fun b h c => f b
|
||||
(by
|
||||
refine UpwardEnumerable.le_trans hl ?_
|
||||
simp only [RangeIterator.Monadic.isPlausibleIndirectOutput_iff, it',
|
||||
← LawfulUpwardEnumerable.succMany?_succ_eq_succ?_bind_succMany?] at h
|
||||
exact ⟨h.choose + 1, h.choose_spec.1⟩)
|
||||
(by simp only [RangeIterator.Monadic.isPlausibleIndirectOutput_iff, it'] at h; exact h.choose_spec.2) c)
|
||||
| ⟨.done c, _⟩ => return c) := by
|
||||
rw [loop]
|
||||
apply bind_congr
|
||||
intro step
|
||||
split
|
||||
· split
|
||||
· split
|
||||
· simp only [*]
|
||||
rw [IterM.DefaultConsumers.forIn']
|
||||
simp only [Monadic.step_eq_step, Monadic.step, ↓reduceIte, *,
|
||||
Internal.LawfulMonadLiftBindFunction.liftBind_pure]
|
||||
rw [loop_eq (lift := lift)]
|
||||
apply bind_congr
|
||||
intro step
|
||||
split
|
||||
· apply IterM.DefaultConsumers.forIn'_eq_forIn'
|
||||
intros; rfl
|
||||
· simp
|
||||
· simp only [*]
|
||||
rw [IterM.DefaultConsumers.forIn']
|
||||
simp [Monadic.step_eq_step, Monadic.step, *,
|
||||
Internal.LawfulMonadLiftBindFunction.liftBind_pure]
|
||||
· simp only [*]
|
||||
rw [IterM.DefaultConsumers.forIn']
|
||||
simp [Monadic.step_eq_step, Monadic.step, Internal.LawfulMonadLiftBindFunction.liftBind_pure]
|
||||
· simp
|
||||
termination_by IteratorLoop.WithWF.mk ⟨⟨some next, upperBound⟩⟩ acc (hwf := wf)
|
||||
decreasing_by
|
||||
simp [IteratorLoop.rel, RangeIterator.Monadic.isPlausibleStep_iff,
|
||||
RangeIterator.Monadic.step, *]
|
||||
|
||||
instance RangeIterator.instLawfulIteratorLoop {su} [UpwardEnumerable α] [SupportsUpperBound su α]
|
||||
[LawfulUpwardEnumerable α] [LawfulUpwardEnumerableUpperBound su α]
|
||||
{n : Type u → Type w} [Monad n] [LawfulMonad n] :
|
||||
LawfulIteratorLoop (RangeIterator su α) Id n where
|
||||
lawful := by
|
||||
intro lift instLawfulMonadLiftFunction
|
||||
ext γ PlausibleForInStep hwf it init f
|
||||
simp only [IteratorLoop.forIn, IteratorLoop.defaultImplementation]
|
||||
rw [IterM.DefaultConsumers.forIn']
|
||||
simp only [RangeIterator.Monadic.step_eq_step, RangeIterator.Monadic.step]
|
||||
simp only [Internal.LawfulMonadLiftBindFunction.liftBind_pure]
|
||||
split
|
||||
· rename_i it f next upperBound f'
|
||||
simp
|
||||
split
|
||||
· simp only
|
||||
rw [instIteratorLoop.loop_eq (lift := lift)]
|
||||
apply bind_congr
|
||||
intro step
|
||||
split
|
||||
· apply IterM.DefaultConsumers.forIn'_eq_forIn'
|
||||
intro b c hPb hQb
|
||||
congr
|
||||
· simp
|
||||
· simp
|
||||
· simp
|
||||
|
||||
end Std.PRange.IteratorLoop
|
||||
|
||||
@@ -99,17 +99,26 @@ none
|
||||
def Subarray.foldlM {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (f : β → α → m β) (init : β) (as : Subarray α) : m β :=
|
||||
Slice.foldlM f (init := init) as
|
||||
|
||||
/--
|
||||
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 α) : β :=
|
||||
Slice.foldl f (init := init) as
|
||||
|
||||
namespace Array
|
||||
|
||||
/--
|
||||
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
|
||||
def ofSubarray (s : Subarray α) : Array α :=
|
||||
Slice.toArray s
|
||||
|
||||
instance : Coe (Subarray α) (Array α) := ⟨ofSubarray⟩
|
||||
|
||||
@@ -129,3 +138,7 @@ instance [ToString α] : ToString (Subarray α) where
|
||||
toString s := toString s.toArray
|
||||
|
||||
end Array
|
||||
|
||||
@[inherit_doc Array.ofSubarray]
|
||||
def Subarray.toArray (s : Subarray α) : Array α :=
|
||||
Array.ofSubarray s
|
||||
|
||||
@@ -220,22 +220,22 @@ If both the replacement character and the replaced character are 7-bit ASCII cha
|
||||
string is not shared, then it is updated in-place and not copied.
|
||||
|
||||
Examples:
|
||||
* `abc.modify ⟨1⟩ Char.toUpper = "aBc"`
|
||||
* `abc.modify ⟨3⟩ Char.toUpper = "abc"`
|
||||
* `"abc".modify ⟨1⟩ Char.toUpper = "aBc"`
|
||||
* `"abc".modify ⟨3⟩ Char.toUpper = "abc"`
|
||||
-/
|
||||
def modify (s : String) (i : Pos) (f : Char → Char) : String :=
|
||||
s.set i <| f <| s.get i
|
||||
|
||||
/--
|
||||
Returns the next position in a string after position `p`. The result is unspecified if `p` is not a
|
||||
valid position or if `p = s.endPos`.
|
||||
Returns the next position in a string after position `p`. If `p` is not a valid position or
|
||||
`p = s.endPos`, returns the position one byte after `p`.
|
||||
|
||||
A run-time bounds check is performed to determine whether `p` is at the end of the string. If a
|
||||
bounds check has already been performed, use `String.next'` to avoid a repeated check.
|
||||
|
||||
Some examples where the result is unspecified:
|
||||
* `"abc".next ⟨3⟩`, since `3 = "abc".endPos`
|
||||
* `"L∃∀N".next ⟨2⟩`, since `2` points into the middle of a multi-byte UTF-8 character
|
||||
Some examples of edge cases:
|
||||
* `"abc".next ⟨3⟩ = ⟨4⟩`, since `3 = "abc".endPos`
|
||||
* `"L∃∀N".next ⟨2⟩ = ⟨3⟩`, since `2` points into the middle of a multi-byte UTF-8 character
|
||||
|
||||
Examples:
|
||||
* `"abc".get ("abc".next 0) = 'b'`
|
||||
@@ -247,17 +247,18 @@ def next (s : @& String) (p : @& Pos) : Pos :=
|
||||
p + c
|
||||
|
||||
def utf8PrevAux : List Char → Pos → Pos → Pos
|
||||
| [], _, _ => 0
|
||||
| [], _, p => ⟨p.byteIdx - 1⟩
|
||||
| c::cs, i, p =>
|
||||
let i' := i + c
|
||||
if i' = p then i else utf8PrevAux cs i' p
|
||||
if p ≤ i' then i else utf8PrevAux cs i' p
|
||||
|
||||
/--
|
||||
Returns the position in a string before a specified position, `p`. If `p = ⟨0⟩`, returns `0`. If `p`
|
||||
is not a valid position, the result is unspecified.
|
||||
is greater than `endPos`, returns the position one byte before `p`. Otherwise, if `p` occurs in the
|
||||
middle of a multi-byte character, returns the beginning position of that character.
|
||||
|
||||
For example, `"L∃∀N".prev ⟨3⟩` is unspecified, since byte 3 occurs in the middle of the multi-byte
|
||||
character `'∃'`.
|
||||
For example, `"L∃∀N".prev ⟨3⟩` is `⟨1⟩`, since byte 3 occurs in the middle of the multi-byte
|
||||
character `'∃'` that starts at byte 1.
|
||||
|
||||
Examples:
|
||||
* `"abc".get ("abc".endPos |> "abc".prev) = 'c'`
|
||||
@@ -265,7 +266,7 @@ Examples:
|
||||
-/
|
||||
@[extern "lean_string_utf8_prev", expose]
|
||||
def prev : (@& String) → (@& Pos) → Pos
|
||||
| ⟨s⟩, p => if p = 0 then 0 else utf8PrevAux s 0 p
|
||||
| ⟨s⟩, p => utf8PrevAux s 0 p
|
||||
|
||||
/--
|
||||
Returns the first character in `s`. If `s = ""`, returns `(default : Char)`.
|
||||
@@ -339,7 +340,7 @@ Requires evidence, `h`, that `p` is within bounds. No run-time bounds check is p
|
||||
A typical pattern combines `String.next'` with a dependent `if`-expression to avoid the overhead of
|
||||
an additional bounds check. For example:
|
||||
```
|
||||
def next? (s: String) (p : String.Pos) : Option Char :=
|
||||
def next? (s : String) (p : String.Pos) : Option Char :=
|
||||
if h : s.atEnd p then none else s.get (s.next' p h)
|
||||
```
|
||||
|
||||
@@ -369,20 +370,17 @@ protected theorem Pos.ne_zero_of_lt : {a b : Pos} → a < b → b ≠ 0
|
||||
theorem lt_next (s : String) (i : Pos) : i.1 < (s.next i).1 :=
|
||||
Nat.add_lt_add_left (Char.utf8Size_pos _) _
|
||||
|
||||
theorem utf8PrevAux_lt_of_pos : ∀ (cs : List Char) (i p : Pos), p ≠ 0 →
|
||||
theorem utf8PrevAux_lt_of_pos : ∀ (cs : List Char) (i p : Pos), i < p → p ≠ 0 →
|
||||
(utf8PrevAux cs i p).1 < p.1
|
||||
| [], _, _, h =>
|
||||
Nat.lt_of_le_of_lt (Nat.zero_le _)
|
||||
(Nat.zero_lt_of_ne_zero (mt (congrArg Pos.mk) h))
|
||||
| c::cs, i, p, h => by
|
||||
| [], _, _, _, h => Nat.sub_one_lt (mt (congrArg Pos.mk) h)
|
||||
| c::cs, i, p, h, h' => by
|
||||
simp [utf8PrevAux]
|
||||
apply iteInduction (motive := (Pos.byteIdx · < _)) <;> intro h'
|
||||
next => exact h' ▸ Nat.add_lt_add_left (Char.utf8Size_pos _) _
|
||||
next => exact utf8PrevAux_lt_of_pos _ _ _ h
|
||||
apply iteInduction (motive := (Pos.byteIdx · < _)) <;> intro h''
|
||||
next => exact h
|
||||
next => exact utf8PrevAux_lt_of_pos _ _ _ (Nat.lt_of_not_le h'') h'
|
||||
|
||||
theorem prev_lt_of_pos (s : String) (i : Pos) (h : i ≠ 0) : (s.prev i).1 < i.1 := by
|
||||
simp [prev, h]
|
||||
exact utf8PrevAux_lt_of_pos _ _ _ h
|
||||
theorem prev_lt_of_pos (s : String) (i : Pos) (h : i ≠ 0) : (s.prev i).1 < i.1 :=
|
||||
utf8PrevAux_lt_of_pos _ _ _ (Nat.zero_lt_of_ne_zero (mt (congrArg Pos.mk) h)) h
|
||||
|
||||
def posOfAux (s : String) (c : Char) (stopPos : Pos) (pos : Pos) : Pos :=
|
||||
if h : pos < stopPos then
|
||||
@@ -419,7 +417,7 @@ Returns the position of the last occurrence of a character, `c`, in a string `s`
|
||||
contain `c`, returns `none`.
|
||||
|
||||
Examples:
|
||||
* `"abcabc".refPosOf 'a' = some ⟨3⟩`
|
||||
* `"abcabc".revPosOf 'a' = some ⟨3⟩`
|
||||
* `"abcabc".revPosOf 'z' = none`
|
||||
* `"L∃∀N".revPosOf '∀' = some ⟨4⟩`
|
||||
-/
|
||||
@@ -2068,7 +2066,11 @@ end Pos
|
||||
|
||||
theorem lt_next' (s : String) (p : Pos) : p < next s p := lt_next ..
|
||||
|
||||
@[simp] theorem prev_zero (s : String) : prev s 0 = 0 := rfl
|
||||
@[simp] theorem prev_zero (s : String) : prev s 0 = 0 := by
|
||||
cases s with | mk cs
|
||||
cases cs
|
||||
next => rfl
|
||||
next => simp [prev, utf8PrevAux, Pos.le_iff]
|
||||
|
||||
@[simp] theorem get'_eq (s : String) (p : Pos) (h) : get' s p h = get s p := rfl
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ prelude
|
||||
public import Init.Data.UInt.BasicAux
|
||||
public import Init.Data.BitVec.Basic
|
||||
|
||||
public section
|
||||
@[expose] public section
|
||||
|
||||
set_option linter.missingDocs true
|
||||
|
||||
|
||||
@@ -8,13 +8,14 @@ module
|
||||
|
||||
prelude
|
||||
public meta import Init.Coe
|
||||
public import Init.Data.Stream
|
||||
public import Init.Data.Array.Lemmas
|
||||
public import Init.Data.Array.MapIdx
|
||||
public import Init.Data.Array.InsertIdx
|
||||
public import Init.Data.Array.Range
|
||||
public import Init.Data.Range
|
||||
import Init.Data.Slice.Array.Basic
|
||||
public import Init.Data.Stream
|
||||
-- TODO: Making this private leads to a panic in Init.Grind.Ring.Poly.
|
||||
public import Init.Data.Slice.Array.Iterator
|
||||
|
||||
public section
|
||||
|
||||
@@ -54,6 +55,11 @@ open Lean in
|
||||
macro_rules
|
||||
| `(#v[ $elems,* ]) => `(Vector.mk (n := $(quote elems.getElems.size)) #[$elems,*] rfl)
|
||||
|
||||
@[app_unexpander Vector.mk]
|
||||
meta def unexpandMk : Lean.PrettyPrinter.Unexpander
|
||||
| `($_ #[ $elems,* ] $_) => `(#v[ $elems,* ])
|
||||
| _ => throw ()
|
||||
|
||||
recommended_spelling "empty" for "#v[]" in [Vector.mk, «term#v[_,]»]
|
||||
recommended_spelling "singleton" for "#v[x]" in [Vector.mk, «term#v[_,]»]
|
||||
|
||||
@@ -562,7 +568,7 @@ Lexicographic comparator for vectors.
|
||||
- there is an index `i` such that `lt v[i] w[i]`, and for all `j < i`, `v[j] == w[j]`.
|
||||
-/
|
||||
def lex [BEq α] (xs ys : Vector α n) (lt : α → α → Bool := by exact (· < ·)) : Bool := Id.run do
|
||||
for h : i in [0 : n] do
|
||||
for h : i in 0...n do
|
||||
if lt xs[i] ys[i] then
|
||||
return true
|
||||
else if xs[i] != ys[i] then
|
||||
|
||||
@@ -284,7 +284,7 @@ set_option linter.indexVariables false in
|
||||
(xs.drop i).toArray = xs.toArray.extract i n := by
|
||||
simp [drop]
|
||||
|
||||
@[simp, grind] theorem toArray_empty : (#v[] : Vector α 0).toArray = #[] := rfl
|
||||
@[simp, grind =] theorem toArray_empty : (#v[] : Vector α 0).toArray = #[] := rfl
|
||||
|
||||
@[simp, grind] theorem toArray_emptyWithCapacity {cap} :
|
||||
(Vector.emptyWithCapacity (α := α) cap).toArray = Array.emptyWithCapacity cap := rfl
|
||||
@@ -1219,12 +1219,12 @@ instance [BEq α] [LawfulBEq α] (a : α) (as : Vector α n) : Decidable (a ∈
|
||||
as.contains a = decide (a ∈ as) := by
|
||||
rw [Bool.eq_iff_iff, contains_iff, decide_eq_true_iff]
|
||||
|
||||
@[simp] theorem any_push [BEq α] {as : Vector α n} {a : α} {p : α → Bool} :
|
||||
@[simp] theorem any_push {as : Vector α n} {a : α} {p : α → Bool} :
|
||||
(as.push a).any p = (as.any p || p a) := by
|
||||
rcases as with ⟨as, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem all_push [BEq α] {as : Vector α n} {a : α} {p : α → Bool} :
|
||||
@[simp] theorem all_push {as : Vector α n} {a : α} {p : α → Bool} :
|
||||
(as.push a).all p = (as.all p && p a) := by
|
||||
rcases as with ⟨as, rfl⟩
|
||||
simp
|
||||
|
||||
@@ -10,6 +10,7 @@ public import all Init.Data.Vector.Basic
|
||||
public import Init.Data.Vector.Lemmas
|
||||
public import all Init.Data.Array.Lex.Basic
|
||||
public import Init.Data.Array.Lex.Lemmas
|
||||
import Init.Data.Range.Polymorphic.Lemmas
|
||||
|
||||
public section
|
||||
|
||||
@@ -43,7 +44,7 @@ protected theorem not_le_iff_gt [LT α] {xs ys : Vector α n} :
|
||||
|
||||
@[simp] theorem mk_lex_mk [BEq α] {lt : α → α → Bool} {xs ys : Array α} {n₁ : xs.size = n} {n₂ : ys.size = n} :
|
||||
(Vector.mk xs n₁).lex (Vector.mk ys n₂) lt = xs.lex ys lt := by
|
||||
simp [Vector.lex, Array.lex, n₁, n₂]
|
||||
simp [Vector.lex, Array.lex, n₁, n₂, Std.PRange.forIn'_eq_forIn'_toList]
|
||||
rfl
|
||||
|
||||
@[simp, grind =] theorem lex_toArray [BEq α] {lt : α → α → Bool} {xs ys : Vector α n} :
|
||||
|
||||
@@ -131,6 +131,11 @@ theorem Bool.eq_true_of_not_eq_false' {a : Bool} (h : ¬ a = false) : a = true :
|
||||
theorem Bool.false_of_not_eq_self {a : Bool} (h : (!a) = a) : False := by
|
||||
by_cases a <;> simp_all
|
||||
|
||||
theorem Bool.ne_of_eq_true_of_eq_false {a b : Bool} (h₁ : a = true) (h₂ : b = false) : (a = b) = False := by
|
||||
cases a <;> cases b <;> simp_all
|
||||
theorem Bool.ne_of_eq_false_of_eq_true {a b : Bool} (h₁ : a = false) (h₂ : b = true) : (a = b) = False := by
|
||||
cases a <;> cases b <;> simp_all
|
||||
|
||||
/- The following two helper theorems are used to case-split `a = b` representing `iff`. -/
|
||||
theorem of_eq_eq_true {a b : Prop} (h : (a = b) = True) : (a ∧ b) ∨ (¬ a ∧ ¬ b) := by
|
||||
by_cases a <;> by_cases b <;> simp_all
|
||||
|
||||
@@ -45,11 +45,19 @@ theorem imp_true_eq (p : Prop) : (p → True) = True := by simp
|
||||
theorem imp_false_eq (p : Prop) : (p → False) = ¬p := by simp
|
||||
theorem imp_self_eq (p : Prop) : (p → p) = True := by simp
|
||||
|
||||
theorem not_and (p q : Prop) : (¬(p ∧ q)) = (¬p ∨ ¬q) := by
|
||||
by_cases p <;> by_cases q <;> simp [*]
|
||||
theorem not_true : (¬True) = False := by simp
|
||||
theorem not_false : (¬False) = True := by simp
|
||||
theorem not_not (p : Prop) : (¬¬p) = p := by by_cases p <;> simp [*]
|
||||
theorem not_and (p q : Prop) : (¬(p ∧ q)) = (¬p ∨ ¬q) := by by_cases p <;> by_cases q <;> simp [*]
|
||||
theorem not_or (p q : Prop) : (¬(p ∨ q)) = (¬p ∧ ¬q) := by by_cases p <;> by_cases q <;> simp [*]
|
||||
theorem not_ite {_ : Decidable p} (q r : Prop) : (¬ite p q r) = ite p (¬q) (¬r) := by by_cases p <;> simp [*]
|
||||
theorem not_forall (p : α → Prop) : (¬∀ x, p x) = ∃ x, ¬p x := by simp
|
||||
theorem not_exists (p : α → Prop) : (¬∃ x, p x) = ∀ x, ¬p x := by simp
|
||||
theorem not_implies (p q : Prop) : (¬(p → q)) = (p ∧ ¬q) := by simp
|
||||
|
||||
theorem not_ite {_ : Decidable p} (q r : Prop) : (¬ite p q r) = ite p (¬q) (¬r) := by
|
||||
by_cases p <;> simp [*]
|
||||
theorem or_assoc (p q r : Prop) : ((p ∨ q) ∨ r) = (p ∨ (q ∨ r)) := by by_cases p <;> simp [*]
|
||||
theorem or_swap12 (p q r : Prop) : (p ∨ q ∨ r) = (q ∨ p ∨ r) := by by_cases p <;> simp [*]
|
||||
theorem or_swap13 (p q r : Prop) : (p ∨ q ∨ r) = (r ∨ q ∨ p) := by by_cases p <;> by_cases q <;> simp [*]
|
||||
|
||||
theorem ite_true_false {_ : Decidable p} : (ite p True False) = p := by
|
||||
by_cases p <;> simp
|
||||
@@ -57,10 +65,6 @@ theorem ite_true_false {_ : Decidable p} : (ite p True False) = p := by
|
||||
theorem ite_false_true {_ : Decidable p} : (ite p False True) = ¬p := by
|
||||
by_cases p <;> simp
|
||||
|
||||
theorem not_forall (p : α → Prop) : (¬∀ x, p x) = ∃ x, ¬p x := by simp
|
||||
|
||||
theorem not_exists (p : α → Prop) : (¬∃ x, p x) = ∀ x, ¬p x := by simp
|
||||
|
||||
theorem cond_eq_ite (c : Bool) (a b : α) : cond c a b = ite c a b := by
|
||||
cases c <;> simp [*]
|
||||
|
||||
@@ -70,9 +74,6 @@ theorem Nat.lt_eq (a b : Nat) : (a < b) = (a + 1 ≤ b) := by
|
||||
theorem Int.lt_eq (a b : Int) : (a < b) = (a + 1 ≤ b) := by
|
||||
simp [Int.lt, LT.lt]
|
||||
|
||||
theorem ge_eq [LE α] (a b : α) : (a ≥ b) = (b ≤ a) := rfl
|
||||
theorem gt_eq [LT α] (a b : α) : (a > b) = (b < a) := rfl
|
||||
|
||||
theorem beq_eq_decide_eq {_ : BEq α} [LawfulBEq α] [DecidableEq α] (a b : α) : (a == b) = (decide (a = b)) := by
|
||||
by_cases a = b
|
||||
next h => simp [h]
|
||||
@@ -81,14 +82,11 @@ theorem beq_eq_decide_eq {_ : BEq α} [LawfulBEq α] [DecidableEq α] (a b : α)
|
||||
theorem bne_eq_decide_not_eq {_ : BEq α} [LawfulBEq α] [DecidableEq α] (a b : α) : (a != b) = (decide (¬ a = b)) := by
|
||||
by_cases a = b <;> simp [*]
|
||||
|
||||
theorem xor_eq (a b : Bool) : (a ^^ b) = (a != b) := by
|
||||
rfl
|
||||
|
||||
theorem natCast_eq [NatCast α] (a : Nat) : (Nat.cast a : α) = (NatCast.natCast a : α) := rfl
|
||||
theorem natCast_div (a b : Nat) : (NatCast.natCast (a / b) : Int) = (NatCast.natCast a) / (NatCast.natCast b) := rfl
|
||||
theorem natCast_mod (a b : Nat) : (NatCast.natCast (a % b) : Int) = (NatCast.natCast a) % (NatCast.natCast b) := rfl
|
||||
theorem natCast_add (a b : Nat) : (NatCast.natCast (a + b : Nat) : Int) = (NatCast.natCast a : Int) + (NatCast.natCast b : Int) := rfl
|
||||
theorem natCast_mul (a b : Nat) : (NatCast.natCast (a * b : Nat) : Int) = (NatCast.natCast a : Int) * (NatCast.natCast b : Int) := rfl
|
||||
theorem natCast_pow (a b : Nat) : (NatCast.natCast (a ^ b : Nat) : Int) = (NatCast.natCast a : Int) ^ b := by simp
|
||||
|
||||
theorem Nat.pow_one (a : Nat) : a ^ 1 = a := by
|
||||
simp
|
||||
@@ -127,52 +125,49 @@ theorem forall_forall_or {α : Sort u} {β : α → Sort v} (p : α → Prop) (q
|
||||
intro h'; simp at h'; have ⟨⟨b, h₁⟩, h₂⟩ := h'
|
||||
replace h := h a b; simp [h₁, h₂] at h
|
||||
|
||||
theorem forall_and {α} {p q : α → Prop} : (∀ x, p x ∧ q x) = ((∀ x, p x) ∧ (∀ x, q x)) := by
|
||||
apply propext; apply _root_.forall_and
|
||||
|
||||
theorem exists_const (α : Sort u) [i : Nonempty α] {b : Prop} : (∃ _ : α, b) = b := by
|
||||
apply propext; apply _root_.exists_const
|
||||
|
||||
theorem exists_or {α : Sort u} {p q : α → Prop} : (∃ x, p x ∨ q x) = ((∃ x, p x) ∨ ∃ x, q x) := by
|
||||
apply propext; apply _root_.exists_or
|
||||
|
||||
theorem exists_prop {a b : Prop} : (∃ _h : a, b) = (a ∧ b) := by
|
||||
apply propext; apply _root_.exists_prop
|
||||
|
||||
theorem exists_and_left {α : Sort u} {p : α → Prop} {b : Prop} : (∃ x, b ∧ p x) = (b ∧ (∃ x, p x)) := by
|
||||
apply propext; apply _root_.exists_and_left
|
||||
|
||||
theorem exists_and_right {α : Sort u} {p : α → Prop} {b : Prop} : (∃ x, p x ∧ b) = ((∃ x, p x) ∧ b) := by
|
||||
apply propext; apply _root_.exists_and_right
|
||||
|
||||
theorem zero_sub (a : Nat) : 0 - a = 0 := by
|
||||
simp
|
||||
|
||||
-- Remark: for additional `grind` simprocs, check `Lean/Meta/Tactic/Grind`
|
||||
init_grind_norm
|
||||
/- Pre theorems -/
|
||||
not_and not_or not_ite not_forall not_exists
|
||||
/- Nat relational ops neg -/
|
||||
Nat.not_ge_eq Nat.not_le_eq
|
||||
|
|
||||
/- Post theorems -/
|
||||
Classical.not_not
|
||||
ne_eq iff_eq eq_self heq_eq_eq
|
||||
forall_or_forall forall_forall_or
|
||||
-- Prop equality
|
||||
eq_true_eq eq_false_eq not_eq_prop
|
||||
-- True
|
||||
not_true
|
||||
-- False
|
||||
not_false_eq_true
|
||||
-- Implication
|
||||
true_imp_eq false_imp_eq imp_true_eq imp_false_eq imp_self_eq
|
||||
iff_eq heq_eq_eq
|
||||
-- And
|
||||
and_true true_and and_false false_and and_assoc
|
||||
-- Or
|
||||
or_true true_or or_false false_or or_assoc
|
||||
-- ite
|
||||
ite_true ite_false ite_true_false ite_false_true
|
||||
dite_eq_ite
|
||||
-- Forall
|
||||
forall_and forall_false forall_true
|
||||
forall_imp_eq_or
|
||||
-- Exists
|
||||
exists_const exists_or exists_prop exists_and_left exists_and_right
|
||||
ite_true_false ite_false_true
|
||||
-- Bool cond
|
||||
cond_eq_ite
|
||||
-- Bool or
|
||||
Bool.or_false Bool.or_true Bool.false_or Bool.true_or Bool.or_eq_true Bool.or_assoc
|
||||
Bool.or_false Bool.or_true Bool.false_or Bool.true_or Bool.or_eq_true
|
||||
-- Bool and
|
||||
Bool.and_false Bool.and_true Bool.false_and Bool.true_and Bool.and_eq_true Bool.and_assoc
|
||||
Bool.and_false Bool.and_true Bool.false_and Bool.true_and Bool.and_eq_true
|
||||
-- Bool not
|
||||
Bool.not_not
|
||||
-- Bool xor
|
||||
xor_eq
|
||||
-- beq
|
||||
beq_iff_eq beq_eq_decide_eq beq_self_eq_true
|
||||
-- bne
|
||||
bne_iff_ne bne_eq_decide_not_eq
|
||||
-- Bool not eq true/false
|
||||
Bool.not_eq_true Bool.not_eq_false
|
||||
-- decide
|
||||
decide_eq_true_eq decide_not not_decide_eq_true
|
||||
-- Nat
|
||||
@@ -180,19 +175,17 @@ init_grind_norm
|
||||
Nat.add_eq Nat.sub_eq Nat.mul_eq Nat.zero_eq Nat.le_eq
|
||||
Nat.div_zero Nat.mod_zero Nat.div_one Nat.mod_one
|
||||
Nat.sub_sub Nat.pow_zero Nat.pow_one Nat.sub_self
|
||||
Nat.one_pow
|
||||
Nat.one_pow Nat.zero_sub
|
||||
-- Int
|
||||
Int.lt_eq
|
||||
Int.emod_neg Int.ediv_neg
|
||||
Int.ediv_zero Int.emod_zero
|
||||
Int.ediv_one Int.emod_one
|
||||
Int.negSucc_eq
|
||||
natCast_eq natCast_div natCast_mod
|
||||
natCast_add natCast_mul
|
||||
natCast_div natCast_mod
|
||||
natCast_add natCast_mul natCast_pow
|
||||
Int.one_pow
|
||||
Int.pow_zero Int.pow_one
|
||||
-- GT GE
|
||||
ge_eq gt_eq
|
||||
-- Int op folding
|
||||
Int.add_def Int.mul_def Int.ofNat_eq_coe
|
||||
Int.Linear.sub_fold Int.Linear.neg_fold
|
||||
@@ -202,6 +195,6 @@ init_grind_norm
|
||||
Function.const_apply Function.comp_apply Function.const_comp
|
||||
Function.comp_const Function.true_comp Function.false_comp
|
||||
-- Field
|
||||
Field.div_eq_mul_inv Field.inv_zero Field.inv_inv Field.inv_one Field.inv_neg
|
||||
Field.inv_zero Field.inv_inv Field.inv_one Field.inv_neg
|
||||
|
||||
end Lean.Grind
|
||||
|
||||
@@ -115,6 +115,11 @@ structure Config where
|
||||
When `true` (default: `true`), uses procedure for handling linear integer arithmetic for `Int` and `Nat`.
|
||||
-/
|
||||
cutsat := true
|
||||
/--
|
||||
Maximum exponent eagerly evaluated while computing bounds for `ToInt` and
|
||||
the characteristic of a ring.
|
||||
-/
|
||||
exp : Nat := 2^20
|
||||
deriving Inhabited, BEq
|
||||
|
||||
end Lean.Grind
|
||||
|
||||
@@ -37,7 +37,7 @@ inductive IntInterval : Type where
|
||||
io (hi : Int)
|
||||
| /-- The infinite interval `(-∞, ∞)`. -/
|
||||
ii
|
||||
deriving BEq, DecidableEq
|
||||
deriving BEq, DecidableEq, Inhabited
|
||||
|
||||
instance : LawfulBEq IntInterval where
|
||||
rfl := by intro a; cases a <;> simp_all! [BEq.beq]
|
||||
|
||||
@@ -16,6 +16,11 @@ namespace Lean.Grind
|
||||
/-- A helper gadget for annotating nested proofs in goals. -/
|
||||
def nestedProof (p : Prop) {h : p} : p := h
|
||||
|
||||
/-- A helper gadget for annotating nested decidable instances in goals. -/
|
||||
-- Remark: we currently have special gadgets for the two most common subsingletons in Lean, and are the only
|
||||
-- currently supported in `grind`. We may add a generic `nestedSubsingleton` inn the future.
|
||||
@[expose] def nestedDecidable {p : Prop} (h : Decidable p) : Decidable p := h
|
||||
|
||||
/--
|
||||
Gadget for marking `match`-expressions that should not be reduced by the `grind` simplifier, but the discriminants should be normalized.
|
||||
We use it when adding instances of `match`-equations to prevent them from being simplified to true.
|
||||
@@ -53,11 +58,14 @@ abbrev MatchCond (p : Prop) : Prop := p
|
||||
Similar to `MatchCond`, but not reducible. We use it to ensure `simp`
|
||||
will not eliminate it. After we apply `simp`, we replace it with `MatchCond`.
|
||||
-/
|
||||
def PreMatchCond (p : Prop) : Prop := p
|
||||
@[expose] def PreMatchCond (p : Prop) : Prop := p
|
||||
|
||||
theorem nestedProof_congr (p q : Prop) (h : p = q) (hp : p) (hq : q) : @nestedProof p hp ≍ @nestedProof q hq := by
|
||||
subst h; apply HEq.refl
|
||||
|
||||
theorem nestedDecidable_congr (p q : Prop) (h : p = q) (hp : Decidable p) (hq : Decidable q) : @nestedDecidable p hp ≍ @nestedDecidable q hq := by
|
||||
subst h; cases hp <;> cases hq <;> simp <;> contradiction
|
||||
|
||||
@[app_unexpander nestedProof]
|
||||
meta def nestedProofUnexpander : PrettyPrinter.Unexpander := fun stx => do
|
||||
match stx with
|
||||
|
||||
@@ -161,7 +161,7 @@ structure Config where
|
||||
-/
|
||||
contextual : Bool := false
|
||||
/--
|
||||
When true (default: `true`) then the simplifier caches the result of simplifying each subexpression, if possible.
|
||||
When true (default: `true`) then the simplifier caches the result of simplifying each sub-expression, if possible.
|
||||
-/
|
||||
memoize : Bool := true
|
||||
/--
|
||||
@@ -252,14 +252,14 @@ structure Config where
|
||||
-/
|
||||
implicitDefEqProofs : Bool := true
|
||||
/--
|
||||
When `true` (default : `true`), then `simp` will remove unused `let` and `have` expressions:
|
||||
When `true` (default : `true`), then `simp` removes unused `let` and `have` expressions:
|
||||
`let x := v; e` simplifies to `e` when `x` does not occur in `e`.
|
||||
This option takes precedence over `zeta` and `zetaHave`.
|
||||
-/
|
||||
zetaUnused : Bool := true
|
||||
/--
|
||||
When `true` (default : `true`), then simps will catch runtime exceptions and
|
||||
convert them into `simp` exceptions.
|
||||
When `true` (default : `true`), then `simp` catches runtime exceptions and
|
||||
converts them into `simp` exceptions.
|
||||
-/
|
||||
catchRuntime : Bool := true
|
||||
/--
|
||||
@@ -273,6 +273,14 @@ structure Config where
|
||||
if they are non-dependent. This only applies when `zeta := false`.
|
||||
-/
|
||||
letToHave : Bool := true
|
||||
/--
|
||||
When `true` (default : `true`), `simp` tries to realize constant `f.congr_simp`
|
||||
when constructing an auxiliary congruence proof for `f`.
|
||||
This option exists because the termination prover uses `simp` and `withoutModifyingEnv`
|
||||
while constructing the termination proof. Thus, any constant realized by `simp`
|
||||
is deleted.
|
||||
-/
|
||||
congrConsts : Bool := true
|
||||
deriving Inhabited, BEq
|
||||
|
||||
-- Configuration object for `simp_all`
|
||||
|
||||
@@ -763,7 +763,7 @@ and checks that they match the contents of the docstring.
|
||||
Basic example:
|
||||
```lean
|
||||
/--
|
||||
error: unknown identifier 'x'
|
||||
error: Unknown identifier `x`
|
||||
-/
|
||||
#guard_msgs in
|
||||
example : α := x
|
||||
|
||||
@@ -886,6 +886,9 @@ theorem ULift.up_down {α : Type u} (b : ULift.{v} α) : Eq (up (down b)) b := r
|
||||
/-- Bijection between `α` and `ULift.{v} α` -/
|
||||
theorem ULift.down_up {α : Type u} (a : α) : Eq (down (up.{v} a)) a := rfl
|
||||
|
||||
instance [Inhabited α] : Inhabited (ULift α) where
|
||||
default := ULift.up default
|
||||
|
||||
/--
|
||||
Either a proof that `p` is true or a proof that `p` is false. This is equivalent to a `Bool` paired
|
||||
with a proof that the `Bool` is `true` if and only if `p` is true.
|
||||
@@ -2565,7 +2568,7 @@ This function is `@[macro_inline]`, so `dflt` will not be evaluated unless `opt`
|
||||
|
||||
Examples:
|
||||
* `(some "hello").getD "goodbye" = "hello"`
|
||||
* `none.getD "goodbye" = "hello"`
|
||||
* `none.getD "goodbye" = "goodbye"`
|
||||
-/
|
||||
@[macro_inline, expose] def Option.getD (opt : Option α) (dflt : α) : α :=
|
||||
match opt with
|
||||
@@ -3724,7 +3727,7 @@ class MonadWithReader (ρ : outParam (Type u)) (m : Type u → Type v) where
|
||||
During the inner action `x`, reading the value returns `f` applied to the original value. After
|
||||
control returns from `x`, the reader monad's value is restored.
|
||||
-/
|
||||
withReader {α : Type u} : (ρ → ρ) → m α → m α
|
||||
withReader {α : Type u} : (f : ρ → ρ) → (x : m α) → m α
|
||||
|
||||
export MonadWithReader (withReader)
|
||||
|
||||
@@ -4553,12 +4556,12 @@ in `s!"value = {x}"`.
|
||||
abbrev interpolatedStrKind : SyntaxNodeKind := `interpolatedStrKind
|
||||
|
||||
/-- Creates an info-less node of the given kind and children. -/
|
||||
@[inline] def mkNode (k : SyntaxNodeKind) (args : Array Syntax) : TSyntax (.cons k .nil) :=
|
||||
@[inline, expose] def mkNode (k : SyntaxNodeKind) (args : Array Syntax) : TSyntax (.cons k .nil) :=
|
||||
⟨Syntax.node SourceInfo.none k args⟩
|
||||
|
||||
/-- Creates an info-less `nullKind` node with the given children, if any. -/
|
||||
-- NOTE: used by the quotation elaborator output
|
||||
@[inline] def mkNullNode (args : Array Syntax := Array.empty) : Syntax :=
|
||||
@[inline, expose] def mkNullNode (args : Array Syntax := Array.empty) : Syntax :=
|
||||
mkNode nullKind args |>.raw
|
||||
|
||||
namespace Syntax
|
||||
|
||||
@@ -151,7 +151,7 @@ matching on the constructor `quot.mk`.
|
||||
`rcases h : e with PAT` will do the same as `rcases e with PAT` with the exception that an
|
||||
assumption `h : e = PAT` will be added to the context.
|
||||
-/
|
||||
syntax (name := rcases) "rcases" elimTarget,* (" with " rcasesPatLo)? : tactic
|
||||
syntax (name := rcases) "rcases " elimTarget,* (" with " rcasesPatLo)? : tactic
|
||||
|
||||
/--
|
||||
The `obtain` tactic is a combination of `have` and `rcases`. See `rcases` for
|
||||
|
||||
@@ -144,6 +144,12 @@ theorem ite_congr {x y u v : α} {s : Decidable b} [Decidable c]
|
||||
| inl h => rw [if_pos h]; subst b; rw [if_pos h]; exact h₂ h
|
||||
| inr h => rw [if_neg h]; subst b; rw [if_neg h]; exact h₃ h
|
||||
|
||||
theorem ite_cond_congr {α} {b c : Prop} {s : Decidable b} [Decidable c] {x y : α}
|
||||
(h₁ : b = c) : ite b x y = ite c x y := by
|
||||
cases Decidable.em c with
|
||||
| inl h => rw [if_pos h]; subst b; rw [if_pos h]
|
||||
| inr h => rw [if_neg h]; subst b; rw [if_neg h]
|
||||
|
||||
theorem Eq.mpr_prop {p q : Prop} (h₁ : p = q) (h₂ : q) : p := h₁ ▸ h₂
|
||||
theorem Eq.mpr_not {p q : Prop} (h₁ : p = q) (h₂ : ¬q) : ¬p := h₁ ▸ h₂
|
||||
|
||||
@@ -158,6 +164,13 @@ theorem dite_congr {_ : Decidable b} [Decidable c]
|
||||
| inl h => rw [dif_pos h]; subst b; rw [dif_pos h]; exact h₂ h
|
||||
| inr h => rw [dif_neg h]; subst b; rw [dif_neg h]; exact h₃ h
|
||||
|
||||
theorem dite_cond_congr {α} {b c : Prop} {s : Decidable b} [Decidable c]
|
||||
{x : b → α} {y : ¬ b → α} (h₁ : b = c) :
|
||||
dite b x y = dite c (fun h => x (h₁.mpr_prop h)) (fun h => y (h₁.mpr_not h)) := by
|
||||
cases Decidable.em c with
|
||||
| inl h => rw [dif_pos h]; subst b; rw [dif_pos h]
|
||||
| inr h => rw [dif_neg h]; subst b; rw [dif_neg h]
|
||||
|
||||
@[simp] theorem ne_eq (a b : α) : (a ≠ b) = ¬(a = b) := rfl
|
||||
norm_cast_add_elim ne_eq
|
||||
@[simp] theorem ite_true (a b : α) : (if True then a else b) = a := rfl
|
||||
|
||||
@@ -24,7 +24,7 @@ reordered.
|
||||
Makes sure we never reorder `IO` operations.
|
||||
|
||||
TODO: mark opaque -/
|
||||
def IO.RealWorld : Type := Unit
|
||||
@[expose] def IO.RealWorld : Type := Unit
|
||||
|
||||
/--
|
||||
A monad that can have side effects on the external world or throw exceptions of type `ε`.
|
||||
@@ -1350,7 +1350,7 @@ output, or error streams.
|
||||
For `IO.Process.Stdio.piped`, this type is `IO.FS.Handle`. Otherwise, it is `Unit`, because no
|
||||
communication is possible.
|
||||
-/
|
||||
def Stdio.toHandleType : Stdio → Type
|
||||
@[expose] def Stdio.toHandleType : Stdio → Type
|
||||
| Stdio.piped => FS.Handle
|
||||
| Stdio.inherit => Unit
|
||||
| Stdio.null => Unit
|
||||
@@ -1717,7 +1717,7 @@ def readToEnd (s : Stream) : IO String := do
|
||||
match String.fromUTF8? data with
|
||||
| some s => return s
|
||||
| none => throw <| .userError s!"Tried to read from stream containing non UTF-8 data."
|
||||
|
||||
|
||||
/--
|
||||
Reads the entire remaining contents of the stream as a UTF-8-encoded array of lines.
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ def Promise.result := @Promise.result!
|
||||
/--
|
||||
Like `Promise.result`, but resolves to `dflt` if the promise is dropped without ever being resolved.
|
||||
-/
|
||||
@[macro_inline] def Promise.resultD (promise : Promise α) (dflt : α) : Task α :=
|
||||
@[macro_inline, expose] def Promise.resultD (promise : Promise α) (dflt : α) : Task α :=
|
||||
promise.result?.map (sync := true) (·.getD dflt)
|
||||
|
||||
/--
|
||||
|
||||
@@ -826,8 +826,12 @@ The `have` tactic is for adding hypotheses to the local context of the main goal
|
||||
It is convenient for types that have only one applicable constructor.
|
||||
For example, given `h : p ∧ q ∧ r`, `have ⟨h₁, h₂, h₃⟩ := h` produces the
|
||||
hypotheses `h₁ : p`, `h₂ : q`, and `h₃ : r`.
|
||||
* The syntax `have (eq := h) pat := e` is equivalent to `match h : e with | pat => _`,
|
||||
which adds the equation `h : e = pat` to the local context.
|
||||
|
||||
The tactic supports all the same syntax variants and options as the `have` term.
|
||||
-/
|
||||
syntax "have " letConfig letDecl : tactic
|
||||
syntax "have" letConfig letDecl : tactic
|
||||
macro_rules
|
||||
-- special case: when given a nested `by` block, move it outside of the `refine` to enable
|
||||
-- incrementality
|
||||
@@ -878,8 +882,12 @@ The `let` tactic is for adding definitions to the local context of the main goal
|
||||
It is convenient for types that let only one applicable constructor.
|
||||
For example, given `p : α × β × γ`, `let ⟨x, y, z⟩ := p` produces the
|
||||
local variables `x : α`, `y : β`, and `z : γ`.
|
||||
* The syntax `let (eq := h) pat := e` is equivalent to `match h : e with | pat => _`,
|
||||
which adds the equation `h : e = pat` to the local context.
|
||||
|
||||
The tactic supports all the same syntax variants and options as the `let` term.
|
||||
-/
|
||||
macro "let " c:letConfig d:letDecl : tactic => `(tactic| refine_lift let $c:letConfig $d:letDecl; ?_)
|
||||
macro "let" c:letConfig d:letDecl : tactic => `(tactic| refine_lift let $c:letConfig $d:letDecl; ?_)
|
||||
|
||||
/-- `let rec f : t := e` adds a recursive definition `f` to the current goal.
|
||||
The syntax is the same as term-mode `let rec`. -/
|
||||
@@ -890,24 +898,21 @@ macro_rules
|
||||
/-- Similar to `refine_lift`, but using `refine'` -/
|
||||
macro "refine_lift' " e:term : tactic => `(tactic| focus (refine' no_implicit_lambda% $e; rotate_right))
|
||||
/-- Similar to `have`, but using `refine'` -/
|
||||
macro (name := tacticHave') "have' " c:letConfig d:letDecl : tactic => `(tactic| refine_lift' have $c:letConfig $d:letDecl; ?_)
|
||||
set_option linter.missingDocs false in -- OK, because `tactic_alt` causes inheritance of docs
|
||||
macro (priority := high) "have'" x:ident " := " p:term : tactic => `(tactic| have' $x:ident : _ := $p)
|
||||
attribute [tactic_alt tacticHave'] «tacticHave'_:=_»
|
||||
macro (name := tacticHave') "have'" c:letConfig d:letDecl : tactic => `(tactic| refine_lift' have $c:letConfig $d:letDecl; ?_)
|
||||
/-- Similar to `let`, but using `refine'` -/
|
||||
macro "let' " c:letConfig d:letDecl : tactic => `(tactic| refine_lift' let $c:letConfig $d:letDecl; ?_)
|
||||
macro "let'" c:letConfig d:letDecl : tactic => `(tactic| refine_lift' let $c:letConfig $d:letDecl; ?_)
|
||||
|
||||
/--
|
||||
The left hand side of an induction arm, `| foo a b c` or `| @foo a b c`
|
||||
where `foo` is a constructor of the inductive type and `a b c` are the arguments
|
||||
to the constructor.
|
||||
-/
|
||||
syntax inductionAltLHS := withPosition("| " (("@"? ident) <|> hole) (colGt (ident <|> hole))*)
|
||||
syntax inductionAltLHS := ppDedent(ppLine) withPosition("| " (("@"? ident) <|> hole) (colGt (ident <|> hole))*)
|
||||
/--
|
||||
In induction alternative, which can have 1 or more cases on the left
|
||||
and `_`, `?_`, or a tactic sequence after the `=>`.
|
||||
-/
|
||||
syntax inductionAlt := ppDedent(ppLine) inductionAltLHS+ (" => " (hole <|> syntheticHole <|> tacticSeq))?
|
||||
syntax inductionAlt := inductionAltLHS+ (" => " (hole <|> syntheticHole <|> tacticSeq))?
|
||||
/--
|
||||
After `with`, there is an optional tactic that runs on all branches, and
|
||||
then a list of alternatives.
|
||||
@@ -1117,7 +1122,7 @@ For a `match` expression with `n` cases, the `split` tactic generates at most `n
|
||||
For example, given `n : Nat`, and a target `if n = 0 then Q else R`, `split` will generate
|
||||
one goal with hypothesis `n = 0` and target `Q`, and a second goal with hypothesis
|
||||
`¬n = 0` and target `R`. Note that the introduced hypothesis is unnamed, and is commonly
|
||||
renamed used the `case` or `next` tactics.
|
||||
renamed using the `case` or `next` tactics.
|
||||
|
||||
- `split` will split the goal (target).
|
||||
- `split at h` will split the hypothesis `h`.
|
||||
@@ -2045,6 +2050,16 @@ macro (name := mstopMacro) (priority:=low) "mstop" : tactic =>
|
||||
Macro.throwError "to use `mstop`, please include `import Std.Tactic.Do`"
|
||||
|
||||
|
||||
/--
|
||||
Leaves the stateful proof mode of `Std.Do.SPred`, tries to eta-expand through all definitions
|
||||
related to the logic of the `Std.Do.SPred` and gently simplifies the resulting pure Lean
|
||||
proposition. This is often the right thing to do after `mvcgen` in order for automation to prove
|
||||
the goal.
|
||||
-/
|
||||
macro (name := mleaveMacro) (priority:=low) "mleave" : tactic =>
|
||||
Macro.throwError "to use `mleave`, please include `import Std.Tactic.Do`"
|
||||
|
||||
|
||||
/--
|
||||
Like `rcases`, but operating on stateful `Std.Do.SPred` goals.
|
||||
Example: Given a goal `h : (P ∧ (Q ∨ R) ∧ (Q → R)) ⊢ₛ R`,
|
||||
@@ -2117,7 +2132,7 @@ the verification conditions `?pre : H ⊢ₛ P` and `?post : Q ⊢ₚ Q'`.
|
||||
success and failure continuations.
|
||||
* `?pre` and `?post.*` goals introduce their stateful hypothesis as `h`.
|
||||
* Any uninstantiated MVar arising from instantiation of `foo_spec` becomes a new subgoal.
|
||||
* If the goal looks like `fun s => _ ⊢ₛ _` then `mspec` will first `mintro ∀s`.
|
||||
* If the target of the stateful goal looks like `fun s => _` then `mspec` will first `mintro ∀s`.
|
||||
* If `P` has schematic variables that can be instantiated by doing `mintro ∀s`, for example
|
||||
`foo_spec : ∀(n:Nat), ⦃⌜n = ‹Nat›ₛ⌝⦄ foo ⦃Q⦄`, then `mspec` will do `mintro ∀s` first to
|
||||
instantiate `n = s`.
|
||||
|
||||
@@ -144,7 +144,7 @@ def registerTagAttribute (name : Name) (descr : String)
|
||||
addImportedFn := fun _ _ => pure {}
|
||||
addEntryFn := fun (s : NameSet) n => s.insert n
|
||||
exportEntriesFn := fun es =>
|
||||
let r : Array Name := es.fold (fun a e => a.push e) #[]
|
||||
let r : Array Name := es.foldl (fun a e => a.push e) #[]
|
||||
r.qsort Name.quickLt
|
||||
statsFn := fun s => "tag attribute" ++ Format.line ++ "number of local entries: " ++ format s.size
|
||||
asyncMode := asyncMode
|
||||
@@ -219,7 +219,7 @@ def registerParametricAttribute (impl : ParametricAttributeImpl α) : IO (Parame
|
||||
addImportedFn := fun s => impl.afterImport s *> pure {}
|
||||
addEntryFn := fun (s : NameMap α) (p : Name × α) => s.insert p.1 p.2
|
||||
exportEntriesFn := fun m =>
|
||||
let r : Array (Name × α) := m.fold (fun a n p => a.push (n, p)) #[]
|
||||
let r : Array (Name × α) := m.foldl (fun a n p => a.push (n, p)) #[]
|
||||
r.qsort (fun a b => Name.quickLt a.1 b.1)
|
||||
statsFn := fun s => "parametric attribute" ++ Format.line ++ "number of local entries: " ++ format s.size
|
||||
}
|
||||
@@ -276,7 +276,7 @@ def registerEnumAttributes (attrDescrs : List (Name × String × α))
|
||||
addImportedFn := fun _ _ => pure {}
|
||||
addEntryFn := fun (s : NameMap α) (p : Name × α) => s.insert p.1 p.2
|
||||
exportEntriesFn := fun m =>
|
||||
let r : Array (Name × α) := m.fold (fun a n p => a.push (n, p)) #[]
|
||||
let r : Array (Name × α) := m.foldl (fun a n p => a.push (n, p)) #[]
|
||||
r.qsort (fun a b => Name.quickLt a.1 b.1)
|
||||
statsFn := fun s => "enumeration attribute extension" ++ Format.line ++ "number of local entries: " ++ format s.size
|
||||
-- We assume (and check below) that, if used asynchronously, enum attributes are set only in the
|
||||
@@ -364,7 +364,7 @@ private def AttributeExtension.mkInitial : IO AttributeExtensionState := do
|
||||
|
||||
unsafe def mkAttributeImplOfConstantUnsafe (env : Environment) (opts : Options) (declName : Name) : Except String AttributeImpl :=
|
||||
match env.find? declName with
|
||||
| none => throw ("unknown constant '" ++ toString declName ++ "'")
|
||||
| none => throw ("Unknown constant `" ++ toString declName ++ "`")
|
||||
| some info =>
|
||||
match info.type with
|
||||
| Expr.const `Lean.AttributeImpl _ => env.evalConst AttributeImpl opts declName
|
||||
|
||||
@@ -6,7 +6,6 @@ Authors: Leonardo de Moura
|
||||
prelude
|
||||
import Lean.Compiler.InlineAttrs
|
||||
import Lean.Compiler.Specialize
|
||||
import Lean.Compiler.ConstFolding
|
||||
import Lean.Compiler.ClosedTermCache
|
||||
import Lean.Compiler.ExternAttr
|
||||
import Lean.Compiler.ImplementedByAttr
|
||||
@@ -17,5 +16,4 @@ import Lean.Compiler.FFI
|
||||
import Lean.Compiler.MetaAttr
|
||||
import Lean.Compiler.NoncomputableAttr
|
||||
import Lean.Compiler.Main
|
||||
import Lean.Compiler.AtMostOnce -- TODO: delete after we port code generator to Lean
|
||||
import Lean.Compiler.Old -- TODO: delete after we port code generator to Lean
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
/-
|
||||
Copyright (c) 2022 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Leonardo de Moura
|
||||
-/
|
||||
prelude
|
||||
import Lean.Environment
|
||||
|
||||
namespace Lean.Compiler
|
||||
|
||||
namespace atMostOnce
|
||||
|
||||
structure AtMostOnceData where
|
||||
found : Bool
|
||||
result : Bool
|
||||
|
||||
def Visitor := AtMostOnceData → AtMostOnceData
|
||||
|
||||
@[inline] def seq (f g : Visitor) : Visitor := fun d =>
|
||||
match f d with
|
||||
| ⟨found, false⟩ => ⟨found, false⟩
|
||||
| other => g other
|
||||
|
||||
instance : AndThen Visitor where
|
||||
andThen a b := seq a (b ())
|
||||
|
||||
@[inline] def skip : Visitor := id
|
||||
|
||||
@[inline] def visitFVar (x y : FVarId) : Visitor
|
||||
| d@{result := false, ..} => d
|
||||
| {found := false, result := true} => {found := x == y, result := true}
|
||||
| {found := true, result := true} => {found := true, result := x != y}
|
||||
|
||||
def visit (x : FVarId) : Expr → Visitor
|
||||
| Expr.fvar y => visitFVar y x
|
||||
| Expr.app f a => visit x a >> visit x f
|
||||
| Expr.lam _ d b _ => visit x d >> visit x b
|
||||
| Expr.forallE _ d b _ => visit x d >> visit x b
|
||||
| Expr.letE _ t v b _ => visit x t >> visit x v >> visit x b
|
||||
| Expr.mdata _ e => visit x e
|
||||
| Expr.proj _ _ e => visit x e
|
||||
| _ => skip
|
||||
|
||||
end atMostOnce
|
||||
|
||||
open atMostOnce (visit) in
|
||||
/-- Return true iff the free variable with id `x` occurs at most once in `e` -/
|
||||
@[export lean_at_most_once]
|
||||
def atMostOnce (e : Expr) (x : FVarId) : Bool :=
|
||||
let {result := result, ..} := visit x e {found := false, result := true}
|
||||
result
|
||||
|
||||
end Lean.Compiler
|
||||
@@ -10,7 +10,6 @@ namespace Lean
|
||||
def markBorrowed (e : Expr) : Expr :=
|
||||
mkAnnotation `borrowed e
|
||||
|
||||
@[export lean_is_marked_borrowed]
|
||||
def isMarkedBorrowed (e : Expr) : Bool :=
|
||||
annotation? `borrowed e |>.isSome
|
||||
|
||||
|
||||
@@ -72,7 +72,6 @@ private def initFn :=
|
||||
discard <| add declName attrKind
|
||||
}
|
||||
|
||||
@[export lean_csimp_replace_constants]
|
||||
def replaceConstants (env : Environment) (e : Expr) : Expr :=
|
||||
let s := ext.getState env
|
||||
e.replace fun e =>
|
||||
|
||||
@@ -23,11 +23,9 @@ builtin_initialize closedTermCacheExt : EnvExtension ClosedTermCache ←
|
||||
let c := newState.map.find! e
|
||||
{ s with map := s.map.insert e c, constNames := s.constNames.insert c, revExprs := e :: s.revExprs })
|
||||
|
||||
@[export lean_cache_closed_term_name]
|
||||
def cacheClosedTermName (env : Environment) (e : Expr) (n : Name) : Environment :=
|
||||
closedTermCacheExt.modifyState env fun s => { s with map := s.map.insert e n, constNames := s.constNames.insert n }
|
||||
|
||||
@[export lean_get_closed_term_name]
|
||||
def getClosedTermName? (env : Environment) (e : Expr) : Option Name :=
|
||||
(closedTermCacheExt.getState env).map.find? e
|
||||
|
||||
|
||||
@@ -1,204 +0,0 @@
|
||||
/-
|
||||
Copyright (c) 2019 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Leonardo de Moura
|
||||
-/
|
||||
prelude
|
||||
import Lean.Expr
|
||||
|
||||
/-! Constant folding for primitives that have special runtime support. -/
|
||||
|
||||
namespace Lean.Compiler
|
||||
|
||||
def mkLcProof (p : Expr) :=
|
||||
mkApp (mkConst ``lcProof []) p
|
||||
|
||||
abbrev BinFoldFn := Bool → Expr → Expr → Option Expr
|
||||
abbrev UnFoldFn := Bool → Expr → Option Expr
|
||||
|
||||
def mkUIntTypeName (nbytes : Nat) : Name :=
|
||||
Name.mkSimple ("UInt" ++ toString nbytes)
|
||||
|
||||
structure NumScalarTypeInfo where
|
||||
nbits : Nat
|
||||
id : Name := mkUIntTypeName nbits
|
||||
ofNatFn : Name := Name.mkStr id "ofNat"
|
||||
toNatFn : Name := Name.mkStr id "toNat"
|
||||
size : Nat := 2^nbits
|
||||
|
||||
def numScalarTypes : List NumScalarTypeInfo :=
|
||||
[{nbits := 8}, {nbits := 16}, {nbits := 32}, {nbits := 64},
|
||||
{id := ``USize, nbits := System.Platform.numBits}]
|
||||
|
||||
def isOfNat (fn : Name) : Bool :=
|
||||
numScalarTypes.any (fun info => info.ofNatFn == fn)
|
||||
|
||||
def isToNat (fn : Name) : Bool :=
|
||||
numScalarTypes.any (fun info => info.toNatFn == fn)
|
||||
|
||||
def getInfoFromFn (fn : Name) : List NumScalarTypeInfo → Option NumScalarTypeInfo
|
||||
| [] => none
|
||||
| info::infos =>
|
||||
if info.ofNatFn == fn then some info
|
||||
else getInfoFromFn fn infos
|
||||
|
||||
def getInfoFromVal : Expr → Option NumScalarTypeInfo
|
||||
| Expr.app (Expr.const fn _) _ => getInfoFromFn fn numScalarTypes
|
||||
| _ => none
|
||||
|
||||
@[export lean_get_num_lit]
|
||||
def getNumLit : Expr → Option Nat
|
||||
| Expr.lit (Literal.natVal n) => some n
|
||||
| Expr.app (Expr.const fn _) a => if isOfNat fn then getNumLit a else none
|
||||
| _ => none
|
||||
|
||||
def mkUIntLit (info : NumScalarTypeInfo) (n : Nat) : Expr :=
|
||||
mkApp (mkConst info.ofNatFn) (mkRawNatLit (n%info.size))
|
||||
|
||||
def mkUInt32Lit (n : Nat) : Expr :=
|
||||
mkUIntLit {nbits := 32} n
|
||||
|
||||
def foldBinUInt (fn : NumScalarTypeInfo → Bool → Nat → Nat → Nat) (beforeErasure : Bool) (a₁ a₂ : Expr) : Option Expr := do
|
||||
let n₁ ← getNumLit a₁
|
||||
let n₂ ← getNumLit a₂
|
||||
let info ← getInfoFromVal a₁
|
||||
return mkUIntLit info (fn info beforeErasure n₁ n₂)
|
||||
|
||||
def foldUIntAdd := foldBinUInt fun _ _ => Add.add
|
||||
def foldUIntMul := foldBinUInt fun _ _ => Mul.mul
|
||||
def foldUIntDiv := foldBinUInt fun _ _ => Div.div
|
||||
def foldUIntMod := foldBinUInt fun _ _ => Mod.mod
|
||||
def foldUIntSub := foldBinUInt fun info _ a b => (a + (info.size - b))
|
||||
|
||||
def preUIntBinFoldFns : List (Name × BinFoldFn) :=
|
||||
[(`add, foldUIntAdd), (`mul, foldUIntMul), (`div, foldUIntDiv),
|
||||
(`mod, foldUIntMod), (`sub, foldUIntSub)]
|
||||
|
||||
def uintBinFoldFns : List (Name × BinFoldFn) :=
|
||||
numScalarTypes.foldl (fun r info => r ++ (preUIntBinFoldFns.map (fun ⟨suffix, fn⟩ => (info.id ++ suffix, fn)))) []
|
||||
|
||||
def foldNatBinOp (fn : Nat → Nat → Nat) (a₁ a₂ : Expr) : Option Expr := do
|
||||
let n₁ ← getNumLit a₁
|
||||
let n₂ ← getNumLit a₂
|
||||
return mkRawNatLit (fn n₁ n₂)
|
||||
|
||||
def foldNatAdd (_ : Bool) := foldNatBinOp Add.add
|
||||
def foldNatMul (_ : Bool) := foldNatBinOp Mul.mul
|
||||
def foldNatDiv (_ : Bool) := foldNatBinOp Div.div
|
||||
def foldNatMod (_ : Bool) := foldNatBinOp Mod.mod
|
||||
|
||||
-- TODO: add option for controlling the limit
|
||||
def natPowThreshold := 256
|
||||
|
||||
def foldNatPow (_ : Bool) (a₁ a₂ : Expr) : Option Expr := do
|
||||
let n₁ ← getNumLit a₁
|
||||
let n₂ ← getNumLit a₂
|
||||
if n₂ < natPowThreshold then
|
||||
return mkRawNatLit (n₁ ^ n₂)
|
||||
else
|
||||
failure
|
||||
|
||||
def mkNatEq (a b : Expr) : Expr :=
|
||||
mkAppN (mkConst ``Eq [levelOne]) #[(mkConst `Nat), a, b]
|
||||
|
||||
def mkNatLt (a b : Expr) : Expr :=
|
||||
mkAppN (mkConst ``LT.lt [levelZero]) #[mkConst ``Nat, mkConst ``Nat.lt, a, b]
|
||||
|
||||
def mkNatLe (a b : Expr) : Expr :=
|
||||
mkAppN (mkConst ``LE.le [levelZero]) #[mkConst ``Nat, mkConst ``Nat.le, a, b]
|
||||
|
||||
def toDecidableExpr (beforeErasure : Bool) (pred : Expr) (r : Bool) : Expr :=
|
||||
match beforeErasure, r with
|
||||
| false, true => mkConst ``Bool.true
|
||||
| false, false => mkConst ``Bool.false
|
||||
| true, true => mkDecIsTrue pred (mkLcProof pred)
|
||||
| true, false => mkDecIsFalse pred (mkLcProof pred)
|
||||
|
||||
def foldNatBinPred (mkPred : Expr → Expr → Expr) (fn : Nat → Nat → Bool)
|
||||
(beforeErasure : Bool) (a₁ a₂ : Expr) : Option Expr := do
|
||||
let n₁ ← getNumLit a₁
|
||||
let n₂ ← getNumLit a₂
|
||||
return toDecidableExpr beforeErasure (mkPred a₁ a₂) (fn n₁ n₂)
|
||||
|
||||
def foldNatDecEq := foldNatBinPred mkNatEq (fun a b => a = b)
|
||||
def foldNatDecLt := foldNatBinPred mkNatLt (fun a b => a < b)
|
||||
def foldNatDecLe := foldNatBinPred mkNatLe (fun a b => a ≤ b)
|
||||
|
||||
def foldNatBinBoolPred (fn : Nat → Nat → Bool) (a₁ a₂ : Expr) : Option Expr := do
|
||||
let n₁ ← getNumLit a₁
|
||||
let n₂ ← getNumLit a₂
|
||||
if fn n₁ n₂ then
|
||||
return mkConst ``Bool.true
|
||||
else
|
||||
return mkConst ``Bool.false
|
||||
|
||||
def foldNatBeq := fun _ : Bool => foldNatBinBoolPred (fun a b => a == b)
|
||||
def foldNatBlt := fun _ : Bool => foldNatBinBoolPred (fun a b => a < b)
|
||||
def foldNatBle := fun _ : Bool => foldNatBinBoolPred (fun a b => a ≤ b)
|
||||
|
||||
def natFoldFns : List (Name × BinFoldFn) :=
|
||||
[(``Nat.add, foldNatAdd),
|
||||
(``Nat.mul, foldNatMul),
|
||||
(``Nat.div, foldNatDiv),
|
||||
(``Nat.mod, foldNatMod),
|
||||
(``Nat.pow, foldNatPow),
|
||||
(``Nat.decEq, foldNatDecEq),
|
||||
(``Nat.decLt, foldNatDecLt),
|
||||
(``Nat.decLe, foldNatDecLe),
|
||||
(``Nat.beq, foldNatBeq),
|
||||
(``Nat.blt, foldNatBlt),
|
||||
(``Nat.ble, foldNatBle)
|
||||
]
|
||||
|
||||
def binFoldFns : List (Name × BinFoldFn) :=
|
||||
uintBinFoldFns ++ natFoldFns
|
||||
|
||||
def foldNatSucc (_ : Bool) (a : Expr) : Option Expr := do
|
||||
let n ← getNumLit a
|
||||
return mkRawNatLit (n+1)
|
||||
|
||||
def foldCharOfNat (beforeErasure : Bool) (a : Expr) : Option Expr := do
|
||||
guard (!beforeErasure)
|
||||
let n ← getNumLit a
|
||||
if isValidChar n.toUInt32 then
|
||||
return mkUInt32Lit n
|
||||
else
|
||||
return mkUInt32Lit 0
|
||||
|
||||
def foldToNat (size : Nat) (_ : Bool) (a : Expr) : Option Expr := do
|
||||
let n ← getNumLit a
|
||||
return mkRawNatLit (n % size)
|
||||
|
||||
|
||||
def uintFoldToNatFns : List (Name × UnFoldFn) :=
|
||||
numScalarTypes.foldl (fun r info => (info.toNatFn, foldToNat info.size) :: r) []
|
||||
|
||||
def unFoldFns : List (Name × UnFoldFn) :=
|
||||
[(``Nat.succ, foldNatSucc),
|
||||
(``Char.ofNat, foldCharOfNat)]
|
||||
++ uintFoldToNatFns
|
||||
|
||||
def findBinFoldFn (fn : Name) : Option BinFoldFn :=
|
||||
binFoldFns.lookup fn
|
||||
|
||||
def findUnFoldFn (fn : Name) : Option UnFoldFn :=
|
||||
unFoldFns.lookup fn
|
||||
|
||||
@[export lean_fold_bin_op]
|
||||
def foldBinOp (beforeErasure : Bool) (f : Expr) (a : Expr) (b : Expr) : Option Expr := do
|
||||
match f with
|
||||
| Expr.const fn _ =>
|
||||
let foldFn ← findBinFoldFn fn
|
||||
foldFn beforeErasure a b
|
||||
| _ =>
|
||||
failure
|
||||
|
||||
@[export lean_fold_un_op]
|
||||
def foldUnOp (beforeErasure : Bool) (f : Expr) (a : Expr) : Option Expr := do
|
||||
match f with
|
||||
| Expr.const fn _ =>
|
||||
let foldFn ← findUnFoldFn fn
|
||||
foldFn beforeErasure a
|
||||
| _ => failure
|
||||
|
||||
end Lean.Compiler
|
||||
@@ -58,7 +58,6 @@ builtin_initialize exportAttr : ParametricAttribute Name ←
|
||||
return exportName
|
||||
}
|
||||
|
||||
@[export lean_get_export_name_for]
|
||||
def getExportNameFor? (env : Environment) (n : Name) : Option Name :=
|
||||
exportAttr.getParam? env n
|
||||
|
||||
|
||||
@@ -59,25 +59,24 @@ private def syntaxToExternAttrData (stx : Syntax) : AttrM ExternAttrData := do
|
||||
entries := entries.push <| ExternEntry.inline backend str
|
||||
return { arity? := arity?, entries := entries.toList }
|
||||
|
||||
-- Forward declaration
|
||||
@[extern "lean_add_extern"]
|
||||
opaque addExtern (env : Environment) (n : Name) : ExceptT String Id Environment
|
||||
opaque addExtern (declName : Name) (externAttrData : ExternAttrData) : CoreM Unit
|
||||
|
||||
builtin_initialize externAttr : ParametricAttribute ExternAttrData ←
|
||||
registerParametricAttribute {
|
||||
name := `extern
|
||||
descr := "builtin and foreign functions"
|
||||
getParam := fun _ stx => syntaxToExternAttrData stx
|
||||
afterSet := fun declName _ => do
|
||||
afterSet := fun declName externAttrData => do
|
||||
let env ← getEnv
|
||||
if env.isProjectionFn declName || env.isConstructor declName then
|
||||
if let some (.thmInfo ..) := env.find? declName then
|
||||
-- We should not mark theorems as extern
|
||||
return ()
|
||||
let env ← ofExcept <| addExtern env declName
|
||||
setEnv env
|
||||
addExtern declName externAttrData
|
||||
}
|
||||
|
||||
@[export lean_get_extern_attr_data]
|
||||
def getExternAttrData? (env : Environment) (n : Name) : Option ExternAttrData :=
|
||||
externAttr.getParam? env n
|
||||
|
||||
@@ -154,7 +153,6 @@ private def getExternConstArity (declName : Name) : CoreM Nat := do
|
||||
| some arity => return arity
|
||||
| none => fromSignature ()
|
||||
|
||||
@[export lean_get_extern_const_arity]
|
||||
def getExternConstArityExport (env : Environment) (declName : Name) : IO (Option Nat) := do
|
||||
try
|
||||
let (arity, _) ← (getExternConstArity declName).toIO { fileName := "<compiler>", fileMap := default } { env := env }
|
||||
|
||||
@@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Leonardo de Moura
|
||||
-/
|
||||
prelude
|
||||
import Lean.Compiler.IR.AddExtern
|
||||
import Lean.Compiler.IR.Basic
|
||||
import Lean.Compiler.IR.Format
|
||||
import Lean.Compiler.IR.CompilerM
|
||||
@@ -23,6 +24,7 @@ import Lean.Compiler.IR.EmitC
|
||||
import Lean.Compiler.IR.Sorry
|
||||
import Lean.Compiler.IR.ToIR
|
||||
import Lean.Compiler.IR.ToIRType
|
||||
import Lean.Compiler.IR.Meta
|
||||
|
||||
-- The following imports are not required by the compiler. They are here to ensure that there
|
||||
-- are no orphaned modules.
|
||||
@@ -36,14 +38,14 @@ register_builtin_option compiler.reuse : Bool := {
|
||||
descr := "heuristically insert reset/reuse instruction pairs"
|
||||
}
|
||||
|
||||
private def compileAux (decls : Array Decl) : CompilerM Unit := do
|
||||
def compile (decls : Array Decl) : CompilerM (Array Decl) := do
|
||||
logDecls `init decls
|
||||
checkDecls decls
|
||||
let mut decls ← elimDeadBranches decls
|
||||
logDecls `elim_dead_branches decls
|
||||
decls := decls.map Decl.pushProj
|
||||
logDecls `push_proj decls
|
||||
if compiler.reuse.get (← read) then
|
||||
if compiler.reuse.get (← getOptions) then
|
||||
decls := decls.map Decl.insertResetReuse
|
||||
logDecls `reset_reuse decls
|
||||
decls := decls.map Decl.elimDead
|
||||
@@ -57,7 +59,7 @@ private def compileAux (decls : Array Decl) : CompilerM Unit := do
|
||||
logDecls `boxing decls
|
||||
decls ← explicitRC decls
|
||||
logDecls `rc decls
|
||||
if compiler.reuse.get (← read) then
|
||||
if compiler.reuse.get (← getOptions) then
|
||||
decls := decls.map Decl.expandResetReuse
|
||||
logDecls `expand_reset_reuse decls
|
||||
decls := decls.map Decl.pushProj
|
||||
@@ -66,29 +68,12 @@ private def compileAux (decls : Array Decl) : CompilerM Unit := do
|
||||
logDecls `result decls
|
||||
checkDecls decls
|
||||
addDecls decls
|
||||
inferMeta decls
|
||||
return decls
|
||||
|
||||
@[export lean_ir_compile]
|
||||
def compile (env : Environment) (opts : Options) (decls : Array Decl) : Log × (Except String Environment) :=
|
||||
match (compileAux decls opts).run { env := env } with
|
||||
| EStateM.Result.ok _ s => (s.log, Except.ok s.env)
|
||||
| EStateM.Result.error msg s => (s.log, Except.error msg)
|
||||
|
||||
def addBoxedVersionAux (decl : Decl) : CompilerM Unit := do
|
||||
let env ← getEnv
|
||||
if !ExplicitBoxing.requiresBoxedVersion env decl then
|
||||
pure ()
|
||||
else
|
||||
let decl := ExplicitBoxing.mkBoxedVersion decl
|
||||
let decls : Array Decl := #[decl]
|
||||
let decls ← explicitRC decls
|
||||
decls.forM fun decl => modifyEnv fun env => addDeclAux env decl
|
||||
pure ()
|
||||
|
||||
-- Remark: we are ignoring the `Log` here. This should be fine.
|
||||
@[export lean_ir_add_boxed_version]
|
||||
def addBoxedVersion (env : Environment) (decl : Decl) : Except String Environment :=
|
||||
match (addBoxedVersionAux decl Options.empty).run { env := env } with
|
||||
| EStateM.Result.ok _ s => Except.ok s.env
|
||||
| EStateM.Result.error msg _ => Except.error msg
|
||||
builtin_initialize
|
||||
registerTraceClass `compiler.ir
|
||||
registerTraceClass `compiler.ir.init (inherited := true)
|
||||
registerTraceClass `compiler.ir.result (inherited := true)
|
||||
|
||||
end Lean.IR
|
||||
|
||||
39
src/Lean/Compiler/IR/AddExtern.lean
Normal file
39
src/Lean/Compiler/IR/AddExtern.lean
Normal file
@@ -0,0 +1,39 @@
|
||||
/-
|
||||
Copyright (c) 2025 Lean FRO LLC. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Cameron Zwarich
|
||||
-/
|
||||
|
||||
prelude
|
||||
import Lean.CoreM
|
||||
import Lean.Compiler.BorrowedAnnotation
|
||||
import Lean.Compiler.ExternAttr
|
||||
import Lean.Compiler.IR.Basic
|
||||
import Lean.Compiler.IR.Boxing
|
||||
import Lean.Compiler.IR.CompilerM
|
||||
import Lean.Compiler.IR.ToIRType
|
||||
import Lean.Compiler.LCNF.MonoTypes
|
||||
|
||||
namespace Lean.IR
|
||||
|
||||
@[export lean_add_extern]
|
||||
def addExtern (declName : Name) (externAttrData : ExternAttrData) : CoreM Unit := do
|
||||
let mut type ← Compiler.LCNF.getOtherDeclMonoType declName
|
||||
let mut params := #[]
|
||||
let mut nextVarIndex := 0
|
||||
repeat
|
||||
let .forallE _ d b _ := type | break
|
||||
let borrow := isMarkedBorrowed d
|
||||
let ty ← toIRType d
|
||||
params := params.push { x := ⟨nextVarIndex⟩, borrow, ty }
|
||||
type := b
|
||||
nextVarIndex := nextVarIndex + 1
|
||||
let irType ← toIRType type
|
||||
let decl := .extern declName params irType externAttrData
|
||||
addDecl decl
|
||||
if !isPrivateName decl.name then
|
||||
modifyEnv (Compiler.LCNF.setDeclPublic · decl.name)
|
||||
if ExplicitBoxing.requiresBoxedVersion (← Lean.getEnv) decl then
|
||||
addDecl (ExplicitBoxing.mkBoxedVersion decl)
|
||||
|
||||
end Lean.IR
|
||||
@@ -24,24 +24,17 @@ abbrev Index := Nat
|
||||
/-- Variable identifier -/
|
||||
structure VarId where
|
||||
idx : Index
|
||||
deriving Inhabited, Repr
|
||||
deriving Inhabited, BEq, Hashable, Repr
|
||||
|
||||
/-- Join point identifier -/
|
||||
structure JoinPointId where
|
||||
idx : Index
|
||||
deriving Inhabited, Repr
|
||||
deriving Inhabited, BEq, Hashable, Repr
|
||||
|
||||
abbrev Index.lt (a b : Index) : Bool := a < b
|
||||
|
||||
instance : BEq VarId := ⟨fun a b => a.idx == b.idx⟩
|
||||
instance : ToString VarId := ⟨fun a => "x_" ++ toString a.idx⟩
|
||||
instance : ToFormat VarId := ⟨fun a => toString a⟩
|
||||
instance : Hashable VarId := ⟨fun a => hash a.idx⟩
|
||||
|
||||
instance : BEq JoinPointId := ⟨fun a b => a.idx == b.idx⟩
|
||||
instance : ToString JoinPointId := ⟨fun a => "block_" ++ toString a.idx⟩
|
||||
instance : ToFormat JoinPointId := ⟨fun a => toString a⟩
|
||||
instance : Hashable JoinPointId := ⟨fun a => hash a.idx⟩
|
||||
|
||||
abbrev MData := KVMap
|
||||
abbrev MData.empty : MData := {}
|
||||
@@ -52,12 +45,13 @@ abbrev MData.empty : MData := {}
|
||||
because it is 32-bit in 32-bit machines, and 64-bit in 64-bit machines,
|
||||
and we want the C++ backend for our Compiler to generate platform independent code.
|
||||
|
||||
- `irrelevant` for Lean types, propositions and proofs.
|
||||
- `erased` for Lean types, propositions and proofs.
|
||||
|
||||
- `object` a pointer to a value in the heap.
|
||||
|
||||
- `tobject` a pointer to a value in the heap or tagged pointer
|
||||
(i.e., the least significant bit is 1) storing a scalar value.
|
||||
- `tagged` a tagged pointer (i.e., the least significant bit is 1) storing a scalar value.
|
||||
|
||||
- `tobject` an `object` or a `tagged` pointer
|
||||
|
||||
- `struct` and `union` are used to return small values (e.g., `Option`, `Prod`, `Except`)
|
||||
on the stack.
|
||||
@@ -80,31 +74,16 @@ then one of the following must hold in each (execution) branch.
|
||||
-/
|
||||
inductive IRType where
|
||||
| float | uint8 | uint16 | uint32 | uint64 | usize
|
||||
| irrelevant | object | tobject
|
||||
| erased | object | tobject
|
||||
| float32
|
||||
| struct (leanTypeName : Option Name) (types : Array IRType) : IRType
|
||||
| union (leanTypeName : Name) (types : Array IRType) : IRType
|
||||
deriving Inhabited, Repr
|
||||
-- TODO: Move this upwards after a stage0 update.
|
||||
| tagged
|
||||
deriving Inhabited, BEq, Repr
|
||||
|
||||
namespace IRType
|
||||
|
||||
partial def beq : IRType → IRType → Bool
|
||||
| float, float => true
|
||||
| float32, float32 => true
|
||||
| uint8, uint8 => true
|
||||
| uint16, uint16 => true
|
||||
| uint32, uint32 => true
|
||||
| uint64, uint64 => true
|
||||
| usize, usize => true
|
||||
| irrelevant, irrelevant => true
|
||||
| object, object => true
|
||||
| tobject, tobject => true
|
||||
| struct n₁ tys₁, struct n₂ tys₂ => n₁ == n₂ && Array.isEqv tys₁ tys₂ beq
|
||||
| union n₁ tys₁, union n₂ tys₂ => n₁ == n₂ && Array.isEqv tys₁ tys₂ beq
|
||||
| _, _ => false
|
||||
|
||||
instance : BEq IRType := ⟨beq⟩
|
||||
|
||||
def isScalar : IRType → Bool
|
||||
| float => true
|
||||
| float32 => true
|
||||
@@ -117,51 +96,47 @@ def isScalar : IRType → Bool
|
||||
|
||||
def isObj : IRType → Bool
|
||||
| object => true
|
||||
| tagged => true
|
||||
| tobject => true
|
||||
| _ => false
|
||||
|
||||
def isIrrelevant : IRType → Bool
|
||||
| irrelevant => true
|
||||
def isPossibleRef : IRType → Bool
|
||||
| object | tobject => true
|
||||
| _ => false
|
||||
|
||||
def isStruct : IRType → Bool
|
||||
| struct _ _ => true
|
||||
def isDefiniteRef : IRType → Bool
|
||||
| object => true
|
||||
| _ => false
|
||||
|
||||
def isUnion : IRType → Bool
|
||||
| union _ _ => true
|
||||
def isErased : IRType → Bool
|
||||
| erased => true
|
||||
| _ => false
|
||||
|
||||
def boxed : IRType → IRType
|
||||
| object | float | float32 => object
|
||||
| tagged | uint8 | uint16 => tagged
|
||||
| _ => tobject
|
||||
|
||||
end IRType
|
||||
|
||||
/-- Arguments to applications, constructors, etc.
|
||||
We use `irrelevant` for Lean types, propositions and proofs that have been erased.
|
||||
We use `erased` for Lean types, propositions and proofs that have been erased.
|
||||
Recall that for a Function `f`, we also generate `f._rarg` which does not take
|
||||
`irrelevant` arguments. However, `f._rarg` is only safe to be used in full applications. -/
|
||||
`erased` arguments. However, `f._rarg` is only safe to be used in full applications. -/
|
||||
inductive Arg where
|
||||
| var (id : VarId)
|
||||
| irrelevant
|
||||
deriving Inhabited
|
||||
| erased
|
||||
deriving Inhabited, BEq, Repr
|
||||
|
||||
protected def Arg.beq : Arg → Arg → Bool
|
||||
| var x, var y => x == y
|
||||
| irrelevant, irrelevant => true
|
||||
| erased, erased => true
|
||||
| _, _ => false
|
||||
|
||||
instance : BEq Arg := ⟨Arg.beq⟩
|
||||
|
||||
@[export lean_ir_mk_var_arg] def mkVarArg (id : VarId) : Arg := Arg.var id
|
||||
|
||||
inductive LitVal where
|
||||
| num (v : Nat)
|
||||
| str (v : String)
|
||||
|
||||
def LitVal.beq : LitVal → LitVal → Bool
|
||||
| num v₁, num v₂ => v₁ == v₂
|
||||
| str v₁, str v₂ => v₁ == v₂
|
||||
| _, _ => false
|
||||
|
||||
instance : BEq LitVal := ⟨LitVal.beq⟩
|
||||
deriving Inhabited, BEq
|
||||
|
||||
/-- Constructor information.
|
||||
|
||||
@@ -180,13 +155,7 @@ structure CtorInfo where
|
||||
size : Nat
|
||||
usize : Nat
|
||||
ssize : Nat
|
||||
deriving Inhabited, Repr
|
||||
|
||||
def CtorInfo.beq : CtorInfo → CtorInfo → Bool
|
||||
| ⟨n₁, cidx₁, size₁, usize₁, ssize₁⟩, ⟨n₂, cidx₂, size₂, usize₂, ssize₂⟩ =>
|
||||
n₁ == n₂ && cidx₁ == cidx₂ && size₁ == size₂ && usize₁ == usize₂ && ssize₁ == ssize₂
|
||||
|
||||
instance : BEq CtorInfo := ⟨CtorInfo.beq⟩
|
||||
deriving Inhabited, BEq, Repr
|
||||
|
||||
def CtorInfo.isRef (info : CtorInfo) : Bool :=
|
||||
info.size > 0 || info.usize > 0 || info.ssize > 0
|
||||
@@ -194,6 +163,9 @@ def CtorInfo.isRef (info : CtorInfo) : Bool :=
|
||||
def CtorInfo.isScalar (info : CtorInfo) : Bool :=
|
||||
!info.isRef
|
||||
|
||||
def CtorInfo.type (info : CtorInfo) : IRType :=
|
||||
if info.isRef then .object else .tagged
|
||||
|
||||
inductive Expr where
|
||||
/-- We use `ctor` mainly for constructing Lean object/tobject values `lean_ctor_object` in the runtime.
|
||||
This instruction is also used to creat `struct` and `union` return values.
|
||||
@@ -225,26 +197,12 @@ inductive Expr where
|
||||
| isShared (x : VarId)
|
||||
deriving Inhabited
|
||||
|
||||
@[export lean_ir_mk_ctor_expr] def mkCtorExpr (n : Name) (cidx : Nat) (size : Nat) (usize : Nat) (ssize : Nat) (ys : Array Arg) : Expr :=
|
||||
Expr.ctor ⟨n, cidx, size, usize, ssize⟩ ys
|
||||
@[export lean_ir_mk_proj_expr] def mkProjExpr (i : Nat) (x : VarId) : Expr := Expr.proj i x
|
||||
@[export lean_ir_mk_uproj_expr] def mkUProjExpr (i : Nat) (x : VarId) : Expr := Expr.uproj i x
|
||||
@[export lean_ir_mk_sproj_expr] def mkSProjExpr (n : Nat) (offset : Nat) (x : VarId) : Expr := Expr.sproj n offset x
|
||||
@[export lean_ir_mk_fapp_expr] def mkFAppExpr (c : FunId) (ys : Array Arg) : Expr := Expr.fap c ys
|
||||
@[export lean_ir_mk_papp_expr] def mkPAppExpr (c : FunId) (ys : Array Arg) : Expr := Expr.pap c ys
|
||||
@[export lean_ir_mk_app_expr] def mkAppExpr (x : VarId) (ys : Array Arg) : Expr := Expr.ap x ys
|
||||
@[export lean_ir_mk_num_expr] def mkNumExpr (v : Nat) : Expr := Expr.lit (LitVal.num v)
|
||||
@[export lean_ir_mk_str_expr] def mkStrExpr (v : String) : Expr := Expr.lit (LitVal.str v)
|
||||
|
||||
structure Param where
|
||||
x : VarId
|
||||
borrow : Bool
|
||||
ty : IRType
|
||||
deriving Inhabited, Repr
|
||||
|
||||
@[export lean_ir_mk_param]
|
||||
def mkParam (x : VarId) (borrow : Bool) (ty : IRType) : Param := ⟨x, borrow, ty⟩
|
||||
|
||||
mutual
|
||||
|
||||
inductive Alt where
|
||||
@@ -263,7 +221,7 @@ inductive FnBody where
|
||||
/-- Store `y : Usize` at Position `sizeof(void*)*i` in `x`. `x` must be a Constructor object and `RC(x)` must be 1. -/
|
||||
| uset (x : VarId) (i : Nat) (y : VarId) (b : FnBody)
|
||||
/-- Store `y : ty` at Position `sizeof(void*)*i + offset` in `x`. `x` must be a Constructor object and `RC(x)` must be 1.
|
||||
`ty` must not be `object`, `tobject`, `irrelevant` nor `Usize`. -/
|
||||
`ty` must not be `object`, `tobject`, `erased` nor `Usize`. -/
|
||||
| sset (x : VarId) (i : Nat) (offset : Nat) (y : VarId) (ty : IRType) (b : FnBody)
|
||||
/-- RC increment for `object`. If c == `true`, then `inc` must check whether `x` is a tagged pointer or not.
|
||||
If `persistent == true` then `x` is statically known to be a persistent object. -/
|
||||
@@ -278,26 +236,14 @@ inductive FnBody where
|
||||
/-- Jump to join point `j` -/
|
||||
| jmp (j : JoinPointId) (ys : Array Arg)
|
||||
| unreachable
|
||||
deriving Inhabited
|
||||
|
||||
end
|
||||
|
||||
instance : Inhabited FnBody := ⟨FnBody.unreachable⟩
|
||||
deriving instance Inhabited for Alt
|
||||
|
||||
abbrev FnBody.nil := FnBody.unreachable
|
||||
|
||||
@[export lean_ir_mk_vdecl] def mkVDecl (x : VarId) (ty : IRType) (e : Expr) (b : FnBody) : FnBody := FnBody.vdecl x ty e b
|
||||
@[export lean_ir_mk_jdecl] def mkJDecl (j : JoinPointId) (xs : Array Param) (v : FnBody) (b : FnBody) : FnBody := FnBody.jdecl j xs v b
|
||||
@[export lean_ir_mk_uset] def mkUSet (x : VarId) (i : Nat) (y : VarId) (b : FnBody) : FnBody := FnBody.uset x i y b
|
||||
@[export lean_ir_mk_sset] def mkSSet (x : VarId) (i : Nat) (offset : Nat) (y : VarId) (ty : IRType) (b : FnBody) : FnBody := FnBody.sset x i offset y ty b
|
||||
@[export lean_ir_mk_case] def mkCase (tid : Name) (x : VarId) (cs : Array Alt) : FnBody :=
|
||||
-- Type field `xType` is set by `explicitBoxing` compiler pass.
|
||||
FnBody.case tid x IRType.object cs
|
||||
@[export lean_ir_mk_ret] def mkRet (x : Arg) : FnBody := FnBody.ret x
|
||||
@[export lean_ir_mk_jmp] def mkJmp (j : JoinPointId) (ys : Array Arg) : FnBody := FnBody.jmp j ys
|
||||
@[export lean_ir_mk_unreachable] def mkUnreachable : Unit → FnBody := fun _ => FnBody.unreachable
|
||||
|
||||
instance : Inhabited Alt := ⟨Alt.default default⟩
|
||||
|
||||
def FnBody.isTerminal : FnBody → Bool
|
||||
| FnBody.case _ _ _ _ => true
|
||||
| FnBody.ret _ => true
|
||||
@@ -353,7 +299,7 @@ def Alt.setBody : Alt → FnBody → Alt
|
||||
| Alt.ctor c b => Alt.ctor c (f b)
|
||||
| Alt.default b => Alt.default (f b)
|
||||
|
||||
@[inline] def Alt.mmodifyBody {m : Type → Type} [Monad m] (f : FnBody → m FnBody) : Alt → m Alt
|
||||
@[inline] def Alt.modifyBodyM {m : Type → Type} [Monad m] (f : FnBody → m FnBody) : Alt → m Alt
|
||||
| Alt.ctor c b => Alt.ctor c <$> f b
|
||||
| Alt.default b => Alt.default <$> f b
|
||||
|
||||
@@ -388,14 +334,11 @@ def reshape (bs : Array FnBody) (term : FnBody) : FnBody :=
|
||||
| FnBody.jdecl j xs v k => FnBody.jdecl j xs (f v) k
|
||||
| other => other
|
||||
|
||||
@[inline] def mmodifyJPs {m : Type → Type} [Monad m] (bs : Array FnBody) (f : FnBody → m FnBody) : m (Array FnBody) :=
|
||||
@[inline] def modifyJPsM {m : Type → Type} [Monad m] (bs : Array FnBody) (f : FnBody → m FnBody) : m (Array FnBody) :=
|
||||
bs.mapM fun b => match b with
|
||||
| FnBody.jdecl j xs v k => return FnBody.jdecl j xs (← f v) k
|
||||
| other => return other
|
||||
|
||||
@[export lean_ir_mk_alt] def mkAlt (n : Name) (cidx : Nat) (size : Nat) (usize : Nat) (ssize : Nat) (b : FnBody) : Alt :=
|
||||
Alt.ctor ⟨n, cidx, size, usize, ssize⟩ b
|
||||
|
||||
/-- Extra information associated with a declaration. -/
|
||||
structure DeclInfo where
|
||||
/-- If `some <blame>`, then declaration depends on `<blame>` which uses a `sorry` axiom. -/
|
||||
@@ -435,29 +378,22 @@ def updateBody! (d : Decl) (bNew : FnBody) : Decl :=
|
||||
|
||||
end Decl
|
||||
|
||||
@[export lean_ir_mk_decl] def mkDecl (f : FunId) (xs : Array Param) (ty : IRType) (b : FnBody) : Decl :=
|
||||
Decl.fdecl f xs ty b {}
|
||||
|
||||
@[export lean_ir_mk_extern_decl] def mkExternDecl (f : FunId) (xs : Array Param) (ty : IRType) (e : ExternAttrData) : Decl :=
|
||||
Decl.extern f xs ty e
|
||||
|
||||
-- Hack: we use this declaration as a stub for declarations annotated with `implemented_by` or `init`
|
||||
@[export lean_ir_mk_dummy_extern_decl] def mkDummyExternDecl (f : FunId) (xs : Array Param) (ty : IRType) : Decl :=
|
||||
def mkDummyExternDecl (f : FunId) (xs : Array Param) (ty : IRType) : Decl :=
|
||||
Decl.fdecl f xs ty FnBody.unreachable {}
|
||||
|
||||
/-- Set of variable and join point names -/
|
||||
abbrev IndexSet := RBTree Index compare
|
||||
instance : Inhabited IndexSet := ⟨{}⟩
|
||||
abbrev IndexSet := Std.TreeSet Index
|
||||
|
||||
def mkIndexSet (idx : Index) : IndexSet :=
|
||||
RBTree.empty.insert idx
|
||||
Std.TreeSet.empty.insert idx
|
||||
|
||||
inductive LocalContextEntry where
|
||||
| param : IRType → LocalContextEntry
|
||||
| localVar : IRType → Expr → LocalContextEntry
|
||||
| joinPoint : Array Param → FnBody → LocalContextEntry
|
||||
|
||||
abbrev LocalContext := RBMap Index LocalContextEntry compare
|
||||
abbrev LocalContext := Std.TreeMap Index LocalContextEntry
|
||||
|
||||
def LocalContext.addLocal (ctx : LocalContext) (x : VarId) (t : IRType) (v : Expr) : LocalContext :=
|
||||
ctx.insert x.idx (LocalContextEntry.localVar t v)
|
||||
@@ -472,48 +408,48 @@ def LocalContext.addParams (ctx : LocalContext) (ps : Array Param) : LocalContex
|
||||
ps.foldl LocalContext.addParam ctx
|
||||
|
||||
def LocalContext.isJP (ctx : LocalContext) (idx : Index) : Bool :=
|
||||
match ctx.find? idx with
|
||||
match ctx.get? idx with
|
||||
| some (LocalContextEntry.joinPoint _ _) => true
|
||||
| _ => false
|
||||
|
||||
def LocalContext.getJPBody (ctx : LocalContext) (j : JoinPointId) : Option FnBody :=
|
||||
match ctx.find? j.idx with
|
||||
match ctx.get? j.idx with
|
||||
| some (LocalContextEntry.joinPoint _ b) => some b
|
||||
| _ => none
|
||||
|
||||
def LocalContext.getJPParams (ctx : LocalContext) (j : JoinPointId) : Option (Array Param) :=
|
||||
match ctx.find? j.idx with
|
||||
match ctx.get? j.idx with
|
||||
| some (LocalContextEntry.joinPoint ys _) => some ys
|
||||
| _ => none
|
||||
|
||||
def LocalContext.isParam (ctx : LocalContext) (idx : Index) : Bool :=
|
||||
match ctx.find? idx with
|
||||
match ctx.get? idx with
|
||||
| some (LocalContextEntry.param _) => true
|
||||
| _ => false
|
||||
|
||||
def LocalContext.isLocalVar (ctx : LocalContext) (idx : Index) : Bool :=
|
||||
match ctx.find? idx with
|
||||
match ctx.get? idx with
|
||||
| some (LocalContextEntry.localVar _ _) => true
|
||||
| _ => false
|
||||
|
||||
def LocalContext.contains (ctx : LocalContext) (idx : Index) : Bool :=
|
||||
RBMap.contains ctx idx
|
||||
Std.TreeMap.contains ctx idx
|
||||
|
||||
def LocalContext.eraseJoinPointDecl (ctx : LocalContext) (j : JoinPointId) : LocalContext :=
|
||||
ctx.erase j.idx
|
||||
|
||||
def LocalContext.getType (ctx : LocalContext) (x : VarId) : Option IRType :=
|
||||
match ctx.find? x.idx with
|
||||
match ctx.get? x.idx with
|
||||
| some (LocalContextEntry.param t) => some t
|
||||
| some (LocalContextEntry.localVar t _) => some t
|
||||
| _ => none
|
||||
|
||||
def LocalContext.getValue (ctx : LocalContext) (x : VarId) : Option Expr :=
|
||||
match ctx.find? x.idx with
|
||||
match ctx.get? x.idx with
|
||||
| some (LocalContextEntry.localVar _ v) => some v
|
||||
| _ => none
|
||||
|
||||
abbrev IndexRenaming := RBMap Index Index compare
|
||||
abbrev IndexRenaming := Std.TreeMap Index Index
|
||||
|
||||
class AlphaEqv (α : Type) where
|
||||
aeqv : IndexRenaming → α → α → Bool
|
||||
@@ -521,7 +457,7 @@ class AlphaEqv (α : Type) where
|
||||
export AlphaEqv (aeqv)
|
||||
|
||||
def VarId.alphaEqv (ρ : IndexRenaming) (v₁ v₂ : VarId) : Bool :=
|
||||
match ρ.find? v₁.idx with
|
||||
match ρ.get? v₁.idx with
|
||||
| some v => v == v₂.idx
|
||||
| none => v₁ == v₂
|
||||
|
||||
@@ -529,7 +465,7 @@ instance : AlphaEqv VarId := ⟨VarId.alphaEqv⟩
|
||||
|
||||
def Arg.alphaEqv (ρ : IndexRenaming) : Arg → Arg → Bool
|
||||
| Arg.var v₁, Arg.var v₂ => aeqv ρ v₁ v₂
|
||||
| Arg.irrelevant, Arg.irrelevant => true
|
||||
| Arg.erased, Arg.erased => true
|
||||
| _, _ => false
|
||||
|
||||
instance : AlphaEqv Arg := ⟨Arg.alphaEqv⟩
|
||||
@@ -555,7 +491,7 @@ def Expr.alphaEqv (ρ : IndexRenaming) : Expr → Expr → Bool
|
||||
| Expr.isShared x₁, Expr.isShared x₂ => aeqv ρ x₁ x₂
|
||||
| _, _ => false
|
||||
|
||||
instance : AlphaEqv Expr:= ⟨Expr.alphaEqv⟩
|
||||
instance : AlphaEqv Expr := ⟨Expr.alphaEqv⟩
|
||||
|
||||
def addVarRename (ρ : IndexRenaming) (x₁ x₂ : Nat) :=
|
||||
if x₁ == x₂ then ρ else ρ.insert x₁ x₂
|
||||
@@ -571,7 +507,7 @@ def addParamsRename (ρ : IndexRenaming) (ps₁ ps₂ : Array Param) : Option In
|
||||
failure
|
||||
else
|
||||
let mut ρ := ρ
|
||||
for i in [:ps₁.size] do
|
||||
for i in *...ps₁.size do
|
||||
ρ ← addParamRename ρ ps₁[i]! ps₂[i]!
|
||||
pure ρ
|
||||
|
||||
@@ -604,8 +540,7 @@ def FnBody.beq (b₁ b₂ : FnBody) : Bool :=
|
||||
|
||||
instance : BEq FnBody := ⟨FnBody.beq⟩
|
||||
|
||||
abbrev VarIdSet := RBTree VarId (fun x y => compare x.idx y.idx)
|
||||
instance : Inhabited VarIdSet := ⟨{}⟩
|
||||
abbrev VarIdSet := Std.TreeSet VarId (fun x y => compare x.idx y.idx)
|
||||
|
||||
def mkIf (x : VarId) (t e : FnBody) : FnBody :=
|
||||
FnBody.case `Bool x IRType.uint8 #[
|
||||
|
||||
@@ -15,14 +15,6 @@ namespace Borrow
|
||||
namespace OwnedSet
|
||||
abbrev Key := FunId × Index
|
||||
|
||||
def beq : Key → Key → Bool
|
||||
| (f₁, x₁), (f₂, x₂) => f₁ == f₂ && x₁ == x₂
|
||||
|
||||
instance : BEq Key := ⟨beq⟩
|
||||
|
||||
def getHash : Key → UInt64
|
||||
| (f, x) => mixHash (hash f) (hash x)
|
||||
instance : Hashable Key := ⟨getHash⟩
|
||||
end OwnedSet
|
||||
|
||||
open OwnedSet (Key) in
|
||||
@@ -36,16 +28,12 @@ def OwnedSet.contains (s : OwnedSet) (k : OwnedSet.Key) : Bool := Std.HashMap.
|
||||
We keep a mapping from function and joint points to parameters (`Array Param`).
|
||||
Recall that `Param` contains the field `borrow`. -/
|
||||
namespace ParamMap
|
||||
|
||||
inductive Key where
|
||||
| decl (name : FunId)
|
||||
| jp (name : FunId) (jpid : JoinPointId)
|
||||
deriving BEq
|
||||
deriving BEq, Hashable
|
||||
|
||||
def getHash : Key → UInt64
|
||||
| Key.decl n => hash n
|
||||
| Key.jp n id => mixHash (hash n) (hash id)
|
||||
|
||||
instance : Hashable Key := ⟨getHash⟩
|
||||
end ParamMap
|
||||
|
||||
open ParamMap (Key)
|
||||
@@ -208,7 +196,7 @@ def ownArgsUsingParams (xs : Array Arg) (ps : Array Param) : M Unit :=
|
||||
xs.size.forM fun i _ => do
|
||||
let x := xs[i]
|
||||
let p := ps[i]!
|
||||
unless p.borrow do ownArg x
|
||||
unless p.borrow || p.ty.isScalar do ownArg x
|
||||
|
||||
/-- For each xs[i], if xs[i] is owned, then mark ps[i] as owned.
|
||||
We use this action to preserve tail calls. That is, if we have
|
||||
@@ -314,5 +302,7 @@ def inferBorrow (decls : Array Decl) : CompilerM (Array Decl) := do
|
||||
let paramMap := Borrow.infer env decls
|
||||
pure (Borrow.applyParamMap decls paramMap)
|
||||
|
||||
builtin_initialize registerTraceClass `compiler.ir.borrow (inherited := true)
|
||||
|
||||
end IR
|
||||
end Lean
|
||||
|
||||
@@ -21,13 +21,8 @@ Recall that the Lean to λ_pure compiler produces code without these instruction
|
||||
|
||||
Assumptions:
|
||||
- This transformation is applied before explicit RC instructions (`inc`, `dec`) are inserted.
|
||||
- This transformation is applied before `FnBody.case` has been simplified and `Alt.default` is used.
|
||||
Reason: if there is no `Alt.default` branch, then we can decide whether `x` at `FnBody.case x alts` is an
|
||||
enumeration type by simply inspecting the `CtorInfo` values at `alts`.
|
||||
- This transformation is applied before lower level optimizations are applied which use
|
||||
`Expr.isShared`, `Expr.isTaggedPtr`, and `FnBody.set`.
|
||||
- This transformation is applied after `reset` and `reuse` instructions have been added.
|
||||
Reason: `resetreuse.lean` ignores `box` and `unbox` instructions.
|
||||
-/
|
||||
|
||||
def mkBoxedName (n : Name) : Name :=
|
||||
@@ -48,7 +43,7 @@ def requiresBoxedVersion (env : Environment) (decl : Decl) : Bool :=
|
||||
|
||||
def mkBoxedVersionAux (decl : Decl) : N Decl := do
|
||||
let ps := decl.params
|
||||
let qs ← ps.mapM fun _ => do let x ← N.mkFresh; pure { x := x, ty := IRType.object, borrow := false : Param }
|
||||
let qs ← ps.mapM fun p => do let x ← N.mkFresh; pure { x, ty := p.ty.boxed, borrow := false }
|
||||
let (newVDecls, xs) ← qs.size.foldM (init := (#[], #[])) fun i _ (newVDecls, xs) => do
|
||||
let p := ps[i]!
|
||||
let q := qs[i]
|
||||
@@ -63,9 +58,9 @@ def mkBoxedVersionAux (decl : Decl) : N Decl := do
|
||||
pure <| reshape newVDecls (FnBody.ret (Arg.var r))
|
||||
else
|
||||
let newR ← N.mkFresh
|
||||
let newVDecls := newVDecls.push (FnBody.vdecl newR IRType.object (Expr.box decl.resultType r) default)
|
||||
let newVDecls := newVDecls.push (FnBody.vdecl newR .tobject (Expr.box decl.resultType r) default)
|
||||
pure <| reshape newVDecls (FnBody.ret (Arg.var newR))
|
||||
return Decl.fdecl (mkBoxedName decl.name) qs IRType.object body decl.getInfo
|
||||
return Decl.fdecl (mkBoxedName decl.name) qs decl.resultType.boxed body decl.getInfo
|
||||
|
||||
def mkBoxedVersion (decl : Decl) : Decl :=
|
||||
(mkBoxedVersionAux decl).run' 1
|
||||
@@ -83,16 +78,16 @@ def getScrutineeType (alts : Array Alt) : IRType :=
|
||||
| Alt.ctor c _ => c.isScalar
|
||||
| Alt.default _ => false
|
||||
match isScalar with
|
||||
| false => IRType.object
|
||||
| false => .tobject
|
||||
| true => irTypeForEnum alts.size
|
||||
|
||||
def eqvTypes (t₁ t₂ : IRType) : Bool :=
|
||||
(t₁.isScalar == t₂.isScalar) && (!t₁.isScalar || t₁ == t₂)
|
||||
|
||||
structure BoxingContext where
|
||||
f : FunId := default
|
||||
f : FunId
|
||||
localCtx : LocalContext := {}
|
||||
resultType : IRType := IRType.irrelevant
|
||||
resultType : IRType
|
||||
decls : Array Decl
|
||||
env : Environment
|
||||
|
||||
@@ -127,7 +122,7 @@ def getVarType (x : VarId) : M IRType := do
|
||||
let localCtx ← getLocalContext
|
||||
match localCtx.getType x with
|
||||
| some t => pure t
|
||||
| none => pure IRType.object -- unreachable, we assume the code is well formed
|
||||
| none => pure .tobject -- unreachable, we assume the code is well formed
|
||||
|
||||
def getJPParams (j : JoinPointId) : M (Array Param) := do
|
||||
let localCtx ← getLocalContext
|
||||
@@ -153,53 +148,54 @@ def getDecl (fid : FunId) : M Decl := do
|
||||
/-- If `x` declaration is of the form `x := Expr.lit _` or `x := Expr.fap c #[]`,
|
||||
and `x`'s type is not cheap to box (e.g., it is `UInt64), then return its value. -/
|
||||
private def isExpensiveConstantValueBoxing (x : VarId) (xType : IRType) : M (Option Expr) :=
|
||||
if !xType.isScalar then
|
||||
return none -- We assume unboxing is always cheap
|
||||
else match xType with
|
||||
| IRType.uint8 => return none
|
||||
| IRType.uint16 => return none
|
||||
| _ => do
|
||||
let localCtx ← getLocalContext
|
||||
match localCtx.getValue x with
|
||||
| some val =>
|
||||
match val with
|
||||
| Expr.lit _ => return some val
|
||||
| Expr.fap _ args => return if args.size == 0 then some val else none
|
||||
| _ => return none
|
||||
match xType with
|
||||
| .uint8 | .uint16 => return none
|
||||
| _ => do
|
||||
let localCtx ← getLocalContext
|
||||
match localCtx.getValue x with
|
||||
| some val =>
|
||||
match val with
|
||||
-- TODO: This should check whether larger literals fit into tagged values.
|
||||
| .lit _ => return some val
|
||||
| .fap _ args => return if args.size == 0 then some val else none
|
||||
| _ => return none
|
||||
| _ => return none
|
||||
|
||||
/-- Auxiliary function used by castVarIfNeeded.
|
||||
It is used when the expected type does not match `xType`.
|
||||
If `xType` is scalar, then we need to "box" it. Otherwise, we need to "unbox" it. -/
|
||||
def mkCast (x : VarId) (xType : IRType) (expectedType : IRType) : M Expr := do
|
||||
match (← isExpensiveConstantValueBoxing x xType) with
|
||||
| some v => do
|
||||
let ctx ← read
|
||||
let s ← get
|
||||
/- Create auxiliary FnBody
|
||||
```
|
||||
let x_1 : xType := v;
|
||||
let x_2 : expectedType := Expr.box xType x_1;
|
||||
ret x_2
|
||||
```
|
||||
-/
|
||||
let body : FnBody :=
|
||||
FnBody.vdecl { idx := 1 } xType v $
|
||||
FnBody.vdecl { idx := 2 } expectedType (Expr.box xType { idx := 1 }) $
|
||||
FnBody.ret (mkVarArg { idx := 2 })
|
||||
match s.auxDeclCache.find? body with
|
||||
| some v => pure v
|
||||
| none => do
|
||||
let auxName := ctx.f ++ ((`_boxed_const).appendIndexAfter s.nextAuxId)
|
||||
let auxConst := Expr.fap auxName #[]
|
||||
let auxDecl := Decl.fdecl auxName #[] expectedType body {}
|
||||
modify fun s => { s with
|
||||
auxDecls := s.auxDecls.push auxDecl
|
||||
auxDeclCache := s.auxDeclCache.cons body auxConst
|
||||
nextAuxId := s.nextAuxId + 1
|
||||
}
|
||||
pure auxConst
|
||||
| none => pure $ if xType.isScalar then Expr.box xType x else Expr.unbox x
|
||||
if expectedType.isScalar then
|
||||
return .unbox x
|
||||
else
|
||||
match (← isExpensiveConstantValueBoxing x xType) with
|
||||
| some v => do
|
||||
let ctx ← read
|
||||
let s ← get
|
||||
/- Create auxiliary FnBody
|
||||
```
|
||||
let x_1 : xType := v;
|
||||
let x_2 : expectedType := Expr.box xType x_1;
|
||||
ret x_2
|
||||
```
|
||||
-/
|
||||
let body : FnBody :=
|
||||
.vdecl { idx := 1 } xType v <|
|
||||
.vdecl { idx := 2 } expectedType (.box xType { idx := 1 }) <|
|
||||
.ret (.var { idx := 2 })
|
||||
match s.auxDeclCache.find? body with
|
||||
| some v => pure v
|
||||
| none => do
|
||||
let auxName := ctx.f ++ ((`_boxed_const).appendIndexAfter s.nextAuxId)
|
||||
let auxConst := Expr.fap auxName #[]
|
||||
let auxDecl := Decl.fdecl auxName #[] expectedType body {}
|
||||
modify fun s => { s with
|
||||
auxDecls := s.auxDecls.push auxDecl
|
||||
auxDeclCache := s.auxDeclCache.cons body auxConst
|
||||
nextAuxId := s.nextAuxId + 1
|
||||
}
|
||||
pure auxConst
|
||||
| none => return .box xType x
|
||||
|
||||
@[inline] def castVarIfNeeded (x : VarId) (expected : IRType) (k : VarId → M FnBody) : M FnBody := do
|
||||
let xType ← getVarType x
|
||||
@@ -212,8 +208,8 @@ def mkCast (x : VarId) (xType : IRType) (expectedType : IRType) : M Expr := do
|
||||
|
||||
@[inline] def castArgIfNeeded (x : Arg) (expected : IRType) (k : Arg → M FnBody) : M FnBody :=
|
||||
match x with
|
||||
| Arg.var x => castVarIfNeeded x expected (fun x => k (Arg.var x))
|
||||
| _ => k x
|
||||
| .var x => castVarIfNeeded x expected (fun x => k (.var x))
|
||||
| .erased => k x
|
||||
|
||||
def castArgsIfNeededAux (xs : Array Arg) (typeFromIdx : Nat → IRType) : M (Array Arg × Array FnBody) := do
|
||||
let mut xs' := #[]
|
||||
@@ -222,7 +218,7 @@ def castArgsIfNeededAux (xs : Array Arg) (typeFromIdx : Nat → IRType) : M (Arr
|
||||
for x in xs do
|
||||
let expected := typeFromIdx i
|
||||
match x with
|
||||
| Arg.irrelevant =>
|
||||
| Arg.erased =>
|
||||
xs' := xs'.push x
|
||||
| Arg.var x =>
|
||||
let xType ← getVarType x
|
||||
@@ -243,14 +239,14 @@ def castArgsIfNeededAux (xs : Array Arg) (typeFromIdx : Nat → IRType) : M (Arr
|
||||
pure (reshape bs b)
|
||||
|
||||
@[inline] def boxArgsIfNeeded (xs : Array Arg) (k : Array Arg → M FnBody) : M FnBody := do
|
||||
let (ys, bs) ← castArgsIfNeededAux xs (fun _ => IRType.object)
|
||||
let (ys, bs) ← castArgsIfNeededAux xs (fun _ => .tobject)
|
||||
let b ← k ys
|
||||
pure (reshape bs b)
|
||||
|
||||
def unboxResultIfNeeded (x : VarId) (ty : IRType) (e : Expr) (b : FnBody) : M FnBody := do
|
||||
if ty.isScalar then
|
||||
let y ← M.mkFresh
|
||||
return FnBody.vdecl y IRType.object e (FnBody.vdecl x ty (Expr.unbox y) b)
|
||||
return FnBody.vdecl y .tobject e (FnBody.vdecl x ty (Expr.unbox y) b)
|
||||
else
|
||||
return FnBody.vdecl x ty e b
|
||||
|
||||
@@ -306,7 +302,7 @@ partial def visitFnBody : FnBody → M FnBody
|
||||
FnBody.mdata d <$> visitFnBody b
|
||||
| FnBody.case tid x _ alts => do
|
||||
let expected := getScrutineeType alts
|
||||
let alts ← alts.mapM fun alt => alt.mmodifyBody visitFnBody
|
||||
let alts ← alts.mapM fun alt => alt.modifyBodyM visitFnBody
|
||||
castVarIfNeeded x expected fun x => do
|
||||
return FnBody.case tid x expected alts
|
||||
| FnBody.ret x => do
|
||||
@@ -319,12 +315,11 @@ partial def visitFnBody : FnBody → M FnBody
|
||||
pure other
|
||||
|
||||
def run (env : Environment) (decls : Array Decl) : Array Decl :=
|
||||
let ctx : BoxingContext := { decls := decls, env := env }
|
||||
let decls := decls.foldl (init := #[]) fun newDecls decl =>
|
||||
match decl with
|
||||
| .fdecl (f := f) (xs := xs) (type := t) (body := b) .. =>
|
||||
| .fdecl f xs resultType b _ =>
|
||||
let nextIdx := decl.maxIndex + 1
|
||||
let (b, s) := (withParams xs (visitFnBody b) { ctx with f := f, resultType := t }).run { nextIdx := nextIdx }
|
||||
let (b, s) := withParams xs (visitFnBody b) { f, resultType, decls, env } |>.run { nextIdx }
|
||||
let newDecls := newDecls ++ s.auxDecls
|
||||
let newDecl := decl.updateBody! b
|
||||
let newDecl := newDecl.elimDead
|
||||
@@ -338,4 +333,6 @@ def explicitBoxing (decls : Array Decl) : CompilerM (Array Decl) := do
|
||||
let env ← getEnv
|
||||
return ExplicitBoxing.run env decls
|
||||
|
||||
builtin_initialize registerTraceClass `compiler.ir.boxing (inherited := true)
|
||||
|
||||
end Lean.IR
|
||||
|
||||
@@ -26,19 +26,23 @@ opaque getUSizeSize : Unit → Nat
|
||||
def usizeSize := getUSizeSize ()
|
||||
|
||||
structure CheckerContext where
|
||||
env : Environment
|
||||
localCtx : LocalContext := {}
|
||||
currentDecl : Decl
|
||||
decls : Array Decl
|
||||
|
||||
structure CheckerState where
|
||||
foundVars : IndexSet := {}
|
||||
|
||||
abbrev M := ReaderT CheckerContext (ExceptT String (StateT CheckerState Id))
|
||||
abbrev M := ReaderT CheckerContext <| StateRefT CheckerState CompilerM
|
||||
|
||||
def throwCheckerError {α : Type} (msg : String) : M α := do
|
||||
let declName := (← read).currentDecl.name
|
||||
throwError s!"failed to compile definition, compiler IR check failed at '{declName}'. Error: {msg}"
|
||||
|
||||
def markIndex (i : Index) : M Unit := do
|
||||
let s ← get
|
||||
if s.foundVars.contains i then
|
||||
throw s!"variable / joinpoint index {i} has already been used"
|
||||
throwCheckerError s!"variable / joinpoint index {i} has already been used"
|
||||
modify fun s => { s with foundVars := s.foundVars.insert i }
|
||||
|
||||
def markVar (x : VarId) : M Unit :=
|
||||
@@ -49,38 +53,38 @@ def markJP (j : JoinPointId) : M Unit :=
|
||||
|
||||
def getDecl (c : Name) : M Decl := do
|
||||
let ctx ← read
|
||||
match findEnvDecl' ctx.env c ctx.decls with
|
||||
| none => throw s!"depends on declaration '{c}', which has no executable code; consider marking definition as 'noncomputable'"
|
||||
match findEnvDecl' (← getEnv) c ctx.decls with
|
||||
| none => throwCheckerError s!"depends on declaration '{c}', which has no executable code; consider marking definition as 'noncomputable'"
|
||||
| some d => pure d
|
||||
|
||||
def checkVar (x : VarId) : M Unit := do
|
||||
let ctx ← read
|
||||
unless ctx.localCtx.isLocalVar x.idx || ctx.localCtx.isParam x.idx do
|
||||
throw s!"unknown variable '{x}'"
|
||||
throwCheckerError s!"unknown variable '{x}'"
|
||||
|
||||
def checkJP (j : JoinPointId) : M Unit := do
|
||||
let ctx ← read
|
||||
unless ctx.localCtx.isJP j.idx do
|
||||
throw s!"unknown join point '{j}'"
|
||||
throwCheckerError s!"unknown join point '{j}'"
|
||||
|
||||
def checkArg (a : Arg) : M Unit :=
|
||||
match a with
|
||||
| Arg.var x => checkVar x
|
||||
| _ => pure ()
|
||||
| .var x => checkVar x
|
||||
| .erased => pure ()
|
||||
|
||||
def checkArgs (as : Array Arg) : M Unit :=
|
||||
as.forM checkArg
|
||||
|
||||
@[inline] def checkEqTypes (ty₁ ty₂ : IRType) : M Unit := do
|
||||
unless ty₁ == ty₂ do
|
||||
throw "unexpected type '{ty₁}' != '{ty₂}'"
|
||||
throwCheckerError "unexpected type '{ty₁}' != '{ty₂}'"
|
||||
|
||||
@[inline] def checkType (ty : IRType) (p : IRType → Bool) (suffix? : Option String := none): M Unit := do
|
||||
unless p ty do
|
||||
let mut msg := s!"unexpected type '{ty}'"
|
||||
if let some suffix := suffix? then
|
||||
msg := s!"{msg}, {suffix}"
|
||||
throw msg
|
||||
throwCheckerError msg
|
||||
|
||||
def checkObjType (ty : IRType) : M Unit := checkType ty IRType.isObj "object expected"
|
||||
|
||||
@@ -90,7 +94,7 @@ def getType (x : VarId) : M IRType := do
|
||||
let ctx ← read
|
||||
match ctx.localCtx.getType x with
|
||||
| some ty => pure ty
|
||||
| none => throw s!"unknown variable '{x}'"
|
||||
| none => throwCheckerError s!"unknown variable '{x}'"
|
||||
|
||||
@[inline] def checkVarType (x : VarId) (p : IRType → Bool) (suffix? : Option String := none) : M Unit := do
|
||||
let ty ← getType x; checkType ty p suffix?
|
||||
@@ -104,56 +108,85 @@ def checkScalarVar (x : VarId) : M Unit :=
|
||||
def checkFullApp (c : FunId) (ys : Array Arg) : M Unit := do
|
||||
let decl ← getDecl c
|
||||
unless ys.size == decl.params.size do
|
||||
throw s!"incorrect number of arguments to '{c}', {ys.size} provided, {decl.params.size} expected"
|
||||
throwCheckerError s!"incorrect number of arguments to '{c}', {ys.size} provided, {decl.params.size} expected"
|
||||
checkArgs ys
|
||||
|
||||
def checkPartialApp (c : FunId) (ys : Array Arg) : M Unit := do
|
||||
let decl ← getDecl c
|
||||
unless ys.size < decl.params.size do
|
||||
throw s!"too many arguments to partial application '{c}', num. args: {ys.size}, arity: {decl.params.size}"
|
||||
throwCheckerError s!"too many arguments to partial application '{c}', num. args: {ys.size}, arity: {decl.params.size}"
|
||||
checkArgs ys
|
||||
|
||||
def checkExpr (ty : IRType) : Expr → M Unit
|
||||
-- Partial applications should always produce a closure object.
|
||||
| Expr.pap f ys => checkPartialApp f ys *> checkObjType ty
|
||||
-- Applications of closures should always produce a boxed value.
|
||||
| Expr.ap x ys => checkObjVar x *> checkArgs ys *> checkObjType ty
|
||||
| Expr.fap f ys => checkFullApp f ys
|
||||
| Expr.ctor c ys => do
|
||||
if c.cidx > maxCtorTag && (c.size > 0 || c.usize > 0 || c.ssize > 0) then
|
||||
throw s!"tag for constructor '{c.name}' is too big, this is a limitation of the current runtime"
|
||||
def checkExpr (ty : IRType) (e : Expr) : M Unit := do
|
||||
match e with
|
||||
| .pap f ys =>
|
||||
checkPartialApp f ys
|
||||
-- Partial applications should always produce a closure object.
|
||||
checkObjType ty
|
||||
| .ap x ys =>
|
||||
checkObjVar x
|
||||
checkArgs ys
|
||||
-- Applications of closures should always produce a boxed value.
|
||||
checkObjType ty
|
||||
| .fap f ys =>
|
||||
checkFullApp f ys
|
||||
| .ctor c ys =>
|
||||
if c.cidx > maxCtorTag && c.isRef then
|
||||
throwCheckerError s!"tag for constructor '{c.name}' is too big, this is a limitation of the current runtime"
|
||||
if c.size > maxCtorFields then
|
||||
throw s!"constructor '{c.name}' has too many fields"
|
||||
throwCheckerError s!"constructor '{c.name}' has too many fields"
|
||||
if c.ssize + c.usize * usizeSize > maxCtorScalarsSize then
|
||||
throw s!"constructor '{c.name}' has too many scalar fields"
|
||||
if !ty.isStruct && !ty.isUnion && c.isRef then
|
||||
(checkObjType ty) *> checkArgs ys
|
||||
| Expr.reset _ x => checkObjVar x *> checkObjType ty
|
||||
| Expr.reuse x _ _ ys => checkObjVar x *> checkArgs ys *> checkObjType ty
|
||||
| Expr.box xty x => checkObjType ty *> checkScalarVar x *> checkVarType x (fun t => t == xty)
|
||||
| Expr.unbox x => checkScalarType ty *> checkObjVar x
|
||||
| Expr.proj i x => do
|
||||
throwCheckerError s!"constructor '{c.name}' has too many scalar fields"
|
||||
if c.isRef then
|
||||
checkObjType ty
|
||||
checkArgs ys
|
||||
| .reset _ x =>
|
||||
checkObjVar x
|
||||
checkObjType ty
|
||||
| .reuse x _ _ ys =>
|
||||
checkObjVar x
|
||||
checkArgs ys
|
||||
checkObjType ty
|
||||
| .box xty x =>
|
||||
checkObjType ty
|
||||
checkScalarVar x
|
||||
checkVarType x (· == xty)
|
||||
| .unbox x =>
|
||||
checkScalarType ty
|
||||
checkObjVar x
|
||||
| .proj i x =>
|
||||
let xType ← getType x;
|
||||
match xType with
|
||||
| IRType.object => checkObjType ty
|
||||
| IRType.tobject => checkObjType ty
|
||||
| IRType.struct _ tys => if h : i < tys.size then checkEqTypes (tys[i]) ty else throw "invalid proj index"
|
||||
| IRType.union _ tys => if h : i < tys.size then checkEqTypes (tys[i]) ty else throw "invalid proj index"
|
||||
| _ => throw s!"unexpected IR type '{xType}'"
|
||||
| Expr.uproj _ x => checkObjVar x *> checkType ty (fun t => t == IRType.usize)
|
||||
| Expr.sproj _ _ x => checkObjVar x *> checkScalarType ty
|
||||
| Expr.isShared x => checkObjVar x *> checkType ty (fun t => t == IRType.uint8)
|
||||
| Expr.lit (LitVal.str _) => checkObjType ty
|
||||
| Expr.lit _ => pure ()
|
||||
| .object | .tobject =>
|
||||
checkObjType ty
|
||||
| .struct _ tys | .union _ tys =>
|
||||
if h : i < tys.size then
|
||||
checkEqTypes (tys[i]) ty
|
||||
else
|
||||
throwCheckerError "invalid proj index"
|
||||
| _ => throwCheckerError s!"unexpected IR type '{xType}'"
|
||||
| .uproj _ x =>
|
||||
checkObjVar x
|
||||
checkType ty (· == .usize)
|
||||
| .sproj _ _ x =>
|
||||
checkObjVar x
|
||||
checkScalarType ty
|
||||
| .isShared x =>
|
||||
checkObjVar x
|
||||
checkType ty (· == .uint8)
|
||||
| .lit (LitVal.str _) =>
|
||||
checkObjType ty
|
||||
| .lit _ => pure ()
|
||||
|
||||
@[inline] def withParams (ps : Array Param) (k : M Unit) : M Unit := do
|
||||
let ctx ← read
|
||||
let localCtx ← ps.foldlM (init := ctx.localCtx) fun (ctx : LocalContext) p => do
|
||||
markVar p.x
|
||||
pure $ ctx.addParam p
|
||||
withReader (fun _ => { ctx with localCtx := localCtx }) k
|
||||
pure <| ctx.addParam p
|
||||
withReader (fun _ => { ctx with localCtx }) k
|
||||
|
||||
partial def checkFnBody : FnBody → M Unit
|
||||
partial def checkFnBody (fnBody : FnBody) : M Unit := do
|
||||
match fnBody with
|
||||
| .vdecl x t v b => do
|
||||
checkExpr t v
|
||||
markVar x
|
||||
@@ -162,18 +195,41 @@ partial def checkFnBody : FnBody → M Unit
|
||||
markJP j
|
||||
withParams ys (checkFnBody v)
|
||||
withReader (fun ctx => { ctx with localCtx := ctx.localCtx.addJP j ys v }) (checkFnBody b)
|
||||
| .set x _ y b => checkVar x *> checkArg y *> checkFnBody b
|
||||
| .uset x _ y b => checkVar x *> checkVar y *> checkFnBody b
|
||||
| .sset x _ _ y _ b => checkVar x *> checkVar y *> checkFnBody b
|
||||
| .setTag x _ b => checkVar x *> checkFnBody b
|
||||
| .inc x _ _ _ b => checkVar x *> checkFnBody b
|
||||
| .dec x _ _ _ b => checkVar x *> checkFnBody b
|
||||
| .del x b => checkVar x *> checkFnBody b
|
||||
| .mdata _ b => checkFnBody b
|
||||
| .jmp j ys => checkJP j *> checkArgs ys
|
||||
| .ret x => checkArg x
|
||||
| .case _ x _ alts => checkVar x *> alts.forM (fun alt => checkFnBody alt.body)
|
||||
| .unreachable => pure ()
|
||||
| .set x _ y b =>
|
||||
checkVar x
|
||||
checkArg y
|
||||
checkFnBody b
|
||||
| .uset x _ y b =>
|
||||
checkVar x
|
||||
checkVar y
|
||||
checkFnBody b
|
||||
| .sset x _ _ y _ b =>
|
||||
checkVar x
|
||||
checkVar y
|
||||
checkFnBody b
|
||||
| .setTag x _ b =>
|
||||
checkVar x
|
||||
checkFnBody b
|
||||
| .inc x _ _ _ b =>
|
||||
checkVar x
|
||||
checkFnBody b
|
||||
| .dec x _ _ _ b =>
|
||||
checkVar x
|
||||
checkFnBody b
|
||||
| .del x b =>
|
||||
checkVar x
|
||||
checkFnBody b
|
||||
| .mdata _ b =>
|
||||
checkFnBody b
|
||||
| .jmp j ys =>
|
||||
checkJP j
|
||||
checkArgs ys
|
||||
| .ret x =>
|
||||
checkArg x
|
||||
| .case _ x _ alts =>
|
||||
checkVar x
|
||||
alts.forM (checkFnBody ·.body)
|
||||
| .unreachable => pure ()
|
||||
|
||||
def checkDecl : Decl → M Unit
|
||||
| .fdecl (xs := xs) (body := b) .. => withParams xs (checkFnBody b)
|
||||
@@ -182,10 +238,7 @@ def checkDecl : Decl → M Unit
|
||||
end Checker
|
||||
|
||||
def checkDecl (decls : Array Decl) (decl : Decl) : CompilerM Unit := do
|
||||
let env ← getEnv
|
||||
match (Checker.checkDecl decl { env := env, decls := decls }).run' {} with
|
||||
| .error msg => throw s!"failed to compile definition, compiler IR check failed at '{decl.name}'. Error: {msg}"
|
||||
| _ => pure ()
|
||||
Checker.checkDecl decl { decls, currentDecl := decl } |>.run' {}
|
||||
|
||||
def checkDecls (decls : Array Decl) : CompilerM Unit :=
|
||||
decls.forM (checkDecl decls)
|
||||
|
||||
@@ -4,11 +4,13 @@ Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Leonardo de Moura
|
||||
-/
|
||||
prelude
|
||||
import Lean.CoreM
|
||||
import Lean.Environment
|
||||
import Lean.Compiler.IR.Basic
|
||||
import Lean.Compiler.IR.Format
|
||||
import Lean.Compiler.MetaAttr
|
||||
import Lean.Compiler.ExportAttr
|
||||
import Lean.Compiler.LCNF.PhaseExt
|
||||
|
||||
namespace Lean.IR
|
||||
|
||||
@@ -30,18 +32,13 @@ def Log.format (log : Log) : Format :=
|
||||
log.foldl (init := Format.nil) fun fmt entry =>
|
||||
f!"{fmt}{Format.line}{entry}"
|
||||
|
||||
@[export lean_ir_log_to_string]
|
||||
def Log.toString (log : Log) : String :=
|
||||
log.format.pretty
|
||||
|
||||
structure CompilerState where
|
||||
env : Environment
|
||||
log : Log := #[]
|
||||
|
||||
abbrev CompilerM := ReaderT Options (EStateM String CompilerState)
|
||||
abbrev CompilerM := CoreM
|
||||
|
||||
def log (entry : LogEntry) : CompilerM Unit :=
|
||||
modify fun s => { s with log := s.log.push entry }
|
||||
addTrace `Compiler.IR m!"{entry}"
|
||||
|
||||
def tracePrefixOptionName := `trace.compiler.ir
|
||||
|
||||
@@ -51,16 +48,14 @@ private def isLogEnabledFor (opts : Options) (optName : Name) : Bool :=
|
||||
| _ => opts.getBool tracePrefixOptionName
|
||||
|
||||
private def logDeclsAux (optName : Name) (cls : Name) (decls : Array Decl) : CompilerM Unit := do
|
||||
let opts ← read
|
||||
if isLogEnabledFor opts optName then
|
||||
if isLogEnabledFor (← getOptions) optName then
|
||||
log (LogEntry.step cls decls)
|
||||
|
||||
@[inline] def logDecls (cls : Name) (decl : Array Decl) : CompilerM Unit :=
|
||||
logDeclsAux (tracePrefixOptionName ++ cls) cls decl
|
||||
|
||||
private def logMessageIfAux {α : Type} [ToFormat α] (optName : Name) (a : α) : CompilerM Unit := do
|
||||
let opts ← read
|
||||
if isLogEnabledFor opts optName then
|
||||
if isLogEnabledFor (← getOptions) optName then
|
||||
log (LogEntry.message (format a))
|
||||
|
||||
@[inline] def logMessageIf {α : Type} [ToFormat α] (cls : Name) (a : α) : CompilerM Unit :=
|
||||
@@ -69,9 +64,6 @@ private def logMessageIfAux {α : Type} [ToFormat α] (optName : Name) (a : α)
|
||||
@[inline] def logMessage {α : Type} [ToFormat α] (a : α) : CompilerM Unit :=
|
||||
logMessageIfAux tracePrefixOptionName a
|
||||
|
||||
@[inline] def modifyEnv (f : Environment → Environment) : CompilerM Unit :=
|
||||
modify fun s => { s with env := f s.env }
|
||||
|
||||
abbrev DeclMap := PHashMap Name Decl
|
||||
|
||||
private abbrev declLt (a b : Decl) :=
|
||||
@@ -84,46 +76,39 @@ private abbrev findAtSorted? (decls : Array Decl) (declName : Name) : Option Dec
|
||||
let tmpDecl := Decl.extern declName #[] default default
|
||||
decls.binSearch tmpDecl declLt
|
||||
|
||||
namespace CollectUsedFDecls
|
||||
/-- Meta status of local declarations, not persisted. -/
|
||||
private builtin_initialize declMetaExt : EnvExtension (List Name × NameSet) ←
|
||||
registerEnvExtension
|
||||
(mkInitial := pure ([], {}))
|
||||
(asyncMode := .sync)
|
||||
(replay? := some <| fun oldState newState _ s =>
|
||||
let newEntries := newState.1.take (newState.1.length - oldState.1.length)
|
||||
newEntries.foldl (init := s) fun s n =>
|
||||
if s.1.contains n then
|
||||
s
|
||||
else
|
||||
(n :: s.1, s.2.insert n))
|
||||
|
||||
abbrev M := StateM NameSet
|
||||
/-- Whether a declaration should be exported for interpretation. -/
|
||||
def isDeclMeta (env : Environment) (declName : Name) : Bool :=
|
||||
if !env.header.isModule then
|
||||
true
|
||||
else
|
||||
-- The interpreter may call the boxed variant even if the IR does not directly reference it, so
|
||||
-- use same visibility as base decl.
|
||||
-- Note that boxed decls are created after the `inferVisibility` pass.
|
||||
let inferFor := match declName with
|
||||
| .str n "_boxed" => n
|
||||
| n => n
|
||||
declMetaExt.getState env |>.2.contains inferFor
|
||||
|
||||
@[inline] def collect (f : FunId) : M Unit :=
|
||||
modify fun s => s.insert f
|
||||
|
||||
partial def collectFnBody : FnBody → M Unit
|
||||
| .vdecl _ _ v b =>
|
||||
match v with
|
||||
| .fap f _ => collect f *> collectFnBody b
|
||||
| .pap f _ => collect f *> collectFnBody b
|
||||
| _ => collectFnBody b
|
||||
| .jdecl _ _ v b => collectFnBody v *> collectFnBody b
|
||||
| .case _ _ _ alts => alts.forM fun alt => collectFnBody alt.body
|
||||
| e => unless e.isTerminal do collectFnBody e.body
|
||||
|
||||
def collectDecl : Decl → M NameSet
|
||||
| .fdecl (body := b) .. => collectFnBody b *> get
|
||||
| .extern .. => get
|
||||
|
||||
end CollectUsedFDecls
|
||||
|
||||
/-- Adds to `used` all `Decl.fdecl`s referenced directly by `decl`. -/
|
||||
def collectUsedFDecls (decl : Decl) (used : NameSet := {}) : NameSet :=
|
||||
(CollectUsedFDecls.collectDecl decl).run' used
|
||||
|
||||
/-- Computes the closure of `Decl.fdecl`s referenced by `decl`. -/
|
||||
def getFDeclClosure (m : DeclMap) (decls : Array Decl) : NameSet := Id.run do
|
||||
let mut toVisit := decls.map (·.name) |>.toList
|
||||
let mut res : NameSet := .ofList toVisit
|
||||
while !toVisit.isEmpty do
|
||||
let n :: toVisit' := toVisit | continue
|
||||
toVisit := toVisit'
|
||||
let some d := m.find? n | continue
|
||||
for d' in collectUsedFDecls d do
|
||||
if !res.contains d' then
|
||||
res := res.insert d'
|
||||
toVisit := d' :: toVisit
|
||||
return res
|
||||
/-- Marks a declaration to be exported for interpretation. -/
|
||||
def setDeclMeta (env : Environment) (declName : Name) : Environment :=
|
||||
if isDeclMeta env declName then
|
||||
env
|
||||
else
|
||||
declMetaExt.modifyState env fun s =>
|
||||
(declName :: s.1, s.2.insert declName)
|
||||
|
||||
builtin_initialize declMapExt : SimplePersistentEnvExtension Decl DeclMap ←
|
||||
registerSimplePersistentEnvExtension {
|
||||
@@ -131,25 +116,23 @@ builtin_initialize declMapExt : SimplePersistentEnvExtension Decl DeclMap ←
|
||||
addEntryFn := fun s d => s.insert d.name d
|
||||
-- Store `meta` closure only in `.olean`, turn all other decls into opaque externs.
|
||||
-- Leave storing the remainder for `meta import` and server `#eval` to `exportIREntries` below.
|
||||
exportEntriesFnEx? := some fun env s entries level =>
|
||||
exportEntriesFnEx? := some fun env s entries _ =>
|
||||
let decls := entries.foldl (init := #[]) fun decls decl => decls.push decl
|
||||
let entries := sortDecls decls
|
||||
let metaClosure := getFDeclClosure s (decls.filter (isMeta env ·.name))
|
||||
-- Do not save all IR even in .olean.private as it will be in .ir anyway
|
||||
if env.header.isModule then
|
||||
entries.map fun
|
||||
| d@(.fdecl f xs ty b info) =>
|
||||
-- The interpreter may call the boxed variant even if the IR does not directly reference
|
||||
-- it.
|
||||
let n := match f with
|
||||
| .str n "_boxed" => n
|
||||
| n => n
|
||||
if metaClosure.contains n then
|
||||
d
|
||||
else if let some (.str _ s) := getExportNameFor? env n then
|
||||
.extern f xs ty { arity? := xs.size, entries := [.standard `all s] }
|
||||
entries.filterMap fun d => do
|
||||
if isDeclMeta env d.name then
|
||||
return d
|
||||
guard <| Compiler.LCNF.isDeclPublic env d.name
|
||||
-- Bodies of imported IR decls are not relevant for codegen, only interpretation
|
||||
match d with
|
||||
| .fdecl f xs ty b info =>
|
||||
if let some (.str _ s) := getExportNameFor? env f then
|
||||
return .extern f xs ty { arity? := xs.size, entries := [.standard `all s] }
|
||||
else
|
||||
.extern f xs ty { arity? := xs.size, entries := [.opaque f] }
|
||||
| d => d
|
||||
return .extern f xs ty { arity? := xs.size, entries := [.opaque f] }
|
||||
| d => some d
|
||||
else entries
|
||||
-- Written to on codegen environment branch but accessed from other elaboration branches when
|
||||
-- calling into the interpreter. We cannot use `async` as the IR declarations added may not
|
||||
@@ -166,47 +149,37 @@ private def exportIREntries (env : Environment) : Array (Name × Array EnvExtens
|
||||
let entries : Array EnvExtensionEntry := unsafe unsafeCast <| sortDecls decls
|
||||
#[(``declMapExt, entries)]
|
||||
|
||||
/-- Retrieves IR for codegen purposes, i.e. independent of `meta import`. -/
|
||||
@[export lean_ir_find_env_decl]
|
||||
def findEnvDecl (env : Environment) (declName : Name) : Option Decl :=
|
||||
match env.getModuleIdxFor? declName with
|
||||
| some modIdx => findAtSorted? (declMapExt.getModuleEntries env modIdx) declName
|
||||
| none => declMapExt.getState env |>.find? declName
|
||||
|
||||
@[export lean_ir_find_env_decl]
|
||||
private def findInterpreterDecl (env : Environment) (declName : Name) : Option Decl :=
|
||||
match env.getModuleIdxFor? declName with
|
||||
| some modIdx => do
|
||||
let decl ←
|
||||
-- `meta import` and server `#eval`
|
||||
findAtSorted? (declMapExt.getModuleIREntries env modIdx) declName <|>
|
||||
-- (closure of) `meta def`; will report `.extern`s for other `def`s so needs to come second
|
||||
findAtSorted? (declMapExt.getModuleEntries env modIdx) declName
|
||||
guard !decl matches .extern _ _ _ { entries := [.opaque _], .. }
|
||||
return decl
|
||||
| some modIdx =>
|
||||
-- `meta import/import all` and server `#eval`
|
||||
-- This case is important even for codegen because it needs to see IR via `import all` (beause
|
||||
-- it can also see the LCNF)
|
||||
findAtSorted? (declMapExt.getModuleIREntries env modIdx) declName <|>
|
||||
-- (closure of) `meta def`; will report `.extern`s for other `def`s so needs to come second
|
||||
findAtSorted? (declMapExt.getModuleEntries env modIdx) declName
|
||||
| none => declMapExt.getState env |>.find? declName
|
||||
|
||||
def findDecl (n : Name) : CompilerM (Option Decl) :=
|
||||
return findEnvDecl (← get).env n
|
||||
return findEnvDecl (← getEnv) n
|
||||
|
||||
def containsDecl (n : Name) : CompilerM Bool :=
|
||||
return (← findDecl n).isSome
|
||||
|
||||
def getDecl (n : Name) : CompilerM Decl := do
|
||||
let (some decl) ← findDecl n | throw s!"unknown declaration '{n}'"
|
||||
let (some decl) ← findDecl n | throwError s!"unknown declaration '{n}'"
|
||||
return decl
|
||||
|
||||
@[export lean_ir_add_decl]
|
||||
def addDeclAux (env : Environment) (decl : Decl) : Environment :=
|
||||
declMapExt.addEntry (env.addExtraName decl.name) decl
|
||||
def findLocalDecl (n : Name) : CompilerM (Option Decl) :=
|
||||
return declMapExt.getState (← getEnv) |>.find? n
|
||||
|
||||
/-- Returns the list of IR declarations in declaration order. -/
|
||||
def getDecls (env : Environment) : List Decl :=
|
||||
declMapExt.getEntries env
|
||||
|
||||
def getEnv : CompilerM Environment := do
|
||||
let s ← get; pure s.env
|
||||
|
||||
def addDecl (decl : Decl) : CompilerM Unit :=
|
||||
modifyEnv fun env => declMapExt.addEntry (env.addExtraName decl.name) decl
|
||||
def addDecl (decl : Decl) : CompilerM Unit := do
|
||||
modifyEnv (declMapExt.addEntry · decl)
|
||||
|
||||
def addDecls (decls : Array Decl) : CompilerM Unit :=
|
||||
decls.forM addDecl
|
||||
@@ -217,7 +190,7 @@ def findEnvDecl' (env : Environment) (n : Name) (decls : Array Decl) : Option De
|
||||
| none => findEnvDecl env n
|
||||
|
||||
def findDecl' (n : Name) (decls : Array Decl) : CompilerM (Option Decl) :=
|
||||
return findEnvDecl' (← get).env n decls
|
||||
return findEnvDecl' (← getEnv) n decls
|
||||
|
||||
def containsDecl' (n : Name) (decls : Array Decl) : CompilerM Bool := do
|
||||
if decls.any fun decl => decl.name == n then
|
||||
@@ -226,7 +199,7 @@ def containsDecl' (n : Name) (decls : Array Decl) : CompilerM Bool := do
|
||||
containsDecl n
|
||||
|
||||
def getDecl' (n : Name) (decls : Array Decl) : CompilerM Decl := do
|
||||
let (some decl) ← findDecl' n decls | throw s!"unknown declaration '{n}'"
|
||||
let (some decl) ← findDecl' n decls | throwError s!"unknown declaration '{n}'"
|
||||
return decl
|
||||
|
||||
@[export lean_decl_get_sorry_dep]
|
||||
@@ -235,5 +208,12 @@ def getSorryDep (env : Environment) (declName : Name) : Option Name :=
|
||||
| some (.fdecl (info := { sorryDep? := dep?, .. }) ..) => dep?
|
||||
| _ => none
|
||||
|
||||
/-- Returns additional names that compiler env exts may want to call `getModuleIdxFor?` on. -/
|
||||
@[export lean_get_ir_extra_const_names]
|
||||
private def getIRExtraConstNames (env : Environment) (level : OLeanLevel) : Array Name :=
|
||||
declMapExt.getEntries env |>.toArray.map (·.name)
|
||||
|>.filter fun n => !env.contains n &&
|
||||
(level == .private || Compiler.LCNF.isDeclPublic env n || isDeclMeta env n)
|
||||
|
||||
end IR
|
||||
end Lean
|
||||
|
||||
@@ -16,7 +16,7 @@ inductive Value where
|
||||
| top -- any value
|
||||
| ctor (i : CtorInfo) (vs : Array Value)
|
||||
| choice (vs : List Value)
|
||||
deriving Inhabited, Repr
|
||||
deriving Inhabited, BEq, Repr
|
||||
|
||||
protected partial def Value.toFormat : Value → Format
|
||||
| Value.bot => "⊥"
|
||||
@@ -37,18 +37,6 @@ instance : ToString Value where
|
||||
|
||||
namespace Value
|
||||
|
||||
protected partial def beq : Value → Value → Bool
|
||||
| bot, bot => true
|
||||
| top, top => true
|
||||
| ctor i₁ vs₁, ctor i₂ vs₂ => i₁ == i₂ && Array.isEqv vs₁ vs₂ Value.beq
|
||||
| choice vs₁, choice vs₂ =>
|
||||
vs₁.all (fun v₁ => vs₂.any fun v₂ => Value.beq v₁ v₂)
|
||||
&&
|
||||
vs₂.all (fun v₂ => vs₁.any fun v₁ => Value.beq v₁ v₂)
|
||||
| _, _ => false
|
||||
|
||||
instance : BEq Value := ⟨Value.beq⟩
|
||||
|
||||
partial def addChoice (merge : Value → Value → Value) : List Value → Value → List Value
|
||||
| [], v => [v]
|
||||
| v₁@(ctor i₁ _) :: cs, v₂@(ctor i₂ _) =>
|
||||
@@ -132,13 +120,15 @@ builtin_initialize functionSummariesExt : SimplePersistentEnvExtension (FunId ×
|
||||
registerSimplePersistentEnvExtension {
|
||||
addImportedFn := fun _ => {}
|
||||
addEntryFn := fun s ⟨e, n⟩ => s.insert e n
|
||||
toArrayFn := fun s => sortEntries s.toArray
|
||||
exportEntriesFnEx? := some fun env s _ _ =>
|
||||
let entries := sortEntries s.toArray
|
||||
entries.filter (Compiler.LCNF.isDeclPublic env ·.1)
|
||||
asyncMode := .sync -- compilation is non-parallel anyway
|
||||
replay? := some <| SimplePersistentEnvExtension.replayOfFilter (!·.contains ·.1) (fun s ⟨e, n⟩ => s.insert e n)
|
||||
}
|
||||
|
||||
def addFunctionSummary (env : Environment) (fid : FunId) (v : Value) : Environment :=
|
||||
functionSummariesExt.addEntry (env.addExtraName fid) (fid, v)
|
||||
functionSummariesExt.addEntry env (fid, v)
|
||||
|
||||
def getFunctionSummary? (env : Environment) (fid : FunId) : Option Value :=
|
||||
match env.getModuleIdxFor? fid with
|
||||
@@ -170,8 +160,8 @@ def findVarValue (x : VarId) : M Value := do
|
||||
|
||||
def findArgValue (arg : Arg) : M Value :=
|
||||
match arg with
|
||||
| Arg.var x => findVarValue x
|
||||
| _ => pure top
|
||||
| .var x => findVarValue x
|
||||
| .erased => pure top
|
||||
|
||||
def updateVarAssignment (x : VarId) (v : Value) : M Unit := do
|
||||
let v' ← findVarValue x
|
||||
@@ -332,8 +322,7 @@ end UnreachableBranches
|
||||
open UnreachableBranches
|
||||
|
||||
def elimDeadBranches (decls : Array Decl) : CompilerM (Array Decl) := do
|
||||
let s ← get
|
||||
let env := s.env
|
||||
let env ← getEnv
|
||||
let assignments : Array Assignment := decls.map fun _ => {}
|
||||
let funVals := mkPArray decls.size Value.bot
|
||||
let visitedJps := decls.map fun _ => {}
|
||||
@@ -342,10 +331,11 @@ def elimDeadBranches (decls : Array Decl) : CompilerM (Array Decl) := do
|
||||
let (_, s) := (inferMain ctx).run s
|
||||
let funVals := s.funVals
|
||||
let assignments := s.assignments
|
||||
modify fun s =>
|
||||
let env := decls.size.fold (init := s.env) fun i _ env =>
|
||||
modifyEnv fun env =>
|
||||
decls.size.fold (init := env) fun i _ env =>
|
||||
addFunctionSummary env decls[i].name funVals[i]!
|
||||
{ s with env := env }
|
||||
return decls.mapIdx fun i decl => elimDead assignments[i]! decl
|
||||
|
||||
builtin_initialize registerTraceClass `compiler.ir.elim_dead_branches (inherited := true)
|
||||
|
||||
end Lean.IR
|
||||
|
||||
@@ -45,4 +45,6 @@ def Decl.elimDead (d : Decl) : Decl :=
|
||||
| .fdecl (body := b) .. => d.updateBody! b.elimDead
|
||||
| other => other
|
||||
|
||||
builtin_initialize registerTraceClass `compiler.ir.elim_dead (inherited := true)
|
||||
|
||||
end Lean.IR
|
||||
|
||||
@@ -47,8 +47,8 @@ def emitLns {α : Type} [ToString α] (as : List α) : M Unit :=
|
||||
|
||||
def argToCString (x : Arg) : String :=
|
||||
match x with
|
||||
| Arg.var x => toString x
|
||||
| _ => "lean_box(0)"
|
||||
| .var x => toString x
|
||||
| .erased => "lean_box(0)"
|
||||
|
||||
def emitArg (x : Arg) : M Unit :=
|
||||
emit (argToCString x)
|
||||
@@ -62,8 +62,9 @@ def toCType : IRType → String
|
||||
| IRType.uint64 => "uint64_t"
|
||||
| IRType.usize => "size_t"
|
||||
| IRType.object => "lean_object*"
|
||||
| IRType.tagged => "lean_object*"
|
||||
| IRType.tobject => "lean_object*"
|
||||
| IRType.irrelevant => "lean_object*"
|
||||
| IRType.erased => "lean_object*"
|
||||
| IRType.struct _ _ => panic! "not implemented yet"
|
||||
| IRType.union _ _ => panic! "not implemented yet"
|
||||
|
||||
@@ -96,16 +97,18 @@ def emitFnDeclAux (decl : Decl) (cppBaseName : String) (isExternal : Bool) : M U
|
||||
let ps := decl.params
|
||||
let env ← getEnv
|
||||
if ps.isEmpty then
|
||||
if isClosedTermName env decl.name then emit "static "
|
||||
else if isExternal then emit "extern "
|
||||
if isExternal then emit "extern "
|
||||
-- The first half is a pre-module system approximation, we keep it around for the benefit of
|
||||
-- unported code.
|
||||
else if isClosedTermName env decl.name || !Compiler.LCNF.isDeclPublic env decl.name then emit "static "
|
||||
else emit "LEAN_EXPORT "
|
||||
else
|
||||
if !isExternal then emit "LEAN_EXPORT "
|
||||
emit (toCType decl.resultType ++ " " ++ cppBaseName)
|
||||
unless ps.isEmpty do
|
||||
emit "("
|
||||
-- We omit irrelevant parameters for extern constants
|
||||
let ps := if isExternC env decl.name then ps.filter (fun p => !p.ty.isIrrelevant) else ps
|
||||
-- We omit erased parameters for extern constants
|
||||
let ps := if isExternC env decl.name then ps.filter (fun p => !p.ty.isErased) else ps
|
||||
if ps.size > closureMaxArgs && isBoxedName decl.name then
|
||||
emit "lean_object**"
|
||||
else
|
||||
@@ -405,10 +408,10 @@ def toStringArgs (ys : Array Arg) : List String :=
|
||||
|
||||
def emitSimpleExternalCall (f : String) (ps : Array Param) (ys : Array Arg) : M Unit := do
|
||||
emit f; emit "("
|
||||
-- We must remove irrelevant arguments to extern calls.
|
||||
-- We must remove erased arguments to extern calls.
|
||||
discard <| ys.size.foldM
|
||||
(fun i _ (first : Bool) =>
|
||||
if ps[i]!.ty.isIrrelevant then
|
||||
if ps[i]!.ty.isErased then
|
||||
pure first
|
||||
else do
|
||||
unless first do emit ", "
|
||||
@@ -540,8 +543,8 @@ def isTailCall (x : VarId) (v : Expr) (b : FnBody) : M Bool := do
|
||||
|
||||
def paramEqArg (p : Param) (x : Arg) : Bool :=
|
||||
match x with
|
||||
| Arg.var x => p.x == x
|
||||
| _ => false
|
||||
| .var x => p.x == x
|
||||
| .erased => false
|
||||
|
||||
/--
|
||||
Given `[p_0, ..., p_{n-1}]`, `[y_0, ..., y_{n-1}]`, representing the assignments
|
||||
|
||||
@@ -322,8 +322,9 @@ def toLLVMType (t : IRType) : M llvmctx (LLVM.LLVMType llvmctx) := do
|
||||
-- TODO: how to cleanly size_t in LLVM? We can do eg. instantiate the current target and query for size.
|
||||
| IRType.usize => LLVM.size_tType llvmctx
|
||||
| IRType.object => do LLVM.pointerType (← LLVM.i8Type llvmctx)
|
||||
| IRType.tagged => do LLVM.pointerType (← LLVM.i8Type llvmctx)
|
||||
| IRType.tobject => do LLVM.pointerType (← LLVM.i8Type llvmctx)
|
||||
| IRType.irrelevant => do LLVM.pointerType (← LLVM.i8Type llvmctx)
|
||||
| IRType.erased => do LLVM.pointerType (← LLVM.i8Type llvmctx)
|
||||
| IRType.struct _ _ => panic! "not implemented yet"
|
||||
| IRType.union _ _ => panic! "not implemented yet"
|
||||
|
||||
@@ -485,8 +486,8 @@ def emitFnDeclAux (mod : LLVM.Module llvmctx)
|
||||
let retty ← (toLLVMType decl.resultType)
|
||||
let mut argtys := #[]
|
||||
for p in ps do
|
||||
-- if it is extern, then we must not add irrelevant args
|
||||
if !(isExternC env decl.name) || !p.ty.isIrrelevant then
|
||||
-- if it is extern, then we must not add erased args
|
||||
if !(isExternC env decl.name) || !p.ty.isErased then
|
||||
argtys := argtys.push (← toLLVMType p.ty)
|
||||
-- TODO (bollu): simplify this API, this code of `closureMaxArgs` is duplicated in multiple places.
|
||||
if argtys.size > closureMaxArgs && isBoxedName decl.name then
|
||||
@@ -548,11 +549,11 @@ def emitLhsSlotStore (builder : LLVM.Builder llvmctx)
|
||||
def emitArgSlot_ (builder : LLVM.Builder llvmctx)
|
||||
(x : Arg) : M llvmctx (LLVM.LLVMType llvmctx × LLVM.Value llvmctx) := do
|
||||
match x with
|
||||
| Arg.var x => emitLhsSlot_ x
|
||||
| _ => do
|
||||
| .var x => emitLhsSlot_ x
|
||||
| .erased => do
|
||||
let slotty ← LLVM.voidPtrType llvmctx
|
||||
let slot ← buildPrologueAlloca builder slotty "irrelevant_slot"
|
||||
let v ← callLeanBox builder (← constIntSizeT 0) "irrelevant_val"
|
||||
let slot ← buildPrologueAlloca builder slotty "erased_slot"
|
||||
let v ← callLeanBox builder (← constIntSizeT 0) "erased_val"
|
||||
let _ ← LLVM.buildStore builder v slot
|
||||
return (slotty, slot)
|
||||
|
||||
@@ -645,7 +646,7 @@ def emitSimpleExternalCall (builder : LLVM.Builder llvmctx)
|
||||
let mut args := #[]
|
||||
let mut argTys := #[]
|
||||
for (p, y) in ps.zip ys do
|
||||
if !p.ty.isIrrelevant then
|
||||
if !p.ty.isErased then
|
||||
let (_yty, yv) ← emitArgVal builder y ""
|
||||
argTys := argTys.push (← toLLVMType p.ty)
|
||||
args := args.push yv
|
||||
@@ -1176,7 +1177,7 @@ def emitFnArgs (builder : LLVM.Builder llvmctx)
|
||||
(needsPackedArgs? : Bool) (llvmfn : LLVM.Value llvmctx) (params : Array Param) : M llvmctx Unit := do
|
||||
if needsPackedArgs? then do
|
||||
let argsp ← LLVM.getParam llvmfn 0 -- lean_object **args
|
||||
for h : i in [:params.size] do
|
||||
for h : i in *...params.size do
|
||||
let param := params[i]
|
||||
-- argsi := (args + i)
|
||||
let argsi ← LLVM.buildGEP2 builder (← LLVM.voidPtrType llvmctx) argsp #[← constIntUnsigned i] s!"packed_arg_{i}_slot"
|
||||
@@ -1189,7 +1190,7 @@ def emitFnArgs (builder : LLVM.Builder llvmctx)
|
||||
addVartoState param.x alloca llvmty
|
||||
else
|
||||
let n ← LLVM.countParams llvmfn
|
||||
for i in [:n.toNat] do
|
||||
for i in *...n.toNat do
|
||||
let param := params[i]!
|
||||
let llvmty ← toLLVMType param.ty
|
||||
let alloca ← buildPrologueAlloca builder llvmty s!"arg_{i}"
|
||||
|
||||
@@ -139,7 +139,7 @@ def releaseUnreadFields (y : VarId) (mask : Mask) (b : FnBody) : M FnBody :=
|
||||
| some _ => pure b -- code took ownership of this field
|
||||
| none => do
|
||||
let fld ← mkFresh
|
||||
pure (FnBody.vdecl fld IRType.object (Expr.proj i y) (FnBody.dec fld 1 true false b))
|
||||
pure (FnBody.vdecl fld .tobject (Expr.proj i y) (FnBody.dec fld 1 true false b))
|
||||
|
||||
def setFields (y : VarId) (zs : Array Arg) (b : FnBody) : FnBody :=
|
||||
zs.size.fold (init := b) fun i _ b => FnBody.set y i zs[i] b
|
||||
@@ -147,11 +147,11 @@ def setFields (y : VarId) (zs : Array Arg) (b : FnBody) : FnBody :=
|
||||
/-- Given `set x[i] := y`, return true iff `y := proj[i] x` -/
|
||||
def isSelfSet (ctx : Context) (x : VarId) (i : Nat) (y : Arg) : Bool :=
|
||||
match y with
|
||||
| Arg.var y =>
|
||||
| .var y =>
|
||||
match ctx.projMap[y]? with
|
||||
| some (Expr.proj j w) => j == i && w == x
|
||||
| _ => false
|
||||
| _ => false
|
||||
| .erased => false
|
||||
|
||||
/-- Given `uset x[i] := y`, return true iff `y := uproj[i] x` -/
|
||||
def isSelfUSet (ctx : Context) (x : VarId) (i : Nat) (y : VarId) : Bool :=
|
||||
@@ -257,7 +257,7 @@ partial def searchAndExpand : FnBody → Array FnBody → M FnBody
|
||||
let v ← searchAndExpand v #[]
|
||||
searchAndExpand b (push bs (FnBody.jdecl j xs v FnBody.nil))
|
||||
| FnBody.case tid x xType alts, bs => do
|
||||
let alts ← alts.mapM fun alt => alt.mmodifyBody fun b => searchAndExpand b #[]
|
||||
let alts ← alts.mapM fun alt => alt.modifyBodyM fun b => searchAndExpand b #[]
|
||||
return reshape bs (FnBody.case tid x xType alts)
|
||||
| b, bs =>
|
||||
if b.isTerminal then return reshape bs b
|
||||
@@ -278,4 +278,6 @@ end ExpandResetReuse
|
||||
def Decl.expandResetReuse (d : Decl) : Decl :=
|
||||
(ExpandResetReuse.main d).normalizeIds
|
||||
|
||||
builtin_initialize registerTraceClass `compiler.ir.expand_reset_reuse (inherited := true)
|
||||
|
||||
end Lean.IR
|
||||
|
||||
@@ -10,8 +10,8 @@ namespace Lean
|
||||
namespace IR
|
||||
|
||||
private def formatArg : Arg → Format
|
||||
| Arg.var id => format id
|
||||
| Arg.irrelevant => "◾"
|
||||
| Arg.var id => format id
|
||||
| Arg.erased => "◾"
|
||||
|
||||
instance : ToFormat Arg := ⟨formatArg⟩
|
||||
|
||||
@@ -61,8 +61,9 @@ private partial def formatIRType : IRType → Format
|
||||
| IRType.uint32 => "u32"
|
||||
| IRType.uint64 => "u64"
|
||||
| IRType.usize => "usize"
|
||||
| IRType.irrelevant => "◾"
|
||||
| IRType.erased => "◾"
|
||||
| IRType.object => "obj"
|
||||
| IRType.tagged => "tagged"
|
||||
| IRType.tobject => "tobj"
|
||||
| IRType.struct _ tys =>
|
||||
let _ : ToFormat IRType := ⟨formatIRType⟩
|
||||
@@ -134,7 +135,6 @@ def formatDecl (decl : Decl) (indent : Nat := 2) : Format :=
|
||||
|
||||
instance : ToFormat Decl := ⟨formatDecl⟩
|
||||
|
||||
@[export lean_ir_decl_to_string]
|
||||
def declToString (d : Decl) : String :=
|
||||
(format d).pretty
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ instance : AndThen Collector where
|
||||
andThen a b := seq a (b ())
|
||||
|
||||
private def collectArg : Arg → Collector
|
||||
| Arg.var x => collectVar x
|
||||
| _ => skip
|
||||
| .var x => collectVar x
|
||||
| .erased => skip
|
||||
|
||||
private def collectArray {α : Type} (as : Array α) (f : α → Collector) : Collector :=
|
||||
fun m => as.foldl (fun m a => f a m) m
|
||||
@@ -124,8 +124,8 @@ instance : AndThen Collector where
|
||||
andThen a b := seq a (b ())
|
||||
|
||||
private def collectArg : Arg → Collector
|
||||
| Arg.var x => collectVar x
|
||||
| _ => skip
|
||||
| .var x => collectVar x
|
||||
| .erased => skip
|
||||
|
||||
private def collectArray {α : Type} (as : Array α) (f : α → Collector) : Collector :=
|
||||
fun bv fv => as.foldl (fun fv a => f a bv fv) fv
|
||||
@@ -184,8 +184,8 @@ def visitVar (w : Index) (x : VarId) : Bool := w == x.idx
|
||||
def visitJP (w : Index) (x : JoinPointId) : Bool := w == x.idx
|
||||
|
||||
def visitArg (w : Index) : Arg → Bool
|
||||
| Arg.var x => visitVar w x
|
||||
| _ => false
|
||||
| .var x => visitVar w x
|
||||
| .erased => false
|
||||
|
||||
def visitArgs (w : Index) (xs : Array Arg) : Bool :=
|
||||
xs.any (visitArg w)
|
||||
|
||||
@@ -80,13 +80,10 @@ def FnBody.hasLiveVar (b : FnBody) (ctx : LocalContext) (x : VarId) : Bool :=
|
||||
(IsLive.visitFnBody x.idx b).run' ctx
|
||||
|
||||
abbrev LiveVarSet := VarIdSet
|
||||
abbrev JPLiveVarMap := RBMap JoinPointId LiveVarSet (fun j₁ j₂ => compare j₁.idx j₂.idx)
|
||||
|
||||
instance : Inhabited LiveVarSet where
|
||||
default := {}
|
||||
abbrev JPLiveVarMap := Std.TreeMap JoinPointId LiveVarSet (fun j₁ j₂ => compare j₁.idx j₂.idx)
|
||||
|
||||
def mkLiveVarSet (x : VarId) : LiveVarSet :=
|
||||
RBTree.empty.insert x
|
||||
Std.TreeSet.empty.insert x
|
||||
|
||||
namespace LiveVars
|
||||
|
||||
@@ -96,8 +93,8 @@ abbrev Collector := LiveVarSet → LiveVarSet
|
||||
@[inline] private def collectVar (x : VarId) : Collector := fun s => s.insert x
|
||||
|
||||
private def collectArg : Arg → Collector
|
||||
| Arg.var x => collectVar x
|
||||
| _ => skip
|
||||
| .var x => collectVar x
|
||||
| .erased => skip
|
||||
|
||||
private def collectArray {α : Type} (as : Array α) (f : α → Collector) : Collector := fun s =>
|
||||
as.foldl (fun s a => f a s) s
|
||||
@@ -106,10 +103,10 @@ private def collectArgs (as : Array Arg) : Collector :=
|
||||
collectArray as collectArg
|
||||
|
||||
private def accumulate (s' : LiveVarSet) : Collector :=
|
||||
fun s => s'.fold (fun s x => s.insert x) s
|
||||
fun s => s'.foldl (fun s x => s.insert x) s
|
||||
|
||||
private def collectJP (m : JPLiveVarMap) (j : JoinPointId) : Collector :=
|
||||
match m.find? j with
|
||||
match m.get? j with
|
||||
| some xs => accumulate xs
|
||||
| none => skip -- unreachable for well-formed code
|
||||
|
||||
|
||||
49
src/Lean/Compiler/IR/Meta.lean
Normal file
49
src/Lean/Compiler/IR/Meta.lean
Normal file
@@ -0,0 +1,49 @@
|
||||
/-
|
||||
Copyright (c) 2025 Lean FRO. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Sebastian Ullrich
|
||||
-/
|
||||
prelude
|
||||
import Lean.Compiler.IR.CompilerM
|
||||
import Lean.Compiler.MetaAttr
|
||||
|
||||
namespace Lean.IR
|
||||
|
||||
private partial def collectUsedFDecls (decl : IR.Decl) : NameSet :=
|
||||
collectDecl decl |>.run {} |>.2
|
||||
where
|
||||
collectDecl : Decl → StateM NameSet Unit
|
||||
| .fdecl (body := b) .. => collectFnBody b
|
||||
| .extern .. => pure ()
|
||||
collectFnBody : FnBody → StateM NameSet Unit
|
||||
| .vdecl _ _ v b =>
|
||||
match v with
|
||||
| .fap f _ => collect f *> collectFnBody b
|
||||
| .pap f _ => collect f *> collectFnBody b
|
||||
| _ => collectFnBody b
|
||||
| .jdecl _ _ v b => collectFnBody v *> collectFnBody b
|
||||
| .case _ _ _ alts => alts.forM fun alt => collectFnBody alt.body
|
||||
| e => unless e.isTerminal do collectFnBody e.body
|
||||
collect (f : FunId) : StateM NameSet Unit :=
|
||||
modify (·.insert f)
|
||||
|
||||
private partial def setClosureMeta (decl : Decl) : CompilerM Unit := do
|
||||
for ref in collectUsedFDecls decl do
|
||||
if isDeclMeta (← getEnv) ref then
|
||||
continue
|
||||
let some d ← findLocalDecl ref | continue
|
||||
trace[compiler.ir.inferMeta] m!"Marking {ref} as meta because it is in `meta` closure"
|
||||
modifyEnv (setDeclMeta · ref)
|
||||
setClosureMeta d
|
||||
|
||||
partial def inferMeta (decls : Array Decl) : CompilerM Unit := do
|
||||
if !(← getEnv).header.isModule then
|
||||
return
|
||||
for decl in decls do
|
||||
if metaExt.isTagged (← getEnv) decl.name then
|
||||
trace[compiler.ir.inferMeta] m!"Marking {decl.name} as meta because it is tagged with `meta`"
|
||||
modifyEnv (setDeclMeta · decl.name)
|
||||
setClosureMeta decl
|
||||
|
||||
builtin_initialize
|
||||
registerTraceClass `compiler.ir.inferMeta
|
||||
@@ -39,7 +39,7 @@ namespace NormalizeIds
|
||||
abbrev M := ReaderT IndexRenaming Id
|
||||
|
||||
def normIndex (x : Index) : M Index := fun m =>
|
||||
match m.find? x with
|
||||
match m.get? x with
|
||||
| some y => y
|
||||
| none => x
|
||||
|
||||
@@ -50,8 +50,8 @@ def normJP (x : JoinPointId) : M JoinPointId :=
|
||||
JoinPointId.mk <$> normIndex x.idx
|
||||
|
||||
def normArg : Arg → M Arg
|
||||
| Arg.var x => Arg.var <$> normVar x
|
||||
| other => pure other
|
||||
| .var x => .var <$> normVar x
|
||||
| .erased => pure .erased
|
||||
|
||||
def normArgs (as : Array Arg) : M (Array Arg) := fun m =>
|
||||
as.map fun a => normArg a m
|
||||
@@ -106,7 +106,7 @@ partial def normFnBody : FnBody → N FnBody
|
||||
| FnBody.mdata d b => return FnBody.mdata d (← normFnBody b)
|
||||
| FnBody.case tid x xType alts => do
|
||||
let x ← normVar x
|
||||
let alts ← alts.mapM fun alt => alt.mmodifyBody normFnBody
|
||||
let alts ← alts.mapM fun alt => alt.modifyBodyM normFnBody
|
||||
return FnBody.case tid x xType alts
|
||||
| FnBody.jmp j ys => return FnBody.jmp (← normJP j) (← normArgs ys)
|
||||
| FnBody.ret x => return FnBody.ret (← normArg x)
|
||||
@@ -128,8 +128,8 @@ def Decl.normalizeIds (d : Decl) : Decl :=
|
||||
namespace MapVars
|
||||
|
||||
@[inline] def mapArg (f : VarId → VarId) : Arg → Arg
|
||||
| Arg.var x => Arg.var (f x)
|
||||
| a => a
|
||||
| .var x => .var (f x)
|
||||
| .erased => .erased
|
||||
|
||||
def mapArgs (f : VarId → VarId) (as : Array Arg) : Array Arg :=
|
||||
as.map (mapArg f)
|
||||
|
||||
@@ -54,4 +54,6 @@ def Decl.pushProj (d : Decl) : Decl :=
|
||||
| .fdecl (body := b) .. => d.updateBody! b.pushProj |>.normalizeIds
|
||||
| other => other
|
||||
|
||||
builtin_initialize registerTraceClass `compiler.ir.push_proj (inherited := true)
|
||||
|
||||
end Lean.IR
|
||||
|
||||
@@ -16,12 +16,12 @@ that introduce the instructions `release` and `set`
|
||||
-/
|
||||
|
||||
structure VarInfo where
|
||||
ref : Bool -- true if the variable may be a reference (aka pointer) at runtime
|
||||
type : IRType
|
||||
persistent : Bool -- true if the variable is statically known to be marked a Persistent at runtime
|
||||
consume : Bool -- true if the variable RC must be "consumed"
|
||||
deriving Inhabited
|
||||
|
||||
abbrev VarMap := RBMap VarId VarInfo (fun x y => compare x.idx y.idx)
|
||||
abbrev VarMap := Std.TreeMap VarId VarInfo (fun x y => compare x.idx y.idx)
|
||||
|
||||
structure Context where
|
||||
env : Environment
|
||||
@@ -36,7 +36,7 @@ def getDecl (ctx : Context) (fid : FunId) : Decl :=
|
||||
| none => unreachable!
|
||||
|
||||
def getVarInfo (ctx : Context) (x : VarId) : VarInfo :=
|
||||
match ctx.varMap.find? x with
|
||||
match ctx.varMap.get? x with
|
||||
| some info => info
|
||||
| none => unreachable!
|
||||
|
||||
@@ -46,34 +46,31 @@ def getJPParams (ctx : Context) (j : JoinPointId) : Array Param :=
|
||||
| none => unreachable!
|
||||
|
||||
def getJPLiveVars (ctx : Context) (j : JoinPointId) : LiveVarSet :=
|
||||
match ctx.jpLiveVarMap.find? j with
|
||||
match ctx.jpLiveVarMap.get? j with
|
||||
| some s => s
|
||||
| none => {}
|
||||
|
||||
def mustConsume (ctx : Context) (x : VarId) : Bool :=
|
||||
let info := getVarInfo ctx x
|
||||
info.ref && info.consume
|
||||
info.type.isPossibleRef && info.consume
|
||||
|
||||
@[inline] def addInc (ctx : Context) (x : VarId) (b : FnBody) (n := 1) : FnBody :=
|
||||
let info := getVarInfo ctx x
|
||||
if n == 0 then b else FnBody.inc x n true info.persistent b
|
||||
if n == 0 then b else .inc x n (!info.type.isDefiniteRef) info.persistent b
|
||||
|
||||
@[inline] def addDec (ctx : Context) (x : VarId) (b : FnBody) : FnBody :=
|
||||
let info := getVarInfo ctx x
|
||||
FnBody.dec x 1 true info.persistent b
|
||||
.dec x 1 (!info.type.isDefiniteRef) info.persistent b
|
||||
|
||||
private def updateRefUsingCtorInfo (ctx : Context) (x : VarId) (c : CtorInfo) : Context :=
|
||||
if c.isRef then
|
||||
ctx
|
||||
else
|
||||
let m := ctx.varMap
|
||||
{ ctx with
|
||||
varMap := match m.find? x with
|
||||
| some info => m.insert x { info with ref := false } -- I really want a Lenses library + notation
|
||||
| none => m }
|
||||
let m := ctx.varMap
|
||||
{ ctx with
|
||||
varMap := match m.get? x with
|
||||
| some info => m.insert x { info with type := c.type }
|
||||
| none => m }
|
||||
|
||||
private def addDecForAlt (ctx : Context) (caseLiveVars altLiveVars : LiveVarSet) (b : FnBody) : FnBody :=
|
||||
caseLiveVars.fold (init := b) fun b x =>
|
||||
caseLiveVars.foldl (init := b) fun b x =>
|
||||
if !altLiveVars.contains x && mustConsume ctx x then addDec ctx x b else b
|
||||
|
||||
/-- `isFirstOcc xs x i = true` if `xs[i]` is the first occurrence of `xs[i]` in `xs` -/
|
||||
@@ -87,8 +84,8 @@ private def isBorrowParamAux (x : VarId) (ys : Array Arg) (consumeParamPred : Na
|
||||
ys.size.any fun i _ =>
|
||||
let y := ys[i]
|
||||
match y with
|
||||
| Arg.irrelevant => false
|
||||
| Arg.var y => x == y && !consumeParamPred i
|
||||
| Arg.erased => false
|
||||
| Arg.var y => x == y && !consumeParamPred i
|
||||
|
||||
private def isBorrowParam (x : VarId) (ys : Array Arg) (ps : Array Param) : Bool :=
|
||||
isBorrowParamAux x ys fun i => ! ps[i]!.borrow
|
||||
@@ -102,17 +99,17 @@ private def getNumConsumptions (x : VarId) (ys : Array Arg) (consumeParamPred :
|
||||
ys.size.fold (init := 0) fun i _ n =>
|
||||
let y := ys[i]
|
||||
match y with
|
||||
| Arg.irrelevant => n
|
||||
| Arg.var y => if x == y && consumeParamPred i then n+1 else n
|
||||
| Arg.erased => n
|
||||
| Arg.var y => if x == y && consumeParamPred i then n+1 else n
|
||||
|
||||
private def addIncBeforeAux (ctx : Context) (xs : Array Arg) (consumeParamPred : Nat → Bool) (b : FnBody) (liveVarsAfter : LiveVarSet) : FnBody :=
|
||||
xs.size.fold (init := b) fun i _ b =>
|
||||
let x := xs[i]
|
||||
match x with
|
||||
| Arg.irrelevant => b
|
||||
| Arg.erased => b
|
||||
| Arg.var x =>
|
||||
let info := getVarInfo ctx x
|
||||
if !info.ref || !isFirstOcc xs i then b
|
||||
if !info.type.isPossibleRef || !isFirstOcc xs i then b
|
||||
else
|
||||
let numConsuptions := getNumConsumptions x xs consumeParamPred -- number of times the argument is
|
||||
let numIncs :=
|
||||
@@ -130,8 +127,8 @@ private def addIncBefore (ctx : Context) (xs : Array Arg) (ps : Array Param) (b
|
||||
private def addDecAfterFullApp (ctx : Context) (xs : Array Arg) (ps : Array Param) (b : FnBody) (bLiveVars : LiveVarSet) : FnBody :=
|
||||
xs.size.fold (init := b) fun i _ b =>
|
||||
match xs[i] with
|
||||
| Arg.irrelevant => b
|
||||
| Arg.var x =>
|
||||
| Arg.erased => b
|
||||
| Arg.var x =>
|
||||
/- We must add a `dec` if `x` must be consumed, it is alive after the application,
|
||||
and it has been borrowed by the application.
|
||||
Remark: `x` may occur multiple times in the application (e.g., `f x y x`).
|
||||
@@ -155,23 +152,28 @@ private def isPersistent : Expr → Bool
|
||||
|
||||
/-- We do not need to consume the projection of a variable that is not consumed -/
|
||||
private def consumeExpr (m : VarMap) : Expr → Bool
|
||||
| Expr.proj _ x => match m.find? x with
|
||||
| Expr.proj _ x => match m.get? x with
|
||||
| some info => info.consume
|
||||
| none => true
|
||||
| _ => true
|
||||
|
||||
/-- Return true iff `v` at runtime is a scalar value stored in a tagged pointer.
|
||||
We do not need RC operations for this kind of value. -/
|
||||
private def isScalarBoxedInTaggedPtr (v : Expr) : Bool :=
|
||||
private def typeForScalarBoxedInTaggedPtr? (v : Expr) : Option IRType :=
|
||||
match v with
|
||||
| Expr.ctor c _ => c.size == 0 && c.ssize == 0 && c.usize == 0
|
||||
| Expr.lit (LitVal.num n) => n ≤ maxSmallNat
|
||||
| _ => false
|
||||
| .ctor c _ =>
|
||||
some c.type
|
||||
| .lit (.num n) =>
|
||||
if n ≤ maxSmallNat then
|
||||
some .tagged
|
||||
else
|
||||
some .tobject
|
||||
| _ => none
|
||||
|
||||
private def updateVarInfo (ctx : Context) (x : VarId) (t : IRType) (v : Expr) : Context :=
|
||||
{ ctx with
|
||||
varMap := ctx.varMap.insert x {
|
||||
ref := t.isObj && !isScalarBoxedInTaggedPtr v,
|
||||
type := typeForScalarBoxedInTaggedPtr? v |>.getD t
|
||||
persistent := isPersistent v,
|
||||
consume := consumeExpr ctx.varMap v
|
||||
}
|
||||
@@ -207,7 +209,7 @@ private def processVDecl (ctx : Context) (z : VarId) (t : IRType) (v : Expr) (b
|
||||
|
||||
def updateVarInfoWithParams (ctx : Context) (ps : Array Param) : Context :=
|
||||
let m := ps.foldl (init := ctx.varMap) fun m p =>
|
||||
m.insert p.x { ref := p.ty.isObj, persistent := false, consume := !p.borrow }
|
||||
m.insert p.x { type := p.ty, persistent := false, consume := !p.borrow }
|
||||
{ ctx with varMap := m }
|
||||
|
||||
partial def visitFnBody : FnBody → Context → (FnBody × LiveVarSet)
|
||||
@@ -255,7 +257,7 @@ partial def visitFnBody : FnBody → Context → (FnBody × LiveVarSet)
|
||||
match x with
|
||||
| Arg.var x =>
|
||||
let info := getVarInfo ctx x
|
||||
if info.ref && !info.consume then (addInc ctx x b, mkLiveVarSet x) else (b, mkLiveVarSet x)
|
||||
if info.type.isPossibleRef && !info.consume then (addInc ctx x b, mkLiveVarSet x) else (b, mkLiveVarSet x)
|
||||
| _ => (b, {})
|
||||
| b@(FnBody.jmp j xs), ctx =>
|
||||
let jLiveVars := getJPLiveVars ctx j
|
||||
@@ -282,4 +284,6 @@ def explicitRC (decls : Array Decl) : CompilerM (Array Decl) := do
|
||||
let env ← getEnv
|
||||
return decls.map (ExplicitRC.visitDecl env decls)
|
||||
|
||||
builtin_initialize registerTraceClass `compiler.ir.rc (inherited := true)
|
||||
|
||||
end Lean.IR
|
||||
|
||||
@@ -111,7 +111,7 @@ private def tryS (x : VarId) (c : CtorInfo) (b : FnBody) : M FnBody := do
|
||||
if b == b' then
|
||||
return b
|
||||
else
|
||||
return .vdecl w IRType.object (.reset c.size x) b'
|
||||
return .vdecl w .tobject (.reset c.size x) b'
|
||||
|
||||
private def Dfinalize (x : VarId) (c : CtorInfo) : FnBody × Bool → M FnBody
|
||||
| (b, true) => return b
|
||||
@@ -139,7 +139,7 @@ private partial def Dmain (x : VarId) (c : CtorInfo) (e : FnBody) : M (FnBody ×
|
||||
| .case tid y yType alts =>
|
||||
if e.hasLiveVar (← read).lctx x then
|
||||
/- If `x` is live in `e`, we recursively process each branch. -/
|
||||
let alts ← alts.mapM fun alt => alt.mmodifyBody fun b => Dmain x c b >>= Dfinalize x c
|
||||
let alts ← alts.mapM fun alt => alt.modifyBodyM fun b => Dmain x c b >>= Dfinalize x c
|
||||
return (.case tid y yType alts, true)
|
||||
else
|
||||
return (e, false)
|
||||
@@ -181,7 +181,7 @@ partial def R (e : FnBody) : M FnBody := do
|
||||
let alreadyFound := (← read).alreadyFound.contains x
|
||||
withReader (fun ctx => { ctx with alreadyFound := ctx.alreadyFound.insert x }) do
|
||||
let alts ← alts.mapM fun alt => do
|
||||
let alt ← alt.mmodifyBody R
|
||||
let alt ← alt.modifyBodyM R
|
||||
match alt with
|
||||
| .ctor c b =>
|
||||
if c.isScalar || alreadyFound then
|
||||
@@ -243,4 +243,6 @@ def Decl.insertResetReuse (d : Decl) : Decl :=
|
||||
d.insertResetReuseCore (relaxedReuse := false)
|
||||
|>.insertResetReuseCore (relaxedReuse := true)
|
||||
|
||||
builtin_initialize registerTraceClass `compiler.ir.reset_reuse (inherited := true)
|
||||
|
||||
end Lean.IR
|
||||
|
||||
@@ -20,7 +20,7 @@ def ensureHasDefault (alts : Array Alt) : Array Alt :=
|
||||
private def getOccsOf (alts : Array Alt) (i : Nat) : Nat := Id.run do
|
||||
let aBody := alts[i]!.body
|
||||
let mut n := 1
|
||||
for h : j in [i+1:alts.size] do
|
||||
for h : j in (i+1)...alts.size do
|
||||
if alts[j].body == aBody then
|
||||
n := n+1
|
||||
return n
|
||||
@@ -28,7 +28,7 @@ private def getOccsOf (alts : Array Alt) (i : Nat) : Nat := Id.run do
|
||||
private def maxOccs (alts : Array Alt) : Alt × Nat := Id.run do
|
||||
let mut maxAlt := alts[0]!
|
||||
let mut max := getOccsOf alts 0
|
||||
for h : i in [1:alts.size] do
|
||||
for h : i in 1...alts.size do
|
||||
let curr := getOccsOf alts i
|
||||
if curr > max then
|
||||
maxAlt := alts[i]
|
||||
@@ -75,4 +75,6 @@ def Decl.simpCase (d : Decl) : Decl :=
|
||||
| .fdecl (body := b) .. => d.updateBody! b.simpCase
|
||||
| other => other
|
||||
|
||||
builtin_initialize registerTraceClass `compiler.ir.simp_case (inherited := true)
|
||||
|
||||
end Lean.IR
|
||||
|
||||
@@ -23,11 +23,11 @@ where
|
||||
getSorryDepFor? (f : Name) : ExceptT Name M Unit := do
|
||||
let found (g : Name) :=
|
||||
if g == ``sorryAx then
|
||||
throw f
|
||||
throwThe Name f
|
||||
else
|
||||
throw g
|
||||
throwThe Name g
|
||||
if f == ``sorryAx then
|
||||
throw f
|
||||
throwThe Name f
|
||||
else if let some g := (← get).localSorryMap.find? f then
|
||||
found g
|
||||
else match (← findDecl f) with
|
||||
|
||||
@@ -61,25 +61,28 @@ def findDecl (n : Name) : M (Option Decl) :=
|
||||
return findEnvDecl (← Lean.getEnv) n
|
||||
|
||||
def addDecl (d : Decl) : M Unit :=
|
||||
Lean.modifyEnv fun env => declMapExt.addEntry (env.addExtraName d.name) d
|
||||
Lean.modifyEnv fun env => declMapExt.addEntry env d
|
||||
|
||||
def lowerLitValue (v : LCNF.LitValue) : LitVal :=
|
||||
def lowerLitValue (v : LCNF.LitValue) : LitVal × IRType :=
|
||||
match v with
|
||||
| .nat n => .num n
|
||||
| .str s => .str s
|
||||
| .uint8 v => .num (UInt8.toNat v)
|
||||
| .uint16 v => .num (UInt16.toNat v)
|
||||
| .uint32 v => .num (UInt32.toNat v)
|
||||
| .uint64 v | .usize v => .num (UInt64.toNat v)
|
||||
| .nat n =>
|
||||
let type := if n < UInt32.size then .tagged else .tobject
|
||||
⟨.num n, type⟩
|
||||
| .str s => ⟨.str s, .object⟩
|
||||
| .uint8 v => ⟨.num (UInt8.toNat v), .uint8⟩
|
||||
| .uint16 v => ⟨.num (UInt16.toNat v), .uint16⟩
|
||||
| .uint32 v => ⟨.num (UInt32.toNat v), .uint32⟩
|
||||
| .uint64 v => ⟨.num (UInt64.toNat v), .uint64⟩
|
||||
| .usize v => ⟨.num (UInt64.toNat v), .usize⟩
|
||||
|
||||
def lowerArg (a : LCNF.Arg) : M Arg := do
|
||||
match a with
|
||||
| .fvar fvarId =>
|
||||
match (← get).fvars[fvarId]? with
|
||||
| some (.var varId) => return .var varId
|
||||
| some .erased => return .irrelevant
|
||||
| some .erased => return .erased
|
||||
| some (.joinPoint ..) | none => panic! "unexpected value"
|
||||
| .erased | .type .. => return .irrelevant
|
||||
| .erased | .type .. => return .erased
|
||||
|
||||
inductive TranslatedProj where
|
||||
| expr (e : Expr)
|
||||
@@ -89,10 +92,10 @@ inductive TranslatedProj where
|
||||
def lowerProj (base : VarId) (ctorInfo : CtorInfo) (field : CtorFieldInfo)
|
||||
: TranslatedProj × IRType :=
|
||||
match field with
|
||||
| .object i => ⟨.expr (.proj i base), .object⟩
|
||||
| .object i irType => ⟨.expr (.proj i base), irType⟩
|
||||
| .usize i => ⟨.expr (.uproj i base), .usize⟩
|
||||
| .scalar _ offset irType => ⟨.expr (.sproj (ctorInfo.size + ctorInfo.usize) offset base), irType⟩
|
||||
| .irrelevant => ⟨.erased, .irrelevant⟩
|
||||
| .erased => ⟨.erased, .erased⟩
|
||||
|
||||
def lowerParam (p : LCNF.Param) : M Param := do
|
||||
let x ← bindVar p.fvarId
|
||||
@@ -118,61 +121,29 @@ partial def lowerCode (c : LCNF.Code) : M FnBody := do
|
||||
| some (.var varId) =>
|
||||
return .case cases.typeName
|
||||
varId
|
||||
(← toIRType cases.resultType)
|
||||
(← nameToIRType cases.typeName)
|
||||
(← cases.alts.mapM (lowerAlt varId))
|
||||
| some (.joinPoint ..) | some .erased | none => panic! "unexpected value"
|
||||
| .return fvarId =>
|
||||
let arg := match (← get).fvars[fvarId]? with
|
||||
| some (.var varId) => .var varId
|
||||
| some .erased => .irrelevant
|
||||
| some .erased => .erased
|
||||
| some (.joinPoint ..) | none => panic! "unexpected value"
|
||||
return .ret arg
|
||||
| .unreach .. => return .unreachable
|
||||
| .fun .. => panic! "all local functions should be λ-lifted"
|
||||
|
||||
partial def lowerLet (decl : LCNF.LetDecl) (k : LCNF.Code) : M FnBody := do
|
||||
-- temporary fix: the old compiler inlines these too much as regular `let`s
|
||||
let rec mkVar (v : VarId) : M FnBody := do
|
||||
bindVarToVarId decl.fvarId v
|
||||
lowerCode k
|
||||
let rec mkExpr (e : Expr) : M FnBody := do
|
||||
let var ← bindVar decl.fvarId
|
||||
let type ← match e with
|
||||
| .ctor .. | .pap .. | .ap .. | .proj .. => pure <| .object
|
||||
| _ => toIRType decl.type
|
||||
return .vdecl var type e (← lowerCode k)
|
||||
let rec mkErased (_ : Unit) : M FnBody := do
|
||||
bindErased decl.fvarId
|
||||
lowerCode k
|
||||
let rec mkPartialApp (e : Expr) (restArgs : Array Arg) : M FnBody := do
|
||||
let var ← bindVar decl.fvarId
|
||||
let tmpVar ← newVar
|
||||
return .vdecl tmpVar .object e (.vdecl var .object (.ap tmpVar restArgs) (← lowerCode k))
|
||||
let rec tryIrDecl? (name : Name) (args : Array Arg) : M (Option FnBody) := do
|
||||
if let some decl ← LCNF.getMonoDecl? name then
|
||||
let numArgs := args.size
|
||||
let numParams := decl.params.size
|
||||
if numArgs < numParams then
|
||||
return some (← mkExpr (.pap name args))
|
||||
else if numArgs == numParams then
|
||||
return some (← mkExpr (.fap name args))
|
||||
else
|
||||
let firstArgs := args.extract 0 numParams
|
||||
let restArgs := args.extract numParams numArgs
|
||||
return some (← mkPartialApp (.fap name firstArgs) restArgs)
|
||||
else
|
||||
return none
|
||||
|
||||
match decl.value with
|
||||
| .lit litValue =>
|
||||
mkExpr (.lit (lowerLitValue litValue))
|
||||
let var ← bindVar decl.fvarId
|
||||
let ⟨litValue, type⟩ := lowerLitValue litValue
|
||||
return .vdecl var type (.lit litValue) (← lowerCode k)
|
||||
| .proj typeName i fvarId =>
|
||||
match (← get).fvars[fvarId]? with
|
||||
| some (.var varId) =>
|
||||
-- TODO: have better pattern matching here
|
||||
let some (.inductInfo { ctors, .. }) := (← Lean.getEnv).find? typeName
|
||||
| panic! "projection of non-inductive type"
|
||||
let ctorName := ctors[0]!
|
||||
let some (.inductInfo { ctors := [ctorName], .. }) := (← Lean.getEnv).find? typeName
|
||||
| panic! "projection of non-structure type"
|
||||
let ⟨ctorInfo, fields⟩ ← getCtorLayout ctorName
|
||||
let ⟨result, type⟩ := lowerProj varId ctorInfo fields[i]!
|
||||
match result with
|
||||
@@ -186,111 +157,107 @@ partial def lowerLet (decl : LCNF.LetDecl) (k : LCNF.Code) : M FnBody := do
|
||||
bindErased decl.fvarId
|
||||
lowerCode k
|
||||
| some (.joinPoint ..) | none => panic! "unexpected value"
|
||||
| .const ``Nat.succ _ args =>
|
||||
let irArgs ← args.mapM lowerArg
|
||||
let var ← bindVar decl.fvarId
|
||||
let tmpVar ← newVar
|
||||
let k := (.vdecl var .object (.fap ``Nat.add #[irArgs[0]!, (.var tmpVar)]) (← lowerCode k))
|
||||
return .vdecl tmpVar .object (.lit (.num 1)) k
|
||||
| .const name _ args =>
|
||||
let irArgs ← args.mapM lowerArg
|
||||
if let some code ← tryIrDecl? name irArgs then
|
||||
return code
|
||||
else
|
||||
let env ← Lean.getEnv
|
||||
match env.find? name with
|
||||
| some (.ctorInfo ctorVal) =>
|
||||
if isExtern env name then
|
||||
if let some code ← tryIrDecl? name irArgs then
|
||||
return code
|
||||
else
|
||||
mkExpr (.fap name irArgs)
|
||||
else
|
||||
let type ← nameToIRType ctorVal.induct
|
||||
if type.isScalar then
|
||||
let var ← bindVar decl.fvarId
|
||||
return .vdecl var type (.lit (.num ctorVal.cidx)) (← lowerCode k)
|
||||
else
|
||||
assert! type == .object
|
||||
let ⟨ctorInfo, fields⟩ ← getCtorLayout name
|
||||
let args := args.extract (start := ctorVal.numParams)
|
||||
let objArgs : Array Arg ← do
|
||||
let mut result : Array Arg := #[]
|
||||
for i in [0:fields.size] do
|
||||
match args[i]! with
|
||||
| .fvar fvarId =>
|
||||
if let some (.var varId) := (← get).fvars[fvarId]? then
|
||||
if fields[i]! matches .object .. then
|
||||
result := result.push (.var varId)
|
||||
| .type _ | .erased =>
|
||||
if fields[i]! matches .object .. then
|
||||
result := result.push .irrelevant
|
||||
pure result
|
||||
let objVar ← bindVar decl.fvarId
|
||||
let rec lowerNonObjectFields (_ : Unit) : M FnBody :=
|
||||
let rec loop (usizeCount : Nat) (i : Nat) : M FnBody := do
|
||||
match args[i]? with
|
||||
| some (.fvar fvarId) =>
|
||||
match (← get).fvars[fvarId]? with
|
||||
| some (.var varId) =>
|
||||
match fields[i]! with
|
||||
| .usize .. =>
|
||||
let k ← loop (usizeCount + 1) (i + 1)
|
||||
return .uset objVar (ctorInfo.size + usizeCount) varId k
|
||||
| .scalar _ offset argType =>
|
||||
let k ← loop usizeCount (i + 1)
|
||||
return .sset objVar (ctorInfo.size + ctorInfo.usize) offset varId argType k
|
||||
| .object .. | .irrelevant => loop usizeCount (i + 1)
|
||||
| _ => loop usizeCount (i + 1)
|
||||
| some (.type _) | some .erased => loop usizeCount (i + 1)
|
||||
| none => lowerCode k
|
||||
loop 0 0
|
||||
return .vdecl objVar type (.ctor ctorInfo objArgs) (← lowerNonObjectFields ())
|
||||
| some (.axiomInfo ..) =>
|
||||
if name == ``Quot.lcInv then
|
||||
match irArgs[2]! with
|
||||
| .var varId => mkVar varId
|
||||
| .irrelevant => mkErased ()
|
||||
else if name == ``lcUnreachable then
|
||||
return .unreachable
|
||||
else if let some irDecl ← findDecl name then
|
||||
let numArgs := irArgs.size
|
||||
let numParams := irDecl.params.size
|
||||
if numArgs < numParams then
|
||||
mkExpr (.pap name irArgs)
|
||||
else if numArgs == numParams then
|
||||
mkExpr (.fap name irArgs)
|
||||
else
|
||||
let firstArgs := irArgs.extract 0 numParams
|
||||
let restArgs := irArgs.extract numParams irArgs.size
|
||||
mkPartialApp (.fap name firstArgs) restArgs
|
||||
else
|
||||
throwNamedError lean.dependsOnNoncomputable f!"axiom '{name}' not supported by code generator; consider marking definition as 'noncomputable'"
|
||||
| some (.quotInfo ..) =>
|
||||
if name == ``Quot.mk then
|
||||
match irArgs[2]! with
|
||||
| .var varId => mkVar varId
|
||||
| .irrelevant => mkErased ()
|
||||
else
|
||||
throwError f!"quot {name} unsupported by code generator"
|
||||
| some (.defnInfo ..) | some (.opaqueInfo ..) =>
|
||||
if let some code ← tryIrDecl? name irArgs then
|
||||
return code
|
||||
else
|
||||
mkExpr (.fap name irArgs)
|
||||
| some (.recInfo ..) =>
|
||||
throwError f!"code generator does not support recursor '{name}' yet, consider using 'match ... with' and/or structural recursion"
|
||||
| some (.inductInfo ..) => panic! "induct unsupported by code generator"
|
||||
| some (.thmInfo ..) => panic! "thm unsupported by code generator"
|
||||
| none => panic! "reference to unbound name"
|
||||
let env ← Lean.getEnv
|
||||
match env.find? name with
|
||||
| some (.ctorInfo ctorVal) =>
|
||||
if isExtern env name then
|
||||
return (← mkFap name irArgs)
|
||||
|
||||
let type ← nameToIRType ctorVal.induct
|
||||
if type.isScalar then
|
||||
let var ← bindVar decl.fvarId
|
||||
return .vdecl var type (.lit (.num ctorVal.cidx)) (← lowerCode k)
|
||||
|
||||
let ⟨ctorInfo, fields⟩ ← getCtorLayout name
|
||||
let irArgs := irArgs.extract (start := ctorVal.numParams)
|
||||
let objArgs : Array Arg ← do
|
||||
let mut result : Array Arg := #[]
|
||||
for h : i in *...fields.size do
|
||||
match fields[i] with
|
||||
| .object .. =>
|
||||
result := result.push irArgs[i]!
|
||||
| .usize .. | .scalar .. | .erased => pure ()
|
||||
pure result
|
||||
let objVar ← bindVar decl.fvarId
|
||||
let rec lowerNonObjectFields (_ : Unit) : M FnBody :=
|
||||
let rec loop (i : Nat) : M FnBody := do
|
||||
match irArgs[i]? with
|
||||
| some (.var varId) =>
|
||||
match fields[i]! with
|
||||
| .usize usizeIdx =>
|
||||
let k ← loop (i + 1)
|
||||
return .uset objVar usizeIdx varId k
|
||||
| .scalar _ offset argType =>
|
||||
let k ← loop (i + 1)
|
||||
return .sset objVar (ctorInfo.size + ctorInfo.usize) offset varId argType k
|
||||
| .object .. | .erased => loop (i + 1)
|
||||
| some .erased => loop (i + 1)
|
||||
| none => lowerCode k
|
||||
loop 0
|
||||
return .vdecl objVar ctorInfo.type (.ctor ctorInfo objArgs) (← lowerNonObjectFields ())
|
||||
| some (.defnInfo ..) | some (.opaqueInfo ..) =>
|
||||
mkFap name irArgs
|
||||
| some (.axiomInfo ..) | .some (.quotInfo ..) | .some (.inductInfo ..) | .some (.thmInfo ..) =>
|
||||
throwNamedError lean.dependsOnNoncomputable f!"'{name}' not supported by code generator; consider marking definition as 'noncomputable'"
|
||||
| some (.recInfo ..) =>
|
||||
throwError f!"code generator does not support recursor '{name}' yet, consider using 'match ... with' and/or structural recursion"
|
||||
| none => panic! "reference to unbound name"
|
||||
| .fvar fvarId args =>
|
||||
match (← get).fvars[fvarId]? with
|
||||
| some (.var id) =>
|
||||
let irArgs ← args.mapM lowerArg
|
||||
mkExpr (.ap id irArgs)
|
||||
mkAp id irArgs
|
||||
| some .erased => mkErased ()
|
||||
| some (.joinPoint ..) | none => panic! "unexpected value"
|
||||
| .erased => mkErased ()
|
||||
where
|
||||
mkVar (v : VarId) : M FnBody := do
|
||||
bindVarToVarId decl.fvarId v
|
||||
lowerCode k
|
||||
|
||||
mkErased (_ : Unit) : M FnBody := do
|
||||
bindErased decl.fvarId
|
||||
lowerCode k
|
||||
|
||||
mkFap (name : Name) (args : Array Arg) : M FnBody := do
|
||||
let var ← bindVar decl.fvarId
|
||||
let type ← toIRType decl.type
|
||||
return .vdecl var type (.fap name args) (← lowerCode k)
|
||||
|
||||
mkPap (name : Name) (args : Array Arg) : M FnBody := do
|
||||
let var ← bindVar decl.fvarId
|
||||
return .vdecl var .object (.pap name args) (← lowerCode k)
|
||||
|
||||
mkAp (fnVar : VarId) (args : Array Arg) : M FnBody := do
|
||||
let var ← bindVar decl.fvarId
|
||||
let type := (← toIRType decl.type).boxed
|
||||
return .vdecl var type (.ap fnVar args) (← lowerCode k)
|
||||
|
||||
mkOverApplication (name : Name) (numParams : Nat) (args : Array Arg) : M FnBody := do
|
||||
let var ← bindVar decl.fvarId
|
||||
let type := (← toIRType decl.type).boxed
|
||||
let tmpVar ← newVar
|
||||
let firstArgs := args.extract 0 numParams
|
||||
let restArgs := args.extract numParams args.size
|
||||
return .vdecl tmpVar .object (.fap name firstArgs) <|
|
||||
.vdecl var type (.ap tmpVar restArgs) (← lowerCode k)
|
||||
|
||||
tryIrDecl? (name : Name) (args : Array Arg) : M (Option FnBody) := do
|
||||
if let some decl ← LCNF.getMonoDecl? name then
|
||||
let numArgs := args.size
|
||||
let numParams := decl.params.size
|
||||
if numArgs < numParams then
|
||||
return some (← mkPap name args)
|
||||
else if numArgs == numParams then
|
||||
return some (← mkFap name args)
|
||||
else
|
||||
return some (← mkOverApplication name numParams args)
|
||||
else
|
||||
return none
|
||||
|
||||
partial def lowerAlt (discr : VarId) (a : LCNF.Alt) : M Alt := do
|
||||
match a with
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user